internal static Brep ToBrep(DB.Face face) { var surface = Raw.RawDecoder.ToRhinoSurface(face, out var _, 1.0); if (surface is null) { return(null); } var brep = Brep.CreateFromSurface(surface); if (brep is null) { return(null); } if (!face.MatchesSurfaceOrientation()) { brep.Flip(); } var loops = ToCurveMany(face.GetEdgesAsCurveLoops()).ToArray(); try { return(TrimFaces(brep, loops)); } finally { brep.Dispose(); } }
public static Brep ToRhino(DB.Face face) { if (face is null) { return(null); } var brep = new Brep(); // Set surface var si = AddSurface(brep, face, out var shells); if (si < 0) { return(null); } // Set edges & trims TrimSurface(brep, si, !face.MatchesSurfaceOrientation(), shells); // Set vertices brep.SetVertices(); // Set flags brep.SetTolerancesBoxesAndFlags ( true, true, true, true, true, true, true, true ); if (!brep.IsValid) { #if DEBUG brep.IsValidWithLog(out var log); Debug.WriteLine($"{MethodInfo.GetCurrentMethod().DeclaringType.FullName}.{MethodInfo.GetCurrentMethod().Name}()\n{log}"); #endif brep.Repair(Revit.VertexTolerance); } return(brep); }
public static Brep ToRhino(DB.Face face) { if (face is null) { return(null); } var brep = new Brep(); // Set surface var si = AddSurface(brep, face, out var shells); if (si < 0) { return(null); } // Set edges & trims TrimSurface(brep, si, !face.MatchesSurfaceOrientation(), shells); // Set vertices brep.SetVertices(); // Set flags brep.SetTolerancesBoxesAndFlags ( true, true, true, true, true, true, true, true ); if (!brep.IsValid) { #if DEBUG brep.IsValidWithLog(out var log); #endif brep.Repair(Revit.VertexTolerance); } return(brep); }
static int AddSurface(Brep brep, DB.Face face, out List <BrepBoundary>[] shells, Dictionary <DB.Edge, BrepEdge> brepEdges = null) { // Extract base surface if (ToRhinoSurface(face, out var parametricOrientation) is Surface surface) { if (!parametricOrientation) { surface.Transpose(true); } int si = brep.AddSurface(surface); if (surface is PlaneSurface planar) { var nurbs = planar.ToNurbsSurface(); nurbs.KnotsU.InsertKnot(surface.Domain(0).Mid); nurbs.KnotsV.InsertKnot(surface.Domain(1).Mid); surface = nurbs; } else if (surface is SumSurface sum) { surface = sum.ToNurbsSurface(); } // Extract and classify Edge Loops var edgeLoops = new List <BrepBoundary>(face.EdgeLoops.Size); foreach (var edgeLoop in face.EdgeLoops.Cast <DB.EdgeArray>()) { if (edgeLoop.IsEmpty) { continue; } var edges = edgeLoop.Cast <DB.Edge>(); if (!face.MatchesSurfaceOrientation()) { edges = edges.Reverse(); } var loop = new BrepBoundary() { type = BrepLoopType.Unknown, edges = new List <BrepEdge>(edgeLoop.Size), trims = new PolyCurve(), orientation = new List <int>(edgeLoop.Size) }; foreach (var edge in edges) { var brepEdge = default(BrepEdge); if (brepEdges?.TryGetValue(edge, out brepEdge) != true) { var curve = edge.AsCurve(); if (curve is null) { continue; } brepEdge = brep.Edges.Add(brep.AddEdgeCurve(ToRhino(curve))); brepEdges?.Add(edge, brepEdge); } loop.edges.Add(brepEdge); var segment = ToRhino(edge.AsCurveFollowingFace(face)); if (!face.MatchesSurfaceOrientation()) { segment.Reverse(); } loop.orientation.Add(segment.TangentAt(segment.Domain.Mid).IsParallelTo(brepEdge.TangentAt(brepEdge.Domain.Mid))); var trim = surface.Pullback(segment, Revit.VertexTolerance); loop.trims.Append(trim); } loop.trims.MakeClosed(Revit.VertexTolerance); switch (loop.trims.ClosedCurveOrientation()) { case CurveOrientation.Undefined: loop.type = BrepLoopType.Unknown; break; case CurveOrientation.CounterClockwise: loop.type = BrepLoopType.Outer; break; case CurveOrientation.Clockwise: loop.type = BrepLoopType.Inner; break; } edgeLoops.Add(loop); } var outerLoops = edgeLoops.Where(x => x.type == BrepLoopType.Outer); var innerLoops = edgeLoops.Where(x => x.type == BrepLoopType.Inner); // Group Edge loops in shells with the outer loop as the first one shells = outerLoops. Select(x => new List <BrepBoundary>() { x }). ToArray(); if (shells.Length == 1) { shells[0].AddRange(innerLoops); } else { foreach (var edgeLoop in innerLoops) { foreach (var shell in shells) { var containment = Curve.PlanarClosedCurveRelationship(edgeLoop.trims, shell[0].trims, Plane.WorldXY, Revit.VertexTolerance); if (containment == RegionContainment.AInsideB) { shell.Add(edgeLoop); break; } } } } return(si); } shells = default; return(-1); }
static int AddSurface(Brep brep, DB.Face face, out List <BrepBoundary>[] shells, Dictionary <DB.Edge, BrepEdge> brepEdges = null) { // Extract base surface if (ToRhinoSurface(face, out var parametricOrientation) is Surface surface) { if (!parametricOrientation) { surface.Transpose(true); } int si = brep.AddSurface(surface); if (surface is PlaneSurface planar) { var nurbs = planar.ToNurbsSurface(); nurbs.KnotsU.InsertKnot(surface.Domain(0).Mid); nurbs.KnotsV.InsertKnot(surface.Domain(1).Mid); surface = nurbs; } else if (surface is SumSurface sum) { surface = sum.ToNurbsSurface(); } // Extract and classify Edge Loops var edgeLoops = new List <BrepBoundary>(face.EdgeLoops.Size); foreach (var edgeLoop in face.EdgeLoops.Cast <DB.EdgeArray>()) { if (edgeLoop.IsEmpty) { continue; } var edges = edgeLoop.Cast <DB.Edge>(); if (!face.MatchesSurfaceOrientation()) { edges = edges.Reverse(); } var loop = new BrepBoundary() { type = BrepLoopType.Unknown, orientation = new List <int>(edgeLoop.Size), edges = new List <BrepEdge>(edgeLoop.Size), trims = new PolyCurve() }; var trims = new List <Curve>(edgeLoop.Size); foreach (var edge in edges) { var brepEdge = default(BrepEdge); if (brepEdges?.TryGetValue(edge, out brepEdge) != true) { var curve = edge.AsCurve(); if (curve is null) { continue; } brepEdge = brep.Edges.Add(brep.AddEdgeCurve(ToRhino(curve))); brepEdges?.Add(edge, brepEdge); } var segment = ToRhino(edge.AsCurveFollowingFace(face)); if (!face.MatchesSurfaceOrientation()) { segment.Reverse(); } if (surface.Pullback(segment, 1e-5) is Curve trim) { trims.Add(trim); loop.edges.Add(brepEdge); loop.orientation.Add(segment.TangentAt(segment.Domain.Mid).IsParallelTo(brepEdge.TangentAt(brepEdge.Domain.Mid))); } } // Add singular edges for (int ti = 0, ei = 0; ti < trims.Count; ++ti, ++ei) { int tA = ti; int tB = (ti + 1) % trims.Count; loop.trims.AppendSegment(trims[tA]); int eA = ei; int eB = (ei + 1) % loop.edges.Count; var start = loop.orientation[eA] > 0 ? (loop.edges[eA]).PointAtEnd : (loop.edges[eA]).PointAtStart; var end = loop.orientation[eB] > 0 ? (loop.edges[eB]).PointAtStart : (loop.edges[eB]).PointAtEnd; if (start.EpsilonEquals(end, Revit.VertexTolerance)) { var startTrim = new Point2d(trims[tA].PointAtEnd); var endTrim = new Point2d(trims[tB].PointAtStart); var midTrim = (endTrim + startTrim) * 0.5; if (surface.IsAtSingularity(midTrim.X, midTrim.Y, false)) { loop.orientation.Insert(eA + 1, 0); loop.edges.Insert(eA + 1, default); loop.trims.AppendSegment(new LineCurve(startTrim, endTrim)); ei++; } } else // Missing edge { Debug.WriteLine("Missing edge detected"); } } loop.trims.MakeClosed(Revit.VertexTolerance); switch (loop.trims.ClosedCurveOrientation()) { case CurveOrientation.Undefined: loop.type = BrepLoopType.Unknown; break; case CurveOrientation.CounterClockwise: loop.type = BrepLoopType.Outer; break; case CurveOrientation.Clockwise: loop.type = BrepLoopType.Inner; break; } edgeLoops.Add(loop); } var outerLoops = edgeLoops.Where(x => x.type == BrepLoopType.Outer); var innerLoops = edgeLoops.Where(x => x.type == BrepLoopType.Inner); // Group Edge loops in shells with the outer loop as the first one shells = outerLoops. Select(x => new List <BrepBoundary>() { x }). ToArray(); if (shells.Length == 1) { shells[0].AddRange(innerLoops); } else { foreach (var edgeLoop in innerLoops) { foreach (var shell in shells) { var containment = Curve.PlanarClosedCurveRelationship(edgeLoop.trims, shell[0].trims, Plane.WorldXY, Revit.VertexTolerance); if (containment == RegionContainment.AInsideB) { shell.Add(edgeLoop); break; } } } } return(si); } shells = default; return(-1); }