diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 06439746a9..0263b06d3a 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -33,6 +33,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include class gp_Ax1; @@ -764,6 +771,222 @@ public: CN, }; + + /** Generic shape making with mapped element name from shape history + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @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 built by the shape maker. 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& makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const std::vector& sources, + const char* op = nullptr); + /** Generic shape making with mapped element name from shape history + * + * @param mkShape: OCCT shape maker. + * @param source: source shape. + * @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 built by the shape maker. 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& makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const TopoShape& source, + const char* op = nullptr); + /** Generic shape making with mapped element name from shape history + * + * @param mkShape: OCCT shape maker. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Returns the new shape built by the shape maker with mappend element + * name generated using this shape as the source. The shape itself + * is not modified. + */ + TopoShape makeElementShape(BRepBuilderAPI_MakeShape& mkShape, const char* op = nullptr) const + { + return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op); + } + + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @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 built by the shape maker. 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& makeElementShape(BRepBuilderAPI_Sewing& mkShape, + const std::vector& sources, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param source: source shape. + * @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 built by the shape maker. 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& makeElementShape(BRepBuilderAPI_Sewing& mkShape, + const TopoShape& source, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Returns the new shape built by the shape maker with mappend element + * name generated using this shape as the source. The shape itself + * is not modified. + */ + TopoShape makeElementShape(BRepBuilderAPI_Sewing& mkShape, const char* op = nullptr) const + { + return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op); + } + + /** Specialized shape making for BRepBuilderAPI_ThruSections with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @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 built by the shape maker. 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& makeElementShape(BRepOffsetAPI_ThruSections& mkShape, + const std::vector& sources, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param source: source shape. + * @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 built by the shape maker. 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& makeElementShape(BRepOffsetAPI_ThruSections& mkShape, + const TopoShape& source, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Returns the new shape built by the shape maker with mappend element + * name generated using this shape as the source. The shape itself + * is not modified. + */ + TopoShape makeElementShape(BRepOffsetAPI_ThruSections& mkShape, const char* op = nullptr) const + { + return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op); + } + + /** Specialized shape making for BRepBuilderAPI_MakePipeShell with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @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 built by the shape maker. 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& makeElementShape(BRepOffsetAPI_MakePipeShell& mkShape, + const std::vector& sources, + const char* op = nullptr); + + /** Specialized shape making for BRepBuilderAPI_MakeHalfSpace with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param source: source shape. + * @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 built by the shape maker. 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& makeElementShape(BRepPrimAPI_MakeHalfSpace& mkShape, + const TopoShape& source, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_MakeHalfSpace with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Returns the new shape built by the shape maker with mappend element + * name generated using this shape as the source. The shape itself + * is not modified. + */ + TopoShape makeElementShape(BRepPrimAPI_MakeHalfSpace& mkShape, const char* op = nullptr) const + { + return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op); + } + + /** Specialized shape making for BRepBuilderAPI_MakePrism with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @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 built by the shape maker. 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& makeElementShape(BRepFeat_MakePrism& mkShape, + const std::vector& sources, + const TopoShape& uptoface, + const char* op); + + /** Helper class to return the generated and modified shape given an input shape + * + * Shape history information is extracted using OCCT APIs + * BRepBuilderAPI_MakeShape::Generated/Modified(). However, there is often + * some glitches in various derived class. So we use this class as an + * abstraction, and create various derived classes to deal with the glitches. + */ + friend class TopoShapeCache; private: @@ -898,6 +1121,22 @@ private: }; + +/** Shape mapper for generic BRepBuilderAPI_MakeShape derived class + * + * Uses BRepBuilderAPI_MakeShape::Modified/Generated() function to extract + * shape history for generating mapped element names + */ +struct PartExport MapperMaker: TopoShape::Mapper +{ + BRepBuilderAPI_MakeShape& maker; + MapperMaker(BRepBuilderAPI_MakeShape& maker) + : maker(maker) + {} + virtual const std::vector& modified(const TopoDS_Shape& s) const override; + virtual const std::vector& generated(const TopoDS_Shape& s) const override; +}; + } // namespace Part diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index f6abf55423..c5a122e95e 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -551,7 +551,146 @@ TopoShape::makeElementCompound(const std::vector& shapes, const char* return *this; } +<<<<<<< HEAD +======= +struct MapperSewing: Part::TopoShape::Mapper +{ + BRepBuilderAPI_Sewing& maker; + MapperSewing(BRepBuilderAPI_Sewing& maker) + : maker(maker) + {} + virtual const std::vector& modified(const TopoDS_Shape& s) const override + { + _res.clear(); + try { + const auto& shape = maker.Modified(s); + if (!shape.IsNull() && !shape.IsSame(s)) { + _res.push_back(shape); + } + else { + const auto& sshape = maker.ModifiedSubShape(s); + if (!sshape.IsNull() && !sshape.IsSame(s)) { + _res.push_back(sshape); + } + } + } + catch (const Standard_Failure& e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + } + return _res; + } +}; +struct MapperThruSections: MapperMaker +{ + TopoShape firstProfile; + TopoShape lastProfile; + + MapperThruSections(BRepOffsetAPI_ThruSections& tmaker, const std::vector& profiles) + : MapperMaker(tmaker) + { + if (!tmaker.FirstShape().IsNull()) { + firstProfile = profiles.front(); + } + if (!tmaker.LastShape().IsNull()) { + lastProfile = profiles.back(); + } + } + virtual const std::vector& generated(const TopoDS_Shape& s) const override + { + MapperMaker::generated(s); + if (_res.size()) { + return _res; + } + try { + auto& tmaker = static_cast(maker); + auto shape = tmaker.GeneratedFace(s); + if (!shape.IsNull()) { + _res.push_back(shape); + } + if (firstProfile.getShape().IsSame(s) || firstProfile.findShape(s)) { + _res.push_back(tmaker.FirstShape()); + } + else if (lastProfile.getShape().IsSame(s) || lastProfile.findShape(s)) { + _res.push_back(tmaker.LastShape()); + } + } + catch (const Standard_Failure& e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + } + return _res; + } +}; + + +TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const TopoShape& source, + const char* op) +{ + std::vector sources(1, source); + return makeElementShape(mkShape, sources, op); +} + +TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const std::vector& shapes, + const char* op) +{ + return makeShapeWithElementMap(mkShape.Shape(), MapperMaker(mkShape), shapes, op); +} + +TopoShape& +TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, const TopoShape& source, const char* op) +{ + if (!op) { + op = Part::OpCodes::ThruSections; + } + return makeElementShape(mk, std::vector(1, source), op); +} + +TopoShape& TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, + const std::vector& sources, + const char* op) +{ + if (!op) { + op = Part::OpCodes::ThruSections; + } + return makeShapeWithElementMap(mk.Shape(), MapperThruSections(mk, sources), sources, op); +} + +TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mk, + const std::vector& shapes, + const char* op) +{ + if (!op) { + op = Part::OpCodes::Sewing; + } + return makeShapeWithElementMap(mk.SewedShape(), MapperSewing(mk), shapes, op); +} + +TopoShape& +TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mkShape, const TopoShape& source, const char* op) +{ + if (!op) { + op = Part::OpCodes::Sewing; + } + return makeElementShape(mkShape, std::vector(1, source), op); +} + +TopoShape& TopoShape::makeElementShape(BRepPrimAPI_MakeHalfSpace& mkShape, + const TopoShape& source, + const char* op) +{ + if (!op) { + op = Part::OpCodes::HalfSpace; + } + return makeShapeWithElementMap(mkShape.Solid(), MapperMaker(mkShape), {source}, op); +} + +>>>>>>> ad521d6a23 (Missing method) TopoShape& TopoShape::makeElementFace(const TopoShape& shape, const char* op, const char* maker, @@ -796,5 +935,134 @@ TopoShape TopoShape::splitWires(std::vector* inner, SplitWireReorient return TopoShape(); } +TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const TopoShape& source, + const char* op) +{ + std::vector sources(1, source); + return makeElementShape(mkShape, sources, op); +} + +TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const std::vector& shapes, + const char* op) +{ + return makeShapeWithElementMap(mkShape.Shape(), MapperMaker(mkShape), shapes, op); +} + +TopoShape &TopoShape::makeElementShape(BRepOffsetAPI_ThruSections &mk, const TopoShape &source, + const char *op) +{ + if(!op) op = Part::OpCodes::ThruSections; + return makeElementShape(mk,std::vector(1,source),op); +} + +TopoShape &TopoShape::makeElementShape(BRepOffsetAPI_ThruSections &mk, const std::vector &sources, + const char *op) +{ + if(!op) op = Part::OpCodes::ThruSections; + return makeShapeWithElementMap(mk.Shape(),MapperThruSections(mk,sources),sources,op); +} + +TopoShape &TopoShape::makeElementShape(BRepBuilderAPI_Sewing &mk, const std::vector &shapes, + const char *op) +{ + if(!op) op = Part::OpCodes::Sewing; + return makeShapeWithElementMap(mk.SewedShape(),MapperSewing(mk),shapes,op); +} + +TopoShape &TopoShape::makeElementShape(BRepBuilderAPI_Sewing &mkShape, + const TopoShape &source, const char *op) +{ + if(!op) op = Part::OpCodes::Sewing; + return makeElementShape(mkShape,std::vector(1,source),op); +} + +struct MapperSewing: Part::TopoShape::Mapper { + BRepBuilderAPI_Sewing &maker; + MapperSewing(BRepBuilderAPI_Sewing &maker) + :maker(maker) + {} + virtual const std::vector &modified(const TopoDS_Shape &s) const override { + _res.clear(); + try { + const auto &shape = maker.Modified(s); + if(!shape.IsNull() && !shape.IsSame(s)) + _res.push_back(shape); + else { + const auto &sshape = maker.ModifiedSubShape(s); + if(!sshape.IsNull() && !sshape.IsSame(s)) + _res.push_back(sshape); + } + } catch (const Standard_Failure & e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + return _res; + } +}; + +struct MapperThruSections: MapperMaker { + TopoShape firstProfile; + TopoShape lastProfile; + + MapperThruSections(BRepOffsetAPI_ThruSections &tmaker, + const std::vector &profiles) + :MapperMaker(tmaker) + { + if(!tmaker.FirstShape().IsNull()) + firstProfile = profiles.front(); + if(!tmaker.LastShape().IsNull()) + lastProfile = profiles.back(); + } + virtual const std::vector &generated(const TopoDS_Shape &s) const override { + MapperMaker::generated(s); + if(_res.size()) return _res; + try { + auto &tmaker = static_cast(maker); + auto shape = tmaker.GeneratedFace(s); + if(!shape.IsNull()) + _res.push_back(shape); + if(firstProfile.getShape().IsSame(s) || firstProfile.findShape(s)) + _res.push_back(tmaker.FirstShape()); + else if(lastProfile.getShape().IsSame(s) || lastProfile.findShape(s)) + _res.push_back(tmaker.LastShape()); + } catch (const Standard_Failure & e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + return _res; + } +}; + +const std::vector & +MapperMaker::modified(const TopoDS_Shape &s) const +{ + _res.clear(); + try { + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(maker.Modified(s)); it.More(); it.Next()) + _res.push_back(it.Value()); + } catch (const Standard_Failure & e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + return _res; +} + +const std::vector & +MapperMaker::generated(const TopoDS_Shape &s) const +{ + _res.clear(); + try { + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(maker.Generated(s)); it.More(); it.Next()) + _res.push_back(it.Value()); + } catch (const Standard_Failure & e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + return _res; +} } // namespace Part