Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Toponaming: missing code bits in App #13963

Merged
merged 2 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/App/ComplexGeoData.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,18 @@
{

//struct MappedChildElements;
/// Option for App::GeoFeature::searchElementCache()
enum class SearchOptions {
/// Whether to compare shape geometry
CheckGeometry = 1,
SingleResult = 2,
};

/** Segments
* Sub-element type of the ComplexGeoData type
* It is used to split an object in further sub-parts.
*/
class AppExport Segment: public Base::BaseClass

Check warning on line 67 in src/App/ComplexGeoData.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

class 'Segment' defines a default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT

Expand All @@ -75,7 +81,7 @@

/** ComplexGeoData Object
*/
class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled

Check warning on line 84 in src/App/ComplexGeoData.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

class 'ComplexGeoData' defines a default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT

Expand Down Expand Up @@ -280,7 +286,7 @@

/// Append the Tag (if and only if it is non zero) into the element map
virtual void reTagElementMap(long tag,
App::StringHasherRef hasher,

Check warning on line 289 in src/App/ComplexGeoData.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

the parameter 'hasher' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
const char *postfix=nullptr) {
(void)tag;
(void)hasher;
Expand Down Expand Up @@ -344,7 +350,7 @@
*/
void traceElement(const MappedName& name, TraceCallback cb) const
{
_elementMap->traceElement(name, Tag, cb);

Check warning on line 353 in src/App/ComplexGeoData.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

parameter 'cb' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]
}

/** Flush an internal buffering for element mapping */
Expand Down Expand Up @@ -433,10 +439,10 @@
static_cast<float>(tmp.z));
}
public:
mutable long Tag{0};

Check warning on line 442 in src/App/ComplexGeoData.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

member variable 'Tag' has public visibility [cppcoreguidelines-non-private-member-variables-in-classes]

/// String hasher for element name shortening
mutable App::StringHasherRef Hasher;

Check warning on line 445 in src/App/ComplexGeoData.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

member variable 'Hasher' has public visibility [cppcoreguidelines-non-private-member-variables-in-classes]

protected:

Expand Down Expand Up @@ -468,8 +474,8 @@
ElementMapPtr _elementMap;

protected:
mutable std::string _persistenceName;

Check warning on line 477 in src/App/ComplexGeoData.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

member variable '_persistenceName' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]
mutable bool _restoreFailed = false;

Check warning on line 478 in src/App/ComplexGeoData.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

member variable '_restoreFailed' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]
};

} //namespace App
Expand Down
78 changes: 58 additions & 20 deletions src/App/GeoFeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@
#include "GeoFeature.h"
#include "GeoFeatureGroupExtension.h"
#include "ElementNamingUtils.h"
#include "Link.h"


using namespace App;


PROPERTY_SOURCE(App::GeoFeature, App::DocumentObject)

Check warning on line 39 in src/App/GeoFeature.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

variable 'classTypeId' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]


//===========================================================================
Expand Down Expand Up @@ -141,20 +142,27 @@
ElementNameType type, const DocumentObject *filter,
const char **_element, GeoFeature **geoFeature)
{
#ifdef FC_USE_TNP_FIX
elementName.first.clear();
elementName.second.clear();
#endif
if(!obj || !obj->isAttachedToDocument())
return nullptr;
if(!subname)
subname = "";
const char *element = Data::findElementName(subname);
if(_element) *_element = element;
#ifdef FC_USE_TNP_FIX
elementName.first.clear();
elementName.second.clear();
auto sobj = obj->getSubObject(std::string(subname, element).c_str());
if(!sobj)
return nullptr;
auto linked = sobj->getLinkedObject(true);
auto geo = Base::freecad_dynamic_cast<GeoFeature>(linked);
if(!geo && linked) {
auto ext = linked->getExtensionByType<LinkBaseExtension>(true);
if(ext)
geo = Base::freecad_dynamic_cast<GeoFeature>(ext->getTrueLinkedObject(true));
}
#else
auto sobj = obj->getSubObject(subname);
if(!sobj)
Expand Down Expand Up @@ -202,43 +210,73 @@
}

