Salome HOME
Fix and unit test for the issue #1064
authormpv <mpv@opencascade.com>
Mon, 19 Oct 2015 12:42:47 +0000 (15:42 +0300)
committermpv <mpv@opencascade.com>
Mon, 19 Oct 2015 12:42:47 +0000 (15:42 +0300)
src/ConstructionPlugin/ConstructionPlugin_Plane.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelectionList.cpp
src/Model/Model_AttributeSelectionList.h
src/Model/Model_Objects.cpp
src/Model/Model_ResultPart.cpp
src/Model/Model_ResultPart.h
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI_AttributeSelectionList.h
src/ModelAPI/ModelAPI_ResultPart.h
src/ModelAPI/Test/Test1064.py [new file with mode: 0644]

index adcd4c1229bdf34e622cc1adaa0a629994f60515..07a223b44e5053d8e6180e69eea43f56ca6ddda1 100644 (file)
@@ -113,24 +113,32 @@ std::shared_ptr<GeomAPI_Shape>  ConstructionPlugin_Plane::createPlaneByFaceAndDi
       double aXmin, aYmin, Zmin, aXmax, aYmax, Zmax;
       aShape->computeSize(aXmin, aYmin, Zmin, aXmax, aYmax, Zmax);
 
-      std::shared_ptr<GeomAPI_Pnt> aPnt1 = std::shared_ptr<GeomAPI_Pnt>(
-          new GeomAPI_Pnt(aXmin, aYmin, Zmin));
-      std::shared_ptr<GeomAPI_Pnt> aPnt2 = std::shared_ptr<GeomAPI_Pnt>(
-          new GeomAPI_Pnt(aXmax, aYmax, Zmax));
-
-      std::shared_ptr<GeomAPI_Pnt2d> aPnt2d1 = aPnt1->to2D(aNewPln);
-      std::shared_ptr<GeomAPI_Pnt2d> aPnt2d2 = aPnt2->to2D(aNewPln);
-
-      double aWidth = aPnt2d2->x() - aPnt2d1->x();
-      double aHeight = aPnt2d2->y() - aPnt2d1->y();
-      double aWgap = aWidth * 0.1;
-      double aHgap = aHeight * 0.1;
-
+      // use all 8 points of the bounding box to find the 2D bounds
+      bool isFirst = true;
+      double aMinX2d, aMaxX2d, aMinY2d, aMaxY2d;
+      for(int aXIsMin = 0; aXIsMin < 2; aXIsMin++) {
+        for(int aYIsMin = 0; aYIsMin < 2; aYIsMin++) {
+          for(int aZIsMin = 0; aZIsMin < 2; aZIsMin++) {
+            std::shared_ptr<GeomAPI_Pnt> aPnt = std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(
+              aXIsMin ? aXmin : aXmax, aYIsMin ? aYmin : aYmax, aZIsMin ? Zmin : Zmax));
+            std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = aPnt->to2D(aNewPln);
+            if (isFirst || aPnt2d->x() < aMinX2d)
+              aMinX2d = aPnt2d->x();
+            if (isFirst || aPnt2d->y() < aMinY2d)
+              aMinY2d = aPnt2d->y();
+            if (isFirst || aPnt2d->x() > aMaxX2d)
+              aMaxX2d = aPnt2d->x();
+            if (isFirst || aPnt2d->y() > aMaxY2d)
+              aMaxY2d = aPnt2d->y();
+            if (isFirst)
+              isFirst = !isFirst;
+          }
+        }
+      }
+      double aWgap = (aMaxX2d - aMinX2d) * 0.1;
+      double aHgap = (aMaxY2d - aMinY2d) * 0.1;
       aPlane = GeomAlgoAPI_FaceBuilder::planarFace(aNewPln,
-                                                   aPnt2d1->x() - aWgap,
-                                                   aPnt2d1->y() - aHgap,
-                                                   aWidth + 2 * aWgap,
-                                                   aHeight + 2 * aHgap);
+        aMinX2d - aWgap, aMinY2d - aHgap, aMaxX2d - aMinX2d + 2. * aWgap, aMaxY2d - aMinY2d + 2. * aHgap);
     }
   }
   return aPlane;
