//--------------------------------------------------------------------------------------------------

        bool _FindBendAxis(MakeContext context)
        {
            // Find the longest edge to revolve around
            var foundEdges = EdgeAlgo.FindLongestEdge(context.TargetFace);

            if (!foundEdges.axis.HasValue || !foundEdges.opAxis.HasValue)
            {
                Messages.Error("No linear edge found to bend around.");
                return(false);
            }

            context.BendEdge     = _Reverse ? foundEdges.opEdge : foundEdges.edge;
            context.OppositeEdge = _Reverse ? foundEdges.edge : foundEdges.opEdge;
            context.BendAxis     = _Reverse ? foundEdges.opAxis.Value : foundEdges.axis.Value;

            // Direction of the inner: Get face plane, get cross vector of edge axis and plane normal
            if (!FaceAlgo.GetCenteredPlaneFromFace(context.TargetFace, out var facePlane))
            {
                Messages.Error("Face must be of planar type.");
                return(false);
            }

            context.TopDirection = context.BendAxis.Direction.Crossed(facePlane.Axis.Direction);

            // Move axis by radius to the center of the revolve
            var radius = Math.Max(0.001, _Radius);

            context.BendAxis.Translate(context.TopDirection.ToVec().Multiplied(radius));
            return(true);
        }
        public void FindMinMaxAdjacentFaces()
        {
            var box    = Box.Create(10.0, 10.0, 1.0);
            var edge   = box.GetBRep().Edges()[1];
            var faces  = box.GetBRep().Faces();
            var result = EdgeAlgo.FindSmallestAndLargestAdjacentFaces(box.GetBRep(), edge);

            Assert.NotNull(result.smallestFace);
            Assert.NotNull(result.largestFace);

            Assert.AreEqual(faces[0], result.smallestFace);
            Assert.AreEqual(faces[5], result.largestFace);
        }
        public void FindAdjacentFaces()
        {
            var box   = Box.Create(10.0, 10.0, 1.0);
            var edge  = box.GetBRep().Edges()[1];
            var faces = box.GetBRep().Faces();

            var(face1, face2) = EdgeAlgo.FindAdjacentFaces(box.GetBRep(), edge);

            Assert.NotNull(face1);
            Assert.NotNull(face2);

            Assert.AreEqual(faces[0], face1);
            Assert.AreEqual(faces[5], face2);
        }
        public void FindLongestEdge()
        {
            var box    = Box.Create(10.0, 10.0, 1.0);
            var face   = box.GetBRep().Faces()[1];
            var edges  = face.Edges();
            var result = EdgeAlgo.FindLongestEdge(face);

            Assert.NotNull(result.edge);
            Assert.NotNull(result.axis);
            Assert.NotNull(result.opEdge);
            Assert.NotNull(result.opAxis);

            Assert.AreEqual(edges[1], result.edge);
            Assert.AreEqual(edges[3], result.opEdge);

            Assert.IsTrue(result.axis.Value.IsParallel(result.opAxis.Value, Double.Epsilon));
        }
