예제 #1
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
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);
        }
        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);
        }