Salome HOME
Implementation of geometrical naming and a first unit-test for placement face selection.
authormpv <mpv@opencascade.com>
Tue, 6 Nov 2018 12:06:42 +0000 (15:06 +0300)
committermpv <mpv@opencascade.com>
Mon, 19 Nov 2018 08:45:52 +0000 (11:45 +0300)
src/FeaturesPlugin/Test/Test2724.py
src/Model/Model_AttributeSelection.cpp
src/ModelAPI/CMakeLists.txt
src/ModelAPI/Test/Test2685.py
src/ModelAPI/Test/TestGeomNamingPlacement.py [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_Tools.cpp
src/ModelHighAPI/ModelHighAPI_Tools.h
src/Selector/Selector_Selector.cpp

index 98272e6d09914df49f1b5253b0a0a5f92a14d6df..16cd2c3304f645c0a5c619c7f013f0ae204bc4c2 100644 (file)
@@ -63,5 +63,5 @@ Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
 Placement_1 = model.addPlacement(Part_1_doc, [model.selection("SOLID", (-30.00000000000001, -10, -10))], model.selection("FACE", (5, 10, 5)), model.selection("FACE", (-30, 40, -10)), True, True)
 Common_1 = model.addCommon(Part_1_doc, [model.selection("SOLID", (-30.00000000000001, -210, -10)), model.selection("SOLID", (18, -293.9999999999999, -9.999999999999998))])
 model.do()
-assert(model.checkPythonDump(True))
+assert(model.checkPythonDump(model.ModelHighAPI.CHECK_WEAK))
 model.end()
index 7abe5fa37c5253c4f864f59439596155fbf186b3..4b9b6e97f4d187cbd19c069e23b7767c38e905ab 100644 (file)
@@ -911,13 +911,14 @@ void Model_AttributeSelection::selectSubShape(
       }
     }
 
-    Selector_Selector aSelector(aDoc->generalLabel());
+    Selector_Selector aSelector(selectionLabel());
     if (ModelAPI_Session::get()->moduleDocument() != owner()->document()) {
       aSelector.setBaseDocument(std::dynamic_pointer_cast<Model_Document>
         (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel());
     }
     myRestoreDocument = aDoc;
-    TDF_Label aContextLabel = aSelector.restoreByName(aSubShapeName, aShapeType, this);
+    TDF_Label aContextLabel = aSelector.restoreByName(
+      aSubShapeName, aShapeType, this, myIsGeometricalSelection);
     myRestoreDocument.reset();
     if (!aContextLabel.IsNull()) {
       ResultPtr aContext = aDoc->resultByLab(aContextLabel); // any label for document access
@@ -929,14 +930,26 @@ void Model_AttributeSelection::selectSubShape(
           aShapeToBeSelected->setImpl<TopoDS_Shape>(new TopoDS_Shape(aSelectorShape));
           // make the context result the latest existing
           aContext = newestContext(aContext, aShapeToBeSelected);
-          if (aCenterType != NOT_CENTER) {
-            if (!aShapeToBeSelected->isEdge())
-              continue;
-            std::shared_ptr<GeomAPI_Edge> aSelectedEdge(new GeomAPI_Edge(aShapeToBeSelected));
-            setValueCenter(aContext, aSelectedEdge, aCenterType);
+          if (myIsGeometricalSelection) { // store the currently generated name
+            selectionLabel().ForgetAllAttributes(true);
+            bool aToUnblock = false;
+            aToUnblock = !owner()->data()->blockSendAttributeUpdated(true);
+            myRef.setValue(aContext);
+            aSelector.store();
+            owner()->data()->sendAttributeUpdated(this);
+            if (aToUnblock)
+              owner()->data()->blockSendAttributeUpdated(false);
+            return;
+          } else { // re-select by context and value
+            if (aCenterType != NOT_CENTER) {
+              if (!aShapeToBeSelected->isEdge())
+                continue;
+              std::shared_ptr<GeomAPI_Edge> aSelectedEdge(new GeomAPI_Edge(aShapeToBeSelected));
+              setValueCenter(aContext, aSelectedEdge, aCenterType);
+            }
+            else
+              setValue(aContext, aShapeToBeSelected);
           }
-          else
-            setValue(aContext, aShapeToBeSelected);
           return;
         }
       }
index 0f513a9ca62b8099ce30fa4326f0a9de25720f52..96ad5bed35bce4069d6613400a1c6b9389862767 100644 (file)
@@ -224,4 +224,5 @@ ADD_UNIT_TESTS(TestConstants.py
                TestWeakNaming2446.py
                TestWeakNaming2452.py
                Test2685.py
+               TestGeomNamingPlacement.py
 )
index a861739465ea5412954cc69b35607d5985fca715..f851694d7085d6ca8ccd656d9246bba402aa79c4 100644 (file)
@@ -63,4 +63,4 @@ SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_5.result())
 SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_5.result(), 25)
 model.end()
 
