From d08810c6495fea2cf79c604387cadc850039b5b8 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sun, 15 Dec 2024 16:58:52 +0100 Subject: [PATCH] Part: Extract methods from AttachEngine::readLinks --- src/Mod/Part/App/Attacher.cpp | 101 +++++++++++++++++++++------------- src/Mod/Part/App/Attacher.h | 23 ++++++++ 2 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/Mod/Part/App/Attacher.cpp b/src/Mod/Part/App/Attacher.cpp index 84c1c08d2c..5009ce260b 100644 --- a/src/Mod/Part/App/Attacher.cpp +++ b/src/Mod/Part/App/Attacher.cpp @@ -831,52 +831,20 @@ void AttachEngine::readLinks(const std::vector& objs, storage.reserve(objs.size()); shapes.resize(objs.size()); types.resize(objs.size()); + for (std::size_t i = 0; i < objs.size(); i++) { - auto* geof = dynamic_cast(objs[i]); + auto geof = extractGeoFeature(objs[i]); if (!geof) { - // Accept App::Links to GeoFeatures - geof = dynamic_cast(objs[i]->getLinkedObject()); - if (!geof) { - FC_THROWM(AttachEngineException, - "AttachEngine3D: attached to a non App::GeoFeature '" << objs[i]->getNameInDocument() << "'"); - } - } - Part::TopoShape shape; - try { - // getTopoShape support fully qualified subnames and should return shape with correct - // global placement. - shape = Part::Feature::getTopoShape(objs[i], subs[i].c_str(), true); - for (;;) { - if (shape.isNull()) { - FC_THROWM(AttachEngineException, - "AttachEngine3D: subshape not found " - << objs[i]->getNameInDocument() << '.' << subs[i]); - } - if (shape.shapeType() != TopAbs_COMPOUND - || shape.countSubShapes(TopAbs_SHAPE) != 1) { - break; - } - // auto extract the single sub-shape from a compound - shape = shape.getSubTopoShape(TopAbs_SHAPE, 1); - } - } - catch (Standard_Failure& e) { FC_THROWM(AttachEngineException, - "AttachEngine3D: subshape not found " << objs[i]->getNameInDocument() - << '.' << subs[i] << std::endl - << e.GetMessageString()); - } - catch (Base::CADKernelError& e) { - FC_THROWM(AttachEngineException, - "AttachEngine3D: subshape not found " << objs[i]->getNameInDocument() - << '.' << subs[i] << std::endl - << e.what()); + "AttachEngine3D: attached to a non App::GeoFeature '" + << objs[i]->getNameInDocument() << "'"); } + auto shape = extractSubShape(objs[i], subs[i]); if (shape.isNull()) { FC_THROWM(AttachEngineException, - "AttachEngine3D: null subshape " << objs[i]->getNameInDocument() << '.' - << subs[i]); + "AttachEngine3D: null subshape " << objs[i]->getNameInDocument() << '.' + << subs[i]); } storage.emplace_back(shape); @@ -885,12 +853,67 @@ void AttachEngine::readLinks(const std::vector& objs, // FIXME: unpack single-child compounds here? Compounds are not used so far, so it should be // considered later, when the need arises. types[i] = getShapeType(shapes[i]->getShape()); + if (subs[i].length() == 0) { types[i] = eRefType(types[i] | rtFlagHasPlacement); } } } +App::GeoFeature* AttachEngine::extractGeoFeature(App::DocumentObject *obj) +{ + if (auto geof = dynamic_cast(obj)) { + return geof; + } + + auto linkedObject = obj->getLinkedObject(); + if (auto linkedGeof = dynamic_cast(linkedObject)) { + return linkedGeof; + } + + return nullptr; +} + +TopoShape AttachEngine::extractSubShape(App::DocumentObject* obj, const std::string& subname) +{ + TopoShape shape; + + try { + // getTopoShape support fully qualified subnames and should return shape with correct + // global placement. + shape = Feature::getTopoShape(obj, subname.c_str(), true); + + for (;;) { + if (shape.isNull()) { + FC_THROWM(AttachEngineException, + "AttachEngine3D: subshape not found " << obj->getNameInDocument() << '.' + << subname); + } + + if (shape.shapeType() != TopAbs_COMPOUND || shape.countSubShapes(TopAbs_SHAPE) != 1) { + break; + } + + // auto extract the single sub-shape from a compound + shape = shape.getSubTopoShape(TopAbs_SHAPE, 1); + } + } + catch (Standard_Failure& e) { + FC_THROWM(AttachEngineException, + "AttachEngine3D: subshape not found " << obj->getNameInDocument() << '.' + << subname << std::endl + << e.GetMessageString()); + } + catch (Base::CADKernelError& e) { + FC_THROWM(AttachEngineException, + "AttachEngine3D: subshape not found " << obj->getNameInDocument() << '.' + << subname << std::endl + << e.what()); + } + + return shape; +} + void AttachEngine::throwWrongMode(eMapMode mmode) { std::stringstream errmsg; diff --git a/src/Mod/Part/App/Attacher.h b/src/Mod/Part/App/Attacher.h index 9b617d7547..a990069f0b 100644 --- a/src/Mod/Part/App/Attacher.h +++ b/src/Mod/Part/App/Attacher.h @@ -438,6 +438,29 @@ protected: static void throwWrongMode(eMapMode mmode); + /** + * Extracts GeoFeature instance from given DocumentObject. + * + * In case of object itself being GeoFeature it returns itself, in other cases (like links) + * the method should return pointer to associated GeoFeature or nullptr if none is available. + * + * @param obj The document object to extract the GeoFeature. + * + * @return App::GeoFeature pointer associated with this document object + */ + static App::GeoFeature* extractGeoFeature(App::DocumentObject* obj); + + /** + * Tries to extract sub shape from document object with given subname. + * + * @param obj DocumentObject containing the sub shape + * @param subname Name of the sub shape to extract + * + * @return Extracted sub shape. Can be null. + * + * @throws AttachEngineException If given sub shape does not exist or is impossible to obtain. + */ + static Part::TopoShape extractSubShape(App::DocumentObject* obj, const std::string& subname); };