Skip to content

Commit 7e928ec

Browse files
authored
Merge pull request #1464 from mcneel/kike/1.36
Added `ARDB.Mesh.TryGetNakedEdges` extension method.
2 parents 80b4ca0 + 26bfa3a commit 7e928ec

File tree

5 files changed

+160
-4
lines changed

5 files changed

+160
-4
lines changed

src/RhinoInside.Revit.External/DB/Extensions/Mesh.cs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
14
using Autodesk.Revit.DB;
25

36
namespace RhinoInside.Revit.External.DB.Extensions
@@ -207,5 +210,125 @@ public static double ComputeSurfaceArea(this Mesh mesh)
207210
return area.Value * 0.5;
208211
}
209212
#endif
213+
214+
#region Naked Edges
215+
public static bool TryGetNakedEdges(this Mesh mesh, out PolyLine[] edges)
216+
{
217+
if (mesh.NumTriangles > 0)
218+
{
219+
var polylines = JoinLines(GetNakedEdges(mesh));
220+
if (polylines.Count > 0)
221+
{
222+
edges = new PolyLine[polylines.Count];
223+
224+
var vertices = mesh.Vertices;
225+
var index = 0;
226+
foreach (var pline in polylines)
227+
edges[index++] = PolyLine.Create(pline.Select(x => vertices[x]).ToArray());
228+
}
229+
else edges = Array.Empty<PolyLine>(); // A totally closed mesh with no naked edges.
230+
231+
return true;
232+
}
233+
234+
edges = Array.Empty<PolyLine>();
235+
return false;
236+
}
237+
238+
static ISet<(int V0, int V1)> GetNakedEdges(this Mesh mesh)
239+
{
240+
static (int V0, int V1) Edge(int v0, int v1) => v0 < v1 ? (v0, v1) : (v1, v0);
241+
var edges = new SortedSet<(int V0, int V1)>();
242+
243+
var numTriangles = mesh.NumTriangles;
244+
for (int t = 0; t < numTriangles; ++t)
245+
{
246+
var triangle = mesh.get_Triangle(t);
247+
var v0 = (int) triangle.get_Index(0);
248+
var v1 = (int) triangle.get_Index(1);
249+
var v2 = (int) triangle.get_Index(2);
250+
251+
var edge0 = Edge(v0, v1);
252+
if (!edges.Remove(edge0)) edges.Add(edge0);
253+
var edge1 = Edge(v1, v2);
254+
if (!edges.Remove(edge1)) edges.Add(edge1);
255+
var edge2 = Edge(v2, v0);
256+
if (!edges.Remove(edge2)) edges.Add(edge2);
257+
}
258+
259+
return edges;
260+
}
261+
262+
static List<List<int>> JoinLines(ISet<(int A, int B)> segments)
263+
{
264+
var adjacency = new Dictionary<int, List<(int A, int B)>>();
265+
{
266+
foreach (var segment in segments)
267+
{
268+
if (!adjacency.ContainsKey(segment.A)) adjacency[segment.A] = new List<(int A, int B)>();
269+
if (!adjacency.ContainsKey(segment.B)) adjacency[segment.B] = new List<(int A, int B)>();
270+
271+
adjacency[segment.A].Add(segment);
272+
adjacency[segment.B].Add(segment);
273+
}
274+
}
275+
276+
var polylines = new List<List<int>>();
277+
278+
// Open polylines
279+
{
280+
foreach (int start in adjacency.Where(x => x.Value.Count != 2).Select(x => x.Key))
281+
{
282+
if (adjacency[start].All(segments.Contains))
283+
continue;
284+
285+
var poly = new List<int>();
286+
287+
int current = start;
288+
while (true)
289+
{
290+
poly.Add(current);
291+
292+
var next = adjacency[current].FirstOrDefault(segments.Contains);
293+
if (next.Equals(default) && !segments.Contains(next))
294+
break;
295+
296+
segments.Remove(next);
297+
298+
current = (next.A == current) ? next.B : next.A;
299+
if (adjacency[current].Count != 2)
300+
{
301+
poly.Add(current);
302+
break;
303+
}
304+
}
305+
306+
polylines.Add(poly);
307+
}
308+
}
309+
310+
// Closed polylines
311+
{
312+
while (segments.Count > 0)
313+
{
314+
var first = segments.First();
315+
segments.Remove(first);
316+
int start = first.A;
317+
int current = first.B;
318+
var loop = new List<int> { start, current };
319+
while (current != start)
320+
{
321+
var next = adjacency[current].First(segments.Contains);
322+
segments.Remove(next);
323+
current = (next.A == current) ? next.B : next.A;
324+
loop.Add(current);
325+
}
326+
polylines.Add(loop);
327+
}
328+
}
329+
330+
return polylines;
331+
}
332+
#endregion
210333
}
211334
}

src/RhinoInside.Revit.External/Extensions/RhinoCommon.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,28 @@ public static BoundingBox GetBoundingBox(this Box value, Transform xform)
218218