index 7bc7217dcfca8e0ca54dd9925cdd4771e066e29f..232ff61b558ead55e47049e9d23208513d06c975 100644 (file)
@@ -200,7 +200,6 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
         return aResult; // empty result
     }
     if (aSelLab.IsAttribute(kPART_REF_ID)) {
-      /* TODO: implement used text here
       ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(context());
       if (!aPart.get() || !aPart->isActivated())
         return std::shared_ptr<GeomAPI_Shape>(); // postponed naming needed
@@ -208,11 +207,12 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
       if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
         return aPart->selectionValue(anIndex->Get());
       }
+      /*
       Handle(TDataStd_Name) aName;
       if (!selectionLabel().FindAttribute(TDataStd_Name::GetID(), aName)) {
         return std::shared_ptr<GeomAPI_Shape>(); // something is wrong
       }
-      return aPart->shapeInPart(TCollection_AsciiString(aName).ToCString());
+      return aPart->shapeInPart(TCollection_AsciiString(aName->Get()).ToCString());
       */
     }
 
@@ -873,6 +873,24 @@ void Model_AttributeSelection::selectSubShape(
 {
   if(theSubShapeName.empty() || theType.empty()) return;
 
+  // check this is Part-name: 2 delimiters in the name
+  std::size_t aPartEnd = theSubShapeName.find('/');
+  if (aPartEnd != string::npos && aPartEnd != theSubShapeName.rfind('/')) {
+    std::string aPartName = theSubShapeName.substr(0, aPartEnd);
+    ObjectPtr aFound = owner()->document()->objectByName(ModelAPI_ResultPart::group(), aPartName);
+    if (aFound.get()) { // found such part, so asking it for the name
+      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aFound);
+      string aNameInPart = theSubShapeName.substr(aPartEnd + 1);
+      int anIndex;
+      std::shared_ptr<GeomAPI_Shape> aSelected = aPart->shapeInPart(aNameInPart, theType, anIndex);
+      if (aSelected.get()) {
+        setValue(aPart, aSelected);
+        TDataStd_Integer::Set(selectionLabel(), anIndex);
+        return;
+      }
+    }
+  }
+
   Model_SelectionNaming aSelNaming(selectionLabel());
   std::shared_ptr<Model_Document> aDoc = 
     std::dynamic_pointer_cast<Model_Document>(owner()->document());
index 07e62e2bcf45bcad212b5e9c1995413d16e13bf7..f762ebaf39699e006fc32d8f45ceab799528bdf0 100644 (file)
@@ -50,7 +50,8 @@ void Model_AttributeSelectionList::append(
   owner()->data()->sendAttributeUpdated(this);
 }
 
-void Model_AttributeSelectionList::append(std::string theNamingName)
+void Model_AttributeSelectionList::append(
+  const std::string theNamingName, const std::string& theType)
 {
   int aNewTag = mySize->Get() + 1;
   TDF_Label aNewLab = mySize->Label().FindChild(aNewTag);
@@ -60,8 +61,9 @@ void Model_AttributeSelectionList::append(std::string theNamingName)
   if (owner()) {
     aNewAttr->setObject(owner());
   }
+  aNewAttr->setID(id());
   mySize->Set(aNewTag);
-  aNewAttr->selectSubShape(selectionType(), theNamingName);
+  aNewAttr->selectSubShape(theType.empty() ? selectionType() : theType, theNamingName);
   owner()->data()->sendAttributeUpdated(this);
 }
 
index 55dad109f3f8b4032deb2976d09311c1b6f4c519..6721dd8adfff67a59d0ed9b1a458a1de8bfe6fc8 100644 (file)
@@ -36,8 +36,8 @@ public:
     const bool theTemporarily = false);
 
   /// Adds the new reference to the end of the list by the naming name of the selected shape