-assert(model.checkPythonDump(True))
+assert(model.checkPythonDump(model.ModelHighAPI.CHECK_WEAK))
diff --git a/src/ModelAPI/Test/TestGeomNamingPlacement.py b/src/ModelAPI/Test/TestGeomNamingPlacement.py
new file mode 100644 (file)
index 0000000..254bf50
--- /dev/null
@@ -0,0 +1,89 @@
+## 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>
+##
+
+# -*- coding: utf-8 -*-
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+param = model.addParameter(Part_1_doc, "p", "60")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(30, 30, -20, 30)
+SketchLine_2 = Sketch_1.addLine(-20, 30, -20, -20)
+SketchLine_3 = Sketch_1.addLine(-20, -20, 30, -20)
+SketchLine_4 = Sketch_1.addLine(30, -20, 30, 30)
+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())
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_1.startPoint(), SketchLine_2.startPoint(), 50)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_4.endPoint(), SketchLine_3.endPoint(), 50)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchLine_2.startPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_2 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 10, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_5 = Sketch_2.addLine(19.58333333333334, 17.27351642784226, -0.4166666666666646, 17.27351642784226)
+SketchLine_6 = Sketch_2.addLine(-0.4166666666666646, 17.27351642784226, -0.4166666666794808, -42.72648357216971)
+SketchLine_7 = Sketch_2.addLine(-0.4166666666794808, -42.72648357216971, 19.58333333332052, -42.72648357216971)
+SketchLine_8 = Sketch_2.addLine(19.58333333332052, -42.72648357216971, 19.58333333333334, 17.27351642784226)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3][Extrusion_1_1/To_Face]"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_1 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_7.startPoint(), 30, True)
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4][Extrusion_1_1/To_Face]"), False)
+SketchPoint_3 = SketchProjection_3.createdFeature()
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_3).coordinates(), SketchLine_7.endPoint(), 25, True)
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_7.result(), 20)
+SketchConstraintLength_2 = Sketch_2.setLength(SketchLine_8.result(), "p")
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_5r-SketchLine_6f-SketchLine_7f-SketchLine_8f")], model.selection(), -5, -2)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
+Box_1 = model.addBox(Part_1_doc, 50, 50, 30)
+Placement_1 = model.addPlacement(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Cut_1_1/Modified_Face&Extrusion_1_1/To_Face"), False, True)
+model.do()
+# change parameter to split extrusion top face to two
+param.setValue(100)
+model.end()
+
+# check that placement is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Placement_1.feature()))
+
+assert(model.checkPythonDump(model.ModelHighAPI.CHECK_NAMING))
index cf9fcc35a54de9f93d91af1774af26d7a811dacb..a8a2ffcf3a7d00854d934f2e372980f8cdba3843 100644 (file)
@@ -377,7 +377,7 @@ std::string strByValueType(const ModelAPI_AttributeTables::ValueType theType)
   return ""; // bad case
 }
 
-/// stores the features information, recoursively stores sub-documetns features
+/// stores the features information, recursively stores sub-documents features
 std::string storeFeatures(const std::string& theDocName, DocumentPtr theDoc,
   std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> >& theStore,
   const bool theCompare) // if false => store
@@ -390,7 +390,7 @@ std::string storeFeatures(const std::string& theDocName, DocumentPtr theDoc,
      }
   }
   // store the model features information: iterate all features
-  int anObjectsCount = 0; // stores the number of compared features for this document to compate
+  int anObjectsCount = 0; // stores the number of compared features for this document to compare
   std::set<std::string> aProcessed; // processed features names (that are in the current document)
 
   // process all objects (features and folders)
