Salome HOME
Task 2.1. Management of result names
authorazv <azv@opencascade.com>
Tue, 14 Nov 2017 06:37:35 +0000 (09:37 +0300)
committerazv <azv@opencascade.com>
Tue, 14 Nov 2017 12:26:08 +0000 (15:26 +0300)
Improve checking default names when dumping to Python

src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Objects.cpp
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelAPI/Test/TestCustomName_DefaultName.py [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_Dumper.cpp

index 32c9215547d930969ebc91b4fee79421063e8cdc..9911a796463fe41ec18cfc94fa6e9e22b048003b 100644 (file)
@@ -754,8 +754,8 @@ std::shared_ptr<ModelAPI_Object> 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);
index d46c13c31f695bce15bdf6e8ed009a7bcc6032bc..186cfefc2a353a030c9df47d881a6b8140a4d3c2 100644 (file)
@@ -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.
index 373e5ff1457f85861e2794f173db347e0977cd06..e1636118df3e9d6362dd4cb5ec205a567287bcc4 100644 (file)
@@ -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<ResultPtr>& aResults = theFeature->results();
-  for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
-       aResIt != aResults.end(); ++aResIt) {
-    ResultCompSolidPtr aCompSolidRes =
-        std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*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<ObjectPtr> > > ListOfReferences;
-
-  SessionPtr aSession = ModelAPI_Session::get();
-  FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner());
-
   ResultCompSolidPtr aCompSolidRes =
       std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(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<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(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<ObjectPtr>::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<ModelAPI_Result>(*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<ModelAPI_Data> theFeatureData,
index 94462f161e0e9b50b13c1106eb20e0db27e574bf..8e809227a85754099eae7ac88c56ee5220a2818d 100644 (file)
@@ -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
index c28a1ae8800541e63caca2ceb1183d138f1de535..e1848123e782d42e57cbd8095417128b887fd79a 100644 (file)
@@ -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();
index 3be42d1f47248161f147105f5eecac93fa1d1534..7956c4dbb91966ec0a54917e62e6c7d0777b0e2b 100755 (executable)
@@ -32,6 +32,7 @@
 #include <list>
 #include <map>
 #include <iostream>
+#include <sstream>
 
 #include <Events_Loop.h>
 #include <ModelAPI_Events.h>
@@ -622,4 +623,82 @@ void getConcealedResults(const FeaturePtr& theFeature,
   }
 }
 
+std::string getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
+                           const int theResultIndex)
+{
+  typedef std::list< std::pair < std::string, std::list<ObjectPtr> > > 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<ResultPtr>& aResults = anOwner->results();
+    for (std::list<ResultPtr>::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<ObjectPtr>::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<ModelAPI_Result>(*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
index c119924cb88d16a43106dd9a0de15b69879d9de0..1a2db5e05b2ecc979215b76d11979e245c3f2ba4 100755 (executable)
@@ -186,6 +186,11 @@ MODELAPI_EXPORT void findRefsToFeatures(
 */
 MODELAPI_EXPORT void getConcealedResults(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                                    std::list<std::shared_ptr<ModelAPI_Result> >& theResults);
+
+/*! Return the default name of the result according the the features it depends.
+ */
+MODELAPI_EXPORT std::string getDefaultName(const std::shared_ptr<ModelAPI_Result>& 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 (file)
index 0000000..f1149d7
--- /dev/null
@@ -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<mailto: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())
index ba329d412e4b3783596f73ed44c772cf372cff4c..230f12b3b8fc6e9fcc94f7f7adae922b761f3c2e 100644 (file)
@@ -51,6 +51,7 @@
 #include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Tools.h>
 
 #include <PartSetPlugin_Part.h>
 
@@ -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<ResultPtr>& aResults = theFeature->results();
   std::list<ResultPtr>::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);
       }
     }
   }