diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 8c6a83cd10..3435ff49af 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -3026,3 +3026,76 @@ std::vector Document::getRootObjects() const return ret; } + +namespace App { +typedef vector Node; +typedef vector Path; +void _findAllPathsAt(const std::vector &all_nodes, size_t id, + std::vector &all_paths, Path tmp) +{ + if (std::find(tmp.begin(), tmp.end(), id) != tmp.end()) { + Path tmp2(tmp); + tmp2.push_back(id); + all_paths.push_back(tmp2); + return; // a cycle + } + + tmp.push_back(id); + if (all_nodes[id].empty()) { + all_paths.push_back(tmp); + return; + } + + for (size_t i=0; i < all_nodes[id].size(); i++) { + Path tmp2(tmp); + _findAllPathsAt(all_nodes, all_nodes[id][i], all_paths, tmp2); + } +} +} + +std::vector > +Document::getPathsByOutList(const App::DocumentObject* from, const App::DocumentObject* to) const +{ + std::map indexMap; + for (size_t i=0; iobjectArray.size(); ++i) { + indexMap[d->objectArray[i]] = i; + } + + std::vector all_nodes(d->objectArray.size()); + for (size_t i=0; iobjectArray.size(); ++i) { + DocumentObject* obj = d->objectArray[i]; + std::vector outList = obj->getOutList(); + for (auto it : outList) { + all_nodes[i].push_back(indexMap[it]); + } + } + + std::vector > array; + if (from == to) + return array; + + size_t index_from = indexMap[from]; + size_t index_to = indexMap[to]; + Path tmp; + std::vector all_paths; + _findAllPathsAt(all_nodes, index_from, all_paths, tmp); + + for (std::vector::iterator it = all_paths.begin(); it != all_paths.end(); ++it) { + Path::iterator jt = std::find(it->begin(), it->end(), index_to); + if (jt != it->end()) { + std::list path; + for (Path::iterator kt = it->begin(); kt != jt; ++kt) { + path.push_back(d->objectArray[*kt]); + } + + path.push_back(d->objectArray[*jt]); + array.push_back(path); + } + } + + // remove duplicates + std::sort(array.begin(), array.end()); + array.erase(std::unique(array.begin(), array.end()), array.end()); + + return array; +} diff --git a/src/App/Document.h b/src/App/Document.h index 4ec3f89390..b88985f476 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -332,6 +332,9 @@ public: std::vector topologicalSort() const; /// get all root objects (objects no other one reference too) std::vector getRootObjects() const; + /// get all possible paths from one object to another following the OutList + std::vector > getPathsByOutList + (const App::DocumentObject* from, const App::DocumentObject* to) const; //@} /// Function called to signal that an object identifier has been renamed diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index 68718150c8..41f8d28345 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -271,6 +271,12 @@ std::vector DocumentObject::getOutListRecursive(void) cons return array; } +std::vector > +DocumentObject::getPathsByOutList(App::DocumentObject* to) const +{ + return _pDoc->getPathsByOutList(this, to); +} + DocumentObjectGroup* DocumentObject::getGroup() const { return dynamic_cast(GroupExtension::getGroupOfObject(this)); diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index c6cfe30d13..08c312b67a 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -140,6 +140,8 @@ public: std::vector getOutList(void) const; /// returns a list of objects this object is pointing to by Links and all further descended std::vector getOutListRecursive(void) const; + /// get all possible paths from this to another object following the OutList + std::vector > getPathsByOutList(App::DocumentObject* to) const; /// get all objects link to this object std::vector getInList(void) const; /// get all objects link directly or indirectly to this object diff --git a/src/App/DocumentObjectPy.xml b/src/App/DocumentObjectPy.xml index 31e009cbbe..012a903c59 100644 --- a/src/App/DocumentObjectPy.xml +++ b/src/App/DocumentObjectPy.xml @@ -69,6 +69,11 @@ in a single group, hence only a single return value. + + + Get all paths from this object to another object following the OutList. + + A list of all objects this object links to. diff --git a/src/App/DocumentObjectPyImp.cpp b/src/App/DocumentObjectPyImp.cpp index 42013879e3..c689b96d07 100644 --- a/src/App/DocumentObjectPyImp.cpp +++ b/src/App/DocumentObjectPyImp.cpp @@ -361,6 +361,31 @@ PyObject* DocumentObjectPy::getParentGeoFeatureGroup(PyObject *args) } } +PyObject* DocumentObjectPy::getPathsByOutList(PyObject *args) +{ + PyObject* o; + if (!PyArg_ParseTuple(args, "O!", &DocumentObjectPy::Type, &o)) + return NULL; + + try { + DocumentObject* target = static_cast + (o)->getDocumentObjectPtr(); + auto array = getDocumentObjectPtr()->getPathsByOutList(target); + Py::List list; + for (auto it : array) { + Py::List path; + for (auto jt : it) { + path.append(Py::asObject(jt->getPyObject())); + } + list.append(path); + } + return Py::new_reference_to(list); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } +} + PyObject *DocumentObjectPy::getCustomAttributes(const char* attr) const { // search for dynamic property