From 0cf033e3d2d9a6419aac40d77cd200187562a159 Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 4 Aug 2016 17:00:54 +0300 Subject: [PATCH] Issue #1662: implementation of Recover feature. To do: select as base not result, but feature (in GUI widget) --- src/FeaturesAPI/CMakeLists.txt | 2 + src/FeaturesAPI/FeaturesAPI.i | 2 + src/FeaturesAPI/FeaturesAPI_Recover.cpp | 58 ++++++++++ src/FeaturesAPI/FeaturesAPI_Recover.h | 70 ++++++++++++ src/FeaturesAPI/FeaturesAPI_swig.h | 1 + src/FeaturesPlugin/CMakeLists.txt | 3 +- src/FeaturesPlugin/FeaturesPlugin_Recover.cpp | 104 +++++++++++++++++- src/FeaturesPlugin/FeaturesPlugin_Recover.h | 51 +++++++-- src/FeaturesPlugin/Test/TestRecover.py | 66 +++++++++++ src/FeaturesPlugin/icons/recover.png | Bin 0 -> 319 bytes src/FeaturesPlugin/plugin-Features.xml | 4 +- src/FeaturesPlugin/recover_widget.xml | 15 +-- src/Model/Model_Data.cpp | 9 +- src/Model/Model_Data.h | 1 + src/Model/Model_Validator.cpp | 51 ++++++++- src/Model/Model_Validator.h | 23 +++- src/ModelAPI/ModelAPI_Validator.h | 13 +++ src/ModelHighAPI/CMakeLists.txt | 3 + src/ModelHighAPI/ModelHighAPI.i | 62 +++++++++++ src/ModelHighAPI/ModelHighAPI_Reference.cpp | 46 ++++++++ src/ModelHighAPI/ModelHighAPI_Reference.h | 56 ++++++++++ src/ModelHighAPI/ModelHighAPI_Tools.cpp | 26 +++++ src/ModelHighAPI/ModelHighAPI_Tools.h | 13 +++ src/ModelHighAPI/ModelHighAPI_swig.h | 1 + src/ModelHighAPI/Test/TestReference.py | 35 ++++++ src/PythonAPI/model/features/__init__.py | 3 +- src/SketchPlugin/SketchPlugin_Validators.cpp | 2 +- 27 files changed, 687 insertions(+), 33 deletions(-) create mode 100644 src/FeaturesAPI/FeaturesAPI_Recover.cpp create mode 100644 src/FeaturesAPI/FeaturesAPI_Recover.h create mode 100644 src/FeaturesPlugin/Test/TestRecover.py create mode 100644 src/FeaturesPlugin/icons/recover.png create mode 100644 src/ModelHighAPI/ModelHighAPI_Reference.cpp create mode 100644 src/ModelHighAPI/ModelHighAPI_Reference.h create mode 100644 src/ModelHighAPI/Test/TestReference.py diff --git a/src/FeaturesAPI/CMakeLists.txt b/src/FeaturesAPI/CMakeLists.txt index ac6f97e99..1db8f2dd6 100644 --- a/src/FeaturesAPI/CMakeLists.txt +++ b/src/FeaturesAPI/CMakeLists.txt @@ -12,6 +12,7 @@ SET(PROJECT_HEADERS FeaturesAPI_Partition.h FeaturesAPI_Pipe.h FeaturesAPI_Placement.h + FeaturesAPI_Recover.h FeaturesAPI_RemoveSubShapes.h FeaturesAPI_Revolution.h FeaturesAPI_RevolutionBoolean.h @@ -28,6 +29,7 @@ SET(PROJECT_SOURCES FeaturesAPI_Partition.cpp FeaturesAPI_Pipe.cpp FeaturesAPI_Placement.cpp + FeaturesAPI_Recover.cpp FeaturesAPI_RemoveSubShapes.cpp FeaturesAPI_Revolution.cpp FeaturesAPI_RevolutionBoolean.cpp diff --git a/src/FeaturesAPI/FeaturesAPI.i b/src/FeaturesAPI/FeaturesAPI.i index 748634b66..d2c9f968a 100644 --- a/src/FeaturesAPI/FeaturesAPI.i +++ b/src/FeaturesAPI/FeaturesAPI.i @@ -29,6 +29,7 @@ %shared_ptr(FeaturesAPI_Partition) %shared_ptr(FeaturesAPI_Pipe) %shared_ptr(FeaturesAPI_Placement) +%shared_ptr(FeaturesAPI_Recover) %shared_ptr(FeaturesAPI_RemoveSubShapes) %shared_ptr(FeaturesAPI_Revolution) %shared_ptr(FeaturesAPI_RevolutionBoolean) @@ -46,6 +47,7 @@ %include "FeaturesAPI_Partition.h" %include "FeaturesAPI_Pipe.h" %include "FeaturesAPI_Placement.h" +%include "FeaturesAPI_Recover.h" %include "FeaturesAPI_RemoveSubShapes.h" %include "FeaturesAPI_Revolution.h" %include "FeaturesAPI_RevolutionBoolean.h" diff --git a/src/FeaturesAPI/FeaturesAPI_Recover.cpp b/src/FeaturesAPI/FeaturesAPI_Recover.cpp new file mode 100644 index 000000000..4fdf104f7 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Recover.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesAPI_Recover.cpp +// Created: 07 June 2016 +// Author: Dmitry Bobylev + +#include "FeaturesAPI_Recover.h" + +#include +#include + +FeaturesAPI_Recover::FeaturesAPI_Recover(const std::shared_ptr& theFeature) +: ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +FeaturesAPI_Recover::FeaturesAPI_Recover(const std::shared_ptr& theFeature, + const ModelHighAPI_Reference& theBaseFeature, + const std::list& theRecoveredList, const bool thePersistent) +: ModelHighAPI_Interface(theFeature) +{ + if(initialize()) { + setBaseFeature(theBaseFeature); + setRecoveredList(theRecoveredList); + setIsPersistent(thePersistent); + } +} + +FeaturesAPI_Recover::~FeaturesAPI_Recover() +{} + +void FeaturesAPI_Recover::setBaseFeature(const ModelHighAPI_Reference& theBaseFeature) +{ + fillAttribute(theBaseFeature, mybaseFeature); + // do not need to execute because on attribute changed it does everything anyway +} + +void FeaturesAPI_Recover::setRecoveredList(const std::list& theRecoverList) +{ + fillAttribute(theRecoverList, myrecoveredList); + // do not need to execute because on attribute changed it does everything anyway +} + +void FeaturesAPI_Recover::setIsPersistent(bool thePersistent) +{ + fillAttribute(thePersistent, myisPersistent); + // do not need to execute because on attribute changed it does everything anyway +} + +RecoverPtr addRecover(const std::shared_ptr& thePart, + const ModelHighAPI_Reference& theBaseFeature, + const std::list& theRecoveredList, const bool thePersistent) +{ + std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Recover::ID()); + return RecoverPtr(new FeaturesAPI_Recover( + aFeature, theBaseFeature, theRecoveredList, thePersistent)); +} diff --git a/src/FeaturesAPI/FeaturesAPI_Recover.h b/src/FeaturesAPI/FeaturesAPI_Recover.h new file mode 100644 index 000000000..28c8e1804 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Recover.h @@ -0,0 +1,70 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesAPI_Recover.h +// Created: 04 August 2016 +// Author: Mikhail Ponikarov + +#ifndef FeaturesAPI_Recover_H_ +#define FeaturesAPI_Recover_H_ + +#include "FeaturesAPI.h" + +#include + +#include +#include + +class ModelHighAPI_Reference; + +/// \class FeaturesAPI_Recover +/// \ingroup CPPHighAPI +/// \brief Interface for Recover feature. +class FeaturesAPI_Recover: public ModelHighAPI_Interface +{ +public: + /// Constructor without values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Recover(const std::shared_ptr& theFeature); + + /// Constructor with values. + FEATURESAPI_EXPORT + FeaturesAPI_Recover(const std::shared_ptr& theFeature, + const ModelHighAPI_Reference& theBaseFeature, + const std::list& theRecoveredList, + const bool thePersistent = false); + + /// Destructor. + FEATURESAPI_EXPORT + virtual ~FeaturesAPI_Recover(); + + INTERFACE_3(FeaturesPlugin_Recover::ID(), + baseFeature, FeaturesPlugin_Recover::BASE_FEATURE(), ModelAPI_AttributeReference, /** Concealed feature */, + recoveredList, FeaturesPlugin_Recover::RECOVERED_ENTITIES(), ModelAPI_AttributeRefList, /** Recover list*/, + isPersistent, FeaturesPlugin_Recover::PERSISTENT(), ModelAPI_AttributeBoolean, /** Is persistent flag */) + + /// Set base feature. + FEATURESAPI_EXPORT + void setBaseFeature(const ModelHighAPI_Reference& theBaseFeature); + + /// Set recovered list of the base feature + FEATURESAPI_EXPORT + void setRecoveredList(const std::list& theRecoverList); + + /// Set auxiliary + FEATURESAPI_EXPORT + void setIsPersistent(bool thePersistent); + +}; + +/// Pointer on Recover object. +typedef std::shared_ptr RecoverPtr; + +/// \ingroup CPPHighAPI +/// \brief Create Recover feature. +FEATURESAPI_EXPORT +RecoverPtr addRecover(const std::shared_ptr& thePart, + const ModelHighAPI_Reference& theBaseFeature, + const std::list& theRecoveredList, + const bool thePersistent = false); + +#endif // FeaturesAPI_Recover_H_ diff --git a/src/FeaturesAPI/FeaturesAPI_swig.h b/src/FeaturesAPI/FeaturesAPI_swig.h index 0710405ad..f8da2bcfa 100644 --- a/src/FeaturesAPI/FeaturesAPI_swig.h +++ b/src/FeaturesAPI/FeaturesAPI_swig.h @@ -18,6 +18,7 @@ #include "FeaturesAPI_Partition.h" #include "FeaturesAPI_Pipe.h" #include "FeaturesAPI_Placement.h" + #include "FeaturesAPI_Recover.h" #include "FeaturesAPI_RemoveSubShapes.h" #include "FeaturesAPI_Revolution.h" #include "FeaturesAPI_RevolutionBoolean.h" diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 5b5ab88fe..61eddab92 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -132,4 +132,5 @@ ADD_UNIT_TESTS(TestExtrusion.py TestIntersection.py TestUnion.py TestRemoveSubShapes.py - TestPipe.py) + TestPipe.py + TestRecover.py) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Recover.cpp b/src/FeaturesPlugin/FeaturesPlugin_Recover.cpp index 5eb5aa84e..5bdff264f 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Recover.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Recover.cpp @@ -10,8 +10,11 @@ #include #include #include +#include #include #include +#include +#include using namespace std; @@ -21,13 +24,108 @@ FeaturesPlugin_Recover::FeaturesPlugin_Recover() void FeaturesPlugin_Recover::initAttributes() { - data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeReference::typeId()); + data()->addAttribute(BASE_FEATURE(), ModelAPI_AttributeReference::typeId()); data()->addAttribute(RECOVERED_ENTITIES(), ModelAPI_AttributeRefList::typeId()); + data()->addAttribute(PERSISTENT(), ModelAPI_AttributeBoolean::typeId()); - /// temporary modification for empty list - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), RECOVERED_ENTITIES()); + myPersistent = boolean(PERSISTENT())->value(); + // temporary modification for empty list + // ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), RECOVERED_ENTITIES()); + + synchronizeRegistered(); } void FeaturesPlugin_Recover::execute() { + synchronizeRegistered(); +} + +void FeaturesPlugin_Recover::attributeChanged(const std::string& theID) +{ + synchronizeRegistered(); +} + +void FeaturesPlugin_Recover::synchronizeRegistered() +{ + FeaturePtr aBase = baseFeature(); + bool aNewPersistent = boolean(PERSISTENT())->value(); + if (aNewPersistent != myPersistent) + clearRegistered(); + + std::set aRecoveredInList; + // add unconcealed which are not in the myRegistered map + if (isStable() && !isDisabled()) { // if unstable, clear any unconcealment effect + AttributeRefListPtr aRecovered = reflist(RECOVERED_ENTITIES()); + for(int anIndex = aRecovered->size() - 1; anIndex >= 0; anIndex--) { + ObjectPtr anObj = aRecovered->object(anIndex); + aRecoveredInList.insert(anObj); + if (myRegistered.find(anObj) == myRegistered.end()) { + // not found, so register a new + ResultPtr aRes = std::dynamic_pointer_cast(anObj); + ModelAPI_Session::get()->validators()->registerUnconcealment( + aRes, aNewPersistent ? FeaturePtr() : aBase); + myRegistered.insert(anObj); + } + } + } + // remove unconcealed which are not in the stored list, but in the map + std::set >::iterator aMyReg = myRegistered.begin(); + while(aMyReg != myRegistered.end()) { + if (aRecoveredInList.find(*aMyReg) == aRecoveredInList.end()) { + ResultPtr aRes = std::dynamic_pointer_cast(*aMyReg); + ModelAPI_Session::get()->validators()->disableUnconcealment( + aRes, aNewPersistent ? FeaturePtr() : myCurrentBase); + myRegistered.erase(aMyReg); + aMyReg = myRegistered.begin(); // restart iteration because after erase iterator may be bad + } else { + aMyReg++; + } + } + myCurrentBase = aBase; + myPersistent = aNewPersistent; +} + +void FeaturesPlugin_Recover::erase() +{ + // clears myRegistered before all information is destroyed + clearRegistered(); + ModelAPI_Feature::erase(); +} + +bool FeaturesPlugin_Recover::setStable(const bool theFlag) +{ + bool aRes = ModelAPI_Feature::setStable(theFlag); + synchronizeRegistered(); + return aRes; +} + +bool FeaturesPlugin_Recover::setDisabled(const bool theFlag) +{ + bool aRes = ModelAPI_Feature::setDisabled(theFlag); + synchronizeRegistered(); + return aRes; +} + +FeaturePtr FeaturesPlugin_Recover::baseFeature() +{ + // for the current moment it can be result of feature of feature: GUI is not debugged + ObjectPtr aBaseObj = reference(BASE_FEATURE())->value(); + FeaturePtr aResult; + if (aBaseObj.get() == NULL) + return aResult; + aResult = std::dynamic_pointer_cast(aBaseObj); + if (aResult.get() == NULL) + aResult = aBaseObj->document()->feature(std::dynamic_pointer_cast(aBaseObj)); + return aResult; +} + +void FeaturesPlugin_Recover::clearRegistered() +{ + std::set >::iterator aMyReg = myRegistered.begin(); + for(; aMyReg != myRegistered.end(); aMyReg++) { + ResultPtr aRes = std::dynamic_pointer_cast(*aMyReg); + ModelAPI_Session::get()->validators()->disableUnconcealment( + aRes, myPersistent ? FeaturePtr() : myCurrentBase); + } + myRegistered.clear(); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Recover.h b/src/FeaturesPlugin/FeaturesPlugin_Recover.h index e24db88c1..9016ddbd8 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Recover.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Recover.h @@ -17,27 +17,42 @@ */ class FeaturesPlugin_Recover : public ModelAPI_Feature { + /// List of already registered unconcealed pairs of unconcealed result and feature that caused + /// concealment. If attributes of this feature were changed, this list helps to synchronise + /// the current state with validators. + std::set > myRegistered; + /// The last stored Base to unregister Unconcealed when even attributes are already erased. + FeaturePtr myCurrentBase; + /// previous state of persistent flag + bool myPersistent; public: /// Extrusion kind inline static const std::string& ID() { - static const std::string MY_GROUP_ID("Recover"); - return MY_GROUP_ID; + static const std::string MY_RECOVER_ID("Recover"); + return MY_RECOVER_ID; } - /// Attribute name of base shape. - inline static const std::string& BASE_SHAPE_ID() + /// Attribute name of base feature. + inline static const std::string& BASE_FEATURE() { - static const std::string MY_BASE_SHAPE_ID("base_shape"); - return MY_BASE_SHAPE_ID; + static const std::string MY_BASE_FEATURE("base_feature"); + return MY_BASE_FEATURE; } - /// Attribute name of base shape. + /// Attribute name of recovered results list. inline static const std::string& RECOVERED_ENTITIES() { - static const std::string MY_RECOVERED_ENTITIES_ID("recovered_entities"); + static const std::string MY_RECOVERED_ENTITIES_ID("recovered"); return MY_RECOVERED_ENTITIES_ID; } + /// Attribute name of persistenc concealment flag. + inline static const std::string& PERSISTENT() + { + static const std::string MY_PERSISTENT_ID("persistent"); + return MY_PERSISTENT_ID; + } + /// Returns the kind of a feature FEATURESPLUGIN_EXPORT virtual const std::string& getKind() { @@ -54,6 +69,26 @@ class FeaturesPlugin_Recover : public ModelAPI_Feature /// Use plugin manager for features creation FeaturesPlugin_Recover(); + /// Called on change of any argument-attribute of this object. Needed here for synchronization + /// of registered unconcealed. + virtual void attributeChanged(const std::string& theID); + + /// Synchronises myRegistered before all attributes are erased + virtual void erase(); + + /// on unstability of feature, remove all unconcealment effect + virtual bool setStable(const bool theFlag); + /// on disable of feature, remove all unconcealment effect + virtual bool setDisabled(const bool theFlag); +private: + /// Synchronises registration of unconcealed entities with the attributes values of this feature + void synchronizeRegistered(); + + /// Returns the base feature of this + FeaturePtr baseFeature(); + + /// erases all registered cashed values + void clearRegistered(); }; #endif diff --git a/src/FeaturesPlugin/Test/TestRecover.py b/src/FeaturesPlugin/Test/TestRecover.py new file mode 100644 index 000000000..28a47fc83 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestRecover.py @@ -0,0 +1,66 @@ +# Test made with high level API +# ----------------------------- + +import model + +# Initialisation + +model.begin() +mypartset = model.moduleDocument() + + +# Creating a new Part, two circles, extrusions on them and Boolean CUT + +mypart = model.addPart(mypartset).document() + +sk1 = model.addSketch(mypart, model.defaultPlane("XOY")) +c1 = sk1.addCircle(0, 0, 100) +bigcyl = model.addExtrusion(mypart, sk1.selectFace(), 100) + +sk2 = model.addSketch(mypart, model.defaultPlane("XOY")) +c2 = sk2.addCircle(20, 30, 30) +smallcyl = model.addExtrusion(mypart, sk2.selectFace(), 150) + +cut = model.addCut(mypart, bigcyl.result(), smallcyl.result()) + +model.do() + +# check bodies number is 1: only Boolean result +assert(mypart.size("Bodies") == 1) + +model.addRecover(mypart, cut, smallcyl.result()) + +model.end() + +# check that one is recovered +assert(mypart.size("Bodies") == 2) + +model.undo() + +# check bodies number is 1: recover is canceled +assert(mypart.size("Bodies") == 1) + + +# check persistent flag of recover: never concealed +model.begin() + +recover = model.addRecover(mypart, cut, smallcyl.result(), True) +assert(mypart.size("Bodies") == 2) +sk3 = model.addSketch(mypart, model.defaultPlane("XOY")) +c3 = sk3.addCircle(0, 0, 90) +big2 = model.addExtrusion(mypart, sk3.selectFace(), 110) + +cut2 = model.addCut(mypart, big2.result(), smallcyl.result()) + +model.end() + +# two booleans and small cylinder +assert(mypart.size("Bodies") == 3) + + +# make the flag as not-persistent => cylinder must be disappeared +model.begin() +recover.setIsPersistent(False) +model.end() +# only two booleans +assert(mypart.size("Bodies") == 2) diff --git a/src/FeaturesPlugin/icons/recover.png b/src/FeaturesPlugin/icons/recover.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5619c63865292c7f5f3367c4ad9a58faf5192c GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=fts&@Fyn;$$~izmsS?+SlHmNblJdl&REB`W%)AmkKi3e2GGjec zJwpS7FGUN1s@8eBIEGmG@13w)@Q{Om^L8$A2QTgx7nQzPP0essU|`PZUXHC->uI@_fys^183N5#zBxMQP&*p?FsvR|cLde4bmvhk%157f@w40iwV@820K7Kali4VUW~e{ol8%&uel(5Nrta{8{K)&a*Y zJeiioULhS#3eRR7E!|$VxoK5mdK II;Vst0JaTv(EtDd literal 0 HcmV?d00001 diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 98786b67b..cd08911d6 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -55,12 +55,10 @@ icon="icons/Features/shape_group.png"> - - + icon="icons/Features/recover.png"> diff --git a/src/FeaturesPlugin/recover_widget.xml b/src/FeaturesPlugin/recover_widget.xml index daf0d16b5..51582a8b7 100644 --- a/src/FeaturesPlugin/recover_widget.xml +++ b/src/FeaturesPlugin/recover_widget.xml @@ -1,12 +1,13 @@ - - - \ No newline at end of file + + diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index fe4ec99db..60714f8be 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -455,7 +455,8 @@ void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID, // the second condition is for history upper than concealment causer, so the feature result may // be displayed and previewed; also for avoiding of quick show/hide on history // moving deep down - if (aRes && !theFeature->isDisabled()) { + if (aRes && !theFeature->isDisabled() && + !ModelAPI_Session::get()->validators()->isUnconcealed(aRes, theFeature)) { aRes->setIsConcealed(true); } } @@ -473,9 +474,11 @@ void Model_Data::updateConcealmentFlag() std::shared_ptr aRes = std::dynamic_pointer_cast(myObject); if (aRes.get()) { - aRes->setIsConcealed(true); // set concealed + if (!ModelAPI_Session::get()->validators()->isUnconcealed(aRes, aFeature)) { + aRes->setIsConcealed(true); // set concealed + return; + } } - return; } } } diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index c8a5a03d8..6264e68b5 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -74,6 +74,7 @@ class Model_Data : public ModelAPI_Data friend class Model_AttributeRefAttrList; friend class Model_AttributeSelection; friend class Model_AttributeSelectionList; + friend class Model_ValidatorsFactory; public: /// The simplest constructor. "setLabel" must be called just after to initialize correctly. diff --git a/src/Model/Model_Validator.cpp b/src/Model/Model_Validator.cpp index ed7ffac93..f7a58ddb6 100644 --- a/src/Model/Model_Validator.cpp +++ b/src/Model/Model_Validator.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -313,6 +314,54 @@ bool Model_ValidatorsFactory::isConcealed(std::string theFeature, std::string th return aFind != myConcealed.end() && aFind->second.find(theAttribute) != aFind->second.end(); } +void Model_ValidatorsFactory::registerUnconcealment(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat) +{ + if (myUnconcealed.find(theUnconcealed) == myUnconcealed.end()) { + myUnconcealed[theUnconcealed] = std::list >(); + } + myUnconcealed[theUnconcealed].push_back(theCanceledFeat); + std::dynamic_pointer_cast(theUnconcealed->data())->updateConcealmentFlag(); +} + +void Model_ValidatorsFactory::disableUnconcealment(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat) +{ + std::map, std::list > > + ::iterator aResFound = myUnconcealed.find(theUnconcealed); + if (aResFound != myUnconcealed.end()) { + std::list >::iterator anIter = aResFound->second.begin(); + for(; anIter != aResFound->second.end(); anIter++) { + if (*anIter == theCanceledFeat) { + aResFound->second.erase(anIter); + std::dynamic_pointer_cast(theUnconcealed->data())->updateConcealmentFlag(); + break; + } + } + } +} + +bool Model_ValidatorsFactory::isUnconcealed(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat) +{ + std::map, std::list > > + ::iterator aResFound = myUnconcealed.find(theUnconcealed); + if (aResFound != myUnconcealed.end()) { + std::list >::iterator aFeatIter = aResFound->second.begin(); + for(; aFeatIter != aResFound->second.end(); aFeatIter++) { + if (aFeatIter->get()) { + if ((*aFeatIter)->isDisabled()) continue; + if (*aFeatIter == theCanceledFeat) + return true; // this is exactly canceled + if (theCanceledFeat->document()->isLater(*aFeatIter, theCanceledFeat)) + return true; // if unconcealed feature (from the list) is later than concealed + } else + return true; // empty attribute means that everything is canceled + } + } + return false; +} + void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string theAttribute, const std::list >& theCases) { @@ -331,7 +380,7 @@ void Model_ValidatorsFactory::registerCase(std::string theFeature, std::string t aFindAttrID = aFindFeature->second.find(theAttribute); } std::list >::const_iterator aCasesIt = theCases.begin(), - aCasesLast = theCases.end(); + aCasesLast = theCases.end(); std::map > aFindCases = aFindAttrID->second; for (; aCasesIt != aCasesLast; aCasesIt++) { std::pair aCasePair = *aCasesIt; diff --git a/src/Model/Model_Validator.h b/src/Model/Model_Validator.h index 87a9b02da..bda886ec9 100644 --- a/src/Model/Model_Validator.h +++ b/src/Model/Model_Validator.h @@ -37,6 +37,10 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory /// Stores the registered attributes that leads to the concealment of referenced objects in /// data tree. Map from feature kind to set of attribute IDs. std::map > myConcealed; + /// Stored the unconcealed results and features that caused the canceled concealment (Recover). + /// If the feature is empty, unconcealment is persistent. + std::map, std::list > > + myUnconcealed; /// Stores the registered attributes must be checked only if the particular case is activated /// Map from feature kind to map of attribute IDs to pair // (switchId (ID of the attribute) and case Ids (possible values of the switch attribute)) @@ -67,8 +71,8 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory MODEL_EXPORT virtual void validators(const std::string& theFeatureID, Validators& theResult) const; /// Provides a validator for the attribute, returns NULL if no validator - MODEL_EXPORT virtual void validators(const std::string& theFeatureID, const std::string& theAttrID, - Validators& theResult) const; + MODEL_EXPORT virtual void validators(const std::string& theFeatureID, + const std::string& theAttrID, Validators& theResult) const; /// Returns registered validator by its Id MODEL_EXPORT virtual const ModelAPI_Validator* validator(const std::string& theID) const; @@ -94,9 +98,18 @@ class Model_ValidatorsFactory : public ModelAPI_ValidatorsFactory /// Returns true that it was registered that attribute conceals the referenced result virtual bool isConcealed(std::string theFeature, std::string theAttribute); - /// register the case-attribute (\a myCases set definition) - //virtual void registerCase(std::string theFeature, std::string theAttribute, - // std::string theSwitchId, std::string theCaseId); + /// Registers (by Recover feature) cancel of concealment of specific result by specific feature. + /// If theCanceledFeat is empty, the concealment is canceled for this result forever. + virtual void registerUnconcealment(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat); + + /// Disables cancel of concealment of specific result by specific feature. + virtual void disableUnconcealment(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat); + + /// Returns true if concealment is canceled. + virtual bool isUnconcealed(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat); /// register the case-attribute (\a myCases set definition) virtual void registerCase(std::string theFeature, std::string theAttribute, diff --git a/src/ModelAPI/ModelAPI_Validator.h b/src/ModelAPI/ModelAPI_Validator.h index 0557333ba..c621363d5 100644 --- a/src/ModelAPI/ModelAPI_Validator.h +++ b/src/ModelAPI/ModelAPI_Validator.h @@ -101,6 +101,19 @@ class MODELAPI_EXPORT ModelAPI_ValidatorsFactory /// Returns true that it was registered that attribute conceals the referenced result virtual bool isConcealed(std::string theFeature, std::string theAttribute) = 0; + /// Registers (by Recover feature) cancel of concealment of specific result by specific feature. + /// If theCanceledFeat is empty, the concealment is canceled for this result forever. + virtual void registerUnconcealment(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat) = 0; + + /// Disables cancel of concealment of specific result by specific feature. + virtual void disableUnconcealment(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat) = 0; + + /// Returns true if concealment is canceled. + virtual bool isUnconcealed(std::shared_ptr theUnconcealed, + std::shared_ptr theCanceledFeat) = 0; + /// Register the case-attribute: this attribute is checked only if its case is selected virtual void registerCase(std::string theFeature, std::string theAttribute, const std::list >& theCases) = 0; diff --git a/src/ModelHighAPI/CMakeLists.txt b/src/ModelHighAPI/CMakeLists.txt index 0e47ce3bd..dfd97daaf 100644 --- a/src/ModelHighAPI/CMakeLists.txt +++ b/src/ModelHighAPI/CMakeLists.txt @@ -9,6 +9,7 @@ SET(PROJECT_HEADERS ModelHighAPI_Interface.h ModelHighAPI_Macro.h ModelHighAPI_RefAttr.h + ModelHighAPI_Reference.h ModelHighAPI_Selection.h ModelHighAPI_Services.h ModelHighAPI_Tools.h @@ -19,6 +20,7 @@ SET(PROJECT_SOURCES ModelHighAPI_Integer.cpp ModelHighAPI_Interface.cpp ModelHighAPI_RefAttr.cpp + ModelHighAPI_Reference.cpp ModelHighAPI_Selection.cpp ModelHighAPI_Services.cpp ModelHighAPI_Tools.cpp @@ -81,4 +83,5 @@ ADD_UNIT_TESTS( TestDouble.py TestInteger.py TestRefAttr.py + TestReference.py ) diff --git a/src/ModelHighAPI/ModelHighAPI.i b/src/ModelHighAPI/ModelHighAPI.i index 20e338042..1dd6be785 100644 --- a/src/ModelHighAPI/ModelHighAPI.i +++ b/src/ModelHighAPI/ModelHighAPI.i @@ -108,20 +108,82 @@ } } +%typemap(in) const ModelHighAPI_Reference & (ModelHighAPI_Reference temp) { + std::shared_ptr * temp_object; + std::shared_ptr * temp_interface; + int newmem = 0; + if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_object, $descriptor(std::shared_ptr *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) { + if (!temp_object) { + PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Interface or ModelAPI_Object."); + return NULL; + } + temp = ModelHighAPI_Reference(*temp_object); + if (newmem & SWIG_CAST_NEW_MEMORY) { + delete temp_object; + } + $1 = &temp; + } else + if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_interface, $descriptor(std::shared_ptr *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) { + if (!temp_interface) { + PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Interface or ModelAPI_Object."); + return NULL; + } + temp = ModelHighAPI_Reference(*temp_interface); + if (newmem & SWIG_CAST_NEW_MEMORY) { + delete temp_interface; + } + $1 = &temp; + } else + if ((SWIG_ConvertPtr($input, (void **)&$1, $1_descriptor, SWIG_POINTER_EXCEPTION)) == 0) { + } else { + PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Interface or ModelAPI_Object."); + return NULL; + } +} + +%typecheck(SWIG_TYPECHECK_POINTER) ModelHighAPI_Reference, const ModelHighAPI_Reference & { + std::shared_ptr * temp_object; + std::shared_ptr * temp_interface; + int newmem = 0; + if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_object, $descriptor(std::shared_ptr *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) { + if (temp_object) { + $1 = 1; + } else { + $1 = 0; + } + } else + if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_interface, $descriptor(std::shared_ptr *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) { + if (temp_interface) { + $1 = 1; + } else { + $1 = 0; + } + } else { + $1 = 0; + } +} + %typemap(out) const ModelHighAPI_Selection & { $1_basetype * ptr = new $1_basetype(*$1); $result = SWIG_NewPointerObj( (void*) ptr, $1_descriptor, 1 ); } +%typemap(out) const ModelHighAPI_Reference & { + $1_basetype * ptr = new $1_basetype(*$1); + $result = SWIG_NewPointerObj( (void*) ptr, $1_descriptor, 1 ); +} + // std::list -> [] %template(SelectionList) std::list; %template(RefAttrList) std::list; +%template(RefList) std::list; // all supported interfaces %include "ModelHighAPI_Double.h" %include "ModelHighAPI_Integer.h" %include "ModelHighAPI_Interface.h" %include "ModelHighAPI_RefAttr.h" +%include "ModelHighAPI_Reference.h" %include "ModelHighAPI_Selection.h" %include "ModelHighAPI_Services.h" %include "ModelHighAPI_Macro.h" diff --git a/src/ModelHighAPI/ModelHighAPI_Reference.cpp b/src/ModelHighAPI/ModelHighAPI_Reference.cpp new file mode 100644 index 000000000..3e13a0b46 --- /dev/null +++ b/src/ModelHighAPI/ModelHighAPI_Reference.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesAPI_Reference.cpp +// Created: 04 August 2016 +// Author: Mikhail Ponikarov + +//-------------------------------------------------------------------------------------- +#include "ModelHighAPI_Reference.h" + +#include +#include +#include +#include +#include "ModelHighAPI_Interface.h" +//-------------------------------------------------------------------------------------- +ModelHighAPI_Reference::ModelHighAPI_Reference() +{} + +ModelHighAPI_Reference::ModelHighAPI_Reference( + const std::shared_ptr & theValue) +: myObject(theValue) +{} + +ModelHighAPI_Reference::ModelHighAPI_Reference( + const std::shared_ptr & theValue) +: myObject(std::shared_ptr(theValue->defaultResult())) +{ +} + +ModelHighAPI_Reference::~ModelHighAPI_Reference() +{ +} + +//-------------------------------------------------------------------------------------- +void ModelHighAPI_Reference::fillAttribute( + const std::shared_ptr & theAttribute) const +{ + theAttribute->setValue(myObject); +} + +//-------------------------------------------------------------------------------------- +void ModelHighAPI_Reference::appendToList( + const std::shared_ptr & theAttribute) const +{ + theAttribute->append(myObject); +} diff --git a/src/ModelHighAPI/ModelHighAPI_Reference.h b/src/ModelHighAPI/ModelHighAPI_Reference.h new file mode 100644 index 000000000..71a6f2aca --- /dev/null +++ b/src/ModelHighAPI/ModelHighAPI_Reference.h @@ -0,0 +1,56 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesAPI_Reference.h +// Created: 04 August 2016 +// Author: Mikhail Ponikarov + +#ifndef SRC_MODELHIGHAPI_MODELHIGHAPI_REFERENCE_H_ +#define SRC_MODELHIGHAPI_MODELHIGHAPI_REFERENCE_H_ + +//-------------------------------------------------------------------------------------- +#include "ModelHighAPI.h" + +#include +#include +//-------------------------------------------------------------------------------------- +class ModelAPI_Attribute; +class ModelAPI_AttributeReference; +class ModelAPI_AttributeRefList; +class ModelAPI_Object; +class ModelHighAPI_Interface; +//-------------------------------------------------------------------------------------- +/**\class ModelHighAPI_Reference + * \ingroup CPPHighAPI + * \brief Class for filling ModelAPI_AttributeReference + */ +class ModelHighAPI_Reference +{ +public: + /// Default constructor + MODELHIGHAPI_EXPORT + ModelHighAPI_Reference(); + /// Constructor for object + MODELHIGHAPI_EXPORT + ModelHighAPI_Reference(const std::shared_ptr & theValue); + /// Constructor for Interface (use result() for object) + MODELHIGHAPI_EXPORT + ModelHighAPI_Reference(const std::shared_ptr & theValue); + /// Destructor + MODELHIGHAPI_EXPORT + virtual ~ModelHighAPI_Reference(); + + /// Fill attribute values + MODELHIGHAPI_EXPORT + virtual void fillAttribute(const std::shared_ptr & theAttribute) const; + + /// Append to list attribute + MODELHIGHAPI_EXPORT + virtual void appendToList(const std::shared_ptr & theAttribute) const; + +private: + std::shared_ptr myObject; +}; + +//-------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------- +#endif /* SRC_MODELHIGHAPI_MODELHIGHAPI_REFATTR_H_ */ diff --git a/src/ModelHighAPI/ModelHighAPI_Tools.cpp b/src/ModelHighAPI/ModelHighAPI_Tools.cpp index fb1df5c4c..be4e0186f 100644 --- a/src/ModelHighAPI/ModelHighAPI_Tools.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Tools.cpp @@ -31,6 +31,7 @@ #include "ModelHighAPI_Double.h" #include "ModelHighAPI_Integer.h" #include "ModelHighAPI_RefAttr.h" +#include "ModelHighAPI_Reference.h" #include "ModelHighAPI_Selection.h" #include @@ -104,6 +105,22 @@ void fillAttribute(const std::list & theValue, it->appendToList(theAttribute); } +//-------------------------------------------------------------------------------------- +void fillAttribute(const ModelHighAPI_Reference & theValue, + const std::shared_ptr & theAttribute) +{ + theValue.fillAttribute(theAttribute); +} + +//-------------------------------------------------------------------------------------- +void fillAttribute(const std::list & theValue, + const std::shared_ptr & theAttribute) +{ + theAttribute->clear(); + for (auto it = theValue.begin(); it != theValue.end(); ++it) + it->appendToList(theAttribute); +} + //-------------------------------------------------------------------------------------- void fillAttribute(const std::shared_ptr & theValue, const std::shared_ptr & theAttribute) @@ -120,6 +137,15 @@ void fillAttribute(const std::list > & theValue theAttribute->append(*it); } +MODELHIGHAPI_EXPORT +void fillAttribute(const std::list & theValue, + const std::shared_ptr & theAttribute) +{ + theAttribute->clear(); + for (auto it = theValue.begin(); it != theValue.end(); ++it) + theAttribute->append(it->resultSubShapePair().first); // use only context +} + //-------------------------------------------------------------------------------------- void fillAttribute(const ModelHighAPI_Selection & theValue, const std::shared_ptr & theAttribute) diff --git a/src/ModelHighAPI/ModelHighAPI_Tools.h b/src/ModelHighAPI/ModelHighAPI_Tools.h index d731086b1..f5467566d 100644 --- a/src/ModelHighAPI/ModelHighAPI_Tools.h +++ b/src/ModelHighAPI/ModelHighAPI_Tools.h @@ -41,6 +41,7 @@ class ModelAPI_Object; class ModelHighAPI_Double; class ModelHighAPI_Integer; class ModelHighAPI_RefAttr; +class ModelHighAPI_Reference; class ModelHighAPI_Selection; //-------------------------------------------------------------------------------------- MODELHIGHAPI_EXPORT @@ -84,6 +85,14 @@ MODELHIGHAPI_EXPORT void fillAttribute(const std::list & theValue, const std::shared_ptr & theAttribute); +MODELHIGHAPI_EXPORT +void fillAttribute(const ModelHighAPI_Reference & theValue, + const std::shared_ptr & theAttribute); + +MODELHIGHAPI_EXPORT +void fillAttribute(const std::list & theValue, + const std::shared_ptr & theAttribute); + MODELHIGHAPI_EXPORT void fillAttribute(const std::shared_ptr & theValue, const std::shared_ptr & theAttribute); @@ -92,6 +101,10 @@ MODELHIGHAPI_EXPORT void fillAttribute(const std::list > & theValue, const std::shared_ptr & theAttribute); +MODELHIGHAPI_EXPORT +void fillAttribute(const std::list & theValue, + const std::shared_ptr & theAttribute); + MODELHIGHAPI_EXPORT void fillAttribute(const ModelHighAPI_Selection & theValue, const std::shared_ptr & theAttribute); diff --git a/src/ModelHighAPI/ModelHighAPI_swig.h b/src/ModelHighAPI/ModelHighAPI_swig.h index 2205a8796..d430240cc 100644 --- a/src/ModelHighAPI/ModelHighAPI_swig.h +++ b/src/ModelHighAPI/ModelHighAPI_swig.h @@ -17,6 +17,7 @@ #include "ModelHighAPI_Interface.h" #include "ModelHighAPI_Macro.h" #include "ModelHighAPI_RefAttr.h" + #include "ModelHighAPI_Reference.h" #include "ModelHighAPI_Selection.h" #include "ModelHighAPI_Services.h" #include "ModelHighAPI_Tools.h" diff --git a/src/ModelHighAPI/Test/TestReference.py b/src/ModelHighAPI/Test/TestReference.py new file mode 100644 index 000000000..136894e25 --- /dev/null +++ b/src/ModelHighAPI/Test/TestReference.py @@ -0,0 +1,35 @@ +import unittest + +import ModelAPI +import ModelHighAPI +import model + +class FeaturesFixture(unittest.TestCase): + + def setUp(self): + model.begin() + # Create part + partset = model.moduleDocument() + self.part = model.addPart(partset).document() + model.do() + self.feature = model.addPoint(self.part, 0, 0, 0) + + def tearDown(self): + model.end() + model.reset() + + +class RefAttrTestCase(FeaturesFixture): + + def test_create_default(self): + ModelHighAPI.ModelHighAPI_Reference() + + def test_create_from_object(self): + ModelHighAPI.ModelHighAPI_Reference(self.feature.feature()) + + def test_create_from_None(self): + ModelHighAPI.ModelHighAPI_Reference(None) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/PythonAPI/model/features/__init__.py b/src/PythonAPI/model/features/__init__.py index b0f8a075e..9d1dd8d17 100644 --- a/src/PythonAPI/model/features/__init__.py +++ b/src/PythonAPI/model/features/__init__.py @@ -10,4 +10,5 @@ from FeaturesAPI import addPartition from FeaturesAPI import addExtrusion, addExtrusionCut, addExtrusionFuse from FeaturesAPI import addRevolution, addRevolutionCut, addRevolutionFuse -from FeaturesAPI import addGroup +from FeaturesAPI import addGroup, addRecover + diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 98c74cb2e..73321550b 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -112,7 +112,7 @@ static bool hasCoincidentPoint(FeaturePtr theFeature1, FeaturePtr theFeature2) { FeaturePtr aCoincidenceFeature = SketchPlugin_ConstraintCoincidence::findCoincidenceFeature (theFeature1, theFeature2); - return aCoincidenceFeature.get(); + return aCoincidenceFeature.get() != NULL; } bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute, -- 2.39.2