diff --git a/src/App/ComplexGeoDataPy.xml b/src/App/ComplexGeoDataPy.xml index c60f905826..7b094cb3dd 100644 --- a/src/App/ComplexGeoDataPy.xml +++ b/src/App/ComplexGeoDataPy.xml @@ -64,6 +64,37 @@ Apply a transformation to the underlying geometry + + + + setElementName(element,name=None,postfix=None,overwrite=False,sid=None), Set an element name + + element : the original element name, e.g. Edge1, Vertex2 + name : the new name for the element, None to remove the mapping + postfix : postfix of the name that will not be hashed + overwrite: if true, it will overwrite exiting name + sid : to hash the name any way you want, provide your own string id(s) in this parameter + + An element can have multiple mapped names. However, a name can only be mapped + to one element + + + + + + getElementName(name,direction=0) - Return a mapped element name or reverse + + + + + getElementIndexedName(name) - Return the indexed element name + + + + + getElementMappedName(name) - Return the mapped element name + + Get the bounding box (BoundBox) of the complex geometric data. @@ -88,5 +119,35 @@ + + + Get/Set the string hasher of this object + + + + + + Get the current element map size + + + + + + Get/Set a dict of element mapping + + + + + + Get a dict of element reverse mapping + + + + + + Element map version + + + diff --git a/src/App/ComplexGeoDataPyImp.cpp b/src/App/ComplexGeoDataPyImp.cpp index e6c9fe69a5..b3469ddc1a 100644 --- a/src/App/ComplexGeoDataPyImp.cpp +++ b/src/App/ComplexGeoDataPyImp.cpp @@ -27,10 +27,13 @@ #endif #include "ComplexGeoData.h" +#include "StringHasher.h" // inclusion of the generated files (generated out of ComplexGeoDataPy.xml) #include #include +#include +#include #include #include #include @@ -292,6 +295,184 @@ PyObject* ComplexGeoDataPy::transformGeometry(PyObject *args) } } +PyObject* ComplexGeoDataPy::getElementName(PyObject *args) +{ + char* input; + int direction = 0; + if (!PyArg_ParseTuple(args, "s|i", &input,&direction)) + return NULL; + + Data::MappedElement res = getComplexGeoDataPtr()->getElementName(input); + std::string s; + if (direction == 1) + return Py::new_reference_to(Py::String(res.name.appendToBuffer(s))); + else if (direction == 0) + return Py::new_reference_to(Py::String(res.index.appendToStringBuffer(s))); + else if (Data::IndexedName(input)) + return Py::new_reference_to(Py::String(res.name.appendToBuffer(s))); + else + return Py::new_reference_to(Py::String(res.index.appendToStringBuffer(s))); +} + +PyObject* ComplexGeoDataPy::getElementIndexedName(PyObject *args) +{ + char* input; + PyObject *returnID = Py_False; + if (!PyArg_ParseTuple(args, "s|O", &input,&returnID)) + return NULL; + + ElementIDRefs ids; + Data::MappedElement res = getComplexGeoDataPtr()->getElementName( + input, PyObject_IsTrue(returnID)?&ids:nullptr); + std::string s; + Py::String name(res.index.appendToStringBuffer(s)); + if (!PyObject_IsTrue(returnID)) + return Py::new_reference_to(name); + + Py::List list; + for (auto &id : ids) + list.append(Py::Long(id.value())); + return Py::new_reference_to(Py::TupleN(name, list)); +} + +PyObject* ComplexGeoDataPy::getElementMappedName(PyObject *args) +{ + char* input; + PyObject *returnID = Py_False; + if (!PyArg_ParseTuple(args, "s|O", &input,&returnID)) + return NULL; + + ElementIDRefs ids; + Data::MappedElement res = getComplexGeoDataPtr()->getElementName( + input, PyObject_IsTrue(returnID)?&ids:nullptr); + std::string s; + Py::String name(res.name.appendToBuffer(s)); + if (!PyObject_IsTrue(returnID)) + return Py::new_reference_to(name); + + Py::List list; + for (auto &id : ids) + list.append(Py::Long(id.value())); + return Py::new_reference_to(Py::TupleN(name, list)); +} + +PyObject *ComplexGeoDataPy::setElementName(PyObject *args, PyObject *kwds) { + const char *element; + const char *name = 0; + const char *postfix = 0; + int tag = 0; + PyObject *pySid = Py_None; + PyObject *overwrite = Py_False; + + static char *kwlist[] = {"element", "name", "postfix", "overwrite", "sid", "tag", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|sssOOi", kwlist, + &element,&name,&postfix,&overwrite,&pySid,&tag)) + return NULL; + ElementIDRefs sids; + if(pySid != Py_None) { + if(PyObject_TypeCheck(pySid,&App::StringIDPy::Type)) + sids.push_back(static_cast(pySid)->getStringIDPtr()); + else if(PySequence_Check(pySid)) { + Py::Sequence seq(pySid); + for(auto it=seq.begin();it!=seq.end();++it) { + auto ptr = (*it).ptr(); + if(PyObject_TypeCheck(ptr,&App::StringIDPy::Type)) + sids.push_back(static_cast(ptr)->getStringIDPtr()); + else + throw Py::TypeError("expect StringID in sid sequence"); + } + } else + throw Py::TypeError("expect sid to contain either StringID or sequence of StringID"); + } + PY_TRY { + Data::IndexedName index(element, getComplexGeoDataPtr()->getElementTypes()); + Data::MappedName mapped = Data::MappedName::fromRawData(name); + std::ostringstream ss; + ElementMapPtr map = getComplexGeoDataPtr()->resetElementMap(); + map->encodeElementName(getComplexGeoDataPtr()->elementType(index), + mapped, ss, &sids, tag, postfix, tag); + Data::MappedName res = map->setElementName( + index, mapped, tag, &sids, PyObject_IsTrue(overwrite)); + return Py::new_reference_to(Py::String(res.toString(0))); + }PY_CATCH +} + +Py::Object ComplexGeoDataPy::getHasher() const { + auto self = getComplexGeoDataPtr(); + if(!self->Hasher) + return Py::None(); + return Py::Object(self->Hasher->getPyObject(),true); +} + +Py::Dict ComplexGeoDataPy::getElementMap() const { + Py::Dict ret; + std::string s; + for(auto &v : getComplexGeoDataPtr()->getElementMap()) { + s.clear(); + ret.setItem(v.name.toString(0), Py::String(v.index.appendToStringBuffer(s))); + } + return ret; +} + +void ComplexGeoDataPy::setElementMap(Py::Dict dict) { + std::vector map; + const auto & types = getComplexGeoDataPtr()->getElementTypes(); + for(auto it=dict.begin();it!=dict.end();++it) { + const auto &value = *it; + if(!value.first.isString() || !value.second.isString()) + throw Py::TypeError("expect only strings in the dict"); + map.emplace_back(Data::MappedName(value.first.as_string().c_str()), + Data::IndexedName(Py::Object(value.second).as_string().c_str(), types)); + } + getComplexGeoDataPtr()->setElementMap(map); +} + +Py::Dict ComplexGeoDataPy::getElementReverseMap() const { + Py::Dict ret; + std::string s; + for(auto &v : getComplexGeoDataPtr()->getElementMap()) { + s.clear(); + auto value = ret[Py::String(v.index.appendToStringBuffer(s))]; + Py::Object item(value); + if(item.isNone()) { + s.clear(); + value = Py::String(v.name.appendToBuffer(s)); + } else if(item.isList()) { + Py::List list(item); + s.clear(); + list.append(Py::String(v.name.appendToBuffer(s))); + } else { + Py::List list; + list.append(item); + s.clear(); + list.append(Py::String(v.name.appendToBuffer(s))); + value = list; + } + } + return ret; +} + +Py::Int ComplexGeoDataPy::getElementMapSize() const { + return Py::Int((long)getComplexGeoDataPtr()->getElementMapSize()); +} + +void ComplexGeoDataPy::setHasher(Py::Object obj) { + auto self = getComplexGeoDataPtr(); + if(obj.isNone()) { + if(self->Hasher) { + self->Hasher = App::StringHasherRef(); + self->resetElementMap(); + } + }else if(PyObject_TypeCheck(obj.ptr(),&App::StringHasherPy::Type)) { + App::StringHasherRef ref(static_cast(obj.ptr())->getStringHasherPtr()); + if(self->Hasher != ref) { + self->Hasher = ref; + self->resetElementMap(); + } + }else + throw Py::TypeError("invalid type"); +} + Py::Object ComplexGeoDataPy::getBoundBox() const { return Py::BoundingBox(getComplexGeoDataPtr()->getBoundBox()); @@ -324,6 +505,12 @@ void ComplexGeoDataPy::setPlacement(Py::Object arg) } } +Py::String ComplexGeoDataPy::getElementMapVersion() const +{ + return Py::String(getComplexGeoDataPtr()->getElementMapVersion()); +} + + Py::Int ComplexGeoDataPy::getTag() const { return Py::Int(getComplexGeoDataPtr()->Tag);