Skip to content
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
123 changes: 123 additions & 0 deletions src/RhinoInside.Revit.External/DB/Extensions/Mesh.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;

namespace RhinoInside.Revit.External.DB.Extensions
Expand Down Expand Up @@ -207,5 +210,125 @@ public static double ComputeSurfaceArea(this Mesh mesh)
return area.Value * 0.5;
}
#endif

#region Naked Edges
public static bool TryGetNakedEdges(this Mesh mesh, out PolyLine[] edges)
{
if (mesh.NumTriangles > 0)
{
var polylines = JoinLines(GetNakedEdges(mesh));
if (polylines.Count > 0)
{
edges = new PolyLine[polylines.Count];

var vertices = mesh.Vertices;
var index = 0;
foreach (var pline in polylines)
edges[index++] = PolyLine.Create(pline.Select(x => vertices[x]).ToArray());
}
else edges = Array.Empty<PolyLine>(); // A totally closed mesh with no naked edges.

return true;
}

edges = Array.Empty<PolyLine>();
return false;
}

static ISet<(int V0, int V1)> GetNakedEdges(this Mesh mesh)
{
static (int V0, int V1) Edge(int v0, int v1) => v0 < v1 ? (v0, v1) : (v1, v0);
var edges = new SortedSet<(int V0, int V1)>();

var numTriangles = mesh.NumTriangles;
for (int t = 0; t < numTriangles; ++t)
{
var triangle = mesh.get_Triangle(t);
var v0 = (int) triangle.get_Index(0);
var v1 = (int) triangle.get_Index(1);
var v2 = (int) triangle.get_Index(2);

var edge0 = Edge(v0, v1);
if (!edges.Remove(edge0)) edges.Add(edge0);
var edge1 = Edge(v1, v2);
if (!edges.Remove(edge1)) edges.Add(edge1);
var edge2 = Edge(v2, v0);
if (!edges.Remove(edge2)) edges.Add(edge2);
}

return edges;
}

static List<List<int>> JoinLines(ISet<(int A, int B)> segments)
{
var adjacency = new Dictionary<int, List<(int A, int B)>>();
{
foreach (var segment in segments)
{
if (!adjacency.ContainsKey(segment.A)) adjacency[segment.A] = new List<(int A, int B)>();
if (!adjacency.ContainsKey(segment.B)) adjacency[segment.B] = new List<(int A, int B)>();

adjacency[segment.A].Add(segment);
adjacency[segment.B].Add(segment);
}
}

var polylines = new List<List<int>>();

// Open polylines
{
foreach (int start in adjacency.Where(x => x.Value.Count != 2).Select(x => x.Key))
{
if (adjacency[start].All(segments.Contains))
continue;

var poly = new List<int>();

int current = start;
while (true)
{
poly.Add(current);

var next = adjacency[current].FirstOrDefault(segments.Contains);
if (next.Equals(default) && !segments.Contains(next))
break;

segments.Remove(next);

current = (next.A == current) ? next.B : next.A;
if (adjacency[current].Count != 2)
{
poly.Add(current);
break;
}
}

polylines.Add(poly);
}
}

// Closed polylines
{
while (segments.Count > 0)
{
var first = segments.First();
segments.Remove(first);
int start = first.A;
int current = first.B;
var loop = new List<int> { start, current };
while (current != start)
{
var next = adjacency[current].First(segments.Contains);
segments.Remove(next);
current = (next.A == current) ? next.B : next.A;
loop.Add(current);
}
polylines.Add(loop);
}
}

return polylines;
}
#endregion
}
}
28 changes: 26 additions & 2 deletions src/RhinoInside.Revit.External/Extensions/RhinoCommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,28 @@ public static BoundingBox GetBoundingBox(this Box value, Transform xform)

return new BoundingBox(value.GetCorners(), xform);
}

