App: GeoFeature/ComplexGeoData API changes
These are the bare minimum set of APIs for future new topogical naming feature (see [here](https://git.io/fj6hy) for a overview of the new APIs). These APIs are added early to avoid too much code change for the new features introduced in the current patch set.
This commit is contained in:
@@ -27,7 +27,10 @@
|
||||
# include <cstdlib>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Console.h>
|
||||
#include "ComplexGeoData.h"
|
||||
|
||||
using namespace Data;
|
||||
@@ -39,6 +42,7 @@ TYPESYSTEM_SOURCE_ABSTRACT(Data::ComplexGeoData , Base::Persistence);
|
||||
|
||||
|
||||
ComplexGeoData::ComplexGeoData(void)
|
||||
:Tag(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -153,3 +157,97 @@ bool ComplexGeoData::getCenterOfGravity(Base::Vector3d&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string &ComplexGeoData::elementMapPrefix() {
|
||||
static std::string prefix(";");
|
||||
return prefix;
|
||||
}
|
||||
|
||||
const char *ComplexGeoData::isMappedElement(const char *name) {
|
||||
if(name && boost::starts_with(name,elementMapPrefix()))
|
||||
return name+elementMapPrefix().size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string ComplexGeoData::newElementName(const char *name) {
|
||||
if(!name) return std::string();
|
||||
const char *dot = strrchr(name,'.');
|
||||
if(!dot || dot==name) return name;
|
||||
const char *c = dot-1;
|
||||
for(;c!=name;--c) {
|
||||
if(*c == '.') {
|
||||
++c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isMappedElement(c))
|
||||
return std::string(name,dot-name);
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string ComplexGeoData::oldElementName(const char *name) {
|
||||
if(!name) return std::string();
|
||||
const char *dot = strrchr(name,'.');
|
||||
if(!dot || dot==name) return name;
|
||||
const char *c = dot-1;
|
||||
for(;c!=name;--c) {
|
||||
if(*c == '.') {
|
||||
++c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isMappedElement(c))
|
||||
return std::string(name,c-name)+(dot+1);
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string ComplexGeoData::noElementName(const char *name) {
|
||||
auto element = findElementName(name);
|
||||
if(element)
|
||||
return std::string(name,element-name);
|
||||
return name;
|
||||
}
|
||||
|
||||
const char *ComplexGeoData::findElementName(const char *subname) {
|
||||
if(!subname || !subname[0] || isMappedElement(subname))
|
||||
return subname;
|
||||
const char *dot = strrchr(subname,'.');
|
||||
if(!dot)
|
||||
return subname;
|
||||
const char *element = dot+1;
|
||||
if(dot==subname || isMappedElement(element))
|
||||
return element;
|
||||
for(--dot;dot!=subname;--dot) {
|
||||
if(*dot == '.') {
|
||||
++dot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isMappedElement(dot))
|
||||
return dot;
|
||||
return element;
|
||||
}
|
||||
|
||||
const std::string &ComplexGeoData::tagPostfix() {
|
||||
static std::string postfix(elementMapPrefix() + ":T");
|
||||
return postfix;
|
||||
}
|
||||
|
||||
const std::string &ComplexGeoData::indexPostfix() {
|
||||
static std::string postfix(elementMapPrefix() + ":I");
|
||||
return postfix;
|
||||
}
|
||||
|
||||
const std::string &ComplexGeoData::missingPrefix() {
|
||||
static std::string prefix("?");
|
||||
return prefix;
|
||||
}
|
||||
|
||||
bool ComplexGeoData::hasMissingElement(const char *subname) {
|
||||
if(!subname)
|
||||
return false;
|
||||
auto dot = strrchr(subname,'.');
|
||||
if(dot)
|
||||
subname = dot+1;
|
||||
return boost::starts_with(subname,missingPrefix());
|
||||
}
|
||||
|
||||
@@ -156,6 +156,41 @@ public:
|
||||
virtual bool getCenterOfGravity(Base::Vector3d& center) const;
|
||||
//@}
|
||||
|
||||
/** @name Element name mapping */
|
||||
//@{
|
||||
/// Sepecial prefix to mark the begining of a mapped sub-element name
|
||||
static const std::string &elementMapPrefix();
|
||||
/// Sepecial postfix to mark the following tag
|
||||
static const std::string &tagPostfix();
|
||||
/// Speical postfix to mark the index of an array element
|
||||
static const std::string &indexPostfix();
|
||||
/// Speical prefix to mark a missing element
|
||||
static const std::string &missingPrefix();
|
||||
/// Check if a subname contains missing element
|
||||
static bool hasMissingElement(const char *subname);
|
||||
/** Check if the name starts with elementMapPrefix()
|
||||
*
|
||||
* @param name: input name
|
||||
* @return Returns the name stripped with elementMapPrefix(), or 0 if not
|
||||
* start with the prefix
|
||||
*/
|
||||
static const char *isMappedElement(const char *name);
|
||||
|
||||
/// Strip out the trailing element name if there is mapped element name preceeds it.
|
||||
static std::string newElementName(const char *name);
|
||||
/// Strip out the mapped element name if there is one.
|
||||
static std::string oldElementName(const char *name);
|
||||
/// Strip out the old and new element name if there is one.
|
||||
static std::string noElementName(const char *name);
|
||||
|
||||
/// Find the start of an element name in a subname
|
||||
static const char *findElementName(const char *subname);
|
||||
|
||||
static inline const char *hasMappedElementName(const char *subname) {
|
||||
return isMappedElement(findElementName(subname));
|
||||
}
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
/// from local to outside
|
||||
@@ -171,6 +206,8 @@ protected:
|
||||
Base::Vector3d tmp = tmpM * vec;
|
||||
return Base::Vector3f((float)tmp.x,(float)tmp.y,(float)tmp.z);
|
||||
}
|
||||
public:
|
||||
mutable long Tag;
|
||||
};
|
||||
|
||||
} //namespace App
|
||||
|
||||
@@ -37,5 +37,11 @@
|
||||
</Documentation>
|
||||
<Parameter Name="Matrix" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Tag">
|
||||
<Documentation>
|
||||
<UserDocu>Geometry Tag</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Tag" Type="Int"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
@@ -126,6 +126,14 @@ void ComplexGeoDataPy::setMatrix(Py::Object arg)
|
||||
}
|
||||
}
|
||||
|
||||
Py::Int ComplexGeoDataPy::getTag() const {
|
||||
return Py::Int(getComplexGeoDataPtr()->Tag);
|
||||
}
|
||||
|
||||
void ComplexGeoDataPy::setTag(Py::Int tag) {
|
||||
getComplexGeoDataPtr()->Tag = tag;
|
||||
}
|
||||
|
||||
PyObject *ComplexGeoDataPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -79,3 +79,62 @@ PyObject* GeoFeature::getPyObject(void)
|
||||
}
|
||||
return Py::new_reference_to(PythonObject);
|
||||
}
|
||||
|
||||
|
||||
std::pair<std::string,std::string> GeoFeature::getElementName(
|
||||
const char *name, ElementNameType type) const
|
||||
{
|
||||
(void)type;
|
||||
|
||||
std::pair<std::string,std::string> ret;
|
||||
if(!name) return ret;
|
||||
|
||||
ret.second = name;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DocumentObject *GeoFeature::resolveElement(DocumentObject *obj, const char *subname,
|
||||
std::pair<std::string,std::string> &elementName, bool append,
|
||||
ElementNameType type, const DocumentObject *filter,
|
||||
const char **_element, GeoFeature **geoFeature)
|
||||
{
|
||||
if(!obj || !obj->getNameInDocument())
|
||||
return 0;
|
||||
if(!subname)
|
||||
subname = "";
|
||||
const char *element = Data::ComplexGeoData::findElementName(subname);
|
||||
if(_element) *_element = element;
|
||||
auto sobj = obj->getSubObject(subname);
|
||||
if(!sobj)
|
||||
return 0;
|
||||
obj = sobj->getLinkedObject(true);
|
||||
auto geo = dynamic_cast<GeoFeature*>(obj);
|
||||
if(geoFeature)
|
||||
*geoFeature = geo;
|
||||
if(!obj || (filter && obj!=filter))
|
||||
return 0;
|
||||
if(!element || !element[0]) {
|
||||
if(append)
|
||||
elementName.second = Data::ComplexGeoData::oldElementName(subname);
|
||||
return sobj;
|
||||
}
|
||||
|
||||
if(!geo || hasHiddenMarker(element)) {
|
||||
if(!append)
|
||||
elementName.second = element;
|
||||
else
|
||||
elementName.second = Data::ComplexGeoData::oldElementName(subname);
|
||||
return sobj;
|
||||
}
|
||||
if(!append)
|
||||
elementName = geo->getElementName(element,type);
|
||||
else{
|
||||
const auto &names = geo->getElementName(element,type);
|
||||
std::string prefix(subname,element-subname);
|
||||
if(names.first.size())
|
||||
elementName.first = prefix + names.first;
|
||||
elementName.second = prefix + names.second;
|
||||
}
|
||||
return sobj;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,48 @@ public:
|
||||
* @return the Python binding object
|
||||
*/
|
||||
virtual PyObject* getPyObject(void);
|
||||
|
||||
|
||||
/// Specify the type of element name to return when calling getElementName()
|
||||
enum ElementNameType {
|
||||
/// Normal usage
|
||||
Normal=0,
|
||||
/// For importing
|
||||
Import=1,
|
||||
/// For exporting
|
||||
Export=2,
|
||||
};
|
||||
/** Return the new and old style sub-element name
|
||||
*
|
||||
* @param name: input name
|
||||
* @param type: desired element name type to return
|
||||
*
|
||||
* @return a pair(newName,oldName). New element name may be empty.
|
||||
*
|
||||
* This function currently is does nothing. The new style element name
|
||||
* generation will be added in the next batch of patches.
|
||||
*/
|
||||
virtual std::pair<std::string,std::string> getElementName(
|
||||
const char *name, ElementNameType type=Normal) const;
|
||||
|
||||
/** Resolve both the new and old style element name
|
||||
*
|
||||
* @param obj: top parent object
|
||||
* @param subname: subname reference
|
||||
* @param elementName: output of a pair(newElementName,oldElementName)
|
||||
* @param append: Whether to include subname prefix into the returned
|
||||
* element name
|
||||
* @param type: the type of element name to request
|
||||
* @param filter: If none zero, then only perform lookup when the element
|
||||
* owner object is the same as this filter
|
||||
* @param element: return the start of element name in subname
|
||||
*
|
||||
* @return Return the owner object of the element
|
||||
*/
|
||||
static DocumentObject *resolveElement(App::DocumentObject *obj,
|
||||
const char *subname, std::pair<std::string,std::string> &elementName,
|
||||
bool append=false, ElementNameType type=Normal,
|
||||
const DocumentObject *filter=0,const char **element=0, GeoFeature **geo=0);
|
||||
|
||||
/**
|
||||
* @brief Calculates the placement in the global reference coordinate system
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user