diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 0aaa5d9fe7..e3673bbdb5 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -965,6 +965,43 @@ public: { return TopoShape(0, Hasher).makeElementBoolean(maker, *this, op, tol); } + /* Make draft shape + * + * @param source: the source shape + * @param faces: the faces of the source shape to make draft faces + * @param pullDirection: the pulling direction for making the draft + * @param angle: the angle of the draft + * @param neutralPlane: the neutral plane used as a reference to decide pulling direction + * @param retry: whether to keep going by skipping faces that failed to create draft + * @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 &makeElementDraft(const TopoShape &source, const std::vector &faces, + const gp_Dir &pullDirection, double angle, const gp_Pln &neutralPlane, + bool retry=true, const char *op=nullptr); + /* Make draft shape + * + * @param source: the source shape + * @param faces: the faces of the source shape to make draft faces + * @param pullDirection: the pulling direction for making the draft + * @param angle: the angle of the draft + * @param neutralPlane: the neutral plane used as a reference to decide pulling direction + * @param retry: whether to keep going by skipping faces that failed to create draft + * @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 makeElementDraft(const std::vector &faces, + const gp_Dir &pullDirection, double angle, const gp_Pln &neutralPlane, + bool retry=true, const char *op=nullptr) const { + return TopoShape(0,Hasher).makeElementDraft(*this,faces,pullDirection,angle,neutralPlane,retry,op); + } /* Make a shell using this shape * @param silent: whether to throw exception on failure diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index 3194b0b76f..fca36f0c6c 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -1811,6 +1811,45 @@ TopoShape& TopoShape::makeElementShape(BRepPrimAPI_MakeHalfSpace& mkShape, return makeShapeWithElementMap(mkShape.Solid(), MapperMaker(mkShape), {source}, op); } +TopoShape &TopoShape::makeElementDraft(const TopoShape &shape, const std::vector &_faces, + const gp_Dir &pullDirection, double angle, const gp_Pln &neutralPlane, + bool retry, const char *op) +{ + if(!op) op = Part::OpCodes::Draft; + + if(shape.isNull()) + HANDLE_NULL_SHAPE; + + std::vector faces(_faces); + bool done = true; + BRepOffsetAPI_DraftAngle mkDraft; + do { + if(faces.empty()) + FC_THROWM(Base::CADKernelError,"no faces can be used"); + + mkDraft.Init(shape.getShape()); + done = true; + for(auto it=faces.begin();it!=faces.end();++it) { + // TODO: What is the flag for? + mkDraft.Add(TopoDS::Face(it->getShape()), pullDirection, angle, neutralPlane); + if (!mkDraft.AddDone()) { + // Note: the function ProblematicShape returns the face on which the error occurred + // Note: mkDraft.Remove() stumbles on a bug in Draft_Modification::Remove() and is + // therefore unusable. See http://forum.freecadweb.org/viewtopic.php?f=10&t=3209&start=10#p25341 + // The only solution is to discard mkDraft and start over without the current face + // mkDraft.Remove(face); + FC_ERR("Failed to add some face for drafting, skip"); + done = false; + faces.erase(it); + break; + } + } + }while(retry && !done); + + mkDraft.Build(); + return makeElementShape(mkDraft,shape,op); +} + TopoShape& TopoShape::makeElementFace(const TopoShape& shape, const char* op, const char* maker,