Skip to content

Commit

Permalink
App: GeoFeature/ComplexGeoData API changes
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
realthunder committed Jul 16, 2019
1 parent b73fb1c commit d059be5
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 1 deletion.
98 changes: 98 additions & 0 deletions src/App/ComplexGeoData.cpp
Expand Up @@ -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;
Expand All @@ -39,6 +42,7 @@ TYPESYSTEM_SOURCE_ABSTRACT(Data::ComplexGeoData , Base::Persistence);


ComplexGeoData::ComplexGeoData(void)
:Tag(0)
{
}

Expand Down Expand Up @@ -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());
}
37 changes: 37 additions & 0 deletions src/App/ComplexGeoData.h
Expand Up @@ -156,6 +156,41 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled
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
Expand All @@ -171,6 +206,8 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled
Base::Vector3d tmp = tmpM * vec;
return Base::Vector3f((float)tmp.x,(float)tmp.y,(float)tmp.z);
}
public:
mutable long Tag;
};

} //namespace App
Expand Down
6 changes: 6 additions & 0 deletions src/App/ComplexGeoDataPy.xml
Expand Up @@ -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>
8 changes: 8 additions & 0 deletions src/App/ComplexGeoDataPyImp.cpp
Expand Up @@ -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;
Expand Down
59 changes: 59 additions & 0 deletions src/App/GeoFeature.cpp
Expand Up @@ -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;
}

43 changes: 42 additions & 1 deletion src/App/GeoFeature.h
Expand Up @@ -66,7 +66,48 @@ class AppExport GeoFeature : public App::DocumentObject
* @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
*
Expand Down

0 comments on commit d059be5

Please sign in to comment.