Skip to content

Commit

Permalink
Merge pull request #1062 from hypar-io/fix-mesh-intersection
Browse files Browse the repository at this point in the history
fix mesh / topo intersection
  • Loading branch information
andrewheumann committed Nov 22, 2023
2 parents f7525d2 + 0493caa commit a4f0d19
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 34 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
- `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.
- `Ray.Intersects(Topography)` now considers the topography's transform.

### Changed

Expand Down
19 changes: 13 additions & 6 deletions Elements/src/Geometry/Mesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -450,25 +451,31 @@ public List<Polyline> GetNakedBoundaries()
}

/// <summary>
/// Does the provided ray intersect this mesh mesh?
/// Does the provided ray intersect this mesh?
/// </summary>
/// <param name="ray">The Ray to intersect.</param>
/// <param name="intersection">The location of intersection.</param>
/// <param name="intersection">The location of the closest intersection.</param>
/// <returns>True if an intersection result occurs.
/// False if no intersection occurs.</returns>
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)
Expand Down
10 changes: 9 additions & 1 deletion Elements/src/Geometry/Ray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,15 @@ public bool Intersects(Plane plane, out Vector3 result, out double t)
/// False if no intersection occurs.</returns>
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;
}

/// <summary>
Expand Down
47 changes: 20 additions & 27 deletions Elements/test/RayTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Xunit.Abstractions;
using System.Diagnostics;
using Vertex = Elements.Geometry.Vertex;
using Xunit.Sdk;
using System.Linq;

namespace Elements.Tests
{
Expand Down Expand Up @@ -63,43 +65,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)
{
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 modelPoints = new ModelPoints(new List<Vector3>(), new Material("begin", Colors.Blue));
this.Model.AddElement(modelPoints);
foreach (var t in topo.Mesh.Triangles)
this.Model.AddElements(new Transform().ToModelCurves());
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, out var result2);
Assert.True(intersect);
var line = new Line(result2, newRay.Origin);
Model.AddElement(new ModelCurve(line, BuiltInMaterials.XAxis));
Assert.True(result2.Z > elevations.Min() + 2 && result2.Z < elevations.Max() + 2);
}
}
}
Expand Down

0 comments on commit a4f0d19

Please sign in to comment.