From 524d88b5c908ef4995ddd2b3975a4333a6db558d Mon Sep 17 00:00:00 2001 From: azv Date: Mon, 10 Feb 2020 15:20:22 +0300 Subject: [PATCH] General approach of versioning the feature. Update Boolean operations according. --- src/FeaturesAPI/FeaturesAPI_BooleanCommon.cpp | 49 ++----- src/FeaturesAPI/FeaturesAPI_BooleanCommon.h | 6 +- src/FeaturesAPI/FeaturesAPI_BooleanCut.cpp | 16 +-- src/FeaturesAPI/FeaturesAPI_BooleanCut.h | 3 +- src/FeaturesAPI/FeaturesAPI_BooleanFill.cpp | 18 +-- src/FeaturesAPI/FeaturesAPI_BooleanFill.h | 3 +- src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp | 60 +++------ src/FeaturesAPI/FeaturesAPI_BooleanFuse.h | 6 +- src/FeaturesAPI/FeaturesAPI_BooleanSmash.cpp | 18 +-- src/FeaturesAPI/FeaturesAPI_BooleanSmash.h | 3 +- src/FeaturesAPI/FeaturesAPI_Partition.cpp | 15 +-- src/FeaturesAPI/FeaturesAPI_Partition.h | 3 +- src/FeaturesAPI/FeaturesAPI_Union.cpp | 15 +-- src/FeaturesAPI/FeaturesAPI_Union.h | 3 +- src/FeaturesPlugin/CMakeLists.txt | 1 + .../FeaturesPlugin_BooleanCommon.cpp | 8 +- .../FeaturesPlugin_BooleanCut.cpp | 7 +- .../FeaturesPlugin_BooleanFill.cpp | 7 +- .../FeaturesPlugin_BooleanFuse.cpp | 8 +- .../FeaturesPlugin_BooleanSmash.cpp | 5 +- .../FeaturesPlugin_Partition.cpp | 5 +- src/FeaturesPlugin/FeaturesPlugin_Union.cpp | 5 +- .../FeaturesPlugin_VersionedBoolean.cpp | 27 ++-- .../FeaturesPlugin_VersionedBoolean.h | 19 +-- src/FeaturesPlugin/Test/Test3139.py | 124 ++++++++++++++++++ src/Model/Model_Data.cpp | 23 +++- src/Model/Model_Data.h | 4 + src/ModelAPI/ModelAPI_Data.h | 5 + test.hdfs/Test3139.hdf | Bin 0 -> 36866 bytes test.hdfs/Test3139.py | 37 ++++++ 30 files changed, 287 insertions(+), 216 deletions(-) create mode 100644 src/FeaturesPlugin/Test/Test3139.py create mode 100644 test.hdfs/Test3139.hdf create mode 100644 test.hdfs/Test3139.py diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanCommon.cpp b/src/FeaturesAPI/FeaturesAPI_BooleanCommon.cpp index 6b7236978..c28868287 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanCommon.cpp +++ b/src/FeaturesAPI/FeaturesAPI_BooleanCommon.cpp @@ -34,13 +34,11 @@ FeaturesAPI_BooleanCommon::FeaturesAPI_BooleanCommon( //================================================================================================== FeaturesAPI_BooleanCommon::FeaturesAPI_BooleanCommon( const std::shared_ptr& theFeature, - const std::list& theMainObjects, - const int theVersion) + const std::list& theMainObjects) : ModelHighAPI_Interface(theFeature) { if(initialize()) { fillAttribute(FeaturesPlugin_BooleanCommon::CREATION_METHOD_SIMPLE(), mycreationMethod); - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Boolean::VERSION_ID())); fillAttribute(theMainObjects, mymainObjects); execute(false); @@ -51,13 +49,11 @@ FeaturesAPI_BooleanCommon::FeaturesAPI_BooleanCommon( FeaturesAPI_BooleanCommon::FeaturesAPI_BooleanCommon( const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion) + const std::list& theToolObjects) : ModelHighAPI_Interface(theFeature) { if(initialize()) { fillAttribute(FeaturesPlugin_BooleanCommon::CREATION_METHOD_ADVANCED(), mycreationMethod); - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Boolean::VERSION_ID())); fillAttribute(theMainObjects, mymainObjects); fillAttribute(theToolObjects, mytoolObjects); @@ -115,8 +111,6 @@ void FeaturesAPI_BooleanCommon::dump(ModelHighAPI_Dumper& theDumper) const aBase->selectionList(FeaturesPlugin_BooleanCommon::OBJECT_LIST_ID()); AttributeSelectionListPtr aTools = aBase->selectionList(FeaturesPlugin_BooleanCommon::TOOL_LIST_ID()); - AttributeIntegerPtr aVersion = - aBase->integer(FeaturesPlugin_BooleanCommon::VERSION_ID()); theDumper << "(" << aDocName << ", " << anObjects; @@ -124,44 +118,25 @@ void FeaturesAPI_BooleanCommon::dump(ModelHighAPI_Dumper& theDumper) const theDumper << ", " << aTools; } - if (aVersion && aVersion->isInitialized() && - aVersion->value() == FeaturesPlugin_VersionedBoolean::THE_VERSION_1) { + if (!aBase->data()->version().empty()) theDumper << ", keepSubResults = True"; - } theDumper << ")" << std::endl; } -//================================================================================================== -static BooleanCommonPtr addCommon(const std::shared_ptr& thePart, - const std::list& theMainObjects, - const int theVersion) -{ - std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanCommon::ID()); - return BooleanCommonPtr(new FeaturesAPI_BooleanCommon(aFeature, theMainObjects, theVersion)); -} - -//================================================================================================== -static BooleanCommonPtr addCommon(const std::shared_ptr& thePart, - const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion) -{ - std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanCommon::ID()); - return BooleanCommonPtr(new FeaturesAPI_BooleanCommon(aFeature, - theMainObjects, - theToolObjects, - theVersion)); -} - //================================================================================================== BooleanCommonPtr addCommon(const std::shared_ptr& thePart, const std::list& theMainObjects, const std::list& theToolObjects, const bool keepSubResults) { - int aVersion = keepSubResults ? FeaturesPlugin_VersionedBoolean::THE_VERSION_1 - : FeaturesPlugin_VersionedBoolean::THE_VERSION_0; - return theToolObjects.empty() ? addCommon(thePart, theMainObjects, aVersion) - : addCommon(thePart, theMainObjects, theToolObjects, aVersion); + std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanCommon::ID()); + if (!keepSubResults) + aFeature->data()->setVersion(""); + BooleanCommonPtr aCommon; + if (theToolObjects.empty()) + aCommon.reset(new FeaturesAPI_BooleanCommon(aFeature, theMainObjects)); + else + aCommon.reset(new FeaturesAPI_BooleanCommon(aFeature, theMainObjects, theToolObjects)); + return aCommon; } diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanCommon.h b/src/FeaturesAPI/FeaturesAPI_BooleanCommon.h index 66d4e74cd..f7bc955be 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanCommon.h +++ b/src/FeaturesAPI/FeaturesAPI_BooleanCommon.h @@ -43,15 +43,13 @@ public: /// Constructor with values. FEATURESAPI_EXPORT FeaturesAPI_BooleanCommon(const std::shared_ptr& theFeature, - const std::list& theMainObjects, - const int theVersion = 0); + const std::list& theMainObjects); /// Constructor with values. FEATURESAPI_EXPORT FeaturesAPI_BooleanCommon(const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion = 0); + const std::list& theToolObjects); /// Destructor. FEATURESAPI_EXPORT diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanCut.cpp b/src/FeaturesAPI/FeaturesAPI_BooleanCut.cpp index 6c44139de..64b4f4d46 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanCut.cpp +++ b/src/FeaturesAPI/FeaturesAPI_BooleanCut.cpp @@ -34,12 +34,10 @@ FeaturesAPI_BooleanCut::FeaturesAPI_BooleanCut(const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion) + const std::list& theToolObjects) : ModelHighAPI_Interface(theFeature) { if(initialize()) { - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Boolean::VERSION_ID())); fillAttribute(theMainObjects, mymainObjects); fillAttribute(theToolObjects, mytoolObjects); @@ -81,13 +79,10 @@ void FeaturesAPI_BooleanCut::dump(ModelHighAPI_Dumper& theDumper) const aBase->selectionList(FeaturesPlugin_BooleanCut::OBJECT_LIST_ID()); AttributeSelectionListPtr aTools = aBase->selectionList(FeaturesPlugin_BooleanCut::TOOL_LIST_ID()); - AttributeIntegerPtr aVersion = - aBase->integer(FeaturesPlugin_BooleanCut::VERSION_ID()); theDumper << "(" << aDocName << ", " << anObjects << ", " << aTools; - if (aVersion && aVersion->isInitialized() && - aVersion->value() == FeaturesPlugin_VersionedBoolean::THE_VERSION_1) + if (!aBase->data()->version().empty()) theDumper << ", keepSubResults = True"; theDumper << ")" << std::endl; @@ -100,10 +95,9 @@ BooleanCutPtr addCut(const std::shared_ptr& thePart, const bool keepSubResults) { std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanCut::ID()); - int aVersion = keepSubResults ? FeaturesPlugin_VersionedBoolean::THE_VERSION_1 - : FeaturesPlugin_VersionedBoolean::THE_VERSION_0; + if (!keepSubResults) + aFeature->data()->setVersion(""); return BooleanCutPtr(new FeaturesAPI_BooleanCut(aFeature, theMainObjects, - theToolObjects, - aVersion)); + theToolObjects)); } diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanCut.h b/src/FeaturesAPI/FeaturesAPI_BooleanCut.h index 80beb3175..9c9c6bad3 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanCut.h +++ b/src/FeaturesAPI/FeaturesAPI_BooleanCut.h @@ -44,8 +44,7 @@ public: FEATURESAPI_EXPORT FeaturesAPI_BooleanCut(const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion = 0); + const std::list& theToolObjects); /// Destructor. FEATURESAPI_EXPORT diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanFill.cpp b/src/FeaturesAPI/FeaturesAPI_BooleanFill.cpp index da25a8b43..6bd8c314a 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanFill.cpp +++ b/src/FeaturesAPI/FeaturesAPI_BooleanFill.cpp @@ -35,12 +35,10 @@ FeaturesAPI_BooleanFill::FeaturesAPI_BooleanFill( FeaturesAPI_BooleanFill::FeaturesAPI_BooleanFill( const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion) + const std::list& theToolObjects) : ModelHighAPI_Interface(theFeature) { if(initialize()) { - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Boolean::VERSION_ID())); fillAttribute(theMainObjects, mymainObjects); fillAttribute(theToolObjects, mytoolObjects); @@ -84,13 +82,10 @@ void FeaturesAPI_BooleanFill::dump(ModelHighAPI_Dumper& theDumper) const aBase->selectionList(FeaturesPlugin_BooleanFill::OBJECT_LIST_ID()); AttributeSelectionListPtr aTools = aBase->selectionList(FeaturesPlugin_BooleanFill::TOOL_LIST_ID()); - AttributeIntegerPtr aVersion = - aBase->integer(FeaturesPlugin_BooleanFill::VERSION_ID()); theDumper << "(" << aDocName << ", " << anObjects << ", " << aTools; - if (aVersion && aVersion->isInitialized() && - aVersion->value() == FeaturesPlugin_VersionedBoolean::THE_VERSION_1) + if (!aBase->data()->version().empty()) theDumper << ", keepSubResults = True"; theDumper << ")" << std::endl; @@ -103,10 +98,7 @@ BooleanFillPtr addSplit(const std::shared_ptr& thePart, const bool keepSubResults) { std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanFill::ID()); - int aVersion = keepSubResults ? FeaturesPlugin_VersionedBoolean::THE_VERSION_1 - : FeaturesPlugin_VersionedBoolean::THE_VERSION_0; - return BooleanFillPtr(new FeaturesAPI_BooleanFill(aFeature, - theMainObjects, - theToolObjects, - aVersion)); + if (!keepSubResults) + aFeature->data()->setVersion(""); + return BooleanFillPtr(new FeaturesAPI_BooleanFill(aFeature, theMainObjects, theToolObjects)); } diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanFill.h b/src/FeaturesAPI/FeaturesAPI_BooleanFill.h index 7375db2cf..7efc0e772 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanFill.h +++ b/src/FeaturesAPI/FeaturesAPI_BooleanFill.h @@ -44,8 +44,7 @@ public: FEATURESAPI_EXPORT FeaturesAPI_BooleanFill(const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion = 0); + const std::list& theToolObjects); /// Destructor. FEATURESAPI_EXPORT diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp b/src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp index a80b06908..74d45c3be 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp +++ b/src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp @@ -35,13 +35,11 @@ FeaturesAPI_BooleanFuse::FeaturesAPI_BooleanFuse( FeaturesAPI_BooleanFuse::FeaturesAPI_BooleanFuse( const std::shared_ptr& theFeature, const std::list& theMainObjects, - const bool theRemoveEdges, - const int theVersion) + const bool theRemoveEdges) : ModelHighAPI_Interface(theFeature) { if (initialize()) { fillAttribute(FeaturesPlugin_BooleanFuse::CREATION_METHOD_SIMPLE(), mycreationMethod); - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Boolean::VERSION_ID())); fillAttribute(theMainObjects, mymainObjects); fillAttribute(theRemoveEdges, myremoveEdges); @@ -54,13 +52,11 @@ FeaturesAPI_BooleanFuse::FeaturesAPI_BooleanFuse( const std::shared_ptr& theFeature, const std::list& theMainObjects, const std::list& theToolObjects, - const bool theRemoveEdges, - const int theVersion) + const bool theRemoveEdges) : ModelHighAPI_Interface(theFeature) { if(initialize()) { fillAttribute(FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED(), mycreationMethod); - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Boolean::VERSION_ID())); fillAttribute(theMainObjects, mymainObjects); fillAttribute(theToolObjects, mytoolObjects); fillAttribute(theRemoveEdges, myremoveEdges); @@ -129,8 +125,6 @@ void FeaturesAPI_BooleanFuse::dump(ModelHighAPI_Dumper& theDumper) const aBase->selectionList(FeaturesPlugin_BooleanFuse::TOOL_LIST_ID()); AttributeBooleanPtr aRemoveEdges = aBase->boolean(FeaturesPlugin_BooleanFuse::REMOVE_INTERSECTION_EDGES_ID()); - AttributeIntegerPtr aVersion = - aBase->integer(FeaturesPlugin_BooleanFuse::VERSION_ID()); theDumper << "(" << aDocName << ", " << anObjects; @@ -142,42 +136,12 @@ void FeaturesAPI_BooleanFuse::dump(ModelHighAPI_Dumper& theDumper) const theDumper << ", removeEdges = True"; } - if (aVersion && aVersion->isInitialized() && - aVersion->value() == FeaturesPlugin_VersionedBoolean::THE_VERSION_1) { + if (!aBase->data()->version().empty()) theDumper << ", keepSubResults = True"; - } theDumper << ")" << std::endl; } -//================================================================================================== -static BooleanFusePtr addFuse(const std::shared_ptr& thePart, - const std::list& theObjects, - const bool theRemoveEdges, - const int theVersion) -{ - std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanFuse::ID()); - return BooleanFusePtr(new FeaturesAPI_BooleanFuse(aFeature, - theObjects, - theRemoveEdges, - theVersion)); -} - -//================================================================================================== -static BooleanFusePtr addFuse(const std::shared_ptr& thePart, - const std::list& theMainObjects, - const std::list& theToolObjects, - const bool theRemoveEdges, - const int theVersion) -{ - std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanFuse::ID()); - return BooleanFusePtr(new FeaturesAPI_BooleanFuse(aFeature, - theMainObjects, - theToolObjects, - theRemoveEdges, - theVersion)); -} - //================================================================================================== BooleanFusePtr addFuse(const std::shared_ptr& thePart, const std::list& theMainObjects, @@ -185,12 +149,20 @@ BooleanFusePtr addFuse(const std::shared_ptr& thePart, const bool theRemoveEdges, const bool keepSubResults) { - int aVersion = keepSubResults ? FeaturesPlugin_VersionedBoolean::THE_VERSION_1 - : FeaturesPlugin_VersionedBoolean::THE_VERSION_0; + std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanFuse::ID()); + if (!keepSubResults) + aFeature->data()->setVersion(""); + bool aRemoveEdges = theRemoveEdges; if (theToolObjects.first.empty()) aRemoveEdges = aRemoveEdges || theToolObjects.second; - return theToolObjects.first.empty() ? - addFuse(thePart, theMainObjects, aRemoveEdges, aVersion) : - addFuse(thePart, theMainObjects, theToolObjects.first, aRemoveEdges, aVersion); + + BooleanFusePtr aFuse; + if (theToolObjects.first.empty()) + aFuse.reset(new FeaturesAPI_BooleanFuse(aFeature, theMainObjects, aRemoveEdges)); + else { + aFuse.reset(new FeaturesAPI_BooleanFuse(aFeature, theMainObjects, theToolObjects.first, + aRemoveEdges)); + } + return aFuse; } diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanFuse.h b/src/FeaturesAPI/FeaturesAPI_BooleanFuse.h index 307a886bb..552f13807 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanFuse.h +++ b/src/FeaturesAPI/FeaturesAPI_BooleanFuse.h @@ -44,16 +44,14 @@ public: FEATURESAPI_EXPORT FeaturesAPI_BooleanFuse(const std::shared_ptr& theFeature, const std::list& theMainObjects, - const bool theRemoveEdges = false, - const int theVersion = 0); + const bool theRemoveEdges = false); /// Constructor with values. FEATURESAPI_EXPORT FeaturesAPI_BooleanFuse(const std::shared_ptr& theFeature, const std::list& theMainObjects, const std::list& theToolObjects, - const bool theRemoveEdges = false, - const int theVersion = 0); + const bool theRemoveEdges = false); /// Destructor. FEATURESAPI_EXPORT diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanSmash.cpp b/src/FeaturesAPI/FeaturesAPI_BooleanSmash.cpp index a91647c09..0d2abf81f 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanSmash.cpp +++ b/src/FeaturesAPI/FeaturesAPI_BooleanSmash.cpp @@ -35,12 +35,10 @@ FeaturesAPI_BooleanSmash::FeaturesAPI_BooleanSmash( FeaturesAPI_BooleanSmash::FeaturesAPI_BooleanSmash( const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion) + const std::list& theToolObjects) : ModelHighAPI_Interface(theFeature) { if(initialize()) { - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Boolean::VERSION_ID())); fillAttribute(theMainObjects, mymainObjects); fillAttribute(theToolObjects, mytoolObjects); @@ -84,13 +82,10 @@ void FeaturesAPI_BooleanSmash::dump(ModelHighAPI_Dumper& theDumper) const aBase->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()); AttributeSelectionListPtr aTools = aBase->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID()); - AttributeIntegerPtr aVersion = - aBase->integer(FeaturesPlugin_BooleanSmash::VERSION_ID()); theDumper << "(" << aDocName << ", " << anObjects << ", " << aTools; - if (aVersion && aVersion->isInitialized() && - aVersion->value() == FeaturesPlugin_VersionedBoolean::THE_VERSION_1) + if (!aBase->data()->version().empty()) theDumper << ", keepSubResults = True"; theDumper << ")" << std::endl; @@ -103,10 +98,7 @@ BooleanSmashPtr addSmash(const std::shared_ptr& thePart, const bool keepSubResults) { std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanSmash::ID()); - int aVersion = keepSubResults ? FeaturesPlugin_VersionedBoolean::THE_VERSION_1 - : FeaturesPlugin_VersionedBoolean::THE_VERSION_0; - return BooleanSmashPtr(new FeaturesAPI_BooleanSmash(aFeature, - theMainObjects, - theToolObjects, - aVersion)); + if (!keepSubResults) + aFeature->data()->setVersion(""); + return BooleanSmashPtr(new FeaturesAPI_BooleanSmash(aFeature, theMainObjects, theToolObjects)); } diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanSmash.h b/src/FeaturesAPI/FeaturesAPI_BooleanSmash.h index 46d9fd870..503255ff1 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanSmash.h +++ b/src/FeaturesAPI/FeaturesAPI_BooleanSmash.h @@ -44,8 +44,7 @@ public: FEATURESAPI_EXPORT FeaturesAPI_BooleanSmash(const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects, - const int theVersion = 0); + const std::list& theToolObjects); /// Destructor. FEATURESAPI_EXPORT diff --git a/src/FeaturesAPI/FeaturesAPI_Partition.cpp b/src/FeaturesAPI/FeaturesAPI_Partition.cpp index 8e5ac5658..6d383f422 100644 --- a/src/FeaturesAPI/FeaturesAPI_Partition.cpp +++ b/src/FeaturesAPI/FeaturesAPI_Partition.cpp @@ -32,12 +32,10 @@ FeaturesAPI_Partition::FeaturesAPI_Partition(const std::shared_ptr& theFeature, - const std::list& theBaseObjects, - const int theVersion) + const std::list& theBaseObjects) : ModelHighAPI_Interface(theFeature) { if(initialize()) { - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Partition::VERSION_ID())); setBase(theBaseObjects); } } @@ -64,13 +62,10 @@ void FeaturesAPI_Partition::dump(ModelHighAPI_Dumper& theDumper) const AttributeSelectionListPtr anAttrObjects = aBase->selectionList(FeaturesPlugin_Partition::BASE_OBJECTS_ID()); - AttributeIntegerPtr aVersion = - aBase->integer(FeaturesPlugin_Partition::VERSION_ID()); theDumper << aBase << " = model.addPartition(" << aDocName << ", " << anAttrObjects; - if (aVersion && aVersion->isInitialized() && - aVersion->value() == FeaturesPlugin_VersionedBoolean::THE_VERSION_1) + if (!aBase->data()->version().empty()) theDumper << ", keepSubResults = True"; theDumper << ")" << std::endl; @@ -81,8 +76,8 @@ PartitionPtr addPartition(const std::shared_ptr& thePart, const std::list& theBaseObjects, const bool keepSubResults) { - int aVersion = keepSubResults ? FeaturesPlugin_VersionedBoolean::THE_VERSION_1 - : FeaturesPlugin_VersionedBoolean::THE_VERSION_0; std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Partition::ID()); - return PartitionPtr(new FeaturesAPI_Partition(aFeature, theBaseObjects, aVersion)); + if (!keepSubResults) + aFeature->data()->setVersion(""); + return PartitionPtr(new FeaturesAPI_Partition(aFeature, theBaseObjects)); } diff --git a/src/FeaturesAPI/FeaturesAPI_Partition.h b/src/FeaturesAPI/FeaturesAPI_Partition.h index 392aa5907..e324b26b1 100644 --- a/src/FeaturesAPI/FeaturesAPI_Partition.h +++ b/src/FeaturesAPI/FeaturesAPI_Partition.h @@ -43,8 +43,7 @@ public: /// Constructor with values. FEATURESAPI_EXPORT explicit FeaturesAPI_Partition(const std::shared_ptr& theFeature, - const std::list& theBaseObjects, - const int theVersion = 0); + const std::list& theBaseObjects); /// Destructor. FEATURESAPI_EXPORT diff --git a/src/FeaturesAPI/FeaturesAPI_Union.cpp b/src/FeaturesAPI/FeaturesAPI_Union.cpp index bc8bc1859..7e20fb1a5 100644 --- a/src/FeaturesAPI/FeaturesAPI_Union.cpp +++ b/src/FeaturesAPI/FeaturesAPI_Union.cpp @@ -31,12 +31,10 @@ FeaturesAPI_Union::FeaturesAPI_Union(const std::shared_ptr& th //================================================================================================ FeaturesAPI_Union::FeaturesAPI_Union(const std::shared_ptr& theFeature, - const std::list& theBaseObjects, - const int theVersion) + const std::list& theBaseObjects) : ModelHighAPI_Interface(theFeature) { if(initialize()) { - fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_VersionedBoolean::VERSION_ID())); setBase(theBaseObjects); } } @@ -63,13 +61,10 @@ void FeaturesAPI_Union::dump(ModelHighAPI_Dumper& theDumper) const AttributeSelectionListPtr anAttrObjects = aBase->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID()); - AttributeIntegerPtr aVersion = - aBase->integer(FeaturesPlugin_Union::VERSION_ID()); theDumper << aBase << " = model.addUnion(" << aDocName << ", " << anAttrObjects; - if (aVersion && aVersion->isInitialized() && - aVersion->value() == FeaturesPlugin_VersionedBoolean::THE_VERSION_1) + if (!aBase->data()->version().empty()) theDumper << ", keepSubResults = True"; theDumper << ")" << std::endl; @@ -80,8 +75,8 @@ UnionPtr addUnion(const std::shared_ptr& thePart, const std::list& theBaseObjects, const bool keepSubResults) { - int aVersion = keepSubResults ? FeaturesPlugin_VersionedBoolean::THE_VERSION_1 - : FeaturesPlugin_VersionedBoolean::THE_VERSION_0; std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Union::ID()); - return UnionPtr(new FeaturesAPI_Union(aFeature, theBaseObjects, aVersion)); + if (!keepSubResults) + aFeature->data()->setVersion(""); + return UnionPtr(new FeaturesAPI_Union(aFeature, theBaseObjects)); } diff --git a/src/FeaturesAPI/FeaturesAPI_Union.h b/src/FeaturesAPI/FeaturesAPI_Union.h index bcc6aee2e..693a06b5e 100644 --- a/src/FeaturesAPI/FeaturesAPI_Union.h +++ b/src/FeaturesAPI/FeaturesAPI_Union.h @@ -43,8 +43,7 @@ public: /// Constructor with values. FEATURESAPI_EXPORT explicit FeaturesAPI_Union(const std::shared_ptr& theFeature, - const std::list& theBaseObjects, - const int theVersion = 0); + const std::list& theBaseObjects); /// Destructor. FEATURESAPI_EXPORT diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index f307e317b..bdca89390 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -568,4 +568,5 @@ ADD_UNIT_TESTS(TestExtrusion.py TestDefeaturing_OnCompound.py Test3137_1.py Test3137_2.py + Test3139.py ) diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp index 1afe60e8b..be2c09a50 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp @@ -52,7 +52,7 @@ void FeaturesPlugin_BooleanCommon::initAttributes() data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); data()->addAttribute(TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); - initVersion(THE_VERSION_1, selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); + initVersion(BOP_VERSION_9_4(), selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); } //================================================================================================== @@ -87,7 +87,7 @@ void FeaturesPlugin_BooleanCommon::execute() } // version of COMMON feature - int aCommonVersion = version(); + const std::string aCommonVersion = data()->version(); int aResultIndex = 0; GeomShapePtr aResultCompound; @@ -115,7 +115,7 @@ void FeaturesPlugin_BooleanCommon::execute() aMakeShapeList->appendAlgo(aCommonAlgo); } - if (aCommonVersion == THE_VERSION_1) { + if (aCommonVersion == BOP_VERSION_9_4()) { // merge hierarchies of compounds containing objects and tools // and append the result of the FUSE operation aShape = keepUnusedSubsOfCompound(aShape, anObjects, aTools, aMakeShapeList); @@ -147,7 +147,7 @@ void FeaturesPlugin_BooleanCommon::execute() aResultShapesList.push_back(aShape); } } else { - if (aCommonVersion == THE_VERSION_1) { + if (aCommonVersion == BOP_VERSION_9_4()) { // merge hierarchies of compounds containing objects and tools aResultCompound = keepUnusedSubsOfCompound(GeomShapePtr(), anObjects, aTools, aMakeShapeList); diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp index d954e917d..bc67a28e1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp @@ -45,7 +45,7 @@ FeaturesPlugin_BooleanCut::FeaturesPlugin_BooleanCut() void FeaturesPlugin_BooleanCut::initAttributes() { FeaturesPlugin_Boolean::initAttributes(); - initVersion(THE_VERSION_1, selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); + initVersion(BOP_VERSION_9_4(), selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); } //================================================================================================== @@ -67,9 +67,6 @@ void FeaturesPlugin_BooleanCut::execute() return; } - // version of CUT feature - int aCutVersion = version(); - std::vector aResultBaseAlgoList; ListOfShape aResultShapesList; std::string anError; @@ -77,7 +74,7 @@ void FeaturesPlugin_BooleanCut::execute() std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); GeomShapePtr aResultCompound; - if (aCutVersion == THE_VERSION_1) { + if (data()->version() == BOP_VERSION_9_4()) { // merge hierarchies of compounds containing objects and tools aResultCompound = keepUnusedSubsOfCompound(GeomShapePtr(), anObjects, aTools, aMakeShapeList); diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp index 6db4eb4d9..3f6dd4cc0 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp @@ -50,7 +50,7 @@ FeaturesPlugin_BooleanFill::FeaturesPlugin_BooleanFill() void FeaturesPlugin_BooleanFill::initAttributes() { FeaturesPlugin_Boolean::initAttributes(); - initVersion(THE_VERSION_1, selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); + initVersion(BOP_VERSION_9_4(), selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); } //================================================================================================= @@ -78,16 +78,13 @@ void FeaturesPlugin_BooleanFill::execute() return; } - // version of Split feature - int aSplitVersion = version(); - std::vector aResultBaseAlgoList; ListOfShape aResultShapesList; std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); GeomShapePtr aResultCompound; - if (aSplitVersion == THE_VERSION_1) { + if (data()->version() == BOP_VERSION_9_4()) { // merge hierarchies of compounds containing objects and tools aResultCompound = keepUnusedSubsOfCompound(GeomShapePtr(), anObjects, aTools, aMakeShapeList); diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp index 242629097..a7a1b0cc1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp @@ -60,7 +60,7 @@ void FeaturesPlugin_BooleanFuse::initAttributes() ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID()); - initVersion(THE_VERSION_1, selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); + initVersion(BOP_VERSION_9_4(), selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); } //================================================================================================== @@ -102,7 +102,7 @@ void FeaturesPlugin_BooleanFuse::execute() } // version of FUSE feature - int aFuseVersion = version(); + const std::string aFuseVersion = data()->version(); // Collecting all solids which will be fused. ListOfShape aSolidsToFuse; @@ -111,7 +111,7 @@ void FeaturesPlugin_BooleanFuse::execute() // Collecting solids from compsolids which will not be modified // in boolean operation and will be added to result. - bool isProcessCompsolid = !isSimpleCreation || aFuseVersion >= THE_VERSION_1; + bool isProcessCompsolid = !isSimpleCreation || !aFuseVersion.empty(); ListOfShape aShapesToAdd; for (ObjectHierarchy::Iterator anObjectsIt = anObjectsHierarchy.Begin(); isProcessCompsolid && anObjectsIt != anObjectsHierarchy.End(); @@ -234,7 +234,7 @@ void FeaturesPlugin_BooleanFuse::execute() aMakeShapeList->appendAlgo(aUnifyAlgo); } - if (aFuseVersion == THE_VERSION_1) { + if (aFuseVersion == BOP_VERSION_9_4()) { // merge hierarchies of compounds containing objects and tools // and append the result of the FUSE operation aShape = keepUnusedSubsOfCompound(aShape, anObjectsHierarchy, aToolsHierarchy, aMakeShapeList); diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp index 11b47079e..9d053f0e9 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp @@ -47,7 +47,7 @@ void FeaturesPlugin_BooleanSmash::initAttributes() data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); data()->addAttribute(TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); - initVersion(THE_VERSION_1, selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); + initVersion(BOP_VERSION_9_4(), selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); } //================================================================================================== @@ -167,8 +167,7 @@ void FeaturesPlugin_BooleanSmash::execute() } // take into account a version of SMASH feature - int aSmashVersion = version(); - if (aSmashVersion == THE_VERSION_1) { + if (data()->version() == BOP_VERSION_9_4()) { // merge hierarchies of compounds containing objects and tools // and append the result of the FUSE operation aShape = keepUnusedSubsOfCompound(aShape, anObjectsHistory, aToolsHistory, aMakeShapeList); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp index 824a9cb46..58b3784e9 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp @@ -58,7 +58,7 @@ FeaturesPlugin_Partition::FeaturesPlugin_Partition() void FeaturesPlugin_Partition::initAttributes() { data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); - initVersion(THE_VERSION_1, selectionList(BASE_OBJECTS_ID())); + initVersion(BOP_VERSION_9_4(), selectionList(BASE_OBJECTS_ID())); } //================================================================================================= @@ -124,8 +124,7 @@ void FeaturesPlugin_Partition::execute() int aResultIndex = 0; - int aPartitionVersion = version(); - if (aPartitionVersion < THE_VERSION_1) { + if (data()->version().empty()) { // default behaviors of Partition if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) { for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Union.cpp b/src/FeaturesPlugin/FeaturesPlugin_Union.cpp index 5663d6918..0a3107b76 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Union.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Union.cpp @@ -42,7 +42,7 @@ FeaturesPlugin_Union::FeaturesPlugin_Union() void FeaturesPlugin_Union::initAttributes() { data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); - initVersion(THE_VERSION_1, selectionList(BASE_OBJECTS_ID())); + initVersion(BOP_VERSION_9_4(), selectionList(BASE_OBJECTS_ID())); } //================================================================================================= @@ -65,7 +65,6 @@ void FeaturesPlugin_Union::execute() std::vector aResultBaseAlgoList; ListOfShape aResultShapesList; - int aUnionVersion = version(); GeomShapePtr aResultCompound = GeomAlgoAPI_CompoundBuilder::compound(ListOfShape()); // Fuse objects. @@ -102,7 +101,7 @@ void FeaturesPlugin_Union::execute() GeomShapePtr aShape; GeomAPI_ShapeIterator aCIt(aResultCompound); - if (aUnionVersion < THE_VERSION_1) { + if (data()->version().empty()) { // if the compound consists of a single sub-shape, take it, // otherwise, take the full compound aShape = aCIt.current(); diff --git a/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp index ea18dd5a9..bba9645aa 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp @@ -71,19 +71,20 @@ static void performBoolean(const GeomAlgoAPI_Tools::BOPType theBooleanType, } //================================================================================================= -void FeaturesPlugin_VersionedBoolean::initVersion(const int theVersion, +void FeaturesPlugin_VersionedBoolean::initVersion(const std::string& theVersion, const AttributePtr theObjectsAttr, const AttributePtr theToolsAttr) { - AttributePtr aVerAttr = data()->addAttribute(VERSION_ID(), ModelAPI_AttributeInteger::typeId()); - aVerAttr->setIsArgument(false); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VERSION_ID()); - if (!integer(VERSION_ID())->isInitialized() && - (!theObjectsAttr || !theObjectsAttr->isInitialized()) && - (!theToolsAttr || !theToolsAttr->isInitialized())) { + AttributeIntegerPtr anOldVersionAttr = integer("version"); + if (anOldVersionAttr && anOldVersionAttr->isInitialized() && data()->version().empty()) { + // move value to the common version interface in ModelAPI_Data + data()->setVersion(BOP_VERSION_9_4()); + } + else if ((!theObjectsAttr || !theObjectsAttr->isInitialized()) && + (!theToolsAttr || !theToolsAttr->isInitialized())) { // this is a newly created feature (not read from file), // so, initialize the latest version - integer(VERSION_ID())->setValue(theVersion); + data()->setVersion(theVersion); } } @@ -450,16 +451,6 @@ void FeaturesPlugin_VersionedBoolean::resizePlanes( } } -//================================================================================================= -int FeaturesPlugin_VersionedBoolean::version() -{ - AttributeIntegerPtr aVersionAttr = integer(VERSION_ID()); - int aVersion = 0; - if (aVersionAttr && aVersionAttr->isInitialized()) - aVersion = aVersionAttr->value(); - return aVersion; -} - //================================================================================================= void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::AddObject(const GeomShapePtr& theObject) diff --git a/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h b/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h index 21db544d7..098509c3c 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h @@ -36,26 +36,20 @@ class GeomAlgoAPI_MakeShapeList; /// \brief Feature controls a version of Boolean operations. class FeaturesPlugin_VersionedBoolean : public ModelAPI_Feature { -public: - static const int THE_VERSION_0 = 0; - static const int THE_VERSION_1 = 20190506; - - /// Attribute name of the version of Boolean feature - inline static const std::string& VERSION_ID() +protected: + static const std::string& BOP_VERSION_9_4() { - static const std::string MY_VERSION_ID("version"); - return MY_VERSION_ID; + static const std::string VERSION("v9.4"); + return VERSION; } -protected: - /// Use plugin manager for features creation. FeaturesPlugin_VersionedBoolean() {} /// Initialize version field of the Boolean feature. /// The version is initialized for newly created features, /// not read from previously stored document. - void initVersion(const int theVersion, + void initVersion(const std::string& theVersion, const std::shared_ptr theObjectsAttr = std::shared_ptr(), const std::shared_ptr theToolsAttr @@ -203,9 +197,6 @@ protected: const ObjectHierarchy& theToolsHierarchy, std::shared_ptr theMakeShapeList); - /// Return version of the feature - int version(); - private: void parentForShape(const GeomShapePtr& theShape, const std::shared_ptr& theContext, diff --git a/src/FeaturesPlugin/Test/Test3139.py b/src/FeaturesPlugin/Test/Test3139.py new file mode 100644 index 000000000..351bebad0 --- /dev/null +++ b/src/FeaturesPlugin/Test/Test3139.py @@ -0,0 +1,124 @@ +# Copyright (C) 2020 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(52.9121725731895, 8.799859429739596, 7.781201848998454, 8.799859429739596) +SketchLine_2 = Sketch_1.addLine(7.781201848998454, 8.799859429739596, 7.781201848998454, 36.33111129445148) +SketchLine_3 = Sketch_1.addLine(7.781201848998454, 36.33111129445148, 52.9121725731895, 36.33111129445148) +SketchLine_4 = Sketch_1.addLine(52.9121725731895, 36.33111129445148, 52.9121725731895, 8.799859429739596) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +SketchLine_5 = Sketch_1.addLine(29.87981510015411, 36.33111129445148, 29.87981510015411, 8.799859429739596) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.startPoint(), SketchLine_3.result()) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_1.result()) +SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_5.result()) +SketchCircle_1 = Sketch_1.addCircle(88.70570107858241, 30.96918335901386, 15.95582825781952) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 20, 0) +Compound_1 = model.addCompound(Part_1_doc, [model.selection("COMPSOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2")]) +Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOY")) +SketchLine_6 = Sketch_2.addLine(91.78842679005474, 52.44197384283513, 18.42664179347724, 52.44197384283513) +SketchLine_7 = Sketch_2.addLine(18.42664179347724, 52.44197384283513, 18.42664179347724, 23.73518840939176) +SketchLine_8 = Sketch_2.addLine(18.42664179347724, 23.73518840939176, 91.78842679005474, 23.73518840939176) +SketchLine_9 = Sketch_2.addLine(91.78842679005474, 23.73518840939176, 91.78842679005474, 52.44197384283513) +SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint()) +SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_6.result()) +SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_7.result()) +SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_8.result()) +SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_9.result()) +model.do() +Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_6r-SketchLine_7f-SketchLine_8f-SketchLine_9f")], model.selection(), 10, 0) +Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Compound_1_1_1_1")], [model.selection("SOLID", "Extrusion_2_1")]) +model.do() + +Part_2 = model.addPart(partSet) +Part_2_doc = Part_2.document() +Sketch_3 = model.addSketch(Part_2_doc, model.defaultPlane("XOY")) +SketchLine_10 = Sketch_3.addLine(52.9121725731895, 8.799859429739596, 7.781201848998454, 8.799859429739596) +SketchLine_11 = Sketch_3.addLine(7.781201848998454, 8.799859429739596, 7.781201848998454, 36.33111129445148) +SketchLine_12 = Sketch_3.addLine(7.781201848998454, 36.33111129445148, 52.9121725731895, 36.33111129445148) +SketchLine_13 = Sketch_3.addLine(52.9121725731895, 36.33111129445148, 52.9121725731895, 8.799859429739596) +SketchConstraintCoincidence_11 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchLine_10.startPoint()) +SketchConstraintCoincidence_12 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint()) +SketchConstraintCoincidence_13 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint()) +SketchConstraintCoincidence_14 = Sketch_3.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint()) +SketchConstraintHorizontal_5 = Sketch_3.setHorizontal(SketchLine_10.result()) +SketchConstraintVertical_6 = Sketch_3.setVertical(SketchLine_11.result()) +SketchConstraintHorizontal_6 = Sketch_3.setHorizontal(SketchLine_12.result()) +SketchConstraintVertical_7 = Sketch_3.setVertical(SketchLine_13.result()) +SketchLine_14 = Sketch_3.addLine(29.87981510015411, 36.33111129445148, 29.87981510015411, 8.799859429739596) +SketchConstraintCoincidence_15 = Sketch_3.setCoincident(SketchLine_14.startPoint(), SketchLine_12.result()) +SketchConstraintCoincidence_16 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchLine_10.result()) +SketchConstraintVertical_8 = Sketch_3.setVertical(SketchLine_14.result()) +SketchCircle_2 = Sketch_3.addCircle(88.70570107858241, 30.96918335901386, 15.95582825781952) +model.do() +Extrusion_3 = model.addExtrusion(Part_2_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 20, 0) +Compound_2 = model.addCompound(Part_2_doc, [model.selection("COMPSOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2")]) +Sketch_4 = model.addSketch(Part_2_doc, model.standardPlane("XOY")) +SketchLine_15 = Sketch_4.addLine(91.78842679005474, 52.44197384283513, 18.42664179347724, 52.44197384283513) +SketchLine_16 = Sketch_4.addLine(18.42664179347724, 52.44197384283513, 18.42664179347724, 23.73518840939176) +SketchLine_17 = Sketch_4.addLine(18.42664179347724, 23.73518840939176, 91.78842679005474, 23.73518840939176) +SketchLine_18 = Sketch_4.addLine(91.78842679005474, 23.73518840939176, 91.78842679005474, 52.44197384283513) +SketchConstraintCoincidence_17 = Sketch_4.setCoincident(SketchLine_18.endPoint(), SketchLine_15.startPoint()) +SketchConstraintCoincidence_18 = Sketch_4.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint()) +SketchConstraintCoincidence_19 = Sketch_4.setCoincident(SketchLine_16.endPoint(), SketchLine_17.startPoint()) +SketchConstraintCoincidence_20 = Sketch_4.setCoincident(SketchLine_17.endPoint(), SketchLine_18.startPoint()) +SketchConstraintHorizontal_7 = Sketch_4.setHorizontal(SketchLine_15.result()) +SketchConstraintVertical_9 = Sketch_4.setVertical(SketchLine_16.result()) +SketchConstraintHorizontal_8 = Sketch_4.setHorizontal(SketchLine_17.result()) +SketchConstraintVertical_10 = Sketch_4.setVertical(SketchLine_18.result()) +model.do() +Extrusion_4 = model.addExtrusion(Part_2_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_6r-SketchLine_7f-SketchLine_8f-SketchLine_9f")], model.selection(), 10, 0) +Cut_2 = model.addCut(Part_2_doc, [model.selection("SOLID", "Compound_1_1_1_1")], [model.selection("SOLID", "Extrusion_2_1")], keepSubResults = True) +model.do() + +model.end() + +from GeomAPI import * + +model.testNbResults(Part_1, 1) +model.testNbSubResults(Part_1, [0]) +model.testNbSubShapes(Part_1, GeomAPI_Shape.SOLID, [2]) +model.testNbSubShapes(Part_1, GeomAPI_Shape.FACE, [16]) +model.testNbSubShapes(Part_1, GeomAPI_Shape.EDGE, [74]) +model.testNbSubShapes(Part_1, GeomAPI_Shape.VERTEX, [148]) +model.testResultsVolumes(Part_1, [23407.60956]) + +model.testNbResults(Part_2, 1) +model.testNbSubResults(Part_2, [0]) +model.testNbSubShapes(Part_2, GeomAPI_Shape.SOLID, [3]) +model.testNbSubShapes(Part_2, GeomAPI_Shape.FACE, [19]) +model.testNbSubShapes(Part_2, GeomAPI_Shape.EDGE, [80]) +model.testNbSubShapes(Part_2, GeomAPI_Shape.VERTEX, [160]) +model.testResultsVolumes(Part_2, [39403.873983562]) diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 2a25c5136..a47d95c2f 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -77,7 +77,7 @@ static const int kFlagDisplayed = 1; static const int kFlagDeleted = 2; // TDataStd_Integer - 0 if the name of the object is generated automatically, // otherwise the name is defined by user -Standard_GUID kUSER_DEFINED_NAME("9c694d18-a83c-4a56-bc9b-8020628a8244"); +static const Standard_GUID kUSER_DEFINED_NAME("9c694d18-a83c-4a56-bc9b-8020628a8244"); // invalid data const static std::shared_ptr kInvalid(new Model_Data()); @@ -85,6 +85,9 @@ const static std::shared_ptr kInvalid(new Model_Data()); static const Standard_GUID kGroupAttributeGroupID("df64ea4c-fc42-4bf8-ad7e-08f7a54bf1b8"); static const Standard_GUID kGroupAttributeID("ebdcb22a-e045-455b-9a7f-cfd38d68e185"); +// id of attribute to store the version of the feature +static const Standard_GUID kVERSION_ID("61cdb78a-1ba7-4942-976f-63bea7f4a2b1"); + Model_Data::Model_Data() : mySendAttributeUpdated(true), myWasChangedButBlocked(false) { @@ -158,6 +161,24 @@ bool Model_Data::hasUserDefinedName() const return shapeLab().IsAttribute(kUSER_DEFINED_NAME); } +std::string Model_Data::version() +{ + Handle(TDataStd_Name) aVersionAttr; + std::string aVersion; + if (shapeLab().FindAttribute(kVERSION_ID, aVersionAttr)) + aVersion = TCollection_AsciiString(aVersionAttr->Get()).ToCString(); + return aVersion; +} + +void Model_Data::setVersion(const std::string& theVersion) +{ + Handle(TDataStd_Name) aVersionAttr; + std::string aVersion; + if (!shapeLab().FindAttribute(kVERSION_ID, aVersionAttr)) + aVersionAttr = TDataStd_Name::Set(shapeLab(), kVERSION_ID, TCollection_ExtendedString()); + aVersionAttr->Set(theVersion.c_str()); +} + AttributePtr Model_Data::addAttribute( const std::string& theID, const std::string theAttrType, const int theIndex) { diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index 7f9fa9b01..fa833bdd3 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -107,6 +107,10 @@ class Model_Data : public ModelAPI_Data MODEL_EXPORT virtual void setName(const std::string& theName); /// Return \c true if the object has been renamed by the user MODEL_EXPORT virtual bool hasUserDefinedName() const; + /// Returns version of the feature (empty string if not applicable) + MODEL_EXPORT virtual std::string version(); + /// Initialize the version of the feature + MODEL_EXPORT virtual void setVersion(const std::string& theVersion); /// Returns the attribute that references to another document MODEL_EXPORT virtual std::shared_ptr document(const std::string& theID); /// Returns the attribute that contains real value with double precision diff --git a/src/ModelAPI/ModelAPI_Data.h b/src/ModelAPI/ModelAPI_Data.h index de771058d..bed7201ac 100644 --- a/src/ModelAPI/ModelAPI_Data.h +++ b/src/ModelAPI/ModelAPI_Data.h @@ -78,6 +78,11 @@ class MODELAPI_EXPORT ModelAPI_Data /// Return \c true if the object has been renamed by the user virtual bool hasUserDefinedName() const = 0; + /// Returns version of the feature (empty string if not applicable) + virtual std::string version() = 0; + /// Initialize the version of the feature + virtual void setVersion(const std::string& theVersion) = 0; + /// Returns the attribute that references to another document virtual std::shared_ptr document(const std::string& theID) = 0; /// Returns the attribute that contains real value with double precision diff --git a/test.hdfs/Test3139.hdf b/test.hdfs/Test3139.hdf new file mode 100644 index 0000000000000000000000000000000000000000..cbd6dd31a17efde5cf77bdba405793672dd5d5e3 GIT binary patch literal 36866 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