static int AddSurface(Brep brep, Surface surface, Curve[] loops, out List <BrepBoundary>[] shells) { // Extract base surface if (surface is object) { double trimTolerance = Revit.VertexTolerance * 0.1; int si = brep.AddSurface(surface); if (surface is PlaneSurface) { var nurbs = surface.ToNurbsSurface(); nurbs.KnotsU.InsertKnot(surface.Domain(0).Mid); nurbs.KnotsV.InsertKnot(surface.Domain(1).Mid); surface = nurbs; } // Classify Loops var nesting = new int[loops.Length]; var edgeLoops = new BrepBoundary[loops.Length]; { var trims = new Curve[loops.Length]; int index = 0; foreach (var loop in loops) { if (loop is PolyCurve polycurve) { var trim = new PolyCurve(); for (int s = 0; s < polycurve.SegmentCount; s++) { var segment = polycurve.SegmentCurve(s); var trimSegment = surface.Pullback(segment, trimTolerance); trim.AppendSegment(trimSegment); } trims[index++] = trim; } else { trims[index++] = surface.Pullback(loop, trimTolerance); } } for (int i = 0; i < edgeLoops.Length; ++i) { for (int j = i + 1; j < edgeLoops.Length; ++j) { var containment = Curve.PlanarClosedCurveRelationship(trims[i], trims[j], Plane.WorldXY, Revit.VertexTolerance * Revit.ModelUnits); if (containment == RegionContainment.MutualIntersection) { edgeLoops[i].type = BrepLoopType.Outer; edgeLoops[j].type = BrepLoopType.Outer; } else if (containment == RegionContainment.AInsideB) { nesting[i]++; } else if (containment == RegionContainment.BInsideA) { nesting[j]++; } } } // Fix orientation if necessary index = 0; foreach (var loop in loops) { // Ignore intersecting loops if (edgeLoops[index].type == BrepLoopType.Unknown) { if (nesting[index] % 2 != 0) { edgeLoops[index].type = BrepLoopType.Inner; } else { edgeLoops[index].type = BrepLoopType.Outer; } } switch (trims[index].ClosedCurveOrientation()) { case CurveOrientation.Undefined: break; case CurveOrientation.CounterClockwise: if (edgeLoops[index].type == BrepLoopType.Inner) { loops[index].Reverse(); } break; case CurveOrientation.Clockwise: if (edgeLoops[index].type == BrepLoopType.Outer) { loops[index].Reverse(); } break; } ++index; } } // Create Brep Edges and compute trims { int index = 0; foreach (var edgeLoop in loops) { // Ignore unclasified loops if (edgeLoops[index].type == BrepLoopType.Unknown) { continue; } var kinks = new List <double>(); { var domain = edgeLoop.Domain; var t = domain.Min; while (edgeLoop.GetNextDiscontinuity(Continuity.C1_locus_continuous, t, domain.Max, out t)) { kinks.Add(t); } } var edges = kinks.Count > 0 ? edgeLoop.Split(kinks) : new Curve[] { edgeLoop }; edgeLoops[index].edges = new List <BrepEdge>(); edgeLoops[index].trims = new PolyCurve(); edgeLoops[index].orientation = new List <int>(); foreach (var edge in edges) { var brepEdge = default(BrepEdge); brepEdge = brep.Edges.Add(brep.AddEdgeCurve(edge)); edgeLoops[index].edges.Add(brepEdge); var segment = edge; edgeLoops[index].orientation.Add(segment.TangentAt(segment.Domain.Mid).IsParallelTo(brepEdge.TangentAt(brepEdge.Domain.Mid))); var trim = surface.Pullback(segment, trimTolerance); edgeLoops[index].trims.Append(trim); } edgeLoops[index].trims.MakeClosed(Revit.VertexTolerance); ++index; } } // Sort edgeLoops in nesting orther, shallow loops first Array.Sort(nesting, edgeLoops); 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 { // Iterate in reverse order to found deeper loops before others foreach (var innerLoop in innerLoops.Reverse()) { foreach (var shell in shells.Reverse()) { var containment = Curve.PlanarClosedCurveRelationship(innerLoop.trims, shell[0].trims, Plane.WorldXY, Revit.VertexTolerance); if (containment == RegionContainment.AInsideB) { shell.Add(innerLoop); 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); }
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); }
private static void AddNXFace(NXOpen.Face face, Brep brep) { Surface surface = face.ToRhinoSurface(); if (surface == null) { return; } int surfIndex = brep.AddSurface(surface); BrepFace brepFace = brep.Faces.Add(surfIndex); // Console.WriteLine("***************************************************"); try { var loopList = face.GetLoops().ToList(); if (loopList.Count == 0) { return; } if (loopList[0].Type != NXOpen.Extensions.Topology.LoopType.Outer && loopList[0].Type != NXOpen.Extensions.Topology.LoopType.LikelyOuter) { var outerLoop = loopList.FirstOrDefault(obj => obj.Type == NXOpen.Extensions.Topology.LoopType.Outer || obj.Type == NXOpen.Extensions.Topology.LoopType.LikelyOuter); if (outerLoop != null) { loopList.Remove(outerLoop); loopList.Insert(0, outerLoop); } } var faceSense = face.GetSense(); // Console.WriteLine("Face Sense:" + faceSense); var outerLoopSense = loopList[0].FirstFin.Sense; // Console.WriteLine("Outer loop:" + outerLoopSense); for (int i = 0; i < loopList.Count; i++) { // Console.WriteLine("********Loop*******"); var currentNxLoop = loopList[i]; if (currentNxLoop.Fins.Length == 0) { continue; } BrepLoopType brepLoopType; switch (currentNxLoop.Type) { case NXOpen.Extensions.Topology.LoopType.LikelyOuter: case NXOpen.Extensions.Topology.LoopType.Outer: brepLoopType = BrepLoopType.Outer; break; case NXOpen.Extensions.Topology.LoopType.LikelyInner: case NXOpen.Extensions.Topology.LoopType.Inner: case NXOpen.Extensions.Topology.LoopType.InnerSingular: brepLoopType = BrepLoopType.Inner; break; case NXOpen.Extensions.Topology.LoopType.Winding: if (i == 0) { brepLoopType = BrepLoopType.Outer; } else { brepLoopType = BrepLoopType.Inner; } break; case NXOpen.Extensions.Topology.LoopType.Unknown: default: brepLoopType = BrepLoopType.Unknown; break; } var brepLoop = brep.Loops.Add(brepLoopType, brepFace); var currentFin = currentNxLoop.FirstFin; var trims = new PolyCurve(); Dictionary <BrepEdge, int> brepEdges = new Dictionary <BrepEdge, int>(); int finCount = 0; do { finCount++; var curve3d = currentFin.Edge.ToRhinoCurve(); if (currentFin.StartVertex != null && curve3d.PointAtStart.DistanceTo(currentFin.StartVertex.Position.ToRhino()) > Globals.DistanceTolerance) { curve3d.Reverse(); } var brepEdgeCurve = brep.AddEdgeCurve(curve3d); var brepEdge = brep.Edges.Add(brepEdgeCurve); //Console.WriteLine("Start of Fin" + currentFin.StartVertex.Position); //Console.WriteLine("Start of Edge" + curve3d.PointAtStart); //Console.WriteLine("End of Fin" + currentFin.EndVertex.Position); //Console.WriteLine("End of Edge" + curve3d.PointAtEnd); brepEdges.Add(brepEdge, curve3d.TangentAt(curve3d.Domain.Mid).IsParallelTo(brepEdge.TangentAt(brepEdge.Domain.Mid))); var curve2d = surface.Pullback(curve3d, Globals.DistanceTolerance); trims.Append(curve2d); currentFin = currentFin.Next; } while (currentFin != currentNxLoop.FirstFin); trims.MakeClosed(Globals.DistanceTolerance); for (int j = 0; j < brepEdges.Count; j++) { if (trims.SegmentCurve(j) is Curve) { var curve = trims.SegmentCurve(j) as Curve; var ti = brep.AddTrimCurve(curve); if (brepEdges.ElementAt(j).Value == 0) { continue; } var brepTrim = brep.Trims.Add(brepEdges.ElementAt(j).Key, brepEdges.ElementAt(j).Value < 0, brepLoop, ti); brepTrim.TrimType = BrepTrimType.Boundary; } } // brepLoop.Trims.MatchEnds(); // brep.Trims.MatchEnds(brepLoop.Trims[0], brepLoop.Trims.Last()); // brep.Repair(Globals.DistanceTolerance); } } catch (Exception ex) { Console.WriteLine("无法添加 NX 面:" + ex); } brep.Trims.MatchEnds(); brep.Repair(Globals.DistanceTolerance); }