-  /// The type of shape is taken from the current selection type
-  MODEL_EXPORT virtual void append(std::string theNamingName);
+  /// The type of shape is taken from the current selection type if the given is empty
+  MODEL_EXPORT virtual void append(const std::string theNamingName, const std::string& theType="");
 
   /// Removes the last element in the list
   MODEL_EXPORT virtual void removeLast();
index 601e0c1b74d5cad5461558136e8700987f059143..0d1021820f9583d3c53bba163ee6ea46e52ea953 100644 (file)
@@ -445,11 +445,37 @@ std::shared_ptr<ModelAPI_Object> Model_Objects::objectByName(
     const std::string& theGroupID, const std::string& theName)
 {
   createHistory(theGroupID);
-  std::list<std::shared_ptr<ModelAPI_Feature> > allObjs = allFeatures();
-  std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anObjIter = allObjs.begin();
-  for(; anObjIter != allObjs.end(); anObjIter++) {
-    if ((*anObjIter)->data()->name() == theName)
-      return *anObjIter;
+  if (theGroupID == ModelAPI_Feature::group()) { // searching among features (in history or not)
+    std::list<std::shared_ptr<ModelAPI_Feature> > allObjs = allFeatures();
+    std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anObjIter = allObjs.begin();
+    for(; anObjIter != allObjs.end(); anObjIter++) {
+      if ((*anObjIter)->data()->name() == theName)
+        return *anObjIter;
+    }
+  } else { // searching among results (concealed or not)
+    std::list<std::shared_ptr<ModelAPI_Feature> > allObjs = allFeatures();
+    std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anObjIter = allObjs.begin();
+    for(; anObjIter != allObjs.end(); anObjIter++) {
+      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = (*anObjIter)->results();
+      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
+      for (; aRIter != aResults.cend(); aRIter++) {
+        if (aRIter->get() && (*aRIter)->groupName() == theGroupID) {
+          if ((*aRIter)->data()->name() == theName)
+            return *aRIter;
+          ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRIter);
+          if (aCompRes.get()) {
+            int aNumSubs = aCompRes->numberOfSubs();
+            for(int a = 0; a < aNumSubs; a++) {
+              ResultPtr aSub = aCompRes->subResult(a);
+              if (aSub.get() && aSub->groupName() == theGroupID) {
+                if (aSub->data()->name() == theName)
+                  return aSub;
+              }
+            }
+          }
+        }
+      }
+    }
   }
   // not found
   return ObjectPtr();
index bb12b10756fffa3c95096e4eda37a3d8ca10f63d..124fecd49c1eda73330f5bee4c67e9b1ef4e7045 100644 (file)
@@ -285,12 +285,33 @@ bool Model_ResultPart::updateInPart(const int theIndex)
   return false; // something is wrong
 }
 
-std::shared_ptr<GeomAPI_Shape> Model_ResultPart::shapeInPart(const std::string& theName)
+std::shared_ptr<GeomAPI_Shape> Model_ResultPart::shapeInPart(
+  const std::string& theName, const std::string& theType, int& theIndex)
 {
-  /// TODO: not implemented yet
-  return std::shared_ptr<GeomAPI_Shape>();
+  theIndex = 0; // not found yet
+  std::shared_ptr<GeomAPI_Shape> aResult;
+  std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(partDoc());
+  if (!aDoc.get()) // the part document is not presented for the moment
+    return aResult;
+
+  AttributeSelectionListPtr aSelAttr = aDoc->selectionInPartFeature();
+  aSelAttr->append(theName, theType);
+  theIndex = aSelAttr->size();
+  aResult = aSelAttr->value(theIndex - 1)->value();
+  return aResult;
 }
 