Beispiel #5
0
        //--------------------------------------------------------------------------------------------------

        void _AddEdgeProperties(TopoDS_Edge edge)
        {
            const string edgecat  = "Edge";
            const string curvecat = "Curve";

            if (Shape != null)
            {
                var subshapeRef = Shape.GetSubshapeReference(_TopLevelShape, edge);
                _AddProperty(edgecat, "SubshapeRef", subshapeRef?.ToString() ?? "null");
            }

            var flags = "";

            if (BRep_Tool.Degenerated(edge))
            {
                flags += "Degenerated ";
            }
            if (BRep_Tool.SameParameter(edge))
            {
                flags += "SameParameter ";
            }
            if (BRep_Tool.SameRange(edge))
            {
                flags += "SameRange ";
            }

            _AddProperty(edgecat, "Is Closed", $"{(BRep_Tool.IsClosed(edge) ? "Yes" : "No")}");
            _AddProperty(edgecat, "Curve Type", $"{(BRep_Tool.IsGeometric(edge) ? "Geometric Curve" : "Curve on Surface")}");

            var props = new GProp_GProps();

            BRepGProp.LinearProperties(BrepShape, props);
            _AddProperty(edgecat, "Length", $"{props.Mass()}");

            _AddProperty(edgecat, "Tolerance", $"{BRep_Tool.Tolerance(edge)}");
            if (!flags.IsEmpty())
            {
                _AddProperty(edgecat, "Flags", flags);
            }

            if (BRep_Tool.IsGeometric(edge))
            {
                // 3D curve
                double first = 0, last = 0;
                var    curve = BRep_Tool.Curve(edge, ref first, ref last);
                if (curve != null)
                {
                    _AddProperty(edgecat, "Parameter", $"({first}, {last})");
                    _AddProperty(curvecat, "Class", curve.GetType().Name.Replace("Geom_", ""));
                    _AddProperty(curvecat, "Is Closed", $"{(curve.IsClosed() ? "Yes" : "No")}");
                    if (curve.IsPeriodic())
                    {
                        _AddProperty(curvecat, "Period", $"{curve.Period()}");
                    }
                    _AddProperty(curvecat, "Continuity", curve.Continuity().ToString().Replace("GeomAbs_", ""));

                    switch (curve)
                    {
                    case Geom_Line line:
                        const string linecat = "Line";
                        var          lineLoc = line.Position().Location;
                        _AddProperty(linecat, "Location", $"({lineLoc.X.ToRoundedString()}, {lineLoc.Y.ToRoundedString()}, {lineLoc.Z.ToRoundedString()})");
                        var lineDir = line.Position().Direction;
                        _AddProperty(linecat, "Direction", $"({lineDir.X.ToRoundedString()}, {lineDir.Y.ToRoundedString()}, {lineDir.Z.ToRoundedString()})");
                        break;

                    case Geom_Circle circle:
                        const string circlecat = "Circle";
                        _AddProperty(circlecat, "Radius", $"{circle.Radius().ToRoundedString()}");
                        var circleLoc = circle.Position().Location;
                        _AddProperty(circlecat, "Location", $"({circleLoc.X.ToRoundedString()}, {circleLoc.Y.ToRoundedString()}, {circleLoc.Z.ToRoundedString()})");
                        var circleDir = circle.Position().Direction;
                        _AddProperty(circlecat, "Direction", $"({circleDir.X.ToRoundedString()}, {circleDir.Y.ToRoundedString()}, {circleDir.Z.ToRoundedString()})");
                        var circleXDir = circle.Position().XDirection;
                        _AddProperty(circlecat, "X-Direction", $"({circleXDir.X.ToRoundedString()}, {circleXDir.Y.ToRoundedString()}, {circleXDir.Z.ToRoundedString()})");
                        var circleYDir = circle.Position().YDirection;
                        _AddProperty(circlecat, "Y-Direction", $"({circleYDir.X.ToRoundedString()}, {circleYDir.Y.ToRoundedString()}, {circleYDir.Z.ToRoundedString()})");
                        break;

                    case Geom_Ellipse ellipse:
                        const string ellipsecat = "Ellipse";
                        _AddProperty(ellipsecat, "Major Radius", $"{ellipse.MajorRadius().ToRoundedString()}");
                        _AddProperty(ellipsecat, "Minor Radius", $"{ellipse.MinorRadius().ToRoundedString()}");
                        _AddProperty(ellipsecat, "Eccentricity", $"{ellipse.Eccentricity().ToRoundedString()}");
                        _AddProperty(ellipsecat, "Focal", $"{ellipse.Focal().ToRoundedString()}");
                        var ellipseFocus = ellipse.Focus1();
                        _AddProperty(ellipsecat, "Focus 1", $"({ellipseFocus.X.ToRoundedString()}, {ellipseFocus.Y.ToRoundedString()}, {ellipseFocus.Z.ToRoundedString()})");
                        ellipseFocus = ellipse.Focus2();
                        _AddProperty(ellipsecat, "Focus 2", $"({ellipseFocus.X.ToRoundedString()}, {ellipseFocus.Y.ToRoundedString()}, {ellipseFocus.Z.ToRoundedString()})");
                        var ellipseLoc = ellipse.Position().Location;
                        _AddProperty(ellipsecat, "Location", $"({ellipseLoc.X.ToRoundedString()}, {ellipseLoc.Y.ToRoundedString()}, {ellipseLoc.Z.ToRoundedString()})");
                        var ellipseDir = ellipse.Position().Direction;
                        _AddProperty(ellipsecat, "Direction", $"({ellipseDir.X.ToRoundedString()}, {ellipseDir.Y.ToRoundedString()}, {ellipseDir.Z.ToRoundedString()})");
                        var ellipseXDir = ellipse.Position().XDirection;
                        _AddProperty(ellipsecat, "X-Direction", $"({ellipseXDir.X.ToRoundedString()}, {ellipseXDir.Y.ToRoundedString()}, {ellipseXDir.Z.ToRoundedString()})");
                        var ellipseYDir = ellipse.Position().YDirection;
                        _AddProperty(ellipsecat, "Y-Direction", $"({ellipseYDir.X.ToRoundedString()}, {ellipseYDir.Y.ToRoundedString()}, {ellipseYDir.Z.ToRoundedString()})");
                        break;

                    case Geom_BezierCurve bezier:
                        const string beziercat = "Bézier Curve";
                        _AddProperty(beziercat, "Degree", $"{bezier.Degree()}");
                        _AddProperty(beziercat, "Pole Count", $"{bezier.NbPoles()}");
                        _AddProperty(beziercat, "Is Rational", $"{(bezier.IsRational() ? "Yes" : "No")}");
                        break;

                    case Geom_BSplineCurve bspline:
                        const string bsplinecat = "B-Spline Curve";
                        _AddProperty(bsplinecat, "Degree", $"{bspline.Degree()}");
                        _AddProperty(bsplinecat, "Pole Count", $"{bspline.NbPoles()}");
                        _AddProperty(bsplinecat, "Knoe Count", $"{bspline.NbKnots()}");
                        _AddProperty(bsplinecat, "Knot Distrib.", bspline.KnotDistribution().ToString().Replace("GeomAbs_", ""));
                        _AddProperty(bsplinecat, "Is Rational", $"{(bspline.IsRational() ? "Yes" : "No")}");
                        break;
                    }
                }
            }
            else
            {
                // Curve on surface, currently not supported
            }

            // Get continuity information
            var(face1, face2) = EdgeAlgo.FindAdjacentFaces(_TopLevelShape, edge);
            if (face1 != null && face2 != null)
            {
                _AddProperty(edgecat, "Face Contin.", BRep_Tool.Continuity(edge, face1, face2).ToString().Replace("GeomAbs_", ""));
            }
        }
        //--------------------------------------------------------------------------------------------------

        void _FindFacesConnectedToBendSection(MakeContext context, TopoDS_Edge sharedEdge, BendParameter bendParams)
        {
            // Find connected section faces
            bendParams.ConnectedInSharedEdges[0] = sharedEdge;
            bendParams.ConnectedInFaces[0]       = FaceAlgo.FindConnectedFace(context.SourceShape, bendParams.Faces[0], sharedEdge);
            var opEdge = bendParams.Faces[0].Edges().Find(e => !e.IsSame(sharedEdge) && !e.IsSame(bendParams.Edges[0]) && !e.IsSame(bendParams.Edges[1]));

            if (opEdge != null)
            {
                bendParams.ConnectedOutSharedEdges[0] = opEdge;
                bendParams.ConnectedOutFaces[0]       = FaceAlgo.FindConnectedFace(context.SourceShape, bendParams.Faces[0], opEdge);
            }

            // Find the other connection edge
            TopoDS_Vertex sharedVtx1 = null;

            foreach (var edge in bendParams.Faces[1].Edges())
            {
                var vtx = EdgeAlgo.FindSharedVertex(edge, sharedEdge);
                if (vtx != null)
                {
                    // Get the other (not shared) vertex
                    sharedVtx1 = edge.Vertices().Find(v => !v.IsSame(vtx));
                    break;
                }
            }
            TopoDS_Vertex sharedVtx2 = null;

            foreach (var edge in bendParams.Faces[2].Edges())
            {
                var vtx = EdgeAlgo.FindSharedVertex(edge, sharedEdge);
                if (vtx != null)
                {
                    // Get the other (not shared) vertex
                    sharedVtx2 = edge.Vertices().Find(v => !v.IsSame(vtx));
                    break;
                }
            }
            TopoDS_Edge otherSharedEdge = null;

            foreach (var edge in bendParams.Faces[3].Edges())
            {
                var vertices = edge.Vertices();
                if (vertices.ContainsSame(sharedVtx1) &&
                    vertices.ContainsSame(sharedVtx2))
                {
                    otherSharedEdge = edge;
                    break;
                }
            }
            if (otherSharedEdge == null)
            {
                return;
            }

            // Find connected section faces for the other edge
            bendParams.ConnectedOutSharedEdges[1] = otherSharedEdge;
            bendParams.ConnectedInFaces[1]        = FaceAlgo.FindConnectedFace(context.SourceShape, bendParams.Faces[3], otherSharedEdge);
            var otherOpEdge = bendParams.Faces[3].Edges().Find(e => !e.IsSame(otherSharedEdge) && !e.IsSame(bendParams.Edges[2]) && !e.IsSame(bendParams.Edges[3]));

            if (otherOpEdge != null)
            {
                bendParams.ConnectedOutSharedEdges[1] = otherOpEdge;
                bendParams.ConnectedOutFaces[1]       = FaceAlgo.FindConnectedFace(context.SourceShape, bendParams.Faces[3], otherOpEdge);
            }
        }
        //--------------------------------------------------------------------------------------------------

        /*
         * Determine if a face belongs to a bend section. To recognise a bend section, it must have the
         * following structure:
         * - Four faces, two of them planar (side faces) and two of them cylinder (top/bottom)
         * - All edges connecting these four faces must be circular
         * - All circles must have coaxial axes with only two different positions
         * - All circles must have one of two radii
         *
         * If a side face is detected, the iteration of faces should stop, but no section is built.
         * If a top/bottom face is detected, the whole section is recovered and all parameters are
         * determined. The faces are found by searching for faces which share the circular edges.
         *
         * This function is called recursively if one of the out-faces is also recognized
         * as part of a connected bend section.
         */
        bool _AnalyzeBendSection(MakeContext context, TopoDS_Face baseFace, TopoDS_Edge sharedEdge, out Section section)
        {
            section = null;

            var bendParams = new BendParameter();

            bendParams.Faces[0] = baseFace;

            if (!_IsFaceOfBendSection(baseFace, bendParams))
            {
                return(false);
            }

            var faceAdaptor = new BRepAdaptor_Surface(baseFace);

            // Surface is flat, but two edges are of circle and coplanar
            if (faceAdaptor.GetGeomType() == GeomAbs_SurfaceType.GeomAbs_Plane)
            {
                // Ignore them for the moment, but sign them as bend section face
                return(true);
            }

            if (faceAdaptor.GetGeomType() != GeomAbs_SurfaceType.GeomAbs_Cylinder)
            {
                // Surface must be of type Cylinder, other are not supported currently
                return(false);
            }

            // Find side faces
            var facesForEdge0 = EdgeAlgo.FindAdjacentFaces(context.SourceShape, bendParams.Edges[0]);

            bendParams.Faces[1] = facesForEdge0.face1.IsSame(baseFace) ? facesForEdge0.face2 : facesForEdge0.face1;
            if (!_IsFaceOfBendSection(bendParams.Faces[1], bendParams))
            {
                return(false);
            }
            var facesForEdge1 = EdgeAlgo.FindAdjacentFaces(context.SourceShape, bendParams.Edges[1]);

            bendParams.Faces[2] = facesForEdge1.face1.IsSame(baseFace) ? facesForEdge1.face2 : facesForEdge1.face1;
            if (!_IsFaceOfBendSection(bendParams.Faces[2], bendParams))
            {
                return(false);
            }

            // Find fourth face
            var facesForEdge2 = EdgeAlgo.FindAdjacentFaces(context.SourceShape, bendParams.Edges[2]);
            var facesForEdge3 = EdgeAlgo.FindAdjacentFaces(context.SourceShape, bendParams.Edges[3]);

            if (facesForEdge2.face1.IsSame(facesForEdge3.face1) ||
                facesForEdge2.face1.IsSame(facesForEdge3.face2))
            {
                bendParams.Faces[3] = facesForEdge2.face1;
            }
            else if (facesForEdge2.face2.IsSame(facesForEdge3.face1) ||
                     facesForEdge2.face2.IsSame(facesForEdge3.face2))
            {
                bendParams.Faces[3] = facesForEdge2.face2;
            }
            else
            {
                return(false); // fourth face not found
            }
            if (!_IsFaceOfBendSection(bendParams.Faces[3], bendParams))
            {
                return(false);
            }

            // Create Section
            section = new Section();
            section.Faces.AddRange(bendParams.Faces.Where(face => face != null));
            section.BendParameter = bendParams;

            // Find connected faces
            _FindFacesConnectedToBendSection(context, sharedEdge, bendParams);

            // Check if the connected section is also an bend section
            if (bendParams.ConnectedOutFaces[0] != null &&
                _AnalyzeBendSection(context, bendParams.ConnectedOutFaces[0], bendParams.ConnectedOutSharedEdges[0], out var connectedBendSection))
            {
                if (connectedBendSection == null)
                {
                    Messages.Error("A bend section is connected to another bend section with an perpendicular direction.",
                                   "To fix this, you need to add a small flange between these two bend sections.");
                }
                section.Children.Add(connectedBendSection);
            }
            else
            {
                section.Children.Add(new Section()); // Bend sections have exactly one connected section
            }
            return(true);
        }