public static IEnumerable<Plane> ToPlanes(this Box box)
{
var plane = box.Plane;
yield return new Plane(plane.PointAt(0.0, 0.0, box.Z.T0), plane.YAxis, plane.XAxis);
yield return new Plane(plane.PointAt(0.0, box.Y.T0, 0.0), plane.XAxis, plane.ZAxis);
yield return new Plane(plane.PointAt(box.X.T0, 0.0, 0.0), plane.ZAxis, plane.YAxis);
yield return new Plane(plane.PointAt(box.X.T1, 0.0, 0.0), plane.YAxis, plane.ZAxis);
yield return new Plane(plane.PointAt(0.0, box.Y.T1, 0.0), plane.ZAxis, plane.XAxis);
yield return new Plane(plane.PointAt(0.0, 0.0, box.Z.T1), plane.XAxis, plane.YAxis);
}

public static IEnumerable<PlaneSurface> ToSurfaces(this Box box)
{
var plane = box.Plane;
yield return new PlaneSurface(new Plane(plane.PointAt(0.0, 0.0, box.Z.T0), plane.YAxis, plane.XAxis), box.Y, box.X);
yield return new PlaneSurface(new Plane(plane.PointAt(0.0, box.Y.T0, 0.0), plane.XAxis, plane.ZAxis), box.X, box.Z);
yield return new PlaneSurface(new Plane(plane.PointAt(box.X.T0, 0.0, 0.0), plane.ZAxis, plane.YAxis), box.Z, box.Y);
yield return new PlaneSurface(new Plane(plane.PointAt(box.X.T1, 0.0, 0.0), plane.YAxis, plane.ZAxis), box.Y, box.Z);
yield return new PlaneSurface(new Plane(plane.PointAt(0.0, box.Y.T1, 0.0), plane.ZAxis, plane.XAxis), box.Z, box.X);
yield return new PlaneSurface(new Plane(plane.PointAt(0.0, 0.0, box.Z.T1), plane.XAxis, plane.YAxis), box.X, box.Y);
}
}

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

if (!viewport.SetViewProjection(projection, updateTargetLocation: true))
if (!viewport.SetViewProjection(projection, updateTargetLocation: false))
return false;

var cplane = viewport.GetConstructionPlane();
cplane.Plane.Transform(scaleTransform);
var location = cplane.Plane;
location.Transform(scaleTransform);
cplane.Plane = location;
cplane.GridSpacing *= scaleFactor;
cplane.SnapSpacing *= scaleFactor;
viewport.SetConstructionPlane(cplane);
Expand Down
10 changes: 10 additions & 0 deletions src/RhinoInside.Revit/Convert/Display/PreviewConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,16 @@ this IEnumerable<ARDB.GeometryObject> geometries
}
break;
}
case ARDB.Mesh mesh:
{
if (mesh.TryGetNakedEdges(out var edges))
{
foreach (var edge in edges)
yield return edge.ToPolylineCurve();
}

break;
}
case ARDB.Solid solid:
{
if (solid.Faces.IsEmpty)
Expand Down
1 change: 0 additions & 1 deletion src/RhinoInside.Revit/Convert/Geometry/MeshDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ internal static Mesh FromRawMesh(Mesh mesh, double scaleFactor)
}

mesh.Vertices.Align(2.0 * GeometryTolerance.Model.VertexTolerance); // MeshEncoder.ShortEdgeTolerance in model units
mesh.Ngons.AddPlanarNgons(GeometryTolerance.Model.VertexTolerance, 4, 2, true);
return mesh;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/RhinoInside.Revit/Convert/Geometry/Raw/RawDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ public static Curve ToRhino(ARDB.Curve curve)

public static PolylineCurve ToRhino(ARDB.PolyLine polyline)
{
return new PolylineCurve(polyline.GetCoordinates().Select(x => AsPoint3d(x)));
return new PolylineCurve(polyline.GetCoordinates().Select(AsPoint3d));
}
#endregion

Expand Down
Loading