#ifdef FC_USE_TNP_FIX
bool GeoFeature::hasMissingElement(const char *subname) {
bool GeoFeature::hasMissingElement(const char* subname)
{
return Data::hasMissingElement(subname);
if(!subname)
if (!subname) {
return false;
auto dot = strrchr(subname,'.');
if(!dot)
return subname[0]=='?';
return dot[1]=='?';
}
auto dot = strrchr(subname, '.');
if (!dot) {
return subname[0] == '?';
}
return dot[1] == '?';
}

void GeoFeature::updateElementReference() {
void GeoFeature::updateElementReference()
{
auto prop = getPropertyOfGeometry();
if(!prop) return;
if (!prop) {
return;
}
auto geo = prop->getComplexData();
if(!geo) return;
if (!geo) {
return;
}
bool reset = false;
PropertyLinkBase::updateElementReferences(this,reset);
PropertyLinkBase::updateElementReferences(this, reset);
}

void GeoFeature::onChanged(const Property *prop) {
if(prop==getPropertyOfGeometry()) {
if(getDocument() && !getDocument()->testStatus(Document::Restoring)
&& !getDocument()->isPerformingTransaction())
{
void GeoFeature::onChanged(const Property* prop)
{
if (prop == getPropertyOfGeometry()) {
if (getDocument() && !getDocument()->testStatus(Document::Restoring)
&& !getDocument()->isPerformingTransaction()) {
updateElementReference();
}
}
DocumentObject::onChanged(prop);
}

const std::vector<std::string>& GeoFeature::searchElementCache(const std::string& element,
Data::SearchOptions options,
double tol,
double atol) const
{
static std::vector<std::string> none;
(void)element;
(void)options;
(void)tol;
(void)atol;
return none;
}

std::vector<Data::IndexedName>
GeoFeature::getHigherElements(const char *element, bool silent) const
const std::vector<const char*>& GeoFeature::getElementTypes(bool /*all*/) const
{
static std::vector<const char*> nil;
auto prop = getPropertyOfGeometry();
if (!prop)
if (!prop) {
return nil;
}
return prop->getComplexData()->getElementTypes();
}

std::vector<Data::IndexedName> GeoFeature::getHigherElements(const char* element, bool silent) const
{
auto prop = getPropertyOfGeometry();
if (!prop) {
return {};
}
return prop->getComplexData()->getHigherElements(element, silent);
}
#endif
23 changes: 23 additions & 0 deletions src/App/GeoFeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "PropertyGeo.h"
#include "MappedElement.h"
#include "Material.h"
#include "ComplexGeoData.h"

namespace App
{
Expand Down Expand Up @@ -141,12 +142,34 @@ class AppExport GeoFeature : public App::DocumentObject
*/
virtual void setMaterialAppearance(const App::Material& material);
#ifdef FC_USE_TNP_FIX
/** Search sub element using internal cached geometry
*
* @param element: element name
* @param options: search options
* @param tol: coordinate tolerance
* @param atol: angle tolerance
*
* @return Returns a list of found element reference to the new geometry.
* The returned value will be invalidated when the geometry is changed.
*
* Before changing the property of geometry, GeoFeature will internally
* make a snapshot of all referenced element geometry. After change, user
* code may call this function to search for the new element name that
* reference to the same geometry of the old element.
*/
virtual const std::vector<std::string>& searchElementCache(const std::string &element,
Data::SearchOptions options = Data::SearchOptions::CheckGeometry,
double tol = 1e-7,
double atol = 1e-10) const;

static bool hasMissingElement(const char *subname);

/// Return the object that owns the shape that contains the give element name
virtual DocumentObject *getElementOwner(const Data::MappedName & /*name*/) const
{return nullptr;}

virtual const std::vector<const char *>& getElementTypes(bool all=true) const;

/// Return the higher level element names of the given element
virtual std::vector<Data::IndexedName> getHigherElements(const char *name, bool silent=false) const;

Expand Down
18 changes: 16 additions & 2 deletions src/App/Link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif

FC_LOG_LEVEL_INIT("App::Link", true,true)

Check warning on line 46 in src/App/Link.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

non-POD static (LogLevel) [-Wclazy-non-pod-global-static]

using namespace App;
using namespace Base;
Expand Down Expand Up @@ -1420,8 +1420,22 @@
!PyObject_TypeCheck(*pyObj, &Data::ComplexGeoDataPy::Type))
return;

// auto geoData = static_cast<Data::ComplexGeoDataPy*>(*pyObj)->getComplexGeoDataPtr();
// geoData->reTagElementMap(obj->getID(),obj->getDocument()->Hasher,postfix);
// auto geoData = static_cast<Data::ComplexGeoDataPy*>(*pyObj)->getComplexGeoDataPtr();
// geoData->reTagElementMap(obj->getID(),obj->getDocument()->Hasher,postfix);

auto geoData = static_cast<Data::ComplexGeoDataPy*>(*pyObj)->getComplexGeoDataPtr();
std::string _postfix;
if (linked && obj && linked->getDocument() != obj->getDocument()) {
_postfix = Data::POSTFIX_EXTERNAL_TAG;
if (postfix) {
if (!boost::starts_with(postfix, Data::ComplexGeoData::elementMapPrefix()))
_postfix += Data::ComplexGeoData::elementMapPrefix();
_postfix += postfix;
}
postfix = _postfix.c_str();
}
geoData->reTagElementMap(obj->getID(),obj->getDocument()->getStringHasher(),postfix);

}

void LinkBaseExtension::onExtendedUnsetupObject() {
Expand Down
39 changes: 34 additions & 5 deletions src/App/PropertyLinks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
#include "GeoFeature.h"


FC_LOG_LEVEL_INIT("PropertyLinks",true,true)

Check warning on line 45 in src/App/PropertyLinks.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

non-POD static (LogLevel) [-Wclazy-non-pod-global-static]

using namespace App;
using namespace Base;
Expand All @@ -56,9 +56,9 @@

TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkBase , App::Property)

static std::unordered_map<std::string, std::set<PropertyLinkBase*> > _LabelMap;

Check warning on line 59 in src/App/PropertyLinks.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

non-POD static (unordered_map) [-Wclazy-non-pod-global-static]

static std::unordered_map<App::DocumentObject *, std::unordered_set<PropertyLinkBase*> > _ElementRefMap;

Check warning on line 61 in src/App/PropertyLinks.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

non-POD static (unordered_map) [-Wclazy-non-pod-global-static]

PropertyLinkBase::PropertyLinkBase() = default;

Expand Down Expand Up @@ -218,6 +218,19 @@
return prop->getFullName();
}

const std::unordered_set<PropertyLinkBase*>&
PropertyLinkBase::getElementReferences(DocumentObject* feature)
{
static std::unordered_set<PropertyLinkBase*> none;

auto it = _ElementRefMap.find(feature);
if (it == _ElementRefMap.end()) {
return none;
}

return it->second;
}

void PropertyLinkBase::updateElementReferences(DocumentObject *feature, bool reverse) {
#ifdef FC_USE_TNP_FIX
if (!feature || !feature->getNameInDocument()) {
Expand Down Expand Up @@ -394,15 +407,15 @@
}
}

bool missing = Data::hasMissingElement(elementName.second.c_str());
bool missing = GeoFeature::hasMissingElement(elementName.second.c_str());
if (feature == geo && (missing || reverse)) {
// If the referenced element is missing, or we are generating element
// map for the first time, or we are re-generating the element map due
// to version change, i.e. 'reverse', try search by geometry first
const char* oldElement = Data::findElementName(shadow.second.c_str());
if (!Data::hasMissingElement(oldElement)) {
// const auto& names = geo->searchElementCache(oldElement);
std::vector<std::string> names; // searchElementCache isn't implemented.
const auto& names = geo->searchElementCache(oldElement);
// std::vector<std::string> names; // searchElementCache isn't implemented.
if (names.size()) {
missing = false;
std::string newsub(subname, strlen(subname) - strlen(element));
Expand Down Expand Up @@ -502,11 +515,18 @@
}

std::pair<DocumentObject*, std::string>
PropertyLinkBase::tryReplaceLink(const PropertyContainer *owner, DocumentObject *obj,
const DocumentObject *parent, DocumentObject *oldObj, DocumentObject *newObj, const char *subname)
PropertyLinkBase::tryReplaceLink(const PropertyContainer* owner,
DocumentObject* obj,
const DocumentObject* parent,
DocumentObject* oldObj,
DocumentObject* newObj,
const char* subname)
{
std::pair<DocumentObject*, std::string> res;
res.first = 0;
if (!obj) {
return res;
}

if (oldObj == obj) {
if (owner == parent) {
Expand Down Expand Up @@ -536,6 +556,9 @@
for (auto pos = sub.find('.'); pos != std::string::npos; pos = sub.find('.', pos)) {
++pos;
char c = sub[pos];
if (c == '.') {
continue;
}
sub[pos] = 0;
auto sobj = obj->getSubObject(sub.c_str());
sub[pos] = c;
Expand Down Expand Up @@ -577,6 +600,8 @@
{
std::pair<DocumentObject*,std::vector<std::string> > res;
res.first = 0;
if (!obj)
return res;

auto r = tryReplaceLink(owner,obj,parent,oldObj,newObj);
if(r.first) {
Expand Down Expand Up @@ -1545,8 +1570,12 @@
#define ATTR_SHADOW "shadow"
#define ATTR_MAPPED "mapped"

#ifdef FC_USE_TNP_FIX
#define IGNORE_SHADOW false
#else
// We do not have topo naming yet, ignore shadow sub for now
#define IGNORE_SHADOW true
#endif

void PropertyLinkSub::Save (Base::Writer &writer) const
{
Expand Down
11 changes: 9 additions & 2 deletions src/App/PropertyLinks.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include <map>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include "Property.h"

namespace Base {
Expand All @@ -38,6 +41,8 @@ namespace App
{
class DocumentObject;
class Document;
class GeoFeature;
class SubObjectT;

class DocInfo;
using DocInfoPtr = std::shared_ptr<DocInfo>;
Expand Down Expand Up @@ -262,7 +267,7 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink

/// Helper function to return a map of linked object and its subname references
void getLinkedElements(std::map<App::DocumentObject*, std::vector<std::string> > &elements,
bool newStyle=true, bool all=true) const
bool newStyle=true, bool all=false) const
{
std::vector<App::DocumentObject*> ret;
std::vector<std::string> subs;
Expand All @@ -275,7 +280,7 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink

/// Helper function to return a map of linked object and its subname references
std::map<App::DocumentObject*, std::vector<std::string> >
linkedElements(bool newStyle=true, bool all=true) const
linkedElements(bool newStyle=true, bool all=false) const
{
std::map<App::DocumentObject*, std::vector<std::string> > ret;
getLinkedElements(ret,newStyle,all);
Expand Down Expand Up @@ -346,6 +351,8 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink
/// Update all element references in all link properties of \a feature
static void updateElementReferences(DocumentObject *feature, bool reverse=false);

/// Obtain link properties that contain element references to a given object
static const std::unordered_set<PropertyLinkBase*>& getElementReferences(DocumentObject *);

/** Helper function for update individual element reference
*
Expand Down
Loading