Salome HOME
Fix for the issue #2276: selecting the center of a circle crashes SHAPER
authormpv <mpv@opencascade.com>
Thu, 19 Oct 2017 10:52:36 +0000 (13:52 +0300)
committermpv <mpv@opencascade.com>
Thu, 19 Oct 2017 11:00:14 +0000 (14:00 +0300)
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI_AttributeSelection.h
src/ModelAPI/Test/Test2276.py [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_Projection.cpp

index 6d97b417e48eda32395f55ed9b6d958507a52a59..95af31053e7cc424e589db0b5b2c09d2ba2b746b 100644 (file)
@@ -90,25 +90,26 @@ Standard_GUID kELLIPSE_CENTER2("1395ae73-8e02-4cf8-b204-06ff35873a32");
 // TDataStd_IntPackedMap - indexes of edges in composite element (for construction)
 // TDataStd_Integer - type of the selected shape (for construction)
 // TDF_Reference - from ReferenceAttribute, the context
-void Model_AttributeSelection::setValue(const ResultPtr& theContext,
+bool Model_AttributeSelection::setValue(const ResultPtr& theContext,
   const std::shared_ptr<GeomAPI_Shape>& theSubShape, const bool theTemporarily)
 {
   if (theTemporarily) { // just keep the stored without DF update
     myTmpContext = theContext;
     myTmpSubShape = theSubShape;
     owner()->data()->sendAttributeUpdated(this);
-    return;
+    return true;
   } else {
     myTmpContext.reset();
     myTmpSubShape.reset();
     myTmpCenterType = NOT_CENTER;
   }
 
-  const std::shared_ptr<GeomAPI_Shape>& anOldShape = value();
+  CenterType aType;
+  const std::shared_ptr<GeomAPI_Shape>& anOldShape = internalValue(aType);
   bool isOldContext = theContext == myRef.value();
   bool isOldShape = isOldContext &&
     (theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape)));
-  if (isOldShape) return; // shape is the same, so context is also unchanged
+  if (isOldShape) return false; // shape is the same, so context is also unchanged
   // update the referenced object if needed
   if (!isOldContext) {
       myRef.setValue(theContext);
@@ -134,7 +135,7 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
     TDF_Label aRefLab = myRef.myRef->Label();
     aSelLab.ForgetAllAttributes(true);
     myRef.myRef = TDF_Reference::Set(aSelLab.Father(), aSelLab.Father());
-    return;
+    return false;
   }
   if (theContext->groupName() == ModelAPI_ResultBody::group()) {
     // do not select the whole shape for body:it is already must be in the data framework
@@ -168,32 +169,54 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
   }
 
   owner()->data()->sendAttributeUpdated(this);
+  return true;
 }
 
 void Model_AttributeSelection::setValueCenter(
     const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
     const CenterType theCenterType, const bool theTemporarily)
 {
-  setValue(theContext, theEdge, theTemporarily);
+  bool anUpdated = setValue(theContext, theEdge, theTemporarily);
   if (theTemporarily) {
     myTmpCenterType = theCenterType;
   } else { // store in the data structure
     TDF_Label aSelLab = selectionLabel();
     switch(theCenterType) {
     case CIRCLE_CENTER:
+      if (!anUpdated)
+        anUpdated = !aSelLab.IsAttribute(kCIRCLE_CENTER);
       TDataStd_UAttribute::Set(aSelLab, kCIRCLE_CENTER);
       break;
     case ELLIPSE_FIRST_FOCUS:
+      if (!anUpdated)
+        anUpdated = !aSelLab.IsAttribute(kELLIPSE_CENTER1);
       TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER1);
       break;
     case ELLIPSE_SECOND_FOCUS:
+      if (!anUpdated)
+        anUpdated = !aSelLab.IsAttribute(kELLIPSE_CENTER2);
       TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER2);
       break;
     }
-    owner()->data()->sendAttributeUpdated(this);
+    if (anUpdated)
+      owner()->data()->sendAttributeUpdated(this);
   }
 }
 