+std::shared_ptr<GeomAPI_Shape> Model_ResultPart::selectionValue(const int theIndex)
+{
+  std::shared_ptr<GeomAPI_Shape> aResult;
+  std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(partDoc());
+  if (!aDoc.get()) // the part document is not presented for the moment
+    return aResult;
+
+  AttributeSelectionListPtr aSelAttr = aDoc->selectionInPartFeature();
+  aResult = aSelAttr->value(theIndex - 1)->value();
+  return aResult;
+}
 
 void Model_ResultPart::colorConfigInfo(std::string& theSection, std::string& theName,
   std::string& theDefault)
index f53ac5e852c6e48444789f0b1812030357206203..220e1b408f50e5a6eb7cac65884bb98a818d7b67 100644 (file)
@@ -61,7 +61,8 @@ class Model_ResultPart : public ModelAPI_ResultPart
   /// Updates the selection inside of the part by the selection index
   MODEL_EXPORT virtual bool updateInPart(const int theIndex);
   /// Returns the shape by the name in the part
-  MODEL_EXPORT virtual std::shared_ptr<GeomAPI_Shape> shapeInPart(const std::string& theName);
+  MODEL_EXPORT virtual std::shared_ptr<GeomAPI_Shape> shapeInPart(
+    const std::string& theName, const std::string& theType, int& theIndex);
   /// Updates the shape-result of the part (called on Part feature execution)
   MODEL_EXPORT virtual void updateShape();
   /// Applies the additional transformation of the part
@@ -72,6 +73,9 @@ class Model_ResultPart : public ModelAPI_ResultPart
   MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName,
                                             std::string& theDefault);
 
+  /// Returns the shape selected in the selection index
+  MODEL_EXPORT virtual std::shared_ptr<GeomAPI_Shape> selectionValue(const int theIndex);
+
 protected:
   /// makes a result on a temporary feature (an action)
   Model_ResultPart();
index 70d61ff25bb1b41c58448213e14dfdc541c8c97a..15686873f4e7934061c05cb65914888e77cda1fb 100644 (file)
@@ -124,4 +124,5 @@ INSTALL(FILES ${SWIG_SCRIPTS} DESTINATION swig)
 
 ADD_UNIT_TESTS(TestConstants.py
                TestUndoRedo.py
-               TestDocument.py)
+               TestDocument.py
+               Test1064.py)
index b12aa518d54daaf898b7b79168e76be2016304b2..e2cad1e1f7404176c8209cf3ecc6b91f0aaa1740 100644 (file)
@@ -29,8 +29,8 @@ class ModelAPI_AttributeSelectionList : public ModelAPI_Attribute
                       const bool theTemporarily = false) = 0;
 
   /// Adds the new reference to the end of the list by the naming name of the selected shape
-  /// The type of shape is taken from the current selection type
-  virtual void append(std::string theNamingName) = 0;
+  /// The type of shape is taken from the current selection type if the given is empty
+  virtual void append(const std::string theNamingName, const std::string& theType = "") = 0;
 
   /// Removes the last element in the list
   virtual void removeLast() = 0;
index b06c3f2ac619ef8c1e7e1fd4d1682ad5cadb0ef9..1d66dba1885b03b0d1e751aa403a26abd721de7d 100644 (file)
@@ -73,7 +73,12 @@ class ModelAPI_ResultPart : public ModelAPI_Result
     const std::shared_ptr<GeomAPI_Trsf>& theTransformation) = 0;
 
   /// Returns the shape by the name in the part
-  virtual std::shared_ptr<GeomAPI_Shape> shapeInPart(const std::string& theName) = 0;
+  virtual std::shared_ptr<GeomAPI_Shape> shapeInPart(
+    const std::string& theName, const std::string& theType, int& theIndex) = 0;
+
+  /// Returns the shape selected in the selection index
+  virtual std::shared_ptr<GeomAPI_Shape> selectionValue(const int theIndex) = 0;
+
   /// Updates the shape-result of the part (called on Part feature execution)
   virtual void updateShape() = 0;
 };
