From 4ecd831bfddd41dbc09a7b8bdaa6b14ca9256cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Sat, 3 Jun 2017 15:18:40 +0200 Subject: [PATCH] GeoFeatureGroup: Make link collection non-DAG save --- src/App/GeoFeatureGroupExtension.cpp | 89 +++++++++++---------- src/App/GeoFeatureGroupExtension.h | 18 ++--- src/App/GroupExtension.cpp | 23 ------ src/App/OriginGroupExtension.h | 2 - src/App/Part.h | 2 - src/App/PropertyLinks.cpp | 3 +- src/Mod/Sketcher/App/SketchObject.cpp | 4 +- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 6 +- 8 files changed, 60 insertions(+), 87 deletions(-) diff --git a/src/App/GeoFeatureGroupExtension.cpp b/src/App/GeoFeatureGroupExtension.cpp index 87bee84eb2..233dd58aea 100644 --- a/src/App/GeoFeatureGroupExtension.cpp +++ b/src/App/GeoFeatureGroupExtension.cpp @@ -130,7 +130,8 @@ std::vector GeoFeatureGroupExtension::addObjects(std::vector links; + getCSRelevantLinks(object, links); links.push_back(object); for( auto obj : links) { @@ -157,7 +158,8 @@ std::vector GeoFeatureGroupExtension::removeObjects(std::vector for(auto object : objects) { //cross CoordinateSystem links are not allowed, so we need to remove the whole link group - auto links = getCSRelevantLinks(object); + std::vector< DocumentObject* > links; + getCSRelevantLinks(object, links); links.push_back(object); //remove all links out of group @@ -206,14 +208,14 @@ std::vector< DocumentObject* > GeoFeatureGroupExtension::getObjectsFromLinks(Doc } -std::vector< DocumentObject* > GeoFeatureGroupExtension::getCSOutList(App::DocumentObject* obj) { +void GeoFeatureGroupExtension::getCSOutList(App::DocumentObject* obj, std::vector< DocumentObject* >& vec) { if(!obj) - return std::vector< App::DocumentObject* >(); + return; //if the object is a geofeaturegroup than all dependencies belong to that CS, we don't want them if(obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId())) - return std::vector< App::DocumentObject* >(); + return; //we get all linked objects. We can't use outList() as this includes the links from expressions auto result = getObjectsFromLinks(obj); @@ -224,37 +226,43 @@ std::vector< DocumentObject* > GeoFeatureGroupExtension::getCSOutList(App::Docum obj->isDerivedFrom(App::Origin::getClassTypeId())); }), result.end()); - //collect all dependencies of those objects - std::vector< App::DocumentObject* > links; + //collect all dependencies of those objects and store them in the result vector for(App::DocumentObject *obj : result) { - auto vec = getCSOutList(obj); - links.insert(links.end(), vec.begin(), vec.end()); + + //prevent infinite recursion + if(std::find(vec.begin(), vec.end(), obj) != vec.end()) + throw Base::Exception("Graph is not DAG"); + + vec.push_back(obj); + std::vector< DocumentObject* > links; + getCSOutList(obj, links); + vec.insert(vec.end(), links.begin(), links.end()); } - if (!links.empty()) { - result.insert(result.end(), links.begin(), links.end()); - std::sort(result.begin(), result.end()); - result.erase(std::unique(result.begin(), result.end()), result.end()); - } - - return result; + //post process the vector + std::sort(vec.begin(), vec.end()); + vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); } -std::vector< DocumentObject* > GeoFeatureGroupExtension::getCSInList(DocumentObject* obj) { +void GeoFeatureGroupExtension::getCSInList(DocumentObject* obj, std::vector< DocumentObject* >& vec) { if(!obj) - return std::vector< App::DocumentObject* >(); + return; //we get all objects that link to it std::vector< App::DocumentObject* > result; //search the inlist for objects that have non-expression links to us for(App::DocumentObject* parent : obj->getInList()) { - + //not interested in other groups (and here we mean all groups, normal ones and geofeaturegroup) if(parent->hasExtension(App::GroupExtension::getExtensionClassTypeId())) continue; + //prevent infinite recursion + if(std::find(vec.begin(), vec.end(), parent) != vec.end()) + throw Base::Exception("Graph is not DAG"); + //check if the link is real or if it is a expression one (could also be both, so it is not //enough to check the expressions) auto res = getObjectsFromLinks(parent); @@ -262,46 +270,39 @@ std::vector< DocumentObject* > GeoFeatureGroupExtension::getCSInList(DocumentObj result.push_back(parent); } - //clear all douplicates + //clear all duplicates std::sort(result.begin(), result.end()); result.erase(std::unique(result.begin(), result.end()), result.end()); //collect all links to those objects - std::vector< App::DocumentObject* > links; for(App::DocumentObject *obj : result) { - auto vec = getCSInList(obj); - links.insert(links.end(), vec.begin(), vec.end()); + vec.push_back(obj); + getCSInList(obj, vec); } - if (!links.empty()) { - result.insert(result.end(), links.begin(), links.end()); - std::sort(result.begin(), result.end()); - result.erase(std::unique(result.begin(), result.end()), result.end()); - } + std::sort(vec.begin(), vec.end()); + vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); - return result; } -std::vector< DocumentObject* > GeoFeatureGroupExtension::getCSRelevantLinks(DocumentObject* obj) { +void GeoFeatureGroupExtension::getCSRelevantLinks(DocumentObject* obj, std::vector< DocumentObject* >& vec ) { - //we need to get the outlist of all inlist objects and ourself. This is needed to handle things + //get all out links + getCSOutList(obj, vec); + + //we need to get the outlist of all inlist objects. This is needed to handle things //like Booleans: the boolean is our parent, than there is a second object under it which relates //to obj and needs to be handled. - auto in = getCSInList(obj); - in.push_back(obj); //there may be nothing in inlist - std::vector result; - for(auto o : in) { - - auto out = getCSOutList(o); - result.insert(result.end(), out.begin(), out.end()); + std::vector< DocumentObject* > in; + getCSInList(obj, in); + for(auto o : in) { + vec.push_back(o); + getCSOutList(o, vec); } - //there will be many douplicates and also the passed obj in - std::sort(result.begin(), result.end()); - result.erase(std::unique(result.begin(), result.end()), result.end()); - result.erase(std::remove(result.begin(), result.end(), obj), result.end()); - - return result; + //post process + std::sort(vec.begin(), vec.end()); + vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); } // Python feature --------------------------------------------------------- diff --git a/src/App/GeoFeatureGroupExtension.h b/src/App/GeoFeatureGroupExtension.h index 522b32103b..1718c7149a 100644 --- a/src/App/GeoFeatureGroupExtension.h +++ b/src/App/GeoFeatureGroupExtension.h @@ -73,8 +73,6 @@ public: * In case this object is not part of any geoFeatureGroup 0 is returned. * Unlike DocumentObjectGroup::getGroupOfObject serches only for GeoFeatureGroups * @param obj the object to search for - * @param indirect if true return if the group that so-called geoHas the object, @see geoHasObject() - * default is true */ static DocumentObject* getGroupOfObject(const DocumentObject* obj); @@ -99,18 +97,18 @@ public: virtual std::vector< DocumentObject* > addObjects(std::vector< DocumentObject* > obj) override; virtual std::vector< DocumentObject* > removeObjects(std::vector< DocumentObject* > obj) override; - /// returns GeoFeatureGroup relevant objects that are linked from the given one. That meas all linked objects + /// Collects GeoFeatureGroup relevant objects that are linked from the given one. That meas all linked objects /// including their linkes (recursively) except GeoFeatureGroups, where the recursion stops. Expressions - /// links are ignored. - static std::vector getCSOutList(App::DocumentObject* obj); - ///returns GeoFeatureGroup relevant objects that link to the given one. That meas all objects + /// links are ignored. A exception is thrown when there are dependency loops. + static void getCSOutList(App::DocumentObject* obj, std::vector& vec); + /// Collects GeoFeatureGroup relevant objects that link to the given one. That meas all objects /// including their parents (recursively) except GeoFeatureGroups, where the recursion stops. Expression - /// links are ignored - static std::vector getCSInList(App::DocumentObject* obj); - /// Returns all links that are relevant for the coordinate system, meaning all recursive links to + /// links are ignored. A exception is thrown when there are dependency loops. + static void getCSInList(App::DocumentObject* obj, std::vector& vec); + /// Collects all links that are relevant for the coordinate system, meaning all recursive links to /// obj and from obj excluding expressions and stopping the recursion at other geofeaturegroups. /// The result is the combination of CSOutList and CSInList. - static std::vector getCSRelevantLinks(App::DocumentObject* obj); + static void getCSRelevantLinks(App::DocumentObject* obj, std::vector& vec); private: Base::Placement recursiveGroupPlacement(GeoFeatureGroupExtension* group); diff --git a/src/App/GroupExtension.cpp b/src/App/GroupExtension.cpp index bd3b123d66..09b21ec838 100644 --- a/src/App/GroupExtension.cpp +++ b/src/App/GroupExtension.cpp @@ -104,29 +104,6 @@ std::vector< DocumentObject* > GroupExtension::addObjects(std::vector< DocumentO return added; } -void GroupExtension::addObjects(const std::vector& objs) -{ - bool objectAdded = false; - std::vector grp = Group.getValues(); - for (auto obj : objs) { - if (allowObject(obj)) { - - //only one group per object - auto *group = App::GroupExtension::getGroupOfObject(obj); - if (group && group != getExtendedObject()) - group->getExtensionByType()->removeObject(obj); - - if (std::find(grp.begin(), grp.end(), obj) == grp.end()) { - grp.push_back(obj); - objectAdded = true; - } - } - } - - if (objectAdded) - Group.setValues(grp); -} - std::vector GroupExtension::removeObject(DocumentObject* obj) { std::vector vec = {obj}; diff --git a/src/App/OriginGroupExtension.h b/src/App/OriginGroupExtension.h index d79ed2d2f7..eecaef29d0 100644 --- a/src/App/OriginGroupExtension.h +++ b/src/App/OriginGroupExtension.h @@ -52,8 +52,6 @@ public: * Returns the origin group which contains this object. * In case this object is not part of any geoFeatureGroup 0 is returned. * @param obj the object to search for - * @param indirect if true return if the group that so-called geoHas the object, @see geoHasObject() - * default is true */ static DocumentObject* getGroupOfObject (const DocumentObject* obj); diff --git a/src/App/Part.h b/src/App/Part.h index a3726251a1..3f4ed3c977 100644 --- a/src/App/Part.h +++ b/src/App/Part.h @@ -88,8 +88,6 @@ public: * Returns the part which contains this object. * In case this object is not belongs to any Part 0 is returned. * @param obj the object to search for - * @param indirect if true return if the part that so-called geoHas the object, @see geoHasObject() - * default is true */ static App::Part* getPartOfObject (const DocumentObject* obj); diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index d7320b47d7..d437f67fb7 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -108,7 +108,8 @@ void ensureCorrectGroups(PropertyContainer* container, App::DocumentObject* obje if(cont->isRestoring() || object->isRestoring()) return; - auto objs = GeoFeatureGroupExtension::getCSRelevantLinks(object); + std::vector< DocumentObject* > objs; + GeoFeatureGroupExtension::getCSRelevantLinks(object, objs); objs.push_back(object); for(auto obj : objs) { diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 45f96a3274..a7ed5a943e 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -2097,8 +2097,8 @@ bool SketchObject::isCarbonCopyAllowed(App::Document *pDoc, App::DocumentObject //App::DocumentObject *support = this->Support.getValue(); Part::BodyBase* body_this = Part::BodyBase::findBodyOf(this); Part::BodyBase* body_obj = Part::BodyBase::findBodyOf(pObj); - App::Part* part_this = App::Part::getPartOfObject(this, true); - App::Part* part_obj = App::Part::getPartOfObject(pObj, true); + App::Part* part_this = App::Part::getPartOfObject(this); + App::Part* part_obj = App::Part::getPartOfObject(pObj); if (part_this == part_obj){ //either in the same part, or in the root of document if (body_this != NULL) { if ((body_this != body_obj) && !this->allowOtherBody) { diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 587bac0534..9e0af75231 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -5819,9 +5819,9 @@ bool ViewProviderSketch::onDelete(const std::vector &subList) return PartGui::ViewProviderPart::onDelete(subList); } -} - void ViewProviderSketch::showRestoreInformationLayer() { visibleInformationChanged = true ; - draw(false,false); \ No newline at end of file + draw(false,false); + +} \ No newline at end of file