Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }