Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix mesh / topo intersection #1062

Merged
merged 3 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading