From 60d69d706d130a421743ab44673995f4f61a00a9 Mon Sep 17 00:00:00 2001 From: hlorus <64740362+hlorus@users.noreply.github.com> Date: Wed, 17 Jul 2024 17:53:12 +0200 Subject: [PATCH 1/3] Measure: Reduce boilerplate code by adding some helper methods --- src/App/MeasureManager.cpp | 21 +++++++++++ src/App/MeasureManager.h | 2 ++ src/Mod/Measure/App/MeasureAngle.cpp | 39 +++++---------------- src/Mod/Measure/App/MeasureArea.cpp | 45 ++++++------------------ src/Mod/Measure/App/MeasureBase.h | 17 +++++++++ src/Mod/Measure/App/MeasureDistance.cpp | 29 +++------------- src/Mod/Measure/App/MeasureLength.cpp | 46 ++++++------------------- src/Mod/Measure/App/MeasurePosition.cpp | 30 ++++------------ src/Mod/Measure/App/MeasureRadius.cpp | 45 +++++------------------- src/Mod/Measure/Gui/TaskMeasure.cpp | 9 +++-- 10 files changed, 93 insertions(+), 190 deletions(-) diff --git a/src/App/MeasureManager.cpp b/src/App/MeasureManager.cpp index c457e6a525..a063a177cb 100644 --- a/src/App/MeasureManager.cpp +++ b/src/App/MeasureManager.cpp @@ -62,6 +62,27 @@ namespace App { return empty; } + MeasureHandler MeasureManager::getMeasureHandler(const App::MeasureSelectionItem& selectionItem) { + auto objT = selectionItem.object; + + App::DocumentObject* sub = objT.getSubObject(); + + const char* className = sub->getTypeId().getName(); + std::string mod = Base::Type::getModuleName(className); + + return getMeasureHandler(mod.c_str()); + } + + MeasureElementType MeasureManager::getMeasureElementType(const App::MeasureSelectionItem& selectionItem) { + auto handler = getMeasureHandler(selectionItem); + if (handler.module.empty()) { + return App::MeasureElementType::INVALID; + } + + auto objT = selectionItem.object; + return handler.typeCb(objT.getObject(), objT.getSubName().c_str()); + } + void MeasureManager::addMeasureType(MeasureType* measureType) { _mMeasureTypes.push_back(measureType); } diff --git a/src/App/MeasureManager.h b/src/App/MeasureManager.h index 2c93b59ebe..303bdd1390 100644 --- a/src/App/MeasureManager.h +++ b/src/App/MeasureManager.h @@ -93,6 +93,8 @@ public: static void addMeasureHandler(const char* module, MeasureTypeMethod typeCb); static bool hasMeasureHandler(const char* module); static MeasureHandler getMeasureHandler(const char* module); + static MeasureHandler getMeasureHandler(const App::MeasureSelectionItem& selectionItem); + static MeasureElementType getMeasureElementType(const App::MeasureSelectionItem& selectionItem); static void addMeasureType(MeasureType* measureType); static void addMeasureType(std::string id, std::string label, std::string measureObj, MeasureValidateMethod validatorCb, MeasurePrioritizeMethod prioritizeCb); static void addMeasureType(const char* id, const char* label, const char* measureObj, MeasureValidateMethod validatorCb, MeasurePrioritizeMethod prioritizeCb); diff --git a/src/Mod/Measure/App/MeasureAngle.cpp b/src/Mod/Measure/App/MeasureAngle.cpp index 87b8fbd419..82eff1e426 100644 --- a/src/Mod/Measure/App/MeasureAngle.cpp +++ b/src/Mod/Measure/App/MeasureAngle.cpp @@ -61,19 +61,7 @@ bool MeasureAngle::isValidSelection(const App::MeasureSelection& selection) } for (auto element : selection) { - auto objT = element.object; - - App::DocumentObject* ob = objT.getObject(); - const std::string& subName = objT.getSubName(); - const char* className = objT.getSubObject()->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return false; - } - - App::MeasureHandler handler = App::MeasureManager::getMeasureHandler(mod.c_str()); - App::MeasureElementType type = handler.typeCb(ob, subName.c_str()); + auto type = App::MeasureManager::getMeasureElementType(element); if (type == App::MeasureElementType::INVALID) { return false; @@ -134,17 +122,12 @@ void MeasureAngle::parseSelection(const App::MeasureSelection& selection) { bool MeasureAngle::getVec(App::DocumentObject& ob, std::string& subName, Base::Vector3d& vecOut) { - const char* className = ob.getSubObject(subName.c_str())->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { + App::SubObjectT subject{&ob, subName.c_str()}; + auto info = getMeasureInfo(subject); + if (!info || !info->valid) { return false; } - auto handler = getGeometryHandler(mod); - App::SubObjectT subject{&ob, subName.c_str()}; - auto info = handler(subject); - auto angleInfo = std::dynamic_pointer_cast(info); vecOut = angleInfo->orientation; return true; @@ -152,16 +135,12 @@ bool MeasureAngle::getVec(App::DocumentObject& ob, std::string& subName, Base::V Base::Vector3d MeasureAngle::getLoc(App::DocumentObject& ob, std::string& subName) { - const char* className = ob.getSubObject(subName.c_str())->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return Base::Vector3d(); - } - - auto handler = getGeometryHandler(mod); App::SubObjectT subject{&ob, subName.c_str()}; - auto info = handler(subject); + auto info = getMeasureInfo(subject); + if (!info || !info->valid) { + return Base::Vector3d(); + } + auto angleInfo = std::dynamic_pointer_cast(info); return angleInfo->position; } diff --git a/src/Mod/Measure/App/MeasureArea.cpp b/src/Mod/Measure/App/MeasureArea.cpp index 553a3e6acf..608c41b34d 100644 --- a/src/Mod/Measure/App/MeasureArea.cpp +++ b/src/Mod/Measure/App/MeasureArea.cpp @@ -56,19 +56,7 @@ bool MeasureArea::isValidSelection(const App::MeasureSelection& selection){ } for (auto element : selection) { - auto objT = element.object; - - App::DocumentObject* ob = objT.getObject(); - const std::string& subName = objT.getSubName(); - const char* className = objT.getSubObject()->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return false; - } - - App::MeasureHandler handler = App::MeasureManager::getMeasureHandler(mod.c_str()); - App::MeasureElementType type = handler.typeCb(ob, subName.c_str()); + auto type = App::MeasureManager::getMeasureElementType(element); if (type == App::MeasureElementType::INVALID) { return false; @@ -114,19 +102,12 @@ void MeasureArea::recalculateArea() // Loop through Elements and call the valid geometry handler for (std::vector::size_type i=0; igetSubObject(subElement.c_str())->getTypeId().getName(); - const std::string& mod = Base::Type::getModuleName(className); - auto handler = getGeometryHandler(mod); - if (!handler) { - throw Base::RuntimeError("No geometry handler available for submitted element type"); + auto info = getMeasureInfo(subject); + if (!info || !info->valid) { + continue; } - - App::SubObjectT subject{object, subElement.c_str()}; - auto info = handler(subject); auto areaInfo = std::dynamic_pointer_cast(info); result += areaInfo->area; } @@ -143,7 +124,7 @@ void MeasureArea::onChanged(const App::Property* prop) if (prop == &Elements) { recalculateArea(); } - + MeasureBase::onChanged(prop); } @@ -156,18 +137,12 @@ Base::Placement MeasureArea::getPlacement() { return Base::Placement(); } - App::DocumentObject* object = objects.front(); - std::string subElement = subElements.front(); - const char* className = object->getSubObject(subElement.c_str())->getTypeId().getName(); - const std::string& mod = Base::Type::getModuleName(className); + App::SubObjectT subject{objects.front(), subElements.front().c_str()}; - auto handler = getGeometryHandler(mod); - if (!handler) { - throw Base::RuntimeError("No geometry handler available for submitted element type"); + auto info = getMeasureInfo(subject); + if (!info) { + return {}; } - - App::SubObjectT subject{object, subElement.c_str()}; - auto info = handler(subject); auto areaInfo = std::dynamic_pointer_cast(info); return areaInfo->placement; } diff --git a/src/Mod/Measure/App/MeasureBase.h b/src/Mod/Measure/App/MeasureBase.h index 42dd209d8c..74dba3cbc7 100644 --- a/src/Mod/Measure/App/MeasureBase.h +++ b/src/Mod/Measure/App/MeasureBase.h @@ -106,6 +106,23 @@ public: return _mGeometryHandlers[module]; } + static Part::MeasureInfoPtr getMeasureInfo(App::SubObjectT& subObjT) { + + App::DocumentObject* sub = subObjT.getSubObject(); + + // Get the Geometry handler based on the module + const char* className = sub->getTypeId().getName(); + std::string mod = Base::Type::getModuleName(className); + + auto handler = getGeometryHandler(mod); + if (!handler) { + Base::Console().Log("MeasureBaseExtendable::getMeasureInfo: No geometry handler available for submitted element type"); + return nullptr; + } + + return handler(subObjT); + } + static void addGeometryHandlers(const std::vector& modules, GeometryHandler callback){ // TODO: this will replace a callback with a later one. Should we check that there isn't already a // handler defined for this module? diff --git a/src/Mod/Measure/App/MeasureDistance.cpp b/src/Mod/Measure/App/MeasureDistance.cpp index da1effe52c..b55320f273 100644 --- a/src/Mod/Measure/App/MeasureDistance.cpp +++ b/src/Mod/Measure/App/MeasureDistance.cpp @@ -76,20 +76,7 @@ bool MeasureDistance::isValidSelection(const App::MeasureSelection& selection){ } for (auto element : selection) { - - auto objT = element.object; - - App::DocumentObject* ob = objT.getObject(); - const std::string& subName = objT.getSubName(); - const char* className = objT.getSubObject()->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return false; - } - - App::MeasureHandler handler = App::MeasureManager::getMeasureHandler(mod.c_str()); - App::MeasureElementType type = handler.typeCb(ob, subName.c_str()); + auto type = App::MeasureManager::getMeasureElementType(element); if (type == App::MeasureElementType::INVALID) { return false; @@ -152,17 +139,11 @@ bool MeasureDistance::getShape(App::PropertyLinkSub* prop, TopoDS_Shape& rShape) } std::string subName = subs.at(0); - const char* className = ob->getSubObject(subName.c_str())->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return false; - } - - auto handler = getGeometryHandler(mod); App::SubObjectT subject{ob, subName.c_str()}; - auto info = handler(subject); - if (!info->valid) { + + auto info = getMeasureInfo(subject); + + if (!info || !info->valid) { return false; } auto distanceInfo = std::dynamic_pointer_cast(info); diff --git a/src/Mod/Measure/App/MeasureLength.cpp b/src/Mod/Measure/App/MeasureLength.cpp index ba95db39a1..78de1389cc 100644 --- a/src/Mod/Measure/App/MeasureLength.cpp +++ b/src/Mod/Measure/App/MeasureLength.cpp @@ -58,19 +58,7 @@ bool MeasureLength::isValidSelection(const App::MeasureSelection& selection){ } for (auto element : selection) { - auto objT = element.object; - - App::DocumentObject* ob = objT.getObject(); - const std::string& subName = objT.getSubName(); - const char* className = objT.getSubObject()->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return false; - } - - App::MeasureHandler handler = App::MeasureManager::getMeasureHandler(mod.c_str()); - App::MeasureElementType type = handler.typeCb(ob, subName.c_str()); + auto type = App::MeasureManager::getMeasureElementType(element); if (type == App::MeasureElementType::INVALID) { return false; @@ -91,7 +79,7 @@ void MeasureLength::parseSelection(const App::MeasureSelection& selection) { std::vector subElements; for (auto element : selection) { - auto objT = element.object; + auto objT = element.object; objects.push_back(objT.getObject()); subElements.push_back(objT.getSubName()); @@ -116,19 +104,13 @@ void MeasureLength::recalculateLength() // Loop through Elements and call the valid geometry handler for (std::vector::size_type i=0; igetSubObject(subElement.c_str())->getTypeId().getName(); - const std::string& mod = Base::Type::getModuleName(className); - auto handler = getGeometryHandler(mod); - if (!handler) { - throw Base::RuntimeError("No geometry handler available for submitted element type"); + App::SubObjectT subject{objects.at(i), subElements.at(i).c_str()}; + auto info = getMeasureInfo(subject); + if (!info || !info->valid) { + continue; } - App::SubObjectT subject{object, subElement.c_str()}; - auto info = handler(subject); auto lengthInfo = std::dynamic_pointer_cast(info); result += lengthInfo->length; } @@ -158,18 +140,12 @@ Base::Placement MeasureLength::getPlacement() { return Base::Placement(); } - App::DocumentObject* object = objects.front(); - std::string subElement = subElements.front(); - const char* className = object->getSubObject(subElement.c_str())->getTypeId().getName(); - const std::string& mod = Base::Type::getModuleName(className); - - auto handler = getGeometryHandler(mod); - if (!handler) { - throw Base::RuntimeError("No geometry handler available for submitted element type"); + App::SubObjectT subject{objects.front(), subElements.front().c_str()}; + auto info = getMeasureInfo(subject); + + if (!info || !info->valid) { + return {}; } - - App::SubObjectT subject{object, subElement.c_str()}; - auto info = handler(subject); auto lengthInfo = std::dynamic_pointer_cast(info); return lengthInfo->placement; } diff --git a/src/Mod/Measure/App/MeasurePosition.cpp b/src/Mod/Measure/App/MeasurePosition.cpp index c4c00d413d..453538d6c4 100644 --- a/src/Mod/Measure/App/MeasurePosition.cpp +++ b/src/Mod/Measure/App/MeasurePosition.cpp @@ -58,19 +58,7 @@ bool MeasurePosition::isValidSelection(const App::MeasureSelection& selection){ } for (auto element : selection) { - auto objT = element.object; - - App::DocumentObject* ob = objT.getObject(); - const std::string& subName = objT.getSubName(); - const char* className = objT.getSubObject()->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return false; - } - - App::MeasureHandler handler = App::MeasureManager::getMeasureHandler(mod.c_str()); - App::MeasureElementType type = handler.typeCb(ob, subName.c_str()); + auto type = App::MeasureManager::getMeasureElementType(element); if (type == App::MeasureElementType::INVALID) { return false; @@ -107,19 +95,13 @@ void MeasurePosition::recalculatePosition() const App::DocumentObject* object = Element.getValue(); const std::vector& subElements = Element.getSubValues(); - // Get the position of the first point - std::string subElement = subElements.front(); - - // Get the Geometry handler based on the module - const char* className = object->getSubObject(subElement.c_str())->getTypeId().getName(); - const std::string& mod = Base::Type::getModuleName(className); - auto handler = getGeometryHandler(mod); - if (!handler) { - throw Base::RuntimeError("No geometry handler available for submitted element type"); + App::SubObjectT subject{object, subElements.front().c_str()}; + auto info = getMeasureInfo(subject); + + if (!info || !info->valid) { + return; } - App::SubObjectT subject{object, subElement.c_str()}; - auto info = handler(subject); auto positionInfo = std::dynamic_pointer_cast(info); Position.setValue(positionInfo->position); } diff --git a/src/Mod/Measure/App/MeasureRadius.cpp b/src/Mod/Measure/App/MeasureRadius.cpp index c573aff30e..96bf88d3af 100644 --- a/src/Mod/Measure/App/MeasureRadius.cpp +++ b/src/Mod/Measure/App/MeasureRadius.cpp @@ -68,19 +68,7 @@ bool MeasureRadius::isValidSelection(const App::MeasureSelection& selection){ } auto element = selection.front(); - auto objT = element.object; - - App::DocumentObject* ob = objT.getObject(); - const std::string& subName = objT.getSubName(); - const char* className = objT.getSubObject()->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return false; - } - - App::MeasureHandler handler = App::MeasureManager::getMeasureHandler(mod.c_str()); - App::MeasureElementType type = handler.typeCb(ob, subName.c_str()); + auto type = App::MeasureManager::getMeasureElementType(element); if (type == App::MeasureElementType::INVALID) { return false; @@ -102,19 +90,7 @@ bool MeasureRadius::isPrioritizedSelection(const App::MeasureSelection& selectio } auto element = selection.front(); - auto objT = element.object; - - App::DocumentObject* ob = objT.getObject(); - const std::string& subName = objT.getSubName(); - const char* className = objT.getSubObject()->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); - - if (!hasGeometryHandler(mod)) { - return false; - } - - App::MeasureHandler handler = App::MeasureManager::getMeasureHandler(mod.c_str()); - App::MeasureElementType type = handler.typeCb(ob, subName.c_str()); + auto type = App::MeasureManager::getMeasureElementType(element); if (type == App::MeasureElementType::CIRCLE || type == App::MeasureElementType::ARC) { @@ -179,7 +155,7 @@ Base::Vector3d MeasureRadius::getPointOnCurve() const //! get the handler's result for the first element Part::MeasureRadiusInfoPtr MeasureRadius::getMeasureInfoFirst() const { - const App::DocumentObject* object = Element.getValue(); + const App::DocumentObject* object = Element.getValue(); const std::vector& subElements = Element.getSubValues(); if (!object || subElements.empty()) { @@ -187,18 +163,13 @@ Part::MeasureRadiusInfoPtr MeasureRadius::getMeasureInfoFirst() const return std::make_shared(); } - std::string subElement = subElements.front(); - const char* className = object->getSubObject(subElement.c_str())->getTypeId().getName(); - const std::string& mod = Base::Type::getModuleName(className); - - auto handler = getGeometryHandler(mod); - if (!handler) { - throw Base::RuntimeError("No geometry handler available for submitted element type"); + App::SubObjectT subject{object, subElements.front().c_str()}; + auto info = getMeasureInfo(subject); + if (!info || !info->valid) { +// NOLINTNEXTLINE(modernize-return-braced-init-list) + return std::make_shared(); } - std::string obName = object->getNameInDocument(); - App::SubObjectT subject{object, subElement.c_str()}; - auto info = handler(subject); auto radiusInfo = std::dynamic_pointer_cast(info); return radiusInfo; } diff --git a/src/Mod/Measure/Gui/TaskMeasure.cpp b/src/Mod/Measure/Gui/TaskMeasure.cpp index 3306340ab7..04aeb23694 100644 --- a/src/Mod/Measure/Gui/TaskMeasure.cpp +++ b/src/Mod/Measure/Gui/TaskMeasure.cpp @@ -185,13 +185,12 @@ void TaskMeasure::update() { if (measureTypes.size() > 0) { measureType = measureTypes.front(); } - if (!measureType) { // Note: If there's no valid measure type we might just restart the selection, // however this requires enough coverage of measuretypes that we can access all of them - + // std::tuple sel = selection.back(); // clearSelection(); // addElement(measureModule.c_str(), get<0>(sel).c_str(), get<1>(sel).c_str()); @@ -215,7 +214,7 @@ void TaskMeasure::update() { if (measureType->isPython) { Base::PyGILStateLocker lock; auto pyMeasureClass = measureType->pythonClass; - + // Create a MeasurePython instance auto featurePython = doc->addObject("Measure::MeasurePython", measureType->label.c_str()); setMeasureObject((Measure::MeasureBase*)featurePython); @@ -297,7 +296,7 @@ void TaskMeasure::reset() { // Reset tool state this->clearSelection(); - // Should the explicit mode also be reset? + // Should the explicit mode also be reset? // setModeSilent(nullptr); // explicitMode = false; @@ -368,7 +367,7 @@ void TaskMeasure::onModeChanged(int index) { void TaskMeasure::setModeSilent(App::MeasureType* mode) { modeSwitch->blockSignals(true); - + if (mode == nullptr) { modeSwitch->setCurrentIndex(0); } From d8bbb3c804e94a40f9cf3aeb911e1f218510f287 Mon Sep 17 00:00:00 2001 From: hlorus <64740362+hlorus@users.noreply.github.com> Date: Sun, 23 Jun 2024 12:06:25 +0200 Subject: [PATCH 2/3] Measure: Resolve App::Link elements --- src/App/MeasureManager.cpp | 6 ++++++ src/Mod/Measure/App/MeasureBase.h | 6 ++++++ src/Mod/Measure/Gui/TaskMeasure.cpp | 9 ++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/App/MeasureManager.cpp b/src/App/MeasureManager.cpp index a063a177cb..825cbc63a9 100644 --- a/src/App/MeasureManager.cpp +++ b/src/App/MeasureManager.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "MeasureManager.h" @@ -65,7 +66,12 @@ namespace App { MeasureHandler MeasureManager::getMeasureHandler(const App::MeasureSelectionItem& selectionItem) { auto objT = selectionItem.object; + // Resolve App::Link App::DocumentObject* sub = objT.getSubObject(); + if (sub->isDerivedFrom()) { + auto link = static_cast(sub); + sub = link->getLinkedObject(true); + } const char* className = sub->getTypeId().getName(); std::string mod = Base::Type::getModuleName(className); diff --git a/src/Mod/Measure/App/MeasureBase.h b/src/Mod/Measure/App/MeasureBase.h index 74dba3cbc7..75fdc61ffc 100644 --- a/src/Mod/Measure/App/MeasureBase.h +++ b/src/Mod/Measure/App/MeasureBase.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -108,7 +109,12 @@ public: static Part::MeasureInfoPtr getMeasureInfo(App::SubObjectT& subObjT) { + // Resolve App::Link App::DocumentObject* sub = subObjT.getSubObject(); + if (sub->isDerivedFrom()) { + auto link = static_cast(sub); + sub = link->getLinkedObject(true); + } // Get the Geometry handler based on the module const char* className = sub->getTypeId().getName(); diff --git a/src/Mod/Measure/Gui/TaskMeasure.cpp b/src/Mod/Measure/Gui/TaskMeasure.cpp index 04aeb23694..e5968c33d5 100644 --- a/src/Mod/Measure/Gui/TaskMeasure.cpp +++ b/src/Mod/Measure/Gui/TaskMeasure.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -156,8 +157,14 @@ void TaskMeasure::update() { for(auto sel : Gui::Selection().getSelection()) { App::DocumentObject* ob = sel.pObject; App::DocumentObject* sub = ob->getSubObject(sel.SubName); - std::string mod = Base::Type::getModuleName(sub->getTypeId().getName()); + // Resolve App::Link + if (sub->isDerivedFrom()) { + auto link = static_cast(sub); + sub = link->getLinkedObject(true); + } + + std::string mod = Base::Type::getModuleName(sub->getTypeId().getName()); if (!App::MeasureManager::hasMeasureHandler(mod.c_str())) { Base::Console().Message("No measure handler available for geometry of module: %s\n", mod); clearSelection(); From 4adb1ecc8a180838ea4f55801e3ea80cb2b5fe7b Mon Sep 17 00:00:00 2001 From: hlorus <64740362+hlorus@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:05:43 +0200 Subject: [PATCH 3/3] Measure: Fix retrival of shape in measure geomtery handlers --- src/Mod/Part/App/MeasureClient.cpp | 31 +++++++----------------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/Mod/Part/App/MeasureClient.cpp b/src/Mod/Part/App/MeasureClient.cpp index 283b5dcef7..ec8275cccd 100644 --- a/src/Mod/Part/App/MeasureClient.cpp +++ b/src/Mod/Part/App/MeasureClient.cpp @@ -89,21 +89,18 @@ static float getRadius(TopoDS_Shape& edge){ return 0.0; } -TopoDS_Shape getLocatedShape(const App::SubObjectT& subject) +TopoDS_Shape getLocatedShape(const App::SubObjectT& subject, Base::Matrix4D* mat = nullptr) { App::DocumentObject* obj = subject.getSubObjectList().back(); if (!obj) { return {}; } - Part::TopoShape shape = Part::Feature::getTopoShape(obj, subject.getElementName()); + Part::TopoShape shape = Part::Feature::getTopoShape(obj, subject.getElementName(), false, mat, nullptr, true); if (shape.isNull()) { + Base::Console().Log("Part::MeasureClient::getLocatedShape: Did not retrieve shape for %s, %s\n", obj->getNameInDocument(), subject.getElementName()); return {}; } - auto geoFeat = dynamic_cast(obj); - if (geoFeat) { - shape.setPlacement(geoFeat->globalPlacement()); - } // Don't get the subShape from datum elements if (obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) { @@ -181,31 +178,22 @@ bool getShapeFromStrings(TopoDS_Shape &shapeOut, const App::SubObjectT& subject, } - Part::VectorAdapter buildAdapter(const App::SubObjectT& subject) { - if (!subject.getObject()) { - return Part::VectorAdapter(); - } Base::Matrix4D mat; - TopoDS_Shape shape = Part::Feature::getShape(subject.getObject(), subject.getElementName(), true); + TopoDS_Shape shape = getLocatedShape(subject, &mat); + if (shape.IsNull()) { // failure here on loading document with existing measurement. Base::Console().Message("Part::buildAdapter did not retrieve shape for %s, %s\n", subject.getObjectName(), subject.getElementName()); return Part::VectorAdapter(); } - TopAbs_ShapeEnum shapeType = shape.ShapeType(); - if (shapeType == TopAbs_EDGE) { - TopoDS_Shape edgeShape; - if (!getShapeFromStrings(edgeShape, subject, &mat)) { - return {}; - } - TopoDS_Edge edge = TopoDS::Edge(edgeShape); + TopoDS_Edge edge = TopoDS::Edge(shape); // make edge orientation so that end of edge closest to pick is head of vector. TopoDS_Vertex firstVertex = TopExp::FirstVertex(edge, Standard_True); TopoDS_Vertex lastVertex = TopExp::LastVertex(edge, Standard_True); @@ -232,12 +220,7 @@ Part::VectorAdapter buildAdapter(const App::SubObjectT& subject) } if (shapeType == TopAbs_FACE) { - TopoDS_Shape faceShape; - if (!getShapeFromStrings(faceShape, subject, &mat)) { - return {}; - } - - TopoDS_Face face = TopoDS::Face(faceShape); + TopoDS_Face face = TopoDS::Face(shape); Base::Vector3d vTemp(0.0, 0.0, 0.0); //v(current.x, current.y, current.z); vTemp = mat*vTemp; gp_Vec pickPoint(vTemp.x, vTemp.y, vTemp.z);