diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 89c55a3940..655c449372 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -1257,6 +1257,50 @@ public: return _res; } }; + /** Make an evolved shape + * + * An evolved shape is built from a planar spine (face or wire) and a + * profile (wire). The evolved shape is the unlooped sweep (pipe) of the + * profile along the spine. Self-intersections are removed. + * + * @param spine: the spine shape, must be planar face or wire + * @param profile: the profile wire, must be planar, or a line segment + * @param join: the join type (only support Arc at the moment) + * @param axeProf: determine the coordinate system for the profile + * @param solid: whether to make a solid + * @param profOnSpine: whether the profile is connect with the spine + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return The original content of this TopoShape is discarded and replaced + * with the new shape. The function returns the TopoShape itself as + * a self reference so that multiple operations can be carried out + * for the same shape in the same line of code. + */ + TopoShape &makEEvolve(const TopoShape &spine, const TopoShape &profile, JoinType join=JoinType::Arc, + bool axeProf=true, bool solid=false, bool profOnSpine=false, double tol=0.0, const char *op=nullptr); + + /** Make an evolved shape using this shape as spine + * + * An evolved shape is built from a planar spine (face or wire) and a + * profile (wire). The evolved shape is the unlooped sweep (pipe) of the + * profile along the spine. Self-intersections are removed. + * + * @param profile: the profile wire, must be planar, or a line segment + * @param join: the join type (only support Arc at the moment) + * @param axeProf: determine the coordinate system for the profile + * @param solid: whether to make a solid + * @param profOnSpine: whether the profile is connect with the spine + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Return the new shape. The TopoShape itself is not modified. + */ + TopoShape makEEvolve(const TopoShape &profile, JoinType join=JoinType::Arc, + bool axeProf=true, bool solid=false, bool profOnSpine=false, double tol=0.0, const char *op=nullptr) + { + return TopoShape(0,Hasher).makEEvolve(*this, profile, join, axeProf, solid, profOnSpine, tol, op); + } /** Make an loft that is a shell or solid passing through a set of sections in a given sequence * diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index 3faf12ffe9..5c7ebff853 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -1857,6 +1857,76 @@ TopoShape TopoShape::getSubTopoShape(TopAbs_ShapeEnum type, int idx, bool silent return shapeMap.getTopoShape(*this, idx); } +TopoShape &TopoShape::makEEvolve(const TopoShape &spine, + const TopoShape &profile, + JoinType join, + bool axeProf, + bool solid, + bool profOnSpine, + double tol, + const char *op) +{ + if (!op) + op = Part::OpCodes::Evolve; + if (tol == 0.0) + tol = 1e-6; + + GeomAbs_JoinType joinType; + switch (join) { + case JoinType::Arc: + joinType = GeomAbs_Tangent; + break; + case JoinType::Intersection: + joinType = GeomAbs_Intersection; + break; + default: + joinType = GeomAbs_Arc; + break; + } + + TopoDS_Shape spineShape; + if (spine.countSubShapes(TopAbs_FACE) > 0) + spineShape = spine.getSubShape(TopAbs_FACE, 1); + else if (spine.countSubShapes(TopAbs_WIRE) > 0) + spineShape = spine.getSubShape(TopAbs_WIRE, 1); + else if (spine.countSubShapes(TopAbs_EDGE) > 0) + spineShape = BRepBuilderAPI_MakeWire(TopoDS::Edge(spine.getSubShape(TopAbs_EDGE, 1))).Wire(); + if (spineShape.IsNull() || !BRepBuilderAPI_FindPlane(spineShape).Found()) + FC_THROWM(Base::CADKernelError, "Expect the the spine to be a planar wire or face"); + + TopoDS_Shape profileShape; + if (profile.countSubShapes(TopAbs_FACE) > 0 || profile.countSubShapes(TopAbs_WIRE) > 0) + profileShape = profile.getSubShape(TopAbs_WIRE, 1); + else if (profile.countSubShapes(TopAbs_EDGE) > 0) + profileShape = BRepBuilderAPI_MakeWire(TopoDS::Edge(profile.getSubShape(TopAbs_EDGE, 1))).Wire(); + if (profileShape.IsNull() || !BRepBuilderAPI_FindPlane(profileShape).Found()) { + if (profileShape.IsNull() + || profile.countSubShapes(TopAbs_EDGE) > 1 + || !profile.getSubTopoShape(TopAbs_EDGE, 1).isLinearEdge()) + { + FC_THROWM(Base::CADKernelError, "Expect the the profile to be a planar wire or face or a line"); + } + } + if (spineShape.ShapeType() == TopAbs_FACE) { + BRepOffsetAPI_MakeEvolved maker(TopoDS::Face(spineShape), + TopoDS::Wire(profileShape), joinType, + axeProf ? Standard_True : Standard_False, + solid ? Standard_True : Standard_False, + profOnSpine ? Standard_True : Standard_False, + tol); + return makEShape(maker, {spine, profile}, op); + } + else { + BRepOffsetAPI_MakeEvolved maker(TopoDS::Wire(spineShape), + TopoDS::Wire(profileShape), joinType, + axeProf ? Standard_True : Standard_False, + solid ? Standard_True : Standard_False, + profOnSpine ? Standard_True : Standard_False, + tol); + return makEShape(maker, {spine, profile}, op); + } +} + TopoShape& TopoShape::makeElementRuledSurface(const std::vector& shapes, int orientation, const char* op)