219219
return new BoundingBox(value.GetCorners(), xform);
220220
}
221+
222+
public static IEnumerable<Plane> ToPlanes(this Box box)
223+
{
224+
var plane = box.Plane;
225+
yield return new Plane(plane.PointAt(0.0, 0.0, box.Z.T0), plane.YAxis, plane.XAxis);
226+
yield return new Plane(plane.PointAt(0.0, box.Y.T0, 0.0), plane.XAxis, plane.ZAxis);
227+
yield return new Plane(plane.PointAt(box.X.T0, 0.0, 0.0), plane.ZAxis, plane.YAxis);
228+
yield return new Plane(plane.PointAt(box.X.T1, 0.0, 0.0), plane.YAxis, plane.ZAxis);
229+
yield return new Plane(plane.PointAt(0.0, box.Y.T1, 0.0), plane.ZAxis, plane.XAxis);
230+
yield return new Plane(plane.PointAt(0.0, 0.0, box.Z.T1), plane.XAxis, plane.YAxis);
231+
}
232+
233+
public static IEnumerable<PlaneSurface> ToSurfaces(this Box box)
234+
{
235+
var plane = box.Plane;
236+
yield return new PlaneSurface(new Plane(plane.PointAt(0.0, 0.0, box.Z.T0), plane.YAxis, plane.XAxis), box.Y, box.X);
237+
yield return new PlaneSurface(new Plane(plane.PointAt(0.0, box.Y.T0, 0.0), plane.XAxis, plane.ZAxis), box.X, box.Z);
238+
yield return new PlaneSurface(new Plane(plane.PointAt(box.X.T0, 0.0, 0.0), plane.ZAxis, plane.YAxis), box.Z, box.Y);
239+
yield return new PlaneSurface(new Plane(plane.PointAt(box.X.T1, 0.0, 0.0), plane.YAxis, plane.ZAxis), box.Y, box.Z);
240+
yield return new PlaneSurface(new Plane(plane.PointAt(0.0, box.Y.T1, 0.0), plane.ZAxis, plane.XAxis), box.Z, box.X);
241+
yield return new PlaneSurface(new Plane(plane.PointAt(0.0, 0.0, box.Z.T1), plane.XAxis, plane.YAxis), box.X, box.Y);
242+
}
221243
}
222244

223245
static class ExtrusionExtension
@@ -1537,11 +1559,13 @@ public static bool Scale(this RhinoViewport viewport, double scaleFactor)
15371559
projection.SetFrustum(left * scaleFactor, right * scaleFactor, bottom * scaleFactor, top * scaleFactor, near * scaleFactor, far * scaleFactor);
15381560
}
15391561

1540-
if (!viewport.SetViewProjection(projection, updateTargetLocation: true))
1562+
if (!viewport.SetViewProjection(projection, updateTargetLocation: false))
15411563
return false;
15421564

15431565
var cplane = viewport.GetConstructionPlane();
1544-
cplane.Plane.Transform(scaleTransform);
1566+
var location = cplane.Plane;
1567+
location.Transform(scaleTransform);
1568+
cplane.Plane = location;
15451569
cplane.GridSpacing *= scaleFactor;
15461570
cplane.SnapSpacing *= scaleFactor;
15471571
viewport.SetConstructionPlane(cplane);

src/RhinoInside.Revit/Convert/Display/PreviewConverter.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,16 @@ this IEnumerable<ARDB.GeometryObject> geometries
222222
}
223223
break;
224224
}
225+
case ARDB.Mesh mesh:
226+
{
227+
if (mesh.TryGetNakedEdges(out var edges))
228+
{
229+
foreach (var edge in edges)
230+
yield return edge.ToPolylineCurve();
231+
}
232+
233+
break;
234+
}
225235
case ARDB.Solid solid:
226236
{
227237
if (solid.Faces.IsEmpty)

src/RhinoInside.Revit/Convert/Geometry/MeshDecoder.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ internal static Mesh FromRawMesh(Mesh mesh, double scaleFactor)
2525
}
2626

2727
mesh.Vertices.Align(2.0 * GeometryTolerance.Model.VertexTolerance); // MeshEncoder.ShortEdgeTolerance in model units
28-
mesh.Ngons.AddPlanarNgons(GeometryTolerance.Model.VertexTolerance, 4, 2, true);
2928
return mesh;
3029
}
3130
}

src/RhinoInside.Revit/Convert/Geometry/Raw/RawDecoder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ public static Curve ToRhino(ARDB.Curve curve)
302302

303303
public static PolylineCurve ToRhino(ARDB.PolyLine polyline)
304304
{
305-
return new PolylineCurve(polyline.GetCoordinates().Select(x => AsPoint3d(x)));
305+
return new PolylineCurve(polyline.GetCoordinates().Select(AsPoint3d));
306306
}
307307
#endregion
308308

0 commit comments

Comments
 (0)