method to get paths between two objects

This commit is contained in:
wmayer
2017-10-20 18:26:18 +02:00
parent af64ffcaf5
commit 725a5b6545
6 changed files with 114 additions and 0 deletions

View File

@@ -3026,3 +3026,76 @@ std::vector<App::DocumentObject*> Document::getRootObjects() const
return ret;
}
namespace App {
typedef vector <size_t> Node;
typedef vector <size_t> Path;
void _findAllPathsAt(const std::vector <Node> &all_nodes, size_t id,
std::vector <Path> &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<std::list<App::DocumentObject*> >
Document::getPathsByOutList(const App::DocumentObject* from, const App::DocumentObject* to) const
{
std::map<const DocumentObject*, size_t> indexMap;
for (size_t i=0; i<d->objectArray.size(); ++i) {
indexMap[d->objectArray[i]] = i;
}
std::vector <Node> all_nodes(d->objectArray.size());
for (size_t i=0; i<d->objectArray.size(); ++i) {
DocumentObject* obj = d->objectArray[i];
std::vector<DocumentObject*> outList = obj->getOutList();
for (auto it : outList) {
all_nodes[i].push_back(indexMap[it]);
}
}
std::vector<std::list<App::DocumentObject*> > array;
if (from == to)
return array;
size_t index_from = indexMap[from];
size_t index_to = indexMap[to];
Path tmp;
std::vector<Path> all_paths;
_findAllPathsAt(all_nodes, index_from, all_paths, tmp);
for (std::vector<Path>::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<App::DocumentObject*> 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;
}

View File

@@ -332,6 +332,9 @@ public:
std::vector<App::DocumentObject*> topologicalSort() const;
/// get all root objects (objects no other one reference too)
std::vector<App::DocumentObject*> getRootObjects() const;
/// get all possible paths from one object to another following the OutList
std::vector<std::list<App::DocumentObject*> > getPathsByOutList
(const App::DocumentObject* from, const App::DocumentObject* to) const;
//@}
/// Function called to signal that an object identifier has been renamed

View File

@@ -271,6 +271,12 @@ std::vector<App::DocumentObject*> DocumentObject::getOutListRecursive(void) cons
return array;
}
std::vector<std::list<App::DocumentObject*> >
DocumentObject::getPathsByOutList(App::DocumentObject* to) const
{
return _pDoc->getPathsByOutList(this, to);
}
DocumentObjectGroup* DocumentObject::getGroup() const
{
return dynamic_cast<DocumentObjectGroup*>(GroupExtension::getGroupOfObject(this));

View File

@@ -140,6 +140,8 @@ public:
std::vector<App::DocumentObject*> getOutList(void) const;
/// returns a list of objects this object is pointing to by Links and all further descended
std::vector<App::DocumentObject*> getOutListRecursive(void) const;
/// get all possible paths from this to another object following the OutList
std::vector<std::list<App::DocumentObject*> > getPathsByOutList(App::DocumentObject* to) const;
/// get all objects link to this object
std::vector<App::DocumentObject*> getInList(void) const;
/// get all objects link directly or indirectly to this object

View File

@@ -69,6 +69,11 @@
in a single group, hence only a single return value.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getPathsByOutList">
<Documentation>
<UserDocu>Get all paths from this object to another object following the OutList.</UserDocu>
</Documentation>
</Methode>
<Attribute Name="OutList" ReadOnly="true">
<Documentation>
<UserDocu>A list of all objects this object links to.</UserDocu>

View File

@@ -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<DocumentObjectPy*>
(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