diff --git a/src/Mod/Part/App/Attacher.cpp b/src/Mod/Part/App/Attacher.cpp index a8a25983d..6acafa6f8 100644 --- a/src/Mod/Part/App/Attacher.cpp +++ b/src/Mod/Part/App/Attacher.cpp @@ -48,6 +48,11 @@ # include # include # include +# include +# include +# include +# include +# include #endif #include #include @@ -580,6 +585,81 @@ std::string AttachEngine::getModeName(eMapMode mmode) return std::string(AttachEngine::eMapModeStrings[mmode]); } +GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector &shapes) +{ + //explode compounds + TopTools_HSequenceOfShape totalSeq; + for (const TopoDS_Shape* pSh: shapes){ + ShapeExtend_Explorer xp; + totalSeq.Append( xp.SeqFromCompound(*pSh, /*recursive=*/true)); + } + if (totalSeq.Length() == 0) + throw Base::Exception("AttachEngine::getInertialPropsOfShape: no geometry provided"); + const TopoDS_Shape &sh0 = totalSeq.Value(1); + switch (sh0.ShapeType()){ + case TopAbs_VERTEX:{ + GProp_PGProps gpr; + for (int i = 0 ; i < totalSeq.Length() ; i++){ + const TopoDS_Shape &sh = totalSeq.Value(i+1); + if (sh.ShapeType() != TopAbs_VERTEX) + throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only vertices)"); + gpr.AddPoint(BRep_Tool::Pnt(TopoDS::Vertex(sh))); + } + return gpr; + } break; + case TopAbs_EDGE: + case TopAbs_WIRE:{ + GProp_GProps gpr_acc; + GProp_GProps gpr; + for (int i = 0 ; i < totalSeq.Length() ; i++){ + const TopoDS_Shape &sh = totalSeq.Value(i+1); + if (sh.ShapeType() != TopAbs_EDGE && sh.ShapeType() != TopAbs_WIRE) + throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only edges/wires)"); + if (sh.Infinite()) + throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided"); + BRepGProp::LinearProperties(sh,gpr); + gpr_acc.Add(gpr); + } + return gpr_acc; + } break; + case TopAbs_FACE: + case TopAbs_SHELL:{ + GProp_GProps gpr_acc; + GProp_GProps gpr; + for (int i = 0 ; i < totalSeq.Length() ; i++){ + const TopoDS_Shape &sh = totalSeq.Value(i+1); + if (sh.ShapeType() != TopAbs_FACE && sh.ShapeType() != TopAbs_SHELL) + throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only faces/shells)"); + if (sh.Infinite()) + throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided"); + BRepGProp::SurfaceProperties(sh,gpr); + gpr_acc.Add(gpr); + } + return gpr_acc; + } break; + case TopAbs_SOLID: + case TopAbs_COMPSOLID:{ + GProp_GProps gpr_acc; + GProp_GProps gpr; + for (int i = 0 ; i < totalSeq.Length() ; i++){ + const TopoDS_Shape &sh = totalSeq.Value(i+1); + if (sh.ShapeType() != TopAbs_SOLID && sh.ShapeType() != TopAbs_COMPSOLID) + throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only solids/compsolids)"); + if (sh.Infinite()) + throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided"); + BRepGProp::SurfaceProperties(sh,gpr); + gpr_acc.Add(gpr); + } + return gpr_acc; + } break; + default: + throw Base::Exception("AttachEngine::getInertialPropsOfShape: unexpected shape type"); + } + + assert(false);//exec shouldn't ever get here + return GProp_GProps(); +} + /*! * \brief AttachEngine3D::readLinks * \param parts @@ -1577,6 +1657,11 @@ AttachEnginePoint::AttachEnginePoint() modeRefTypes[mm0ProximityPoint1].push_back(s); modeRefTypes[mm0ProximityPoint2].push_back(s); + modeRefTypes[mm0CenterOfMass].push_back(cat(rtAnything)); + modeRefTypes[mm0CenterOfMass].push_back(cat(rtAnything,rtAnything)); + modeRefTypes[mm0CenterOfMass].push_back(cat(rtAnything,rtAnything,rtAnything)); + modeRefTypes[mm0CenterOfMass].push_back(cat(rtAnything,rtAnything,rtAnything,rtAnything)); + this->EnableAllSupportedModes(); } @@ -1700,6 +1785,10 @@ Base::Placement AttachEnginePoint::calculateAttachedPlacement(Base::Placement or else BasePoint = p2; }break; + case mm0CenterOfMass:{ + GProp_GProps gpr = AttachEngine::getInertialPropsOfShape(shapes); + BasePoint = gpr.CentreOfMass(); + }break; default: throwWrongMode(mmode); } diff --git a/src/Mod/Part/App/Attacher.h b/src/Mod/Part/App/Attacher.h index 356c0daab..575b01234 100644 --- a/src/Mod/Part/App/Attacher.h +++ b/src/Mod/Part/App/Attacher.h @@ -39,6 +39,7 @@ #include "PartFeature.h" #include +#include namespace Attacher { @@ -304,6 +305,8 @@ public://helper functions that may be useful outside of the class */ static std::string getModeName(eMapMode mmode); + static GProp_GProps getInertialPropsOfShape(const std::vector &shapes); + public: //enums static const char* eMapModeStrings[]; diff --git a/src/Mod/Part/Gui/AttacherTexts.cpp b/src/Mod/Part/Gui/AttacherTexts.cpp index 45aa8defa..51aa737b6 100644 --- a/src/Mod/Part/Gui/AttacherTexts.cpp +++ b/src/Mod/Part/Gui/AttacherTexts.cpp @@ -229,7 +229,7 @@ TextSet getUIStrings(Base::Type attacherType, eMapMode mmode) qApp->translate("Attacher0D", "Center of osculating circle of an edge. Optinal vertex link defines where.","AttachmentPoint mode tooltip")); case mm0CenterOfMass: return TwoStrings(qApp->translate("Attacher0D", "Center of mass","AttachmentPoint mode caption"), - qApp->translate("Attacher0D", "Not implemented","AttachmentPoint mode tooltip")); + qApp->translate("Attacher0D", "Center of mass of all references (equal densities are assumed).","AttachmentPoint mode tooltip")); case mm0Intersection: return TwoStrings(qApp->translate("Attacher0D", "Intersection","AttachmentPoint mode caption"), qApp->translate("Attacher0D", "Not implemented","AttachmentPoint mode tooltip"));