Beispiel #8
0
        //--------------------------------------------------------------------------------------------------

        bool _DoOffset(MakeContext context)
        {
            if (_Offset <= 0)
            {
                return(false);
            }

            // Move neutral plane
            var newPlane = context.NeutralPlane.Translated(context.Direction.ToVec().Multiplied(_Offset));

            // Create section edge
            var faceOfPlane = new BRepBuilderAPI_MakeFace(new Geom_Plane(newPlane), Precision.Confusion()).Shape();
            var section     = new BRepAlgoAPI_Section(context.Face, faceOfPlane);

            section.Build();
            if (!section.IsDone())
            {
                Messages.Warning("The offset can not be performed, section operation failed.");
                return(false);
            }
            var newEdge = section.Shape().Edges().FirstOrDefault();

            if (!section.IsDone() || newEdge == null)
            {
                Messages.Warning("The offset value seems to be out of range.");
                return(false);
            }

            if (context.ReversedFaceSense)
            {
                newEdge.Orientation(TopAbs_Orientation.TopAbs_REVERSED);
            }

            // Split face with section edge
            var splitShape = new BRepFeat_SplitShape(context.Source);

            splitShape.Add(newEdge, context.Face);
            splitShape.Build();
            if (!splitShape.IsDone())
            {
                Messages.Warning("The offset can not be performed, the face split operation failed.");
                return(false);
            }
            var newShape = splitShape.Shape();
            var newFace  = splitShape.DirectLeft().First().ToFace();

            // Reduce continuity of new edge to C0 to allow the draft algo to make a sharp corner
            var(face1, face2) = EdgeAlgo.FindAdjacentFaces(newShape, newEdge);
            if (face1 == null || face2 == null)
            {
                Messages.Warning("The offset can not be performed, invalid face count after split operation.");
                return(false);
            }
            var builder = new BRep_Builder();

            builder.Continuity(newEdge, face1, face2, GeomAbs_Shape.GeomAbs_C0);

            // Set results
            context.NeutralPlane = newPlane;
            context.Source       = newShape;
            context.Face         = newFace;
            UpdateModifiedSubshapes(context.Source, splitShape);

            return(true);
        }