Merge pull request #13963 from bgbsww/bgbsww-toponamingMissingPartDesignTests2

Toponaming: missing code bits in App
This commit is contained in:
Chris Hennes
2024-05-12 19:30:04 -05:00
committed by GitHub
6 changed files with 146 additions and 29 deletions

View File

@@ -53,6 +53,12 @@ namespace Data
{
//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

View File

@@ -30,6 +30,7 @@
#include "GeoFeature.h"
#include "GeoFeatureGroupExtension.h"
#include "ElementNamingUtils.h"
#include "Link.h"
using namespace App;
@@ -141,6 +142,10 @@ DocumentObject *GeoFeature::resolveElement(DocumentObject *obj, const char *subn
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)
@@ -148,13 +153,16 @@ DocumentObject *GeoFeature::resolveElement(DocumentObject *obj, const char *subn
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)
@@ -202,43 +210,73 @@ void GeoFeature::setMaterialAppearance(const App::Material& material)
}
#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) {
return nil;
}
return prop->getComplexData()->getElementTypes();
}
std::vector<Data::IndexedName> GeoFeature::getHigherElements(const char* element, bool silent) const
{
auto prop = getPropertyOfGeometry();
if (!prop)
if (!prop) {
return {};
}
return prop->getComplexData()->getHigherElements(element, silent);
}
#endif

View File

@@ -28,6 +28,7 @@
#include "PropertyGeo.h"
#include "MappedElement.h"
#include "Material.h"
#include "ComplexGeoData.h"
namespace App
{
@@ -141,12 +142,34 @@ public:
*/
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;

View File

@@ -1420,8 +1420,22 @@ void LinkBaseExtension::checkGeoElementMap(const App::DocumentObject *obj,
!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() {

View File

@@ -218,6 +218,19 @@ static std::string propertyName(const Property *prop) {
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()) {
@@ -394,15 +407,15 @@ bool PropertyLinkBase::_updateElementReference(DocumentObject *feature,
}
}
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));
@@ -502,11 +515,18 @@ bool PropertyLinkBase::_updateElementReference(DocumentObject *feature,
}
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) {
@@ -536,6 +556,9 @@ PropertyLinkBase::tryReplaceLink(const PropertyContainer *owner, DocumentObject
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;
@@ -577,6 +600,8 @@ PropertyLinkBase::tryReplaceLinkSubs(const PropertyContainer *owner,
{
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) {
@@ -1545,8 +1570,12 @@ std::string PropertyLinkBase::tryImportSubName(const App::DocumentObject *obj, c
#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
{

View File

@@ -28,6 +28,9 @@
#include <map>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include "Property.h"
namespace Base {
@@ -38,6 +41,8 @@ namespace App
{
class DocumentObject;
class Document;
class GeoFeature;
class SubObjectT;
class DocInfo;
using DocInfoPtr = std::shared_ptr<DocInfo>;
@@ -262,7 +267,7 @@ public:
/// 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;
@@ -275,7 +280,7 @@ public:
/// 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);
@@ -346,6 +351,8 @@ public:
/// 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
*