From 3e67d539ff2a32111d8559201692fa04157fbc3b Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 14 Nov 2017 09:37:35 +0300 Subject: [PATCH] Task 2.1. Management of result names Improve checking default names when dumping to Python --- src/Model/Model_Data.cpp | 4 +- src/Model/Model_Data.h | 4 +- src/Model/Model_Objects.cpp | 68 +--------------- src/ModelAPI/CMakeLists.txt | 1 + src/ModelAPI/ModelAPI_Data.h | 4 + src/ModelAPI/ModelAPI_Tools.cpp | 79 +++++++++++++++++++ src/ModelAPI/ModelAPI_Tools.h | 5 ++ .../Test/TestCustomName_DefaultName.py | 35 ++++++++ src/ModelHighAPI/ModelHighAPI_Dumper.cpp | 39 +++------ 9 files changed, 141 insertions(+), 98 deletions(-) create mode 100644 src/ModelAPI/Test/TestCustomName_DefaultName.py diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 32c921554..9911a7964 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -754,8 +754,8 @@ std::shared_ptr Model_Data::owner() return myObject; } -bool Model_Data::isEarlierAttribute(const std::string& theAttribute1, - const std::string& theAttribute2) const +bool Model_Data::isPrecedingAttribute(const std::string& theAttribute1, + const std::string& theAttribute2) const { AttributeMap::const_iterator aFound1 = myAttrs.find(theAttribute1); AttributeMap::const_iterator aFound2 = myAttrs.find(theAttribute2); diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index d46c13c31..186cfefc2 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -295,8 +295,8 @@ private: MODEL_EXPORT virtual void setDisplayed(const bool theDisplay); /// Returns \c true if theAttribute1 is going earlier than theAttribute2 in the data - bool isEarlierAttribute(const std::string& theAttribute1, - const std::string& theAttribute2) const; + MODEL_EXPORT virtual bool isPrecedingAttribute(const std::string& theAttribute1, + const std::string& theAttribute2) const; }; /// Generic method to register back reference, used in referencing attributes. diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 373e5ff14..e1636118d 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -933,35 +933,16 @@ TDF_Label Model_Objects::resultLabel( return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1); } - -// Obtain an index of result in the CompSolid (return 0 if the indexing is not necessary) -static int subResultIndex(const FeaturePtr& theFeature, const ResultPtr& theResult) -{ - int anIndex = 0; - const std::list& aResults = theFeature->results(); - for (std::list::const_iterator aResIt = aResults.begin(); - aResIt != aResults.end(); ++aResIt) { - ResultCompSolidPtr aCompSolidRes = - std::dynamic_pointer_cast(*aResIt); - if (aCompSolidRes && aCompSolidRes->isSub(theResult, anIndex)) - break; - } - return anIndex; -} - bool Model_Objects::hasCustomName(DataPtr theFeatureData, ResultPtr theResult, int theResultIndex, std::string& theParentName) const { - typedef std::list< std::pair < std::string, std::list > > ListOfReferences; - - SessionPtr aSession = ModelAPI_Session::get(); - FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner()); - ResultCompSolidPtr aCompSolidRes = std::dynamic_pointer_cast(theFeatureData->owner()); if (aCompSolidRes) { + FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner()); + // names of sub-solids in CompSolid should be default (for example, // result of boolean operation 'Boolean_1' is a CompSolid which is renamed to 'MyBOOL', // however, sub-elements of 'MyBOOL' should be named 'Boolean_1_1', 'Boolean_1_2' etc.) @@ -979,49 +960,8 @@ bool Model_Objects::hasCustomName(DataPtr theFeatureData, return false; } - std::shared_ptr aData = std::dynamic_pointer_cast(anOwner->data()); - - ListOfReferences aReferences; - aData->referencesToObjects(aReferences); - - // find first result with user-defined name - ListOfReferences::const_iterator aFoundRef = aReferences.end(); - for (ListOfReferences::const_iterator aRefIt = aReferences.begin(); - aRefIt != aReferences.end(); ++aRefIt) { - if (aSession->validators()->isConcealed(anOwner->getKind(), aRefIt->first)) { - // check the referred object is a Body - // (for example, ExtrusionCut has a sketch as a first attribute which is concealing) - bool isBody = aRefIt->second.size() > 1 || (aRefIt->second.size() == 1 && - aRefIt->second.front()->groupName() == ModelAPI_ResultBody::group()); - if (isBody && (aFoundRef == aReferences.end() || - aData->isEarlierAttribute(aRefIt->first, aFoundRef->first))) - aFoundRef = aRefIt; - } - } - - // find an object which is concealed by theResult - if (aFoundRef != aReferences.end() && !aFoundRef->second.empty()) { - std::list::const_iterator anObjIt = aFoundRef->second.begin(); - while (--theResultIndex >= 0) { - ++anObjIt; - if (anObjIt == aFoundRef->second.end()) { - anObjIt = aFoundRef->second.begin(); - break; - } - } - // check the result is a Body - if ((*anObjIt)->groupName() == ModelAPI_ResultBody::group()) { - // check the result is part of CompSolid - ResultPtr anObjRes = std::dynamic_pointer_cast(*anObjIt); - ResultCompSolidPtr aParentCompSolid = ModelAPI_Tools::compSolidOwner(anObjRes); - if (aParentCompSolid) - anObjRes = aParentCompSolid; - theParentName = anObjRes->data()->name(); - return true; - } - } - - return false; + theParentName = ModelAPI_Tools::getDefaultName(theResult, theResultIndex); + return true; } void Model_Objects::storeResult(std::shared_ptr theFeatureData, diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index 94462f161..8e809227a 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -176,6 +176,7 @@ ADD_UNIT_TESTS(TestConstants.py TestCustomName_CommonCompSolid.py TestCustomName_CutCompSolid.py TestCustomName_CutGroup.py + TestCustomName_DefaultName.py TestCustomName_ExtrudeFace.py TestCustomName_ExtrusionCut.py TestCustomName_MultiTranslation.py diff --git a/src/ModelAPI/ModelAPI_Data.h b/src/ModelAPI/ModelAPI_Data.h index c28a1ae88..e1848123e 100644 --- a/src/ModelAPI/ModelAPI_Data.h +++ b/src/ModelAPI/ModelAPI_Data.h @@ -199,6 +199,10 @@ class MODELAPI_EXPORT ModelAPI_Data /// Sets true if the object is deleted, but some data is still keept in memory virtual void setIsDeleted(const bool theFlag) = 0; + /// Returns \c true if theAttribute1 is going earlier than theAttribute2 in the data + virtual bool isPrecedingAttribute(const std::string& theAttribute1, + const std::string& theAttribute2) const = 0; + protected: /// Objects are created for features automatically ModelAPI_Data(); diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index 3be42d1f4..7956c4dbb 100755 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -622,4 +623,82 @@ void getConcealedResults(const FeaturePtr& theFeature, } } +std::string getDefaultName(const std::shared_ptr& theResult, + const int theResultIndex) +{ + typedef std::list< std::pair < std::string, std::list > > ListOfReferences; + + SessionPtr aSession = ModelAPI_Session::get(); + FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner()); + + ResultCompSolidPtr aCompSolidRes = compSolidOwner(theResult); + if (aCompSolidRes) { + // names of sub-solids in CompSolid should be default (for example, + // result of boolean operation 'Boolean_1_1' is a CompSolid which is renamed to 'MyBOOL', + // however, sub-elements of 'MyBOOL' should be named 'Boolean_1_1_1', 'Boolean_1_1_2' etc.) + std::ostringstream aDefaultName; + aDefaultName << anOwner->name(); + // compute default name of CompSolid (name of feature + index of CompSolid's result) + int aCompSolidResultIndex = 0; + const std::list& aResults = anOwner->results(); + for (std::list::const_iterator anIt = aResults.begin(); + anIt != aResults.end(); ++anIt, ++aCompSolidResultIndex) + if (aCompSolidRes == *anIt) + break; + aDefaultName << "_" << (aCompSolidResultIndex + 1) << "_" << (theResultIndex + 1); + return aDefaultName.str(); + } + + DataPtr aData = anOwner->data(); + + ListOfReferences aReferences; + aData->referencesToObjects(aReferences); + + // find first result with user-defined name + ListOfReferences::const_iterator aFoundRef = aReferences.end(); + for (ListOfReferences::const_iterator aRefIt = aReferences.begin(); + aRefIt != aReferences.end(); ++aRefIt) { + if (aSession->validators()->isConcealed(anOwner->getKind(), aRefIt->first)) { + // check the referred object is a Body + // (for example, ExtrusionCut has a sketch as a first attribute which is concealing) + bool isBody = aRefIt->second.size() > 1 || (aRefIt->second.size() == 1 && + aRefIt->second.front()->groupName() == ModelAPI_ResultBody::group()); + if (isBody && (aFoundRef == aReferences.end() || + aData->isPrecedingAttribute(aRefIt->first, aFoundRef->first))) + aFoundRef = aRefIt; + } + } + + // find an object which is concealed by theResult + if (aFoundRef != aReferences.end() && !aFoundRef->second.empty()) { + std::list::const_iterator anObjIt = aFoundRef->second.begin(); + int aResultIndex = theResultIndex; + while (--aResultIndex >= 0) { + ++anObjIt; + if (anObjIt == aFoundRef->second.end()) { + anObjIt = aFoundRef->second.begin(); + break; + } + } + // check the result is a Body + if ((*anObjIt)->groupName() == ModelAPI_ResultBody::group()) { + // check the result is part of CompSolid + ResultPtr anObjRes = std::dynamic_pointer_cast(*anObjIt); + ResultCompSolidPtr aParentCompSolid = ModelAPI_Tools::compSolidOwner(anObjRes); + if (aParentCompSolid) + anObjRes = aParentCompSolid; + return anObjRes->data()->name(); + } + } + + // compose default name by the name of the feature and the index of result + std::stringstream aDefaultName; + aDefaultName << anOwner->name(); + // if there are several results (issue #899: any number of result), + // add unique prefix starting from second + if (theResultIndex > 0 || theResult->groupName() == ModelAPI_ResultBody::group()) + aDefaultName << "_" << theResultIndex + 1; + return aDefaultName.str(); +} + } // namespace ModelAPI_Tools diff --git a/src/ModelAPI/ModelAPI_Tools.h b/src/ModelAPI/ModelAPI_Tools.h index c119924cb..1a2db5e05 100755 --- a/src/ModelAPI/ModelAPI_Tools.h +++ b/src/ModelAPI/ModelAPI_Tools.h @@ -186,6 +186,11 @@ MODELAPI_EXPORT void findRefsToFeatures( */ MODELAPI_EXPORT void getConcealedResults(const std::shared_ptr& theFeature, std::list >& theResults); + +/*! Return the default name of the result according the the features it depends. + */ +MODELAPI_EXPORT std::string getDefaultName(const std::shared_ptr& theResult, + const int theResultIndex); } #endif diff --git a/src/ModelAPI/Test/TestCustomName_DefaultName.py b/src/ModelAPI/Test/TestCustomName_DefaultName.py new file mode 100644 index 000000000..f1149d712 --- /dev/null +++ b/src/ModelAPI/Test/TestCustomName_DefaultName.py @@ -0,0 +1,35 @@ +## Copyright (C) 2014-2017 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() +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), 10) +Boolean_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("SOLID", "Sphere_1_1")]) +Boolean_1.result().setName("Boolean_1_1") +model.do() + +model.end() + +assert(model.checkPythonDump()) diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp index ba329d412..230f12b3b 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include @@ -191,29 +192,16 @@ const std::string& ModelHighAPI_Dumper::parentName(const FeaturePtr& theEntity) void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature) { // Default name of the feature - const std::string& aKind = theFeature->getKind(); - DocumentPtr aDoc = theFeature->document(); - int aNbFeatures = myFeatureCount[aDoc][aKind]; - std::ostringstream aNameStream; - aNameStream << aKind << "_" << aNbFeatures; - std::string aFeatureName = aNameStream.str(); + bool isFeatureDefaultName = myNames[theFeature].myIsDefault; // Save only names of results which is not correspond to default feature name const std::list& aResults = theFeature->results(); std::list::const_iterator aResIt = aResults.begin(); - for (int i = 1; aResIt != aResults.end(); ++aResIt, ++i) { - bool isUserDefined = true; + for (int i = 0; aResIt != aResults.end(); ++aResIt, ++i) { + std::string aDefaultName = ModelAPI_Tools::getDefaultName(*aResIt, i); std::string aResName = (*aResIt)->data()->name(); - size_t anIndex = aResName.find(aFeatureName); - if (anIndex == 0) { - std::string aSuffix = aResName.substr(aFeatureName.length()); - if (aSuffix.empty() && i == 1) // first result may not constain index in the name - isUserDefined = false; - else { - if (aSuffix[0] == '_' && std::stoi(aSuffix.substr(1)) == i) - isUserDefined = false; - } - } + + bool isUserDefined = !(isFeatureDefaultName && aDefaultName == aResName); myNames[*aResIt] = EntityName(aResName, (isUserDefined ? aResName : std::string()), !isUserDefined); @@ -223,22 +211,13 @@ void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature) if (aCompSolid) { int aNbSubs = aCompSolid->numberOfSubs(); for (int j = 0; j < aNbSubs; ++j) { - isUserDefined = true; ResultPtr aSub = aCompSolid->subResult(j); std::string aSubName = aSub->data()->name(); - size_t anIndex = aSubName.find(aResName); - if (anIndex == 0) { - std::string aSuffix = aSubName.substr(aResName.length()); - if (aSuffix.empty() && aNbSubs == 1) // first result may not constain index in the name - isUserDefined = false; - else { - if (aSuffix[0] == '_' && std::stoi(aSuffix.substr(1)) == j + 1) - isUserDefined = false; - } - } + aDefaultName = ModelAPI_Tools::getDefaultName(aSub, j); + bool isUserDefinedSubName = isUserDefined || aDefaultName != aSubName; myNames[aSub] = EntityName(aSubName, - (isUserDefined ? aSubName : std::string()), !isUserDefined); + (isUserDefinedSubName ? aSubName : std::string()), !isUserDefinedSubName); } } } -- 2.39.2