From 07711bb8a8c618ad79db62e741e6454c26906d05 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 17 Nov 2022 15:46:06 +0100 Subject: [PATCH] App: fix endless-loop when recursively determining placement of an object --- src/App/GeoFeatureGroupExtension.cpp | 30 ++++++++++++++++++---------- src/App/GeoFeatureGroupExtension.h | 3 ++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/App/GeoFeatureGroupExtension.cpp b/src/App/GeoFeatureGroupExtension.cpp index db154a8f0a..a3f746071d 100644 --- a/src/App/GeoFeatureGroupExtension.cpp +++ b/src/App/GeoFeatureGroupExtension.cpp @@ -103,25 +103,35 @@ DocumentObject* GeoFeatureGroupExtension::getGroupOfObject(const DocumentObject* return nullptr; } -Base::Placement GeoFeatureGroupExtension::globalGroupPlacement() { - - if(getExtendedObject()->isRecomputing()) +Base::Placement GeoFeatureGroupExtension::globalGroupPlacement() +{ + if (getExtendedObject()->isRecomputing()) { throw Base::RuntimeError("Global placement cannot be calculated on recompute"); + } - return recursiveGroupPlacement(this); + std::unordered_set history; + history.insert(this); + return recursiveGroupPlacement(this, history); } -Base::Placement GeoFeatureGroupExtension::recursiveGroupPlacement(GeoFeatureGroupExtension* group) { +Base::Placement GeoFeatureGroupExtension::recursiveGroupPlacement(GeoFeatureGroupExtension* group, + std::unordered_set& history) +{ + history.insert(this); - auto inList = group->getExtendedObject()->getInList(); - for(auto* link : inList) { + for (auto* link : inList) { auto parent = link->getExtensionByType(true); - if(parent && parent->hasObject(group->getExtendedObject())) - return recursiveGroupPlacement(parent) * group->placement().getValue(); + if (parent && parent->hasObject(group->getExtendedObject())) { + // Cyclic dependencies detected + if (history.count(parent) > 0) { + break; + } + return recursiveGroupPlacement(parent, history) * group->placement().getValue(); + } } - + return group->placement().getValue(); } diff --git a/src/App/GeoFeatureGroupExtension.h b/src/App/GeoFeatureGroupExtension.h index 621145e1b5..351c658250 100644 --- a/src/App/GeoFeatureGroupExtension.h +++ b/src/App/GeoFeatureGroupExtension.h @@ -25,6 +25,7 @@ #ifndef APP_GeoFeatureGroup_H #define APP_GeoFeatureGroup_H +#include #include "DocumentObject.h" #include "GroupExtension.h" #include "PropertyGeo.h" @@ -120,7 +121,7 @@ public: static void getInvalidLinkObjects(const App::DocumentObject* obj, std::vector& vec); private: - Base::Placement recursiveGroupPlacement(GeoFeatureGroupExtension* group); + Base::Placement recursiveGroupPlacement(GeoFeatureGroupExtension* group, std::unordered_set& history); static std::vector getScopedObjectsFromLinks(const App::DocumentObject*, LinkScope scope = LinkScope::Local); static std::vector getScopedObjectsFromLink(App::Property*, LinkScope scope = LinkScope::Local);