@@ -422,7 +422,7 @@ std::string storeFeatures(const std::string& theDocName, DocumentPtr theDoc,
       ModelAPI_Tools::allResults(aFeature, allResults);
       std::list<ResultPtr>::iterator aRes = allResults.begin();
       for(; aRes != allResults.end(); aRes++) {
-        // recoursively store features of sub-documents
+        // recursively store features of sub-documents
         if ((*aRes)->groupName() == ModelAPI_ResultPart::group()) {
           DocumentPtr aDoc = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRes)->partDoc();
           if (aDoc.get()) {
@@ -511,7 +511,7 @@ static bool checkDump(SessionPtr theSession,
   return true;
 }
 
-bool checkPythonDump(const bool theWeakNameCheck)
+bool checkPythonDump(const checkDumpType theCheckType)
 {
   static const std::string anErrorByNaming("checkPythonDump by naming");
   static const std::string anErrorByGeometry("checkPythonDump by geometry");
@@ -522,14 +522,17 @@ bool checkPythonDump(const bool theWeakNameCheck)
   static char aFileForWeakDump[] = "./check_dump_weak.py";
 
   SessionPtr aSession = ModelAPI_Session::get();
-  if (!theWeakNameCheck) {
+  if (theCheckType & CHECK_NAMING) {
     // dump with the selection by names
     if (!dumpToPython(aSession, aFileForNamingDump, "topological_naming", anErrorByNaming))
       return false;
+  }
+  if (theCheckType & CHECK_GEOMETRICAL) {
     // dump with the selection by geometry
     if (!dumpToPython(aSession, aFileForGeometryDump, "geometric_selection", anErrorByGeometry))
       return false;
-  } else {
+  }
+  if (theCheckType & CHECK_WEAK) {
     // dump with the selection by weak naming
     if (!dumpToPython(aSession, aFileForWeakDump, "weak_naming", anErrorByWeak))
       return false;
@@ -546,13 +549,16 @@ bool checkPythonDump(const bool theWeakNameCheck)
   }
 
   bool isOk;
-  if (!theWeakNameCheck) {
+  if (theCheckType & CHECK_NAMING) {
     // check dump with the selection by names
     isOk = checkDump(aSession, aFileForNamingDump, aStore, anErrorByNaming);
+  }
+  if (theCheckType & CHECK_GEOMETRICAL) {
     // check dump with the selection by geometry
     isOk = isOk && checkDump(aSession, aFileForGeometryDump, aStore, anErrorByGeometry);
-  } else {
-    isOk = checkDump(aSession, aFileForWeakDump, aStore, anErrorByWeak);
+  }
+  if (theCheckType & CHECK_WEAK) {
+    isOk = isOk && checkDump(aSession, aFileForWeakDump, aStore, anErrorByWeak);
   }
 
   return isOk;
index a3f5293bf51616d89da85f80d83cd30e9a540848..8da24a0e5b8962cc07e94d8e87d1c91190d7504f 100644 (file)
@@ -168,11 +168,19 @@ ModelAPI_AttributeTables::ValueType valueTypeByStr(const std::string& theValueTy
 MODELHIGHAPI_EXPORT
 std::string strByValueType(const ModelAPI_AttributeTables::ValueType theType);
 
+/// Enumeration to manage the check python dump modes.
+enum checkDumpType {
+  CHECK_NAMING = 1, ///< check topological naming only
+  CHECK_GEOMETRICAL = 2, ///< check geometrical naming only
+  CHECK_NAMING_AND_GEOMETRICAL = 3, ///< default option, check topological and geometrical dumps
+  CHECK_WEAK = 4, ///< check weak naming only
+};
+
 /// Performs the high level API dump, then closes all and executes the script:
 /// model must be recreated fully, with all attributes
 /// \returns true if check is well done
 MODELHIGHAPI_EXPORT
-bool checkPythonDump(const bool theWeakNameCheck = false);
+bool checkPythonDump(const checkDumpType theCheckType = CHECK_NAMING_AND_GEOMETRICAL);
 
 //--------------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------------
index a184f6aad11f5881bfbd1aa3cfdeaa275db1dea9..b0cc3a1f5e66309e641b3f5e1a2e2d52f13740de 100644 (file)
@@ -197,7 +197,7 @@ static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theV
 
 /// Returns true if the given shapes are based on the same geometry
 static bool sameGeometry(const TopoDS_Shape theShape1, const TopoDS_Shape theShape2) {
-  if (!theShape1.IsNull() && theShape2.IsNull() && theShape1.ShapeType() == theShape2.ShapeType())
+  if (!theShape1.IsNull() && !theShape2.IsNull() && theShape1.ShapeType() == theShape2.ShapeType())
   {
     if (theShape1.ShapeType() == TopAbs_FACE) { // check surfaces
       TopLoc_Location aLoc1, aLoc2;
@@ -942,7 +942,7 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext)
     break;
   }
   case SELTYPE_MODIFICATION: {
-    if (myBases.IsEmpty() && myWeakIndex) { // weak name by the final shapes index
+    if (myBases.IsEmpty() && myWeakIndex > 0) { // weak name by the final shapes index
       TopoDS_ListOfShape aCommon;
       Handle(TNaming_NamedShape) aNS;
       if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
@@ -959,7 +959,7 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext)
       findModificationResult(aFinalsCommon);
       if (aFinalsCommon.Extent() == 1) { // result is valid: found only one shape
         aResult = aFinalsCommon.First();
-      } else if (aFinalsCommon.Extent() > 1 && myWeakIndex) {
+      } else if (aFinalsCommon.Extent() > 1 && myWeakIndex > 0) {
         Selector_NExplode aNExp(aFinalsCommon);
         aResult = aNExp.shape(myWeakIndex);
       } else if (aFinalsCommon.Extent() > 1 && myGeometricalNaming) {// if same geometry - compound