From d98e219126e8d9ae0ee32a7f8c9da0f2d108339c Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 21 Nov 2023 12:40:41 -0500 Subject: [PATCH 1/3] fix mesh / topo intersection --- Elements/src/Geometry/Mesh.cs | 19 +++++++++++----- Elements/src/Geometry/Ray.cs | 2 +- Elements/test/RayTests.cs | 43 ++++++++++++++--------------------- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/Elements/src/Geometry/Mesh.cs b/Elements/src/Geometry/Mesh.cs index 1a28b4f26..9a7aeb3b9 100644 --- a/Elements/src/Geometry/Mesh.cs +++ b/Elements/src/Geometry/Mesh.cs @@ -259,7 +259,8 @@ public Triangle AddTriangle(Triangle t) public void RemoveTriangle(Triangle face) { this.Triangles.Remove(face); - foreach(var vert in face.Vertices) { + foreach (var vert in face.Vertices) + { vert.Triangles.Remove(face); } } @@ -450,10 +451,10 @@ public List GetNakedBoundaries() } /// - /// Does the provided ray intersect this mesh mesh? + /// Does the provided ray intersect this mesh? /// /// The Ray to intersect. - /// The location of intersection. + /// The location of the closest intersection. /// True if an intersection result occurs. /// False if no intersection occurs. public bool Intersects(Ray ray, out Vector3 intersection) @@ -461,14 +462,20 @@ public bool Intersects(Ray ray, out Vector3 intersection) var nearbyVertices = GetOctree().GetNearby(ray, _maxTriangleSize).ToList(); var nearbyTriangles = nearbyVertices.SelectMany(v => v.Triangles).Distinct(); intersection = default; + var closest = double.MaxValue; foreach (var t in nearbyTriangles) { - if (ray.Intersects(t, out intersection)) + if (ray.Intersects(t, out var triangleIntersection)) { - return true; + var d = triangleIntersection.DistanceTo(ray.Origin); + if (d < closest) + { + intersection = triangleIntersection; + closest = d; + } } } - return false; + return closest < double.MaxValue; } private double SignedVolumeOfTriangle(Triangle t) diff --git a/Elements/src/Geometry/Ray.cs b/Elements/src/Geometry/Ray.cs index 2c82d2a35..9cd8fa456 100644 --- a/Elements/src/Geometry/Ray.cs +++ b/Elements/src/Geometry/Ray.cs @@ -236,7 +236,7 @@ public bool Intersects(Plane plane, out Vector3 result, out double t) } /// - /// Does this ray intersect the provided topography? + /// Does this ray intersect the provided topography? Note that the Topography's transform is not considered. /// /// The topography. /// The location of intersection. diff --git a/Elements/test/RayTests.cs b/Elements/test/RayTests.cs index fb2e6b433..11ae7d864 100644 --- a/Elements/test/RayTests.cs +++ b/Elements/test/RayTests.cs @@ -63,43 +63,34 @@ public void RayIntersectsTopography() { this.Name = "RayIntersectTopo"; - var elevations = new double[25]; + var elevations = new double[100]; int e = 0; - for (var x = 0; x < 5; x++) + for (var x = 0; x < 10; x++) { - for (var y = 0; y < 5; y++) + for (var y = 0; y < 10; y++) { - elevations[e] = Math.Sin(((double)x / 5.0) * Math.PI) * 10; + elevations[e] = Math.Sin(((double)x / 10.0) * Math.PI) * 5; e++; } } - var topo = new Topography(Vector3.Origin, 4, elevations); + var topo = new Topography(Vector3.Origin, 10, elevations); + topo.Material = new Material("topo", new Color(0.5, 0.5, 0.5, 0.5)); this.Model.AddElement(topo); - var modelPoints = new ModelPoints(new List(), new Material("begin", Colors.Blue)); - this.Model.AddElement(modelPoints); - foreach (var t in topo.Mesh.Triangles) + var ray = new Ray(Vector3.Origin, Vector3.ZAxis); + this.Model.AddElement(ModelCurveFromRay(ray)); + Assert.True(ray.Intersects(topo.Mesh, out var result)); + for (int i = 1; i < 9; i++) { - var c = Center(t); - var o = new Vector3(c.X, c.Y); - modelPoints.Locations.Add(o); - - var ray = new Ray(o, Vector3.ZAxis); - - Vector3 xsect; - if (ray.Intersects(t, out xsect)) + for (int j = 1; j < 9; j++) { - try - { - var l = new Line(o, xsect); - var ml = new ModelCurve(l); - this.Model.AddElement(ml); - } - catch - { - continue; - } + var newRay = new Ray(new Vector3(i, j, 40), Vector3.ZAxis.Negate()); + var intersect = newRay.Intersects(topo.Mesh, out var result2); + Assert.True(intersect); + var line = new Line(result2, newRay.Origin); + Model.AddElement(new ModelCurve(line, BuiltInMaterials.XAxis)); + Assert.True(result2.Z > 0 && result2.Z < 40); } } } From e15e19dc473a8baa4acfd17d990c95be1b196391 Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 21 Nov 2023 12:42:19 -0500 Subject: [PATCH 2/3] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bc41f3e2..ce7b04fc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ - `Polyline.TransformAt` returns correct transformations when parameter on domain is provided. - `IndexedPolycurve` constructor that takes list of `BoundedCurve` now produces `CurveIndices` that share vertices and are withing index range. This means `IndexedPolyline.TransformedPolyline` preserves `CurveIndicies` on new `IndexedPolyline`. - `BoundedCurve.ToPolyline` now works correctly for `EllipticalArc` class. +- `Ray.Intersects(Topography)` and `Ray.Intersects(Mesh)` would sometimes return a different intersection than the closest one. ### Changed From 0493caa59f9331aac263678b8993e392b2eafe7b Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 22 Nov 2023 09:59:35 -0500 Subject: [PATCH 3/3] include topo transform in ray check --- CHANGELOG.md | 1 + Elements/src/Geometry/Ray.cs | 12 ++++++++++-- Elements/test/RayTests.cs | 18 ++++++++++-------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce7b04fc8..7c4dded2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ - `IndexedPolycurve` constructor that takes list of `BoundedCurve` now produces `CurveIndices` that share vertices and are withing index range. This means `IndexedPolyline.TransformedPolyline` preserves `CurveIndicies` on new `IndexedPolyline`. - `BoundedCurve.ToPolyline` now works correctly for `EllipticalArc` class. - `Ray.Intersects(Topography)` and `Ray.Intersects(Mesh)` would sometimes return a different intersection than the closest one. +- `Ray.Intersects(Topography)` now considers the topography's transform. ### Changed diff --git a/Elements/src/Geometry/Ray.cs b/Elements/src/Geometry/Ray.cs index 9cd8fa456..4e9989c6b 100644 --- a/Elements/src/Geometry/Ray.cs +++ b/Elements/src/Geometry/Ray.cs @@ -236,7 +236,7 @@ public bool Intersects(Plane plane, out Vector3 result, out double t) } /// - /// Does this ray intersect the provided topography? Note that the Topography's transform is not considered. + /// Does this ray intersect the provided topography? /// /// The topography. /// The location of intersection. @@ -244,7 +244,15 @@ public bool Intersects(Plane plane, out Vector3 result, out double t) /// False if no intersection occurs. public bool Intersects(Topography topo, out Vector3 result) { - return Intersects(topo.Mesh, out result); + var transform = topo.Transform; + var inverse = transform.Inverted(); + var transformedRay = new Ray(inverse.OfPoint(Origin), Direction); + var intersects = transformedRay.Intersects(topo.Mesh, out result); + if (intersects) + { + result = transform.OfPoint(result); + } + return intersects; } /// diff --git a/Elements/test/RayTests.cs b/Elements/test/RayTests.cs index 11ae7d864..03c791ba7 100644 --- a/Elements/test/RayTests.cs +++ b/Elements/test/RayTests.cs @@ -7,6 +7,8 @@ using Xunit.Abstractions; using System.Diagnostics; using Vertex = Elements.Geometry.Vertex; +using Xunit.Sdk; +using System.Linq; namespace Elements.Tests { @@ -74,23 +76,23 @@ public void RayIntersectsTopography() e++; } } - var topo = new Topography(Vector3.Origin, 10, elevations); - topo.Material = new Material("topo", new Color(0.5, 0.5, 0.5, 0.5)); + var topo = new Topography(Vector3.Origin, 10, elevations) + { + Material = new Material("topo", new Color(0.5, 0.5, 0.5, 0.5)), + Transform = new Transform(0, 0, 2) + }; this.Model.AddElement(topo); - - var ray = new Ray(Vector3.Origin, Vector3.ZAxis); - this.Model.AddElement(ModelCurveFromRay(ray)); - Assert.True(ray.Intersects(topo.Mesh, out var result)); + this.Model.AddElements(new Transform().ToModelCurves()); for (int i = 1; i < 9; i++) { for (int j = 1; j < 9; j++) { var newRay = new Ray(new Vector3(i, j, 40), Vector3.ZAxis.Negate()); - var intersect = newRay.Intersects(topo.Mesh, out var result2); + var intersect = newRay.Intersects(topo, out var result2); Assert.True(intersect); var line = new Line(result2, newRay.Origin); Model.AddElement(new ModelCurve(line, BuiltInMaterials.XAxis)); - Assert.True(result2.Z > 0 && result2.Z < 40); + Assert.True(result2.Z > elevations.Min() + 2 && result2.Z < elevations.Max() + 2); } } }