diff --git a/src/ModelAPI/Test/Test1064.py b/src/ModelAPI/Test/Test1064.py
new file mode 100644 (file)
index 0000000..e4fb929
--- /dev/null
@@ -0,0 +1,104 @@
+"""
+      Test1064.py
+      Unit test for testing the Part sub-shapes naming, described in the issue 1064
+      
+"""
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+
+__updated__ = "2015-10-16"
+
+aSession = ModelAPI_Session.get()
+
+#=========================================================================
+# Create a sketch triangle in PartSet
+#=========================================================================
+aPartSet = aSession.moduleDocument()
+aSession.startOperation()
+aSketchFeature = featureToCompositeFeature(aPartSet.addFeature("Sketch"))
+origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm.setValue(0, 0, 1)
+# Create lines
+aLine1 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine1.attribute("StartPoint")).setValue(0, 0)
+geomDataAPI_Point2D(aLine1.attribute("EndPoint")).setValue(200, 0)
+aLine2 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine2.attribute("StartPoint")).setValue(200, 0)
+geomDataAPI_Point2D(aLine2.attribute("EndPoint")).setValue(0, 200)
+aLine3 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine3.attribute("StartPoint")).setValue(0, 200)
+geomDataAPI_Point2D(aLine3.attribute("EndPoint")).setValue(0, 0)
+aSession.finishOperation()
+
+#=========================================================================
+# Create a part
+#=========================================================================
+aSession.startOperation()
+aPartFeature = aPartSet.addFeature("Part")
+aSession.finishOperation()
+assert (len(aPartFeature.results()) == 1)
+aPart = aSession.activeDocument()
+
+#=========================================================================
+# Make extrusion on triangle
+#=========================================================================
+aSketchResult = aSketchFeature.firstResult()
+aSketchEdges = modelAPI_ResultConstruction(aSketchResult).shape()
+aSketchFaces = ShapeList()
+GeomAlgoAPI_SketchBuilder.createFaces(
+    origin.pnt(), dirx.dir(), norm.dir(), aSketchEdges, aSketchFaces)
+aSession.startOperation()
+anExtrusionFt = aPart.addFeature("Extrusion")
+anExtrusionFt.selectionList("base").append(aSketchResult, aSketchFaces[0])
+anExtrusionFt.string("CreationMethod").setValue("BySizes")
+anExtrusionFt.real("to_size").setValue(50)
+anExtrusionFt.real("from_size").setValue(0)
+aSession.finishOperation()
+
+
+#=========================================================================
+# Make a plane in PartSet on lateral face of the Extrusion
+#=========================================================================
+aSession.startOperation()
+aSession.setActiveDocument(aPartSet)
+aPlane = aPartSet.addFeature("Plane")
+aPlane.string("CreationMethod").setValue("PlaneByFaceAndDistance")
+aPlane.real("distance").setValue(0)
+aPlane.selection("planeFace").selectSubShape("face", "Part_1/Extrusion_1_1/LateralFace_3")
+aSession.finishOperation()
+
+#=========================================================================
+# Update the sketch edges in order to update the plane on the lateral face automatically
+#=========================================================================
+aSession.startOperation()
+geomDataAPI_Point2D(aLine1.attribute("EndPoint")).setValue(400, 0)
+geomDataAPI_Point2D(aLine2.attribute("StartPoint")).setValue(400, 0)
+aSession.finishOperation()
+
+#=========================================================================
+# Check that the plane is also updated
+#=========================================================================
+
+assert(len(aPlane.results()) > 0)
+aShape = aPlane.firstResult().shape()
+aFace = GeomAPI_Face(aShape)
+assert(aFace.isPlanar())
+aPln = aFace.getPlane()
+# Must be 0.4472135955, 0.894427191, 0.0
+assert(aPln.direction().x() > 0.44)
+assert(aPln.direction().x() < 0.45)
+assert(aPln.direction().y() > 0.89)
+assert(aPln.direction().y() < 0.90)
+assert(aPln.direction().z() == 0.)
+
+#=========================================================================
+# End of test
+#=========================================================================