+void Model_AttributeSelection::selectValue(
+    const std::shared_ptr<ModelAPI_AttributeSelection>& theSource)
+{
+  CenterType aType;
+  std::shared_ptr<GeomAPI_Shape> aValue =
+    std::dynamic_pointer_cast<Model_AttributeSelection>(theSource)->internalValue(aType);
+  if (!aValue.get() || aType == NOT_CENTER) {
+    setValue(theSource->context(), aValue);
+  } else {
+    std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge);
+    anEdge->setImpl(new TopoDS_Shape(aValue->impl<TopoDS_Shape>()));
+    setValueCenter(theSource->context(), anEdge, aType);
+  }
+}
 
 void Model_AttributeSelection::removeTemporaryValues()
 {
index 5011bdce420ccde489bded88f141932b5fdaa673..5306aa68df25b65573dc303b3006dee5c57e8528 100644 (file)
@@ -53,7 +53,8 @@ public:
   /// \param theSubShape selected sub-shape (if null, the whole context is selected)
   /// \param theTemporarily if it is true, do not store and name the added in the data framework
   ///           (used to remove immideately, without the following updates)
-  MODEL_EXPORT virtual void setValue(
+  /// \returns true if attribute was updated
+  MODEL_EXPORT virtual bool setValue(
     const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
     const bool theTemporarily = false);
 
@@ -64,6 +65,10 @@ public:
     const CenterType theCenterType,
     const bool theTemporarily = false);
 
+  /// Makes this selection attribute selects the same as in theSource selection
+  MODEL_EXPORT virtual void selectValue(
+    const std::shared_ptr<ModelAPI_AttributeSelection>& theSource);
+
   /// Reset temporary stored values
   virtual void removeTemporaryValues();
 
index bdd120bff2a31af03547168b7d880cc1b6ef6bc4..e043a23a2731cb5d8bedcb33639334b311749e19 100644 (file)
@@ -171,4 +171,5 @@ ADD_UNIT_TESTS(TestConstants.py
                Test2228.py
                Test2241.py
                Test2252.py
+               Test2276.py
 )
index 44eace64ffbba7793492591b684aef5ba9d4193e..904711ea2776363b14e1921203f8e0e2ebabce7b 100644 (file)
@@ -47,7 +47,8 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute
   /// \param theSubShape selected sub-shape (if null, the whole context is selected)
   /// \param theTemporarily if it is true, do not store and name the added in the data framework
   ///           (used to remove immideately, without the following updates)
-  virtual void setValue(
+  /// \returns true if attribute was updated
+  virtual bool setValue(
     const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
     const bool theTemporarily = false) = 0;
 
@@ -58,6 +59,10 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute
     const CenterType theCenterType,
     const bool theTemporarily = false) = 0;
 
+  /// Makes this selection attribute selects the same as in theSource selection
+  virtual void selectValue(
+    const std::shared_ptr<ModelAPI_AttributeSelection>& theSource) = 0;
+
   /// Reset temporary stored values
   virtual void removeTemporaryValues() = 0;
 
diff --git a/src/ModelAPI/Test/Test2276.py b/src/ModelAPI/Test/Test2276.py
new file mode 100644 (file)
index 0000000..8697b5d
--- /dev/null
@@ -0,0 +1,38 @@
+## 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()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(-9.954190485756755, -75.16051465706819, 60.31858435553394)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), 10, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face_1"))
+SketchProjection_1 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1__cc"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_2 = Sketch_2.addCircle(-9.954190485756755, -75.16051465706819, 33.11263086848982)
+SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchPoint_1.result(), SketchCircle_2.center())
+model.end()
+
+assert(model.checkPythonDump())
index a0d8090c80bb2c9b515757176c6300227c68983b..254ccafc99899862470662f77a7daa3ce5eacff0 100644 (file)
@@ -253,7 +253,7 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID)
   aRefAttr->setObject(aProjection);
 
   if (theID == EXTERNAL_FEATURE_ID()) {
-    selection(EXTERNAL_ID())->setValue(aExtFeature->context(), aExtFeature->value());
+    selection(EXTERNAL_ID())->selectValue(aExtFeature);
 
     if (aResult) {
       aResult->setShape(aProjection->lastResult()->shape());