]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'master' into cgt/devCEA
authorClarisse Genrault <clarisse.genrault@cea.fr>
Mon, 3 Apr 2017 14:32:54 +0000 (16:32 +0200)
committerClarisse Genrault <clarisse.genrault@cea.fr>
Mon, 3 Apr 2017 14:32:54 +0000 (16:32 +0200)
187 files changed:
src/BuildPlugin/Test/TestSubShapes.py
src/BuildPlugin/Test/TestVertex.py
src/CollectionPlugin/Test/TestGroup.py
src/ConstructionPlugin/Test/TestAxisCreation.py
src/Events/Events_Loop.cpp
src/Events/Events_Loop.h
src/ExchangePlugin/ExchangePlugin_Dump.cpp
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp
src/FeaturesPlugin/FeaturesPlugin_Tools.cpp
src/FeaturesPlugin/Test/Test2038.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2046.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestBoolean.py
src/FeaturesPlugin/Test/TestBooleanCompSolids.py
src/FeaturesPlugin/Test/TestBooleanSmash.py
src/FeaturesPlugin/Test/TestCompositeFeaturesOnCompSolids.py
src/FeaturesPlugin/Test/TestExtrusion.py
src/FeaturesPlugin/Test/TestExtrusionCut.py
src/FeaturesPlugin/Test/TestExtrusionFuse.py
src/FeaturesPlugin/Test/TestIntersection.py
src/FeaturesPlugin/Test/TestMultiBoolean.py
src/FeaturesPlugin/Test/TestPartition.py
src/FeaturesPlugin/Test/TestPipe.py
src/FeaturesPlugin/Test/TestRemoveSubShapes.py
src/FeaturesPlugin/Test/TestRevolution.py
src/FeaturesPlugin/Test/TestRevolutionCut.py
src/FeaturesPlugin/Test/TestRevolutionFuse.py
src/FeaturesPlugin/Test/TestRotation.py
src/FeaturesPlugin/Test/TestSerialBoolean.py
src/FeaturesPlugin/Test/TestTranslation.py
src/FeaturesPlugin/Test/TestUnion.py
src/GeomAPI/GeomAPI.i
src/GeomAPI/GeomAPI_Circ2d.cpp
src/GeomAPI/GeomAPI_Circ2d.h
src/GeomAPI/GeomAPI_Shape.cpp
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI.i
src/GeomAlgoAPI/GeomAlgoAPI_Circ2dBuilder.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Circ2dBuilder.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h
src/GeomValidators/GeomValidators_BooleanArguments.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_Document.cpp
src/Model/Model_Objects.cpp
src/Model/Model_Session.cpp
src/Model/Model_Update.cpp
src/Model/Model_Validator.cpp
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_EventReentrantMessage.cpp [new file with mode: 0644]
src/ModelAPI/ModelAPI_EventReentrantMessage.h [new file with mode: 0644]
src/ModelAPI/ModelAPI_Feature.cpp
src/ModelAPI/ModelAPI_IReentrant.cpp [new file with mode: 0644]
src/ModelAPI/ModelAPI_IReentrant.h [new file with mode: 0644]
src/ModelAPI/Test/Test1512.py
src/ModelGeomAlgo/ModelGeomAlgo_Point2D.cpp
src/ModelGeomAlgo/ModelGeomAlgo_Point2D.h
src/ModelHighAPI/ModelHighAPI_Selection.cpp
src/ModelHighAPI/ModelHighAPI_Tools.cpp
src/ModuleBase/ModuleBase_IErrorMgr.h
src/ModuleBase/ModuleBase_IModule.cpp
src/ModuleBase/ModuleBase_IModule.h
src/ModuleBase/ModuleBase_IPropertyPanel.cpp
src/ModuleBase/ModuleBase_IPropertyPanel.h
src/ModuleBase/ModuleBase_IWorkshop.h
src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ModelWidget.h
src/ParametersPlugin/Test/TestParameterChangeValue.py
src/ParametersPlugin/Test/TestParameterCreation.py
src/ParametersPlugin/Test/TestParameterRename.py
src/PartSet/PartSet_CustomPrs.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_OperationPrs.cpp
src/PartSet/PartSet_OperationPrs.h
src/PartSet/PartSet_OverconstraintListener.cpp
src/PartSet/PartSet_OverconstraintListener.h
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherReentrantMgr.cpp
src/PartSet/PartSet_SketcherReentrantMgr.h
src/PartSet/PartSet_Tools.cpp
src/PartSet/PartSet_Tools.h
src/PartSet/PartSet_WidgetFeaturePointSelector.cpp
src/PartSet/PartSet_WidgetPoint2d.cpp
src/PythonAPI/CMakeLists.txt
src/PythonAPI/Test/Test2044.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherAddMirror.py
src/PythonAPI/Test/TestSketcherSetTangent.py
src/PythonAPI/model/sketcher/__init__.py
src/PythonAPI/model/sketcher/tools.py
src/PythonAPI/model/tests/tests.py
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_Arc.cpp
src/SketchPlugin/SketchPlugin_ConstraintCoincidence.cpp
src/SketchPlugin/SketchPlugin_ConstraintCoincidence.h
src/SketchPlugin/SketchPlugin_Fillet.cpp
src/SketchPlugin/SketchPlugin_Fillet.h
src/SketchPlugin/SketchPlugin_Line.cpp
src/SketchPlugin/SketchPlugin_Line.h
src/SketchPlugin/SketchPlugin_MacroArc.cpp
src/SketchPlugin/SketchPlugin_MacroArc.h
src/SketchPlugin/SketchPlugin_MacroArcReentrantMessage.h [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_MacroCircle.cpp
src/SketchPlugin/SketchPlugin_MacroCircle.h
src/SketchPlugin/SketchPlugin_Plugin.cpp
src/SketchPlugin/SketchPlugin_Point.h
src/SketchPlugin/SketchPlugin_Sketch.cpp
src/SketchPlugin/SketchPlugin_SketchEntity.h
src/SketchPlugin/SketchPlugin_Trim.cpp
src/SketchPlugin/SketchPlugin_Trim.h
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/SketchPlugin_msg_en.ts
src/SketchPlugin/Test/TestArcBehavior.py
src/SketchPlugin/Test/TestConstraintCoincidence.py
src/SketchPlugin/Test/TestConstraintDistance.py
src/SketchPlugin/Test/TestConstraintEqual.py
src/SketchPlugin/Test/TestConstraintMiddlePoint.py
src/SketchPlugin/Test/TestConstraintMirror.py [deleted file]
src/SketchPlugin/Test/TestConstraintRadius.py
src/SketchPlugin/Test/TestConstraintTangent.py
src/SketchPlugin/Test/TestCreateArcByCenterStartEnd.py [new file with mode: 0644]
src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py
src/SketchPlugin/Test/TestCreateCircleByThreePoints.py
src/SketchPlugin/Test/TestCreateCircleChangeType.py
src/SketchPlugin/Test/TestFillet.py
src/SketchPlugin/Test/TestFilletInteracting.py
src/SketchPlugin/Test/TestMirror.py [new file with mode: 0644]
src/SketchPlugin/Test/TestMultiRotation.py
src/SketchPlugin/Test/TestMultiTranslation.py
src/SketchPlugin/Test/TestProjection.py
src/SketchPlugin/Test/TestSketchPointLine.py
src/SketchPlugin/Test/TestTrimArc07.py [new file with mode: 0644]
src/SketchPlugin/Test/TestTrimLine01.py
src/SketchPlugin/Test/TestTrimLine02.py [new file with mode: 0644]
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h
src/SketchSolver/SketchSolver_ConstraintCollinear.cpp
src/SketchSolver/SketchSolver_ConstraintCollinear.h
src/SketchSolver/SketchSolver_ConstraintFixed.cpp
src/SketchSolver/SketchSolver_ConstraintMirror.cpp
src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp
src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp
src/SketchSolver/SketchSolver_ConstraintTangent.cpp
src/SketchSolver/SketchSolver_Error.h
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Group.h
src/SketchSolver/SketchSolver_Manager.cpp
src/SketchSolver/SketchSolver_Storage.cpp
src/SketchSolver/SketchSolver_Storage.h
src/SketchSolver/SketchSolver_msg_en.ts
src/SketcherPrs/SketcherPrs_Coincident.cpp
src/SketcherPrs/SketcherPrs_Coincident.h
src/SketcherPrs/SketcherPrs_Collinear.cpp
src/SketcherPrs/SketcherPrs_Collinear.h
src/SketcherPrs/SketcherPrs_Equal.cpp
src/SketcherPrs/SketcherPrs_Equal.h
src/SketcherPrs/SketcherPrs_HVDirection.cpp
src/SketcherPrs/SketcherPrs_HVDirection.h
src/SketcherPrs/SketcherPrs_Middle.cpp
src/SketcherPrs/SketcherPrs_Middle.h
src/SketcherPrs/SketcherPrs_Mirror.cpp
src/SketcherPrs/SketcherPrs_Mirror.h
src/SketcherPrs/SketcherPrs_Parallel.cpp
src/SketcherPrs/SketcherPrs_Parallel.h
src/SketcherPrs/SketcherPrs_Perpendicular.cpp
src/SketcherPrs/SketcherPrs_Perpendicular.h
src/SketcherPrs/SketcherPrs_Rigid.cpp
src/SketcherPrs/SketcherPrs_Rigid.h
src/SketcherPrs/SketcherPrs_SymbolPrs.cpp
src/SketcherPrs/SketcherPrs_SymbolPrs.h
src/SketcherPrs/SketcherPrs_Tangent.cpp
src/SketcherPrs/SketcherPrs_Tangent.h
src/SketcherPrs/SketcherPrs_Transformation.cpp
src/SketcherPrs/SketcherPrs_Transformation.h
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_ErrorMgr.h
src/XGUI/XGUI_ModuleConnector.cpp
src/XGUI/XGUI_ModuleConnector.h
test.API/SHAPER/Primitives/TestCylinder.py
test.models/angle30.py
test.models/clothespin.py
test.models/wheel_rim.py
test.squish/suite_STANDALONE/tst_DISTANCE/test.py

index 1453d8af7ddfa14f4ac3cef5c4a488529f2a8be9..d4f0ddd0a17919e5620cb35bd73f70d2bcaffc51 100644 (file)
@@ -8,8 +8,8 @@ import random
 
 def createPoint(theSketchFeature):
     aSketchPointFeature = theSketchFeature.addFeature("SketchPoint")
-    aPointCoordindates = geomDataAPI_Point2D(aSketchPointFeature.attribute("PointCoordindates"))
-    aPointCoordindates.setValue(random.uniform(0, 50), random.uniform(0, 50))
+    aPointCoordinates = geomDataAPI_Point2D(aSketchPointFeature.attribute("PointCoordinates"))
+    aPointCoordinates.setValue(random.uniform(0, 50), random.uniform(0, 50))
     return aSketchPointFeature
 
 def createLine(theSketchFeature):
index be6c50e79456c01b0f7ea9d402851c8acfc69b75..237283590974096517d90b1d3b4fbd96497b704e 100644 (file)
@@ -8,8 +8,8 @@ import random
 
 def createPoint(theSketchFeature):
     aSketchPointFeature = theSketchFeature.addFeature("SketchPoint")
-    aPointCoordindates = geomDataAPI_Point2D(aSketchPointFeature.attribute("PointCoordindates"))
-    aPointCoordindates.setValue(random.uniform(0, 100), random.uniform(0, 100))
+    aPointCoordinates = geomDataAPI_Point2D(aSketchPointFeature.attribute("PointCoordinates"))
+    aPointCoordinates.setValue(random.uniform(0, 100), random.uniform(0, 100))
     return aSketchPointFeature
 
 # Get document
index 4c21a570a3a3ab323b0a8c96677fc00fff5e7aaf..a5e078821835a0007080a0cc7eb4be86814adfb4 100644 (file)
@@ -177,8 +177,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0., 57.74)
 aCircleRadius.setValue(50.)
 aSession.finishOperation()
index f9ef91118aae8d624499ca51ae1d9e4f47a13e93..0db452f9cb2bf493baa9518959cc02b53e7b60ef 100644 (file)
@@ -81,8 +81,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(50)
 aSession.finishOperation()
index 013e0a02d6e9e0952e76a42db5da0c165b2046f9..7b9d16b1c1285c63c164f0cc971047b70d978a3e 100644 (file)
@@ -171,6 +171,7 @@ void Events_Loop::flush(const Events_ID& theID)
 {
   if (!myFlushActive)
     return;
+  bool hasEventsToFlush = !myGroups.empty();
   std::map<char*, std::shared_ptr<Events_Message> >::iterator aMyGroup;
   for(aMyGroup = myGroups.find(theID.eventText());
     aMyGroup != myGroups.end(); aMyGroup = myGroups.find(theID.eventText()))
@@ -206,6 +207,12 @@ void Events_Loop::flush(const Events_ID& theID)
       }
     }
   }
+  if (hasEventsToFlush && myGroups.empty() && myFlushed.empty()) {
+    // no more messages left in the queue, so, finalize the sketch processing
+    static Events_ID anID = Events_Loop::eventByName("SketchPrepared");
+    std::shared_ptr<Events_Message> aMsg(new Events_Message(anID, this));
+    Events_Loop::loop()->send(aMsg, false);
+  }
 }
 
 void Events_Loop::eraseMessages(const Events_ID& theID)
@@ -234,14 +241,6 @@ void Events_Loop::clear(const Events_ID& theID)
   }
 }
 
-void Events_Loop::autoFlush(const Events_ID& theID, const bool theAuto)
-{
-  if (theAuto)
-    myFlushed.insert(theID.myID);
-  else
-    myFlushed.erase(myFlushed.find(theID.myID));
-}
-
 bool Events_Loop::isFlushed(const Events_ID& theID)
 {
   return myFlushed.find(theID.myID) != myFlushed.end();
@@ -254,3 +253,8 @@ void Events_Loop::setFlushed(const Events_ID& theID, const bool theValue)
   else
     myFlushed.erase(myFlushed.find(theID.myID));
 }
+
+bool Events_Loop::hasGrouppedEvent(const Events_ID& theID)
+{
+  return myGroups.find(theID.myID) != myGroups.end();
+}
\ No newline at end of file
index 69ea2ed2485e9ad15cbcf6fe07389c16f918e966..94122adbe03100e2d8bb37bb30b1ba58260f6250 100644 (file)
@@ -86,14 +86,14 @@ class Events_Loop
   //! Clears all collected messages
   EVENTS_EXPORT void clear(const Events_ID& theID);
 
-  //! Enables flush without grouping for the given message
-  EVENTS_EXPORT void autoFlush(const Events_ID& theID, const bool theAuto = true);
-
   //! Returns true if the evement is flushed right now
   EVENTS_EXPORT bool isFlushed(const Events_ID& theID);
   //! Sets the flag that the event is flished right now
   EVENTS_EXPORT void setFlushed(const Events_ID& theID, const bool theValue);
 
+  //! Returns true if a loop accumulated events to be flashed
+  EVENTS_EXPORT bool hasGrouppedEvent(const Events_ID& theID);
+
 private:
   //! Calls "processEvent" for the given listeners.
   //! If theFlushedNow for grouped listeners is stores message in listeners.
index 5c5ee466594e0734d48c671311445f6ab8b444a5..d9effab930aee2af11c5e5845650d4fc76184be0 100644 (file)
@@ -50,6 +50,27 @@ void ExchangePlugin_Dump::dump(const std::string& theFileName)
   aDumper->clear();
   DocumentPtr aDoc = ModelAPI_Session::get()->moduleDocument();
 
+  int aFeaturesNb = aDoc->size(ModelAPI_Feature::group());
+  if(aFeaturesNb > 1) {
+    FeaturePtr aLastFeature =
+        ModelAPI_Feature::feature(aDoc->object(ModelAPI_Feature::group(), aFeaturesNb - 1));
+    if(aDoc->currentFeature(true) != aLastFeature) {
+        setError("Dump cannot be done. Please move the history line to the end before dumping.");
+        return;
+    }
+  }
+
+  DocumentPtr anActiveDoc = ModelAPI_Session::get()->activeDocument();
+  aFeaturesNb = anActiveDoc->size(ModelAPI_Feature::group());
+  if(aFeaturesNb > 1) {
+    FeaturePtr aLastFeature =
+        ModelAPI_Feature::feature(anActiveDoc->object(ModelAPI_Feature::group(), aFeaturesNb - 1));
+    if(anActiveDoc->currentFeature(true) != aLastFeature) {
+        setError("Dump cannot be done. Please move the history line to the end before dumping.");
+        return;
+    }
+  }
+
   std::list<FeaturePtr> aFeatures = aDoc->allFeatures();
   for(std::list<FeaturePtr>::const_iterator aFeatIt = aFeatures.begin();
       aFeatIt != aFeatures.end();
index 1214c5890efb895722b6deb249d745772b6df1da..193d513e48894da26395251d2d5a4cec5e475e75 100644 (file)
@@ -147,4 +147,6 @@ ADD_UNIT_TESTS(TestExtrusion.py
                Test1942.py
                Test1915.py
                Test2023.py
+               Test2046.py
+               Test2038.py
 )
index 06320e03c71610916e502b84e3993381f73101af..6556b2f467a1b8651acc73e11fb593535ff505fc 100644 (file)
@@ -278,7 +278,10 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes
 
   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
   switch(aBaseShapeType) {
-    case GeomAPI_Shape::EDGE:
+    case GeomAPI_Shape::EDGE: {
+            aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
+      break;
+    }
     case GeomAPI_Shape::WIRE: {
       //std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
       //GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
@@ -291,7 +294,7 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes
       //if(!aV2History.empty()) {
       //  theResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", theTag++);
       //}
-      aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
+      aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
       break;
     }
     case GeomAPI_Shape::FACE:
index 89f5870b230ef7521c65b3edf3b6ab9c47df1dab..6a2db66944aa61279d65b2e28c1d46b01d13fabd 100644 (file)
@@ -39,7 +39,7 @@ void FeaturesPlugin_Tools::storeModifiedShapes(GeomAlgoAPI_MakeShape& theAlgo,
     case GeomAPI_Shape::SHELL: {
       theResultBody->loadAndOrientModifiedShapes(&theAlgo,
                                 theBaseShape, GeomAPI_Shape::FACE,
-                                theFaceTag, theName + "_Face", theSubShapes);
+                                theFaceTag, theName + "_Face", theSubShapes, false, true);
       if (theBaseShape->shapeType() == GeomAPI_Shape::COMPSOLID
           || theBaseShape->shapeType() == GeomAPI_Shape::SOLID) {
         break;
@@ -49,12 +49,12 @@ void FeaturesPlugin_Tools::storeModifiedShapes(GeomAlgoAPI_MakeShape& theAlgo,
     case GeomAPI_Shape::WIRE: {
       theResultBody->loadAndOrientModifiedShapes(&theAlgo,
                                 theBaseShape, GeomAPI_Shape::EDGE,
-                                theEdgeTag, theName + "_Edge", theSubShapes);
+                                theEdgeTag, theName + "_Edge", theSubShapes, false, true);
     }
     case GeomAPI_Shape::EDGE: {
       theResultBody->loadAndOrientModifiedShapes(&theAlgo,
                               theBaseShape, GeomAPI_Shape::VERTEX,
-                              theVertexTag, theName + "_Vertex", theSubShapes);
+                              theVertexTag, theName + "_Vertex", theSubShapes, false, true);
     }
   }
 }
diff --git a/src/FeaturesPlugin/Test/Test2038.py b/src/FeaturesPlugin/Test/Test2038.py
new file mode 100644 (file)
index 0000000..7fdd342
--- /dev/null
@@ -0,0 +1,36 @@
+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"))
+SketchLine_1 = Sketch_1.addLine(-379.073756432247, 108.9193825042881, -672.3842195540308, -33.44768439108059)
+SketchLine_2 = Sketch_1.addLine(-672.3842195540308, -33.44768439108059, -360.2058319039451, -146.6552315608919)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(-360.2058319039451, -146.6552315608919, -78.9022298456261, -14.57975986277871)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-78.9022298456261, -14.57975986277871, -379.073756432247, 108.9193825042881)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+SketchLine_5 = Sketch_1.addLine(-379.073756432247, 108.9193825042881, -360.2058319039451, -146.6552315608919)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_5.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_5r")], model.selection(), 100, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_3f-SketchLine_4f-SketchLine_5f")], model.selection(), 100, 0)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Translation_1_1"), model.selection("SOLID", "Extrusion_2_1")])
+Translation_2 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("EDGE", "PartSet/OZ"), 50)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Translation_2_1/Translated_Face_24"), model.selection("FACE", "Translation_2_1/Translated_Face_13"), model.selection("FACE", "Translation_2_1/Translated_Face_16"), model.selection("FACE", "Translation_2_1/Translated_Face_12"), model.selection("FACE", "Translation_2_1/Translated_Face_9"), model.selection("FACE", "Translation_2_1/Translated_Face_10"), model.selection("FACE", "Translation_2_1/Translated_Face_11"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_20"), model.selection("FACE", "Translation_2_1/Translated_Face_19"), model.selection("FACE", "Translation_2_1/Translated_Face_18"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_17"), model.selection("FACE", "Translation_2_1/Translated_Face_31"), model.selection("FACE", "Translation_2_1/Translated_Face_32"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_28"), model.selection("FACE", "Translation_2_1/Translated_Face_29"), model.selection("FACE", "Translation_2_1/Translated_Face_8"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_7"), model.selection("FACE", "Translation_2_1/Translated_Face_6"), model.selection("FACE", "Translation_2_1/Translated_Face_5"), model.selection("FACE", "Translation_2_1/Translated_Face_3"), model.selection("FACE", "Translation_2_1/Translated_Face_1"), model.selection("FACE", "Translation_2_1/Translated_Face_2"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_4"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_26"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_14"), model.selection("FACE", "Translation_2_1/Translated_Face_15")])
+model.do()
+model.end()
+
+groupFeature = Group_1.feature()
+groupSelectionList = groupFeature.selectionList("group_list")
+for index in range(0, groupSelectionList.size()):
+  attrSelection = groupSelectionList.value(index)
+  shape = attrSelection.value()
+  name = attrSelection.namingName()
+  assert(shape.isFace())
+  assert(name != ""), "Empty shape name"
diff --git a/src/FeaturesPlugin/Test/Test2046.py b/src/FeaturesPlugin/Test/Test2046.py
new file mode 100644 (file)
index 0000000..48590c8
--- /dev/null
@@ -0,0 +1,28 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-1154.716981132076, -199.5283018867925, -849.0566037735849, 128.7735849056603)
+SketchLine_2 = Sketch_1.addLine(-849.0566037735849, 128.7735849056603, -563.2075471698113, -69.33962264150945)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(-563.2075471698113, -69.33962264150945, -70.75471698113215, 326.8867924528301)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "PartSet/Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "PartSet/Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "PartSet/Sketch_1/Edge-SketchLine_3")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], model.selection(), 100, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/Generated_Face_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_2"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1")])
+model.do()
+model.end()
+
+groupFeature = Group_1.feature()
+groupSelectionList = groupFeature.selectionList("group_list")
+assert(groupSelectionList.size() == 3)
+for index in range(0, groupSelectionList.size()):
+  attrSelection = groupSelectionList.value(index)
+  shape = attrSelection.value()
+  name = attrSelection.namingName()
+  assert(shape.isFace())
+  assert(name != ""), "Empty shape name"
index 968263eaa732fa79c2d7f3ad4e561be1a7a08ce1..0d3426549cdd584c12db7a0e3db3f5e8b3fffcdb 100644 (file)
@@ -40,8 +40,8 @@ dirx.setValue(1, 0, 0)
 norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(10., 10.)
 aCircleRadius.setValue(50.)
 aSession.finishOperation()
index 414498fb4b47828860aaa1e787b05fd37638c65c..d4c5864f6423a008ab7f3e7076de5a4aee1374a2 100644 (file)
@@ -27,8 +27,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-aCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+aCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 aCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(50)
 
index 02d0606c71c1a4477e42bb02a77393a33ee3ed51..9570b1cd8f83d581852d27ac7c20159838ea62ff 100644 (file)
@@ -24,8 +24,8 @@ dirx.setValue(1, 0, 0)
 norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(10., 10.)
 aCircleRadius.setValue(50.)
 aSession.finishOperation()
index fceb782ff3c7ad881e575e1e6883a8523470927b..ef74d83916124bdc1c215a5722ee1161a8be309d 100644 (file)
@@ -28,8 +28,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-aCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+aCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 aCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(50)
 
@@ -118,8 +118,8 @@ norm.setValue(0, 0, 1)
 aCircleSketchFeature.selection("External").selectSubShape("face", "Extrusion_1/To_Face_1")
 aSession.startOperation()
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(10)
 aSession.finishOperation()
@@ -195,8 +195,8 @@ norm.setValue(0, 0, 1)
 aCircleSketchFeature.selection("External").selectSubShape("face", "Extrusion_1/To_Face_1")
 aSession.startOperation()
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(10)
 aSession.finishOperation()
index 527dafeacefc3de82bc6b86c340d20d30d50694d..efe7f293c9a1f3c185ba2e9a944600ab873ba351 100644 (file)
@@ -57,8 +57,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(50., 50)
 aCircleRadius.setValue(20.)
 aSession.finishOperation()
index e461c50e1ae800cdbcb4bf22cdcfa2ed336ed6e9..1d62b41c9b2694ec62916fa655d10e10fecf9e1b 100644 (file)
@@ -33,8 +33,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(20)
 aSession.finishOperation()
@@ -91,8 +91,8 @@ norm.setValue(0, 0, 1)
 aCircleSketchFeature.selection("External").selectSubShape("face", "Extrusion_1/To_Face_1")
 aSession.startOperation()
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(10)
 aSession.finishOperation()
index 12693b837380cb3a272c3c9f0993a832b0e8df25..c05adb3e9e0cf45c3afa4c0fad8977674b060e7b 100644 (file)
@@ -33,8 +33,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(20)
 aSession.finishOperation()
@@ -91,8 +91,8 @@ norm.setValue(0, 0, 1)
 aCircleSketchFeature.selection("External").selectSubShape("face", "Extrusion_1/To_Face_1")
 aSession.startOperation()
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(10)
 aSession.finishOperation()
index d1c0043a6ac44343e24bb4648b808fd6467c8007..1bcd0a6be53fad9da966ca3c615958f6d3e19ce4 100644 (file)
@@ -32,8 +32,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(-10, 0)
 aCircleRadius.setValue(50)
 aSession.finishOperation()
@@ -86,8 +86,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(10, 0)
 aCircleRadius.setValue(50)
 aSession.finishOperation()
index aa36d86280812bc8b1492249212b0355ba9e5bee..a7ea2cabd01b23280dad5290dfdaddc708daaf44 100644 (file)
@@ -58,8 +58,8 @@ for i in xrange(0, N):
         norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
         norm.setValue(0, 0, 1)
         aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-        anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-        aCircleRadius = aSketchCircle.real("CircleRadius")
+        anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+        aCircleRadius = aSketchCircle.real("circle_radius")
         anCircleCentr.setValue(0.5 + step * (0.5 + i), 0.5 + step * (0.5 + j))
         aCircleRadius.setValue(radius)
         aSketchFeatures.append(aSketchFeature)
index 127209b2afe39d574d799c26a68d4f8a92cade80..b21298a33fc4ed85903d2da21bcddb9576bb5e80 100644 (file)
@@ -34,8 +34,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(50)
 aSession.finishOperation()
index 21ba065e16f3e837a3d868d11eb133b9c13bd609..b6d59e23e0348097ef7ee143c0121aa086bae4fc 100644 (file)
@@ -27,8 +27,8 @@ norm.setValue(0, 0, 1)
 
 # Create circle
 aSketchCircleFeature = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircleFeature.attribute("CircleCenter"))
-aCircleRadius = aSketchCircleFeature.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircleFeature.attribute("circle_center"))
+aCircleRadius = aSketchCircleFeature.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(10)
 aSession.finishOperation()
@@ -65,10 +65,9 @@ aSketchLineEndPoint.setValue(0, 200)
 
 # Create arc
 aSketchArcFeature = aSketchFeature.addFeature("SketchArc")
-aSketchArcFeature.string("ArcType").setValue("CenterStartEnd")
-aSketchArcCenterPoint = geomDataAPI_Point2D(aSketchArcFeature.attribute("ArcCenter"))
-aSketchArcStartPoint = geomDataAPI_Point2D(aSketchArcFeature.attribute("ArcStartPoint"))
-aSketchArcEndPoint = geomDataAPI_Point2D(aSketchArcFeature.attribute("ArcEndPoint"))
+aSketchArcCenterPoint = geomDataAPI_Point2D(aSketchArcFeature.attribute("center_point"))
+aSketchArcStartPoint = geomDataAPI_Point2D(aSketchArcFeature.attribute("start_point"))
+aSketchArcEndPoint = geomDataAPI_Point2D(aSketchArcFeature.attribute("end_point"))
 aSketchArcCenterPoint.setValue(100, 200)
 aSketchArcStartPoint.setValue(200, 200)
 aSketchArcEndPoint.setValue(0, 200)
@@ -132,8 +131,8 @@ norm.setValue(0, 0, 1)
 
 # Create circle
 aSketchCircleFeature = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircleFeature.attribute("CircleCenter"))
-aCircleRadius = aSketchCircleFeature.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircleFeature.attribute("circle_center"))
+aCircleRadius = aSketchCircleFeature.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(20)
 aSession.finishOperation()
index 6227d4580e65876a3943c2f4b173de96978d691b..4d36094ff14aa91eec659cc098d37b46990e1b75 100644 (file)
@@ -33,13 +33,13 @@ norm.setValue(0, 0, 1)
 
 # Create circles
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(-25, 0)
 aCircleRadius.setValue(50)
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(25, 0)
 aCircleRadius.setValue(50)
 aSession.finishOperation()
index 28aba7762db84a42c6900e2dc144cdf831923250..306f1803e76494f6595e6b99d70b675c3008eb07 100644 (file)
@@ -59,8 +59,8 @@ norm.setValue(0, 0, 1)
 
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0., 0.)
 aCircleRadius.setValue(30.)
 aSession.finishOperation()
index c9b10c8feacfcd70a32a51922d6cb4cb741c27f9..c2d337e26a2ec41868263200540c17713b5b695a 100644 (file)
@@ -33,8 +33,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(20)
 aSession.finishOperation()
@@ -117,8 +117,8 @@ norm.setValue(0, 0, 1)
 aCircleSketchFeature.selection("External").selectSubShape("face", "Extrusion_1/To_Face_1")
 aSession.startOperation()
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(10)
 aSession.finishOperation()
index 863d2a6d0d11affe61e3a4ddd181770d67ac45ed..1512f87f3fb38a4ed4c8f98266e52ee5299d7387 100644 (file)
@@ -61,8 +61,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(20)
 aSession.finishOperation()
@@ -145,8 +145,8 @@ norm.setValue(0, 0, 1)
 aCircleSketchFeature.selection("External").selectSubShape("face", "Extrusion_1/To_Face_1")
 aSession.startOperation()
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(0, 0)
 aCircleRadius.setValue(10)
 aSession.finishOperation()
index 175b08fdf86e696e59924fa5c67084d0bc3fec12..c33308acb21a5cf4c0ff8f584d479c847785705f 100644 (file)
@@ -46,8 +46,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(50, 50)
 aCircleRadius.setValue(20)
 aSession.finishOperation()
index 7adf336245fcb522d8d82f0cbd019ef3e15053d6..2fef110c0411604a7a4e9a49c10d205a79f3baa9 100644 (file)
@@ -58,8 +58,8 @@ for i in xrange(0, N):
         norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
         norm.setValue(0, 0, 1)
         aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-        anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-        aCircleRadius = aSketchCircle.real("CircleRadius")
+        anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+        aCircleRadius = aSketchCircle.real("circle_radius")
         anCircleCentr.setValue(0.5 + step * (0.5 + i), 0.5 + step * (0.5 + j))
         aCircleRadius.setValue(radius)
         aSketchFeatures.append(aSketchFeature)
index f6d95033d504cd45abab887b0d4fbce565d2572a..d981d535f256005cd6cbe3d0d028482fe3c70dc1 100644 (file)
@@ -46,8 +46,8 @@ norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
 aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(50, 50)
 aCircleRadius.setValue(20)
 aSession.finishOperation()
index 2b6f931ac779978cd7a84cc65bc5ed6cfdd43530..3ccfd563b76bc26095e94b72cb01d08fc891b041 100644 (file)
@@ -33,13 +33,13 @@ norm.setValue(0, 0, 1)
 
 # Create circles
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(-25, 0)
 aCircleRadius.setValue(50)
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(25, 0)
 aCircleRadius.setValue(50)
 aSession.finishOperation()
index 87223200698d78bd340a951e7f4ad17ba6023349..02687c2590dfec87e98ca7870e7897f241a77dec 100644 (file)
@@ -76,9 +76,3 @@
 %include "GeomAPI_XYZ.h"
 %include "GeomAPI_Trsf.h"
 %include "GeomAPI_Wire.h"
-
-%include "std_list.i"
-%include "std_set.i"
-
-%template(PointList) std::list<std::shared_ptr<GeomAPI_Pnt> >;
-%template(PointSet) std::set<std::shared_ptr<GeomAPI_Pnt> >;
index a50e343ca11607142790e9b3a18450690d3826cb..7cb9f20ba2fdb02df4fb556aa8af1b27e040e562 100644 (file)
 // Author:      Artem ZHIDKOV
 
 #include <GeomAPI_Circ2d.h>
-#include <GeomAPI_Ax3.h>
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Shape.h>
 
-#include <BRep_Tool.hxx>
-#include <gp_Dir2d.hxx>
 #include <gp_Circ2d.hxx>
-#include <gp_Lin2d.hxx>
 #include <gp_Pnt2d.hxx>
-#include <gp_Ax2d.hxx>
-#include <GccAna_Circ2d3Tan.hxx>
-#include <GccAna_Circ2dTanCen.hxx>
-#include <GccEnt.hxx>
-#include <GccEnt_QualifiedCirc.hxx>
-#include <GccEnt_QualifiedLin.hxx>
 #include <GeomLib_Tool.hxx>
 #include <Geom2d_Circle.hxx>
-#include <Geom2dAPI_ProjectPointOnCurve.hxx>
-#include <Geom_Plane.hxx>
-#include <IntAna2d_AnaIntersection.hxx>
 #include <Precision.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Edge.hxx>
-
-#include <vector>
 
 #define MY_CIRC2D implPtr<gp_Circ2d>()
 
-typedef std::shared_ptr<Geom2dAdaptor_Curve>  CurveAdaptorPtr;
-
-class CircleBuilder
-{
-public:
-  CircleBuilder(const std::shared_ptr<GeomAPI_Ax3>& theBasePlane)
-    : myPlane(new Geom_Plane(theBasePlane->impl<gp_Ax3>()))
-  {}
-
-  void addCenter(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter)
-  { myCenter = theCenter; }
-
-  void addPassingEntity(const std::shared_ptr<GeomAPI_Interface>& theEntity)
-  {
-    std::shared_ptr<GeomAPI_Pnt2d> aPoint = std::dynamic_pointer_cast<GeomAPI_Pnt2d>(theEntity);
-    if (aPoint)
-      addPassingPoint(aPoint);
-    else {
-      std::shared_ptr<GeomAPI_Shape> aShape = std::dynamic_pointer_cast<GeomAPI_Shape>(theEntity);
-      if (aShape)
-        addTangentCurve(aShape);
-    }
-  }
-
-  void addTangentCurve(const std::shared_ptr<GeomAPI_Shape>& theEdge)
-  {
-    if (!theEdge->isEdge())
-      return;
-
-    const TopoDS_Edge& anEdge = TopoDS::Edge(theEdge->impl<TopoDS_Shape>());
-
-    double aFirst, aLast;
-    TopLoc_Location aLoc;
-    Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, myPlane, aLoc, aFirst, aLast);
-    CurveAdaptorPtr aCurveAdaptor(new Geom2dAdaptor_Curve(aCurve, aFirst, aLast));
-
-    myTangentShapes.push_back(aCurveAdaptor);
-  }
-
-  void addPassingPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
-  {
-    myPassingPoints.push_back(thePoint->impl<gp_Pnt2d>());
-  }
-
-  gp_Circ2d* circle()
-  {
-    gp_Circ2d* aResult = 0;
-    if (myCenter) {
-      if (myPassingPoints.size() == 1)
-        aResult = circleByCenterAndPassingPoint();
-      else if (myTangentShapes.size() == 1)
-        aResult = circleByCenterAndTangent();
-    } else {
-      switch (myPassingPoints.size()) {
-      case 0:
-        aResult = circleByThreeTangentCurves();
-        break;
-      case 1:
-        aResult = circleByPointAndTwoTangentCurves();
-        break;
-      case 2:
-        aResult = circleByTwoPointsAndTangentCurve();
-        break;
-      case 3:
-        aResult = circleByThreePassingPoints();
-        break;
-      default:
-        break;
-      }
-    }
-    return aResult;
-  }
-
-private:
-  gp_Circ2d* circleByCenterAndPassingPoint()
-  {
-    const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
-    GccAna_Circ2dTanCen aBuilder(myPassingPoints[0], aCenter);
-    if (aBuilder.NbSolutions() > 0)
-      return new gp_Circ2d(aBuilder.ThisSolution(1));
-    return 0;
-  }
-
-  gp_Circ2d* circleByCenterAndTangent()
-  {
-    const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
-    CurveAdaptorPtr aCurve = myTangentShapes[0];
-
-    std::shared_ptr<GccAna_Circ2dTanCen> aCircleBuilder;
-    if (aCurve->GetType() == GeomAbs_Line) {
-      aCircleBuilder = std::shared_ptr<GccAna_Circ2dTanCen>(
-          new GccAna_Circ2dTanCen(aCurve->Line(), aCenter));
-    } else if (aCurve->GetType() == GeomAbs_Circle) {
-      aCircleBuilder = std::shared_ptr<GccAna_Circ2dTanCen>(new GccAna_Circ2dTanCen(
-          GccEnt::Unqualified(aCurve->Circle()), aCenter, Precision::Confusion()));
-    }
-
-    return getProperCircle(aCircleBuilder);
-  }
-
-  gp_Circ2d* getProperCircle(const std::shared_ptr<GccAna_Circ2dTanCen>& theBuilder) const
-  {
-    if (!theBuilder)
-      return 0;
-
-    CurveAdaptorPtr aCurve = myTangentShapes[0];
-
-    gp_Circ2d* aResult = 0;
-    int aNbSol = theBuilder->NbSolutions();
-    double aParSol, aPonTgCurve;
-    gp_Pnt2d aTgPnt;
-    for (int i = 1; i <= aNbSol && aCurve; ++i) {
-      theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
-      if (aPonTgCurve >= aCurve->FirstParameter() && aPonTgCurve <= aCurve->LastParameter()) {
-        aResult = new gp_Circ2d(theBuilder->ThisSolution(i));
-        break;
-      }
-    }
-    // unable to build circle passing through the tangent curve,
-    // so get a circle passing any tangent point
-    if (!aResult && aNbSol > 0)
-      aResult =  new gp_Circ2d(theBuilder->ThisSolution(1));
-    return aResult;
-  }
-
-
-  gp_Circ2d* circleByThreeTangentCurves()
-  {
-    std::shared_ptr<GccEnt_QualifiedCirc> aTgCirc[3];
-    std::shared_ptr<GccEnt_QualifiedLin>  aTgLine[3];
-    int aNbTgCirc = 0;
-    int aNbTgLine = 0;
-
-    std::vector<CurveAdaptorPtr>::iterator anIt = myTangentShapes.begin();
-    for (; anIt != myTangentShapes.end(); ++anIt) {
-      switch ((*anIt)->GetType()) {
-      case GeomAbs_Line:
-        aTgLine[aNbTgLine++] = std::shared_ptr<GccEnt_QualifiedLin>(
-            new GccEnt_QualifiedLin((*anIt)->Line(), GccEnt_unqualified));
-        break;
-      case GeomAbs_Circle:
-        aTgCirc[aNbTgCirc++] = std::shared_ptr<GccEnt_QualifiedCirc>(
-            new GccEnt_QualifiedCirc((*anIt)->Circle(), GccEnt_unqualified));
-        break;
-      default:
-        break;
-      }
-    }
-    if (aNbTgCirc + aNbTgLine != 3)
-      return 0;
-
-    std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
-    switch (aNbTgLine) {
-    case 0:
-      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
-          *aTgCirc[0], *aTgCirc[1], *aTgCirc[2], Precision::Confusion()));
-      break;
-    case 1:
-      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
-          *aTgCirc[0], *aTgCirc[1], *aTgLine[0], Precision::Confusion()));
-      break;
-    case 2:
-      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
-          *aTgCirc[0], *aTgLine[0], *aTgLine[1], Precision::Confusion()));
-      break;
-    case 3:
-      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
-          *aTgLine[0], *aTgLine[1], *aTgLine[0], Precision::Confusion()));
-      break;
-    default:
-      break;
-    }
-
-    return getProperCircle(aCircleBuilder);
-  }
-
-  gp_Circ2d* circleByPointAndTwoTangentCurves()
-  {
-    const gp_Pnt2d& aPoint = myPassingPoints[0];
-    CurveAdaptorPtr aCurve1 = myTangentShapes[0];
-    CurveAdaptorPtr aCurve2 = myTangentShapes[1];
-    if (!aCurve1 || !aCurve2)
-      return 0;
-
-    std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
-    if (aCurve1->GetType() == GeomAbs_Line) {
-      if (aCurve2->GetType() == GeomAbs_Line) {
-        aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
-            new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve1->Line()),
-                                  GccEnt::Unqualified(aCurve2->Line()),
-                                  aPoint, Precision::Confusion()));
-      } else if (aCurve2->GetType() == GeomAbs_Circle) {
-        aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
-            new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve2->Circle()),
-                                  GccEnt::Unqualified(aCurve1->Line()),
-                                  aPoint, Precision::Confusion()));
-      }
-    } else if (aCurve1->GetType() == GeomAbs_Circle) {
-      if (aCurve2->GetType() == GeomAbs_Line) {
-        aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
-            new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve1->Circle()),
-                                  GccEnt::Unqualified(aCurve2->Line()),
-                                  aPoint, Precision::Confusion()));
-      } else if (aCurve2->GetType() == GeomAbs_Circle) {
-        aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
-            new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve2->Circle()),
-                                  GccEnt::Unqualified(aCurve1->Circle()),
-                                  aPoint, Precision::Confusion()));
-      }
-    }
-
-    return getProperCircle(aCircleBuilder);
-  }
-
-  gp_Circ2d* circleByTwoPointsAndTangentCurve()
-  {
-    const gp_Pnt2d& aPoint1 = myPassingPoints[0];
-    const gp_Pnt2d& aPoint2 = myPassingPoints[1];
-    CurveAdaptorPtr aCurve = myTangentShapes[0];
-    if (!aCurve)
-      return 0;
-
-    std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
-    if (aCurve->GetType() == GeomAbs_Line) {
-      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
-        GccEnt::Unqualified(aCurve->Line()), aPoint1, aPoint2, Precision::Confusion()));
-    } else if (aCurve->GetType() == GeomAbs_Circle) {
-      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
-          GccEnt::Unqualified(aCurve->Circle()), aPoint1, aPoint2, Precision::Confusion()));
-    }
-
-    return getProperCircle(aCircleBuilder);
-  }
-
-  gp_Circ2d* circleByThreePassingPoints()
-  {
-    GccAna_Circ2d3Tan aCircleBuilder(myPassingPoints[0],
-                                     myPassingPoints[1],
-                                     myPassingPoints[2],
-                                     Precision::Confusion());
-    if (aCircleBuilder.NbSolutions() > 0)
-      return new gp_Circ2d(aCircleBuilder.ThisSolution(1));
-    return 0;
-  }
-
-
-  gp_Circ2d* getProperCircle(const std::shared_ptr<GccAna_Circ2d3Tan>& theBuilder) const
-  {
-    if (!theBuilder)
-      return 0;
-
-    gp_Circ2d* aResult = 0;
-    int aNbSol = theBuilder->NbSolutions();
-    double aParSol, aPonTgCurve;
-    gp_Pnt2d aTgPnt;
-    for (int i = 1; i <= aNbSol; ++i) {
-      bool isApplicable = false;
-      if (myTangentShapes.size() >= 1) {
-        theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
-        isApplicable = aPonTgCurve >= myTangentShapes[0]->FirstParameter() &&
-                       aPonTgCurve <= myTangentShapes[0]->LastParameter();
-      }
-      if (myTangentShapes.size() >= 2 && isApplicable) {
-        theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
-        isApplicable = aPonTgCurve >= myTangentShapes[1]->FirstParameter() &&
-                       aPonTgCurve <= myTangentShapes[1]->LastParameter();
-      }
-      if (myTangentShapes.size() >= 3 && isApplicable) {
-        theBuilder->Tangency3(i, aParSol, aPonTgCurve, aTgPnt);
-        isApplicable = aPonTgCurve >= myTangentShapes[2]->FirstParameter() &&
-                       aPonTgCurve <= myTangentShapes[2]->LastParameter();
-      }
-
-      if (isApplicable) {
-        aResult = new gp_Circ2d(theBuilder->ThisSolution(i));
-        break;
-      }
-    }
-    // unable to build circle passing through the tangent curve => get any tangent point
-    if (!aResult && aNbSol > 0)
-      aResult =  new gp_Circ2d(theBuilder->ThisSolution(1));
-    return aResult;
-  }
-
-private:
-  Handle(Geom_Plane) myPlane;
-  std::shared_ptr<GeomAPI_Pnt2d> myCenter;
-  std::vector<gp_Pnt2d> myPassingPoints;
-  std::vector<CurveAdaptorPtr> myTangentShapes;
-};
-
-typedef std::shared_ptr<CircleBuilder> CircleBuilderPtr;
-
 
 static gp_Circ2d* newCirc2d(const double theCenterX, const double theCenterY, const gp_Dir2d theDir,
                             const double theRadius)
@@ -351,49 +40,6 @@ static gp_Circ2d* newCirc2d(const double theCenterX, const double theCenterY,
   return newCirc2d(theCenterX, theCenterY, aDir, aRadius);
 }
 
-static gp_Circ2d* newCirc2d(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
-                            const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
-                            const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint)
-{
-  gp_XY aFirstPnt(theFirstPoint->x(), theFirstPoint->y());
-  gp_XY aSecondPnt(theSecondPoint->x(), theSecondPoint->y());
-  gp_XY aThirdPnt(theThirdPoint->x(), theThirdPoint->y());
-
-  gp_XY aVec12 = aSecondPnt - aFirstPnt;
-  gp_XY aVec23 = aThirdPnt - aSecondPnt;
-  gp_XY aVec31 = aFirstPnt - aThirdPnt;
-
-  // coefficients to calculate center
-  double aCoeff1, aCoeff2, aCoeff3;
-
-  // square of parallelogram
-  double aSquare2 = aVec12.Crossed(aVec23);
-  aSquare2 *= aSquare2 * 2.0;
-  if (aSquare2 < 1.e-20) {
-    // if two points are equal, build a circle on two different points as on diameter
-    double aSqLen12 = aVec12.SquareModulus();
-    double aSqLen23 = aVec23.SquareModulus();
-    double aSqLen31 = aVec31.SquareModulus();
-    if (aSqLen12 < Precision::SquareConfusion() &&
-        aSqLen23 < Precision::SquareConfusion() &&
-        aSqLen31 < Precision::SquareConfusion())
-      return NULL;
-    aCoeff1 = aCoeff2 = aCoeff3 = 1.0 / 3.0;
-  }
-  else {
-    aCoeff1 = aVec23.Dot(aVec23) / aSquare2 * aVec12.Dot(aVec31.Reversed());
-    aCoeff2 = aVec31.Dot(aVec31) / aSquare2 * aVec23.Dot(aVec12.Reversed());
-    aCoeff3 = aVec12.Dot(aVec12) / aSquare2 * aVec31.Dot(aVec23.Reversed());
-  }
-  // center
-  gp_XY aCenter = aFirstPnt * aCoeff1 + aSecondPnt * aCoeff2 + aThirdPnt * aCoeff3;
-  // radius
-  double aRadius = (aFirstPnt - aCenter).Modulus();
-
-  gp_Dir2d aDir(aFirstPnt - aCenter);
-  return newCirc2d(aCenter.X(), aCenter.Y(), aDir, aRadius);
-}
-
 
 
 GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
@@ -410,36 +56,6 @@ GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
 {
 }
 
-GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
-                               const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
-                               const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint)
-    : GeomAPI_Interface(newCirc2d(theFirstPoint, theSecondPoint, theThirdPoint))
-{
-}
-
-GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
-                               const std::shared_ptr<GeomAPI_Shape>& theTangent,
-                               const std::shared_ptr<GeomAPI_Ax3>&   thePlane)
-{
-  CircleBuilderPtr aBuilder(new CircleBuilder(thePlane));
-  aBuilder->addCenter(theCenter);
-  aBuilder->addTangentCurve(theTangent);
-  setImpl(aBuilder->circle());
-}
-
-GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Interface>& theEntity1,
-                               const std::shared_ptr<GeomAPI_Interface>& theEntity2,
-                               const std::shared_ptr<GeomAPI_Interface>& theEntity3,
-                               const std::shared_ptr<GeomAPI_Ax3>&       thePlane)
-{
-  CircleBuilderPtr aBuilder(new CircleBuilder(thePlane));
-  aBuilder->addPassingEntity(theEntity1);
-  aBuilder->addPassingEntity(theEntity2);
-  aBuilder->addPassingEntity(theEntity3);
-  setImpl(aBuilder->circle());
-}
-
-
 const std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Circ2d::project(
     const std::shared_ptr<GeomAPI_Pnt2d>& thePoint) const
 {
index 0777ad3540e384c5411c1074f341a8b42d08c91a..42e47defaba1018dcc460823afbae2dd476b5ac7 100644 (file)
@@ -33,26 +33,6 @@ class GeomAPI_Circ2d : public GeomAPI_Interface
   GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
                  const std::shared_ptr<GeomAPI_Dir2d>& theDir, double theRadius);
 
-  /// Creation of circle defined by three points lying on it
-  GEOMAPI_EXPORT
-  GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
-                 const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
-                 const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint);
-
-  /// Creation of a circle defined by center and a tangent curve on the given plane
-  GEOMAPI_EXPORT
-  GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
-                 const std::shared_ptr<GeomAPI_Shape>& theTangent,
-                 const std::shared_ptr<GeomAPI_Ax3>&   thePlane);
-
-  /// Creation of a circle passing through or tangent to given entities.
-  /// Supported items are GeomAPI_Pnt2d or GeomAPI_Shape
-  GEOMAPI_EXPORT
-  GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Interface>& theEntity1,
-                 const std::shared_ptr<GeomAPI_Interface>& theEntity2,
-                 const std::shared_ptr<GeomAPI_Interface>& theEntity3,
-                 const std::shared_ptr<GeomAPI_Ax3>&       thePlane);
-
   /// Return center of the circle
   GEOMAPI_EXPORT
   const std::shared_ptr<GeomAPI_Pnt2d> center() const;
index b8c32ec2867a16c9b1e28ef83be64607b363c12c..c811116dff5529eb7b96243b3eecbd07d05bdf2d 100644 (file)
@@ -444,8 +444,11 @@ GeomShapePtr GeomAPI_Shape::intersect(const GeomShapePtr theShape) const
   if (aResult.ShapeType() == TopAbs_COMPOUND) {
     NCollection_List<TopoDS_Shape> aSubs;
     addSimpleToList(aResult, aSubs);
-    if (aSubs.Size() == 1)
+    if(aSubs.Size() == 1) {
       aResult = aSubs.First();
+    } else if(aSubs.Size() == 0) {
+      return GeomShapePtr();
+    }
   }
 
   GeomShapePtr aResShape(new GeomAPI_Shape);
index 0ad49ca0f7f9607906714d8ca1b945ec2b7dd4ab..628b3f2358c9cc178c8a2f8739eb2faae10d3167 100644 (file)
@@ -52,6 +52,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_ConeSegment.h
     GeomAlgoAPI_Symmetry.h
     GeomAlgoAPI_Scale.h
+    GeomAlgoAPI_Circ2dBuilder.h
 )
 
 SET(PROJECT_SOURCES
@@ -100,6 +101,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_ConeSegment.cpp
     GeomAlgoAPI_Symmetry.cpp
     GeomAlgoAPI_Scale.cpp
+    GeomAlgoAPI_Circ2dBuilder.cpp
 )
 
 SET(PROJECT_LIBRARIES
index e79c011bdb0cca7c845a1715aa73a3ad294f47d9..6ba7fc781e0e444790fdcf1af8f142171ae0b453 100644 (file)
@@ -2,9 +2,6 @@
 %module GeomAlgoAPI
 %{
   #include "GeomAlgoAPI_swig.h"
-
-  // fix for SWIG v2.0.4
-  #define SWIGPY_SLICE_ARG(obj) ((PySliceObject*)(obj))
 %}
 
 // import other modules
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Circ2dBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Circ2dBuilder.cpp
new file mode 100644 (file)
index 0000000..754ef43
--- /dev/null
@@ -0,0 +1,539 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Circ2dBuilder.cpp
+// Created:     3 April 2017
+// Author:      Artem ZHIDKOV
+
+#include <GeomAlgoAPI_Circ2dBuilder.h>
+#include <GeomAPI_Ax3.h>
+#include <GeomAPI_Circ2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Shape.h>
+
+#include <BRep_Tool.hxx>
+#include <ElCLib.hxx>
+#include <GccAna_Circ2d2TanRad.hxx>
+#include <GccAna_Circ2d3Tan.hxx>
+#include <GccAna_Circ2dTanCen.hxx>
+#include <GccEnt.hxx>
+#include <GccEnt_QualifiedCirc.hxx>
+#include <GccEnt_QualifiedLin.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom_Plane.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+
+#include <cmath>
+
+typedef std::shared_ptr<gp_Circ2d> Circ2dPtr;
+typedef std::shared_ptr<Geom2dAdaptor_Curve> CurveAdaptorPtr;
+typedef std::vector< std::shared_ptr<GccEnt_QualifiedCirc> > VectorOfGccCirc;
+typedef std::vector< std::shared_ptr<GccEnt_QualifiedLin> >  VectorOfGccLine;
+
+
+// Provide different mechanisms to create circle:
+// * by passing points
+// * by tangent edges
+// * with specified radius
+// * etc.
+class CircleBuilder
+{
+public:
+  CircleBuilder(const std::shared_ptr<GeomAPI_Ax3>& theBasePlane)
+    : myPlane(new Geom_Plane(theBasePlane->impl<gp_Ax3>())),
+      myRadius(0.0)
+  {}
+
+  void setRadius(const double theRadius)
+  { myRadius = theRadius; }
+
+  void setCenter(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter)
+  { myCenter = theCenter; }
+
+  void setTangentCurves(const std::vector< std::shared_ptr<GeomAPI_Shape> >& theEdges)
+  {
+    std::vector< std::shared_ptr<GeomAPI_Shape> >::const_iterator anEdgeIt;
+    for (anEdgeIt = theEdges.begin(); anEdgeIt != theEdges.end(); ++anEdgeIt) {
+      const TopoDS_Edge& anEdge = TopoDS::Edge((*anEdgeIt)->impl<TopoDS_Shape>());
+
+      double aFirst, aLast;
+      TopLoc_Location aLoc;
+      Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, myPlane, aLoc, aFirst, aLast);
+      CurveAdaptorPtr aCurveAdaptor(new Geom2dAdaptor_Curve(aCurve, aFirst, aLast));
+
+      // sort curves (circles should become first)
+      if (aCurveAdaptor->GetType() == GeomAbs_Circle)
+        myTangentShapes.insert(myTangentShapes.begin(), aCurveAdaptor);
+      else
+        myTangentShapes.push_back(aCurveAdaptor);
+    }
+  }
+
+  void setPassingPoints(const std::vector< std::shared_ptr<GeomAPI_Pnt2d> >& thePoints)
+  {
+    std::vector< std::shared_ptr<GeomAPI_Pnt2d> >::const_iterator aPIt;
+    for (aPIt = thePoints.begin(); aPIt != thePoints.end(); ++aPIt)
+      myPassingPoints.push_back((*aPIt)->impl<gp_Pnt2d>());
+  }
+
+  void setClosestPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
+  { myClosestPoint = thePoint; }
+
+
+  Circ2dPtr circle()
+  {
+    Circ2dPtr aResult;
+    if (myCenter) {
+      if (myPassingPoints.size() == 1)
+        aResult = circleByCenterAndPassingPoint();
+      else if (myTangentShapes.size() == 1)
+        aResult = circleByCenterAndTangent();
+      else if (myRadius > 0.0)
+        aResult = circleByCenterAndRadius();
+    } else if (myRadius > 0.0) {
+      if (myTangentShapes.size() == 2)
+        aResult = circleByRadiusAndTwoTangentCurves();
+    } else {
+      switch (myPassingPoints.size()) {
+      case 0:
+        aResult = circleByThreeTangentCurves();
+        break;
+      case 1:
+        aResult = circleByPointAndTwoTangentCurves();
+        break;
+      case 2:
+        aResult = circleByTwoPointsAndTangentCurve();
+        break;
+      case 3:
+        aResult = circleByThreePassingPoints();
+        break;
+      default:
+        break;
+      }
+    }
+    return aResult;
+  }
+
+private:
+  Circ2dPtr circleByCenterAndRadius()
+  {
+    const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
+    return Circ2dPtr(new gp_Circ2d(gp_Ax2d(aCenter, gp::DX2d()), myRadius));
+  }
+
+  Circ2dPtr circleByCenterAndPassingPoint()
+  {
+    const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
+    if (aCenter.SquareDistance(myPassingPoints[0]) > Precision::SquareConfusion()) {
+      GccAna_Circ2dTanCen aBuilder(myPassingPoints[0], aCenter);
+      if (aBuilder.NbSolutions() > 0)
+        return Circ2dPtr(new gp_Circ2d(aBuilder.ThisSolution(1)));
+    }
+    return Circ2dPtr();
+  }
+
+  Circ2dPtr circleByCenterAndTangent()
+  {
+    const gp_Pnt2d& aCenter = myCenter->impl<gp_Pnt2d>();
+    CurveAdaptorPtr aCurve = myTangentShapes[0];
+
+    std::shared_ptr<GccAna_Circ2dTanCen> aCircleBuilder;
+    if (aCurve->GetType() == GeomAbs_Line) {
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2dTanCen>(
+          new GccAna_Circ2dTanCen(aCurve->Line(), aCenter));
+    } else if (aCurve->GetType() == GeomAbs_Circle) {
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2dTanCen>(new GccAna_Circ2dTanCen(
+          GccEnt::Unqualified(aCurve->Circle()), aCenter, Precision::Confusion()));
+    }
+
+    return getProperCircle(aCircleBuilder);
+  }
+
+  Circ2dPtr getProperCircle(const std::shared_ptr<GccAna_Circ2dTanCen>& theBuilder) const
+  {
+    if (!theBuilder)
+      return Circ2dPtr();
+
+    CurveAdaptorPtr aCurve = myTangentShapes[0];
+
+    int aNbSol = theBuilder->NbSolutions();
+    if (aNbSol == 0)
+      return Circ2dPtr();
+
+    int anAppropriateSolution = 1;
+    double aMinDist = Precision::Infinite();
+
+    double aParSol, aPonTgCurve;
+    gp_Pnt2d aTgPnt;
+    for (int i = 1; i <= aNbSol && aCurve; ++i) {
+      theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
+      if (isParamOnCurve(aPonTgCurve, aCurve)) {
+        double aDist = distanceToClosestPoint(theBuilder->ThisSolution(i));
+        if (aDist < aMinDist) {
+          anAppropriateSolution = i;
+          aMinDist = aDist;
+        }
+      }
+    }
+
+    return Circ2dPtr(new gp_Circ2d(theBuilder->ThisSolution(anAppropriateSolution)));
+  }
+
+  double distanceToClosestPoint(const gp_Circ2d& theCirc) const
+  {
+    if (myClosestPoint) {
+      double aDist = myClosestPoint->impl<gp_Pnt2d>().Distance(theCirc.Location());
+      return fabs(aDist - theCirc.Radius());
+    }
+    return 0.0;
+  }
+
+
+  Circ2dPtr circleByThreeTangentCurves()
+  {
+    VectorOfGccCirc aTgCirc;
+    VectorOfGccLine aTgLine;
+    convertTangentCurvesToGccEnt(aTgCirc, aTgLine);
+
+    if (aTgCirc.size() + aTgLine.size() != 3)
+      return Circ2dPtr();
+
+    std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
+    switch (aTgLine.size()) {
+    case 0:
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
+          *aTgCirc[0], *aTgCirc[1], *aTgCirc[2], Precision::Confusion()));
+      break;
+    case 1:
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
+          *aTgCirc[0], *aTgCirc[1], *aTgLine[0], Precision::Confusion()));
+      break;
+    case 2:
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
+          *aTgCirc[0], *aTgLine[0], *aTgLine[1], Precision::Confusion()));
+      break;
+    case 3:
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
+          *aTgLine[0], *aTgLine[1], *aTgLine[0], Precision::Confusion()));
+      break;
+    default:
+      break;
+    }
+
+    return getProperCircle(aCircleBuilder);
+  }
+
+  Circ2dPtr circleByPointAndTwoTangentCurves()
+  {
+    const gp_Pnt2d& aPoint = myPassingPoints[0];
+    CurveAdaptorPtr aCurve1 = myTangentShapes[0];
+    CurveAdaptorPtr aCurve2 = myTangentShapes[1];
+    if (!aCurve1 || !aCurve2)
+      return Circ2dPtr();
+
+    std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
+    if (aCurve1->GetType() == GeomAbs_Line) {
+      if (aCurve2->GetType() == GeomAbs_Line) {
+        aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
+            new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve1->Line()),
+                                  GccEnt::Unqualified(aCurve2->Line()),
+                                  aPoint, Precision::Confusion()));
+      } else if (aCurve2->GetType() == GeomAbs_Circle) {
+        aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
+            new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve2->Circle()),
+                                  GccEnt::Unqualified(aCurve1->Line()),
+                                  aPoint, Precision::Confusion()));
+      }
+    } else if (aCurve1->GetType() == GeomAbs_Circle) {
+      if (aCurve2->GetType() == GeomAbs_Line) {
+        aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
+            new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve1->Circle()),
+                                  GccEnt::Unqualified(aCurve2->Line()),
+                                  aPoint, Precision::Confusion()));
+      } else if (aCurve2->GetType() == GeomAbs_Circle) {
+        aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(
+            new GccAna_Circ2d3Tan(GccEnt::Unqualified(aCurve2->Circle()),
+                                  GccEnt::Unqualified(aCurve1->Circle()),
+                                  aPoint, Precision::Confusion()));
+      }
+    }
+
+    return getProperCircle(aCircleBuilder);
+  }
+
+  Circ2dPtr circleByTwoPointsAndTangentCurve()
+  {
+    const gp_Pnt2d& aPoint1 = myPassingPoints[0];
+    const gp_Pnt2d& aPoint2 = myPassingPoints[1];
+    CurveAdaptorPtr aCurve = myTangentShapes[0];
+    if (!aCurve)
+      return Circ2dPtr();
+
+    std::shared_ptr<GccAna_Circ2d3Tan> aCircleBuilder;
+    if (aCurve->GetType() == GeomAbs_Line) {
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
+        GccEnt::Unqualified(aCurve->Line()), aPoint1, aPoint2, Precision::Confusion()));
+    } else if (aCurve->GetType() == GeomAbs_Circle) {
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d3Tan>(new GccAna_Circ2d3Tan(
+          GccEnt::Unqualified(aCurve->Circle()), aPoint1, aPoint2, Precision::Confusion()));
+    }
+
+    return getProperCircle(aCircleBuilder);
+  }
+
+  Circ2dPtr circleByThreePassingPoints()
+  {
+    GccAna_Circ2d3Tan aCircleBuilder(myPassingPoints[0],
+                                     myPassingPoints[1],
+                                     myPassingPoints[2],
+                                     Precision::Confusion());
+    if (aCircleBuilder.NbSolutions() > 0)
+      return Circ2dPtr(new gp_Circ2d(aCircleBuilder.ThisSolution(1)));
+    return Circ2dPtr();
+  }
+
+  Circ2dPtr getProperCircle(const std::shared_ptr<GccAna_Circ2d3Tan>& theBuilder) const
+  {
+    if (!theBuilder)
+      return Circ2dPtr();
+
+    int aNbSol = theBuilder->NbSolutions();
+    if (aNbSol == 0)
+      return Circ2dPtr();
+
+    int anAppropriateSolution = 1;
+    double aMinDist = Precision::Infinite();
+
+    double aParSol, aPonTgCurve;
+    gp_Pnt2d aTgPnt;
+    for (int i = 1; i <= aNbSol; ++i) {
+      bool isApplicable = false;
+      if (myTangentShapes.size() >= 1) {
+        theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
+        isApplicable = isParamOnCurve(aPonTgCurve, myTangentShapes[0]);
+      }
+      if (myTangentShapes.size() >= 2 && isApplicable) {
+        theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
+        isApplicable = isParamOnCurve(aPonTgCurve, myTangentShapes[1]);
+      }
+      if (myTangentShapes.size() >= 3 && isApplicable) {
+        theBuilder->Tangency3(i, aParSol, aPonTgCurve, aTgPnt);
+        isApplicable = isParamOnCurve(aPonTgCurve, myTangentShapes[2]);
+      }
+
+      if (isApplicable) {
+        double aDist = distanceToClosestPoint(theBuilder->ThisSolution(i));
+        if (aDist < aMinDist) {
+          anAppropriateSolution = i;
+          aMinDist = aDist;
+        }
+      }
+    }
+
+    return Circ2dPtr(new gp_Circ2d(theBuilder->ThisSolution(anAppropriateSolution)));
+  }
+
+
+  Circ2dPtr circleByRadiusAndTwoTangentCurves()
+  {
+    VectorOfGccCirc aTgCirc;
+    VectorOfGccLine aTgLine;
+    convertTangentCurvesToGccEnt(aTgCirc, aTgLine);
+
+    if (aTgCirc.size() + aTgLine.size() != 2)
+      return Circ2dPtr();
+
+    std::shared_ptr<GccAna_Circ2d2TanRad> aCircleBuilder;
+    switch (aTgLine.size()) {
+    case 0:
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
+          *aTgCirc[0], *aTgCirc[1], myRadius, Precision::Confusion()));
+      break;
+    case 1:
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
+          *aTgCirc[0], *aTgLine[0], myRadius, Precision::Confusion()));
+      break;
+    case 2:
+      aCircleBuilder = std::shared_ptr<GccAna_Circ2d2TanRad>(new GccAna_Circ2d2TanRad(
+          *aTgLine[0], *aTgLine[1], myRadius, Precision::Confusion()));
+      break;
+    default:
+      break;
+    }
+
+    return getProperCircle(aCircleBuilder);
+  }
+
+  Circ2dPtr getProperCircle(const std::shared_ptr<GccAna_Circ2d2TanRad>& theBuilder) const
+  {
+    if (!theBuilder)
+      return Circ2dPtr();
+
+    int aNbSol = theBuilder->NbSolutions();
+    if (aNbSol == 0)
+      return Circ2dPtr();
+
+    int anAppropriateSolution = 1;
+    double aMinDist = Precision::Infinite();
+
+    double aParSol, aPonTgCurve;
+    gp_Pnt2d aTgPnt;
+    for (int i = 1; i <= aNbSol; ++i) {
+      bool isApplicable = false;
+      if (myTangentShapes.size() >= 1) {
+        theBuilder->Tangency1(i, aParSol, aPonTgCurve, aTgPnt);
+        isApplicable = isParamInCurve(aPonTgCurve, myTangentShapes[0]);
+      }
+      if (myTangentShapes.size() >= 2 && isApplicable) {
+        theBuilder->Tangency2(i, aParSol, aPonTgCurve, aTgPnt);
+        isApplicable = isParamInCurve(aPonTgCurve, myTangentShapes[1]);
+      }
+
+      if (isApplicable) {
+        double aDist = distanceToClosestPoint(theBuilder->ThisSolution(i));
+        if (aDist < aMinDist) {
+          anAppropriateSolution = i;
+          aMinDist = aDist;
+        }
+      }
+    }
+
+    return Circ2dPtr(new gp_Circ2d(theBuilder->ThisSolution(anAppropriateSolution)));
+  }
+
+
+  void convertTangentCurvesToGccEnt(VectorOfGccCirc& theTangentCircles,
+                                    VectorOfGccLine& theTangentLines)
+  {
+    theTangentCircles.reserve(3);
+    theTangentLines.reserve(3);
+
+    std::vector<CurveAdaptorPtr>::iterator anIt = myTangentShapes.begin();
+    for (; anIt != myTangentShapes.end(); ++anIt) {
+      switch ((*anIt)->GetType()) {
+      case GeomAbs_Line:
+        theTangentLines.push_back(
+            std::shared_ptr<GccEnt_QualifiedLin>(
+            new GccEnt_QualifiedLin((*anIt)->Line(), GccEnt_unqualified))
+        );
+        break;
+      case GeomAbs_Circle:
+        theTangentCircles.push_back(
+            std::shared_ptr<GccEnt_QualifiedCirc>(
+            new GccEnt_QualifiedCirc((*anIt)->Circle(), GccEnt_unqualified))
+        );
+        break;
+      default:
+        break;
+      }
+    }
+  }
+
+
+  // boundary parameters of curve are NOT applied
+  static bool isParamInCurve(double& theParameter, const CurveAdaptorPtr& theCurve)
+  {
+    if (theCurve->Curve()->IsPeriodic()) {
+      theParameter = ElCLib::InPeriod(theParameter,
+                                      theCurve->FirstParameter(),
+                                      theCurve->FirstParameter() + theCurve->Period());
+    }
+    return theParameter > theCurve->FirstParameter() &&
+           theParameter < theCurve->LastParameter();
+  }
+
+  // boundary parameters of curve are applied too
+  static bool isParamOnCurve(double& theParameter, const CurveAdaptorPtr& theCurve)
+  {
+    if (theCurve->IsPeriodic()) {
+      theParameter = ElCLib::InPeriod(theParameter,
+                                      theCurve->FirstParameter(),
+                                      theCurve->FirstParameter() + theCurve->Period());
+    }
+    return theParameter >= theCurve->FirstParameter() &&
+           theParameter <= theCurve->LastParameter();
+  }
+
+private:
+  Handle(Geom_Plane) myPlane;
+  std::shared_ptr<GeomAPI_Pnt2d> myCenter;
+  std::vector<gp_Pnt2d> myPassingPoints;
+  std::vector<CurveAdaptorPtr> myTangentShapes;
+  double myRadius;
+  std::shared_ptr<GeomAPI_Pnt2d> myClosestPoint;
+};
+
+
+
+
+
+GeomAlgoAPI_Circ2dBuilder::GeomAlgoAPI_Circ2dBuilder(const std::shared_ptr<GeomAPI_Ax3>& thePlane)
+  : myPlane(thePlane),
+    myRadius(0.)
+{
+}
+
+void GeomAlgoAPI_Circ2dBuilder::setRadius(const double theRadius)
+{
+  myRadius = theRadius;
+}
+
+void GeomAlgoAPI_Circ2dBuilder::setCenter(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter)
+{
+  myCenter = theCenter;
+}
+
+void GeomAlgoAPI_Circ2dBuilder::addTangentCurve(const std::shared_ptr<GeomAPI_Shape>& theEdge)
+{
+  if (theEdge->isEdge())
+    myTangentShapes.push_back(theEdge);
+}
+
+void GeomAlgoAPI_Circ2dBuilder::addPassingPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
+{
+  myPassingPoints.push_back(thePoint);
+}
+
+void GeomAlgoAPI_Circ2dBuilder::setClosestPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
+{
+  myClosestPoint = thePoint;
+}
+
+std::shared_ptr<GeomAPI_Circ2d> GeomAlgoAPI_Circ2dBuilder::circle(
+    const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+    const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
+    const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint)
+{
+  std::shared_ptr<GeomAPI_Ax3> aPlane(new GeomAPI_Ax3);
+
+  GeomAlgoAPI_Circ2dBuilder aBuilder(aPlane);
+  aBuilder.addPassingPoint(theFirstPoint);
+  aBuilder.addPassingPoint(theSecondPoint);
+  aBuilder.addPassingPoint(theThirdPoint);
+  return aBuilder.circle();
+}
+
+std::shared_ptr<GeomAPI_Circ2d> GeomAlgoAPI_Circ2dBuilder::circle()
+{
+  CircleBuilder aCircleBuilder(myPlane);
+  aCircleBuilder.setCenter(myCenter);
+  aCircleBuilder.setTangentCurves(myTangentShapes);
+  aCircleBuilder.setPassingPoints(myPassingPoints);
+  aCircleBuilder.setClosestPoint(myClosestPoint);
+  aCircleBuilder.setRadius(myRadius);
+  Circ2dPtr aCirc2d = aCircleBuilder.circle();
+
+  std::shared_ptr<GeomAPI_Circ2d> aCircle;
+  if (aCirc2d) {
+    const gp_Pnt2d& aCenter = aCirc2d->Location();
+    const gp_Dir2d& aXAxis = aCirc2d->XAxis().Direction();
+
+    std::shared_ptr<GeomAPI_Pnt2d> aCircleCenter(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y()));
+    std::shared_ptr<GeomAPI_Dir2d> aCircleDir(new GeomAPI_Dir2d(aXAxis.X(), aXAxis.Y()));
+
+    aCircle = std::shared_ptr<GeomAPI_Circ2d>(
+        new GeomAPI_Circ2d(aCircleCenter, aCircleDir, aCirc2d->Radius()));
+  }
+  return aCircle;
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Circ2dBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_Circ2dBuilder.h
new file mode 100644 (file)
index 0000000..6aad612
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Circ2dBuilder.h
+// Created:     3 April 2017
+// Author:      Artem ZHIDKOV
+
+#ifndef GeomAlgoAPI_Circ2dBuilder_H_
+#define GeomAlgoAPI_Circ2dBuilder_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <memory>
+#include <vector>
+
+class GeomAPI_Ax3;
+class GeomAPI_Circ2d;
+class GeomAPI_Pnt2d;
+class GeomAPI_Shape;
+
+/// \class GeomAlgoAPI_Circ2dBuilder
+/// \ingroup DataAlgo
+/// \brief Creates circle in 2D space satisfying combination of the following constraints:
+///        * center of a circle
+///        * passing through the point
+///        * tangent to a curve
+///        * fixed radius
+class GeomAlgoAPI_Circ2dBuilder
+{
+public:
+  /// \brief Create a builder object.
+  ///        Constraints should be applied separately.
+  /// \param thePlane [in]  plane to project tangent curves
+  GEOMALGOAPI_EXPORT
+  GeomAlgoAPI_Circ2dBuilder(const std::shared_ptr<GeomAPI_Ax3>& thePlane);
+
+  /// \brief Set fixed radius of the circle
+  GEOMALGOAPI_EXPORT
+  void setRadius(const double theRadius);
+
+  /// \brief Set fixed center of the circle
+  GEOMALGOAPI_EXPORT
+  void setCenter(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter);
+
+  /// \brief Constrain circle to be tangent to the given edge
+  GEOMALGOAPI_EXPORT
+  void addTangentCurve(const std::shared_ptr<GeomAPI_Shape>& theEdge);
+
+  /// \brief Constrain circle to pass through the given point
+  GEOMALGOAPI_EXPORT
+  void addPassingPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
+
+  /// \brief Optional constraint to find circle closest to the given point
+  GEOMALGOAPI_EXPORT
+  void setClosestPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
+
+  /// \brief Build circle
+  GEOMALGOAPI_EXPORT
+  std::shared_ptr<GeomAPI_Circ2d> circle();
+
+  /// \brief Create a circle passing through three points
+  GEOMALGOAPI_EXPORT
+  static std::shared_ptr<GeomAPI_Circ2d>
+      circle(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+             const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint,
+             const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPoint);
+
+private:
+  std::shared_ptr<GeomAPI_Ax3>                  myPlane;
+  std::shared_ptr<GeomAPI_Pnt2d>                myCenter;
+  std::vector< std::shared_ptr<GeomAPI_Pnt2d> > myPassingPoints;
+  std::vector< std::shared_ptr<GeomAPI_Shape> > myTangentShapes;
+  std::shared_ptr<GeomAPI_Pnt2d>                myClosestPoint;
+  double                                        myRadius;
+};
+
+#endif
index cf3ab9623ab8d0a94497b6c1c3cd7b9f963551b2..1df2c7f8745f37b64881a809f7885f922452a77e 100644 (file)
@@ -648,27 +648,6 @@ bool GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(
   return true;
 }
 
-//==================================================================================================
-bool GeomAlgoAPI_ShapeTools::isShapesIntersects(
-  const std::shared_ptr<GeomAPI_Shape> theShape1,
-  const std::shared_ptr<GeomAPI_Shape> theShape2)
-{
-  if(!theShape1.get() || !theShape2.get()) {
-    return false;
-  }
-
-  const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
-  const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
-
-  BRepExtrema_DistShapeShape aDist(aShape1, aShape2);
-  aDist.Perform();
-  if(aDist.IsDone() && aDist.Value() < Precision::Confusion()) {
-    return true;
-  }
-
-  return false;
-}
-
 //==================================================================================================
 bool GeomAlgoAPI_ShapeTools::isShapeValid(const std::shared_ptr<GeomAPI_Shape> theShape)
 {
index e6df0520b50345f4cf85c1137641a4ec966f9044..d3b712585176a24a8e7316e42611d48153ebf8ba 100644 (file)
@@ -108,14 +108,6 @@ public:
     const std::shared_ptr<GeomAPI_Shape> theSubShape,
     const std::shared_ptr<GeomAPI_Shape> theBaseShape);
 
-  /// \brief Checks that shapes intersects.
-  /// \param[in] theShape1 first shape.
-  /// \param[in] theShape2 second shape.
-  /// \return true if shapes intersects.
-  GEOMALGOAPI_EXPORT static bool GeomAlgoAPI_ShapeTools::isShapesIntersects(
-    const std::shared_ptr<GeomAPI_Shape> theShape1,
-    const std::shared_ptr<GeomAPI_Shape> theShape2);
-
   /// \return true if theShape is valid.
   GEOMALGOAPI_EXPORT static bool isShapeValid(const std::shared_ptr<GeomAPI_Shape> theShape);
 
index c22b7abd318d07d7ae67cc67cab5cbba7b547ba0..54cb1069eee9ff42f5dc077f84c0e03324d5730a 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_Tools.h>
 
 //=================================================================================================
 bool GeomValidators_BooleanArguments::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
@@ -26,15 +28,47 @@ bool GeomValidators_BooleanArguments::isValid(const std::shared_ptr<ModelAPI_Fea
 
   std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
 
-  std::shared_ptr<ModelAPI_AttributeSelectionList> anAttrSelList = theFeature->selectionList(*anIt);
+  bool isAllInSameCompSolid = true;
+  ResultCompSolidPtr aCompSolid;
+
+  AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
   if(anAttrSelList) {
     anObjectsNb = anAttrSelList->size();
+    for(int anIndex = 0; anIndex < anObjectsNb; ++anIndex) {
+      AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
+      ResultPtr aContext = anAttr->context();
+      ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+      if(aResCompSolidPtr.get()) {
+        if(aCompSolid.get()) {
+          isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
+        } else {
+          aCompSolid = aResCompSolidPtr;
+        }
+      } else {
+        isAllInSameCompSolid = false;
+      }
+    }
   }
   anIt++;
 
+
   anAttrSelList = theFeature->selectionList(*anIt);
   if(anAttrSelList) {
     aToolsNb = anAttrSelList->size();
+    for(int anIndex = 0; anIndex < aToolsNb; ++anIndex) {
+      AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
+      ResultPtr aContext = anAttr->context();
+      ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+      if(aResCompSolidPtr.get()) {
+        if(aCompSolid.get()) {
+          isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
+        } else {
+          aCompSolid = aResCompSolidPtr;
+        }
+      } else {
+        isAllInSameCompSolid = false;
+      }
+    }
   }
   anIt++;
 
@@ -43,14 +77,31 @@ bool GeomValidators_BooleanArguments::isValid(const std::shared_ptr<ModelAPI_Fea
     anOperationType = anAttrInt->value();
   }
 
-  if(anOperationType == 1 && (anObjectsNb + aToolsNb > 1)) {
-    return true;
-  } else if (anOperationType != 1 && anObjectsNb > 0 && aToolsNb > 0) {
-    return true;
+  if(anOperationType == 1) {
+    // Fuse operation
+    if(anObjectsNb + aToolsNb < 2) {
+      theError = "Not enough arguments for Fuse operation.";
+      return false;
+    } else if(isAllInSameCompSolid) {
+      theError = "Operations only between sub-shapes of the same shape not allowed.";
+      return false;
+    }
+  } else {
+    if(anObjectsNb < 1) {
+      theError = "Objects not selected.";
+      return false;
+    }
+    if(aToolsNb < 1) {
+      theError = "Tools not selected.";
+      return false;
+    }
+    if(isAllInSameCompSolid) {
+      theError = "Operations only between sub-shapes of the same shape not allowed.";
+      return false;
+    }
   }
 
-  theError = "Not enough arguments";
-  return false;
+  return true;
 }
 
 //=================================================================================================
index 9ebc852596933efb58c8747649f55e09410b5e9e..513c39d5c65b0afcc68d5d6793bed57ec070da0c 100644 (file)
@@ -663,7 +663,12 @@ void Model_AttributeSelection::selectSubShape(
       }
     }
     setValue(aCont, aShapeToBeSelected);
+    return;
   }
+
+  TDF_Label aSelLab = selectionLabel();
+  setInvalidIfFalse(aSelLab, false);
+  reset();
 }
 
 int Model_AttributeSelection::Id()
index ce8386a2ef30547398597ecd3b3321697c0979bd..7c93ab7b596a35df445dca43627dc1d615ac12cd 100755 (executable)
@@ -235,6 +235,17 @@ bool Model_Document::load(const char* theDirName, const char* theFileName, Docum
 bool Model_Document::save(
   const char* theDirName, const char* theFileName, std::list<std::string>& theResults)
 {
+  // if the history line is not in the end, move it to the end before save, otherwise
+  // problems with results restore and (the most important) naming problems will appear
+  // due to change evolution to SELECTION (problems in NamedShape and Name)
+  FeaturePtr aWasCurrent;
+  std::shared_ptr<Model_Session> aSession =
+    std::dynamic_pointer_cast<Model_Session>(Model_Session::get());
+  if (currentFeature(false) != lastFeature()) {
+    aSession->setCheckTransactions(false);
+    aWasCurrent = currentFeature(false);
+    setCurrentFeature(lastFeature(), false);
+  }
   // create a directory in the root document if it is not yet exist
   Handle(Model_Application) anApp = Model_Application::getApplication();
   if (isRoot()) {
@@ -253,6 +264,10 @@ bool Model_Document::save(
     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
     Events_InfoMessage("Model_Document",
         "Exception in saving of document: %1").arg(aFail->GetMessageString()).send();
+    if (aWasCurrent.get()) { // return the current feature to the initial position
+      setCurrentFeature(aWasCurrent, false);
+      aSession->setCheckTransactions(true);
+    }
     return false;
   }
   bool isDone = aStatus == PCDM_SS_OK || aStatus == PCDM_SS_No_Obj;
@@ -271,6 +286,12 @@ bool Model_Document::save(
         break;
     }
   }
+
+  if (aWasCurrent.get()) { // return the current feature to the initial position
+    setCurrentFeature(aWasCurrent, false);
+    aSession->setCheckTransactions(true);
+  }
+
   myTransactionSave = int(myTransactions.size());
   if (isDone) {  // save also sub-documents if any
     theResults.push_back(TCollection_AsciiString(aPath).ToCString());
@@ -536,10 +557,14 @@ bool Model_Document::finishOperation()
   }
   myObjs->synchronizeBackRefs();
   Events_Loop* aLoop = Events_Loop::loop();
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+  static const Events_ID kCreatedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED);
+  static const Events_ID kUpdatedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED);
+  static const Events_ID kRedispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static const Events_ID kDeletedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED);
+  aLoop->flush(kCreatedEvent);
+  aLoop->flush(kUpdatedEvent);
+  aLoop->flush(kRedispEvent);
+  aLoop->flush(kDeletedEvent);
 
   if (isNestedClosed) {
     if (myDoc->CommitCommand())
@@ -550,12 +575,19 @@ bool Model_Document::finishOperation()
   // to avoid messages about modifications outside of the transaction
   // and to rebuild everything after all updates and creates
   if (isRoot()) { // once for root document
-    Events_Loop::loop()->autoFlush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
     static std::shared_ptr<Events_Message> aFinishMsg
       (new Events_Message(Events_Loop::eventByName("FinishOperation")));
     Events_Loop::loop()->send(aFinishMsg);
-    Events_Loop::loop()->autoFlush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED), false);
   }
+
+  while(aLoop->hasGrouppedEvent(kCreatedEvent) || aLoop->hasGrouppedEvent(kUpdatedEvent) ||
+        aLoop->hasGrouppedEvent(kRedispEvent) || aLoop->hasGrouppedEvent(kDeletedEvent)) {
+    aLoop->flush(kCreatedEvent);
+    aLoop->flush(kUpdatedEvent);
+    aLoop->flush(kRedispEvent);
+    aLoop->flush(kDeletedEvent);
+  }
+
   // to avoid "updated" message appearance by updater
   //aLoop->clear(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
 
@@ -918,22 +950,23 @@ void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis)
   // add it after all nested (otherwise the nested will be disabled)
   CompositeFeaturePtr aCompositeAfter =
     std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theAfterThis);
+  FeaturePtr anAfterThisSub = theAfterThis;
   if (aCompositeAfter.get()) {
     FeaturePtr aSub = aCompositeAfter;
     do {
       FeaturePtr aNext = myObjs->nextFeature(aSub);
       if (!isSub(aCompositeAfter, aNext)) {
-        theAfterThis = aSub;
+        anAfterThisSub = aSub;
         break;
       }
       aSub = aNext;
     } while (aSub.get());
   }
 
-  myObjs->moveFeature(theMoved, theAfterThis);
+  myObjs->moveFeature(theMoved, anAfterThisSub);
   if (aCurrentUp) { // make the moved feature enabled or disabled due to the real status
     setCurrentFeature(currentFeature(false), false);
-  } else if (theAfterThis == currentFeature(false)) {
+  } else if (theAfterThis == currentFeature(false) || anAfterThisSub == currentFeature(false)) {
     // must be after move to make enabled all features which are before theMoved
     setCurrentFeature(theMoved, true);
   }
index dca740f6c558dc6d821677c2b574f460446b7c56..798e234c5c5c7b68a1c14bb6c0a5bf6d46f84d7e 100644 (file)
@@ -1124,17 +1124,14 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
           if (!aNewP->partDoc().get())
             // create the part result: it is better to restore the previous result if it is possible
             theFeature->execute();
-          break;
         } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
           theFeature->execute(); // construction shapes are needed for sketch solver
-          break;
         } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
           aNewBody = createGroup(theFeature->data(), aResIndex);
         } else if (aGroup->Get() == ModelAPI_ResultField::group().c_str()) {
           aNewBody = createField(theFeature->data(), aResIndex);
         } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) {
           theFeature->attributeChanged("expression"); // just produce a value
-          break;
         } else {
           Events_InfoMessage("Model_Objects", "Unknown type of result is found in the document:")
             .arg(TCollection_AsciiString(aGroup->Get()).ToCString()).send();
index 924783bb25e1955dd2ce3dbe4fda71cd65b2e054..c73516a43069ef9382894fe3eb1456a588310bb1 100644 (file)
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Tools.h>
 
+#include <TDF_ChildIDIterator.hxx>
 #include <TDF_CopyTool.hxx>
 #include <TDF_DataSet.hxx>
 #include <TDF_RelocationTable.hxx>
 #include <TDF_ClosureTool.hxx>
 
+#include <TNaming_Builder.hxx>
+#include <TNaming_Iterator.hxx>
+#include <TNaming_NamedShape.hxx>
+
+#include <TopoDS_Shape.hxx>
+
 static Model_Session* myImpl = new Model_Session();
 
 // t oredirect all calls to the root document
@@ -331,6 +338,50 @@ std::shared_ptr<ModelAPI_Document> Model_Session::copy(
   aRT->SetRelocation(aSourceRoot, aTargetRoot);
   TDF_CopyTool::Copy(aDS, aRT);
 
+  // TODO: remove after fix in OCCT.
+  // All named shapes are stored in reversed order, so to fix this we reverse them back.
+  for(TDF_ChildIDIterator aChildIter(aTargetRoot, TNaming_NamedShape::GetID(), true);
+      aChildIter.More();
+      aChildIter.Next()) {
+    Handle(TNaming_NamedShape) aNamedShape =
+      Handle(TNaming_NamedShape)::DownCast(aChildIter.Value());
+    if (aNamedShape.IsNull()) {
+      continue;
+    }
+
+    TopoDS_Shape aShape = aNamedShape->Get();
+    if(aShape.IsNull() || aShape.ShapeType() != TopAbs_COMPOUND) {
+      continue;
+    }
+
+    TNaming_Evolution anEvol = aNamedShape->Evolution();
+    std::list<std::pair<TopoDS_Shape, TopoDS_Shape> > aShapePairs; // to store old and new shapes
+    for(TNaming_Iterator anIter(aNamedShape); anIter.More(); anIter.Next()) {
+      aShapePairs.push_back(
+        std::pair<TopoDS_Shape, TopoDS_Shape>(anIter.OldShape(), anIter.NewShape()));
+    }
+
+    // Add in reverse order.
+    TDF_Label aLabel = aNamedShape->Label();
+    TNaming_Builder aBuilder(aLabel);
+    for(std::list<std::pair<TopoDS_Shape, TopoDS_Shape> >::iterator aPairsIter =
+          aShapePairs.begin();
+        aPairsIter != aShapePairs.end();
+        aPairsIter++) {
+      if (anEvol == TNaming_GENERATED) {
+        aBuilder.Generated(aPairsIter->first, aPairsIter->second);
+      } else if (anEvol == TNaming_MODIFY) {
+        aBuilder.Modify(aPairsIter->first, aPairsIter->second);
+      } else if (anEvol == TNaming_DELETE) {
+        aBuilder.Delete(aPairsIter->first);
+      } else if (anEvol == TNaming_PRIMITIVE) {
+        aBuilder.Generated(aPairsIter->second);
+      } else if (anEvol == TNaming_SELECTED) {
+        aBuilder.Select(aPairsIter->second, aPairsIter->first);
+      }
+    }
+  }
+
   TDF_LabelList anEmptyUpdated;
   aNew->objects()->synchronizeFeatures(anEmptyUpdated, true, true, true, true);
   return aNew;
index f1e23dcf8f4588637780ecde79aecfb49f6b13bf..2c18d72bc9b6c673acce6543c69f36a40d20d7b4 100755 (executable)
@@ -500,10 +500,6 @@ bool Model_Update::processFeature(FeaturePtr theFeature)
           (*aRIter)->attributeChanged("External");
       }
     }
-    // send event that sketch is prepared to be recomputed
-    static Events_ID anID = Events_Loop::eventByName("SketchPrepared");
-    std::shared_ptr<Events_Message> aMsg(new Events_Message(anID, this));
-    Events_Loop::loop()->send(aMsg);
   }
 
   if (!aIsModified) { // no modification is needed
index bf126c17b35654806c9b3b091861a7c56fc0cefa..7314b48aaadd89a409aca0ab582003e22add29ce 100644 (file)
@@ -174,11 +174,6 @@ bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>&
     for(; aValidatorIt != aValidators.cend(); aValidatorIt++) {
       const std::string& aValidatorID = aValidatorIt->first;
       const std::list<std::string>& anArguments = aValidatorIt->second;
-      // validators() checks invalid validator names
-      //if (!aValidator) {
-      //  Events_Error::send(std::string("Validator ") + aValidatorID + " was not registered");
-      //  continue;
-      //}
       const ModelAPI_FeatureValidator* aFValidator =
         dynamic_cast<const ModelAPI_FeatureValidator*>(validator(aValidatorID));
       if (aFValidator) {
@@ -196,30 +191,8 @@ bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>&
       }
     }
   }
-  // The default validator was retrned by validators() and was checked in previous cycle
-  //// check default validator
-  //std::map<std::string, ModelAPI_Validator*>::const_iterator aDefaultVal = myIDs.find(kDefaultId);
-  //if(aDefaultVal != myIDs.end()) {
-  //  static const std::list<std::string> anEmptyArgList;
-  //  const ModelAPI_FeatureValidator* aFValidator =
-  //    dynamic_cast<const ModelAPI_FeatureValidator*>(aDefaultVal->second);
-  //  if (aFValidator) {
-  //    std::string anError;
-  //    if (!aFValidator->isValid(theFeature, anEmptyArgList, anError)) {
-  //      if (anError.empty())
-  //        anError = "Unknown error.";
-  //      anError = "Feature invalidated by \"" + kDefaultId + "\" with error: " + anError;
-  //      theFeature->setError(anError, false);
-  //      theFeature->data()->execState(ModelAPI_StateInvalidArgument);
-  //      return false;
-  //    }
-  //  }
-  //}
 
   // check all attributes for validity
-  // Validity of data is checked by "Model_FeatureValidator" (kDefaultId)
-  // if (!aData || !aData->isValid())
-  //   return false;
   static const std::string kAllTypes = "";
   std::list<std::string> aLtAttributes = aData->attributesIDs(kAllTypes);
   std::list<std::string>::const_iterator anAttrIt = aLtAttributes.cbegin();
index e227fdeab8cc997ed36f174bf68b86fa0830cfc4..fea8bb975fb63c4dab94419929f8d086683c4ca9 100644 (file)
@@ -28,10 +28,12 @@ SET(PROJECT_HEADERS
     ModelAPI_CompositeFeature.h
     ModelAPI_Data.h
     ModelAPI_Document.h
+    ModelAPI_EventReentrantMessage.h
     ModelAPI_Events.h
     ModelAPI_Expression.h
     ModelAPI_Feature.h
     ModelAPI_FeatureValidator.h
+    ModelAPI_IReentrant.h
     ModelAPI_Object.h
     ModelAPI_Plugin.h
     ModelAPI_Result.h
@@ -69,10 +71,12 @@ SET(PROJECT_SOURCES
     ModelAPI_CompositeFeature.cpp
     ModelAPI_Data.cpp
     ModelAPI_Document.cpp
+    ModelAPI_EventReentrantMessage.cpp
     ModelAPI_Events.cpp
     ModelAPI_Expression.cpp
     ModelAPI_Feature.cpp
     ModelAPI_FeatureValidator.cpp
+    ModelAPI_IReentrant.cpp
     ModelAPI_Object.cpp
     ModelAPI_Plugin.cpp
     ModelAPI_Result.cpp
index ab67ad2ae809d58e261b469c57ee8188ba3a98d3..09cad6cd7876d17fb9a0e48791e93bd8a4500c14 100644 (file)
@@ -10,9 +10,6 @@
 
 %{
   #include "ModelAPI_swig.h"
-
-  // fix for SWIG v2.0.4
-  #define SWIGPY_SLICE_ARG(obj) ((PySliceObject*)(obj))
 %}
 
 // import other modules
@@ -178,5 +175,8 @@ template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr
 %template(modelAPI_AttributeRefAttrList)   shared_ptr_cast<ModelAPI_AttributeRefAttrList, ModelAPI_Attribute>;
 %template(modelAPI_AttributeTables)        shared_ptr_cast<ModelAPI_AttributeTables, ModelAPI_Attribute>;
 
+%template(PointList) std::list<std::shared_ptr<GeomAPI_Pnt> >;
+%template(PointSet) std::set<std::shared_ptr<GeomAPI_Pnt> >;
+
 // Geometry casts
 %template(shapeToEdge) shared_ptr_cast<GeomAPI_Edge, GeomAPI_Shape>;
diff --git a/src/ModelAPI/ModelAPI_EventReentrantMessage.cpp b/src/ModelAPI/ModelAPI_EventReentrantMessage.cpp
new file mode 100644 (file)
index 0000000..b527e70
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:    ModelAPI_EventReentrantMessage.cpp
+// Created: 30 Mar 2017
+// Author:  Natalia ERMOLAEVA
+
+#include <ModelAPI_EventReentrantMessage.h>
+
+ModelAPI_EventReentrantMessage::ModelAPI_EventReentrantMessage(
+                                                 const Events_ID theID,
+                                                 const void* theSender)
+: Events_Message(theID, theSender)
+{
+}
diff --git a/src/ModelAPI/ModelAPI_EventReentrantMessage.h b/src/ModelAPI/ModelAPI_EventReentrantMessage.h
new file mode 100644 (file)
index 0000000..ded9c8b
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:    ModelAPI_EventReentrantMessage.h
+// Created: 30 Mar 2017
+// Author:  Natalia ERMOLAEVA
+
+#ifndef ModelAPI_EventReentrantMessage_H_
+#define ModelAPI_EventReentrantMessage_H_
+
+#include <Events_Message.h>
+#include <Events_Loop.h>
+
+#include <ModelAPI.h>
+
+#include <memory>
+
+class ModelAPI_Object;
+class ModelAPI_Feature;
+class ModelAPI_Attribute;
+class GeomAPI_Pnt2d;
+
+/// Message that style of visualization of parameter is changed.
+/// It will be shown as expression or value
+class ModelAPI_EventReentrantMessage : public Events_Message
+{
+public:
+  /// Creates an empty message
+  MODELAPI_EXPORT ModelAPI_EventReentrantMessage(const Events_ID theID,
+                                                 const void* theSender = 0);
+  /// The virtual destructor
+  MODELAPI_EXPORT virtual ~ModelAPI_EventReentrantMessage() {}
+  /// Static. Returns EventID of the message.
+  MODELAPI_EXPORT static Events_ID eventId()
+  {
+    static const char * MY_EVENT_REENTRANT_MESSAGE_ID("EventReentrantMessage");
+    return Events_Loop::eventByName(MY_EVENT_REENTRANT_MESSAGE_ID);
+  }
+
+  /// Fills previous feature parameter
+  MODELAPI_EXPORT void setCreatedFeature(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  { myCreatedFeature = theFeature; }
+
+  /// Returns previous feature parameter
+  MODELAPI_EXPORT const std::shared_ptr<ModelAPI_Feature>& createdFeature() const
+  { return myCreatedFeature; }
+
+  /// Fills selected object parameter
+  /// \theObject a feature or result
+  MODELAPI_EXPORT void setSelectedObject(const std::shared_ptr<ModelAPI_Object>& theObject)
+  { mySelectedObject = theObject; }
+
+  /// Returns selected object parameter
+  MODELAPI_EXPORT const std::shared_ptr<ModelAPI_Object>& selectedObject() const
+  { return mySelectedObject; }
+
+  /// Fills selected attribute parameter
+  /// \theAttribute
+  MODELAPI_EXPORT void setSelectedAttribute
+                                  (const std::shared_ptr<ModelAPI_Attribute>& theAttribute)
+  { mySelectedAttribute = theAttribute; }
+
+  /// Returns selected attribute parameter
+  MODELAPI_EXPORT const std::shared_ptr<ModelAPI_Attribute>& selectedAttribute()
+  { return mySelectedAttribute; }
+
+  /// Fills clicked point
+  /// \thePoint
+  MODELAPI_EXPORT void setClickedPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
+  { myClickedPoint = thePoint; }
+
+  /// Returns clicked point
+  MODELAPI_EXPORT const std::shared_ptr<GeomAPI_Pnt2d>& clickedPoint()
+  { return myClickedPoint; }
+
+private:
+  std::shared_ptr<ModelAPI_Feature> myCreatedFeature; ///< previous object
+  std::shared_ptr<ModelAPI_Object> mySelectedObject; ///< selected object
+  std::shared_ptr<ModelAPI_Attribute> mySelectedAttribute; ///< selected attribute
+  std::shared_ptr<GeomAPI_Pnt2d> myClickedPoint; ///< clicked point
+};
+
+typedef std::shared_ptr<ModelAPI_EventReentrantMessage> ReentrantMessagePtr;
+
+
+#endif
index 73e0428d257012d02c765a953b48970cf390f769..bb387f81c92d22e435e60be0ec24141fc4123301 100644 (file)
@@ -55,7 +55,8 @@ void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResu
     myResults.push_back(theResult);
   }
   // in any case result becomes enabled
-  theResult->setDisabled(theResult, false);
+  if (!isDisabled()) // disabled feature may be executed when it is added as not enabled (#2078)
+    theResult->setDisabled(theResult, false);
 }
 
 void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResult,
diff --git a/src/ModelAPI/ModelAPI_IReentrant.cpp b/src/ModelAPI/ModelAPI_IReentrant.cpp
new file mode 100644 (file)
index 0000000..53697f9
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        ModelAPI_IReentrant.cpp
+// Created:     30 Mar 2017
+// Author:      Natalia ERMOLAEVA
+
+#include <ModelAPI_IReentrant.h>
+
+ModelAPI_IReentrant::~ModelAPI_IReentrant()
+{
+}
diff --git a/src/ModelAPI/ModelAPI_IReentrant.h b/src/ModelAPI/ModelAPI_IReentrant.h
new file mode 100644 (file)
index 0000000..b556193
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        ModelAPI_IReentrant.hxx
+// Created:     30 Mar 2017
+// Author:      Natalia ERMOLAEVA
+
+#ifndef ModelAPI_IReentrant_H
+#define ModelAPI_IReentrant_H
+
+#include "ModelAPI.h"
+
+#include <vector>
+#include <memory>
+
+class Events_Message;
+
+/** \class ModelAPI_IReentrant
+ *  \ingroup DataModel
+ *  \brief Interface of a class which can process specific messages
+ */
+class ModelAPI_IReentrant
+{
+public:
+  MODELAPI_EXPORT virtual ~ModelAPI_IReentrant();
+
+  /// Apply information of the message to current object.
+  /// \param theMessage a container of information
+  /// \return a next active attribute name
+  virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage) = 0;
+};
+
+typedef std::shared_ptr<ModelAPI_IReentrant> ModelReentrantPtr;
+
+#endif
index 21fce85e8ec2b847e2b3629e71e88f5cc02ae7f8..bce23fd6a121ef14c48345478fef291e331b213d 100755 (executable)
@@ -65,8 +65,8 @@ aSession.startOperation()
 aSketchFeature2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
 aSketchFeature2.selection("External").setValue(aXOYPlane, None);
 aCirc1 = aSketchFeature2.addFeature("SketchCircle")
-geomDataAPI_Point2D(aCirc1.attribute("CircleCenter")).setValue(100, 50)
-aCirc1.real("CircleRadius").setValue(40)
+geomDataAPI_Point2D(aCirc1.attribute("circle_center")).setValue(100, 50)
+aCirc1.real("circle_radius").setValue(40)
 aSession.finishOperation()
 
 #=========================================================================
@@ -97,8 +97,8 @@ aSession.startOperation()
 aSketchFeature3 = featureToCompositeFeature(aPart.addFeature("Sketch"))
 aSketchFeature3.selection("External").setValue(aXOYPlane, None);
 aCirc2 = aSketchFeature3.addFeature("SketchCircle")
-geomDataAPI_Point2D(aCirc2.attribute("CircleCenter")).setValue(20, 20)
-aCirc2.real("CircleRadius").setValue(10)
+geomDataAPI_Point2D(aCirc2.attribute("circle_center")).setValue(20, 20)
+aCirc2.real("circle_radius").setValue(10)
 aSession.finishOperation()
 
 #=========================================================================
index 70cd9cb72e59f4c4ea8ca550c86c1b4170dbe065..d7115a09118e7279c06fc5de6af84f2889c101aa 100755 (executable)
@@ -191,7 +191,8 @@ void appendShapePoints(const GeomShapePtr& theShape,
   }
 }
 
-void ModelGeomAlgo_Point2D::getPointsIntersectedShape(const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
+void ModelGeomAlgo_Point2D::getPointsIntersectedShape(
+                        const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
                         const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
                         PointToRefsMap& thePointToAttributeOrObject)
 {
index 15826a20c3f37d5571224c59952099ab830a3e7e..afa13b127a1c63d1f6356eca43345e2daf6cbffc 100755 (executable)
@@ -51,7 +51,8 @@ public:
   /// \param isSkipFeatureAttributes a boolean value if coincidences to the feature attributes
   /// should be skipped
   /// \returns found point attribute or NULL
-  static MODELGEOMALGO_EXPORT void getPointsOfReference(const std::shared_ptr<ModelAPI_Object>& theObject,
+  static MODELGEOMALGO_EXPORT
+        void getPointsOfReference(const std::shared_ptr<ModelAPI_Object>& theObject,
                                   const std::string& theReferenceFeatureKind,
                                   std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
                                   const std::string& theObjectFeatureKind = "",
index e446cff41b16ea33f764baf76007f2fb14d22a2b..61becae78807cf04e4cfc4d4c325fe667baf79e2 100644 (file)
@@ -12,6 +12,7 @@
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Feature.h>
 #include <ModelAPI_ResultCompSolid.h>
 //--------------------------------------------------------------------------------------
 
@@ -50,6 +51,11 @@ void ModelHighAPI_Selection::fillAttribute(
       return;
     case VT_TypeSubShapeNamePair:
       theAttribute->selectSubShape(myTypeSubShapeNamePair.first, myTypeSubShapeNamePair.second);
+      if(theAttribute->isInvalid()) {
+        FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
+        aFeature->setError(
+          std::string("Error: attribute \"") + theAttribute->id() + std::string("\" is invalid."));
+      }
       return;
   }
 }
index c431fc9b65055b457a9b32e887fed528a742182b..75d782817df330b989b81a2d05cf52ce0b955162 100644 (file)
@@ -392,9 +392,15 @@ bool checkPythonDump()
     aDump->execute();
   }
   bool isProblem = !aDump.get() || !aDump->error().empty(); // after "finish" dump will be removed
+  if (isProblem && aDump.get()) {
+    std::cout<<"Dump feature error "<<aDump->error()<<std::endl;
+    Events_InfoMessage anErrorMsg(std::string("checkPythonDump"), aDump->error());
+    anErrorMsg.send();
+  }
   aSession->finishOperation();
-  if (isProblem)
+  if (isProblem) {
     return false; // something is wrong during dump
+  }
 
    // map from document name to feature name to feature data
   std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> > aStore;
index 9f595fdbbf7bb5e5fa97c9467694d7d1cd882f1c..c41b0b5238233ff14c9b076196a6779037811392 100644 (file)
@@ -8,9 +8,13 @@
 #define ModuleBase_IErrorMgr_H
 
 #include "ModuleBase.h"
+
 #include <QObject>
 
+#include <memory>
+
 class ModuleBase_IPropertyPanel;
+class ModelAPI_Feature;
 
 /**
  * \class ModuleBase_IErrorMgr
@@ -34,6 +38,10 @@ public:
   /// \return Currently installed property panel
   ModuleBase_IPropertyPanel* propertyPanel() const { return myPropertyPanel; }
 
+  /// Update actions for the given feature
+  /// \param theFeature a feature
+  virtual void updateActions(const std::shared_ptr<ModelAPI_Feature>& theFeature) = 0;
+
 protected slots:
   /// Process values changed event for processing feature attribute validation errors.
   virtual void onWidgetChanged() = 0;
index 3a5aebb6a90e49f14dc750114f84b0c3c20a0ab4..7dc2d8f82e28c7b550a6c4919cb2151340858b92 100644 (file)
@@ -1,10 +1,13 @@
 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
+#include "ModelAPI_IReentrant.h"
+#include "ModelAPI_EventReentrantMessage.h"
 
 #include "ModuleBase_IModule.h"
 #include "ModuleBase_IViewer.h"
 #include "ModuleBase_ViewerPrs.h"
 #include "ModuleBase_Operation.h"
+#include "ModuleBase_IPropertyPanel.h"
 #include "ModuleBase_ISelection.h"
 #include "ModuleBase_OperationDescription.h"
 #include "ModuleBase_OperationFeature.h"
 #include "ModuleBase_WidgetFactory.h"
 #include "ModuleBase_PageWidget.h"
 #include "ModuleBase_Dialog.h"
+#include "ModuleBase_IErrorMgr.h"
 
 #include <Events_Loop.h>
+#include <Events_Message.h>
 
 #include <ModelAPI_Events.h>
 #include <ModelAPI_CompositeFeature.h>
@@ -85,9 +90,30 @@ void ModuleBase_IModule::launchOperation(const QString& theCmdId)
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                              (createOperation(theCmdId.toStdString()));
   if (aFOperation) {
-    aFOperation->initSelection(aPreSelected);
+    std::shared_ptr<Events_Message> aMessage = reentrantMessage();
+    if (aMessage.get()) {
+      setReentrantPreSelection(aMessage);
+    }
+    else
+      aFOperation->initSelection(aPreSelected);
 
     workshop()->processLaunchOperation(aFOperation);
+
+    if (aFOperation) {
+      FeaturePtr aFeature = aFOperation->feature();
+      ModelReentrantPtr aReentrantFeature =
+                                      std::dynamic_pointer_cast<ModelAPI_IReentrant>(aFeature);
+      if (aReentrantFeature.get()) {
+        if (aMessage.get()) {
+          ModuleBase_IPropertyPanel* aPanel = workshop()->propertyPanel();
+          std::string aPrevAttribute = aReentrantFeature->processEvent(aMessage);
+          workshop()->errorMgr()->updateActions(aFeature);
+
+          ModuleBase_ModelWidget* aPrevWidget = aPanel->modelWidget(aPrevAttribute);
+          aPanel->activateNextWidget(aPrevWidget);
+        }
+      }
+    }
   }
 }
 
index b57291d2615e31deba45cffd279967de61f1cf77..62b746eabb821cd8fe4c368bbece1eb705162d6c 100755 (executable)
@@ -28,8 +28,11 @@ class QMenu;
 class Config_WidgetAPI;
 class ModuleBase_ModelWidget;
 class ModuleBase_Operation;
+class ModuleBase_ViewerPrs;
+
 class ModuleBase_IWorkshop;
 class ModelAPI_Result;
+class Events_Message;
 
 class AIS_InteractiveObject;
 
@@ -229,6 +232,11 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
                                      AISObjectPtr thePrs,
                                      GeomCustomPrsPtr theCustomPrs) { return false; };
 
+  /// Modifies the given presentation in the custom way after usual customize is performed.
+  virtual bool afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
+                                     AISObjectPtr thePrs,
+                                     GeomCustomPrsPtr theCustomPrs) { return false; };
+
   /// Update the object presentable properties such as color, lines width and other
   /// If the object is result with the color attribute value set, it is used,
   /// otherwise the customize is applyed to the object's feature if it is a custom prs
@@ -312,6 +320,13 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
   virtual AttributePtr findAttribute(const ObjectPtr& theObject,
                                      const GeomShapePtr& theGeomShape) = 0;
 
+  /// Returns reentrant message if it was accepted
+  virtual std::shared_ptr<Events_Message> reentrantMessage() = 0;
+
+  /// Put current selection into reentrant message
+  /// \param theMessage a message of reentrant operation
+  virtual void setReentrantPreSelection(const std::shared_ptr<Events_Message>& theMessage) = 0;
+
   /// Returns XML information by the feature index
   /// \param theFeatureId a feature id
   /// \param theXmlCfg XML configuration
index bb6d2276a9fe1736a4a2d1773d9498a60d973d4f..37230d33de11acb989ba8d4ffec92f417fbf826e 100644 (file)
 ModuleBase_IPropertyPanel::ModuleBase_IPropertyPanel(QWidget* theParent)
  : QDockWidget(theParent), myIsEditing(false)
 {
+}
+
+ModuleBase_ModelWidget* ModuleBase_IPropertyPanel::modelWidget(
+                                          const std::string& theAttributeId) const
+{
+  ModuleBase_ModelWidget* aWidget = 0;
+  QList<ModuleBase_ModelWidget*> aWidgets = modelWidgets();
+  ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+  for (QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin();
+    anIt != aWidgets.end() && !aWidget; anIt++) {
+    ModuleBase_ModelWidget* aCurrentWidget = *anIt;
+    if (aCurrentWidget->attributeID() == theAttributeId &&
+        aCurrentWidget->canAcceptFocus() &&
+        aValidators->isCase(aCurrentWidget->feature(), aCurrentWidget->attributeID()))
+      aWidget = aCurrentWidget;
+  }
 
+  return aWidget;
 }
 
 ModuleBase_ModelWidget* ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget()
index 58683af4178d1b6233eb92ab437acf469f182f6b..123e5084e234f39398883babfd465cbaafa6acfc 100644 (file)
@@ -38,6 +38,10 @@ public:
   /// Returns all property panel's widget created by WidgetFactory
   virtual const QList<ModuleBase_ModelWidget*>& modelWidgets() const = 0;
 
+  /// Returns widget, that has the given attribute index
+  /// \param theAttributeId an attribute from XML
+  virtual ModuleBase_ModelWidget* modelWidget(const std::string& theAttributeId) const;
+
   /// Removes all widgets in the widget area of the property panel
   virtual void cleanContent() = 0;
 
index 8c5695aa8f3106da72a5f562cbb6478612dec100..a9c66405d9a8836758299ebe1ceee3920f6c2fd5 100644 (file)
@@ -21,6 +21,7 @@ class ModuleBase_IModule;
 class ModuleBase_ISelection;
 class ModuleBase_IViewer;
 class ModuleBase_IPropertyPanel;
+class ModuleBase_IErrorMgr;
 class ModuleBase_Operation;
 class ModuleBase_ViewerPrs;
 class QMainWindow;
@@ -62,6 +63,9 @@ Q_OBJECT
   //! Returns property panel
   virtual ModuleBase_IPropertyPanel* propertyPanel() const = 0;
 
+  //! Returns error manager
+  virtual ModuleBase_IErrorMgr* errorMgr() const = 0;
+
   /// A filter to process an attribute validators
   /// \return a filter
   Handle(ModuleBase_FilterValidated) validatorFilter();
index aa0470f7a6c2faca5ef62048f679b1df740ff546..f0be4ae9e58002dba8ddb0082c929506c0d2b1a0 100644 (file)
@@ -51,7 +51,7 @@ ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
 
   myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false);
 
-  myIsModifiedInEdit = theData->getBooleanAttribute(ATTR_MODIFIED_IN_EDIT, true);
+  myIsModifiedInEdit = theData->getProperty(ATTR_MODIFIED_IN_EDIT);
 
   myDefaultValue = theData->getProperty(ATTR_DEFAULT);
   myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true);
@@ -315,8 +315,18 @@ bool ModuleBase_ModelWidget::storeValue()
   bool isDone = false;
   // value is stored only in creation mode and in edition if there is not
   // XML flag prohibited modification in edit mode(macro feature circle/arc)
-  if (!isEditingMode() || isModifiedInEdit())
+  if (!isEditingMode() || isModifiedInEdit().empty())
     isDone = storeValueCustom();
+  else {
+    /// store value in an alternative attribute if possible(attribute has the same type)
+    std::string aWidgetAttribute = attributeID();
+    myAttributeID = isModifiedInEdit();
+    storeValueCustom();
+    myAttributeID = aWidgetAttribute;
+    // operation will be restarted but if isDone == true, PagedContainer will try to set focus
+    // to the current widget, but will be already deleted
+    isDone = false;
+  }
 
   emit afterValuesChanged();
 
index fcd2ad508b81e1218ea686d5031162f8c49cbee6..0b409e6feedb9ce02cd32e60c6224b8e84a938e1 100644 (file)
@@ -95,7 +95,7 @@ Q_OBJECT
 
   /// Returns this parameter value in the xml file
   /// \return the boolean result
-  bool isModifiedInEdit() const { return myIsModifiedInEdit; }
+  std::string isModifiedInEdit() const { return myIsModifiedInEdit; }
 
   /// Returns this widget value state
   /// \return the enumeration result
@@ -364,7 +364,7 @@ private:
   bool myIsInternal;
 
   // an XML state, the value is not stored into model if the widget is in edit mode
-  bool myIsModifiedInEdit;
+  std::string myIsModifiedInEdit;
 
   /// the reset state. If it is false, the reset method of the widget is not performed
   bool myUseReset;
index 3d6d9e23056a22dd0bd9380a53dd3847a01beca3..2eca3f077527b1af01e1acf371052fb6c0220137 100644 (file)
@@ -79,8 +79,8 @@ class TestParameterRename(unittest.TestCase):
         norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
         norm.setValue(0, 0, 1)
         aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-        anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-        aRadiusAttr = aSketchCircle.real("CircleRadius")
+        anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+        aRadiusAttr = aSketchCircle.real("circle_radius")
         anCircleCentr.setValue(10., 20.)
         aRadiusAttr.setValue(10.)
         self.aSession.finishOperation()
index ad85bdf51cfe8464d2ceeb52713eacbf577d1abf..69574c10aceca5459fc76dbb2b09bcd6afbbd468 100644 (file)
@@ -118,8 +118,8 @@ assert (aTmValue == round(2 * math.pi, 6))
 #=========================================================================
 aSession.startOperation()
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aRadiusAttr = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aRadiusAttr = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(250., 250)
 aRadiusAttr.setValue(25.)
 aSession.finishOperation()
index 4141338293245ce6f1d9ab46b56727746a99f0e0..0f2f90174a2879a273ba0ecb391ecac5fcc62cf7 100644 (file)
@@ -82,8 +82,8 @@ class TestParameterRename(unittest.TestCase):
         norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
         norm.setValue(0, 0, 1)
         aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-        anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-        aRadiusAttr = aSketchCircle.real("CircleRadius")
+        anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+        aRadiusAttr = aSketchCircle.real("circle_radius")
         anCircleCentr.setValue(10., 20.)
         aRadiusAttr.setValue(10.)
         self.aSession.finishOperation()
index cc52284cca9e8e51c1452c7cadf4bd56adfa6603..ded37014d7baef9c394fe685f1364105adc7d866 100755 (executable)
@@ -96,6 +96,7 @@ bool PartSet_CustomPrs::displayPresentation(
       break;
     case ModuleBase_IModule::CustomizeResults:
       PartSet_OperationPrs::getResultShapes(myFeature, myWorkshop, aFeatureShapes);
+      PartSet_OperationPrs::getPresentationShapes(myFeature, myWorkshop, aFeatureShapes);
       break;
     case ModuleBase_IModule::CustomizeHighlightedObjects:
       PartSet_OperationPrs::getHighlightedShapes(myWorkshop, aFeatureShapes);
index e7e7e8fa487f6dcbe35914be6d531f8baf0a6966..41c2d3b04db528cb807b85e8bab3ff3fd3310732 100755 (executable)
@@ -512,7 +512,7 @@ bool PartSet_Module::isActionEnableStateFixed(const int theActionId) const
 {
   bool isEnabledFixed = false;
   if (theActionId == XGUI_ActionsMgr::AcceptAll &&
-      mySketchReentrantMgr->isInternalEditStarted())
+      mySketchReentrantMgr->isInternalEditActive())
     isEnabledFixed = true;
   return isEnabledFixed;
 }
@@ -552,6 +552,17 @@ void PartSet_Module::customSubShapesSelectionModes(QIntList& theTypes)
     theTypes.append(SketcherPrs_Tools::Sel_Sketch_Wire);
 }
 
+void PartSet_Module::getGeomSelection(const std::shared_ptr<ModuleBase_ViewerPrs>& theSelected,
+                                      ObjectPtr& theObject, AttributePtr& theAttribute)
+{
+  ObjectPtr anObject = theSelected->object();
+  GeomShapePtr aShape = theSelected->shape();
+
+  theAttribute = findAttribute(anObject, aShape);
+  // TODO: try to create result if object is an external object
+  theObject = anObject;
+}
+
 bool PartSet_Module::isMouseOverWindow()
 {
   return mySketchMgr->isMouseOverWindow();
@@ -560,7 +571,7 @@ bool PartSet_Module::isMouseOverWindow()
 bool PartSet_Module::isSketchNeutralPointActivated() const
 {
   bool isNeutralPoint = true;
-  if (sketchReentranceMgr()->isInternalEditStarted())
+  if (sketchReentranceMgr()->isInternalEditActive())
     isNeutralPoint = false;
   if (myIsOperationIsLaunched)
     isNeutralPoint = false;
@@ -1015,41 +1026,10 @@ bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr the
     return aCustomized;
 
   if (!theResult.get()) {
-    bool isConflicting = myOverconstraintListener->isConflictingObject(anObject);
-    // customize sketch symbol presentation
-    if (thePrs.get()) {
-      Handle(AIS_InteractiveObject) anAISIO = thePrs->impl<Handle(AIS_InteractiveObject)>();
-      if (!anAISIO.IsNull()) {
-        if (!Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO).IsNull()) {
-          Handle(SketcherPrs_SymbolPrs) aPrs = Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO);
-          if (!aPrs.IsNull()) {
-            std::vector<int> aColor;
-            myOverconstraintListener->getConflictingColor(aColor);
-            aPrs->SetConflictingConstraint(isConflicting, aColor);
-            aCustomized = true;
-          }
-        } else if (!Handle(SketcherPrs_Coincident)::DownCast(anAISIO).IsNull()) {
-          Handle(SketcherPrs_Coincident) aPrs = Handle(SketcherPrs_Coincident)::DownCast(anAISIO);
-          if (!aPrs.IsNull()) {
-            std::vector<int> aColor;
-            myOverconstraintListener->getConflictingColor(aColor);
-            aPrs->SetConflictingConstraint(isConflicting, aColor);
-            aCustomized = true;
-          }
-        }
-      }
-    }
-    // customize sketch dimension constraint presentation
-    if (!aCustomized) {
-      std::vector<int> aColor;
-      if (isConflicting) {
-        myOverconstraintListener->getConflictingColor(aColor);
-      }
-      if (aColor.empty())
-        XGUI_CustomPrs::getDefaultColor(anObject, true, aColor);
-      if (!aColor.empty()) {
-        aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
-      }
+    std::vector<int> aColor;
+    XGUI_CustomPrs::getDefaultColor(anObject, true, aColor);
+    if (!aColor.empty()) {
+      aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
     }
   }
   // customize dimentional constrains
@@ -1058,6 +1038,48 @@ bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr the
   return aCustomized;
 }
 
+bool PartSet_Module::afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
+                                                AISObjectPtr thePrs,
+                                                GeomCustomPrsPtr theCustomPrs)
+{
+  bool aCustomized = false;
+
+  XGUI_Workshop* aWorkshop = getWorkshop();
+  XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+  ObjectPtr anObject = aDisplayer->getObject(thePrs);
+  if (!anObject)
+    return aCustomized;
+
+  std::vector<int> aColor;
+  bool aUseCustomColor = true;
+  if (aUseCustomColor)
+    myOverconstraintListener->getCustomColor(anObject, aColor);
+  // customize sketch symbol presentation
+  Handle(AIS_InteractiveObject) anAISIO = thePrs->impl<Handle(AIS_InteractiveObject)>();
+  if (!anAISIO.IsNull()) {
+    if (!Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO).IsNull()) {
+      Handle(SketcherPrs_SymbolPrs) aPrs = Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO);
+      if (!aPrs.IsNull()) {
+        aPrs->SetCustomColor(aColor);
+        aCustomized = true;
+      }
+    } else if (!Handle(SketcherPrs_Coincident)::DownCast(anAISIO).IsNull()) {
+      Handle(SketcherPrs_Coincident) aPrs = Handle(SketcherPrs_Coincident)::DownCast(anAISIO);
+      if (!aPrs.IsNull()) {
+        aPrs->SetCustomColor(aColor);
+        aCustomized = true;
+      }
+    }
+  }
+  // customize sketch dimension constraint presentation
+  if (!aCustomized) {
+    if (!aColor.empty()) { // otherwise presentation has the default color
+      aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+    }
+  }
+  return aCustomized;
+}
+
 bool PartSet_Module::customizeObject(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
                                      const bool theUpdateViewer)
 {
@@ -1413,6 +1435,18 @@ AttributePtr PartSet_Module::findAttribute(const ObjectPtr& theObject,
   return anAttribute;
 }
 
+//******************************************************
+std::shared_ptr<Events_Message> PartSet_Module::reentrantMessage()
+{
+  return sketchReentranceMgr()->reentrantMessage();
+}
+
+//******************************************************
+void PartSet_Module::setReentrantPreSelection(const std::shared_ptr<Events_Message>& theMessage)
+{
+  sketchReentranceMgr()->setReentrantPreSelection(theMessage);
+}
+
 //******************************************************
 void PartSet_Module::onChoiceChanged(ModuleBase_ModelWidget* theWidget,
                                      int theIndex)
index 3c7316458e02a0cfc32b22ab124bbd53574f3fa4..7292bb30ad20c54e0ffc28aa478573394d6e782a 100755 (executable)
@@ -30,6 +30,8 @@
 
 class ModuleBase_Operation;
 class ModuleBase_IViewWindow;
+class ModuleBase_ViewerPrs;
+
 class XGUI_Workshop;
 class PartSet_MenuMgr;
 class PartSet_CustomPrs;
@@ -205,6 +207,13 @@ public:
   /// Returns sketch reentrant manager
   PartSet_SketcherReentrantMgr* sketchReentranceMgr() const { return mySketchReentrantMgr; }
 
+  /// Find object and attribute(if selected) for the given viewer selection
+  /// \param theSelected a viewer selection
+  /// \param theObject a selected model object
+  /// \param theAttribute a selected model attribute
+  virtual void getGeomSelection(const std::shared_ptr<ModuleBase_ViewerPrs>& theSelected,
+                                ObjectPtr& theObject, AttributePtr& theAttribute);
+
   /// Returns listener of overconstraint signal
   /// \return the listener
   PartSet_OverconstraintListener* overconstraintListener() { return myOverconstraintListener; }
@@ -252,6 +261,11 @@ public:
                                      AISObjectPtr thePrs,
                                      std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs);
 
+  /// Modifies the given presentation in the custom way after usual customize is performed.
+  virtual bool afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
+                                          AISObjectPtr thePrs,
+                                          GeomCustomPrsPtr theCustomPrs);
+
   /// Update the object presentable properties such as color, lines width and other
   /// If the object is result with the color attribute value set, it is used,
   /// otherwise the customize is applyed to the object's feature if it is a custom prs
@@ -324,6 +338,13 @@ public:
   /// \return theAttribute
   virtual AttributePtr findAttribute(const ObjectPtr& theObject, const GeomShapePtr& theGeomShape);
 
+  /// Returns reentrant message if it was accepted
+  virtual std::shared_ptr<Events_Message> reentrantMessage();
+
+  /// Put current selection into reentrant message
+  /// \param theMessage a message of reentrant operation
+  virtual void setReentrantPreSelection(const std::shared_ptr<Events_Message>& theMessage);
+
   /// Returns the workshop
   XGUI_Workshop* getWorkshop() const;
 
index 31efa6041197b8ece3291807446e71b0db9c12fd..7068063188130db566b6264cad07d91c1967c2b3 100755 (executable)
@@ -348,6 +348,41 @@ void PartSet_OperationPrs::getResultShapes(const FeaturePtr& theFeature,
   }
 }
 
+void PartSet_OperationPrs::getPresentationShapes(const FeaturePtr& theFeature,
+                                           ModuleBase_IWorkshop* theWorkshop,
+                                           QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes,
+                                           const bool theListShouldBeCleared)
+{
+  if (theListShouldBeCleared)
+    theObjectShapes.clear();
+
+  if (!theFeature.get() || !theFeature->data()->isValid()) // if feature is already removed
+    return;
+
+  XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
+
+  GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theFeature);
+  if (!aPrs.get())
+    return;
+
+  AISObjectPtr anAIS = aPrs->getAISObject(aDisplayer->getAISObject(theFeature));
+  if (!anAIS.get())
+    return;
+
+  Handle(AIS_InteractiveObject) anAISPrs = anAIS->impl<Handle(AIS_InteractiveObject)>();
+  if (!anAISPrs.IsNull()) {
+    Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
+    if (!aShapePrs.IsNull()) {
+      TopoDS_Shape aShape = aShapePrs->Shape();
+      if (!aShape.IsNull()) {
+        std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape());
+        aGeomShape->setImpl(new TopoDS_Shape(aShape));
+        appendShapeIfVisible(theWorkshop, theFeature, aGeomShape, theObjectShapes);
+      }
+    }
+  }
+}
+
 void PartSet_OperationPrs::getHighlightedShapes(ModuleBase_IWorkshop* theWorkshop,
                                                 QMap<ObjectPtr,
                                                 QList<GeomShapePtr> >& theObjectShapes)
index 95ce374efa159fddc39855bcaf403cb3a47d188c..7e871fc5dd7377f1ff922e3a38373125a7386e9a 100755 (executable)
@@ -100,6 +100,16 @@ private:
                               QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes,
                               const bool theListShouldBeCleared = true);
 
+  /// Fills the map by the feature presentation if the feature is presentable
+  /// \param theFeature a current feature
+  /// \param theWorkshop a current workshop
+  /// \param theObjectShapes an output map
+  /// \param theObjectShape an output map of objects
+  static void getPresentationShapes(const FeaturePtr& theFeature,
+                              ModuleBase_IWorkshop* theWorkshop,
+                              QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes,
+                              const bool theListShouldBeCleared = true);
+
   /// Fills the map by the feature object and shapes, which should be visuaziled
   /// Gets the active widget, obtain the highlighted presentations if it has such and
   /// fill map by object and shapes
index 876130044b1ac805dc6fb840ecc6a2c4a46e42f1..1eff378359d69529ff52eba32e640742b7a9a680 100755 (executable)
@@ -4,19 +4,29 @@
 // Created:     20 August 2015
 // Author:      Vitaly SMETANNIKOV
 
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_AttributeString.h>
+
 #include "PartSet_OverconstraintListener.h"
+#include <PartSet_Module.h>
+#include <PartSet_SketcherMgr.h>
+#include <PartSet_SketcherReentrantMgr.h>
 
 #include "XGUI_ModuleConnector.h"
 #include "XGUI_Workshop.h"
 #include "XGUI_Displayer.h"
+#include "XGUI_CustomPrs.h"
 
 #include "SketcherPrs_SymbolPrs.h"
 #include "SketchPlugin_SketchEntity.h"
+#include "SketchPlugin_MacroArcReentrantMessage.h"
+#include "SketchPlugin_Sketch.h"
 
 #include "Events_Loop.h"
 
 #include <GeomAPI_IPresentable.h>
 #include <ModelAPI_Events.h>
+#include <ModelAPI_EventReentrantMessage.h>
 #include <ModuleBase_Tools.h>
 
 #include <QString>
 //#define DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
 
 PartSet_OverconstraintListener::PartSet_OverconstraintListener(ModuleBase_IWorkshop* theWorkshop)
-: myWorkshop(theWorkshop)
+: myWorkshop(theWorkshop), myIsActive(false), myIsFullyConstrained(false)
 {
   Events_Loop* aLoop = Events_Loop::loop();
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
+
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_UNDER_CONSTRAINED));
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_FULLY_CONSTRAINED));
+
+  aLoop->registerListener(this, ModelAPI_EventReentrantMessage::eventId());
+  aLoop->registerListener(this, SketchPlugin_MacroArcReentrantMessage::eventId());
 }
 
-bool PartSet_OverconstraintListener::isConflictingObject(const ObjectPtr& theObject)
+void PartSet_OverconstraintListener::setActive(const bool& theActive)
 {
-  return myConflictingObjects.find(theObject) != myConflictingObjects.end();
+  if (myIsActive == theActive)
+    return;
+
+  myIsActive = theActive;
+  myIsFullyConstrained = false; /// returned to default state, no custom color for it
+
+  if (myIsActive) {
+    PartSet_Module* aModule = module();
+    CompositeFeaturePtr aSketch = aModule->sketchMgr()->activeSketch();
+    if (aSketch.get()) {
+      std::string aDOFMessage = aSketch->string(SketchPlugin_Sketch::SOLVER_DOF())->value();
+      myIsFullyConstrained = QString(aDOFMessage.c_str()).contains("DoF = 0");
+    }
+  }
 }
 
-void PartSet_OverconstraintListener::getConflictingColor(std::vector<int>& theColor)
+void PartSet_OverconstraintListener::getCustomColor(const ObjectPtr& theObject,
+                                                    std::vector<int>& theColor)
 {
-  Quantity_Color aColor = ModuleBase_Tools::color("Visualization", "sketch_overconstraint_color");
-  theColor.push_back(aColor.Red()*255.);
-  theColor.push_back(aColor.Green()*255.);
-  theColor.push_back(aColor.Blue()*255.);
+  if (!myIsActive)
+    return;
+
+  if (myConflictingObjects.find(theObject) != myConflictingObjects.end()) {
+    theColor = Config_PropManager::color("Visualization", "sketch_overconstraint_color");
+  }
+  if (myIsFullyConstrained) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+    // only entity features has custom color when sketch is fully constrained
+    if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {
+      PartSet_Module* aModule = module();
+      CompositeFeaturePtr aSketch = aModule->sketchMgr()->activeSketch();
+      // the given object is sub feature of the current sketch(created or edited)
+      if (ModelAPI_Tools::compositeOwner(aFeature) == aSketch)
+        theColor = Config_PropManager::color("Visualization", "sketch_fully_constrained_color");
+    }
+  }
 }
 
 void PartSet_OverconstraintListener::processEvent(
                                                  const std::shared_ptr<Events_Message>& theMessage)
 {
+  if (!myIsActive)
+    return;
+
 #ifdef DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
   bool isRepaired = theMessage->eventID() == Events_Loop::eventByName(EVENT_SOLVER_REPAIRED);
   int aCount = 0;
@@ -69,31 +115,49 @@ void PartSet_OverconstraintListener::processEvent(
              .arg(aCurrentInfoStr).toStdString().c_str());
 #endif
 
-  if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SOLVER_FAILED)) {
+  Events_ID anEventID = theMessage->eventID();
+  if (anEventID == Events_Loop::eventByName(EVENT_SOLVER_FAILED) ||
+      anEventID == Events_Loop::eventByName(EVENT_SOLVER_REPAIRED)) {
     std::shared_ptr<ModelAPI_SolverFailedMessage> anErrorMsg =
                    std::dynamic_pointer_cast<ModelAPI_SolverFailedMessage>(theMessage);
     bool anUpdated = false;
     if (anErrorMsg.get()) {
       const std::set<ObjectPtr>& aConflictingObjects = anErrorMsg->objects();
-      anUpdated = appendConflictingObjects(aConflictingObjects);
-    }
-    else {
-      // there is a crash in the solver. All objects are invalid
-      //anUpdated = appendConflictingObjects(std::set<ObjectPtr>());
+      if (anEventID == Events_Loop::eventByName(EVENT_SOLVER_FAILED))
+        anUpdated = appendConflictingObjects(aConflictingObjects);
+      else
+        anUpdated = repairConflictingObjects(aConflictingObjects);
     }
   }
-   if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SOLVER_REPAIRED)) {
-    std::shared_ptr<ModelAPI_SolverFailedMessage> anErrorMsg =
-                   std::dynamic_pointer_cast<ModelAPI_SolverFailedMessage>(theMessage);
-    bool anUpdated = false;
-    if (anErrorMsg.get()) {
-      const std::set<ObjectPtr>& aConflictingObjects = anErrorMsg->objects();
-      anUpdated = repairConflictingObjects(aConflictingObjects);
-    }
-    else {
-      // there is no repaired objects, do nothing
+  else if (anEventID == Events_Loop::eventByName(EVENT_SKETCH_UNDER_CONSTRAINED) ||
+           anEventID == Events_Loop::eventByName(EVENT_SKETCH_FULLY_CONSTRAINED)) {
+    bool aPrevFullyConstrained = myIsFullyConstrained;
+    myIsFullyConstrained = anEventID == Events_Loop::eventByName(EVENT_SKETCH_FULLY_CONSTRAINED);
+
+    if (aPrevFullyConstrained != myIsFullyConstrained) {
+      std::set<ObjectPtr> aModifiedObjects;
+      PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+      CompositeFeaturePtr aSketch = aModule->sketchMgr()->activeSketch();
+      if (aSketch.get()) {
+        for (int i = 0; i < aSketch->numberOfSubs(); i++) {
+          FeaturePtr aFeature = aSketch->subFeature(i);
+          aModifiedObjects.insert(aFeature); // is necessary to redisplay presentations
+          std::list<ResultPtr> aResults = aFeature->results();
+          for (std::list<ResultPtr>::const_iterator aIt = aResults.begin();
+               aIt != aResults.end(); ++aIt) {
+            aModifiedObjects.insert(*aIt);
+          }
+        }
+        redisplayObjects(aModifiedObjects);
+      }
     }
   }
+  else if (anEventID == ModelAPI_EventReentrantMessage::eventId() ||
+           anEventID == SketchPlugin_MacroArcReentrantMessage::eventId()) {
+    PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+    PartSet_SketcherReentrantMgr* aReentrantMgr = aModule->sketchReentranceMgr();
+    aReentrantMgr->setReentrantMessage(theMessage);
+  }
 
 #ifdef DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
   aCurrentInfoStr = getObjectsInfo(myConflictingObjects);
@@ -106,8 +170,6 @@ bool PartSet_OverconstraintListener::appendConflictingObjects(
                                                const std::set<ObjectPtr>& theConflictingObjects)
 {
   std::set<ObjectPtr> aModifiedObjects;
-  std::vector<int> aColor;
-  getConflictingColor(aColor);
 
   // set error state for new objects and append them in the internal map of objects
   std::set<ObjectPtr>::const_iterator
@@ -163,10 +225,9 @@ void PartSet_OverconstraintListener::redisplayObjects(
   aLoop->flush(EVENT_DISP);
 }
 
-XGUI_Workshop* PartSet_OverconstraintListener::workshop() const
+PartSet_Module* PartSet_OverconstraintListener::module() const
 {
-  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
-  return aConnector->workshop();
+  return dynamic_cast<PartSet_Module*>(myWorkshop->module());
 }
 
 #ifdef _DEBUG
index 1f0e8f01c7ca3347c5fe5fcc49393dce4819e72d..0721d41d76017b918eef52f1502a43e472a314d2 100755 (executable)
@@ -12,7 +12,7 @@
 #include <ModelAPI_Object.h>
 
 class ModuleBase_IWorkshop;
-class XGUI_Workshop;
+class PartSet_Module;
 
 #include <QString>
 
@@ -33,19 +33,15 @@ public:
 
   virtual ~PartSet_OverconstraintListener() {};
 
-  // Set erroneous color for the presentation of object if the object is in the conflicting list
-  // \param theObject an object to be settled
-  // \param theUpdateViewer a boolean state whether the current viewer should be updated
-  //bool customizeObject(ObjectPtr theObject, const bool theUpdateViewer);
+  /// If active state is changed, update fully defined state and sketch sub-entities color
+  /// \param theActive a state
+  void setActive(const bool& theActive);
 
   /// Returns true if the object belongs to internal container of conflicting objects
   /// \param theObject an object to be checked
-  /// \return boolean result
-  bool isConflictingObject(const ObjectPtr& theObject);
-
-  /// Returns values of conflicting color
   /// \param theColor the output container to be filled in [red, green, blue] values
-  void getConflictingColor(std::vector<int>& theColor);
+  /// \return boolean result
+  void getCustomColor(const ObjectPtr& theObject, std::vector<int>& theColor);
 
   /// Redefinition of Events_Listener method
   virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
@@ -66,8 +62,8 @@ protected:
   void redisplayObjects(const std::set<ObjectPtr>& theObjects);
 
 private:
-  /// Returns workshop
-  XGUI_Workshop* workshop() const;
+  /// Returns module
+  PartSet_Module* module() const;
 
 #ifdef _DEBUG
   /// Unite objects in one string information
@@ -77,8 +73,10 @@ private:
 #endif
 
 private:
-  std::set<ObjectPtr> myConflictingObjects;
   ModuleBase_IWorkshop* myWorkshop;
+  bool myIsActive; /// state if sketch is active
+  std::set<ObjectPtr> myConflictingObjects;
+  bool myIsFullyConstrained; /// state if Solver is fully constrained, DOF = 0
 };
 
 #endif
index 1fd62e95de79c6560fb1c7a72182491811dfdd66..a63586cef8adb0c093ee969f3730e483d029477f 100755 (executable)
@@ -428,6 +428,10 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
   if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
     return;
 
+  // if mouse is pressed when it was over view and at release the mouse is out of view, do nothing
+  if (!myIsMouseOverViewProcessed)
+    return;
+
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
   if (!aViewer->canDragByMouse())
@@ -901,6 +905,9 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
     }
   }
 
+  // update state of overconstraint listener should be done before sketch features/results
+  // display (as the display will ask custom color from the listener)
+  myModule->overconstraintListener()->setActive(true);
   // Display sketcher objects
   QStringList anInfo;
   Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
@@ -1014,6 +1021,7 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
 
     Events_Loop::loop()->flush(aDispEvent);
   }
+  myModule->overconstraintListener()->setActive(false);
   // restore the module selection modes, which were changed on startSketch
   aConnector->activateModuleSelectionModes();
 }
index cab4e9945363d6912af1c7045d259d88ef00109a..b355a8869e1bb8be90d1ee1b49b804fdfd1c5639 100644 (file)
@@ -8,6 +8,7 @@
 #include "ModelAPI_Session.h"
 #include "ModelAPI_AttributeString.h"
 #include "ModelAPI_AttributeRefAttr.h"
+#include "ModelAPI_EventReentrantMessage.h"
 
 #include "GeomDataAPI_Point2D.h"
 
@@ -28,6 +29,7 @@
 #include <SketchPlugin_MacroArc.h>
 #include <SketchPlugin_MacroCircle.h>
 #include <SketchPlugin_Point.h>
+#include <SketchPlugin_Trim.h>
 
 #include <XGUI_Workshop.h>
 #include <XGUI_ModuleConnector.h>
 
 #include <QToolButton>
 
+//#define DEBUG_RESTART
+
 PartSet_SketcherReentrantMgr::PartSet_SketcherReentrantMgr(ModuleBase_IWorkshop* theWorkshop)
 : QObject(theWorkshop),
   myWorkshop(theWorkshop),
   myRestartingMode(RM_None),
   myIsFlagsBlocked(false),
   myIsInternalEditOperation(false),
-  myIsValueChangedBlocked(false),
   myInternalActiveWidget(0),
   myNoMoreWidgetsAttribute("")
 {
@@ -118,7 +121,8 @@ void PartSet_SketcherReentrantMgr::operationStarted(ModuleBase_Operation* theOpe
     ModuleBase_OperationFeature* aCurrentOperation = dynamic_cast<ModuleBase_OperationFeature*>(
                                                                 myWorkshop->currentOperation());
     CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
-    copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch);
+    if (myPreviousFeature.get() && myPreviousFeature->data()->isValid()) // it is not removed
+      copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch);
   }
   resetFlags();
 }
@@ -194,8 +198,8 @@ bool PartSet_SketcherReentrantMgr::processMousePressed(ModuleBase_IViewWindow* /
   return isActiveMgr() && myIsInternalEditOperation;
 }
 
-bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow* theWnd,
-                                                         QMouseEvent* theEvent)
+bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow* theWindow,
+                                                        QMouseEvent* theEvent)
 {
   bool aProcessed = false;
   if (!isActiveMgr())
@@ -228,7 +232,16 @@ bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow*
       QList<ModuleBase_ViewerPrsPtr> aPreSelected =
         aSelection->getSelected(ModuleBase_ISelection::AllControls);
 
+      myClickedSketchPoint = PartSet_Tools::getPnt2d(theEvent, theWindow,
+                                                     module()->sketchMgr()->activeSketch());
+      if (!aPreSelected.empty())
+        module()->getGeomSelection(aPreSelected.first(), mySelectedObject, mySelectedAttribute);
+
       restartOperation();
+      myClickedSketchPoint = std::shared_ptr<GeomAPI_Pnt2d>();
+      mySelectedObject = ObjectPtr();
+      mySelectedAttribute = AttributePtr();
+
       myPreviousFeature = FeaturePtr();
       aProcessed = true;
 
@@ -246,8 +259,14 @@ bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow*
         std::shared_ptr<ModuleBase_ViewerPrs> aSelectedPrs;
         if (!aPreSelected.empty())
           aSelectedPrs = aPreSelected.front();
-        aMouseProcessor->setPreSelection(aSelectedPrs, theWnd, theEvent);
-        //aPoint2DWdg->mouseReleased(theWnd, theEvent);
+        if (aSelectedPrs.get() && aSelectedPrs->object().get()
+            && !aSelectedPrs->object()->data()->isValid()) {
+          // the selected object was removed diring restart, e.g. presentable macro feature
+          // there are created objects to replace the object depending on created feature kind
+          aSelectedPrs = generatePreSelection();
+        }
+        aMouseProcessor->setPreSelection(aSelectedPrs, theWindow, theEvent);
+        //aPoint2DWdg->mouseReleased(theWindow, theEvent);
         //if (!aPreSelected.empty())
         //  aPoint2DWdg->setPreSelection(ModuleBase_ViewerPrsPtr());
       }
@@ -255,10 +274,26 @@ bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow*
       ModuleBase_Tools::blockUpdateViewer(false);
     }
   }
-
   return aProcessed;
 }
 
+//******************************************************
+void PartSet_SketcherReentrantMgr::setReentrantPreSelection(
+                                       const std::shared_ptr<Events_Message>& theMessage)
+{
+  ReentrantMessagePtr aReentrantMessage =
+                      std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
+  if (!aReentrantMessage.get())
+    return;
+
+  // if feature has already filled the selected object, we should not overwrite it
+  if (!aReentrantMessage->selectedObject().get())
+    aReentrantMessage->setSelectedObject(mySelectedObject);
+
+  aReentrantMessage->setSelectedAttribute(mySelectedAttribute);
+  aReentrantMessage->setClickedPoint(myClickedSketchPoint);
+}
+
 void PartSet_SketcherReentrantMgr::onWidgetActivated()
 {
   if (!isActiveMgr())
@@ -278,6 +313,10 @@ void PartSet_SketcherReentrantMgr::onWidgetActivated()
 
 void PartSet_SketcherReentrantMgr::onNoMoreWidgets(const std::string& thePreviousAttributeID)
 {
+#ifdef DEBUG_RESTART
+  std::cout << "PartSet_SketcherReentrantMgr::onNoMoreWidgets" << std::endl;
+#endif
+
   if (!isActiveMgr())
     return;
 
@@ -364,14 +403,12 @@ void PartSet_SketcherReentrantMgr::onVertexSelected()
 
 void PartSet_SketcherReentrantMgr::onAfterValuesChangedInPropertyPanel()
 {
-  // blocked flag in order to avoid circling when storeValue will be applied in
-  // this method to cached widget
-  if (myIsValueChangedBlocked)
-    return;
 
   if (isInternalEditActive()) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                       (myWorkshop->currentOperation());
     ModuleBase_ModelWidget* aWidget = (ModuleBase_ModelWidget*)sender();
-    if (!aWidget->isModifiedInEdit())
+    if (!aWidget->isModifiedInEdit().empty())
       restartOperation();
   }
 }
@@ -389,11 +426,6 @@ bool PartSet_SketcherReentrantMgr::canBeCommittedByPreselection()
   return !isActiveMgr() || myRestartingMode == RM_None;
 }
 
-bool PartSet_SketcherReentrantMgr::isInternalEditStarted() const
-{
-  return myIsInternalEditOperation;
-}
-
 bool PartSet_SketcherReentrantMgr::isActiveMgr() const
 {
   ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation();
@@ -413,6 +445,10 @@ bool PartSet_SketcherReentrantMgr::isActiveMgr() const
 
 bool PartSet_SketcherReentrantMgr::startInternalEdit(const std::string& thePreviousAttributeID)
 {
+#ifdef DEBUG_RESTART
+  std::cout << "PartSet_SketcherReentrantMgr::startInternalEdit" << std::endl;
+#endif
+
   bool isDone = false;
   /// this is workaround for ModuleBase_WidgetEditor, used in SALOME mode. Sometimes key enter
   /// event comes two times, so we should not start another internal edit operation
@@ -498,32 +534,30 @@ void PartSet_SketcherReentrantMgr::beforeStopInternalEdit()
 
 void PartSet_SketcherReentrantMgr::restartOperation()
 {
+#ifdef DEBUG_RESTART
+  std::cout << "PartSet_SketcherReentrantMgr::restartOperation" << std::endl;
+#endif
+
   if (myIsInternalEditOperation) {
     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(
                                                                   myWorkshop->currentOperation());
     if (aFOperation) {
-      // obtain widgets(attributes) which content should be applied to attributes of new feature
-      ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
-      ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
-      const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
-      QList<ModuleBase_ModelWidget*> aValueWidgets;
-      for (int i = 0, aSize = aWidgets.size(); i < aSize; i++) {
-        ModuleBase_ModelWidget* aWidget = aWidgets[i];
-        if (!aWidget->isModifiedInEdit()) {
-          aValueWidgets.append(aWidget);
-          // the widget is cashed to fill feature of new operation by the current widget value
-          // we set empty parent to the widget in order to remove it ourselves. Reason: restart
-          // operation will clear property panel and delete all widgets. This widget should be
-          // removed only after applying value of the widget to new created feature.
-          aWidget->setParent(0);
-        }
-      }
+      ModuleBase_ISelection* aSelection = myWorkshop->selection();
+      QList<ModuleBase_ViewerPrsPtr> aPreSelected =
+        aSelection->getSelected(ModuleBase_ISelection::AllControls);
+
+
+
+      if (myInternalFeature.get())
+        copyReetntrantAttributes(myInternalFeature, aFOperation->feature(),
+                                  module()->sketchMgr()->activeSketch());
 
       myNoMoreWidgetsAttribute = "";
       myIsFlagsBlocked = true;
       module()->launchOperation(aFOperation->id());
       myIsFlagsBlocked = false;
       resetFlags();
+
       // we should avoid processing of the signal about no more widgets attributes and
       // do this after the restart operaion is finished if it was called
       // onNoMoreWidgets depends on myIsFlagsBlocked and fill myNoMoreWidgetsAttribute
@@ -532,21 +566,6 @@ void PartSet_SketcherReentrantMgr::restartOperation()
         onNoMoreWidgets(myNoMoreWidgetsAttribute);
         myNoMoreWidgetsAttribute = "";
       }
-
-      // filling new feature by the previous value of active widget
-      // (e.g. circle_type in macro Circle)
-      ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(
-                                                                myWorkshop->currentOperation());
-      myIsValueChangedBlocked = true; // flag to avoid onAfterValuesChangedInPropertyPanel slot
-      for (int i = 0, aSize = aValueWidgets.size(); i < aSize; i++) {
-        ModuleBase_ModelWidget* aWidget = aValueWidgets[i];
-        aWidget->setEditingMode(false);
-        aWidget->setFeature(aFOperation->feature());
-        aWidget->storeValue();
-        // we must delete this widget
-        delete aWidget;
-      }
-      myIsValueChangedBlocked = false;
     }
   }
 }
@@ -562,6 +581,11 @@ void PartSet_SketcherReentrantMgr::createInternalFeature()
     CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
     myInternalFeature = aSketch->addFeature(anOperationFeature->getKind());
 
+#ifdef DEBUG_RESTART
+    std::cout << "PartSet_SketcherReentrantMgr::createInternalFeature: "
+              << myInternalFeature->data()->name() << std::endl;
+#endif
+
     bool isFeatureChanged = copyReetntrantAttributes(anOperationFeature, myInternalFeature,
                                                      aSketch, false);
     XGUI_PropertyPanel* aPropertyPanel = dynamic_cast<XGUI_PropertyPanel*>
@@ -596,6 +620,10 @@ void PartSet_SketcherReentrantMgr::createInternalFeature()
 
 void PartSet_SketcherReentrantMgr::deleteInternalFeature()
 {
+#ifdef DEBUG_RESTART
+  std::cout << "PartSet_SketcherReentrantMgr::deleteInternalFeature: "
+            << myInternalFeature->data()->name() << std::endl;
+#endif
   if (myInternalActiveWidget) {
     ModuleBase_WidgetSelector* aWSelector =
       dynamic_cast<ModuleBase_WidgetSelector*>(myInternalActiveWidget);
@@ -618,21 +646,28 @@ void PartSet_SketcherReentrantMgr::resetFlags()
     myIsInternalEditOperation = false;
     updateAcceptAllAction();
     myRestartingMode = RM_None;
+    myReentrantMessage = std::shared_ptr<Events_Message>();
   }
 }
 
 bool PartSet_SketcherReentrantMgr::copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
                                                              const FeaturePtr& theNewFeature,
                                                              const CompositeFeaturePtr& theSketch,
-                                                             const bool isTemporary)
+                                                             const bool /*isTemporary*/)
 {
   bool aChanged = false;
   if (!theSourceFeature.get() || !theSourceFeature->data().get() ||
       !theSourceFeature->data()->isValid())
     return aChanged;
 
+#ifdef DEBUG_RESTART
+  std::cout << "PartSet_SketcherReentrantMgr::copyReetntrantAttributes from '"
+            << theSourceFeature->data()->name() << "' to '" << theNewFeature->data()->name()
+            << "'" << std::endl;
+#endif
+
   std::string aFeatureKind = theSourceFeature->getKind();
-  if (aFeatureKind == SketchPlugin_Line::ID()) {
+  /*if (aFeatureKind == SketchPlugin_Line::ID()) {
     // Initialize new line with first point equal to end of previous
     std::shared_ptr<ModelAPI_Data> aSFData = theSourceFeature->data();
     std::shared_ptr<GeomDataAPI_Point2D> aSPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
@@ -647,22 +682,23 @@ bool PartSet_SketcherReentrantMgr::copyReetntrantAttributes(const FeaturePtr& th
                                                  aSFData->attribute(SketchPlugin_Line::END_ID()));
     aNPoint->setValue(aSPoint->x(), aSPoint->y());
   }
-  else if (aFeatureKind == SketchPlugin_MacroCircle::ID()) {
+  else*/ if (aFeatureKind == SketchPlugin_MacroCircle::ID()) {
     // set circle type
-    std::string aTypeAttributeId = SketchPlugin_MacroCircle::CIRCLE_TYPE();
+    /*std::string aTypeAttributeId = SketchPlugin_MacroCircle::CIRCLE_TYPE();
     AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
     AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
-    aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
+    if (aNewFeatureTypeAttr->value() != aTypeAttributeId) // do nothing if there is no changes
+      aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
     //ModuleBase_Tools::flushUpdated(theNewFeature);
-    aChanged = true;
+    aChanged = true;*/
   }
   else if (aFeatureKind == SketchPlugin_MacroArc::ID()) {
     // set arc type
     std::string aTypeAttributeId = SketchPlugin_MacroArc::ARC_TYPE();
     AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
     AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
-    aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
-
+    if (aNewFeatureTypeAttr->value() != aTypeAttributeId) // do nothing if there is no changes
+      aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
     //// if the arc is tangent, set coincidence to end point of the previous arc
     //std::string anArcType = aSourceFeatureTypeAttr->value();
     //if (anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT()) {
@@ -685,6 +721,41 @@ bool PartSet_SketcherReentrantMgr::copyReetntrantAttributes(const FeaturePtr& th
     //ModuleBase_Tools::flushUpdated(theNewFeature);
     aChanged = true;
   }
+  else if (aFeatureKind == SketchPlugin_Trim::ID()) {
+    /*std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
+                      std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+                      theSourceFeature->data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
+    std::shared_ptr<ModelAPI_AttributeReference> aNRefSelectedAttr =
+                      std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+                      theNewFeature->data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
+    aNRefSelectedAttr->setValue(aRefSelectedAttr->value());*/
+
+    std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
+                      std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+                      theSourceFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
+    std::shared_ptr<ModelAPI_AttributeReference> aNRefPreviewAttr =
+                        std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+                        theNewFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
+    aNRefPreviewAttr->setValue(aRefPreviewAttr->value());
+
+    /*std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
+                      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                      theSourceFeature->data()->attribute(SketchPlugin_Trim::SELECTED_POINT()));
+    std::shared_ptr<GeomDataAPI_Point2D> aNPointSelectedAttr =
+                      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                      theNewFeature->data()->attribute(SketchPlugin_Trim::SELECTED_POINT()));
+    aNPointSelectedAttr->setValue(aPointSelectedAttr->x(), aPointSelectedAttr->y());
+    */
+    std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
+                      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                      theSourceFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_POINT()));
+    std::shared_ptr<GeomDataAPI_Point2D> aNPointPreviewAttr =
+                      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                      theNewFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_POINT()));
+    aNPointPreviewAttr->setValue(aPointPreviewAttr->x(), aPointPreviewAttr->y());
+
+    aChanged = true;
+  }
   return aChanged;
 }
 
@@ -705,6 +776,13 @@ bool PartSet_SketcherReentrantMgr::isTangentArc(ModuleBase_Operation* theOperati
   return aTangentArc;
 }
 
+std::shared_ptr<ModuleBase_ViewerPrs> PartSet_SketcherReentrantMgr::generatePreSelection()
+{
+  std::shared_ptr<ModuleBase_ViewerPrs> aPrs;
+
+  return aPrs;
+}
+
 void PartSet_SketcherReentrantMgr::updateAcceptAllAction()
 {
   CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
index b430c2389479bcef9a2c1a283dc38d60e28b405c..3fc5c22469eb820acbbff38bb63648e2a0060565 100644 (file)
@@ -8,6 +8,7 @@
 #include <ModelAPI_Feature.h>
 
 #include <string>
+#include <memory>
 
 #include <QObject>
 
@@ -22,6 +23,10 @@ class QMouseEvent;
 
 class XGUI_Workshop;
 class PartSet_Module;
+class ModuleBase_ViewerPrs;
+class Events_Message;
+class ModelAPI_Attribute;
+class GeomAPI_Pnt2d;
 
 /// \ingroup PartSet_SketcherReentrantMgr
 /// It provides reentrant create operations in sketch, that is when all inputs are valid,
@@ -101,9 +106,17 @@ public:
   /// Returns false if the reentrant mode of the operation is not empty.
   bool canBeCommittedByPreselection();
 
-  /// returns true if an internal edit operation is started
-  /// \return boolean value
-  bool isInternalEditStarted() const;
+  /// Fills reentrant message during restarting operation
+  /// \param theMessage reentrant message
+  void setReentrantMessage(const std::shared_ptr<Events_Message>& theMessage)
+  { myReentrantMessage = theMessage; }
+
+  /// Returnss reentrant message
+  std::shared_ptr<Events_Message> reentrantMessage() const { return myReentrantMessage; }
+
+  /// Put current selection into reentrant message
+  /// \param theMessage a message of reentrant operation
+  void setReentrantPreSelection(const std::shared_ptr<Events_Message>& theMessage);
 
 private slots:
   /// SLOT, that is called by a widget activating in the property panel
@@ -173,6 +186,10 @@ private:
   bool isTangentArc(ModuleBase_Operation* theOperation,
                     const std::shared_ptr<ModelAPI_CompositeFeature>& /*theSketch*/) const;
 
+  /// Creates selection instance by the current feature and created by restart objects
+  /// \returns viewer selection presentation
+  std::shared_ptr<ModuleBase_ViewerPrs> generatePreSelection();
+
   /// Accept All action is enabled if an internal edit is started.
   /// It updates the state of the button
   void updateAcceptAllAction();
@@ -189,13 +206,17 @@ private:
   RestartingMode myRestartingMode;  /// automatical restarting mode flag
   bool myIsFlagsBlocked; /// true when reset of flags should not be perfromed
   bool myIsInternalEditOperation; /// true when the 'internal' edit is started
-  bool myIsValueChangedBlocked; /// blocked flag to avoid circling by value changed
 
   FeaturePtr myPreviousFeature; /// feature of the previous operation, which is restarted
   FeaturePtr myInternalFeature;
   QWidget* myInternalWidget;
   ModuleBase_ModelWidget* myInternalActiveWidget;
   std::string myNoMoreWidgetsAttribute;
+
+  std::shared_ptr<Events_Message> myReentrantMessage; /// message obtained by operation restart
+  ObjectPtr mySelectedObject; /// cashed selected object
+  std::shared_ptr<ModelAPI_Attribute> mySelectedAttribute; /// cashed selected attribute
+  std::shared_ptr<GeomAPI_Pnt2d> myClickedSketchPoint; /// cashed clicked point
 };
 
 #endif
index 37cee3d6771e9b9e6eea108280de8353a0fd1a13..0976d01ced0d523ec3a576ff3bc7ee4a8d714fbe 100755 (executable)
@@ -17,6 +17,8 @@
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Validator.h>
 
+#include <ModuleBase_IViewWindow.h>
+
 #include <ModelGeomAlgo_Point2D.h>
 
 #include <Events_Loop.h>
@@ -73,6 +75,8 @@
 #include <StdSelect_BRepOwner.hxx>
 #include <SelectMgr_IndexedMapOfOwner.hxx>
 
+#include <QMouseEvent>
+
 #ifdef _DEBUG
 #include <QDebug>
 #endif
@@ -643,6 +647,18 @@ std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPoint(
   return std::shared_ptr<GeomAPI_Pnt2d>();
 }
 
+std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPnt2d(QMouseEvent* theEvent,
+                                                ModuleBase_IViewWindow* theWindow,
+                                                const FeaturePtr& theSketch)
+{
+  gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
+  double aX, anY;
+  Handle(V3d_View) aView = theWindow->v3dView();
+  PartSet_Tools::convertTo2D(aPnt, theSketch, aView, aX, anY);
+
+  return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY));
+}
+
 FeaturePtr findFirstCoincidenceByData(const DataPtr& theData,
                                       std::shared_ptr<GeomAPI_Pnt2d> thePoint)
 {
index 1b9937dd1e29c12d32336782dd88128a4c5f82df..1429f9d29cfdfb853b1e38a93487f8ce2202967e 100755 (executable)
@@ -25,6 +25,7 @@
 #include <memory>
 
 class V3d_View;
+class ModuleBase_IViewWindow;
 class ModuleBase_ViewerPrs;
 class ModuleBase_IWorkshop;
 class GeomDataAPI_Point2D;
@@ -36,6 +37,8 @@ class GeomAPI_Edge;
 class GeomAPI_Vertex;
 class ModelAPI_Result;
 
+class QMouseEvent;
+
 /*!
  * \class PartSet_Tools
  * \ingroup Modules
@@ -214,6 +217,16 @@ public:
   static std::shared_ptr<GeomAPI_Pnt2d> getPoint(std::shared_ptr<ModelAPI_Feature>& theFeature,
                                                  const std::string& theAttribute);
 
+  /**
+  * Convertes parameters into a geom point
+  * \theEvent a Qt event to find mouse position
+  * \param theWindow view window to define eye of view
+  * \param theSketch to convert 3D point coordinates into coorditates of the sketch plane
+  */
+  static std::shared_ptr<GeomAPI_Pnt2d> getPnt2d(QMouseEvent* theEvent,
+                                                 ModuleBase_IViewWindow* theWindow,
+                                                 const FeaturePtr& theSketch);
+
   /**
   * Gets all references to the feature, take coincidence constraint features, get point 2d attributes
   * and compare the point value to be equal with the given. Returns the first feature, which has
index f2808b3ad2f929397e103f76106c99bd8ee8cc1a..0fecb7ed7855e535d11dfc007a7ffe30e5565f84 100644 (file)
@@ -167,10 +167,8 @@ bool PartSet_WidgetFeaturePointSelector::fillFeature(
   if (theSelectedPrs.get() && theSelectedPrs->object().get())
     anObject = theSelectedPrs->object();
 
-  gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
-  double aX, anY;
-  Handle(V3d_View) aView = theWindow->v3dView();
-  PartSet_Tools::convertTo2D(aPnt, mySketch, aView, aX, anY);
+  if (!anObject.get())
+    return aFilled;
 
   std::shared_ptr<ModelAPI_AttributeReference> aRef =
                           std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
@@ -180,7 +178,8 @@ bool PartSet_WidgetFeaturePointSelector::fillFeature(
   std::shared_ptr<GeomDataAPI_Point2D> anAttributePoint =
                   std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
                   feature()->data()->attribute(SketchPlugin_Trim::PREVIEW_POINT()));
-  anAttributePoint->setValue(aX, anY);
+  std::shared_ptr<GeomAPI_Pnt2d> aPoint = PartSet_Tools::getPnt2d(theEvent, theWindow, mySketch);
+  anAttributePoint->setValue(aPoint);
   // redisplay AIS presentation in viewer
 #ifndef HIGHLIGHT_STAYS_PROBLEM
   // an attempt to clear highlighted item in the viewer: but of OCCT
index d82e457a8dbafdebca08a4cdc648461bb2faf4bf..0d296dc097204e2aa7804e2f4b51c375af35107b 100644 (file)
@@ -689,7 +689,7 @@ void PartSet_WidgetPoint2D::mouseMoved(ModuleBase_IViewWindow* theWindow, QMouse
 {
   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
 
-  if (isEditingMode() || aModule->sketchReentranceMgr()->isInternalEditStarted())
+  if (isEditingMode() || aModule->sketchReentranceMgr()->isInternalEditActive())
     return;
 
   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
index f68c872585210383296496a7122f21bb1a9d8a86..109e19e3bf57313bd1bd0d1f0a537d79406e3dc8 100644 (file)
@@ -33,10 +33,12 @@ ADD_UNIT_TESTS(
   TestFeatures.py
   TestFeaturesExtrusion.py
   #TestFeaturesRevolution.py
-  
+
   TestPrimitivesBox.py
 
   TestMakeBrick1.py
   TestMakeBrick2.py
   TestPlatine.py
+
+  Test2044.py
   )
diff --git a/src/PythonAPI/Test/Test2044.py b/src/PythonAPI/Test/Test2044.py
new file mode 100644 (file)
index 0000000..437b907
--- /dev/null
@@ -0,0 +1,23 @@
+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"))
+SketchLine_1 = Sketch_1.addLine(-184.375, -81.25, -71.87500000000006, 206.2500000000001)
+SketchLine_2 = Sketch_1.addLine(-71.87500000000006, 206.2500000000001, 281.2500000000001, 178.125)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(281.2500000000001, 178.125, 184.3750000000001, -109.375)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(184.3750000000001, -109.375, -184.375, -81.25)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection("EDGE", "PartSet/OZ"), 50, 0)
+model.do()
+Extrusion_1.setDirection(model.selection("EDGE", "OX"))
+model.do()
+model.end()
+
+assert (len(Extrusion_1.feature().error()) != 0)
index 032bff2374ace8872a5ba954f81895e82bfa1b6f..65d7e3dc8e2fab364fa94e6b81041de60d0a4ecf 100644 (file)
@@ -19,10 +19,10 @@ class SketcherAddLine(SketcherTestCase):
         mirrored_objects = mirror.mirroredObjects()
         mirrored_circle = mirrored_objects.object(0)
         circle_feature = ModelAPI_Feature.feature(mirrored_circle)
-        center = geomDataAPI_Point2D(circle_feature.attribute("CircleCenter"))
+        center = geomDataAPI_Point2D(circle_feature.attribute("circle_center"))
         self.assertEqual(center.x(), -30)
         # dir(mirrored_circle)
-        # center = geomDataAPI_Point2D(mirrored_circle.data().attribute("CircleCenter"))
+        # center = geomDataAPI_Point2D(mirrored_circle.data().attribute("circle_center"))
         # self.assertEqual(center.x(), -30, msg="%s"%(dir(mirrored_circle)))
         # self.assertTrue(False,  msg="%s" % (dir(mirrored_circle)))
 
index b2464370d633c2db784c18bd250985bb7700583a..d92d6433c0f65c25f840ae3b72e4b2a418e6f32b 100644 (file)
@@ -6,9 +6,9 @@ class SketcherSetTangent(SketcherTestCase):
     def setUp(self):
         SketcherTestCase.setUp(self)
         self.line = self.sketch.addLine(0, 0, 0, 1)
-        self.arc = self.sketch.addArc(0, 1, 0, 0, 1, 1)
+        self.arc = self.sketch.addArc(0, 1, 0, 0, 1, 1, False)
         self.sketch.setCoincident(
-            self.line.endPoint(), self.arc.startPoint()
+            self.line.startPoint(), self.arc.startPoint()
             )
         
     def test_set_tangent(self):
index 994ecc6f11ef8b05af65e40c5659c59a7b302be7..b015b4278170b469d81fa7d734d14f4812bb448f 100644 (file)
@@ -2,4 +2,4 @@
 """
 
 from SketchAPI import addSketch
-from tools import addPolyline, addPolygon, dof
+from tools import *
index 3603f20061b35215c312877b8a5b94ec66671af3..0a17f6aeaede8eafbefdd10bd541440af51b9ef0 100644 (file)
@@ -2,6 +2,7 @@
 # Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
 import ModelHighAPI
+import GeomDataAPI
 
 def addPolyline(sketch, *coords):
     """Add a poly-line to sketch.
@@ -48,4 +49,22 @@ def dof(sketch):
     aSketch = sketch
     if issubclass(type(aSketch), ModelHighAPI.ModelHighAPI_Interface):
         aSketch = sketch.feature()
-    return int(filter(str.isdigit, aSketch.string("SolverDOF").value()))
\ No newline at end of file
+    return int(filter(str.isdigit, aSketch.string("SolverDOF").value()))
+
+def distancePointPoint(thePoint1, thePoint2):
+    aGeomPnt1 = thePoint1
+    aGeomPnt2 = thePoint2
+    if issubclass(type(thePoint1), GeomDataAPI.GeomDataAPI_Point2D):
+        aGeomPnt1 = thePoint1.pnt()
+    if issubclass(type(thePoint2), GeomDataAPI.GeomDataAPI_Point2D):
+        aGeomPnt2 = thePoint2.pnt()
+    return aGeomPnt1.distance(aGeomPnt2)
+
+def lastSubFeature(theSketch, theKind):
+    """
+    obtains last feature of given kind from the sketch
+    """
+    for anIndex in range(theSketch.numberOfSubs() - 1, -1, -1):
+        aSub = theSketch.subFeature(anIndex)
+        if (aSub.getKind() == theKind):
+            return aSub
index 68b766385ff109fcd75d92ad92790da2162e8011..84e84c6a6d30f462f624a461c118b193cb27ead0 100644 (file)
@@ -1,8 +1,11 @@
 from GeomAlgoAPI import *
 from GeomAPI import *
+from GeomDataAPI import *
 from ModelAPI import ModelAPI_Feature
 import math
+from salome.shaper.model import sketcher
 
+TOLERANCE = 1.e-7
 
 aShapeTypes = {
   GeomAPI_Shape.SOLID:  "GeomAPI_Shape.SOLID",
@@ -93,11 +96,12 @@ def testNbSubShapes(theFeature, theShapeType, theExpectedNbSubShapes):
     assert (aNbResultSubShapes == anExpectedNbSubShapes), "Number of sub-shapes of type {} for result[{}]: {}. Expected: {}.".format(aShapeTypes[theShapeType], anIndex, aNbResultSubShapes, anExpectedNbSubShapes)
 
 
-def testResultsVolumes(theFeature, theExpectedResultsVolumes, theNbSignificantDigits = 10):
+def testResultsVolumes(theFeature, theExpectedResultsVolumes, theNbSignificantDigits = 7):
   """ Tests results volumes.
   :param theFeature: feature to test.
   :param theExpectedResultsVolumes: list of results volumes. Size of list should be equal to len(theFeature.results()).
   """
+  aTolerance = 10**(-theNbSignificantDigits)
   aNbResults = len(theFeature.results())
   aListSize = len(theExpectedResultsVolumes)
   assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize)
@@ -106,7 +110,7 @@ def testResultsVolumes(theFeature, theExpectedResultsVolumes, theNbSignificantDi
     aResultVolumeStr = "{:0.27f}".format(aResultVolume).lstrip("0").lstrip(".").lstrip("0")
     anExpectedResultVolume = theExpectedResultsVolumes[anIndex]
     anExpectedResultVolumeStr = "{:0.27f}".format(anExpectedResultVolume).lstrip("0").lstrip(".").lstrip("0")
-    assert (aResultVolumeStr[:theNbSignificantDigits] == anExpectedResultVolumeStr[:theNbSignificantDigits]), "Volume of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits)
+    assert math.fabs(aResultVolume - anExpectedResultVolume) < aTolerance * anExpectedResultVolume, "Volume of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits)
 
 def testHaveNamingFaces(theFeature, theModel, thePartDoc) :
   """ Tests if all faces of result have a name
@@ -153,3 +157,15 @@ def testNbSubFeatures(theComposite, theKindOfSub, theExpectedCount):
     if aFeature is not None and aFeature.getKind() == theKindOfSub:
        count += 1
   assert (count == theExpectedCount), "Number of sub-features of type {}: {}, expected {}".format(theKindOfSub, count, theExpectedCount)
+
+def assertSketchArc(theArcFeature):
+  """ Tests whether the arc is correctly defined
+  """
+  aCenterPnt = geomDataAPI_Point2D(theArcFeature.attribute("center_point"))
+  aStartPnt = geomDataAPI_Point2D(theArcFeature.attribute("start_point"))
+  aEndPnt = geomDataAPI_Point2D(theArcFeature.attribute("end_point"))
+  aRadius = theArcFeature.real("radius")
+  aDistCS = sketcher.tools.distancePointPoint(aCenterPnt, aStartPnt)
+  aDistCE = sketcher.tools.distancePointPoint(aCenterPnt, aEndPnt)
+  assert math.fabs(aDistCS - aDistCE) < TOLERANCE, "Wrong arc: center-start distance {}, center-end distance {}".format(aDistCS, aDistCE)
+  assert math.fabs(aRadius.value() -aDistCS) < TOLERANCE, "Wrong arc: radius is {0}, expected {1}".format(aRadius.value(), aDistCS)
index 84349b45b3b4b2e7f89de2c3f0ef99d2c0374504..96e7591c95559ced89aec8c2bf7a22df443aecd3 100644 (file)
@@ -31,6 +31,7 @@ SET(PROJECT_HEADERS
     SketchPlugin_IntersectionPoint.h
     SketchPlugin_Line.h
     SketchPlugin_MacroArc.h
+    SketchPlugin_MacroArcReentrantMessage.h
     SketchPlugin_MacroCircle.h
     SketchPlugin_MultiRotation.h
     SketchPlugin_MultiTranslation.h
@@ -125,7 +126,10 @@ INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Sketc
 INSTALL(FILES ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
 
 ADD_UNIT_TESTS(TestSketchPointLine.py
-               TestCreateArc.py
+               TestCreateArcByCenterStartEnd.py
+               TestCreateArcByThreePoints.py
+               TestCreateArcByTangentEdge.py
+               TestCreateArcChangeType.py
                TestCreateCircleByCenterAndPassed.py
                TestCreateCircleByThreePoints.py
                TestCreateCircleChangeType.py
@@ -141,9 +145,9 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                TestConstraintVertical.py
                TestConstraintEqual.py
                TestConstraintTangent.py
-               TestConstraintMirror.py
                TestConstraintAngle.py
                TestConstraintMiddlePoint.py
+               TestMirror.py
                TestMultiRotation.py
                TestMultiTranslation.py
                TestFillet.py
index 9ebf16eb34205e343f114a511be0a5eb0e9ba60f..ca7579d8664f8f285ba30f85a1d09b63b1c3d0e4 100644 (file)
@@ -103,6 +103,12 @@ void SketchPlugin_Arc::execute()
       GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal)
     : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal);
 
+  if (myParamBefore == 0) { // parameter has not been calculate yet
+    std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
+        new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
+    aCircleForArc->parameter(anEndAttr->pnt(), paramTolerance, myParamBefore);
+  }
+
   std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
   aResult->setShape(anArcShape);
   aResult->setIsInHistory(false);
@@ -190,8 +196,17 @@ void SketchPlugin_Arc::attributeChanged(const std::string& theID)
         aCirc->parameter(anEdge->firstPoint(), paramTolerance, aStartParam);
         aCirc->parameter(aMinPnt, paramTolerance, aMidParam);
         aCirc->parameter(anEdge->lastPoint(), paramTolerance, anEndParam);
+
+        // adjust period
+        anEndParam -= aStartParam;
+        aMidParam -= aStartParam;
+        if (anEndParam < 0.0)
+          anEndParam += 2.0 * PI;
+        if (aMidParam < 0.0)
+          aMidParam += 2.0 * PI;
+
         aWasBlocked = data()->blockSendAttributeUpdated(true);
-        if(aStartParam < aMidParam && aMidParam < anEndParam) {
+        if(aMidParam < anEndParam) {
           setReversed(false);
         } else {
           setReversed(true);
@@ -213,31 +228,25 @@ void SketchPlugin_Arc::attributeChanged(const std::string& theID)
       return;
     std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(new GeomAPI_Circ2d(aCenter, aStart));
 
-    bool aWasBlocked = data()->blockSendAttributeUpdated(true);
-    // The Arc end point is projected
-    // on the circle formed by center and start points
+    // Do not recalculate REVERSED flag if the arc is not consistent
     std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEnd);
-    if (aProjection && anEnd->distance(aProjection) > tolerance) {
-      anEndAttr->setValue(aProjection);
-      anEnd = aProjection;
-    }
-    data()->blockSendAttributeUpdated(aWasBlocked, false);
-
-    double aParameterNew = 0.0;
-    if(aCircleForArc->parameter(anEnd, paramTolerance, aParameterNew)) {
-      bool aWasBlocked = data()->blockSendAttributeUpdated(true);
-      if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) {
-        if(!boolean(REVERSED_ID())->value()) {
-          boolean(REVERSED_ID())->setValue(true);
-        }
-      } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) {
-        if(boolean(REVERSED_ID())->value()) {
-          boolean(REVERSED_ID())->setValue(false);
+    if (aProjection && anEnd->distance(aProjection) <= tolerance) {
+      double aParameterNew = 0.0;
+      if(aCircleForArc->parameter(anEnd, paramTolerance, aParameterNew)) {
+        bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+        if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) {
+          if(!boolean(REVERSED_ID())->value()) {
+            boolean(REVERSED_ID())->setValue(true);
+          }
+        } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) {
+          if(boolean(REVERSED_ID())->value()) {
+            boolean(REVERSED_ID())->setValue(false);
+          }
         }
+        data()->blockSendAttributeUpdated(aWasBlocked, false);
       }
-      data()->blockSendAttributeUpdated(aWasBlocked, false);
+      myParamBefore = aParameterNew;
     }
-    myParamBefore = aParameterNew;
   }
 
   double aRadius = 0;
index 8d2ab687e1ba5b2804787b0b610777e158369c55..3cc02a863e73f99b635880abcd94b982366ebcc6 100644 (file)
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
 
+#include <ModelAPI_Events.h>
 #include <ModelGeomAlgo_Point2D.h>
 #include <GeomDataAPI_Point2D.h>
 
 #include <SketcherPrs_Factory.h>
 
+#include <Events_Loop.h>
+
 SketchPlugin_ConstraintCoincidence::SketchPlugin_ConstraintCoincidence()
 {
 }
@@ -96,3 +99,29 @@ AttributePoint2DPtr SketchPlugin_ConstraintCoincidence::getPoint(const FeaturePt
                                  SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
   return aPoint;
 }
+
+void SketchPlugin_ConstraintCoincidence::createCoincidenceFeature(SketchPlugin_Sketch* theSketch,
+                                           const std::shared_ptr<GeomDataAPI_Point2D>& thePoint1,
+                                           const std::shared_ptr<GeomDataAPI_Point2D>& thePoint2)
+{
+  FeaturePtr aFeature;
+  if (theSketch) {
+    aFeature = theSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+  } else {
+    std::shared_ptr<ModelAPI_Document> aDoc = theSketch->document();
+    aFeature = aDoc->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+  }
+
+  std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
+
+  std::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 = std::dynamic_pointer_cast<
+      ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  aRef1->setAttr(thePoint1);
+
+  std::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 = std::dynamic_pointer_cast<
+      ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  aRef2->setAttr(thePoint2);
+
+  // we need to flush created signal in order to coincidence is processed by solver
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+}
index 4990259e250f8b36c7ef0ed3f1de00898d62ea6f..c41358c3cbc930131be34a63ce0ccf5d1ccbee03 100644 (file)
@@ -52,6 +52,14 @@ class SketchPlugin_ConstraintCoincidence : public SketchPlugin_ConstraintBase
   static FeaturePtr findCoincidenceFeature(const FeaturePtr& theFeature1,
                                            const FeaturePtr& theFeature2);
 
+  /// Creates a constraint on two points
+  /// \param theSketch a sketch feature
+  /// \param thePoint1 the first point
+  /// \param thePoint2 the second point
+  static void createCoincidenceFeature(SketchPlugin_Sketch* theSketch,
+                                const std::shared_ptr<GeomDataAPI_Point2D>& thePoint1,
+                                const std::shared_ptr<GeomDataAPI_Point2D>& thePoint2);
+
   /// Returns point of coincidence feature
   /// \param theFeature a coincidence feature
   /// \return point 2d attribute. Coincidence always has at least one point 2d attribute
index 7039a37ad1c79d4bf6d66fabe97770984f6affd3..2a9acd4b1e7e26af080be5eca8b9c84bafaa93ac 100644 (file)
@@ -24,6 +24,7 @@
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Validator.h>
 
+#include <GeomAlgoAPI_Circ2dBuilder.h>
 #include <GeomAlgoAPI_EdgeBuilder.h>
 
 #include <GeomAPI_Circ2d.h>
 
 const double tolerance = 1.e-7;
 const double paramTolerance = 1.e-4;
+const double PI = 3.141592653589793238463;
 
 /// \brief Attract specified point on theNewArc to the attribute of theFeature
 static void recalculateAttributes(FeaturePtr theNewArc, const std::string& theNewArcAttribute,
   FeaturePtr theFeature, const std::string& theFeatureAttribute);
 
+
+/// \brief Calculate radius of a fillet.
+///        It should not be greater than 1/3 of shortest edge length.
+static double calculateFilletRadius(FeaturePtr theFilletFeatures[2]);
+
 /// \brief Calculates center of fillet arc and coordinates of tangency points
-static void calculateFilletCenter(FeaturePtr theFeatureA, FeaturePtr theFeatureB,
-                                  double theRadius, bool theNotInversed[2],
+static void calculateFilletCenter(FeaturePtr theFilletFeatures[2],
+                                  double theFilletRadius,
+                                  const std::shared_ptr<GeomAPI_Ax3>& theSketchPlane,
                                   std::shared_ptr<GeomAPI_XY>& theCenter,
                                   std::shared_ptr<GeomAPI_XY>& theTangentA,
                                   std::shared_ptr<GeomAPI_XY>& theTangentB);
 
-/// Get point on 1/3 length of edge from fillet point
-static void getPointOnEdge(const FeaturePtr theFeature,
-                           const std::shared_ptr<GeomAPI_Pnt2d> theFilletPoint,
-                           std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
-
-/// Get distance from point to feature
-static double getProjectionDistance(const FeaturePtr theFeature,
-                             const std::shared_ptr<GeomAPI_Pnt2d> thePoint);
-
 /// Get coincide edges for fillet
 static std::set<FeaturePtr> getCoincides(const FeaturePtr& theConstraintCoincidence);
 
@@ -232,18 +231,8 @@ bool SketchPlugin_Fillet::calculateFilletParameters()
     return false;
   }
 
-  // Getting points located at 1/3 of edge length from fillet point.
   std::shared_ptr<GeomAPI_Pnt2d> aFilletPnt2d = aFilletPoint2D->pnt();
-  std::shared_ptr<GeomAPI_Pnt2d> aPnt1, aPnt2;
-  getPointOnEdge(myBaseFeatures[0], aFilletPnt2d, aPnt1);
-  getPointOnEdge(myBaseFeatures[1], aFilletPnt2d, aPnt2);
-
-  /// Getting distances.
-  double aDistance1 = getProjectionDistance(myBaseFeatures[1], aPnt1);
-  double aDistance2 = getProjectionDistance(myBaseFeatures[0], aPnt2);
-
-  // Calculate radius value for fillet.
-  double aRadius = aDistance1 < aDistance2 ? aDistance1 / 2.0 : aDistance2 / 2.0;
+  double aRadius = calculateFilletRadius(myBaseFeatures);
 
   // Calculate arc attributes.
   static const int aNbFeatures = 2;
@@ -276,8 +265,9 @@ bool SketchPlugin_Fillet::calculateFilletParameters()
       }
   }
 
-  calculateFilletCenter(myBaseFeatures[0], myBaseFeatures[1], aRadius,
-      myIsNotInversed, myCenterXY, myTangentXY1, myTangentXY2);
+  std::shared_ptr<GeomAPI_Ax3> aSketchPlane = SketchPlugin_Sketch::plane(sketch());
+  calculateFilletCenter(myBaseFeatures, aRadius, aSketchPlane,
+                        myCenterXY, myTangentXY1, myTangentXY2);
 
   // Tangent directions of the features in coincident point.
   std::shared_ptr<GeomAPI_Dir2d> aTangentDir[aNbFeatures];
@@ -375,344 +365,88 @@ void recalculateAttributes(FeaturePtr theNewArc,  const std::string& theNewArcAt
       theFeature->attribute(theFeatureAttribute))->setValue(anArcPoint->x(), anArcPoint->y());
 }
 
-/// \brief Find intersections of lines shifted along normal direction
-void possibleFilletCenterLineLine(
-    std::shared_ptr<GeomAPI_XY> thePointA, std::shared_ptr<GeomAPI_Dir2d> theDirA,
-    std::shared_ptr<GeomAPI_XY> thePointB, std::shared_ptr<GeomAPI_Dir2d> theDirB,
-    double theRadius, std::list< std::shared_ptr<GeomAPI_XY> >& theCenters)
+static std::shared_ptr<GeomAPI_Pnt2d> toPoint(const AttributePtr& theAttribute)
 {
-  std::shared_ptr<GeomAPI_Dir2d> aDirAT(new GeomAPI_Dir2d(-theDirA->y(), theDirA->x()));
-  std::shared_ptr<GeomAPI_Dir2d> aDirBT(new GeomAPI_Dir2d(-theDirB->y(), theDirB->x()));
-  std::shared_ptr<GeomAPI_XY> aPntA, aPntB;
-  double aDet = theDirA->cross(theDirB);
-  for (double aStepA = -1.0; aStepA <= 1.0; aStepA += 2.0) {
-    aPntA = thePointA->added(aDirAT->xy()->multiplied(aStepA * theRadius));
-    for (double aStepB = -1.0; aStepB <= 1.0; aStepB += 2.0) {
-      aPntB = thePointB->added(aDirBT->xy()->multiplied(aStepB * theRadius));
-      double aVX = aDirAT->xy()->dot(aPntA);
-      double aVY = aDirBT->xy()->dot(aPntB);
-      std::shared_ptr<GeomAPI_XY> aPoint(new GeomAPI_XY(
-          (theDirB->x() * aVX - theDirA->x() * aVY) / aDet,
-          (theDirB->y() * aVX - theDirA->y() * aVY) / aDet));
-      theCenters.push_back(aPoint);
-    }
-  }
+  std::shared_ptr<GeomAPI_Pnt2d> aPoint;
+  AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
+  if (aPointAttr)
+    aPoint = aPointAttr->pnt();
+  return aPoint;
 }
 
-/// \brief Find intersections of line shifted along normal direction in both sides
-///        and a circle with extended radius
-void possibleFilletCenterLineArc(
-    std::shared_ptr<GeomAPI_XY> theStartLine, std::shared_ptr<GeomAPI_Dir2d> theDirLine,
-    std::shared_ptr<GeomAPI_XY> theCenterArc, double theRadiusArc,
-    double theRadius, std::list< std::shared_ptr<GeomAPI_XY> >& theCenters)
+static std::shared_ptr<GeomAPI_Lin2d> toLine(const FeaturePtr& theFeature)
 {
-  std::shared_ptr<GeomAPI_Dir2d> aDirT(new GeomAPI_Dir2d(-theDirLine->y(), theDirLine->x()));
-  std::shared_ptr<GeomAPI_XY> aPnt;
-  double aDirNorm2 = theDirLine->dot(theDirLine);
-  double aRad = 0.0;
-  double aDirX = theDirLine->x();
-  double aDirX2 = theDirLine->x() * theDirLine->x();
-  double aDirY2 = theDirLine->y() * theDirLine->y();
-  double aDirXY = theDirLine->x() * theDirLine->y();
-  for (double aStepA = -1.0; aStepA <= 1.0; aStepA += 2.0) {
-    aPnt = theStartLine->added(aDirT->xy()->multiplied(aStepA * theRadius));
-    double aCoeff = aDirT->xy()->dot(aPnt->decreased(theCenterArc));
-    double aCoeff2 = aCoeff * aCoeff;
-    for (double aStepB = -1.0; aStepB <= 1.0; aStepB += 2.0) {
-      aRad = theRadiusArc + aStepB * theRadius;
-      double aD = aRad * aRad * aDirNorm2 - aCoeff2;
-      if (aD < 0.0)
-        continue;
-      double aDs = sqrt(aD);
-      double x1 = theCenterArc->x() + (aCoeff * aDirT->x() - aDirT->y() * aDs) / aDirNorm2;
-      double x2 = theCenterArc->x() + (aCoeff * aDirT->x() + aDirT->y() * aDs) / aDirNorm2;
-      double y1 = (aDirX2 * aPnt->y() + aDirY2 * theCenterArc->y() -
-          aDirXY * (aPnt->x() - theCenterArc->x()) - theDirLine->y() * aDs) / aDirNorm2;
-      double y2 = (aDirX2 * aPnt->y() + aDirY2 * theCenterArc->y() -
-          aDirXY * (aPnt->x() - theCenterArc->x()) + theDirLine->y() * aDs) / aDirNorm2;
-
-      std::shared_ptr<GeomAPI_XY> aPoint1(new GeomAPI_XY(x1, y1));
-      theCenters.push_back(aPoint1);
-      std::shared_ptr<GeomAPI_XY> aPoint2(new GeomAPI_XY(x2, y2));
-      theCenters.push_back(aPoint2);
-    }
+  std::shared_ptr<GeomAPI_Lin2d> aLine;
+  if (theFeature->getKind() == SketchPlugin_Line::ID()) {
+    std::shared_ptr<GeomAPI_Pnt2d> aStart =
+        toPoint( theFeature->attribute(SketchPlugin_Line::START_ID()) );
+    std::shared_ptr<GeomAPI_Pnt2d> aEnd =
+        toPoint( theFeature->attribute(SketchPlugin_Line::END_ID()) );
+    aLine = std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aStart, aEnd));
   }
+  return aLine;
 }
 
-/// \brief Find intersections of two circles with extended radii
-void possibleFilletCenterArcArc(
-    std::shared_ptr<GeomAPI_XY> theCenterA, double theRadiusA,
-    std::shared_ptr<GeomAPI_XY> theCenterB, double theRadiusB,
-    double theRadius, std::list< std::shared_ptr<GeomAPI_XY> >& theCenters)
+static std::shared_ptr<GeomAPI_Circ2d> toCircle(const FeaturePtr& theFeature)
 {
-  std::shared_ptr<GeomAPI_XY> aCenterDir = theCenterB->decreased(theCenterA);
-  double aCenterDist2 = aCenterDir->dot(aCenterDir);
-  double aCenterDist = sqrt(aCenterDist2);
-
-  double aRadA, aRadB;
-  for (double aStepA = -1.0; aStepA <= 1.0; aStepA += 2.0) {
-    aRadA = theRadiusA + aStepA * theRadius;
-    for (double aStepB = -1.0; aStepB <= 1.0; aStepB += 2.0) {
-      aRadB = theRadiusB + aStepB * theRadius;
-      if (aRadA + aRadB < aCenterDist || fabs(aRadA - aRadB) > aCenterDist)
-        continue; // there is no intersections
-
-      double aMedDist = (aRadA * aRadA - aRadB * aRadB + aCenterDist2) / (2.0 * aCenterDist);
-      double aHeight = sqrt(aRadA * aRadA - aMedDist * aMedDist);
-
-      double x1 = theCenterA->x() +
-        (aMedDist * aCenterDir->x() + aCenterDir->y() * aHeight) / aCenterDist;
-      double y1 = theCenterA->y() +
-        (aMedDist * aCenterDir->y() - aCenterDir->x() * aHeight) / aCenterDist;
-
-      double x2 = theCenterA->x() +
-        (aMedDist * aCenterDir->x() - aCenterDir->y() * aHeight) / aCenterDist;
-      double y2 = theCenterA->y() +
-        (aMedDist * aCenterDir->y() + aCenterDir->x() * aHeight) / aCenterDist;
-
-      std::shared_ptr<GeomAPI_XY> aPoint1(new GeomAPI_XY(x1, y1));
-      theCenters.push_back(aPoint1);
-      std::shared_ptr<GeomAPI_XY> aPoint2(new GeomAPI_XY(x2, y2));
-      theCenters.push_back(aPoint2);
-    }
+  std::shared_ptr<GeomAPI_Circ2d> aCircle;
+  if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
+    std::shared_ptr<GeomAPI_Pnt2d> aCenter =
+        toPoint( theFeature->attribute(SketchPlugin_Arc::CENTER_ID()) );
+    std::shared_ptr<GeomAPI_Pnt2d> aStart =
+        toPoint( theFeature->attribute(SketchPlugin_Arc::START_ID()) );
+    aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aStart));
   }
+  return aCircle;
 }
 
-void calculateFilletCenter(FeaturePtr theFeatureA, FeaturePtr theFeatureB,
-                           double theRadius, bool theNotInversed[2],
+
+void calculateFilletCenter(FeaturePtr theFilletFeatures[2],
+                           double theFilletRadius,
+                           const std::shared_ptr<GeomAPI_Ax3>& theSketchPlane,
                            std::shared_ptr<GeomAPI_XY>& theCenter,
                            std::shared_ptr<GeomAPI_XY>& theTangentA,
                            std::shared_ptr<GeomAPI_XY>& theTangentB)
 {
-  static const int aNbFeatures = 2;
-  FeaturePtr aFeature[aNbFeatures] = {theFeatureA, theFeatureB};
-  std::shared_ptr<GeomAPI_XY> aStart[aNbFeatures], aEnd[aNbFeatures], aCenter[aNbFeatures];
-  std::shared_ptr<GeomDataAPI_Point2D> aStartPoint, aEndPoint;
-
-  for (int i = 0; i < aNbFeatures; i++) {
-    if (aFeature[i]->getKind() == SketchPlugin_Line::ID()) {
-      aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-          aFeature[i]->attribute(SketchPlugin_Line::START_ID()));
-      aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-          aFeature[i]->attribute(SketchPlugin_Line::END_ID()));
-    } else if (aFeature[i]->getKind() == SketchPlugin_Arc::ID()) {
-      aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-          aFeature[i]->attribute(SketchPlugin_Arc::START_ID()));
-      aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-          aFeature[i]->attribute(SketchPlugin_Arc::END_ID()));
-      aCenter[i] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-          aFeature[i]->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt()->xy();
-    } else
-      return;
-    aStart[i] = std::shared_ptr<GeomAPI_XY>(theNotInversed[i] ?
-        new GeomAPI_XY(aStartPoint->x(), aStartPoint->y()) :
-        new GeomAPI_XY(aEndPoint->x(), aEndPoint->y()));
-    aEnd[i] = std::shared_ptr<GeomAPI_XY>(theNotInversed[i] ?
-        new GeomAPI_XY(aEndPoint->x(), aEndPoint->y()) :
-        new GeomAPI_XY(aStartPoint->x(), aStartPoint->y()));
-  }
-
-  if (theFeatureA->getKind() == SketchPlugin_Line::ID() &&
-      theFeatureB->getKind() == SketchPlugin_Line::ID()) {
-    std::shared_ptr<GeomAPI_Dir2d> aDir[2];
-    std::shared_ptr<GeomAPI_Dir2d> aDirT[2];
-    for (int i = 0; i < aNbFeatures; i++) {
-      aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aEnd[i]->decreased(aStart[i])));
-      aDirT[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(-aDir[i]->y(), aDir[i]->x()));
+  GeomShapePtr aShapeA = theFilletFeatures[0]->lastResult()->shape();
+  GeomShapePtr aShapeB = theFilletFeatures[1]->lastResult()->shape();
+
+  GeomAlgoAPI_Circ2dBuilder aCircBuilder(theSketchPlane);
+  aCircBuilder.addTangentCurve(aShapeA);
+  aCircBuilder.addTangentCurve(aShapeB);
+  aCircBuilder.setRadius(theFilletRadius);
+
+  std::shared_ptr<GeomAPI_Circ2d> aFilletCircle = aCircBuilder.circle();
+  if (!aFilletCircle)
+    return;
+
+  theCenter = aFilletCircle->center()->xy();
+  // tangent points
+  std::shared_ptr<GeomAPI_Pnt2d> aTgPoints[2];
+  for (int i = 0; i < 2; ++i) {
+    std::shared_ptr<GeomAPI_Circ2d> aCircle = toCircle(theFilletFeatures[i]);
+    if (aCircle)
+      aTgPoints[i] = aCircle->project(aFilletCircle->center());
+    else {
+      std::shared_ptr<GeomAPI_Lin2d> aLine = toLine(theFilletFeatures[i]);
+      if (aLine)
+        aTgPoints[i] = aLine->project(aFilletCircle->center());
     }
-
-    // get and filter possible centers
-    std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
-    possibleFilletCenterLineLine(aStart[0], aDir[0], aStart[1], aDir[1],
-                                 theRadius, aSuspectCenters);
-    double aDot = 0.0;
-    std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
-    for (; anIt != aSuspectCenters.end(); anIt++) {
-      aDot = aDirT[0]->xy()->dot(aStart[0]->decreased(*anIt));
-      theTangentA = (*anIt)->added(aDirT[0]->xy()->multiplied(aDot));
-      if (theTangentA->decreased(aStart[0])->dot(aDir[0]->xy()) < 0.0)
-        continue; // incorrect position
-      aDot = aDirT[1]->xy()->dot(aStart[1]->decreased(*anIt));
-      theTangentB = (*anIt)->added(aDirT[1]->xy()->multiplied(aDot));
-      if (theTangentB->decreased(aStart[1])->dot(aDir[1]->xy()) < 0.0)
-        continue; // incorrect position
-      // the center is found, stop searching
-      theCenter = *anIt;
-      return;
-    }
-  } else if ((theFeatureA->getKind() == SketchPlugin_Arc::ID() &&
-      theFeatureB->getKind() == SketchPlugin_Line::ID()) ||
-      (theFeatureA->getKind() == SketchPlugin_Line::ID() &&
-      theFeatureB->getKind() == SketchPlugin_Arc::ID())) {
-    int aLineInd = theFeatureA->getKind() == SketchPlugin_Line::ID() ? 0 : 1;
-    double anArcRadius = aStart[1-aLineInd]->distance(aCenter[1-aLineInd]);
-    std::shared_ptr<GeomAPI_Dir2d> aDirLine = std::shared_ptr<GeomAPI_Dir2d>(
-        new GeomAPI_Dir2d(aEnd[aLineInd]->decreased(aStart[aLineInd])));
-    std::shared_ptr<GeomAPI_Dir2d> aDirT = std::shared_ptr<GeomAPI_Dir2d>(
-        new GeomAPI_Dir2d(-aDirLine->y(), aDirLine->x()));
-
-    std::shared_ptr<GeomAPI_Dir2d> aStartArcDir = std::shared_ptr<GeomAPI_Dir2d>(
-        new GeomAPI_Dir2d(aStart[1-aLineInd]->decreased(aCenter[1-aLineInd])));
-    std::shared_ptr<GeomAPI_Dir2d> aEndArcDir = std::shared_ptr<GeomAPI_Dir2d>(
-        new GeomAPI_Dir2d(aEnd[1-aLineInd]->decreased(aCenter[1-aLineInd])));
-    double anArcAngle = aEndArcDir->angle(aStartArcDir);
-
-    // get possible centers and filter them
-    std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
-    possibleFilletCenterLineArc(aStart[aLineInd], aDirLine, aCenter[1-aLineInd],
-                                anArcRadius, theRadius, aSuspectCenters);
-    double aDot = 0.0;
-    // the line is forward into the arc
-    double innerArc = aCenter[1-aLineInd]->decreased(aStart[aLineInd])->dot(aDirLine->xy());
-    std::shared_ptr<GeomAPI_XY> aLineTgPoint, anArcTgPoint;
-    // The possible centers are ranged by their positions.
-    // If the point is not satisfy one of criteria, the weight is decreased with penalty.
-    int aBestWeight = 0;
-    std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
-    for (; anIt != aSuspectCenters.end(); anIt++) {
-      int aWeight = 2;
-      aDot = aDirT->xy()->dot(aStart[aLineInd]->decreased(*anIt));
-      aLineTgPoint = (*anIt)->added(aDirT->xy()->multiplied(aDot));
-      // Check the point is placed on the correct arc (penalty if false)
-      if (aCenter[1-aLineInd]->distance(*anIt) * innerArc > anArcRadius * innerArc)
-        aWeight -= 1;
-      std::shared_ptr<GeomAPI_Dir2d> aCurDir = std::shared_ptr<GeomAPI_Dir2d>(
-          new GeomAPI_Dir2d((*anIt)->decreased(aCenter[1-aLineInd])));
-      double aCurAngle = aCurDir->angle(aStartArcDir);
-      if (anArcAngle < 0.0) aCurAngle *= -1.0;
-      if (aCurAngle < 0.0 || aCurAngle > fabs(anArcAngle))
-        continue;
-      if (aWeight > aBestWeight)
-        aBestWeight = aWeight;
-      else if (aWeight < aBestWeight ||
-               aStart[aLineInd]->distance(*anIt) >
-               aStart[aLineInd]->distance(theCenter)) // <-- take closer point
-        continue;
-      // the center is found, stop searching
-      theCenter = *anIt;
-      anArcTgPoint = aCenter[1-aLineInd]->added(aCurDir->xy()->multiplied(anArcRadius));
-      if (theFeatureA->getKind() == SketchPlugin_Line::ID()) {
-        theTangentA = aLineTgPoint;
-        theTangentB = anArcTgPoint;
-      } else {
-        theTangentA = anArcTgPoint;
-        theTangentB = aLineTgPoint;
-      }
-      //return;
-    }
-  } else if (theFeatureA->getKind() == SketchPlugin_Arc::ID() &&
-      theFeatureB->getKind() == SketchPlugin_Arc::ID()) {
-    double anArcRadius[aNbFeatures];
-    double anArcAngle[aNbFeatures];
-    std::shared_ptr<GeomAPI_Dir2d> aStartArcDir[aNbFeatures];
-    for (int i = 0; i < aNbFeatures; i++) {
-      anArcRadius[i] = aStart[i]->distance(aCenter[i]);
-      aStartArcDir[i] = std::shared_ptr<GeomAPI_Dir2d>(
-          new GeomAPI_Dir2d(aStart[i]->decreased(aCenter[i])));
-      std::shared_ptr<GeomAPI_Dir2d> aEndArcDir = std::shared_ptr<GeomAPI_Dir2d>(
-          new GeomAPI_Dir2d(aEnd[i]->decreased(aCenter[i])));
-      anArcAngle[i] = aEndArcDir->angle(aStartArcDir[i]);
-    }
-
-    // get and filter possible centers
-    std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
-    possibleFilletCenterArcArc(aCenter[0], anArcRadius[0], aCenter[1],
-                               anArcRadius[1], theRadius, aSuspectCenters);
-    double aDot = 0.0;
-    std::shared_ptr<GeomAPI_XY> aLineTgPoint, anArcTgPoint;
-    std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
-    for (; anIt != aSuspectCenters.end(); anIt++) {
-      std::shared_ptr<GeomAPI_Dir2d> aCurDir = std::shared_ptr<GeomAPI_Dir2d>(
-          new GeomAPI_Dir2d((*anIt)->decreased(aCenter[0])));
-      double aCurAngle = aCurDir->angle(aStartArcDir[0]);
-      if (anArcAngle[0] < 0.0) aCurAngle *= -1.0;
-      if (aCurAngle < 0.0 || aCurAngle > fabs(anArcAngle[0]))
-        continue; // incorrect position
-      theTangentA = aCenter[0]->added(aCurDir->xy()->multiplied(anArcRadius[0]));
-
-      aCurDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d((*anIt)->decreased(aCenter[1])));
-      aCurAngle = aCurDir->angle(aStartArcDir[1]);
-      if (anArcAngle[1] < 0.0) aCurAngle *= -1.0;
-      if (aCurAngle < 0.0 || aCurAngle > fabs(anArcAngle[1]))
-        continue; // incorrect position
-      theTangentB = aCenter[1]->added(aCurDir->xy()->multiplied(anArcRadius[1]));
-
-      // the center is found, stop searching
-      theCenter = *anIt;
-      return;
-    }
-  }
-}
-
-void getPointOnEdge(const FeaturePtr theFeature,
-                    const std::shared_ptr<GeomAPI_Pnt2d> theFilletPoint,
-                    std::shared_ptr<GeomAPI_Pnt2d>& thePoint) {
-  if(theFeature->getKind() == SketchPlugin_Line::ID()) {
-    std::shared_ptr<GeomAPI_Pnt2d> aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt();
-    std::shared_ptr<GeomAPI_Pnt2d> aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt();
-    if(aPntStart->distance(theFilletPoint) > 1.e-7) {
-      aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-        theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt();
-      aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-        theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt();
-    }
-    thePoint.reset(
-      new GeomAPI_Pnt2d(aPntStart->xy()->added(
-      aPntEnd->xy()->decreased( aPntStart->xy() )->multiplied(1.0 / 3.0) ) ) );
-  } else {
-    std::shared_ptr<GeomAPI_Pnt2d> aPntTemp;
-    std::shared_ptr<GeomAPI_Pnt2d> aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
-    std::shared_ptr<GeomAPI_Pnt2d> aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
-    if(theFeature->attribute(SketchPlugin_Arc::REVERSED_ID())) {
-      aPntTemp = aPntStart;
-      aPntStart = aPntEnd;
-      aPntEnd = aPntTemp;
-    }
-    std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
-    std::shared_ptr<GeomAPI_Circ2d> aCirc(new GeomAPI_Circ2d(aCenterPnt, aPntStart));
-    double aStartParameter(0), anEndParameter(0);
-    aCirc->parameter(aPntStart, paramTolerance, aStartParameter);
-    aCirc->parameter(aPntEnd, paramTolerance, anEndParameter);
-    if(aPntStart->distance(theFilletPoint) > tolerance) {
-      double aTmpParameter = aStartParameter;
-      aStartParameter = anEndParameter;
-      anEndParameter = aTmpParameter;
-    }
-    double aPntParameter = aStartParameter + (anEndParameter - aStartParameter) / 3.0;
-    aCirc->D0(aPntParameter, thePoint);
   }
+  theTangentA = aTgPoints[0]->xy();
+  theTangentB = aTgPoints[1]->xy();
 }
 
-double getProjectionDistance(const FeaturePtr theFeature,
-                             const std::shared_ptr<GeomAPI_Pnt2d> thePoint)
+double calculateFilletRadius(FeaturePtr theFilletFeatures[2])
 {
-  std::shared_ptr<GeomAPI_Pnt2d> aProjectPnt;
-  if(theFeature->getKind() == SketchPlugin_Line::ID()) {
-    std::shared_ptr<GeomAPI_Pnt2d> aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt();
-    std::shared_ptr<GeomAPI_Pnt2d> aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt();
-    std::shared_ptr<GeomAPI_Lin2d> aLin(new GeomAPI_Lin2d(aPntStart, aPntEnd));
-    aProjectPnt = aLin->project(thePoint);
-  } else {
-    std::shared_ptr<GeomAPI_Pnt2d> aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
-    std::shared_ptr<GeomAPI_Pnt2d> aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
-    std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
-    std::shared_ptr<GeomAPI_Circ2d> aCirc(new GeomAPI_Circ2d(aCenterPnt, aPntStart));
-    aProjectPnt = aCirc->project(thePoint);
-  }
-  if(aProjectPnt.get()) {
-    return aProjectPnt->distance(thePoint);
+  double aLengths[2] = { 0, 0 };
+  for (int i = 0; i < 2; ++i) {
+    GeomShapePtr aShape = theFilletFeatures[i]->lastResult()->shape();
+    std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(aShape);
+    if (anEdge)
+      aLengths[i] = anEdge->length();
   }
-  return -1;
+  return std::min(aLengths[0], aLengths[1]) / 6.0;
 }
 
 std::set<FeaturePtr> getCoincides(const FeaturePtr& theConstraintCoincidence)
index 49388f26a5aad2382cf7ec1ac1ae015b428027f7..7cee33ca4b6af7a17468aaa85c7ba4c00edaa566 100644 (file)
@@ -55,13 +55,13 @@ class SketchPlugin_Fillet: public SketchPlugin_SketchEntity, public GeomAPI_IPre
 
   /// Reimplemented from ModelAPI_Feature::isMacro().
   /// \returns true
-  SKETCHPLUGIN_EXPORT virtual bool isMacro() const {return true;};
+  SKETCHPLUGIN_EXPORT virtual bool isMacro() const {return true;}
 
-  SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const {return false;};
+  SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const {return false;}
 
   /// Reimplemented from SketchPlugin_Feature::move().
   /// Do nothing.
-  SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY) {};
+  SKETCHPLUGIN_EXPORT virtual void move(const double, const double) {}
 
   /// \brief Use plugin manager for features creation
   SketchPlugin_Fillet();
index 10e1ed235e937aa2d04f45d5b2aa19cb2e6d0d3b..5760a866f92da39fbd94002d8f7d2299e163c886 100644 (file)
@@ -6,7 +6,10 @@
 
 #include "SketchPlugin_Line.h"
 #include "SketchPlugin_Sketch.h"
+#include "SketchPlugin_ConstraintCoincidence.h"
+
 #include <ModelAPI_Data.h>
+#include <ModelAPI_EventReentrantMessage.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeBoolean.h>
@@ -64,6 +67,13 @@ void SketchPlugin_Line::execute()
       aConstr->setShape(anEdge);
       aConstr->setIsInHistory(false);
       setResult(aConstr);
+
+      static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
+      std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
+          <ModelAPI_EventReentrantMessage>(new ModelAPI_EventReentrantMessage(anId, 0));
+      aMessage->setCreatedFeature(ModelAPI_Feature::feature(
+                                  data()->attribute(START_ID())->owner()));
+      Events_Loop::loop()->send(aMessage);
     }
   }
 }
@@ -83,6 +93,28 @@ void SketchPlugin_Line::move(double theDeltaX, double theDeltaY)
   aPoint2->move(theDeltaX, theDeltaY);
 }
 
+std::string SketchPlugin_Line::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+  std::string aFilledAttributeName;
+
+  std::shared_ptr<ModelAPI_EventReentrantMessage> aReentrantMessage =
+        std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
+  if (aReentrantMessage.get()) {
+    FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+
+    // Initialize new line with first point equal to end of previous
+    std::shared_ptr<ModelAPI_Data> aSFData = aCreatedFeature->data();
+    std::shared_ptr<GeomDataAPI_Point2D> aSPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                 aSFData->attribute(SketchPlugin_Line::END_ID()));
+    std::shared_ptr<ModelAPI_Data> aNFData = data();
+    std::shared_ptr<GeomDataAPI_Point2D> aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                 aNFData->attribute(SketchPlugin_Line::START_ID()));
+    aNPoint->setValue(aSPoint->x(), aSPoint->y());
+    SketchPlugin_ConstraintCoincidence::createCoincidenceFeature(sketch(), aSPoint, aNPoint);
+  }
+  return aFilledAttributeName;
+}
+
 double SketchPlugin_Line::distanceToPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
 {
   double aDelta = 0;
index e24e90e5444c0f52762a57e99e576f89258db299..173c2c3564570554418ba6f8db38be6381b98239 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef SketchPlugin_Line_H_
 #define SketchPlugin_Line_H_
 
+#include <ModelAPI_IReentrant.h>
+
 #include "SketchPlugin.h"
 #include <SketchPlugin_SketchEntity.h>
 #include <SketchPlugin_Sketch.h>
@@ -18,7 +20,8 @@ class GeomAPI_Pnt2d;
  * \ingroup Plugins
  * \brief Feature for creation of the new part in PartSet.
  */
-class SketchPlugin_Line : public SketchPlugin_SketchEntity
+class SketchPlugin_Line : public SketchPlugin_SketchEntity,
+                          public ModelAPI_IReentrant
 {
  public:
   /// Arc feature kind
@@ -64,6 +67,11 @@ class SketchPlugin_Line : public SketchPlugin_SketchEntity
   /// \param theDeltaY the delta for Y coordinate is moved
   SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
 
+  /// Apply information of the message to current object. It fills start attribute of
+  /// the currrent feature by last attribute of the message feature, build coincidence
+  /// if message has selected object
+  virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
   /// Return the distance between the feature and the point
   /// \param thePoint the point
   double distanceToPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
index de876dc966b433630f81fa2bd1f576587de39421..e963cfe14c33a4cc1a9b2503fda2fdc9e4f6e656 100644 (file)
 #include "SketchPlugin_ConstraintTangent.h"
 #include "SketchPlugin_Sketch.h"
 #include "SketchPlugin_Tools.h"
+#include "SketchPlugin_MacroArcReentrantMessage.h"
 
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Events.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
 
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Vertex.h>
 #include <GeomAPI_XY.h>
+#include <GeomAPI_ShapeIterator.h>
 
 #include <GeomDataAPI_Point2D.h>
 #include <GeomDataAPI_Dir.h>
-#include <GeomAlgoAPI_PointBuilder.h>
+
+#include <GeomAlgoAPI_Circ2dBuilder.h>
 #include <GeomAlgoAPI_EdgeBuilder.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_PointBuilder.h>
 
 // for sqrt on Linux
 #include <math.h>
@@ -48,6 +53,69 @@ static void projectPointOnCircle(AttributePoint2DPtr& thePoint, const GeomAPI_Ci
     thePoint->setValue(aProjection);
 }
 
+static void intersectShapeAndCircle(const GeomShapePtr& theShape,
+                                    const GeomAPI_Circ2d& theCircle,
+                                    const SketchPlugin_Sketch* theSketch,
+                                    AttributePoint2DPtr& theIntersection)
+{
+  if (!theShape->isEdge())
+    return projectPointOnCircle(theIntersection, theCircle);
+
+  // convert shape to unbounded
+  std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theShape));
+  if (anEdge->isLine()) {
+    static const double HALF_SIZE = 1.e6;
+    std::shared_ptr<GeomAPI_XYZ> aLoc = anEdge->line()->location()->xyz();
+    std::shared_ptr<GeomAPI_XYZ> aDir = anEdge->line()->direction()->xyz();
+
+    std::shared_ptr<GeomAPI_Pnt> aStart(
+        new GeomAPI_Pnt(aLoc->added(aDir->multiplied(-HALF_SIZE))));
+    std::shared_ptr<GeomAPI_Pnt> aEnd(
+        new GeomAPI_Pnt(aLoc->added(aDir->multiplied(HALF_SIZE))));
+    anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, aEnd);
+  } else if (anEdge->isArc()) {
+    std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
+    anEdge = GeomAlgoAPI_EdgeBuilder::lineCircle(
+        aCircle->center(), aCircle->normal(), aCircle->radius());
+  }
+
+  // convert 2D circle to 3D object
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter2d = theCircle.center();
+  std::shared_ptr<GeomAPI_Pnt> aCenter(theSketch->to3D(aCenter2d->x(), aCenter2d->y()));
+  std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+      const_cast<SketchPlugin_Sketch*>(theSketch)->attribute(SketchPlugin_Sketch::NORM_ID()));
+  std::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
+
+  GeomShapePtr aCircleShape =
+      GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, theCircle.radius());
+
+  GeomShapePtr anInter = anEdge->intersect(aCircleShape);
+  std::shared_ptr<GeomAPI_Pnt2d> anInterPnt;
+  if (!anInter)
+    return projectPointOnCircle(theIntersection, theCircle);
+  if (anInter->isVertex()) {
+    std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(anInter));
+    anInterPnt = theSketch->to2D(aVertex->point());
+  } else if (anInter->isCompound()) {
+    double aMinDist = 1.e300;
+
+    GeomAPI_ShapeIterator anIt(anInter);
+    for (; anIt.more(); anIt.next()) {
+      GeomShapePtr aCurrent = anIt.current();
+      if (!aCurrent->isVertex())
+        continue;
+      std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aCurrent));
+      std::shared_ptr<GeomAPI_Pnt2d> aPnt = theSketch->to2D(aVertex->point());
+      double aDist = aPnt->distance(theIntersection->pnt());
+      if (aDist < aMinDist) {
+        aMinDist = aDist;
+        anInterPnt = aPnt;
+      }
+    }
+  }
+  theIntersection->setValue(anInterPnt);
+}
+
 
 SketchPlugin_MacroArc::SketchPlugin_MacroArc()
 : SketchPlugin_SketchEntity(),
@@ -82,12 +150,16 @@ void SketchPlugin_MacroArc::initAttributes()
   data()->addAttribute(END_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
   data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
 
+  data()->addAttribute(EDIT_ARC_TYPE_ID(), ModelAPI_AttributeString::typeId());
+
   boolean(REVERSED_ID())->setValue(false);
+  string(EDIT_ARC_TYPE_ID())->setValue("");
 
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), START_POINT_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_POINT_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_ARC_TYPE_ID());
 }
 
 void SketchPlugin_MacroArc::attributeChanged(const std::string& theID)
@@ -143,12 +215,17 @@ void SketchPlugin_MacroArc::attributeChanged(const std::string& theID)
   }
 
   bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+  if(myCenter.get()) {
+    // center attribute is used in processEvent() to set reference to reentrant arc
+    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))
+        ->setValue(myCenter);
+  }
   real(RADIUS_ID())->setValue(aRadius);
   real(ANGLE_ID())->setValue(anAngle);
   data()->blockSendAttributeUpdated(aWasBlocked, false);
 }
 
-GeomShapePtr SketchPlugin_MacroArc::getArcShape()
+GeomShapePtr SketchPlugin_MacroArc::getArcShape(bool isBound)
 {
   if(!myStart.get() || !myEnd.get() || !myCenter.get()) {
     return GeomShapePtr();
@@ -166,9 +243,15 @@ GeomShapePtr SketchPlugin_MacroArc::getArcShape()
     std::dynamic_pointer_cast<GeomDataAPI_Dir>(aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
   std::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
 
-  GeomShapePtr anArcShape = boolean(REVERSED_ID())->value() ?
-      GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal)
-    : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal);
+  GeomShapePtr anArcShape;
+  if (isBound) {
+    anArcShape = boolean(REVERSED_ID())->value() ?
+        GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal)
+      : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal);
+  } else {
+    double aRadius = aCenter->distance(aStart);
+    anArcShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
+  }
 
   return anArcShape;
 }
@@ -268,6 +351,97 @@ void SketchPlugin_MacroArc::execute()
                                          ObjectPtr(),
                                          false);
   }
+
+  // message to init reentrant operation
+  static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId();
+  std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aMessage = std::shared_ptr
+    <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, 0));
+
+  std::string anEditArcType = string(EDIT_ARC_TYPE_ID())->value();
+  aMessage->setTypeOfCreation(!anEditArcType.empty() ? anEditArcType : anArcType);
+  aMessage->setCreatedFeature(anArcFeature);
+  Events_Loop::loop()->send(aMessage);
+}
+
+std::string SketchPlugin_MacroArc::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+  std::string aFilledAttributeName;
+  std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aReentrantMessage =
+        std::dynamic_pointer_cast<SketchPlugin_MacroArcReentrantMessage>(theMessage);
+  if (aReentrantMessage.get()) {
+    FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+    std::string anArcType = aReentrantMessage->typeOfCreation();
+
+    string(ARC_TYPE())->setValue(anArcType);
+
+    aFilledAttributeName = ARC_TYPE();
+    if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) {
+      aFilledAttributeName = TANGENT_POINT_ID();
+      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                                        attribute(aFilledAttributeName));
+      FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+      aRefAttr->setAttr(aCreatedFeature->attribute(SketchPlugin_Arc::END_ID()));
+    }
+    else {
+      ObjectPtr anObject = aReentrantMessage->selectedObject();
+      AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
+      std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
+
+      if (aClickedPoint.get() && (anObject.get() || anAttribute.get())) {
+        if (anArcType == ARC_TYPE_BY_CENTER_AND_POINTS() ||
+            anArcType == ARC_TYPE_BY_THREE_POINTS()) {
+          std::string aReferenceAttributeName;
+          if (anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) {
+            aFilledAttributeName = CENTER_POINT_ID();
+            aReferenceAttributeName = CENTER_POINT_REF_ID();
+          }
+          else {
+            aFilledAttributeName = START_POINT_2_ID();
+            aReferenceAttributeName = START_POINT_REF_ID();
+          }
+          // fill 2d point attribute
+          AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                            attribute(aFilledAttributeName));
+          aPointAttr->setValue(aClickedPoint);
+          // fill reference attribute
+          AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                                          attribute(aReferenceAttributeName));
+          if (aRefAttr.get()) {
+            if (anAttribute.get()) {
+              if (!anAttribute->owner().get() || !anAttribute->owner()->data()->isValid()) {
+                FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+                if (aCreatedFeature.get()) {
+                  std::string anID = anAttribute->id();
+                  std::string anArcID;
+                  if (anID == END_POINT_1_ID() || anID == END_POINT_2_ID() ||
+                      anID == END_POINT_3_ID())
+                    anArcID = SketchPlugin_Arc::END_ID();
+                  else if (anID == START_POINT_1_ID() || anID ==START_POINT_2_ID())
+                    anArcID = SketchPlugin_Arc::START_ID();
+                  else if (anID == CENTER_POINT_ID())
+                    anArcID = SketchPlugin_Arc::CENTER_ID();
+                  anAttribute = aCreatedFeature->attribute(anArcID);
+                }
+              }
+              aRefAttr->setAttr(anAttribute);
+            }
+            else if (anObject.get()) {
+              // if presentation of previous reentrant macro arc is used, the object is invalid,
+              // we should use result of previous feature of the message(Arc)
+              if (!anObject->data()->isValid()) {
+                FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+                if (aCreatedFeature.get())
+                  anObject = aCreatedFeature->lastResult();
+              }
+              aRefAttr->setObject(anObject);
+            }
+          }
+        }
+      }
+    }
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+  }
+  return aFilledAttributeName;
 }
 
 FeaturePtr SketchPlugin_MacroArc::createArcFeature()
@@ -311,9 +485,24 @@ void SketchPlugin_MacroArc::fillByCenterAndTwoPassed()
 
   GeomAPI_Circ2d aCircleForArc(myCenter, myStart);
 
-  // End point should be a projection on circle.
   bool aWasBlocked = data()->blockSendAttributeUpdated(true);
-  projectPointOnCircle(anEndPointAttr, aCircleForArc);
+  // check the end point is referred to another feature
+  GeomShapePtr aRefShape;
+  AttributeRefAttrPtr aEndPointRefAttr = refattr(END_POINT_REF_ID());
+  if (aEndPointRefAttr && aEndPointRefAttr->isInitialized()) {
+    if (aEndPointRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aEndPointRefAttr->object());
+      if (aFeature)
+        aRefShape = aFeature->lastResult()->shape();
+    }
+  }
+  if (aRefShape) {
+    // Calculate end point as an intersection between circle and another shape
+    intersectShapeAndCircle(aRefShape, aCircleForArc, sketch(), anEndPointAttr);
+  } else {
+    // End point should be a projection on circle.
+    projectPointOnCircle(anEndPointAttr, aCircleForArc);
+  }
   data()->blockSendAttributeUpdated(aWasBlocked, false);
   myEnd = anEndPointAttr->pnt();
 
@@ -357,17 +546,22 @@ void SketchPlugin_MacroArc::fillByThreePassedPoints()
     SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
         refattr(PASSED_POINT_REF_ID()), aPassedPointAttr, aTangentCurve, aPassedPnt);
 
-    std::shared_ptr<GeomAPI_Interface> aPassed;
-    if (aTangentCurve)
-      aPassed = aTangentCurve;
-    else
-      aPassed = aPassedPnt;
-
-    std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
-    GeomAPI_Circ2d aCircle(myStart, myEnd, aPassed, anAxis);
-    myCenter = aCircle.center();
+    GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
+    aCircBuilder.addPassingPoint(myStart);
+    aCircBuilder.addPassingPoint(myEnd);
+    if (aTangentCurve) {
+      aCircBuilder.addTangentCurve(aTangentCurve);
+      aCircBuilder.setClosestPoint(aPassedPointAttr->pnt());
+    } else
+      aCircBuilder.addPassingPoint(aPassedPnt);
+
+    std::shared_ptr<GeomAPI_Circ2d> aCircle = aCircBuilder.circle();
+    if (!aCircle)
+      return;
+    myCenter = aCircle->center();
 
-    recalculateReversedFlagByPassed(aCircle);
+    aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(myCenter, myStart));
+    recalculateReversedFlagByPassed(*aCircle);
   } else
     myCenter.reset(new GeomAPI_Pnt2d(myStart->xy()->added(myEnd->xy())->multiplied(0.5)));
 }
@@ -416,11 +610,15 @@ void SketchPlugin_MacroArc::fillByTangentEdge()
   FeaturePtr aTangentFeature = ModelAPI_Feature::feature(aTangentPointAttr->owner());
   std::shared_ptr<GeomAPI_Shape> aTangentShape = aTangentFeature->lastResult()->shape();
 
-  std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
-  GeomAPI_Circ2d aCircle(myStart, myEnd, aTangentShape, anAxis);
-  myCenter = aCircle.center();
+  GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
+  aCircBuilder.addPassingPoint(myStart);
+  aCircBuilder.addPassingPoint(myEnd);
+  aCircBuilder.addTangentCurve(aTangentShape);
+
+  std::shared_ptr<GeomAPI_Circ2d> aCircle = aCircBuilder.circle();
+  myCenter = aCircle->center();
 
   // rebuild circle to set start point equal to zero parameter
-  aCircle = GeomAPI_Circ2d(myCenter, myStart);
-  recalculateReversedFlagByEnd(aCircle);
+  aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(myCenter, myStart));
+  recalculateReversedFlagByEnd(*aCircle);
 }
index cc49b0e0233db56c82a7bc39934d337b33b95adc..e36fc5d9c0ab65387e5ab9fbe81cfaab39599c83 100644 (file)
@@ -7,8 +7,9 @@
 #ifndef SketchPlugin_MacroArc_H_
 #define SketchPlugin_MacroArc_H_
 
-#include "SketchPlugin.h"
+#include <ModelAPI_IReentrant.h>
 
+#include "SketchPlugin.h"
 #include "SketchPlugin_SketchEntity.h"
 
 #include <GeomAPI_IPresentable.h>
@@ -24,7 +25,8 @@ class GeomAPI_Pnt2d;
  * it is calculated if all attributes are initialized.
  */
 class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity,
-                             public GeomAPI_IPresentable
+                             public GeomAPI_IPresentable,
+                             public ModelAPI_IReentrant
 {
  public:
   /// Arc feature kind
@@ -157,6 +159,13 @@ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity,
     return ID;
   }
 
+  /// Arc angle.
+  static const std::string& EDIT_ARC_TYPE_ID()
+  {
+    static const std::string ID("edit_arc_type");
+    return ID;
+  }
+
   /// Returns the kind of a feature
   SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
   {
@@ -189,11 +198,16 @@ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity,
 
   SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const {return false;};
 
+  /// Apply information of the message to current object. It fills reference object,
+  /// tangent type and tangent point refence in case of tangent arc
+  virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
   /// Use plugin manager for features creation.
   SketchPlugin_MacroArc();
 
   /// Returns shape of arc.
-  GeomShapePtr getArcShape();
+  /// \param isBound  if true prepare arc, otherwice create circle containing this arc
+  GeomShapePtr getArcShape(bool isBound = true);
 
 private:
   /// Set fields for center, start and end points
diff --git a/src/SketchPlugin/SketchPlugin_MacroArcReentrantMessage.h b/src/SketchPlugin/SketchPlugin_MacroArcReentrantMessage.h
new file mode 100644 (file)
index 0000000..5ad9a8c
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:    SketchPlugin_MacroArcReentrantMessage.h
+// Created: 01 Apr 2017
+// Author:  Natalia ERMOLAEVA
+
+#ifndef SketchPlugin_MacroArcReentrantMessage_H_
+#define SketchPlugin_MacroArcReentrantMessage_H_
+
+#include <ModelAPI_EventReentrantMessage.h>
+#include <Events_Loop.h>
+
+#include <SketchPlugin.h>
+
+#include <memory>
+
+/// Message that style of visualization of parameter is changed.
+/// It will be shown as expression or value
+class SketchPlugin_MacroArcReentrantMessage : public ModelAPI_EventReentrantMessage
+{
+public:
+  /// Creates an empty message
+  SKETCHPLUGIN_EXPORT SketchPlugin_MacroArcReentrantMessage(const Events_ID theID,
+                                                            const void* theSender = 0)
+  : ModelAPI_EventReentrantMessage(theID, theSender) {}
+  /// The virtual destructor
+  SKETCHPLUGIN_EXPORT virtual ~SketchPlugin_MacroArcReentrantMessage() {}
+  /// Static. Returns EventID of the message.
+
+  inline static Events_ID eventId()
+  {
+    static const char * MY_EVENT_MACRO_ARC_MESSAGE_ID("MacroArcReentrantMessage");
+    return Events_Loop::eventByName(MY_EVENT_MACRO_ARC_MESSAGE_ID);
+  }
+
+  /// Stores type of creation
+  /// \param the type
+  SKETCHPLUGIN_EXPORT void setTypeOfCreation(const std::string& theType)
+  { myTypeOfCreation = theType; }
+
+  /// Returns type of creation
+  /// \return the type
+  SKETCHPLUGIN_EXPORT std::string typeOfCreation() const { return myTypeOfCreation; }
+
+private:
+  std::string myTypeOfCreation; ///< to know what parameters of new feature should be filled
+};
+
+
+#endif
index 7232a6c37fac9462dbdc21e355d865beabbc1c0b..e0c178ddd78f70f2a940676330d8b2a8bbd3e132 100644 (file)
@@ -9,12 +9,14 @@
 #include "SketchPlugin_Circle.h"
 #include "SketchPlugin_Point.h"
 #include "SketchPlugin_Tools.h"
+#include "SketchPlugin_MacroArcReentrantMessage.h"
 
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
+#include <ModelAPI_Events.h>
 
 #include <GeomDataAPI_Dir.h>
 #include <GeomDataAPI_Point2D.h>
@@ -23,6 +25,7 @@
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Vertex.h>
 
+#include <GeomAlgoAPI_Circ2dBuilder.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
 #include <GeomAlgoAPI_EdgeBuilder.h>
 #include <GeomAlgoAPI_PointBuilder.h>
@@ -46,13 +49,15 @@ namespace {
 
 
 SketchPlugin_MacroCircle::SketchPlugin_MacroCircle()
-: SketchPlugin_SketchEntity()
+: SketchPlugin_SketchEntity(),
+  myRadius(0.0)
 {
 }
 
 void SketchPlugin_MacroCircle::initAttributes()
 {
   data()->addAttribute(CIRCLE_TYPE(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(EDIT_CIRCLE_TYPE(), ModelAPI_AttributeString::typeId());
 
   data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
   data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
@@ -69,78 +74,133 @@ void SketchPlugin_MacroCircle::initAttributes()
   data()->addAttribute(CIRCLE_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
 
+  string(EDIT_CIRCLE_TYPE())->setValue("");
+
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), THIRD_POINT_REF_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_CIRCLE_TYPE());
 }
 
 void SketchPlugin_MacroCircle::execute()
 {
+  FeaturePtr aCircle = createCircleFeature();
+
   std::string aType = string(CIRCLE_TYPE())->value();
   if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS())
-    createCircleByCenterAndPassed();
+    constraintsForCircleByCenterAndPassed(aCircle);
   else if (aType == CIRCLE_TYPE_BY_THREE_POINTS())
-    createCircleByThreePoints();
+    constraintsForCircleByThreePoints(aCircle);
+
+  // message to init reentrant operation
+  static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId();
+  std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aMessage = std::shared_ptr
+    <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, 0));
+
+  std::string anEditType = string(EDIT_CIRCLE_TYPE())->value();
+  aMessage->setTypeOfCreation(!anEditType.empty() ? anEditType : aType);
+  aMessage->setCreatedFeature(aCircle);
+  Events_Loop::loop()->send(aMessage);
 }
 
-void SketchPlugin_MacroCircle::createCircleByCenterAndPassed()
+std::string SketchPlugin_MacroCircle::processEvent(
+                                              const std::shared_ptr<Events_Message>& theMessage)
 {
-  // Create circle feature.
-  std::shared_ptr<GeomAPI_Circ2d> aCircle = shapeByCenterAndPassed();
-  FeaturePtr aCircleFeature = createCircleFeature(aCircle);
+  std::string aFilledAttributeName;
+  std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aReentrantMessage =
+        std::dynamic_pointer_cast<SketchPlugin_MacroArcReentrantMessage>(theMessage);
+  if (aReentrantMessage.get()) {
+    FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+    std::string aCircleType = aReentrantMessage->typeOfCreation();
+
+    string(CIRCLE_TYPE())->setValue(aCircleType);
+
+    aFilledAttributeName = CIRCLE_TYPE();
+    ObjectPtr anObject = aReentrantMessage->selectedObject();
+    AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
+    std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
+
+    if (aClickedPoint.get() && (anObject.get() || anAttribute.get())) {
+      std::string aReferenceAttributeName;
+      if (aCircleType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS()) {
+        aFilledAttributeName = CENTER_POINT_ID();
+        aReferenceAttributeName = CENTER_POINT_REF_ID();
+      }
+      else {
+        aFilledAttributeName = FIRST_POINT_ID();
+        aReferenceAttributeName = FIRST_POINT_REF_ID();
+      }
+      // fill 2d point attribute
+      AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                        attribute(aFilledAttributeName));
+      aPointAttr->setValue(aClickedPoint);
+      // fill reference attribute
+      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                                        attribute(aReferenceAttributeName));
+      if (aRefAttr.get()) {
+        if (anAttribute.get())
+          aRefAttr->setAttr(anAttribute);
+        else if (anObject.get()) {
+          // if presentation of previous reentrant macro arc is used, the object is invalid,
+          // we should use result of previous feature of the message(Arc)
+          if (!anObject->data()->isValid()) {
+            FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+            anObject = aCreatedFeature->lastResult();
+          }
+          aRefAttr->setObject(anObject);
+        }
+      }
+    }
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+  }
+  return aFilledAttributeName;
+}
 
+void SketchPlugin_MacroCircle::constraintsForCircleByCenterAndPassed(FeaturePtr theCircleFeature)
+{
   // Create constraints.
-  SketchPlugin_Tools::createConstraint(this,
-                                       CENTER_POINT_REF_ID(),
-                                       aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
-                                       ObjectPtr(),
-                                       false);
-  SketchPlugin_Tools::createConstraint(this,
-                                       PASSED_POINT_REF_ID(),
-                                       AttributePtr(),
-                                       aCircleFeature->lastResult(),
-                                       true);
+  SketchPlugin_Tools::createConstraint(
+      this, CENTER_POINT_REF_ID(),
+      theCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
+      ObjectPtr(), false);
+  SketchPlugin_Tools::createConstraint(
+      this, PASSED_POINT_REF_ID(), AttributePtr(),
+      theCircleFeature->lastResult(), true);
 }
 
-void SketchPlugin_MacroCircle::createCircleByThreePoints()
+void SketchPlugin_MacroCircle::constraintsForCircleByThreePoints(FeaturePtr theCircleFeature)
 {
   std::string aPointRef[3] = { FIRST_POINT_REF_ID(),
                                SECOND_POINT_REF_ID(),
                                THIRD_POINT_REF_ID() };
 
-  // Create circle feature.
-  std::shared_ptr<GeomAPI_Circ2d> aCircle = shapeByThreePoints();
-  FeaturePtr aCircleFeature = createCircleFeature(aCircle);
-  ResultPtr aCircleResult = aCircleFeature->lastResult();
-
   // Create constraints.
+  ResultPtr aCircleResult = theCircleFeature->lastResult();
   for (int i = 0; i < 3; ++i)
     SketchPlugin_Tools::createConstraint(this, aPointRef[i], AttributePtr(), aCircleResult, true);
 }
 
-FeaturePtr SketchPlugin_MacroCircle::createCircleFeature(
-    const std::shared_ptr<GeomAPI_Circ2d>& theCircle)
+FeaturePtr SketchPlugin_MacroCircle::createCircleFeature()
 {
   FeaturePtr aCircleFeature = sketch()->addFeature(SketchPlugin_Circle::ID());
-  std::shared_ptr<GeomAPI_Pnt2d> aCenter = theCircle->center();
   std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(aCenter->x(),
-                                                                             aCenter->y());
-  aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(theCircle->radius());
+      aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(myCenter->x(),
+                                                                             myCenter->y());
+  aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(myRadius);
   aCircleFeature->boolean(SketchPlugin_Circle::AUXILIARY_ID())
                 ->setValue(boolean(AUXILIARY_ID())->value());
   aCircleFeature->execute();
   return aCircleFeature;
 }
 
-std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByCenterAndPassed()
+void SketchPlugin_MacroCircle::fillByCenterAndPassed()
 {
   AttributePtr aCenterAttr = attribute(CENTER_POINT_ID());
   AttributePtr aPassedAttr = attribute(PASSED_POINT_ID());
   if (!aCenterAttr->isInitialized() || !aPassedAttr->isInitialized())
-    return std::shared_ptr<GeomAPI_Circ2d>();
+    return;
 
   AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID());
   // Calculate circle parameters
@@ -152,16 +212,26 @@ std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByCenterAndPassed
       aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
 
   // Build a circle
-  std::shared_ptr<GeomAPI_Circ2d> aCircle;
+  GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
+  aCircBuilder.setCenter(aCenter);
   if (aTangentCurve) {
-    std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
-    aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aTangentCurve, anAxis));
+    aCircBuilder.addTangentCurve(aTangentCurve);
+
+    AttributePoint2DPtr aPassedPntAttr =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPassedAttr);
+    if (aPassedPntAttr)
+      aCircBuilder.setClosestPoint(aPassedPntAttr->pnt());
   } else
-    aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aPassedPoint));
-  return aCircle;
+    aCircBuilder.addPassingPoint(aPassedPoint);
+
+  std::shared_ptr<GeomAPI_Circ2d> aCircle = aCircBuilder.circle();
+  if (aCircle) {
+    myCenter = aCircle->center();
+    myRadius = aCircle->radius();
+  }
 }
 
-std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByThreePoints()
+void SketchPlugin_MacroCircle::fillByThreePoints()
 {
   std::string aPointAttr[3] = { FIRST_POINT_ID(),
                                 SECOND_POINT_ID(),
@@ -169,7 +239,9 @@ std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByThreePoints()
   std::string aPointRef[3] = { FIRST_POINT_REF_ID(),
                                SECOND_POINT_REF_ID(),
                                THIRD_POINT_REF_ID() };
-  std::shared_ptr<GeomAPI_Interface> aPassedEntities[3];
+
+  GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
+
   for (int aPntIndex = 0; aPntIndex < 3; ++aPntIndex) {
     AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]);
     if (!aPassedAttr->isInitialized())
@@ -183,27 +255,34 @@ std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByThreePoints()
         aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
 
     if (aPassedPoint)
-      aPassedEntities[aPntIndex] = aPassedPoint;
-    else
-      aPassedEntities[aPntIndex] = aTangentCurve;
+      aCircBuilder.addPassingPoint(aPassedPoint);
+    else {
+      aCircBuilder.addTangentCurve(aTangentCurve);
+      AttributePoint2DPtr aPassedPoint =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPassedAttr);
+      if (aPassedPoint)
+        aCircBuilder.setClosestPoint(aPassedPoint->pnt());
+    }
   }
 
-  std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
-  std::shared_ptr<GeomAPI_Circ2d> aCircle = std::shared_ptr<GeomAPI_Circ2d>(
-      new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis));
-  if (!aCircle->implPtr<char>())
-    return std::shared_ptr<GeomAPI_Circ2d>();
-  return aCircle;
+  std::shared_ptr<GeomAPI_Circ2d> aCircle = aCircBuilder.circle();
+  if (aCircle) {
+    myCenter = aCircle->center();
+    myRadius = aCircle->radius();
+  }
 }
 
-std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByTwoPassedPoints()
+void SketchPlugin_MacroCircle::fillByTwoPassedPoints()
 {
   std::string aPointAttr[2] = { FIRST_POINT_ID(),
                                 SECOND_POINT_ID() };
   std::string aPointRef[2] = { FIRST_POINT_REF_ID(),
                                SECOND_POINT_REF_ID() };
+
+  GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
+
   std::shared_ptr<GeomAPI_Pnt2d> aPassedPoints[2]; // there is possible only two passed points
-  std::shared_ptr<GeomAPI_Interface> aPassedEntities[3];
+  bool hasTangentCurve = false;
   int aPntIndex = 0;
   for (; aPntIndex < 2; ++aPntIndex) {
     AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]);
@@ -218,67 +297,52 @@ std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByTwoPassedPoints
         aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
 
     if (aPassedPoint) {
-      aPassedEntities[aPntIndex] = aPassedPoint;
+      aCircBuilder.addPassingPoint(aPassedPoint);
       aPassedPoints[aPntIndex] = aPassedPoint;
     } else {
-      aPassedEntities[aPntIndex] = aTangentCurve;
+      hasTangentCurve = true;
+      aCircBuilder.addTangentCurve(aTangentCurve);
       // if the circle is tangent to any curve,
       // the third point will be initialized by the tangent point
-      aPassedEntities[2] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPassedAttr)->pnt();
+      aCircBuilder.addPassingPoint(
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPassedAttr)->pnt());
     }
   }
   if (aPntIndex <= 1)
-    return std::shared_ptr<GeomAPI_Circ2d>();
+    return;
 
   std::shared_ptr<GeomAPI_Circ2d> aCircle;
-  if (aPassedEntities[2]) {
-    std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
-    aCircle = std::shared_ptr<GeomAPI_Circ2d>(
-        new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis));
-  } else {
+
+  if (hasTangentCurve)
+    aCircle = aCircBuilder.circle();
+  else {
     // the circle is defined by two points, calculate its parameters manually
     std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(
         (aPassedPoints[0]->x() + aPassedPoints[1]->x()) * 0.5,
         (aPassedPoints[0]->y() + aPassedPoints[1]->y()) * 0.5));
     aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aPassedPoints[0]));
   }
-  if (!aCircle->implPtr<char>())
-    return std::shared_ptr<GeomAPI_Circ2d>();
-  return aCircle;
+
+  if (aCircle) {
+    myCenter = aCircle->center();
+    myRadius = aCircle->radius();
+  }
 }
 
 AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious)
 {
   SketchPlugin_Sketch* aSketch = sketch();
-  if(!aSketch) {
+  if(!aSketch || !myCenter || myRadius == 0) {
     return AISObjectPtr();
   }
 
-  // Create circle on the sketch plane
-  std::shared_ptr<GeomAPI_Circ2d> aCircleOnSketch;
-  std::string aType = string(CIRCLE_TYPE())->value();
-  if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS())
-    aCircleOnSketch = shapeByCenterAndPassed();
-  else if (aType == CIRCLE_TYPE_BY_THREE_POINTS()) {
-    if (attribute(THIRD_POINT_ID())->isInitialized())
-      aCircleOnSketch = shapeByThreePoints();
-    else
-      aCircleOnSketch = shapeByTwoPassedPoints();
-  }
-
-  if (!aCircleOnSketch)
-    return AISObjectPtr();
-
-  std::shared_ptr<GeomAPI_Pnt2d> aCenter2D = aCircleOnSketch->center();
-  double aRadius = aCircleOnSketch->radius();
-
   // Compute a circle in 3D view.
-  std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenter2D->x(), aCenter2D->y()));
+  std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
   std::shared_ptr<GeomDataAPI_Dir> aNDir =
       std::dynamic_pointer_cast<GeomDataAPI_Dir>(
           aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
   std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
-  GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
+  GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, myRadius);
   GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
   if(!aCircleShape.get() || !aCenterPointShape.get()) {
     return AISObjectPtr();
@@ -311,20 +375,12 @@ void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) {
     SketchPlugin_Tools::resetAttribute(this, SECOND_POINT_REF_ID());
     SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_ID());
     SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_REF_ID());
-  } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID()) {
-    std::shared_ptr<GeomDataAPI_Point2D> aCenterPointAttr =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()));
-    if(!aCenterPointAttr->isInitialized()) {
-      return;
-    }
-    std::shared_ptr<GeomDataAPI_Point2D> aPassedPointAttr =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(PASSED_POINT_ID()));
-    if(!aPassedPointAttr->isInitialized()) {
-      return;
-    }
-
-    aRadius = aCenterPointAttr->pnt()->distance(aPassedPointAttr->pnt());
-  } else if(theID == FIRST_POINT_ID() || theID == SECOND_POINT_ID() || theID == THIRD_POINT_ID()) {
+  } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID() ||
+            theID == CENTER_POINT_REF_ID() || theID == PASSED_POINT_REF_ID())
+    fillByCenterAndPassed();
+  else if(theID == FIRST_POINT_ID() || theID == FIRST_POINT_REF_ID() ||
+          theID == SECOND_POINT_ID() || theID == SECOND_POINT_REF_ID() ||
+          theID == THIRD_POINT_ID() || theID == THIRD_POINT_REF_ID()) {
     std::shared_ptr<GeomAPI_Pnt2d> aPoints[3];
     int aNbInitialized = 0;
     for(int i = 1; i <= 3; ++i) {
@@ -334,19 +390,16 @@ void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) {
         aPoints[aNbInitialized++] = aCurPnt->pnt();
     }
 
-    std::shared_ptr<GeomAPI_Circ2d> aCircle;
     if(aNbInitialized == 1)
       return;
     else if(aNbInitialized == 2)
-      aCircle = shapeByTwoPassedPoints();
+      fillByTwoPassedPoints();
     else
-      aCircle = shapeByThreePoints();
-    if (aCircle)
-      aRadius = aCircle->radius();
+      fillByThreePoints();
   }
 
   AttributeDoublePtr aRadiusAttr = real(CIRCLE_RADIUS_ID());
   bool aWasBlocked = data()->blockSendAttributeUpdated(true);
-  aRadiusAttr->setValue(aRadius);
+  aRadiusAttr->setValue(myRadius);
   data()->blockSendAttributeUpdated(aWasBlocked, false);
 }
index 27130a4e7bc63f6e7b26a00731c7be3384197209..4e1bfeb22e049df6f5d63c5efa375095abccd5ab 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef SketchPlugin_MacroCircle_H_
 #define SketchPlugin_MacroCircle_H_
 
+#include <ModelAPI_IReentrant.h>
+
 #include "SketchPlugin.h"
 
 #include "SketchPlugin_SketchEntity.h"
@@ -21,7 +23,8 @@ class GeomAPI_Pnt2d;
  * \brief Feature for creation of the new circle in Sketch.
  */
 class SketchPlugin_MacroCircle: public SketchPlugin_SketchEntity,
-                                public GeomAPI_IPresentable
+                                public GeomAPI_IPresentable,
+                                public ModelAPI_IReentrant
 {
  public:
   /// Circle feature kind
@@ -37,6 +40,12 @@ class SketchPlugin_MacroCircle: public SketchPlugin_SketchEntity,
     return ID;
   }
 
+  inline static const std::string& EDIT_CIRCLE_TYPE()
+  {
+    static const std::string ID("edit_circle_type");
+    return ID;
+  }
+
   /// Creation method by center and passed point.
   inline static const std::string& CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS()
   {
@@ -159,19 +168,27 @@ class SketchPlugin_MacroCircle: public SketchPlugin_SketchEntity,
 
   SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const {return false;};
 
+  /// Apply information of the message to current object. It fills reference object,
+  /// tangent type and tangent point refence in case of tangent arc
+  virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
   /// Use plugin manager for features creation
   SketchPlugin_MacroCircle();
 
 private:
-  std::shared_ptr<GeomAPI_Circ2d> shapeByCenterAndPassed();
-  std::shared_ptr<GeomAPI_Circ2d> shapeByThreePoints();
-  /// Creates shape if only two of three points is initialized
-  std::shared_ptr<GeomAPI_Circ2d> shapeByTwoPassedPoints();
+  void fillByCenterAndPassed();
+  void fillByThreePoints();
+  /// set fields if only two of three points is initialized
+  void fillByTwoPassedPoints();
 
-  void createCircleByCenterAndPassed();
-  void createCircleByThreePoints();
+  void constraintsForCircleByCenterAndPassed(FeaturePtr theCircleFeature);
+  void constraintsForCircleByThreePoints(FeaturePtr theCircleFeature);
 
-  FeaturePtr createCircleFeature(const std::shared_ptr<GeomAPI_Circ2d>& theCircle);
+  FeaturePtr createCircleFeature();
+
+private:
+  std::shared_ptr<GeomAPI_Pnt2d> myCenter;
+  double                         myRadius;
 };
 
 #endif
index 05ba4c5013be735bc688e289d5181bf33b650e22..3b12526d65f173073c1bca9a414f0feb96dc4a64 100644 (file)
 #include <iostream>
 #endif
 
+#define SKETCH_ENTITY_COLOR "225,0,0"
+#define SKETCH_EXTERNAL_COLOR "170,0,225"
+#define SKETCH_AUXILIARY_COLOR "0,85,0"
+#define SKETCH_OVERCONSTRAINT_COLOR "0,0,0"
+#define SKETCH_FULLY_CONSTRAINED_COLOR "0,150,0"
+
 //#define SET_PLANES_COLOR_IN_PREFERENCES
 
 // the only created instance of this plugin
@@ -124,6 +130,10 @@ SketchPlugin_Plugin::SketchPlugin_Plugin()
                                    "Sketch overconstraint color",
                                    Config_Prop::Color, SKETCH_OVERCONSTRAINT_COLOR);
 
+  Config_PropManager::registerProp("Visualization", "sketch_fully_constrained_color",
+                                   "Sketch fully constrained color",
+                                   Config_Prop::Color, SKETCH_FULLY_CONSTRAINED_COLOR);
+
   // register sketcher properties
 #ifdef SET_PLANES_COLOR_IN_PREFERENCES
   Config_PropManager::registerProp("Visualization", "yz_plane_color", "YZ plane color",
index 142d0915a4e008fd1cbc43f69452553172f70cce..562b50098909a9268f9516c1310ae1d0ffffaf63 100644 (file)
@@ -28,7 +28,7 @@ class SketchPlugin_Point : public SketchPlugin_SketchEntity
   /// Coordinates of the point
   inline static const std::string& COORD_ID()
   {
-    static const std::string MY_COORD_ID("PointCoordindates");
+    static const std::string MY_COORD_ID("PointCoordinates");
     return MY_COORD_ID;
   }
   /// Returns the kind of a feature
index 04cf7331b55d84b1c7fdb5c4f5be0e828ad3c150..91fddccd708bade99ca94b5ec1bc8b51653dec3c 100755 (executable)
@@ -139,6 +139,11 @@ std::shared_ptr<ModelAPI_Feature> SketchPlugin_Sketch::addFeature(std::string th
   }
    // set as current also after it becomes sub to set correctly enabled for other sketch subs
   document()->setCurrentFeature(aNew, false);
+
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aDeleteEvent = aLoop->eventByName(EVENT_OBJECT_DELETED);
+  aLoop->flush(aDeleteEvent);
+
   return aNew;
 }
 
index cbbfcdf55c162bf8d6141366872980645d1cba6b..1af4d28bbc9541abccb51ad2672cbaded7bc3f6b 100644 (file)
 
 #include <Config_PropManager.h>
 
-#define SKETCH_ENTITY_COLOR "225,0,0"
-#define SKETCH_EXTERNAL_COLOR "170,0,225"
-#define SKETCH_AUXILIARY_COLOR "0,85,0"
-#define SKETCH_OVERCONSTRAINT_COLOR "0,0,0"
-
 /**\class SketchPlugin_SketchEntity
  * \ingroup Plugins
  * \brief Sketch Entity for creation of the new feature in PartSet. 
@@ -171,7 +166,7 @@ class SketchPlugin_SketchEntity : public SketchPlugin_Feature, public GeomAPI_IC
     if (!theResult.get()) {
       double aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
       thePrs->setDeflection(aDeflection);
-  }
+    }
     return isCustomized;
   }
 
index f45bb609f225155ff87ba76509c61fecdd18a20a..986b99b30d941314868403303847a83dfcf26bc0 100644 (file)
@@ -41,6 +41,8 @@
 #include <SketchPlugin_MultiTranslation.h>
 #include <SketchPlugin_Point.h>
 
+#include <ModelAPI_EventReentrantMessage.h>
+
 #include <ModelAPI_Events.h>
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Arc.h>
 
 #include <cmath>
 
-#define DEBUG_TRIM
+//#define DEBUG_TRIM_METHODS
+//#define DEBUG_TRIM
+
 #ifdef DEBUG_TRIM
 #include <iostream>
 #endif
 
+#ifdef DEBUG_TRIM_METHODS
+#include <iostream>
+#endif
+
 static const double PI = 3.141592653589793238463;
 
 static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; }
@@ -139,6 +147,8 @@ std::shared_ptr<GeomAPI_Pnt2d> SketchPlugin_Trim::convertPoint(
                                                    const std::shared_ptr<GeomAPI_Pnt>& thePoint)
 {
   std::shared_ptr<GeomAPI_Pnt2d> aPoint;
+  if (!thePoint.get())
+    return aPoint;
 
   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
                                         data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
@@ -174,8 +184,8 @@ std::shared_ptr<GeomAPI_Pnt2d> SketchPlugin_Trim::convertPoint(
 
 void SketchPlugin_Trim::execute()
 {
-#ifdef DEBUG_TRIM
-  std::cout << "SketchPlugin_Trim::execute" << std::endl;
+#ifdef DEBUG_TRIM_METHODS
+  std::cout << "SketchPlugin_Trim::execute: " << data()->name() << std::endl;
 #endif
 
   SketchPlugin_Sketch* aSketch = sketch();
@@ -194,6 +204,21 @@ void SketchPlugin_Trim::execute()
     return;
   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
 
+  /// Remove reference of this feature to feature used in preview, it is not necessary anymore
+  /// as trim will be removed after execute
+  AttributeReferencePtr aPreviewObjectAttr =
+                     std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+                     data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
+
+  ObjectPtr aPreviewObject = aPreviewObjectAttr->value();
+  AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                           data()->attribute(PREVIEW_POINT()));
+  std::shared_ptr<GeomAPI_Pnt2d> aPreviewPnt2d = aPoint->pnt();
+  // nullify pointer of preview attribute
+  aPreviewObjectAttr->setValue(ResultPtr());
+
+  bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject;
+
   /// points of trim
   std::shared_ptr<GeomAPI_Pnt> aStartShapePoint, aLastShapePoint;
 #ifdef DEBUG_TRIM
@@ -202,7 +227,6 @@ void SketchPlugin_Trim::execute()
   findShapePoints(SELECTED_OBJECT(), SELECTED_POINT(), aStartShapePoint, aLastShapePoint);
 
   std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint2d = convertPoint(aStartShapePoint);
-
   std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint2d = convertPoint(aLastShapePoint);
 
   std::set<FeaturePtr> aFeaturesToDelete;
@@ -211,17 +235,58 @@ void SketchPlugin_Trim::execute()
   std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
   std::list<AttributePtr> aRefsToFeature;
   getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature);
-
+#ifdef DEBUG_TRIM
+  std::cout << "---- getRefAttributes ----" << std::endl;
+  std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
+    aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end();
+  std::cout << std::endl << "References to attributes of base feature [" <<
+    aBaseRefAttributes.size() << "]" << std::endl;
+  for (; aRefIt != aRefLast; aRefIt++) {
+    AttributePtr aBaseAttr = aRefIt->first;
+    std::list<AttributePtr> aRefAttributes = aRefIt->second;
+    std::string aRefsInfo;
+    std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
+                                            aRefAttrLast = aRefAttributes.end();
+    for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
+      if (!aRefsInfo.empty())
+        aRefsInfo.append(",");
+      AttributePtr aRAttr = *aRefAttrIt;
+      aRefsInfo.append(aRAttr->id());
+      FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
+      aRefsInfo.append("(" + aRFeature->name() + ") ");
+    }
+    std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
+    std::cout << aPointAttr->id().c_str() <<
+      ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
+  }
+  std::cout << std::endl;
+  std::cout << std::endl << "References to base feature [" <<
+    aRefsToFeature.size() << "]" << std::endl;
+  std::list<AttributePtr>::const_iterator aRefAttrIt = aRefsToFeature.begin(),
+                                          aRefAttrLast = aRefsToFeature.end();
+  std::string aRefsInfo;
+  for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
+    if (!aRefsInfo.empty())
+      aRefsInfo.append(",");
+    AttributePtr aRAttr = *aRefAttrIt;
+    aRefsInfo.append(aRAttr->id());
+    FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
+    aRefsInfo.append("(" + aRFeature->name() + ") ");
+  }
+  std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl;
+  std::cout << "---- getRefAttributes:end ----" << std::endl;
+#endif
   // coincidence to result points
   // find coincidences to the base object, it should be used when attribute is found
   // in myObjectToPoints
-  std::map<AttributePtr, FeaturePtr> aCoincidencesToBaseFeature;
-  getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature);
+  //std::map<AttributePtr, FeaturePtr> aCoincidencesToBaseFeature;
+  //getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature);
 
   std::set<AttributePoint2DPtr> aFurtherCoincidences;
   std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
   const std::string& aKind = aBaseFeature->getKind();
-  FeaturePtr aReplacingFeature;
+  FeaturePtr aReplacingFeature, aNewFeature;
   if (aKind == SketchPlugin_Circle::ID()) {
     aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d,
                aFurtherCoincidences, aModifiedAttributes);
@@ -231,20 +296,14 @@ void SketchPlugin_Trim::execute()
     // otherwise Trim feature will be removed with the circle before
     // this operation is finished
     aBaseObjectAttr->setObject(ResultPtr());
-
-    AttributeReferencePtr aPreviewObjectAttr =
-                     std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
-                     data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
-    aPreviewObjectAttr->setObject(ResultPtr());
-
   }
   else if (aKind == SketchPlugin_Line::ID()) {
-    trimLine(aStartShapePoint2d, aLastShapePoint2d,
-             aFurtherCoincidences, aModifiedAttributes);
+    aNewFeature = trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
+                           aFurtherCoincidences, aModifiedAttributes);
   }
   else if (aKind == SketchPlugin_Arc::ID()) {
-    trimArc(aStartShapePoint2d, aLastShapePoint2d,
-            aFurtherCoincidences, aModifiedAttributes);
+    aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
+                          aFurtherCoincidences, aModifiedAttributes);
   }
 
   // constraints to end points of trim feature
@@ -260,7 +319,7 @@ void SketchPlugin_Trim::execute()
     std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
 
 #ifdef DEBUG_TRIM
-    std::cout << "<compare Points> => "
+    std::cout << "<compare Points> => " << std::endl
             << "aPoint2d: [" << aPoint2d->x() << ", " << aPoint2d->y() << "]" << std::endl;
     if (aStartShapePoint2d.get())
       std::cout << "Start Point: [" << aStartShapePoint2d->x() << ", " << aStartShapePoint2d->y()
@@ -288,29 +347,6 @@ void SketchPlugin_Trim::execute()
         break;
       }
     }
-    /*const std::list<AttributePoint2DPtr >& anAttributes = anInfo.first;
-    for (std::list<AttributePoint2DPtr>::const_iterator anAttrIt = anAttributes.begin();
-          anAttrIt != anAttributes.end(); anAttrIt++) {
-      AttributePtr anAttribute = *anAttrIt;
-      if (aCoincidencesToBaseFeature.find(anAttribute) != aCoincidencesToBaseFeature.end())
-      {
-        FeaturePtr anAttrFeature = aCoincidencesToBaseFeature.at(anAttribute);
-        AttributePtr anOtherAttribute;
-        if (std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
-           (anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_A()))->attr() == anAttribute)
-          anOtherAttribute = anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_B());
-        else if (std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
-          (anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_B()))->attr() == anAttribute)
-          anOtherAttribute = anAttrFeature->attribute(SketchPlugin_Constraint::ENTITY_A());
-        else
-          continue;
-        AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
-                                       (anOtherAttribute);
-        if (aRefAttr.get())
-          aRefAttr->setAttr(aPointAttribute);
-      }
-    }
-    */
     const std::list<ObjectPtr>& anObjects = anInfo.second;
     for (std::list<ObjectPtr>::const_iterator anObjectIt = anObjects.begin();
       anObjectIt != anObjects.end(); anObjectIt++) {
@@ -330,11 +366,16 @@ void SketchPlugin_Trim::execute()
                                           aLast = aRefsToFeature.end();
       anIt != aLast; anIt++) {
     AttributePtr anAttribute = *anIt;
+
+    //if (replaceCoincidenceAttribute(anAttribute, aModifiedAttributes))
+    //  continue;
+
     if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences))
       continue;
 
     if (aReplacingResult.get()) {
-      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
+      AttributeRefAttrPtr aRefAttr =
+          std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
       if (aRefAttr.get())
         aRefAttr->setObject(aReplacingResult);
       else {
@@ -346,22 +387,24 @@ void SketchPlugin_Trim::execute()
     }
   }
 
+  updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete);
+
   // Wait all constraints being created, then send update events
   static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
   bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
   if (isUpdateFlushed)
     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
 
-  updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete);
-
   // delete constraints
 #ifdef DEBUG_TRIM
-  std::cout << "remove features and references:" << std::endl;
-  std::set<FeaturePtr>::const_iterator aDIt = aFeaturesToDelete.begin(),
-                                       aDLast = aFeaturesToDelete.end();
-  for (; aDIt != aDLast; aDIt++) {
-    //std::cout << getFeatureInfo(*aDIt, false) << std::endl;
-    //std::cout << std::endl;
+  if (aFeaturesToDelete.size() > 0) {
+    std::cout << "after SPlit: removeFeaturesAndReferences: " << std::endl;
+    std::string aValue;
+    for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
+         anIt != aFeaturesToDelete.end(); anIt++) {
+      FeaturePtr aFeature = *anIt;
+      std::cout << aFeature->data()->name() << std::endl;
+    }
   }
 #endif
   ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
@@ -372,11 +415,115 @@ void SketchPlugin_Trim::execute()
     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
   }
 
+  if (anIsEqualPreviewAndSelected) {
+    // equal preview and selected objects
+    // nothing to do if the preview and selected objects are different
+    if (aReplacingResult.get()) { // base object was removed
+      aPreviewObject = aReplacingResult;
+      //aMessage->setSelectedObject(aReplacingResult);
+
+      GeomShapePtr aSelectedShape = aReplacingResult->shape();
+      std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
+                                                                aPreviewPnt2d->y());
+      std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
+      if (ModelGeomAlgo_Point2D::isPointOnEdge(aSelectedShape, aPreviewPnt, aProjectedPoint)) {
+        bool aValue = true;
+      }
+      //aBaseShape = aShape;
+
+#ifdef DEBUG_TRIM_METHODS
+      if (!aSelectedShape.get())
+        std::cout << "Set empty selected object" << std::endl;
+      else
+        std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
+#endif
+      bool aValue = true;
+    }
+    else {
+      aPreviewObject = ObjectPtr();
+
+      aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
+      aBaseObject = getFeatureResult(aBaseFeature);
+      std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
+                                                                aPreviewPnt2d->y());
+      ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
+      if (aBaseResult) {
+        GeomShapePtr aShape = aBaseResult->shape();
+        std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
+        if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
+          aPreviewObject = aBaseResult;
+      }
+      if (!aPreviewObject.get() && aNewFeature.get()) {
+        ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature);
+        if (aNewFeatureResult.get()) {
+          GeomShapePtr aShape = aNewFeatureResult->shape();
+          std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
+          if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
+            aPreviewObject = aNewFeatureResult;
+        }
+      }
+    }
+  }
+  if (aPreviewObject.get()) {
+    std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
+      <ModelAPI_EventReentrantMessage>(new ModelAPI_EventReentrantMessage(
+                                           ModelAPI_EventReentrantMessage::eventId(), 0));
+    aMessage->setSelectedObject(aPreviewObject);
+    Events_Loop::loop()->send(aMessage);
+  }
 #ifdef DEBUG_TRIM
   std::cout << "SketchPlugin_Trim::done" << std::endl;
 #endif
 }
 
+std::string SketchPlugin_Trim::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+#ifdef DEBUG_TRIM_METHODS
+  std::cout << "SketchPlugin_Trim::processEvent:" << data()->name() << std::endl;
+#endif
+
+  std::string aFilledAttributeName;
+
+  std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage =
+        std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
+  if (aMessage.get()) {
+    ObjectPtr anObject = aMessage->selectedObject();
+    std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
+
+    if (anObject.get() && aPoint.get()) {
+      std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
+                            std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+                            data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
+      std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
+                            std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+                            data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
+      aRefSelectedAttr->setValue(anObject);
+      aRefPreviewAttr->setValue(anObject);
+
+      std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
+                            std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                            data()->attribute(SketchPlugin_Trim::SELECTED_POINT()));
+      std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
+                            std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                            data()->attribute(SketchPlugin_Trim::PREVIEW_POINT()));
+      aPointSelectedAttr->setValue(aPoint);
+      aPointPreviewAttr->setValue(aPoint);
+
+      Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+
+      GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
+#ifdef DEBUG_TRIM_METHODS
+      if (!aSelectedShape.get())
+        std::cout << "Set empty selected object" << std::endl;
+      else
+        std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
+#endif
+      aFilledAttributeName = SketchPlugin_Trim::SELECTED_OBJECT();
+    }
+  }
+  return aFilledAttributeName;
+}
+
 bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute,
                                 const std::set<AttributePoint2DPtr>& theFurtherCoincidences)
 {
@@ -398,31 +545,43 @@ bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribu
     if (aPoint2d->isEqual(aRefPnt2d)) {
       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
                                                                            theAttribute);
-      /*if (theAttribute->id() == SketchPlugin_ConstraintCoincidence::ENTITY_A())
-        aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-                  aFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B()));
-      else if (theAttribute->id() == SketchPlugin_ConstraintCoincidence::ENTITY_B())
-        aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-                  aFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A()));*/
       if (aRefAttr.get()) {
         aRefAttr->setAttr(aPointAttribute);
         aFoundPoint = true;
       }
     }
   }
-  /*AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
-  if (!aRefAttr.get())
-    return false;
+  return aFoundPoint;
+}
 
-  if (aRefAttr.get())
-    aRefAttr->setObject(aReplacingResult);//continue;
-  else {
-  //AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
-    AttributeReferencePtr aReferenceAttr =
-                          std::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttribute);
-  }*/
+bool SketchPlugin_Trim::replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute,
+                   const std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
+{
+  FeaturePtr aCoincidenceFeature = ModelAPI_Feature::feature(theCoincidenceAttribute->owner());
+  if (aCoincidenceFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
+    return false;
 
-  return aFoundPoint;
+  AttributeRefAttrPtr aCAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                         aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  AttributeRefAttrPtr aCAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                         aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  AttributePtr aCAttrRefA = aCAttrA->attr();
+  AttributePtr aCAttrRefB = aCAttrB->attr();
+
+  bool isProcessed = false;
+  for (std::set<std::pair<AttributePtr, AttributePtr>>::const_iterator
+       anIt = theModifiedAttributes.begin(); anIt != theModifiedAttributes.end(); anIt++) {
+    AttributePtr anAttributeBefore = anIt->first;
+    if (anAttributeBefore == aCAttrRefA) {
+      aCAttrA->setAttr(anIt->second);
+      isProcessed = true;
+    }
+    if (anAttributeBefore == aCAttrRefB) {
+      aCAttrB->setAttr(anIt->second);
+      isProcessed = true;
+    }
+  }
+  return isProcessed;
 }
 
 bool SketchPlugin_Trim::isMacro() const
@@ -432,6 +591,10 @@ bool SketchPlugin_Trim::isMacro() const
 
 AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious)
 {
+#ifdef DEBUG_TRIM_METHODS
+  std::cout << "SketchPlugin_Trim::getAISObject: " << data()->name() << std::endl;
+#endif
+
   AISObjectPtr anAIS = thePrevious;
 
   std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
@@ -599,7 +762,7 @@ void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature,
   }
 }
 
-void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject,
+/*void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject,
                    std::map<AttributePtr, FeaturePtr>& theCoincidencesToBaseFeature)
 {
   const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
@@ -635,7 +798,7 @@ void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject,
       theCoincidencesToBaseFeature[anAttribute] = aRefFeature;
     }
   }
-}
+}*/
 
 void SketchPlugin_Trim::updateRefAttConstraints(
                     const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
@@ -659,27 +822,61 @@ void SketchPlugin_Trim::updateRefAttConstraints(
                                             aRLast = aRefAttributes.end();
 
     AttributePtr aNewAttribute = anIt->second;
-    for (; aRefIt != aRLast; aRefIt++) {
-      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
-      if (aRefAttr.get()) {
-        if (aNewAttribute.get())
-          aRefAttr->setAttr(aNewAttribute);
-        else
-          theFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner()));
-#ifdef DEBUG_TRIM
-        //FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
-        //std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
-#endif
+    if (aNewAttribute.get()) {
+      for (; aRefIt != aRLast; aRefIt++) {
+        AttributeRefAttrPtr aRefAttr =
+                        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
+        if (aRefAttr.get()) {
+            aRefAttr->setAttr(aNewAttribute);
+        }
       }
     }
   }
 }
 
-void SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
-                                 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
-                                 std::set<AttributePoint2DPtr>& thePoints,
+void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttribute,
+                  std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes)
+{
+  /// not found in references
+  if (theBaseRefAttributes.find(theAttribute) == theBaseRefAttributes.end())
+    return;
+
+  std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(theAttribute);
+  std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
+                                          aRLast = aRefAttributes.end();
+
+  std::set<FeaturePtr> aFeaturesToDelete;
+  for (; aRefIt != aRLast; aRefIt++) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
+    if (aRefAttr.get()) {
+      aFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner()));
+    }
+  }
+
+#ifdef DEBUG_TRIM
+  // delete constraints
+  if (aFeaturesToDelete.size() > 0) {
+    std::cout << "removeReferencesToAttribute: " << std::endl;
+    std::string aValue;
+    for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
+         anIt != aFeaturesToDelete.end(); anIt++) {
+      FeaturePtr aFeature = *anIt;
+      std::cout << aFeature->data()->name() << std::endl;
+    }
+  }
+#endif
+  ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+}
+
+FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+                  const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+                  std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+                  std::set<AttributePoint2DPtr>& thePoints,
                   std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
 {
+  FeaturePtr anNewFeature;
+
   // Check the base objects are initialized.
   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
                                         data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
@@ -723,9 +920,14 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartS
     else
       aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
 
+    // it is important to delete references before the feature modification because
+    // if deletion will be after the feature modification, solver returns the feature back
+    removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
+                                theBaseRefAttributes);
+
     fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
-    theModifiedAttributes.insert(
-      std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr()));
+    //theModifiedAttributes.insert(
+    //  std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr()));
 
     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
                                (aBaseFeature->attribute(aModifiedAttribute)));
@@ -734,7 +936,7 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartS
     // result is two lines: start line point - start shape point,
     // last shape point - last line point
     // create second line
-    FeaturePtr anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint);
+    anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint);
     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
                                (anNewFeature->attribute(SketchPlugin_Line::START_ID())));
 
@@ -755,13 +957,16 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartS
                                getFeatureResult(anNewFeature));
 
   }
+  return anNewFeature;
 }
 
-void SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
-                                const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
-                                std::set<AttributePoint2DPtr>& thePoints,
+FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+                 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+                 std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+                 std::set<AttributePoint2DPtr>& thePoints,
                  std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
 {
+  FeaturePtr anNewFeature;
   // Check the base objects are initialized.
   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
                                         data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
@@ -782,14 +987,14 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartSh
 #ifdef DEBUG_TRIM
   std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
   if (aStartShapePoint.get())
-    std::cout << "Start point: [" << aStartShapePoint->x() << ", " <<
+    std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
                                        aStartShapePoint->y() << "]" << std::endl;
-  std::cout << "1st point:   [" << aStartArcPoint->x() << ", " <<
+  std::cout << "Start arc attribute point:   [" << aStartArcPoint->x() << ", " <<
                                    aStartArcPoint->y() << "]" << std::endl;
   if (aLastShapePoint.get())
-    std::cout << "2st point:   [" << aLastShapePoint->x() << ", " <<
+    std::cout << "Last shape point:   [" << aLastShapePoint->x() << ", " <<
                                      aLastShapePoint->y() << "]" << std::endl;
-  std::cout << "End point:   [" << aLastArcPoint->x() << ", " <<
+  std::cout << "Last arc attribute point:   [" << aLastArcPoint->x() << ", " <<
                                    aLastArcPoint->y() << "]" << std::endl;
 #endif
 
@@ -805,9 +1010,10 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartSh
     else
       aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
 
+    removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
+                                theBaseRefAttributes);
+
     fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
-    theModifiedAttributes.insert(
-      std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr()));
 
     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
                                (aBaseFeature->attribute(aModifiedAttribute)));
@@ -815,14 +1021,14 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartSh
   else {
     // result is two arcs: start arc point - start shape point, last shape point - last arc point
     // create second arc
-    FeaturePtr anArcFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint);
+    anNewFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint);
     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
-                               (anArcFeature->attribute(SketchPlugin_Arc::START_ID())));
+                               (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
 
     std::string aModifiedAttribute = SketchPlugin_Arc::END_ID();
     theModifiedAttributes.insert(
       std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
-                                   anArcFeature->attribute(SketchPlugin_Arc::END_ID())));
+                                   anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
 
     // modify base arc
     fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
@@ -831,15 +1037,22 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartSh
                                (aBaseFeature->attribute(aModifiedAttribute)));
 
     // equal Radius constraint for arcs
-    anArcFeature->execute(); // we need the created arc result to set equal constraint
+    anNewFeature->execute(); // we need the created arc result to set equal constraint
     createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
                                getFeatureResult(aBaseFeature),
-                               getFeatureResult(anArcFeature));
+                               getFeatureResult(anNewFeature));
     // coincident centers constraint
     createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
                      aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
-                     anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
+                     anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
+
+#ifdef DEBUG_TRIM
+    std::cout << "Created arc on points:" << std::endl;
+    std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
+                                           aStartShapePoint->y() << "]" << std::endl;
+#endif
   }
+  return anNewFeature;
 }
 
 FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
@@ -858,20 +1071,20 @@ FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& t
   //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
 
   /// trim feature
-  FeaturePtr anArcFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint);
+  FeaturePtr anNewFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint);
   // arc created by trim of circle is always correct, that means that it is not inversed
-  anArcFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false);
+  anNewFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false);
 
   theModifiedAttributes.insert(
     std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
-                   anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
+                   anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
 
   thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
-                             (anArcFeature->attribute(SketchPlugin_Arc::START_ID())));
+                             (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
   thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
-                             (anArcFeature->attribute(SketchPlugin_Arc::END_ID())));
+                             (anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
 
-  return anArcFeature;
+  return anNewFeature;
 }
 
 void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr,
@@ -940,8 +1153,10 @@ void SketchPlugin_Trim::fillPointAttribute(const AttributePtr& theModifiedAttrib
     aModifiedAttribute->setValue(thePoint);
 
 #ifdef DEBUG_TRIM
-    std::cout << "<fillPointAttribute> => Pnt2d - [" << thePoint->x() << ", "
-              << thePoint->y() << "]" << std::endl;
+    FeaturePtr aFeature = ModelAPI_Feature::feature(theModifiedAttribute->owner());
+    std::cout << "<fillPointAttribute[" << aFeature->data()->name() << ": " <<
+      theModifiedAttribute->id() <<
+      "]> => Pnt2d - [" << thePoint->x() << ", " << thePoint->y() << "]" << std::endl;
 #endif
   }
 }
@@ -989,6 +1204,10 @@ FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature
                                         const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
                                         const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
 {
+#ifdef DEBUG_TRIM
+  std::cout << "---- createLineFeature ---" << std::endl;
+#endif
+
   FeaturePtr aFeature;
   SketchPlugin_Sketch* aSketch = sketch();
   if (!aSketch || !theBaseFeature.get())
@@ -1004,6 +1223,10 @@ FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature
 
   aFeature->execute(); // to obtain result
 
+#ifdef DEBUG_TRIM
+  std::cout << "---- createLineFeature:end ---" << std::endl;
+#endif
+
   return aFeature;
 }
 
@@ -1025,6 +1248,10 @@ FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature,
   if (aCenterAttributeId.empty())
     return aFeature;
 
+#ifdef DEBUG_TRIM
+  std::cout << "---- createArcFeature ---" << std::endl;
+#endif
+
   aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
   // update fillet arc: make the arc correct for sure, so, it is not needed to process
   // the "attribute updated"
@@ -1047,6 +1274,10 @@ FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature,
   //aFeature->execute(); // to obtain result
   aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
 
+  #ifdef DEBUG_TRIM
+  std::cout << "---- createArcFeature:end ---" << std::endl;
+  #endif
+
   return aFeature;
 }
 
index 6928c3b9645441b5b3911e68a837f46c7ea1332b..5791ff690c450125bc1588654bb7bd0cade6ada8 100644 (file)
@@ -7,9 +7,11 @@
 #ifndef SketchPlugin_Trim_H_
 #define SketchPlugin_Trim_H_
 
+#include <ModelAPI_IReentrant.h>
+
 #include "SketchPlugin.h"
-#include <SketchPlugin_Sketch.h>
 #include "SketchPlugin_ConstraintBase.h"
+#include <SketchPlugin_Sketch.h>
 
 class GeomDataAPI_Point2D;
 class ModelAPI_Feature;
@@ -22,7 +24,8 @@ typedef std::pair<std::string, std::shared_ptr<GeomDataAPI_Point2D> > IdToPointP
  *  \ingroup Plugins
  *  \brief Feature for creation of a new constraint trimming object. Entities for split:
  */
-class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentable
+class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentable,
+                          public ModelAPI_IReentrant
 {
  public:
   /// Split constraint kind
@@ -89,8 +92,8 @@ class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentab
   /// Moves the feature : Empty
   SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY) {};
 
-  bool setCoincidenceToAttribute(const AttributePtr& theAttribute,
-            const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences);
+  /// Apply information of the message to current object. It fills selected point and object
+  virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
 
   typedef std::map<std::shared_ptr<GeomAPI_Pnt>,
                    std::pair<std::list<std::shared_ptr<GeomDataAPI_Point2D> >,
@@ -102,6 +105,12 @@ class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentab
     std::map<std::shared_ptr<ModelAPI_Object>, PointToRefsMap>& theObjectToPoints);
 
 private:
+  bool setCoincidenceToAttribute(const AttributePtr& theAttribute,
+            const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences);
+
+  bool replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute,
+            const std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+
   GeomShapePtr getSubShape(const std::string& theObjectAttributeId,
                            const std::string& thePointAttributeId);
 
@@ -134,8 +143,8 @@ private:
   /// by the coincident attribute
   /// \param theObject an investigated object
   /// \param theCoincidencesToBaseFeature a container of list of referenced attributes
-  void getCoincidencesToObject(const std::shared_ptr<ModelAPI_Object>& theObject,
-                               std::map<AttributePtr, FeaturePtr>& theCoincidencesToBaseFeature);
+  //void getCoincidencesToObject(const std::shared_ptr<ModelAPI_Object>& theObject,
+  //                             std::map<AttributePtr, FeaturePtr>& theCoincidencesToBaseFeature);
 
   /// Move constraints from attribute of base feature to attribute after modification
   /// \param theBaseRefAttributes container of references to the attributes of base feature
@@ -146,32 +155,34 @@ private:
                const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes,
                std::set<std::shared_ptr<ModelAPI_Feature>>& theFeaturesToDelete);
 
+  /// Remove references constraints from attribute of base feature refer to the given attribute
+  /// \param theAttribute an attribute
+  /// \param theModifiedAttributes modifiable container of attributes
+  void removeReferencesToAttribute(const AttributePtr& theAttribute,
+                  std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes);
+
   /// Make the base object is splitted by the point attributes
-  /// \param theSplitFeature a result split feature
-  /// \param theBeforeFeature a feature between start point and the 1st point of split feature
-  /// \param theAfterFeature a feature between last point of split feature and the end point
+  /// \param theBaseRefAttributes container of references to the attributes of base feature
   /// \param thePoints a list of points where coincidences will be build
   /// \param theModifiedAttributes a container of attribute on base
   /// feature to attribute on new feature
-  void trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+  /// \return new line if it was created
+  FeaturePtr trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
                 const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+                std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
                 std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
                 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
 
   /// Make the base object is splitted by the point attributes
-  /// \param theSplitFeature a result split feature
-  /// \param theBeforeFeature a feature between start point and the 1st point of split feature
-  /// \param theAfterFeature a feature between last point of split feature and the end point
   /// \param thePoints a list of points where coincidences will be build
-  void trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+  /// \return new line if it was created
+  FeaturePtr trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
                const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+               std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
                std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
                std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
 
   /// Make the base object is splitted by the point attributes
-  /// \param theSplitFeature a result split feature
-  /// \param theBeforeFeature a feature between start point and the 1st point of split feature
-  /// \param theAfterFeature a feature between last point of split feature and the end point
   /// \param thePoints a list of points where coincidences will be build
   FeaturePtr trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
                   const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
index 6683c906f8606418ddedbcba9616a6075f1741f6..236a104d1f5f94bf2aba41e777dddea9c5be425d 100755 (executable)
@@ -877,14 +877,17 @@ bool SketchPlugin_TrimValidator::isValid(const AttributePtr& theAttribute,
     AttributePtr aPreviewAttr = aTrimFeature->attribute(SketchPlugin_Trim::PREVIEW_OBJECT());
     aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(aPreviewAttr);
     aBaseObject = aBaseObjectAttr->value();
-
-    //return aValid;
   }
 
   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
   if (!aBaseFeature)
     return aValid;
 
+  std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+                                 std::dynamic_pointer_cast<SketchPlugin_Feature>(aBaseFeature);
+  if (!aSketchFeature.get() || aSketchFeature->isCopy())
+    return aValid;
+
   std::string aKind = aBaseFeature->getKind();
   if (aKind != SketchPlugin_Line::ID() &&
       aKind != SketchPlugin_Arc::ID() &&
@@ -1146,7 +1149,8 @@ static std::shared_ptr<GeomAPI_Pnt2d> toPoint(const FeaturePtr& theMacroCircle,
             aPoint3D = anEdge->line()->project(aPoint3D);
           else if (anEdge->isCircle())
             aPoint3D = anEdge->circle()->project(aPoint3D);
-          aPoint = aSketch->to2D(aPoint3D);
+          if(aPoint3D)
+            aPoint = aSketch->to2D(aPoint3D);
         }
       }
     } else {
@@ -1334,7 +1338,7 @@ bool SketchPlugin_ArcEndPointIntersectionValidator::isValid(
     return true;
   }
 
-  GeomShapePtr anArcShape = anArcFeature->getArcShape();
+  GeomShapePtr anArcShape = anArcFeature->getArcShape(false);
 
   if(!anArcShape.get() || anArcShape->isNull()) {
     return true;
@@ -1350,7 +1354,10 @@ bool SketchPlugin_ArcEndPointIntersectionValidator::isValid(
   if(aResult.get()) {
     GeomShapePtr aShape = aResult->shape();
     if(aShape.get() && !aShape->isNull()) {
-      return GeomAlgoAPI_ShapeTools::isShapesIntersects(anArcShape, aShape);
+      GeomShapePtr anIntersection = anArcShape->intersect(aShape);
+      if(anIntersection.get() && !anIntersection->isNull()) {
+        return true;
+      }
     }
   }
 
@@ -1363,7 +1370,8 @@ bool SketchPlugin_ArcEndPointIntersectionValidator::isValid(
     {
       GeomShapePtr aShape = (*anIt)->shape();
       if(aShape.get() && !aShape->isNull()) {
-        if(GeomAlgoAPI_ShapeTools::isShapesIntersects(anArcShape, aShape)) {
+        GeomShapePtr anIntersection = anArcShape->intersect(aShape);
+        if(anIntersection.get() && !anIntersection->isNull()) {
           return true;
         }
       }
index 994eba6d54054f0e63cb76dbd7b58813d16ada5a..2fcae36b395e81ec9b6ec45c48b8d0c4bad51b55 100755 (executable)
@@ -82,7 +82,7 @@
   <context>
     <name>SketchMacroCircle:Model_FeatureValidator</name>
     <message>
-      <source>Attribute "CircleCenter" is not initialized.</source>
+      <source>Attribute "circle_center" is not initialized.</source>
       <translation>A center point is not selected</translation>
     </message>
   </context>
   <context>
     <name>SketchMacroCircle:CircleCenter</name>
     <message>
-      <source>Attribute "CircleCenter" is locked by modification value in the viewer.</source>
+      <source>Attribute "circle_center" is locked by modification value in the viewer.</source>
       <translation>Select a center point</translation>
     </message>
   </context>
   <context>
     <name>SketchMacroCircle:CircleRadius</name>
     <message>
-      <source>Attribute "CircleRadius" is locked by modification value in the viewer.</source>
+      <source>Attribute "circle_radius" is locked by modification value in the viewer.</source>
       <translation>Select a radius distance</translation>
     </message>
   </context>
   <context>
     <name>SketchMacroCircle:Model_FeatureValidator</name>
     <message>
-      <source>Attribute "CircleRadius" is not initialized.</source>
+      <source>Attribute "circle_radius" is not initialized.</source>
       <translation>Set the circle radius</translation>
     </message>
   </context>
   <context>
     <name>SketchPoint:Model_FeatureValidator</name>
     <message>
-      <source>Attribute "PointCoordindates" is not initialized.</source>
+      <source>Attribute "PointCoordinates" is not initialized.</source>
       <translation>Point is not defined</translation>
     </message>
   </context>
   <context>
-    <name>SketchPoint:PointCoordindates</name>
+    <name>SketchPoint:PointCoordinates</name>
     <message>
-      <source>Attribute "PointCoordindates" is locked by modification value in the viewer.</source>
+      <source>Attribute "PointCoordinates" is locked by modification value in the viewer.</source>
       <translation>Select a point</translation>
     </message>
   </context>
   <context>
     <name>SketchArc:ArcCenter</name>
     <message>
-      <source>Attribute "ArcCenter" is locked by modification value in the viewer.</source>
+      <source>Attribute "center_point" is locked by modification value in the viewer.</source>
       <translation>Select a center point</translation>
     </message>
   </context>
   <context>
     <name>SketchArc:ArcCenter</name>
     <message>
-      <source>Attribute "ArcCenter" is not initialized.</source>
+      <source>Attribute "center_point" is not initialized.</source>
       <translation>Center point is not defined</translation>
     </message>
   </context>
   <context>
     <name>SketchArc:Model_FeatureValidator</name>
     <message>
-      <source>Attribute "ArcCenter" is not initialized.</source>
+      <source>Attribute "center_point" is not initialized.</source>
       <translation>Select an arc center</translation>
     </message>
   </context>
   <context>
     <name>SketchArc:Model_FeatureValidator:ArcStartPoint</name>
     <message>
-      <source>Attribute "ArcStartPoint" is not initialized.</source>
+      <source>Attribute "start_point" is not initialized.</source>
       <translation>Select an arc start point</translation>
     </message>
   </context>
   <context>
     <name>SketchArc:Model_FeatureValidator</name>
     <message>
-      <source>Attribute "ArcEndPoint" is not initialized.</source>
+      <source>Attribute "end_point" is not initialized.</source>
       <translation>Select an arc end point</translation>
     </message>
   </context>
index 24014cae24ef3b1139ebfa4ccd7c2275319594b8..2f8c3f4dbec2575cf10dadadff8aa07247a97122 100644 (file)
@@ -12,6 +12,7 @@
 from GeomDataAPI import *
 from ModelAPI import *
 import math
+from salome.shaper import model
 
 aSession = ModelAPI_Session.get()
 aDocument = aSession.moduleDocument()
@@ -35,11 +36,11 @@ aSession.finishOperation()
 #=========================================================================
 aSession.startOperation()
 aSketchArc = aSketchFeature.addFeature("SketchArc")
-anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
+anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
 anArcCentr.setValue(0., 0.)
-anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
 anArcStartPoint.setValue(0., 10.)
-anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
 anArcEndPoint.setValue(1., 10.)
 aSession.finishOperation()
 # the arc must be small, not near to the whole circle
@@ -85,8 +86,8 @@ assert shapeToEdge(aSketchArc.lastResult().shape()).length() < 32.
 aSession.startOperation()
 anArcEndPoint.setValue(10., 0.)
 aSession.finishOperation()
-assert shapeToEdge(aSketchArc.lastResult().shape()).length() > 47.
-assert shapeToEdge(aSketchArc.lastResult().shape()).length() < 48.
+assert shapeToEdge(aSketchArc.lastResult().shape()).length() > 46.5
+assert shapeToEdge(aSketchArc.lastResult().shape()).length() < 47.5
 aSession.startOperation()
 anArcEndPoint.setValue(1., 10.)
 aSession.finishOperation()
@@ -94,11 +95,11 @@ assert shapeToEdge(aSketchArc.lastResult().shape()).length() > 60.
 # check from the scratch that from initial state to counterclockwise position also works
 aSession.startOperation()
 aSketchArc = aSketchFeature.addFeature("SketchArc")
-anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
+anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
 anArcCentr.setValue(0., 0.)
-anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
 anArcStartPoint.setValue(0., 10.)
-anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
 anArcEndPoint.setValue(-1., 10.)
 aSession.finishOperation()
 # the arc must be small, not near to the whole circle
@@ -108,33 +109,32 @@ assert shapeToEdge(aSketchArc.lastResult().shape()).length() < 2.
 #=========================================================================
 aSession.startOperation()
 aSketchArc = aSketchFeature.addFeature("SketchArc")
-anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
+anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
 anArcCentr.setValue(0., 0.)
-anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
 anArcStartPoint.setValue(0., 10.)
-anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
 anArcEndPoint.setValue(10, 0.)
 aSession.finishOperation()
-anInversed = aSketchArc.boolean("InversedArc").value()
+anInversed = aSketchArc.boolean("reversed").value()
 for aCenterCoords in range(1, 20):
   aSession.startOperation()
   anArcCentr.setValue(aCenterCoords, aCenterCoords/2) # move center
   aSession.finishOperation()
-  assert aSketchArc.boolean("InversedArc").value() == anInversed
+  assert aSketchArc.boolean("reversed").value() == anInversed
 for aCenterCoords in range(20, -20, -1):
   aSession.startOperation()
   anArcCentr.setValue(aCenterCoords, aCenterCoords/2) # move center
   aSession.finishOperation()
-  assert aSketchArc.boolean("InversedArc").value() == anInversed
+  assert aSketchArc.boolean("reversed").value() == anInversed
 for aCenterCoords in range(-20, 20):
   aSession.startOperation()
   anArcCentr.setValue(aCenterCoords, aCenterCoords/2) # move center
   aSession.finishOperation()
-  assert aSketchArc.boolean("InversedArc").value() == anInversed
+  assert aSketchArc.boolean("reversed").value() == anInversed
 #=========================================================================
-# Test that movement of start point of arc does not change central point
+# Test that movement of start point of arc does not break the arc
 #=========================================================================
-TOL = 1.e-5
 x = anArcCentr.x()
 y = anArcCentr.y()
 sx = anArcStartPoint.x()
@@ -143,16 +143,14 @@ for aDelta in range(0, 20):
   aSession.startOperation()
   anArcStartPoint.setValue(sx, sy+aDelta) # move start point
   aSession.finishOperation()
-  assert math.fabs(anArcCentr.x() - x) < TOL
-  assert math.fabs(anArcCentr.y() - y) < TOL
+  model.assertSketchArc(aSketchArc)
 for aDelta in range(20, -1, -1):
   aSession.startOperation()
   anArcStartPoint.setValue(sx, sy+aDelta) # move start point
   aSession.finishOperation()
-  assert math.fabs(anArcCentr.x() - x) < TOL
-  assert math.fabs(anArcCentr.y() - y) < TOL
+  model.assertSketchArc(aSketchArc)
 #=========================================================================
-# Test that movement of end point of arc does not change central point
+# Test that movement of end point of arc does not break the arc
 #=========================================================================
 x = anArcCentr.x()
 y = anArcCentr.y()
@@ -162,11 +160,9 @@ for aDelta in range(0, 20):
   aSession.startOperation()
   anArcEndPoint.setValue(sx+aDelta, sy) # move end point
   aSession.finishOperation()
-  assert math.fabs(anArcCentr.x() - x) < TOL
-  assert math.fabs(anArcCentr.y() - y) < TOL
+  model.assertSketchArc(aSketchArc)
 for aDelta in range(20, -1, -1):
   aSession.startOperation()
   anArcEndPoint.setValue(sx+aDelta, sy) # move end point
   aSession.finishOperation()
-  assert math.fabs(anArcCentr.x() - x) < TOL
-  assert math.fabs(anArcCentr.y() - y) < TOL
+  model.assertSketchArc(aSketchArc)
index 0ee20f691de2f3413b968b203730bce1f35706be..27def860c235ff71554f037f3ce5b9c1f25dbd4a 100644 (file)
@@ -42,14 +42,14 @@ def checkPointOnLine(point, line):
     assert (math.fabs(aDirX * aVecY - aDirY * aVecX) <= TOLERANCE)
 
 def checkPointOnCircle(point, circle):
-    aCenter = geomDataAPI_Point2D(circle.attribute("CircleCenter"))
-    aRadius = circle.real("CircleRadius").value()
+    aCenter = geomDataAPI_Point2D(circle.attribute("circle_center"))
+    aRadius = circle.real("circle_radius").value()
     aDist = math.hypot(point.x() - aCenter.x(), point.y() - aCenter.y())
     assert (math.fabs(aDist - aRadius) <= TOLERANCE)
 
 def checkPointOnArc(point, arc):
-    aStart  = geomDataAPI_Point2D(arc.attribute("ArcStartPoint"))
-    aCenter = geomDataAPI_Point2D(arc.attribute("ArcCenter"))
+    aStart  = geomDataAPI_Point2D(arc.attribute("start_point"))
+    aCenter = geomDataAPI_Point2D(arc.attribute("center_point"))
     aRadius = math.hypot(aStart.x() - aCenter.x(), aStart.y() - aCenter.y())
     aDist = math.hypot(point.x() - aCenter.x(), point.y() - aCenter.y())
     assert (math.fabs(aDist - aRadius) <= TOLERANCE)
@@ -86,9 +86,9 @@ aSession.finishOperation()
 #=========================================================================
 aSession.startOperation()
 aSketchArc = aSketchFeature.addFeature("SketchArc")
-anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
-anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
-anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
 anArcCentr.setValue(10., 10.)
 anArcStartPoint.setValue(0., 50.)
 anArcEndPoint.setValue(50., 0.)
@@ -160,8 +160,8 @@ assert (model.dof(aSketchFeature) == 8)
 aSession.startOperation()
 # create circle with center coincident with origin
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-aCircleCenter = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+aCircleCenter = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 aCircleCenter.setValue(10., 10.)
 aCircleRadius.setValue(25.)
 aSession.finishOperation()
@@ -173,7 +173,7 @@ assert (anOrigRes)
 anOrigShape = anOrigRes.shape()
 assert (anOrigShape)
 anOrigin = aSketchFeature.addFeature("SketchPoint")
-anOriginCoord = geomDataAPI_Point2D(anOrigin.attribute("PointCoordindates"))
+anOriginCoord = geomDataAPI_Point2D(anOrigin.attribute("PointCoordinates"))
 anOriginCoord.setValue(0., 0.)
 anOrigin.selection("External").setValue(anOrigRes, anOrigShape)
 aSession.finishOperation()
index 2c8b5c6a02b0e2c68354bc08e25c3274cdf53cb8..a5c80ae7c0e212f535b62eb2ab0c1881077b1a24 100644 (file)
@@ -31,15 +31,6 @@ from salome.shaper import model
 __updated__ = "2014-10-28"
 
 
-def distancePointPoint(pointA, pointB):
-    """
-    subroutine to calculate distance between two points
-    result of calculated distance is has 10**-5 precision
-    """
-    xdiff = math.pow((pointA.x() - pointB.x()), 2)
-    ydiff = math.pow((pointA.y() - pointB.y()), 2)
-    return round(math.sqrt(xdiff + ydiff), 5)
-
 def distancePointLine(point, line):
     """
     subroutine to calculate distance between point and line
@@ -78,7 +69,7 @@ aSession.finishOperation()
 aSession.startOperation()
 aSketchPoint = aSketchFeature.addFeature("SketchPoint")
 aSketchPointCoords = geomDataAPI_Point2D(
-    aSketchPoint.attribute("PointCoordindates"))
+    aSketchPoint.attribute("PointCoordinates"))
 aSketchPointCoords.setValue(50., 50.)
 aSketchLine = aSketchFeature.addFeature("SketchLine")
 aLineAStartPoint = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint"))
@@ -91,7 +82,7 @@ assert (model.dof(aSketchFeature) == 6)
 # Make a constraint to keep the distance
 #=========================================================================
 PT_PT_DIST = 25.
-aDist = distancePointPoint(aSketchPointCoords, aLineAStartPoint);
+aDist = model.distancePointPoint(aSketchPointCoords, aLineAStartPoint);
 assert (aDist != PT_PT_DIST)
 aSession.startOperation()
 aConstraint = aSketchFeature.addFeature("SketchConstraintDistance")
@@ -125,7 +116,7 @@ assert (model.dof(aSketchFeature) == 5)
 aSession.startOperation()
 aDistance.setValue(PT_PT_DIST)
 aSession.finishOperation()
-assert (math.fabs(distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) < 1.e-10)
+assert (math.fabs(model.distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) < 1.e-10)
 assert (model.dof(aSketchFeature) == 5)
 #=========================================================================
 # Move line, check that distance is constant
@@ -134,7 +125,7 @@ aSession.startOperation()
 aLineAStartPoint.setValue(0., 40.)
 aLineAEndPoint.setValue(100., 40.)
 aSession.finishOperation()
-assert (math.fabs(distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) < 1.e-10)
+assert (math.fabs(model.distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) < 1.e-10)
 assert (model.dof(aSketchFeature) == 5)
 #=========================================================================
 # Remove constraint, check the points are unconstrained now
@@ -145,7 +136,7 @@ aSession.finishOperation()
 aSession.startOperation()
 aSketchPointCoords.setValue(0., 0.)
 aSession.finishOperation()
-assert (math.fabs(distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) > 1.e-10)
+assert (math.fabs(model.distancePointPoint(aSketchPointCoords, aLineAStartPoint) - PT_PT_DIST) > 1.e-10)
 assert (model.dof(aSketchFeature) == 6)
 
 #=========================================================================
@@ -192,7 +183,7 @@ aSession.startOperation()
 refattrA.setAttr(aLineAStartPoint)
 refattrB.setAttr(aLineAEndPoint)
 aSession.finishOperation()
-assert (math.fabs(distancePointPoint(aLineAStartPoint, aLineAEndPoint) - PT_LINE_DIST) < 1.e-10)
+assert (math.fabs(model.distancePointPoint(aLineAStartPoint, aLineAEndPoint) - PT_LINE_DIST) < 1.e-10)
 assert (model.dof(aSketchFeature) == 5)
 #=========================================================================
 # End of test
index 49bf176586198358d9f30b70e2ac1ad7cc200760..5c518e99a8bc0505c0e41dda7bf60c1f234f2b08 100644 (file)
@@ -31,11 +31,11 @@ def externalSketch(theDoc):
     norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
     norm.setValue(0, 0, 1)
     # add circle defined by 3 points
-    circle = aSketchFeature.addFeature("SketchCircle")
-    circle.string("CircleType").setValue("ThreePoints")
-    geomDataAPI_Point2D(circle.attribute("FirstPoint")).setValue(-40., 50.)
-    geomDataAPI_Point2D(circle.attribute("SecondPoint")).setValue(-50., 60.)
-    geomDataAPI_Point2D(circle.attribute("ThirdPoint")).setValue(-60., 50.)
+    circle = aSketchFeature.addFeature("SketchMacroCircle")
+    circle.string("circle_type").setValue("circle_type_by_three_points")
+    geomDataAPI_Point2D(circle.attribute("first_point")).setValue(-40., 50.)
+    geomDataAPI_Point2D(circle.attribute("second_point")).setValue(-50., 60.)
+    geomDataAPI_Point2D(circle.attribute("third_point")).setValue(-60., 50.)
     # add line
     line = aSketchFeature.addFeature("SketchLine")
     lineStart = geomDataAPI_Point2D(line.attribute("StartPoint"))
@@ -80,19 +80,19 @@ aSession.finishOperation()
 #=========================================================================
 aSession.startOperation()
 aSketchArc = aSketchFeature.addFeature("SketchArc")
-anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
+anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
 anArcCentr.setValue(10., 10.)
-anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
 anArcStartPoint.setValue(0., 50.)
-anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
 anArcEndPoint.setValue(50., 0.)
 aSession.finishOperation()
 assert (model.dof(aSketchFeature) == 5)
 # Circle
 aSession.startOperation()
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(-25., -25.)
 aCircleRadius.setValue(25.)
 aSession.finishOperation()
@@ -123,8 +123,8 @@ assert (model.dof(aSketchFeature) == 7)
 #=========================================================================
 aSession.startOperation()
 anExtCircle = aSketchFeature.addFeature("SketchCircle")
-anExtCircleCenter = geomDataAPI_Point2D(anExtCircle.attribute("CircleCenter"))
-anExtCircleRadius = anExtCircle.real("CircleRadius")
+anExtCircleCenter = geomDataAPI_Point2D(anExtCircle.attribute("circle_center"))
+anExtCircleRadius = anExtCircle.real("circle_radius")
 anExtCircleCenter.setValue(-50., 50.)
 anExtCircleRadius.setValue(10.)
 anExtCircle.selection("External").selectSubShape("EDGE", "Sketch_1/Edge-SketchCircle_1_2")
index d8e69beb82929c1f2368bbad14398aa2a5c3d188..558c9ab781427e8d75d0a4d46987b7949f718351 100644 (file)
@@ -145,7 +145,7 @@ assert (anOrigRes)
 anOrigShape = anOrigRes.shape()
 assert (anOrigShape)
 anOrigin = aSketchFeature.addFeature("SketchPoint")
-anOriginCoord = geomDataAPI_Point2D(anOrigin.attribute("PointCoordindates"))
+anOriginCoord = geomDataAPI_Point2D(anOrigin.attribute("PointCoordinates"))
 anOriginCoord.setValue(0., 0.)
 anOrigin.selection("External").setValue(anOrigRes, anOrigShape)
 aSession.finishOperation()
diff --git a/src/SketchPlugin/Test/TestConstraintMirror.py b/src/SketchPlugin/Test/TestConstraintMirror.py
deleted file mode 100644 (file)
index 78fe2fb..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-"""
-    TestConstraintMirror.py
-    Unit test of SketchPlugin_ConstraintMirror class
-        
-    SketchPlugin_ConstraintMirror
-        static const std::string MY_CONSTRAINT_MIRROR_ID("SketchConstraintMirror");
-        data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
-        data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefListAttr::typeId());
-        data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefListAttr::typeId());
-
-"""
-from GeomDataAPI import *
-from ModelAPI import *
-import math
-from salome.shaper import model
-
-#=========================================================================
-# Initialization of the test
-#=========================================================================
-
-__updated__ = "2015-03-17"
-
-#=========================================================================
-# Auxiliary functions
-#=========================================================================
-def normalize(theDir):
-    aLen = math.hypot(theDir[0], theDir[1])
-    if aLen < 1.e-10:
-        aLen = 1.0
-    return [theDir[0] / aLen, theDir[1] / aLen]
-
-def checkMirror(theListInit, theListMirr, theMirrorLine):
-    TOL = 6.e-5
-    aListSize = theListInit.size()
-    
-    aLineStartPoint = geomDataAPI_Point2D(theMirrorLine.attribute("StartPoint"))
-    aLineEndPoint = geomDataAPI_Point2D(theMirrorLine.attribute("EndPoint"))
-    aLineDir = [aLineEndPoint.x() - aLineStartPoint.x(), aLineEndPoint.y() - aLineStartPoint.y()]
-    aLineDir = normalize(aLineDir)
-
-    for ind in range(0, aListSize):
-        aFeatureB = ModelAPI_Feature.feature(theListInit.object(ind))
-        aFeatureC = ModelAPI_Feature.feature(theListMirr.object(ind))
-        assert(aFeatureB is not None)
-        assert(aFeatureC is not None)
-        assert(aFeatureB.getKind() == aFeatureC.getKind())
-        
-        anAttributes = []
-        if (aFeatureB.getKind() == "SketchLine"):
-            anAttributes = ['StartPoint', 'EndPoint']
-        elif (aFeatureB.getKind() == "SketchArc"):
-            anAttributes = ['ArcCenter', 'ArcStartPoint', 'ArcEndPoint']
-        
-        for key in anAttributes:
-            aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key))
-            aPointC = geomDataAPI_Point2D(aFeatureC.attribute(key))
-            aDir = [aPointC.x() - aPointB.x(), aPointC.y() - aPointB.y()]
-            aDir = normalize(aDir)
-            aDot = aLineDir[0] * aDir[0] + aLineDir[1] * aDir[1]
-            assert math.fabs(aDot) < TOL, "aDot = {0}".format(aDot)
-            aDir[0] = aLineEndPoint.x() - 0.5 * (aPointB.x() + aPointC.x())
-            aDir[1] = aLineEndPoint.y() - 0.5 * (aPointB.y() + aPointC.y())
-            aCross = aLineDir[0] * aDir[1] - aLineDir[1] * aDir[0]
-            assert math.fabs(aCross) < TOL, "aCross = {0}".format(aCross)
-
-
-#=========================================================================
-# Start of test
-#=========================================================================
-aSession = ModelAPI_Session.get()
-aDocument = aSession.moduleDocument()
-#=========================================================================
-# Creation of a sketch
-#=========================================================================
-aSession.startOperation()
-aSketchCommonFeature = aDocument.addFeature("Sketch")
-aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
-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)
-aSession.finishOperation()
-#=========================================================================
-# Creation of an arc and two lines
-#=========================================================================
-# Arc
-aSession.startOperation()
-aSketchArc1 = aSketchFeature.addFeature("SketchArc")
-anArcCentr = geomDataAPI_Point2D(aSketchArc1.attribute("ArcCenter"))
-anArcCentr.setValue(10., 10.)
-anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcStartPoint"))
-anArcStartPoint.setValue(0., 50.)
-anArcEndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcEndPoint"))
-anArcEndPoint.setValue(50., 0.)
-aSession.finishOperation()
-# Line 1
-aSession.startOperation()
-aSketchLine1 = aSketchFeature.addFeature("SketchLine")
-aLine1StartPoint = geomDataAPI_Point2D(aSketchLine1.attribute("StartPoint"))
-aLine1EndPoint = geomDataAPI_Point2D(aSketchLine1.attribute("EndPoint"))
-aLine1StartPoint.setValue(0., 50.)
-aLine1EndPoint.setValue(0., 100.)
-aSession.finishOperation()
-# Line 2
-aSession.startOperation()
-aSketchLine2 = aSketchFeature.addFeature("SketchLine")
-aLine2StartPoint = geomDataAPI_Point2D(aSketchLine2.attribute("StartPoint"))
-aLine2EndPoint = geomDataAPI_Point2D(aSketchLine2.attribute("EndPoint"))
-aLine2StartPoint.setValue(50., 0.)
-aLine2EndPoint.setValue(100., 0.)
-aSession.finishOperation()
-assert (model.dof(aSketchFeature) == 13)
-#=========================================================================
-# Link arc points and lines points by the coincidence constraint
-#=========================================================================
-aSession.startOperation()
-aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
-reflistA = aConstraint.refattr("ConstraintEntityA")
-reflistB = aConstraint.refattr("ConstraintEntityB")
-reflistA.setAttr(anArcStartPoint)
-reflistB.setAttr(aLine1StartPoint)
-aConstraint.execute()
-aSession.finishOperation()
-aSession.startOperation()
-aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
-reflistA = aConstraint.refattr("ConstraintEntityA")
-reflistB = aConstraint.refattr("ConstraintEntityB")
-reflistA.setAttr(anArcEndPoint)
-reflistB.setAttr(aLine2StartPoint)
-aConstraint.execute()
-aSession.finishOperation()
-assert (model.dof(aSketchFeature) == 9)
-#=========================================================================
-# Add tangency constraint and check correctness
-#=========================================================================
-aSession.startOperation()
-aTangency = aSketchFeature.addFeature("SketchConstraintTangent")
-aRefObjectA = aTangency.refattr("ConstraintEntityA")
-aRefObjectB = aTangency.refattr("ConstraintEntityB")
-anObjectA = modelAPI_ResultConstruction(aSketchArc1.lastResult())
-anObjectB = modelAPI_ResultConstruction(aSketchLine1.lastResult())
-assert (anObjectA is not None)
-assert (anObjectB is not None)
-aRefObjectA.setObject(anObjectA)
-aRefObjectB.setObject(anObjectB)
-aTangency.execute()
-aSession.finishOperation()
-assert (model.dof(aSketchFeature) == 8)
-#=========================================================================
-# Create mirror line
-#=========================================================================
-aSession.startOperation()
-aMirrorLine = aSketchFeature.addFeature("SketchLine")
-aLineStartPoint = geomDataAPI_Point2D(aMirrorLine.attribute("StartPoint"))
-aLineEndPoint = geomDataAPI_Point2D(aMirrorLine.attribute("EndPoint"))
-aLineStartPoint.setValue(100., 0.)
-aLineEndPoint.setValue(100., 100.)
-aSession.finishOperation()
-assert (model.dof(aSketchFeature) == 12)
-#=========================================================================
-# Make mirror for objects created above
-#=========================================================================
-aSession.startOperation()
-aMirror = aSketchFeature.addFeature("SketchConstraintMirror")
-aRefObjectA = aMirror.refattr("ConstraintEntityA")
-aRefObjectA.setObject(modelAPI_ResultConstruction(aMirrorLine.firstResult()))
-aRefListInitial = aMirror.reflist("ConstraintMirrorList")
-aRefListInitial.append(aSketchLine1.lastResult())
-aRefListInitial.append(aSketchArc1.lastResult())
-aRefListInitial.append(aSketchLine2.lastResult())
-aMirror.execute()
-aSession.finishOperation()
-assert (model.dof(aSketchFeature) == 12)
-#=========================================================================
-# Verify the simmetricity of all mirrored objects
-#=========================================================================
-aRefListB = aMirror.reflist("ConstraintEntityB")
-aRefListC = aMirror.reflist("ConstraintEntityC")
-assert (aRefListB.size() == 3)
-assert (aRefListC.size() == 3)
-checkMirror(aRefListB, aRefListC, aMirrorLine)
-assert (model.dof(aSketchFeature) == 12)
-
-#=========================================================================
-# Remove object from mirror
-#=========================================================================
-aSession.startOperation()
-aRefListInitial.remove(aSketchLine2.lastResult())
-aSession.finishOperation()
-assert (aRefListB.size() == 2)
-assert (aRefListC.size() == 2)
-checkMirror(aRefListB, aRefListC, aMirrorLine)
-assert (model.dof(aSketchFeature) == 12)
-
-#=========================================================================
-# Clear list of mirrored features
-#=========================================================================
-aSession.startOperation()
-aRefListInitial.clear()
-assert (aRefListB.size() == 0)
-assert (aRefListC.size() == 0)
-# add arc once again
-aRefListInitial.append(aSketchArc1.lastResult())
-aSession.finishOperation()
-assert (aRefListB.size() == 1)
-assert (aRefListC.size() == 1)
-checkMirror(aRefListB, aRefListC, aMirrorLine)
-assert (model.dof(aSketchFeature) == 12)
-#=========================================================================
-# End of test
-#=========================================================================
-
-assert(model.checkPythonDump())
index 9ba906752f4c4210ffdc93479bae3e83d25752ae..f11cf74c908f519d1b1dde7dc515b3f939ef8d46 100644 (file)
@@ -28,15 +28,6 @@ from salome.shaper import model
 
 __updated__ = "2014-10-28"
 
-def distancePointPoint(pointA, pointB):
-    """
-    subroutine to calculate distance between two points
-    result of calculated distance is has 10**-5 precision
-    """
-    xdiff = math.pow((pointA.x() - pointB.x()), 2)
-    ydiff = math.pow((pointA.y() - pointB.y()), 2)
-    return round(math.sqrt(xdiff + ydiff), 5)
-
 
 aSession = ModelAPI_Session.get()
 aDocument = aSession.moduleDocument()
@@ -58,11 +49,11 @@ aSession.finishOperation()
 #=========================================================================
 aSession.startOperation()
 aSketchArc = aSketchFeature.addFeature("SketchArc")
-anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
+anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
 anArcCentr.setValue(10., 10.)
-anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
 anArcStartPoint.setValue(0., 50.)
-anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
 anArcEndPoint.setValue(50., 0.)
 aSession.finishOperation()
 assert (model.dof(aSketchFeature) == 5)
@@ -81,22 +72,16 @@ assert (model.dof(aSketchFeature) == 5)
 # Circle
 aSession.startOperation()
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
-anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
-aCircleRadius = aSketchCircle.real("CircleRadius")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("circle_center"))
+aCircleRadius = aSketchCircle.real("circle_radius")
 anCircleCentr.setValue(-25., -25)
 aCircleRadius.setValue(25.)
 aSession.finishOperation()
 assert (model.dof(aSketchFeature) == 8)
-# Change the radius of the arc
-aSession.startOperation()
-RADIUS = 40
-anArcRadius = aSketchArc.real("ArcRadius")
-anArcRadius.setValue(RADIUS)
-aSession.finishOperation()
-assert (model.dof(aSketchFeature) == 8)
 #=========================================================================
 # Make a constraint to keep the radius of the arc
 #=========================================================================
+RADIUS = 40
 aSession.startOperation()
 aConstraint = aSketchFeature.addFeature("SketchConstraintRadius")
 aRadius = aConstraint.real("ConstraintValue")
@@ -104,7 +89,7 @@ aRefObject = aConstraint.refattr("ConstraintEntityA")
 aResult = aSketchArc.lastResult()
 assert (aResult is not None)
 aRefObject.setObject(modelAPI_ResultConstruction(aResult))
-aConstraint.execute()
+aRadius.setValue(RADIUS)
 aSession.finishOperation()
 assert (aRadius.isInitialized())
 assert (aRefObject.isInitialized())
@@ -119,19 +104,21 @@ aRefObject = aConstraint.refattr("ConstraintEntityA")
 aResult = aSketchCircle.lastResult()
 assert (aResult is not None)
 aRefObject.setObject(modelAPI_ResultConstruction(aResult))
-aConstraint.execute()
+aRadius.setValue(RADIUS)
 aSession.finishOperation()
 assert (aRadius.isInitialized())
 assert (aRefObject.isInitialized())
 assert (model.dof(aSketchFeature) == 6)
 #=========================================================================
 # Perform some actions and checks:
-# 1. Check that constraints does not changes values
+# 1. Check that constraints does not change values
 # 2. Move one point of the arc
 # 3. Check that second point is moved also
 #=========================================================================
-assert (math.fabs(distancePointPoint(anArcCentr, anArcStartPoint) - RADIUS) < 1.e-10)
-assert (math.fabs(distancePointPoint(anArcCentr, anArcEndPoint) - RADIUS) < 1.e-10)
+distCS = model.distancePointPoint(anArcCentr, anArcStartPoint)
+distCE = model.distancePointPoint(anArcCentr, anArcEndPoint)
+assert (math.fabs(distCS - RADIUS) < 1.e-10)
+assert (math.fabs(distCE - RADIUS) < 1.e-10)
 anArcPrevEndPointX = anArcEndPoint.x()
 anArcPrevEndPointY = anArcEndPoint.y()
 # Move one point of the arc
@@ -140,8 +127,10 @@ anArcStartPoint.setValue(0, 60)
 aSession.finishOperation()
 assert (anArcEndPoint.x() != anArcPrevEndPointX)
 assert (anArcEndPoint.y() != anArcPrevEndPointY)
-assert (math.fabs(distancePointPoint(anArcCentr, anArcStartPoint) - RADIUS) < 1.e-10)
-assert (math.fabs(distancePointPoint(anArcCentr, anArcEndPoint) - RADIUS) < 1.e-10)
+distCS = model.distancePointPoint(anArcCentr, anArcStartPoint)
+distCE = model.distancePointPoint(anArcCentr, anArcEndPoint)
+assert (math.fabs(distCS - RADIUS) < 1.e-10)
+assert (math.fabs(distCE - RADIUS) < 1.e-10)
 assert (model.dof(aSketchFeature) == 6)
 #=========================================================================
 # 4. Move the centr or the point of the arc
@@ -149,13 +138,13 @@ assert (model.dof(aSketchFeature) == 6)
 #=========================================================================
 assert (anCircleCentr.x() == -25)
 assert (anCircleCentr.y() == -25)
-assert (aCircleRadius.value() == 25)
+assert (aCircleRadius.value() == RADIUS)
 aSession.startOperation()
 anCircleCentr.setValue(100., 100.)
 aSession.finishOperation()
 assert (anCircleCentr.x() == 100)
 assert (anCircleCentr.y() == 100)
-assert (aCircleRadius.value() == 25)
+assert (aCircleRadius.value() == RADIUS)
 assert (model.dof(aSketchFeature) == 6)
 #=========================================================================
 # End of test
index 7b37ce0f3184fc5b258f5b77f22f7d13b5dc2f6c..fb18f3325bc8deddf9b6c0c05591511d01290d2d 100644 (file)
@@ -20,14 +20,6 @@ from salome.shaper import model
 
 __updated__ = "2015-03-17"
 
-def distancePointPoint(thePoint1, thePoint2):
-    """
-    subroutine to calculate distance between two points
-    result of calculated distance is has 10**-5 precision
-    """
-    aDist = math.sqrt((thePoint1.x()-thePoint2.x())**2 + (thePoint1.y()-thePoint2.y())**2)
-    return round(aDist, 5)
-
 def distancePointLine(point, line):
     """
     subroutine to calculate distance between point and line
@@ -50,12 +42,12 @@ def checkArcLineTangency(theArc, theLine):
     subroutine to check that the line is tangent to arc/circle
     """
     if (theArc.getKind() == "SketchCircle"):
-        aCenter = geomDataAPI_Point2D(theArc.attribute("CircleCenter"))
-        aRadius = theArc.real("CircleRadius").value()
+        aCenter = geomDataAPI_Point2D(theArc.attribute("circle_center"))
+        aRadius = theArc.real("circle_radius").value()
     else:
-        aCenter = geomDataAPI_Point2D(theArc.attribute("ArcCenter"))
-        aStartPnt = geomDataAPI_Point2D(theArc.attribute("ArcStartPoint"))
-        aRadius = distancePointPoint(aStartPnt, aCenter)
+        aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
+        aStartPnt = geomDataAPI_Point2D(theArc.attribute("start_point"))
+        aRadius = model.distancePointPoint(aStartPnt, aCenter)
     aDist = distancePointLine(aCenter, theLine)
     assert math.fabs(aDist - aRadius) < 2.e-5, "aDist = {0}, aRadius = {1}".format(aDist, aRadius)
 
@@ -68,15 +60,15 @@ def checkArcArcTangency(theArc1, theArc2):
     aRadii = []
     for anArc in anArcs:
         if (anArc.getKind() == "SketchCircle"):
-            aCenter = geomDataAPI_Point2D(anArc.attribute("CircleCenter"))
-            aRadius = anArc.real("CircleRadius").value()
+            aCenter = geomDataAPI_Point2D(anArc.attribute("circle_center"))
+            aRadius = anArc.real("circle_radius").value()
         else:
-            aCenter = geomDataAPI_Point2D(anArc.attribute("ArcCenter"))
-            aStartPnt = geomDataAPI_Point2D(anArc.attribute("ArcStartPoint"))
-            aRadius = distancePointPoint(aStartPnt, aCenter)
+            aCenter = geomDataAPI_Point2D(anArc.attribute("center_point"))
+            aStartPnt = geomDataAPI_Point2D(anArc.attribute("start_point"))
+            aRadius = model.distancePointPoint(aStartPnt, aCenter)
         aCenters.append(aCenter)
         aRadii.append(aRadius)
-    aDist = distancePointPoint(aCenters[0], aCenters[1])
+    aDist = model.distancePointPoint(aCenters[0], aCenters[1])
     aRSum = aRadii[0] + aRadii[1]
     aRDiff = math.fabs(aRadii[0] - aRadii[1])
     assert math.fabs(aDist - aRSum) < 2.e-5 or math.fabs(aDist - aRDiff) < 2.e-5, "aDist = {0}, aRSum = {1}, aRDiff = {2}".format(aDist, aRSum, aRDiff)
@@ -105,11 +97,11 @@ aSession.finishOperation()
 # Arc
 aSession.startOperation()
 aSketchArc1 = aSketchFeature.addFeature("SketchArc")
-anArcCentr = geomDataAPI_Point2D(aSketchArc1.attribute("ArcCenter"))
+anArcCentr = geomDataAPI_Point2D(aSketchArc1.attribute("center_point"))
 anArcCentr.setValue(10., 10.)
-anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcStartPoint"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("start_point"))
 anArcStartPoint.setValue(0., 50.)
-anArcEndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcEndPoint"))
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("end_point"))
 anArcEndPoint.setValue(50., 0.)
 aSession.finishOperation()
 # Line 1
@@ -192,26 +184,28 @@ assert (model.dof(aSketchFeature) == 7)
 # Arc 1
 aSession.startOperation()
 aSketchArc1 = aSketchFeature.addFeature("SketchArc")
-anArc1Centr = geomDataAPI_Point2D(aSketchArc1.attribute("ArcCenter"))
+anArc1Centr = geomDataAPI_Point2D(aSketchArc1.attribute("center_point"))
 anArc1Centr.setValue(10., 10.)
-anArc1StartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcStartPoint"))
+anArc1StartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("start_point"))
 anArc1StartPoint.setValue(50., 0.)
-anArc1EndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcEndPoint"))
+anArc1EndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("end_point"))
 anArc1EndPoint.setValue(0., 50.)
 aSession.finishOperation()
 # Arc 2
 aSession.startOperation()
-aSketchArc2 = aSketchFeature.addFeature("SketchArc")
-aSketchArc2.string("ArcType").setValue("ThreePoints")
-anArc2Centr = geomDataAPI_Point2D(aSketchArc2.attribute("ArcCenter"))
-anArc2StartPoint = geomDataAPI_Point2D(aSketchArc2.attribute("ArcStartPoint"))
+aSketchArc2 = aSketchFeature.addFeature("SketchMacroArc")
+aSketchArc2.string("arc_type").setValue("by_three_points")
+anArc2StartPoint = geomDataAPI_Point2D(aSketchArc2.attribute("start_point_2"))
 anArc2StartPoint.setValue(0., 50.)
-anArc2EndPoint = geomDataAPI_Point2D(aSketchArc2.attribute("ArcEndPoint"))
+anArc2EndPoint = geomDataAPI_Point2D(aSketchArc2.attribute("end_point_2"))
 anArc2EndPoint.setValue(-50., 0.)
-anArc2PassedPoint = geomDataAPI_Point2D(aSketchArc2.attribute("ArcPassedPoint"))
+anArc2PassedPoint = geomDataAPI_Point2D(aSketchArc2.attribute("passed_point"))
 anArc2PassedPoint.setValue(-40., 40.)
 aSession.finishOperation()
-assert (model.dof(aSketchFeature) == 17)
+#assert (model.dof(aSketchFeature) == 17)
+aSketchArc2 = model.lastSubFeature(aSketchFeature, "SketchArc")
+anArc2Centr = geomDataAPI_Point2D(aSketchArc2.attribute("center_point"))
+anArc2StartPoint = geomDataAPI_Point2D(aSketchArc2.attribute("start_point"))
 #=========================================================================
 # Link points of arcs by the coincidence constraint
 #=========================================================================
@@ -269,11 +263,11 @@ assert (model.dof(aSketchFeature) == 14)
 # 3.2  tangency between non-connected arcs
 aSession.startOperation()
 aSketchArc3 = aSketchFeature.addFeature("SketchArc")
-anArc3Centr = geomDataAPI_Point2D(aSketchArc3.attribute("ArcCenter"))
+anArc3Centr = geomDataAPI_Point2D(aSketchArc3.attribute("center_point"))
 anArc3Centr.setValue(100., -10.)
-anArc3StartPoint = geomDataAPI_Point2D(aSketchArc3.attribute("ArcStartPoint"))
+anArc3StartPoint = geomDataAPI_Point2D(aSketchArc3.attribute("start_point"))
 anArc3StartPoint.setValue(70., -10.)
-anArc3EndPoint = geomDataAPI_Point2D(aSketchArc3.attribute("ArcEndPoint"))
+anArc3EndPoint = geomDataAPI_Point2D(aSketchArc3.attribute("end_point"))
 anArc3EndPoint.setValue(100., 20.)
 aSession.finishOperation()
 assert (model.dof(aSketchFeature) == 19)
@@ -295,8 +289,8 @@ assert (model.dof(aSketchFeature) == 14)
 # 3.3  tangency between arc and circle
 aSession.startOperation()
 aCircle1 = aSketchFeature.addFeature("SketchCircle")
-aCircleCenter = geomDataAPI_Point2D(aCircle1.attribute("CircleCenter"))
-aCircleRadius = aCircle1.real("CircleRadius")
+aCircleCenter = geomDataAPI_Point2D(aCircle1.attribute("circle_center"))
+aCircleRadius = aCircle1.real("circle_radius")
 aCircleCenter.setValue(150., 100.)
 aCircleRadius.setValue(50.)
 aSession.finishOperation()
@@ -313,8 +307,8 @@ assert (model.dof(aSketchFeature) == 16)
 # 3.4  tangency between two circles
 aSession.startOperation()
 aCircle2 = aSketchFeature.addFeature("SketchCircle")
-aCircleCenter = geomDataAPI_Point2D(aCircle2.attribute("CircleCenter"))
-aCircleRadius = aCircle2.real("CircleRadius")
+aCircleCenter = geomDataAPI_Point2D(aCircle2.attribute("circle_center"))
+aCircleRadius = aCircle2.real("circle_radius")
 aCircleCenter.setValue(120., 70.)
 aCircleRadius.setValue(20.)
 aSession.finishOperation()
@@ -332,13 +326,14 @@ assert (model.dof(aSketchFeature) == 18)
 # TEST 4. Creating of tangency arc by the option of the SketchArc feature
 #=========================================================================
 aSession.startOperation()
-aSketchArc3 = aSketchFeature.addFeature("SketchArc")
-aSketchArc3.string("ArcType").setValue("Tangent")
-anArc3Start = aSketchArc3.refattr("ArcTangentPoint")
+aSketchArc3 = aSketchFeature.addFeature("SketchMacroArc")
+aSketchArc3.string("arc_type").setValue("by_tangent_edge")
+anArc3Start = aSketchArc3.refattr("tangent_point")
 anArc3Start.setAttr(anArc1StartPoint)
-anArc3EndPoint = geomDataAPI_Point2D(aSketchArc3.attribute("ArcEndPoint"))
+anArc3EndPoint = geomDataAPI_Point2D(aSketchArc3.attribute("end_point_3"))
 anArc3EndPoint.setValue(anArc1StartPoint.x()-5, anArc1StartPoint.y()-30)
 aSession.finishOperation()
+aSketchArc3 = model.lastSubFeature(aSketchFeature, "SketchArc")
 checkArcArcTangency(aSketchArc1, aSketchArc3)
 # freeze radius of tangent arc
 aSession.startOperation()
@@ -364,8 +359,8 @@ aLineEnd = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
 aLineStart.setValue(100., 100.)
 aLineEnd.setValue(200., 200.)
 aCircle = aSketchFeature.addFeature("SketchCircle")
-aCircleCenter = geomDataAPI_Point2D(aCircle.attribute("CircleCenter"))
-aCircleRadius = aCircle.real("CircleRadius")
+aCircleCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center"))
+aCircleRadius = aCircle.real("circle_radius")
 aCircleCenter.setValue(150., 100.)
 aCircleRadius.setValue(20.)
 aSession.finishOperation()
diff --git a/src/SketchPlugin/Test/TestCreateArcByCenterStartEnd.py b/src/SketchPlugin/Test/TestCreateArcByCenterStartEnd.py
new file mode 100644 (file)
index 0000000..5cbe2fa
--- /dev/null
@@ -0,0 +1,125 @@
+"""
+    TestCreateArc.py
+
+    static const std::string MY_SKETCH_ARC_ID("SketchArc");
+    static const std::string MY_CENTER_ID = "center_point";
+    static const std::string MY_START_ID = "start_point";
+    static const std::string MY_END_ID = "end_point";
+    data()->addAttribute(SketchPlugin_Arc::CENTER_ID(), GeomDataAPI_Point2D::typeId());
+    data()->addAttribute(SketchPlugin_Arc::START_ID(),  GeomDataAPI_Point2D::typeId());
+    data()->addAttribute(SketchPlugin_Arc::END_ID(),    GeomDataAPI_Point2D::typeId());
+"""
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from GeomDataAPI import *
+from ModelAPI import *
+import math
+from salome.shaper import model
+
+__updated__ = "2017-03-28"
+
+TOLERANCE = 1.e-7
+
+#=========================================================================
+# Auxiliary functions
+#=========================================================================
+
+def verifyLastArc(theSketch, theCenter, theStart, theEnd):
+    """
+    subroutine to verify position of last arc in the sketch
+    """
+    aLastArc = model.lastSubFeature(theSketch, "SketchArc")
+    aCenterPnt = geomDataAPI_Point2D(aLastArc.attribute("center_point"))
+    aStartPnt = geomDataAPI_Point2D(aLastArc.attribute("start_point"))
+    aEndPnt = geomDataAPI_Point2D(aLastArc.attribute("end_point"))
+    if len(theCenter):
+        verifyPointCoordinates(aCenterPnt, theCenter[0], theCenter[1])
+    if len(theStart):
+        verifyPointCoordinates(aStartPnt, theStart[0], theStart[1])
+    if len(theEnd):
+        verifyPointCoordinates(aEndPnt, theEnd[0], theEnd[1])
+    model.assertSketchArc(aLastArc)
+
+def verifyPointCoordinates(thePoint, theX, theY):
+    assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.id(), thePoint.x(), thePoint.y(), theX, theY)
+
+
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+aSession.startOperation()
+aSketchCommonFeature = aDocument.addFeature("Sketch")
+aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+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)
+aSession.finishOperation()
+
+#=========================================================================
+# Test 1. Create an arc by center, start and end points
+#=========================================================================
+aCenter = [10., 10.]
+aStart  = [0., 50.]
+aEnd    = [50., 0.]
+aSession.startOperation()
+aSketchArc = aSketchFeature.addFeature("SketchArc")
+assert (aSketchArc.getKind() == "SketchArc")
+anArcCenter = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
+assert (not anArcCenter.isInitialized())
+anArcCenter.setValue(aCenter[0], aCenter[1])
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
+assert (not anArcStartPoint.isInitialized())
+anArcStartPoint.setValue(aStart[0], aStart[1])
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
+assert (not anArcEndPoint.isInitialized())
+anArcEndPoint.setValue(aEnd[0], aEnd[1])
+aSession.finishOperation()
+verifyLastArc(aSketchFeature, aCenter, aStart, aEnd)
+# Move center
+aCenter = [15., 20.]
+aSession.startOperation()
+anArcCenter.setValue(aCenter[0], aCenter[1])
+aSession.finishOperation()
+verifyLastArc(aSketchFeature, [], [], [])
+# Move start point
+deltaX, deltaY = 5., 2.
+aStart = [anArcStartPoint.x() + deltaX, anArcStartPoint.y() + deltaY]
+aSession.startOperation()
+anArcStartPoint.setValue(aStart[0], aStart[1])
+aSession.finishOperation()
+verifyLastArc(aSketchFeature, [], [], [])
+# Move end point
+aEnd = [anArcEndPoint.x() - deltaX, anArcEndPoint.y() - deltaY]
+aSession.startOperation()
+anArcEndPoint.setValue(aEnd[0], aEnd[1])
+aSession.finishOperation()
+verifyLastArc(aSketchFeature, [], [], [])
+# Check that changing the radius does not affect arc
+aSession.startOperation()
+anArcRadius = aSketchArc.real("radius")
+aPrevRadius = anArcRadius.value();
+anArcRadius.setValue(aPrevRadius + 10.)
+aSession.finishOperation()
+assert (math.fabs(anArcRadius.value() - aPrevRadius) < TOLERANCE)
+verifyLastArc(aSketchFeature, [], [], [])
+# Check that changing the angle does not affect arc
+aSession.startOperation()
+anArcAngle = aSketchArc.real("angle")
+aPrevAngle = anArcAngle.value()
+anArcAngle.setValue(aPrevAngle + 10.)
+aSession.finishOperation()
+assert (math.fabs(anArcAngle.value() - aPrevAngle) < TOLERANCE)
+verifyLastArc(aSketchFeature, [], [], [])
+
+#=========================================================================
+# End of test
+#=========================================================================
+
+assert(model.checkPythonDump())
index 272399734498cbdd49028efbd215d291af79bed4..35f55de79ea8ed822c220c1f2de6a493fbb5edde 100644 (file)
@@ -22,28 +22,18 @@ __updated__ = "2017-03-22"
 #=========================================================================
 TOLERANCE = 1.e-7
 
-def getLastCircle(theSketch):
-    """
-    obtains last feature from the sketch and generates error if the feature is not a circle
-    """
-    expectedKind = "SketchCircle"
-    for anIndex in range(theSketch.numberOfSubs() - 1, -1, -1):
-        aSub = theSketch.subFeature(anIndex)
-        if (aSub.getKind() == expectedKind):
-            return aSub
-
 def verifyLastCircle(theSketch, theX, theY, theR):
     """
     subroutine to verify position of last circle in the sketch
     """
-    aLastCircle = getLastCircle(theSketch)
+    aLastCircle = model.lastSubFeature(theSketch, "SketchCircle")
     aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center"))
     verifyPointCoordinates(aCenter, theX, theY)
     aRadius = aLastCircle.real("circle_radius")
     assert aRadius.value() == theR, "Wrong radius {0}, expected {1}".format(aRadius.value(), theR)
 
 def verifyPointCoordinates(thePoint, theX, theY):
-    assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.attributeType(), thePoint.x(), thePoint.y(), theX, theY)
+    assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.id(), thePoint.x(), thePoint.y(), theX, theY)
 
 def verifyPointOnLine(thePoint, theLine):
     aDistance = distancePointLine(thePoint, theLine)
@@ -52,16 +42,13 @@ def verifyPointOnLine(thePoint, theLine):
 def verifyTangentCircles(theCircle1, theCircle2):
     aCenter1 = geomDataAPI_Point2D(theCircle1.attribute("circle_center"))
     aCenter2 = geomDataAPI_Point2D(theCircle2.attribute("circle_center"))
-    aDistCC = distancePointPoint(aCenter1, aCenter2)
+    aDistCC = model.distancePointPoint(aCenter1, aCenter2)
     aRadius1 = theCircle1.real("circle_radius").value()
     aRadius2 = theCircle2.real("circle_radius").value()
     aRSum = aRadius1 + aRadius2
     aRDiff = math.fabs(aRadius1 - aRadius2)
     assert math.fabs(aRSum - aDistCC) < TOLERANCE or math.fabs(aRDiff - aDistCC) < TOLERANCE, "Circles do not tangent"
 
-def distancePointPoint(thePoint1, thePoint2):
-    return thePoint1.pnt().distance(thePoint2.pnt())
-
 def distancePointLine(thePoint, theLine):
     aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy()
     aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy()
@@ -137,7 +124,7 @@ assert (not aCircleType.isInitialized())
 aCircleType.setValue("circle_type_by_center_and_passed_points")
 aCircleCenter.setValue(-25., -25)
 aCirclePassed.setValue(0., -25.)
-aRadius = distancePointPoint(aCircleCenter, aCirclePassed)
+aRadius = model.distancePointPoint(aCircleCenter, aCirclePassed)
 aSession.finishOperation()
 assert (aSketchFeature.numberOfSubs() == 2)
 verifyLastCircle(aSketchFeature, -25., -25., aRadius)
@@ -146,13 +133,13 @@ verifyLastCircle(aSketchFeature, -25., -25., aRadius)
 # Test 3. Create a circle as a macro-feature by center and passed point coincident to other points
 #=========================================================================
 # get previous circle
-aPrevCircle = getLastCircle(aSketchFeature)
+aPrevCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
 aPrevCenter = geomDataAPI_Point2D(aPrevCircle.attribute("circle_center"))
 # create additional point
 aPointCoodinates = [0., 0.]
 aSession.startOperation()
 aPoint = aSketchFeature.addFeature("SketchPoint")
-aPointCoord = geomDataAPI_Point2D(aPoint.attribute("PointCoordindates"))
+aPointCoord = geomDataAPI_Point2D(aPoint.attribute("PointCoordinates"))
 aPointCoord.setValue(aPointCoodinates[0], aPointCoodinates[1])
 aSession.finishOperation()
 # create new circle
@@ -172,7 +159,7 @@ aCenterRef.setObject(aPoint.lastResult())
 aCenter.setValue(aPointCoord.pnt())
 aPassedRef.setAttr(aPrevCenter)
 aPassed.setValue(aPrevCenter.pnt())
-aRadius = distancePointPoint(aPrevCenter, aPointCoord)
+aRadius = model.distancePointPoint(aPrevCenter, aPointCoord)
 aSession.finishOperation()
 assert (aSketchFeature.numberOfSubs() == 6)
 verifyPointCoordinates(aPointCoord, aPointCoodinates[0], aPointCoodinates[1])
@@ -183,7 +170,7 @@ model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 2)
 # Test 4. Create a circle as a macro-feature by center on a line and passed point on another circle
 #=========================================================================
 # get previous circle
-aPrevCircle = getLastCircle(aSketchFeature)
+aPrevCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
 aPrevCenter = geomDataAPI_Point2D(aPrevCircle.attribute("circle_center"))
 aPrevCenterXY = [aPrevCenter.x(), aPrevCenter.y()]
 aPrevRadius = aPrevCircle.real("circle_radius").value()
@@ -212,7 +199,7 @@ anExpectedCenter = [(aLineStart[0] + aLineEnd[0]) * 0.5, (aLineStart[1] + aLineE
 aCenter.setValue(anExpectedCenter[0], anExpectedCenter[1])
 aPassedRef.setObject(aPrevCircle.lastResult())
 aPassed.setValue(aPrevCenter.x() + aPrevRadius, aPrevCenter.y())
-aRadius = distancePointPoint(aCenter, aPassed)
+aRadius = model.distancePointPoint(aCenter, aPassed)
 aSession.finishOperation()
 assert (aSketchFeature.numberOfSubs() == 10)
 # check connected features do not change their positions
@@ -221,7 +208,7 @@ assert(aPrevCircle.real("circle_radius").value() == aPrevRadius)
 verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
 verifyPointCoordinates(aEndPnt, aLineEnd[0], aLineEnd[1])
 # verify newly created circle
-aCircle = getLastCircle(aSketchFeature)
+aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
 aCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center"))
 verifyPointCoordinates(aCenter, anExpectedCenter[0], anExpectedCenter[1])
 verifyPointOnLine(aCenter, aLine)
@@ -249,7 +236,9 @@ aPassed.setValue(aLineStart[0], aLineStart[1])
 aSession.finishOperation()
 aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1)
 assert aLastFeature.getKind() == "SketchMacroCircle", "ERROR: SketchMacroCircle has NOT expected to be valid"
+aSession.startOperation()
 aDocument.removeFeature(aCircle)
+aSession.finishOperation()
 assert (aSketchFeature.numberOfSubs() == 10)
 
 #=========================================================================
index 060127a349bc5bee8766e27a70013de1d3425388..8998bb931eac0e5f4524e1b8f1742f7ab07b8e46 100644 (file)
@@ -22,21 +22,11 @@ __updated__ = "2017-03-22"
 #=========================================================================
 TOLERANCE = 1.e-7
 
-def getLastCircle(theSketch):
-    """
-    obtains last feature from the sketch and generates error if the feature is not a circle
-    """
-    expectedKind = "SketchCircle"
-    for anIndex in range(theSketch.numberOfSubs() - 1, -1, -1):
-        aSub = theSketch.subFeature(anIndex)
-        if (aSub.getKind() == expectedKind):
-            return aSub
-
 def verifyLastCircle(theSketch, theX, theY, theR):
     """
     subroutine to verify position of last circle in the sketch
     """
-    aLastCircle = getLastCircle(theSketch)
+    aLastCircle = model.lastSubFeature(theSketch, "SketchCircle")
     aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center"))
     verifyPointCoordinates(aCenter, theX, theY)
     aRadius = aLastCircle.real("circle_radius")
@@ -47,14 +37,14 @@ def verifyPointCoordinates(thePoint, theX, theY):
 
 def verifyPointOnCircle(thePoint, theCircle):
     aCircleCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center"))
-    aDistCP = distancePointPoint(aCircleCenter, thePoint)
+    aDistCP = model.distancePointPoint(aCircleCenter, thePoint)
     aCircleRadius = theCircle.real("circle_radius").value()
     assert math.fabs(aDistCP - aCircleRadius) < TOLERANCE, "Point is not on circle, distance: {0}, radius of circle: {1}".format(aDistCP, aCircleRadius)
 
 def verifyTangentCircles(theCircle1, theCircle2):
     aCenter1 = geomDataAPI_Point2D(theCircle1.attribute("circle_center"))
     aCenter2 = geomDataAPI_Point2D(theCircle2.attribute("circle_center"))
-    aDistCC = distancePointPoint(aCenter1, aCenter2)
+    aDistCC = model.distancePointPoint(aCenter1, aCenter2)
     aRadius1 = theCircle1.real("circle_radius").value()
     aRadius2 = theCircle2.real("circle_radius").value()
     verifyTangentCircular(aDistCC, aRadius1, aRadius2)
@@ -63,9 +53,9 @@ def verifyTangentCircleArc(theCircle, theArc):
     aCircleCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center"))
     anArcCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
     anArcStart = geomDataAPI_Point2D(theArc.attribute("start_point"))
-    aDistCC = distancePointPoint(aCircleCenter, anArcCenter)
+    aDistCC = model.distancePointPoint(aCircleCenter, anArcCenter)
     aCircleRadius = theCircle.real("circle_radius").value()
-    anArcRadius = distancePointPoint(anArcCenter, anArcStart)
+    anArcRadius = model.distancePointPoint(anArcCenter, anArcStart)
     verifyTangentCircular(aDistCC, aCircleRadius, anArcRadius)
 
 def verifyTangentCircular(theDistBetweenCenters, theRadius1, theRadius2):
@@ -79,9 +69,6 @@ def verifyTangentCircleLine(theCircle, theLine):
     aDistCL = distancePointLine(aCenter, theLine)
     assert math.fabs(aDistCL - aRadius) < TOLERANCE, "Circle and line are not tangent"
 
-def distancePointPoint(thePoint1, thePoint2):
-    return thePoint1.pnt().distance(thePoint2.pnt())
-
 def distancePointLine(thePoint, theLine):
     aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy()
     aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy()
@@ -140,7 +127,7 @@ verifyLastCircle(aSketchFeature, expectedCenter[0], expectedCenter[1], expectedR
 # Test 2. Create a circle by three points coincident to other points
 #=========================================================================
 # get previous circle
-aPrevCircle = getLastCircle(aSketchFeature)
+aPrevCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
 aPrevCenter = geomDataAPI_Point2D(aPrevCircle.attribute("circle_center"))
 aPrevCenterXY = [aPrevCenter.x(), aPrevCenter.y()]
 aPrevCircleRadius = aPrevCircle.real("circle_radius").value()
@@ -150,7 +137,7 @@ aLineStart = [10., 0.]
 aLineEnd = [10., 50.]
 aSession.startOperation()
 aPoint = aSketchFeature.addFeature("SketchPoint")
-aPointCoord = geomDataAPI_Point2D(aPoint.attribute("PointCoordindates"))
+aPointCoord = geomDataAPI_Point2D(aPoint.attribute("PointCoordinates"))
 aPointCoord.setValue(aPointCoodinates[0], aPointCoodinates[1])
 aLine = aSketchFeature.addFeature("SketchLine")
 aStartPnt = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
@@ -183,7 +170,7 @@ verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1])
 verifyPointCoordinates(aPointCoord, aPointCoodinates[0], aPointCoodinates[1])
 verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
 # check newly created circle passes through the points
-aCircle = getLastCircle(aSketchFeature)
+aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
 verifyPointOnCircle(aPrevCenter, aCircle)
 verifyPointOnCircle(aPointCoord, aCircle)
 verifyPointOnCircle(aStartPnt, aCircle)
@@ -236,7 +223,7 @@ verifyPointCoordinates(anArcCenterPnt, anArcCenter[0], anArcCenter[1])
 verifyPointCoordinates(anArcStartPnt, anArcStart[0], anArcStart[1])
 verifyPointCoordinates(anArcEndPnt, anArcEnd[0], anArcEnd[1])
 # check newly created circle passes through the points
-aCircle = getLastCircle(aSketchFeature)
+aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
 verifyTangentCircles(aCircle, aPrevCircle)
 verifyTangentCircleArc(aCircle, anArc)
 verifyTangentCircleLine(aCircle, aLine)
index 52daff262dbdae4ee654dd088d7db8b6156885c3..4a78584aa365d924d9175727f43f545253614445 100644 (file)
@@ -49,21 +49,11 @@ def assertNotInitializedByThreePoints(theMacroCircle):
     assert (not aSecondPointRef.isInitialized())
     assert (not aThirdPointRef.isInitialized())
 
-def getLastCircle(theSketch):
-    """
-    obtains last feature from the sketch and generates error if the feature is not a circle
-    """
-    expectedKind = "SketchCircle"
-    for anIndex in range(theSketch.numberOfSubs() - 1, -1, -1):
-        aSub = theSketch.subFeature(anIndex)
-        if (aSub.getKind() == expectedKind):
-            return aSub
-
 def verifyLastCircle(theSketch, theX, theY, theR):
     """
     subroutine to verify position of last circle in the sketch
     """
-    aLastCircle = getLastCircle(theSketch)
+    aLastCircle = model.lastSubFeature(theSketch, "SketchCircle")
     aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center"))
     verifyPointCoordinates(aCenter, theX, theY)
     aRadius = aLastCircle.real("circle_radius")
@@ -72,9 +62,6 @@ def verifyLastCircle(theSketch, theX, theY, theR):
 def verifyPointCoordinates(thePoint, theX, theY):
     assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.attributeType(), thePoint.x(), thePoint.y(), theX, theY)
 
-def distancePointPoint(thePoint1, thePoint2):
-    return thePoint1.pnt().distance(thePoint2.pnt())
-
 
 #=========================================================================
 # Start of test
@@ -182,7 +169,7 @@ aPassedPointRef.setAttr(aLineEnd)
 aPassedPoint.setValue(aLineEnd.pnt())
 aSession.finishOperation()
 
-aRadius = distancePointPoint(aLineStart, aLineEnd)
+aRadius = model.distancePointPoint(aLineStart, aLineEnd)
 NB_FEATURES_EXPECTED = 4 # line, circle and two coincidences
 assert (aSketchFeature.numberOfSubs() == NB_FEATURES_EXPECTED), "Number of features in sketch {}, expected {}".format(aSketchFeature.numberOfSubs(), NB_FEATURES_EXPECTED)
 verifyLastCircle(aSketchFeature, aLineStart.x(), aLineStart.y(), aRadius)
index 59f353cb8f1e6c792f0216a3aa6ce315a2980190..a52ce5a5cc37af35de8cbc48f4a854411d880105 100644 (file)
@@ -75,9 +75,9 @@ def createSketch2(theSketch):
     allFeatures.append(aSketchLine)
     # Arc
     aSketchArc = theSketch.addFeature("SketchArc")
-    aStartPoint2 = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
-    aEndPoint2   = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
-    aCenterPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
+    aStartPoint2 = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
+    aEndPoint2   = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
+    aCenterPoint = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
     aCenterPoint.setValue(20., 10.)
     aStartPoint2.setValue(10., 10.)
     aEndPoint2.setValue(20., 0.)
@@ -104,15 +104,15 @@ def checkSmoothness(theSketch):
             checkArcLineSmoothness(aConnectedFeatures[1], aConnectedFeatures[0])
 
 def checkArcLineSmoothness(theArc, theLine):
-    aCenter = geomDataAPI_Point2D(theArc.attribute("ArcCenter"))
+    aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
     aDistance = distancePointLine(aCenter, theLine)
     aRadius = arcRadius(theArc)
     assert(math.fabs(aRadius - aDistance) < TOLERANCE)
 
 def checkArcArcSmoothness(theArc1, theArc2):
-    aCenter1 = geomDataAPI_Point2D(theArc1.attribute("ArcCenter"))
-    aCenter2 = geomDataAPI_Point2D(theArc2.attribute("ArcCenter"))
-    aDistance = distancePointPoint(aCenter1, aCenter2)
+    aCenter1 = geomDataAPI_Point2D(theArc1.attribute("center_point"))
+    aCenter2 = geomDataAPI_Point2D(theArc2.attribute("center_point"))
+    aDistance = model.distancePointPoint(aCenter1, aCenter2)
     aRadius1 = arcRadius(theArc1)
     aRadius2 = arcRadius(theArc2)
     aRadSum = aRadius1 + aRadius2
@@ -138,17 +138,14 @@ def connectedFeatures(theCoincidence):
     return [aFeatureA, aFeatureB]
 
 def arcRadius(theArc):
-    aCenter = geomDataAPI_Point2D(theArc.attribute("ArcCenter"))
-    aStart = geomDataAPI_Point2D(theArc.attribute("ArcStartPoint"))
-    return distancePointPoint(aCenter, aStart)
-
-def distancePointPoint(thePoint1, thePoint2):
-    return math.hypot(thePoint1.x() - thePoint2.x(), thePoint1.y() - thePoint2.y())
+    aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
+    aStart = geomDataAPI_Point2D(theArc.attribute("start_point"))
+    return model.distancePointPoint(aCenter, aStart)
 
 def distancePointLine(thePoint, theLine):
     aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint"))
     aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint"))
-    aLength = distancePointPoint(aLineStart, aLineEnd)
+    aLength = model.distancePointPoint(aLineStart, aLineEnd)
 
     aDir1x, aDir1y = aLineEnd.x() - aLineStart.x(), aLineEnd.y() - aLineStart.y()
     aDir2x, aDir2y = thePoint.x() - aLineStart.x(), thePoint.y() - aLineStart.y()
index 15b101e444e24833e6a0a23ef2e2c0e2b66c006b..9653c3cf006837da06f346f863ca51e4382e6800 100644 (file)
@@ -14,15 +14,15 @@ from salome.shaper import model
 __updated__ = "2017-03-06"
 
 def isArcLineSmooth(theArc, theLine, theTolerance):
-  aCenter = geomDataAPI_Point2D(theArc.attribute("ArcCenter"))
+  aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
   aDistance = distancePointLine(aCenter, theLine)
   aRadius = arcRadius(theArc)
   return math.fabs(aRadius - aDistance) < theTolerance
 
 def isArcArcSmooth(theArc1, theArc2, theTolerance):
-  aCenter1 = geomDataAPI_Point2D(theArc1.attribute("ArcCenter"))
-  aCenter2 = geomDataAPI_Point2D(theArc2.attribute("ArcCenter"))
-  aDistance = distancePointPoint(aCenter1, aCenter2)
+  aCenter1 = geomDataAPI_Point2D(theArc1.attribute("center_point"))
+  aCenter2 = geomDataAPI_Point2D(theArc2.attribute("center_point"))
+  aDistance = model.distancePointPoint(aCenter1, aCenter2)
   aRadius1 = arcRadius(theArc1)
   aRadius2 = arcRadius(theArc2)
   aRadSum = aRadius1 + aRadius2
@@ -30,17 +30,14 @@ def isArcArcSmooth(theArc1, theArc2, theTolerance):
   return math.fabs(aDistance - aRadSum) < theTolerance or math.fabs(aDistance - aRadDiff) < theTolerance
 
 def arcRadius(theArc):
-  aCenter = geomDataAPI_Point2D(theArc.attribute("ArcCenter"))
-  aStart = geomDataAPI_Point2D(theArc.attribute("ArcStartPoint"))
-  return distancePointPoint(aCenter, aStart)
-
-def distancePointPoint(thePoint1, thePoint2):
-  return math.hypot(thePoint1.x() - thePoint2.x(), thePoint1.y() - thePoint2.y())
+  aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
+  aStart = geomDataAPI_Point2D(theArc.attribute("start_point"))
+  return model.distancePointPoint(aCenter, aStart)
 
 def distancePointLine(thePoint, theLine):
   aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint"))
   aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint"))
-  aLength = distancePointPoint(aLineStart, aLineEnd)
+  aLength = model.distancePointPoint(aLineStart, aLineEnd)
   aDir1x, aDir1y = aLineEnd.x() - aLineStart.x(), aLineEnd.y() - aLineStart.y()
   aDir2x, aDir2y = thePoint.x() - aLineStart.x(), thePoint.y() - aLineStart.y()
   aCross = aDir1x * aDir2y - aDir1y * aDir2x
diff --git a/src/SketchPlugin/Test/TestMirror.py b/src/SketchPlugin/Test/TestMirror.py
new file mode 100644 (file)
index 0000000..af141ae
--- /dev/null
@@ -0,0 +1,238 @@
+"""
+    TestConstraintMirror.py
+    Unit test of SketchPlugin_ConstraintMirror class
+
+    SketchPlugin_ConstraintMirror
+        static const std::string MY_CONSTRAINT_MIRROR_ID("SketchConstraintMirror");
+        data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+        data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefListAttr::typeId());
+        data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefListAttr::typeId());
+
+"""
+from GeomDataAPI import *
+from ModelAPI import *
+import math
+from salome.shaper import model
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+
+__updated__ = "2015-03-17"
+
+#=========================================================================
+# Auxiliary functions
+#=========================================================================
+def normalize(theDir):
+    aLen = math.hypot(theDir[0], theDir[1])
+    if aLen < 1.e-10:
+        aLen = 1.0
+    return [theDir[0] / aLen, theDir[1] / aLen]
+
+def checkMirror(theListInit, theListMirr, theMirrorLine):
+    TOL = 6.e-5
+    aListSize = theListInit.size()
+
+    aLineStartPoint = geomDataAPI_Point2D(theMirrorLine.attribute("StartPoint"))
+    aLineEndPoint = geomDataAPI_Point2D(theMirrorLine.attribute("EndPoint"))
+    aLineDir = [aLineEndPoint.x() - aLineStartPoint.x(), aLineEndPoint.y() - aLineStartPoint.y()]
+    aLineDir = normalize(aLineDir)
+
+    for ind in range(0, aListSize):
+        aFeatureB = ModelAPI_Feature.feature(theListInit.object(ind))
+        aFeatureC = ModelAPI_Feature.feature(theListMirr.object(ind))
+        assert(aFeatureB is not None)
+        assert(aFeatureC is not None)
+        assert(aFeatureB.getKind() == aFeatureC.getKind())
+
+        anAttributes = []
+        if (aFeatureB.getKind() == "SketchLine"):
+            anAttributes = ['StartPoint', 'EndPoint']
+        elif (aFeatureB.getKind() == "SketchArc"):
+            anAttributes = ['center_point', 'start_point', 'end_point']
+
+        for key in anAttributes:
+            aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key))
+            aPointC = geomDataAPI_Point2D(aFeatureC.attribute(key))
+            aDir = [aPointC.x() - aPointB.x(), aPointC.y() - aPointB.y()]
+            aDir = normalize(aDir)
+            aDot = aLineDir[0] * aDir[0] + aLineDir[1] * aDir[1]
+            assert math.fabs(aDot) < TOL, "aDot = {0}".format(aDot)
+            aDir[0] = aLineEndPoint.x() - 0.5 * (aPointB.x() + aPointC.x())
+            aDir[1] = aLineEndPoint.y() - 0.5 * (aPointB.y() + aPointC.y())
+            aCross = aLineDir[0] * aDir[1] - aLineDir[1] * aDir[0]
+            assert math.fabs(aCross) < TOL, "aCross = {0}".format(aCross)
+
+
+#=========================================================================
+# Start of test
+#=========================================================================
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+aSession.startOperation()
+aSketchCommonFeature = aDocument.addFeature("Sketch")
+aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+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)
+aSession.finishOperation()
+#=========================================================================
+# Creation of an arc and two lines
+#=========================================================================
+# Arc
+aSession.startOperation()
+aSketchArc1 = aSketchFeature.addFeature("SketchArc")
+anArcCentr = geomDataAPI_Point2D(aSketchArc1.attribute("center_point"))
+anArcCentr.setValue(10., 10.)
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("start_point"))
+anArcStartPoint.setValue(0., 50.)
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("end_point"))
+anArcEndPoint.setValue(50., 0.)
+aSession.finishOperation()
+# Line 1
+aSession.startOperation()
+aSketchLine1 = aSketchFeature.addFeature("SketchLine")
+aLine1StartPoint = geomDataAPI_Point2D(aSketchLine1.attribute("StartPoint"))
+aLine1EndPoint = geomDataAPI_Point2D(aSketchLine1.attribute("EndPoint"))
+aLine1StartPoint.setValue(0., 50.)
+aLine1EndPoint.setValue(0., 100.)
+aSession.finishOperation()
+# Line 2
+aSession.startOperation()
+aSketchLine2 = aSketchFeature.addFeature("SketchLine")
+aLine2StartPoint = geomDataAPI_Point2D(aSketchLine2.attribute("StartPoint"))
+aLine2EndPoint = geomDataAPI_Point2D(aSketchLine2.attribute("EndPoint"))
+aLine2StartPoint.setValue(50., 0.)
+aLine2EndPoint.setValue(100., 0.)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 13)
+#=========================================================================
+# Link arc points and lines points by the coincidence constraint
+#=========================================================================
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setAttr(anArcStartPoint)
+reflistB.setAttr(aLine1StartPoint)
+aConstraint.execute()
+aSession.finishOperation()
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setAttr(anArcEndPoint)
+reflistB.setAttr(aLine2StartPoint)
+aConstraint.execute()
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 9)
+#=========================================================================
+# Add tangency constraint and check correctness
+#=========================================================================
+aSession.startOperation()
+aTangency = aSketchFeature.addFeature("SketchConstraintTangent")
+aRefObjectA = aTangency.refattr("ConstraintEntityA")
+aRefObjectB = aTangency.refattr("ConstraintEntityB")
+anObjectA = modelAPI_ResultConstruction(aSketchArc1.lastResult())
+anObjectB = modelAPI_ResultConstruction(aSketchLine1.lastResult())
+assert (anObjectA is not None)
+assert (anObjectB is not None)
+aRefObjectA.setObject(anObjectA)
+aRefObjectB.setObject(anObjectB)
+aTangency.execute()
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 8)
+#=========================================================================
+# Create mirror line
+#=========================================================================
+aSession.startOperation()
+aMirrorLine = aSketchFeature.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aMirrorLine.attribute("StartPoint"))
+aLineEndPoint = geomDataAPI_Point2D(aMirrorLine.attribute("EndPoint"))
+aLineStartPoint.setValue(100., 0.)
+aLineEndPoint.setValue(100., 100.)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 12)
+#=========================================================================
+# Make mirror for objects created above
+#=========================================================================
+aSession.startOperation()
+aMirror = aSketchFeature.addFeature("SketchConstraintMirror")
+aRefObjectA = aMirror.refattr("ConstraintEntityA")
+aRefObjectA.setObject(modelAPI_ResultConstruction(aMirrorLine.firstResult()))
+aRefListInitial = aMirror.reflist("ConstraintMirrorList")
+aRefListInitial.append(aSketchLine1.lastResult())
+aRefListInitial.append(aSketchArc1.lastResult())
+aRefListInitial.append(aSketchLine2.lastResult())
+aMirror.execute()
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 12)
+#=========================================================================
+# Verify the simmetricity of all mirrored objects
+#=========================================================================
+aRefListB = aMirror.reflist("ConstraintEntityB")
+aRefListC = aMirror.reflist("ConstraintEntityC")
+assert (aRefListB.size() == 3)
+assert (aRefListC.size() == 3)
+checkMirror(aRefListB, aRefListC, aMirrorLine)
+assert (model.dof(aSketchFeature) == 12)
+
+#=========================================================================
+# Remove object from mirror
+#=========================================================================
+aSession.startOperation()
+aRefListInitial.remove(aSketchLine2.lastResult())
+aSession.finishOperation()
+assert (aRefListB.size() == 2)
+assert (aRefListC.size() == 2)
+checkMirror(aRefListB, aRefListC, aMirrorLine)
+assert (model.dof(aSketchFeature) == 12)
+
+#=========================================================================
+# Clear list of mirrored features
+#=========================================================================
+aSession.startOperation()
+aRefListInitial.clear()
+assert (aRefListB.size() == 0)
+assert (aRefListC.size() == 0)
+# add arc once again
+aRefListInitial.append(aSketchArc1.lastResult())
+aSession.finishOperation()
+assert (aRefListB.size() == 1)
+assert (aRefListC.size() == 1)
+checkMirror(aRefListB, aRefListC, aMirrorLine)
+assert (model.dof(aSketchFeature) == 12)
+
+#=========================================================================
+# Create distance between original and mirrored entities (check the error appears)
+#=========================================================================
+aSketchErrorAttr = aSketchFeature.string("SolverError")
+assert len(aSketchErrorAttr.value()) == 0, "Sketch failed with error: {}".format(aSketchErrorAttr.value())
+aMirroredArc = model.lastSubFeature(aSketchFeature, "SketchArc")
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintDistance")
+refAttrA = aConstraint.refattr("ConstraintEntityA")
+refAttrB = aConstraint.refattr("ConstraintEntityB")
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("start_point"))
+aMirroredArcStartPoint = geomDataAPI_Point2D(aMirroredArc.attribute("start_point"))
+refAttrA.setAttr(anArcStartPoint)
+refAttrB.setAttr(aMirroredArcStartPoint)
+aConstraint.real("ConstraintValue").setValue(200.)
+aSession.finishOperation()
+print "Sketch error : {}".format(aSketchErrorAttr.value())
+assert len(aSketchErrorAttr.value()) != 0, "ERROR: Sketch has not been failed as expected"
+aSession.startOperation()
+aDocument.removeFeature(aConstraint)
+aSession.finishOperation()
+
+#=========================================================================
+# End of test
+#=========================================================================
+
+assert(model.checkPythonDump())
index 7328e497cc6774babc28be4f4a09bc5523f781c5..905117ae394ef5908c7a39abbed283f7f8f2221b 100644 (file)
@@ -26,9 +26,9 @@ def createSketch(theSketch):
     allFeatures = []
     # Create arc
     aSketchArc = theSketch.addFeature("SketchArc")
-    aCenter     = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
-    aStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
-    aEndPoint   = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+    aCenter     = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
+    aStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
+    aEndPoint   = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
     aCenter.setValue(5., 5.)
     aStartPoint.setValue(10., 5.)
     aEndPoint.setValue(5., 10.)
@@ -69,9 +69,9 @@ def checkRotation(theObjects, theNbObjects, theCenterX, theCenterY, theAngle):
             anAttributes.append('StartPoint')
             anAttributes.append('EndPoint')
         elif (feat.getKind() == "SketchArc"):
-            anAttributes.append('ArcCenter')
-            anAttributes.append('ArcStartPoint')
-            anAttributes.append('ArcEndPoint')
+            anAttributes.append('center_point')
+            anAttributes.append('start_point')
+            anAttributes.append('end_point')
             
         for attr in anAttributes:
             aPoint1 = geomDataAPI_Point2D(feat.attribute(attr))
@@ -127,7 +127,7 @@ ANGLE = 30.
 #=========================================================================
 aSession.startOperation()
 aRotationPoint = aSketchFeature.addFeature("SketchPoint")
-aRotationPointPoint = geomDataAPI_Point2D(aRotationPoint.attribute("PointCoordindates"))
+aRotationPointPoint = geomDataAPI_Point2D(aRotationPoint.attribute("PointCoordinates"))
 aRotationPointPoint.setValue(CENTER_X, CENTER_Y)
 aSession.finishOperation()
 assert(model.dof(aSketchFeature) == 7)
index 80eb90ed108f2315aa34c739d78c5802e4ee3ed1..639fd4e30a2a69cce9da2856b84ff45146156a57 100644 (file)
@@ -25,9 +25,9 @@ def createSketch(theSketch):
     allFeatures = []
     # Create arc
     aSketchArc = theSketch.addFeature("SketchArc")
-    aCenter     = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
-    aStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
-    aEndPoint   = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+    aCenter     = geomDataAPI_Point2D(aSketchArc.attribute("center_point"))
+    aStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("start_point"))
+    aEndPoint   = geomDataAPI_Point2D(aSketchArc.attribute("end_point"))
     aCenter.setValue(5., 5.)
     aStartPoint.setValue(10., 5.)
     aEndPoint.setValue(5., 10.)
@@ -66,9 +66,9 @@ def checkTranslation(theObjects, theNbObjects, theDeltaX, theDeltaY):
             anAttributes.append('StartPoint')
             anAttributes.append('EndPoint')
         elif (feat.getKind() == "SketchArc"):
-            anAttributes.append('ArcCenter')
-            anAttributes.append('ArcStartPoint')
-            anAttributes.append('ArcEndPoint')
+            anAttributes.append('center_point')
+            anAttributes.append('start_point')
+            anAttributes.append('end_point')
             
         for attr in anAttributes:
              aPoint1 = geomDataAPI_Point2D(feat.attribute(attr))
index 9477cdc741d0b609308b00ebd5cc70032369e669..9183aacb578ce9eae0cd405429668c04f1bf18d8 100644 (file)
@@ -43,15 +43,15 @@ aLineStart.setValue(10., 10.)
 aLineEnd.setValue(40., 30.)
 
 aCircle = aSketchFeature.addFeature("SketchCircle")
-aCircleCenter = geomDataAPI_Point2D(aCircle.attribute("CircleCenter"))
-aCircleRadius = aCircle.real("CircleRadius")
+aCircleCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center"))
+aCircleRadius = aCircle.real("circle_radius")
 aCircleCenter.setValue(-25., -25)
 aCircleRadius.setValue(25.)
 
 anArc = aSketchFeature.addFeature("SketchArc")
-anArcCenter = geomDataAPI_Point2D(anArc.attribute("ArcCenter"))
-anArcStart = geomDataAPI_Point2D(anArc.attribute("ArcStartPoint"))
-anArcEnd = geomDataAPI_Point2D(anArc.attribute("ArcEndPoint"))
+anArcCenter = geomDataAPI_Point2D(anArc.attribute("center_point"))
+anArcStart = geomDataAPI_Point2D(anArc.attribute("start_point"))
+anArcEnd = geomDataAPI_Point2D(anArc.attribute("end_point"))
 anArcCenter.setValue(10., 10.)
 anArcStart.setValue(50., 0.)
 anArcEnd.setValue(0., 50.)
@@ -100,16 +100,16 @@ assert(math.fabs(aProjLineEnd.y() - aLineEnd.y()) < 1.e-10)
 
 aProjCircle = ModelAPI_Feature.feature(aCircleProjector.refattr("ProjectedFeature").object())
 assert(aProjCircle)
-aProjCircleCenter = geomDataAPI_Point2D(aProjCircle.attribute("CircleCenter"))
-aProjCircleRadius = aProjCircle.real("CircleRadius")
+aProjCircleCenter = geomDataAPI_Point2D(aProjCircle.attribute("circle_center"))
+aProjCircleRadius = aProjCircle.real("circle_radius")
 assert(math.fabs(aProjCircleCenter.x() - aCircleCenter.x()) < 1.e-10)
 assert(math.fabs(aProjCircleCenter.y() - aCircleCenter.y()) < 1.e-10)
 assert(math.fabs(aProjCircleRadius.value() - aCircleRadius.value()) < 1.e-10)
 
 aProjArc = ModelAPI_Feature.feature(anArcProjector.refattr("ProjectedFeature").object())
-aProjArcCenter = geomDataAPI_Point2D(aProjArc.attribute("ArcCenter"))
-aProjArcStart = geomDataAPI_Point2D(aProjArc.attribute("ArcStartPoint"))
-aProjArcEnd = geomDataAPI_Point2D(aProjArc.attribute("ArcEndPoint"))
+aProjArcCenter = geomDataAPI_Point2D(aProjArc.attribute("center_point"))
+aProjArcStart = geomDataAPI_Point2D(aProjArc.attribute("start_point"))
+aProjArcEnd = geomDataAPI_Point2D(aProjArc.attribute("end_point"))
 assert(math.fabs(aProjArcCenter.x() - anArcCenter.x()) < 1.e-10)
 assert(math.fabs(aProjArcCenter.y() - anArcCenter.y()) < 1.e-10)
 assert(math.fabs(aProjArcStart.x() - anArcStart.x()) < 1.e-10)
index 0d3df2d144fe609d27155688dd93cdbba7b70482..382a53418c6eaf2e23a89cce9de8f70276ed3de4 100644 (file)
@@ -46,7 +46,7 @@ assert (len(aSketchReflist.list()) == 0)
 # aSketchPoint = aDocument.addFeature("SketchPoint")
 aSketchPoint = aSketchFeature.addFeature("SketchPoint")
 assert (aSketchPoint.getKind() == "SketchPoint")
-coords = geomDataAPI_Point2D(aSketchPoint.attribute("PointCoordindates"))
+coords = geomDataAPI_Point2D(aSketchPoint.attribute("PointCoordinates"))
 assert (not coords.isInitialized())
 # Simulate SketchPlugin_Point::move(...)
 coords.setValue(10., 10.)
@@ -56,7 +56,7 @@ aSession.finishOperation()
 aSketchReflist = aSketchFeature.reflist("Features")
 assert (aSketchReflist.size() == 1)
 assert (len(aSketchReflist.list()) == 1)
-coords = geomDataAPI_Point2D(aSketchPoint.attribute("PointCoordindates"))
+coords = geomDataAPI_Point2D(aSketchPoint.attribute("PointCoordinates"))
 assert (coords.x() == 10.0)
 assert (coords.y() == 10.0)
 #=========================================================================
diff --git a/src/SketchPlugin/Test/TestTrimArc07.py b/src/SketchPlugin/Test/TestTrimArc07.py
new file mode 100644 (file)
index 0000000..b94d921
--- /dev/null
@@ -0,0 +1,66 @@
+from salome.shaper import model
+
+from ModelAPI import *
+from GeomDataAPI import *
+from ModelGeomAlgo import ModelGeomAlgo_Point2D
+from salome.shaper import geom
+import math
+
+TOLERANCE = 1.e-7
+
+SketchLineId = 'SketchLine'
+SketchArcId = 'SketchArc'
+SketchConstraintCoincidenceId = 'SketchConstraintCoincidence'
+SketchConstraintEqualId = 'SketchConstraintEqual'
+
+aSession = ModelAPI_Session.get()
+model.begin()
+partSet = model.moduleDocument()
+Part = model.addPart(partSet)
+Part_doc = Part.document()
+
+# Test1:begin split on arc with coincident point and intersection line : smaller part
+Sketch = model.addSketch(Part_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch.addArc(50, 50, 30, 50, 50, 70, False)
+SketchArc_2 = Sketch.addArc(75, 80, 50, 70, 100, 100, True)
+SketchLine = Sketch.addLine(60, 31, 60, 130)
+SketchLine_2 = Sketch.addLine(10, 40, 90, 40)
+
+# correct start point of SketchLine to belong the arc for trim
+Intersected_Points = ModelGeomAlgo_Point2D.getSetOfPntIntersectedShape(SketchArc_1.feature(), FeatureList([SketchLine.feature()]))
+assert(len(Intersected_Points) == 2)
+if Intersected_Points[0].y() < Intersected_Points[1].y():
+  IntersectionPoint = Intersected_Points[0]
+else:
+  IntersectionPoint = Intersected_Points[1]
+
+SketchLine.startPoint().setValue(IntersectionPoint.x(), IntersectionPoint.y())
+
+SketchConstraintCoincidence_1_1 = Sketch.setCoincident(SketchArc_1.endPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_1_2 = Sketch.setCoincident(SketchArc_1.results()[1], SketchLine.startPoint())
+model.do()
+
+
+#find point on arc, where to perform trim
+SketchLine_intersecting = Sketch.addLine(50, 50, 100, 0)
+Geom_Points = ModelGeomAlgo_Point2D.getSetOfPntIntersectedShape(SketchArc_1.feature(), FeatureList([SketchLine_intersecting.feature()]))
+assert(len(Geom_Points) == 1)
+ModelAPI.removeFeaturesAndReferences(FeatureSet([SketchLine_intersecting.feature()]))
+model.do()
+GeomPoint = Geom_Points[0]
+
+model.do()
+SketchTrim = Sketch.addTrim(SketchArc_1, Sketch.to2D(GeomPoint))
+SketchTrim.execute()
+
+
+# Another case
+#GeomPoint = geom.Pnt2d(60, 50)
+#model.do()
+#SketchTrim = Sketch.addTrim(SketchArc_1, GeomPoint)
+#SketchTrim.execute()
+
+
+model.end()
+
+#assert(model.checkPythonDump())
index cc2f909a3665397e8247553c8172333dedf6ca41..5256326fb12a3926cc7c869e18c0cd58c5b602fe 100644 (file)
@@ -66,17 +66,6 @@ for SubIndex in range(SketchFeatures.numberOfSubs()):
 assert(idList_after.count(SketchLineId) == 3)
 assert(idList_after.count(SketchConstraintCoincidenceId) == 2)
 
-#check if line points are the same
-assert(SketchLine_1.startPoint().x() == 200)
-assert(SketchLine_1.startPoint().y() == 20)
-assert(SketchLine_1.endPoint().x() == 20)
-assert(SketchLine_1.endPoint().y() == 70)
-
-assert(SketchLine_3.startPoint().x() == -10)
-assert(SketchLine_3.startPoint().y() == 190)
-assert(SketchLine_3.endPoint().x() == 90)
-assert(SketchLine_3.endPoint().y() == 50)
-
 model.end()
 
 #assert(model.checkPythonDump())
diff --git a/src/SketchPlugin/Test/TestTrimLine02.py b/src/SketchPlugin/Test/TestTrimLine02.py
new file mode 100644 (file)
index 0000000..9730f8e
--- /dev/null
@@ -0,0 +1,88 @@
+from salome.shaper import model
+
+from ModelAPI import *
+from GeomDataAPI import *
+from ModelGeomAlgo import ModelGeomAlgo_Point2D
+from salome.shaper import geom
+import math
+
+TOLERANCE = 1.e-7
+
+SketchLineId = 'SketchLine'
+SketchConstraintCoincidenceId = 'SketchConstraintCoincidence'
+
+aSession = ModelAPI_Session.get()
+model.begin()
+partSet = model.moduleDocument()
+Part = model.addPart(partSet)
+Part_doc = Part.document()
+
+# Test1:begin split on arc with coincident point and intersection line : smaller part
+Sketch = model.addSketch(Part_doc, model.defaultPlane("XOZ"))
+# Test of inverted Arc
+SketchLine_1 = Sketch.addLine(10, 80, 40, 10)
+SketchLine_2 = Sketch.addLine(40, 10, 70, 80)
+SketchLine_3 = Sketch.addLine(70, 80, 100, 10)
+SketchLine_4 = Sketch.addLine(100, 10, 130, 80)
+
+SketchLine_intersecting = Sketch.addLine(10, 50, 130, 50)
+
+SketchConstraintCoincidence_1_1 = Sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_1_2 = Sketch.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_1_3 = Sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+
+GeomPoint = geom.Pnt2d(40, 50)
+
+#check number of features before trim
+Sketch_feature = featureToCompositeFeature(Sketch.feature())
+idList_before = []
+for index in range(Sketch_feature.numberOfSubs()):
+  idList_before.append(Sketch_feature.subFeature(index).getKind())
+
+assert(idList_before.count(SketchLineId) == 5)
+assert(idList_before.count(SketchConstraintCoincidenceId) == 3)
+
+#perform trim
+SketchTrim = Sketch.addTrim(SketchLine_intersecting, GeomPoint)
+SketchTrim.execute()
+model.do()
+
+#check number of features after trim
+SketchFeatures = featureToCompositeFeature(Sketch.feature())
+idList_after = []
+
+LinesList = FeatureList()
+for SubIndex in range(SketchFeatures.numberOfSubs()):
+    SubFeature = SketchFeatures.subFeature(SubIndex)
+    idList_after.append(SubFeature.getKind())
+    if SubFeature.getKind() == SketchLineId:
+      LinesList.append(SubFeature)
+
+assert(idList_after.count(SketchLineId) == 6)
+assert(idList_after.count(SketchConstraintCoincidenceId) == 5)
+
+
+#check lines intersection to the source line
+SketchLine_intersecting_1 = Sketch.addLine(15, 55, 15, 40)
+SketchLine_intersecting_2 = Sketch.addLine(40, 55, 40, 40)
+SketchLine_intersecting_3 = Sketch.addLine(70, 55, 70, 40)
+SketchLine_intersecting_4 = Sketch.addLine(100, 55, 100, 40)
+SketchLine_intersecting_5 = Sketch.addLine(125, 55, 125, 40)
+
+Intersection_Points_1 = ModelGeomAlgo_Point2D.getSetOfPntIntersectedShape(SketchLine_intersecting_1.feature(), LinesList)
+Intersection_Points_2 = ModelGeomAlgo_Point2D.getSetOfPntIntersectedShape(SketchLine_intersecting_2.feature(), LinesList)
+Intersection_Points_3 = ModelGeomAlgo_Point2D.getSetOfPntIntersectedShape(SketchLine_intersecting_3.feature(), LinesList)
+Intersection_Points_4 = ModelGeomAlgo_Point2D.getSetOfPntIntersectedShape(SketchLine_intersecting_4.feature(), LinesList)
+Intersection_Points_5 = ModelGeomAlgo_Point2D.getSetOfPntIntersectedShape(SketchLine_intersecting_5.feature(), LinesList)
+
+assert(len(Intersection_Points_1) == 1)
+assert(len(Intersection_Points_2) == 0)
+assert(len(Intersection_Points_3) == 1)
+assert(len(Intersection_Points_4) == 1)
+assert(len(Intersection_Points_5) == 1)
+
+#check if line points are the same
+
+model.end()
+
+#assert(model.checkPythonDump())
index ec0ed952117a6fc6e7a84d7651b2e42acb5042a7..57d57f82e1b32f2dd299ed30c7e7fabd9f209c4a 100644 (file)
@@ -32,7 +32,7 @@
 
       <!-- SketchPoint -->
       <feature id="SketchPoint" title="Point" tooltip="Create point" icon="icons/Sketch/point.png">
-        <sketch-2dpoint_selector id="PointCoordindates" accept_expressions="0" title="Point" tooltip="Point coordinates"
+        <sketch-2dpoint_selector id="PointCoordinates" accept_expressions="0" title="Point" tooltip="Point coordinates"
                                  enable_value="enable_by_preferences"/>
         <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
       </feature>
@@ -76,7 +76,7 @@
                icon="icons/Sketch/circle.png"
                title="Circle"
                tooltip="Create circle">
-        <toolbox id="circle_type" modified_in_edit="false">
+        <toolbox id="circle_type" modified_in_edit="edit_circle_type">
           <box id="circle_type_by_center_and_passed_points"
                icon="icons/Sketch/circle_pt_rad_32x32.png"
                title="Center and passed points">
         title="Arc"
         tooltip="Create arc"
         icon="icons/Sketch/arc.png">
-        <toolbox id="arc_type">
+        <toolbox id="arc_type" modified_in_edit="edit_arc_type">
           <box id="by_center_and_points"
                icon="icons/Sketch/arc_base_32x32.png"
                title="Center and two points">
                                      accept_expressions="0"
                                      enable_value="enable_by_preferences">
               <validator id="SketchPlugin_DifferentReference" parameters="start_point_ref,end_point_ref"/>
-              <validator id="SketchPlugin_ArcEndPointValidator" parameters="end_point_ref"/>
             </sketch-2dpoint_selector>
             <sketch-2dpoint_selector id="passed_point"
                                      reference_attribute="passed_point_ref"
                icon="icons/Sketch/split.png">
         <sketch_sub_shape_selector
             id="ConstraintValue"
-            label="Split feature"
-            tooltip="Select feature for split"
+            label="Segment"
+            tooltip="Select segment for split"
             shape_types="edge"
             use_external="false"
             use_graphic_intersection="false">
                icon="icons/Sketch/trim.png">
         <sketch_feature_point_selector
             id="SelectedObject"
-            label="Split feature"
-            tooltip="Select feature for split"
+            label="Segment"
+            tooltip="Select segment for trim"
             shape_types="edge"
             use_external="false"
             use_graphic_intersection="true">
index 2be2d62b5ac9bc0472d6ecc262b4f4d06c8c9037..47d783dcec8649e042feedd37b1847b16d686811 100644 (file)
@@ -10,6 +10,7 @@
 
 PlaneGCSSolver_Solver::PlaneGCSSolver_Solver()
   : myEquationSystem(new GCS::System),
+    myDiagnoseBeforeSolve(false),
     myConfCollected(false),
     myDOF(0)
 {
@@ -52,8 +53,10 @@ double* PlaneGCSSolver_Solver::createParameter()
 {
   double* aResult = new double(0);
   myParameters.push_back(aResult);
-  if (myDOF >= 0)
-    ++myDOF;
+  if (myConstraints.empty() && myDOF >= 0)
+    ++myDOF; // calculate DoF by hand if and only if there is no constraints yet
+  else
+    myDiagnoseBeforeSolve = true;
   return aResult;
 }
 
@@ -78,17 +81,18 @@ PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
     return STATUS_INCONSISTENT;
 
   Events_LongOp::start(this);
+  if (myDiagnoseBeforeSolve)
+    diagnose();
   // solve equations
   GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
   Events_LongOp::end(this);
 
-  GCS::VEC_I aRedundant;
-  myEquationSystem->getRedundant(aRedundant);
-  if (!aRedundant.empty()) {
-    collectConflicting();
-    if (!myConflictingIDs.empty())
-      aResult = GCS::Failed;
-  }
+  // collect information about conflicting constraints every time,
+  // sometimes solver reports about succeeded recalculation but has conflicting constraints
+  // (for example, apply horizontal constraint for a copied feature)
+  collectConflicting();
+  if (!myConflictingIDs.empty())
+    aResult = GCS::Failed;
 
   SolveStatus aStatus;
   if (aResult == GCS::Failed)
@@ -130,6 +134,13 @@ void PlaneGCSSolver_Solver::collectConflicting()
 int PlaneGCSSolver_Solver::dof()
 {
   if (myDOF < 0 && !myConstraints.empty())
-    solve();
+    diagnose();
   return myDOF;
 }
+
+void PlaneGCSSolver_Solver::diagnose()
+{
+  myEquationSystem->declareUnknowns(myParameters);
+  myDOF = myEquationSystem->diagnose();
+  myDiagnoseBeforeSolve = false;
+}
index 4da9e60dc5aa116ed4db176f28dc0b1d6f52b323..a5a411dfa4fb4e366a03cd6fb6df21e66fd34e85 100644 (file)
@@ -52,6 +52,9 @@ public:
   /// \brief Check the constraint is conflicted with others
   bool isConflicting(const ConstraintID& theConstraint) const;
 
+  /// \brief Check conflicting/redundant constraints and DoF
+  void diagnose();
+
   /// \brief Degrees of freedom
   int dof();
 
@@ -65,9 +68,9 @@ private:
   ConstraintMap                myConstraints;    ///< list of constraints
 
   std::shared_ptr<GCS::System> myEquationSystem; ///< set of equations for solving in FreeGCS
+  bool                         myDiagnoseBeforeSolve; ///< is the diagnostic necessary
 
   GCS::SET_I                   myConflictingIDs; ///< list of IDs of conflicting constraints
-
   /// specifies the conflicting constraints are already collected
   bool                         myConfCollected;
 
index 472f4add7ccb80c7e4041f1171191d00e225c9ca..96235587d0bd0f2b4bd96d4c01f8bcba4131ce79 100644 (file)
@@ -57,6 +57,10 @@ void PlaneGCSSolver_Storage::addTemporaryConstraint(
   if (myConstraintMap.empty())
     return; // no need to process temporary constraints if there is no active constraint
 
+  // before adding movement constraint to solver, re-check its DOF
+  if (mySketchSolver->dof() == 0)
+    mySketchSolver->diagnose();
+
   theSolverConstraint->setId(CID_MOVEMENT);
   constraintsToSolver(theSolverConstraint, mySketchSolver);
 }
@@ -147,10 +151,11 @@ static bool isCopyInMulti(std::shared_ptr<SketchPlugin_Feature> theFeature)
 
 bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce)
 {
+  bool sendNotify = false;
   bool isUpdated = false;
   EntityWrapperPtr aRelated = entity(theFeature);
   if (aRelated) // send signal to subscribers
-    notify(theFeature);
+    sendNotify = true;
   else { // Feature is not exist, create it
     std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
         std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
@@ -189,6 +194,10 @@ bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce)
         (*anAttrIt)->attributeType() == ModelAPI_AttributeDouble::typeId())
       isUpdated = update(*anAttrIt) || isUpdated;
 
+  // send notification to listeners due to at least one attribute is changed
+  if (sendNotify && isUpdated)
+    notify(theFeature);
+
   // update arc
   if (aRelated && aRelated->type() == ENTITY_ARC) {
     /// TODO: this code should be shared with FeatureBuilder somehow
@@ -354,7 +363,7 @@ void PlaneGCSSolver_Storage::removeParameters(const GCS::SET_pD& theParams)
 }
 
 // indicates attribute containing in the external feature
-bool isExternalAttribute(const AttributePtr& theAttribute)
+static bool isExternalAttribute(const AttributePtr& theAttribute)
 {
   if (!theAttribute)
     return false;
@@ -363,10 +372,19 @@ bool isExternalAttribute(const AttributePtr& theAttribute)
   return aSketchFeature.get() && aSketchFeature->isExternal();
 }
 
+static void addOwnerToSet(const AttributePtr& theAttribute, std::set<FeaturePtr>& theFeatures)
+{
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+  if (anOwner)
+    theFeatures.insert(anOwner);
+}
+
 void PlaneGCSSolver_Storage::refresh() const
 {
   const double aTol = 1000. * tolerance; // tolerance to prevent frequent updates
 
+  std::set<FeaturePtr> anUpdatedFeatures;
+
   std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
   for (; anIt != myAttributeMap.end(); ++anIt) {
     // the external feature always should keep the up to date values, so,
@@ -381,17 +399,26 @@ void PlaneGCSSolver_Storage::refresh() const
           std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
       GCSPointPtr aGCSPoint = aPointWrapper->point();
       if (fabs(aPoint2D->x() - (*aGCSPoint->x)) > aTol ||
-          fabs(aPoint2D->y() - (*aGCSPoint->y)) > aTol)
+          fabs(aPoint2D->y() - (*aGCSPoint->y)) > aTol) {
         aPoint2D->setValue(*aGCSPoint->x, *aGCSPoint->y);
+        addOwnerToSet(anIt->first, anUpdatedFeatures);
+      }
       continue;
     }
     AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
     if (aScalar) {
       ScalarWrapperPtr aScalarWrapper =
           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
-      if (fabs(aScalar->value() - aScalarWrapper->value()) > aTol)
+      if (fabs(aScalar->value() - aScalarWrapper->value()) > aTol) {
         aScalar->setValue(aScalarWrapper->value());
+        addOwnerToSet(anIt->first, anUpdatedFeatures);
+      }
       continue;
     }
   }
+
+  // notify listeners about features update
+  std::set<FeaturePtr>::const_iterator aFIt = anUpdatedFeatures.begin();
+  for (; aFIt != anUpdatedFeatures.end(); ++aFIt)
+    notify(*aFIt);
 }
index 1855de212ac9a0be336bd95ccb8ab0d80915d7c6..c7e1d1edaddfa79db572503617f31f45176036e1 100644 (file)
@@ -64,6 +64,10 @@ public:
   /// \brief Remove all features became invalid
   virtual void removeInvalidEntities();
 
+  /// \brief Check the storage has constraints
+  virtual bool isEmpty() const
+  { return SketchSolver_Storage::isEmpty() && myArcConstraintMap.empty(); }
+
 private:
   /// \brief Convert feature using specified builder.
   EntityWrapperPtr createFeature(const FeaturePtr&             theFeature,
index 32ec0721d2b74809e6aaf0282efb1a2366d8ab9b..9b37c03c616a834693c58c24f56fd4ac8b5d20d3 100644 (file)
@@ -110,12 +110,21 @@ void SketchSolver_ConstraintCollinear::notify(const FeaturePtr&      theFeature,
   }
 
   bool isNew = false;
-  for (int i = 0; i < 4 && !isNew; ++i)
+  for (int i = 0; i < 4; ++i) {
     if (aConstraintToApply[i] != myIsConstraintApplied[i])
       isNew = true;
+    myIsConstraintApplied[i] = aConstraintToApply[i];
+  }
+
   if (isNew) {
     mySolverConstraint = createPointsOnLine(aPoints[0], aPoints[1], aLine);
-    myStorage->removeConstraint(myBaseConstraint);
-    myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
+    if (myInSolver) {
+      myStorage->removeConstraint(myBaseConstraint);
+      myInSolver = false;
+    }
+    if (mySolverConstraint) {
+      myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
+      myInSolver = true;
+    }
   }
 }
index a70cc80acfc821a62d36ddf21323411a63f0dc33..abceb5431fd5f6c585c273e3d8722b9cb04a9781 100644 (file)
@@ -18,7 +18,8 @@ class SketchSolver_ConstraintCollinear : public SketchSolver_Constraint
 public:
   /// Constructor based on SketchPlugin constraint
   SketchSolver_ConstraintCollinear(ConstraintPtr theConstraint)
-    : SketchSolver_Constraint(theConstraint)
+    : SketchSolver_Constraint(theConstraint),
+      myInSolver(false)
   {
     for (int i = 0; i < 4; ++i)
       myIsConstraintApplied[i] = false;
@@ -35,6 +36,7 @@ protected:
 private:
   EntityWrapperPtr myPoints[4];  ///< extremities on collinear lines
   bool myIsConstraintApplied[4]; ///< set \c true if point on opposite line
+  bool myInSolver; ///< the constraint is added to the solver
 };
 
 #endif
index 41ba5d46b5622a7abd141024db70631cb9d23c60..7cf8a2abe0a1b387cccd92852b887dfe8909f1c5 100644 (file)
@@ -8,6 +8,7 @@
 #include <PlaneGCSSolver_PointWrapper.h>
 
 #include <GeomDataAPI_Point2D.h>
+#include <SketchPlugin_Feature.h>
 
 #include <cmath>
 
@@ -125,6 +126,14 @@ void SketchSolver_ConstraintFixed::getAttributes(
     std::vector<EntityWrapperPtr>& theAttributes)
 {
   if (myBaseFeature) {
+    // if the feature is copy, do not move it
+    std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+        std::dynamic_pointer_cast<SketchPlugin_Feature>(myBaseFeature);
+    if (aSketchFeature && aSketchFeature->isCopy()) {
+      myStorage->setNeedToResolve(true);
+      return;
+    }
+
     // The feature is fixed.
     EntityWrapperPtr aSolverEntity = getChangedEntity(myBaseFeature, myStorage);
     myStorage->update(myBaseFeature);
@@ -165,11 +174,14 @@ EntityWrapperPtr getChangedEntity(const FeaturePtr& theFeature,
   for (; aPIt != aPoints.end(); ++aPIt) {
     AttributePoint2DPtr aPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPIt);
     EntityWrapperPtr anEnt = theStorage->entity(*aPIt);
-    if (!anEnt)
-      continue;
-    PointWrapperPtr aPW = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anEnt);
-    if (!isSameCoordinates(aPnt, aPW))
-      aChangedPoints.push_back(anEnt);
+    if (anEnt) {
+      PointWrapperPtr aPW = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anEnt);
+      if (!isSameCoordinates(aPnt, aPW))
+        aChangedPoints.push_back(anEnt);
+    } else {
+      theStorage->update(*aPIt);
+      aChangedPoints.push_back(theStorage->entity(*aPIt));
+    }
   }
 
   EntityWrapperPtr aChanged;
index 335997a2ed1979910353a93d7f6390b55114b6c3..89bc973b27c7fe1402683af303393bbd05b806d8 100644 (file)
@@ -118,6 +118,10 @@ void SketchSolver_ConstraintMirror::adjustConstraint()
     FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
     FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
     mirrorEntities(aMirrorLine, aBase, aMirrored);
+
+    // update mirrored entity if it exists in the storage
+    if (myStorage->entity(aMirrored))
+      myStorage->update(aMirrored);
   }
 }
 
index 5d857e914bf292817e71513776787d0190b656d8..3288c9830480d228ef7b87c0e68cea055707cd3a 100644 (file)
@@ -24,7 +24,8 @@ void SketchSolver_ConstraintMultiRotation::getAttributes(
   theAngle = aValueBuilder.createAttribute(anAngleAttr);
   myStorage->addEntity(anAngleAttr, theAngle);
 
-  AttributePtr aCenterAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID());
+  AttributeRefAttrPtr aCenterAttr =
+      myBaseConstraint->refattr(SketchPlugin_MultiRotation::CENTER_ID());
   if (!aCenterAttr || !aCenterAttr->isInitialized()) {
     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
     return;
@@ -32,14 +33,19 @@ void SketchSolver_ConstraintMultiRotation::getAttributes(
 
   myType = CONSTRAINT_MULTI_ROTATION;
 
-  myStorage->update(aCenterAttr);
-  theCenter = myStorage->entity(aCenterAttr);
+  myStorage->update(AttributePtr(aCenterAttr));
+  theCenter = myStorage->entity(AttributePtr(aCenterAttr));
 
   AttributeStringPtr aMethodTypeAttr =
       myBaseConstraint->string(SketchPlugin_MultiRotation::ANGLE_TYPE());
   theFullValue = aMethodTypeAttr->value() != "SingleAngle";
 
   getEntities(theEntities);
+
+  // add owner of central point of Multi-Rotation to the list of monitored features
+  FeaturePtr anOwner = ModelAPI_Feature::feature(aCenterAttr->attr()->owner());
+  if (anOwner)
+    myFeatures.insert(anOwner);
 }
 
 void SketchSolver_ConstraintMultiRotation::process()
index 5244ec6a4f5f66e1e5f43e6a391c526d2623a59a..1a26ea810177eb250bc8b91a9a42304b65c509e8 100644 (file)
@@ -17,8 +17,10 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes(
     bool& theFullValue, std::list<EntityWrapperPtr>& theEntities)
 {
   DataPtr aData = myBaseConstraint->data();
-  AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
-  AttributePtr aEndPointAttr = aData->attribute(SketchPlugin_MultiTranslation::END_POINT_ID());
+  AttributeRefAttrPtr aStartPointAttr =
+      aData->refattr(SketchPlugin_MultiTranslation::START_POINT_ID());
+  AttributeRefAttrPtr aEndPointAttr =
+      aData->refattr(SketchPlugin_MultiTranslation::END_POINT_ID());
   if (!aStartPointAttr || !aStartPointAttr->isInitialized() ||
       !aEndPointAttr || !aEndPointAttr->isInitialized()) {
     myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
@@ -27,15 +29,23 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes(
 
   myType = CONSTRAINT_MULTI_TRANSLATION;
 
-  myStorage->update(aStartPointAttr);
-  theStartPoint = myStorage->entity(aStartPointAttr);
-  myStorage->update(aEndPointAttr);
-  theEndPoint = myStorage->entity(aEndPointAttr);
+  myStorage->update(AttributePtr(aStartPointAttr));
+  theStartPoint = myStorage->entity(AttributePtr(aStartPointAttr));
+  myStorage->update(AttributePtr(aEndPointAttr));
+  theEndPoint = myStorage->entity(AttributePtr(aEndPointAttr));
 
   AttributeStringPtr aMethodTypeAttr = aData->string(SketchPlugin_MultiTranslation::VALUE_TYPE());
   theFullValue = aMethodTypeAttr->value() != "SingleValue";
 
   getEntities(theEntities);
+
+  // add owner of start and end points of Multi-Translation to the list of monitored features
+  FeaturePtr anOwner = ModelAPI_Feature::feature(aStartPointAttr->attr()->owner());
+  if (anOwner)
+    myFeatures.insert(anOwner);
+  anOwner = ModelAPI_Feature::feature(aEndPointAttr->attr()->owner());
+  if (anOwner)
+    myFeatures.insert(anOwner);
 }
 
 void SketchSolver_ConstraintMultiTranslation::process()
index 709d09185bfe2ad3e4fe89ec65b5584d63321c8e..1c42ac69af7fdceca28e1eeb1f3de71e094165e1 100644 (file)
@@ -307,12 +307,13 @@ ConstraintWrapperPtr createArcLineTangency(EntityWrapperPtr theEntity1,
 
   std::shared_ptr<GCS::Circle> aCirc =
       std::dynamic_pointer_cast<GCS::Circle>(anEntCirc->entity());
+  std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(aCirc);
+
   std::shared_ptr<GCS::Line> aLine =
       std::dynamic_pointer_cast<GCS::Line>(anEntLine->entity());
 
   GCSConstraintPtr aNewConstr;
-  if (theSharedPoint) {
-    std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(aCirc);
+  if (theSharedPoint && anArc) { // do not process shared point between circle and line
     GCSPointPtr aPoint =
         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theSharedPoint)->point();
 
index 64e08004506305ee43ce874c0e7a0bf77bcd832b..a4fe899451b0339d61c03287085b45402d278cb1 100644 (file)
@@ -24,6 +24,14 @@ class SketchSolver_Error
       "To fix this, you can either undo your operation or remove a conflicting constraint.");
     return MY_ERROR_VALUE;
   }
+  /// Cyclic dependency of copied features with their originals
+  inline static const std::string& INFINITE_LOOP()
+  {
+    static const std::string MY_ERROR_VALUE(
+      "There is a circular reference between copied sketch entities and their originals. "
+      "To fix this, you can either undo your operation or remove wrong constraint.");
+    return MY_ERROR_VALUE;
+  }
   /// Constraints should use objects instead of features as attributes
   inline static const std::string& NEED_OBJECT_NOT_FEATURE()
   {
index 709407ee5d79cb9594f433db8f3ab60a75102aea..05840ba95c936f7a36845a5761526b585d8523a2 100644 (file)
 #include <Events_InfoMessage.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Events.h>
+#include <SketchPlugin_ConstraintMirror.h>
 #include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_MultiRotation.h>
+#include <SketchPlugin_MultiTranslation.h>
 
 
 static void sendMessage(const char* theMessageName)
@@ -34,7 +37,9 @@ static void sendMessage(const char* theMessageName, const std::set<ObjectPtr>& t
   Events_Loop::loop()->send(aMessage);
 }
 
-static void sendMessage(const char* theMessageName, const CompositeFeaturePtr& theSketch, const int theDOF)
+static void sendMessage(const char* theMessageName,
+                        const CompositeFeaturePtr& theSketch,
+                        const int theDOF)
 {
   std::shared_ptr<ModelAPI_SolverFailedMessage> aMessage =
       std::shared_ptr<ModelAPI_SolverFailedMessage>(
@@ -58,7 +63,8 @@ SketchSolver_Group::SketchSolver_Group(const CompositeFeaturePtr& theWorkplane)
   : mySketch(theWorkplane),
     myPrevResult(PlaneGCSSolver_Solver::STATUS_UNKNOWN),
     myDOF(0),
-    myIsEventsBlocked(false)
+    myIsEventsBlocked(false),
+    myMultiConstraintUpdateStack(0)
 {
   mySketchSolver = SolverPtr(new PlaneGCSSolver_Solver);
   myStorage = StoragePtr(new PlaneGCSSolver_Storage(mySketchSolver));
@@ -98,6 +104,9 @@ bool SketchSolver_Group::changeConstraint(
   }
   else
     myConstraints[theConstraint]->update();
+
+  // constraint is created/updated => reset stack of "multi" constraints updates
+  myMultiConstraintUpdateStack = 0;
   return true;
 }
 
@@ -108,7 +117,8 @@ bool SketchSolver_Group::updateFeature(FeaturePtr theFeature)
 
 bool SketchSolver_Group::moveFeature(FeaturePtr theFeature)
 {
-  if (myDOF == 0) {
+  bool isFeatureExists = (myStorage->entity(theFeature).get() != 0);
+  if (myDOF == 0 && isFeatureExists) {
     // avoid moving elements of fully constrained sketch
     myStorage->refresh();
     return true;
@@ -134,6 +144,16 @@ bool SketchSolver_Group::moveFeature(FeaturePtr theFeature)
 // ============================================================================
 bool SketchSolver_Group::resolveConstraints()
 {
+  // check the "Multi" constraints do not drop sketch into infinite loop
+  if (myMultiConstraintUpdateStack > 1) {
+    myPrevResult = PlaneGCSSolver_Solver::STATUS_FAILED;
+    // generate error message due to loop update of the sketch
+    getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())
+      ->setValue(SketchSolver_Error::INFINITE_LOOP());
+    sendMessage(EVENT_SOLVER_FAILED, myConflictingConstraints);
+    return false;
+  }
+
   bool aResolved = false;
   bool isGroupEmpty = isEmpty() && myStorage->isEmpty();
   if (myStorage->isNeedToResolve() &&
@@ -142,7 +162,7 @@ bool SketchSolver_Group::resolveConstraints()
 
     PlaneGCSSolver_Solver::SolveStatus aResult = PlaneGCSSolver_Solver::STATUS_OK;
     try {
-      if (!isGroupEmpty)
+      if (!isGroupEmpty && myMultiConstraintUpdateStack <= 1)
         aResult = mySketchSolver->solve();
     } catch (...) {
       getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())
@@ -161,19 +181,26 @@ bool SketchSolver_Group::resolveConstraints()
         aResult == PlaneGCSSolver_Solver::STATUS_EMPTYSET) {
       myStorage->setNeedToResolve(false);
       myStorage->refresh();
-////      updateMultiConstraints(myConstraints);
-////      // multi-constraints updated some parameters, need to store them
-////      if (myStorage->isNeedToResolve())
-////        resolveConstraints();
 
-      if (myPrevResult != PlaneGCSSolver_Solver::STATUS_OK ||
-          myPrevResult == PlaneGCSSolver_Solver::STATUS_UNKNOWN) {
-        getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
-        std::set<ObjectPtr> aConflicting = myConflictingConstraints;
-        myConflictingConstraints.clear();
-        myPrevResult = PlaneGCSSolver_Solver::STATUS_OK;
-        // the error message should be changed before sending the message
-        sendMessage(EVENT_SOLVER_REPAIRED, aConflicting);
+      // additional check that copied entities used in Mirror and other "Multi" constraints
+      // is not connected with their originals by constraints.
+      myMultiConstraintUpdateStack += 1;
+      aResolved = true;
+      if (myStorage->isNeedToResolve())
+        aResolved = resolveConstraints();
+
+      if (aResolved) {
+        myMultiConstraintUpdateStack -= 1;
+
+        if (myPrevResult != PlaneGCSSolver_Solver::STATUS_OK ||
+            myPrevResult == PlaneGCSSolver_Solver::STATUS_UNKNOWN) {
+          getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
+          std::set<ObjectPtr> aConflicting = myConflictingConstraints;
+          myConflictingConstraints.clear();
+          myPrevResult = PlaneGCSSolver_Solver::STATUS_OK;
+          // the error message should be changed before sending the message
+          sendMessage(EVENT_SOLVER_REPAIRED, aConflicting);
+        }
       }
 
       // show degrees of freedom
@@ -207,18 +234,6 @@ bool SketchSolver_Group::resolveConstraints()
       }
     }
 
-    aResolved = true;
-  } else if (!isGroupEmpty) {
-    // Check if the group contains only constraints Fixed, update parameters by stored values
-    aResolved = true;
-    ConstraintConstraintMap::iterator aCIt = myConstraints.begin();
-    for (; aCIt != myConstraints.end(); ++aCIt)
-      if (aCIt->first->getKind() != SketchPlugin_ConstraintRigid::ID()) {
-        aResolved = false;
-        break;
-      }
-    if (aCIt == myConstraints.end())
-      myStorage->refresh();
   } else if (isGroupEmpty && isWorkplaneValid())
     computeDoF();
   removeTemporaryConstraints();
@@ -235,6 +250,8 @@ void SketchSolver_Group::computeDoF()
 {
   std::ostringstream aDoFMsg;
   int aDoF = mySketchSolver->dof();
+  /// "DoF = 0" content of string value is used in PartSet by Sketch edit
+  /// If it is changed, it should be corrected also there
   if (aDoF == 0)
     aDoFMsg << "Sketch is fully fixed (DoF = 0)";
   else
@@ -258,7 +275,7 @@ void SketchSolver_Group::computeDoF()
 // ============================================================================
 void SketchSolver_Group::repairConsistency()
 {
-  if (!myStorage->isConsistent()) {
+  if (!areConstraintsValid() || !myStorage->areFeaturesValid()) {
     // remove invalid constraints
     std::set<ConstraintPtr> anInvalidConstraints;
     ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
@@ -310,6 +327,9 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
   for (; aCIter != myConstraints.end(); aCIter++)
     if (aCIter->first == theConstraint) {
       aCIter->second->remove(); // the constraint is not fully removed
+
+      // constraint is removed => reset stack of "multi" constraints updates
+      myMultiConstraintUpdateStack = 0;
       break;
     }
   if (aCIter != myConstraints.end())
@@ -346,3 +366,13 @@ void SketchSolver_Group::blockEvents(bool isBlocked)
 
   myIsEventsBlocked = isBlocked;
 }
+
+bool SketchSolver_Group::areConstraintsValid() const
+{
+  // Check the constraints are valid
+  ConstraintConstraintMap::const_iterator aCIter = myConstraints.begin();
+  for (; aCIter != myConstraints.end(); ++aCIter)
+    if (!aCIter->first->data() || !aCIter->first->data()->isValid())
+      return false;
+  return true;
+}
index a9d305a44a0ddcc9329f09f4e84f8e977a06eed6..fa590266467fe289621e49dd605838b8ab64ae7d 100644 (file)
@@ -37,7 +37,7 @@ class SketchSolver_Group
   /// \brief Returns true if the group has no constraints yet
   inline bool isEmpty() const
   {
-    return myConstraints.empty();
+    return myConstraints.empty() && myTempConstraints.empty();
   }
 
   /// \brief Check for valid sketch data
@@ -84,6 +84,9 @@ class SketchSolver_Group
   void blockEvents(bool isBlocked);
 
 private:
+  /// \biref Verify constraints have not been removed
+  bool areConstraintsValid() const;
+
   /** \brief Removes constraints from the group
    *  \param[in] theConstraint constraint to be removed
    */
@@ -113,6 +116,8 @@ private:
   int  myDOF; ///< degrees of freedom of the current sketch
 
   bool myIsEventsBlocked; ///< shows the events are blocked for this group
+
+  int myMultiConstraintUpdateStack; ///< depth of the stack updating "Multi" constraints
 };
 
 typedef std::shared_ptr<SketchSolver_Group> SketchGroupPtr;
index 5571e29276bbe8a1dc4ab5f6fe47935280de1d49..ec2f8d77bbb5be2f5047486ca7579ed016315d14 100644 (file)
@@ -74,13 +74,17 @@ bool SketchSolver_Manager::groupMessages()
 void SketchSolver_Manager::processEvent(
   const std::shared_ptr<Events_Message>& theMessage)
 {
+  bool needToResolve = false;
+  bool isUpdateFlushed = false;
+  bool isMovedEvt = false;
+
   static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
   static const Events_ID aSketchPreparedEvent = Events_Loop::eventByName(EVENT_SKETCH_PREPARED);
   // sketch is prepared for resolve: all the needed events
   // are collected and must be processed by the solver
   if (theMessage->eventID() == aSketchPreparedEvent) {
     flushGrouped(anUpdateEvent);
-    return;
+    needToResolve = true;
   }
 
   if (myIsComputed)
@@ -94,9 +98,9 @@ void SketchSolver_Manager::processEvent(
         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
     std::set<ObjectPtr> aFeatures = anUpdateMsg->objects();
 
-    bool isUpdateFlushed = stopSendUpdate();
+    isUpdateFlushed = stopSendUpdate();
 
-    bool isMovedEvt = theMessage->eventID()
+    isMovedEvt = theMessage->eventID()
           == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
 
     // Shows that the message has at least one feature applicable for solver
@@ -113,25 +117,8 @@ void SketchSolver_Manager::processEvent(
       hasProperFeature = updateFeature(aFeature, isMovedEvt) || hasProperFeature;
     }
 
-    if (isMovedEvt && !hasProperFeature) {
-      // in this iteration it will compute nothing, so, no problem with recursion
-      // it is important that solver flushes signal updated after processing move signal as there
-      // is optimization that relies on this update, might be found by key "optimization"
-      myIsComputed = false;
-    }
-
-    // Solve the set of constraints
-    bool needToUpdate = resolveConstraints();
-
-    // Features may be updated => now send events, but for all changed at once
-    if (isUpdateFlushed)
-      allowSendUpdate();
-
-    myIsComputed = false;
-
-    // send update for movement in any case
-    if (needToUpdate || isMovedEvt)
-      Events_Loop::loop()->flush(anUpdateEvent);
+    if (isMovedEvt && hasProperFeature)
+      needToResolve = true;
 
   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
     std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
@@ -158,11 +145,22 @@ void SketchSolver_Manager::processEvent(
         (*aGroupIter)->repairConsistency();
         ++aGroupIter;
       }
-
-      resolveConstraints();
     }
     myIsComputed = false;
   }
+
+  // resolve constraints if needed
+  bool needToUpdate = needToResolve && resolveConstraints();
+
+  // Features may be updated => now send events, but for all changed at once
+  if (isUpdateFlushed)
+    allowSendUpdate();
+
+  myIsComputed = false;
+
+  // send update for movement in any case
+  if (needToUpdate || isMovedEvt)
+    Events_Loop::loop()->flush(anUpdateEvent);
 }
 
 // ============================================================================
index 61694df946786d635621b5e299a9efa96421edaa..895edeb58321c0daf337aff135703098e204791f 100644 (file)
@@ -200,14 +200,8 @@ void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
 }
 
 
-bool SketchSolver_Storage::isConsistent() const
+bool SketchSolver_Storage::areFeaturesValid() const
 {
-  // Check the constraints are valid
-  std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
-      aCIter = myConstraintMap.begin();
-  for (; aCIter != myConstraintMap.end(); ++aCIter)
-    if (!aCIter->first->data() || !aCIter->first->data()->isValid())
-      return false;
   // Check the features are valid
   std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
   for (; aFIter != myFeatureMap.end(); aFIter++)
index bfd8bc62001f731733e7f03843b19f1d8832bd31..6ef8d08b57ca9a464199bd836bc572b755be2258 100644 (file)
@@ -93,11 +93,11 @@ public:
   /// \brief Remove all features became invalid
   virtual void removeInvalidEntities() = 0;
 
-  /// \brief Check the features is not removed
-  bool isConsistent() const;
+  /// \brief Check the features have not been removed
+  bool areFeaturesValid() const;
 
   /// \brief Check the storage has constraints
-  bool isEmpty() const
+  virtual bool isEmpty() const
   { return myConstraintMap.empty(); }
 
   /// \brief Shows the sketch should be resolved
index 424f5d40f7950c092c975a9a3b24cba639568013..f3b66c60984ff2a31af9f06a11a8ea72606e88dc 100755 (executable)
@@ -7,6 +7,10 @@
       <source>The constraint is conflicting with others. To fix this, you can either undo your operation or remove a conflicting constraint.</source>
       <translation>The constraint is conflicting with others. To fix this, you can either undo your operation or remove a conflicting constraint.</translation>
     </message>
+    <message>
+      <source>There is a circular reference between copied sketch entities and their originals. To fix this, you can either undo your operation or remove wrong constraint.</source>
+      <translation>There is a circular reference between copied sketch entities and their originals. To fix this, you can either undo your operation or remove wrong constraint.</translation>
+    </message>
     <message>
       <source>Caution: SolveSpace crash! Constraints are wrong</source>
       <translation>Caution: SolveSpace crash! Constraints are wrong</translation>
index 84e6b130fc5c3e9b1ad19c6dccddcfcd13ee1b97..13ffbee742ff077fa9b7ca5e677160e1804a45d2 100644 (file)
@@ -34,7 +34,7 @@ IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Coincident, AIS_InteractiveObject);
 SketcherPrs_Coincident::SketcherPrs_Coincident(ModelAPI_Feature* theConstraint,
                                                const std::shared_ptr<GeomAPI_Ax3>& thePlane)
 : AIS_InteractiveObject(), myConstraint(theConstraint), mySketcherPlane(thePlane),
-  myPoint(gp_Pnt(0.0, 0.0, 0.0)), myIsConflicting(false)
+  myPoint(gp_Pnt(0.0, 0.0, 0.0)), myIsCustomColor(false)
 {
 }
 
@@ -76,12 +76,12 @@ void SketcherPrs_Coincident::Compute(
     myPoint = aPoint;
 
   // Create the presentation as a combination of standard point markers
-  bool aValid = !myIsConflicting;
+  bool aCustomColor = myIsCustomColor;
   // The external yellow contour
   Handle(Graphic3d_AspectMarker3d) aPtA = new Graphic3d_AspectMarker3d();
   aPtA->SetType(Aspect_TOM_RING3);
   aPtA->SetScale(2.);
-  aPtA->SetColor(aValid ? Quantity_NOC_YELLOW : myConflictingColor);
+  aPtA->SetColor(!aCustomColor ? Quantity_NOC_YELLOW : myCustomColor);
 
   Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup(thePresentation);
   aGroup->SetPrimitivesAspect(aPtA);
@@ -93,7 +93,7 @@ void SketcherPrs_Coincident::Compute(
   aPtA = new Graphic3d_AspectMarker3d();
   aPtA->SetType(Aspect_TOM_RING1);
   aPtA->SetScale(1.);
-  aPtA->SetColor(aValid ? Quantity_NOC_BLACK : myConflictingColor);
+  aPtA->SetColor(!aCustomColor ? Quantity_NOC_BLACK : myCustomColor);
   aGroup->SetPrimitivesAspect(aPtA);
   aGroup->AddPrimitiveArray (aPntArray);
 
@@ -101,7 +101,7 @@ void SketcherPrs_Coincident::Compute(
   aPtA = new Graphic3d_AspectMarker3d();
   aPtA->SetType(Aspect_TOM_POINT);
   aPtA->SetScale(5.);
-  aPtA->SetColor(aValid ? Quantity_NOC_BLACK : myConflictingColor);
+  aPtA->SetColor(!aCustomColor ? Quantity_NOC_BLACK : myCustomColor);
   aGroup->SetPrimitivesAspect(aPtA);
   aGroup->AddPrimitiveArray (aPntArray);
 
@@ -128,10 +128,12 @@ void SketcherPrs_Coincident::SetColor(const Quantity_Color &aCol)
   myOwnColor=aCol;
 }
 
-void SketcherPrs_Coincident::SetConflictingConstraint(const bool& theConflicting,
-                                                     const std::vector<int>& theColor)
+void SketcherPrs_Coincident::SetCustomColor(const std::vector<int>& theColor)
 {
-  myIsConflicting = theConflicting;
-  myConflictingColor = Quantity_Color(theColor[0] / 255., theColor[1] / 255., theColor[2] / 255.,
-                                      Quantity_TOC_RGB);
+  myIsCustomColor = !theColor.empty();
+  if (myIsCustomColor)
+    myCustomColor = Quantity_Color(theColor[0] / 255., theColor[1] / 255.,
+                                   theColor[2] / 255., Quantity_TOC_RGB);
+  else
+    myCustomColor = Quantity_Color();
 }
index 773a9c5ea2415224976e3446857ca494a90354f8..f77aa8d9b5c8b7fd7f8d9dac69301d24c750ebf5 100644 (file)
@@ -38,14 +38,10 @@ public:
   /// \param aColor a color name
   Standard_EXPORT virtual void SetColor(const Quantity_NameOfColor aColor);
 
-  /// Set state of the presentation, in case of conflicting state, the icon of the presentation is
+  /// Set state of the presentation, in case of custom color, the icon of the presentation is
   /// visualized in error color.
-  /// The state is stored in an internal field, so should be changed when
-  /// constraint become not conflicting
-  /// \param theConflicting a state
-  /// \param theColor a color for conflicting object
-  Standard_EXPORT void SetConflictingConstraint(const bool& theConflicting,
-                                                const std::vector<int>& theColor);
+  /// \param theColor a custom color for object presentation
+  Standard_EXPORT void SetCustomColor(const std::vector<int>& theColor);
 
   /// Returns true if the constraint feature arguments are correcly filled to build AIS presentation
   /// \param theConstraint a constraint feature
@@ -74,8 +70,8 @@ private:
   ModelAPI_Feature* myConstraint;
   std::shared_ptr<GeomAPI_Ax3> mySketcherPlane;
   gp_Pnt myPoint;
-  bool myIsConflicting; /// state if the presentation is visualized in error state
-  Quantity_Color myConflictingColor; /// the color of mid ring if there is a conflict
+  bool myIsCustomColor; /// state if the presentation is visualized in custom color
+  Quantity_Color myCustomColor; /// the color of mid ring if there is a conflict
 };
 
 
index e485076aa307bbb4dbffd8dd538e32476b8e145b..ac28d6436ef90ef1ecd9648a0b786972775466d5 100755 (executable)
@@ -22,9 +22,6 @@ SketcherPrs_Collinear::SketcherPrs_Collinear(ModelAPI_Feature* theConstraint,
                                      const std::shared_ptr<GeomAPI_Ax3>& thePlane)
  : SketcherPrs_SymbolPrs(theConstraint, thePlane)
 {
-  myPntArray = new Graphic3d_ArrayOfPoints(2);
-  myPntArray->AddVertex(0., 0., 0.);
-  myPntArray->AddVertex(0., 0., 0.);
 }
 
 bool SketcherPrs_Collinear::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
@@ -43,7 +40,7 @@ bool SketcherPrs_Collinear::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Collinear::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Collinear::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
@@ -57,8 +54,9 @@ bool SketcherPrs_Collinear::updateIfReadyToDisplay(double theStep) const
   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
   gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep);
   gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
-  myPntArray->SetVertice(1, aP1);
-  myPntArray->SetVertice(2, aP2);
+  myPntArray = new Graphic3d_ArrayOfPoints(2, withColor);
+  myPntArray->AddVertex(aP1);
+  myPntArray->AddVertex(aP2);
   return true;
 }
 
index 99c3ac2897aed9bcc0cb3810f568b71846428cc6..67a7a7aca6404894465cd7bbab012292de5781bf 100755 (executable)
@@ -41,7 +41,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 };
 
 #endif
\ No newline at end of file
index b070c171de3e86f2f4c212fb6cb23f25319c7f66..fde1496877a21b9e4cdde21ec53dedb28510e3e0 100644 (file)
@@ -22,9 +22,6 @@ SketcherPrs_Equal::SketcherPrs_Equal(ModelAPI_Feature* theConstraint,
                                      const std::shared_ptr<GeomAPI_Ax3>& thePlane)
  : SketcherPrs_SymbolPrs(theConstraint, thePlane)
 {
-  myPntArray = new Graphic3d_ArrayOfPoints(2);
-  myPntArray->AddVertex(0., 0., 0.);
-  myPntArray->AddVertex(0., 0., 0.);
 }
 
 bool SketcherPrs_Equal::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
@@ -43,7 +40,7 @@ bool SketcherPrs_Equal::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Equal::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Equal::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
@@ -57,8 +54,10 @@ bool SketcherPrs_Equal::updateIfReadyToDisplay(double theStep) const
   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
   gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep);
   gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
-  myPntArray->SetVertice(1, aP1);
-  myPntArray->SetVertice(2, aP2);
+
+  myPntArray = new Graphic3d_ArrayOfPoints(2, withColor);
+  myPntArray->AddVertex(aP1);
+  myPntArray->AddVertex(aP2);
   return true;
 }
 
index 5fd1c55198b4ebc5dd95921983f23e39ecf4980e..07d77bd34525c156fac91c146562a2fe1ade867b 100644 (file)
@@ -41,7 +41,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 };
 
 #endif
\ No newline at end of file
index e1a7ed60118de059498e437db6e8b0d0eb855c28..552da1a6c63bc7c1d20af471218b5df4033ebbd8 100644 (file)
@@ -36,7 +36,7 @@ bool SketcherPrs_HVDirection::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_HVDirection::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_HVDirection::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
@@ -45,7 +45,8 @@ bool SketcherPrs_HVDirection::updateIfReadyToDisplay(double theStep) const
   ObjectPtr aObj = SketcherPrs_Tools::getResult(myConstraint, SketchPlugin_Constraint::ENTITY_A());
   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
   gp_Pnt aP1 = aMgr->getPosition(aObj, this, theStep);
-  myPntArray->SetVertice(1, aP1);
+  myPntArray = new Graphic3d_ArrayOfPoints(1, withColor);
+  myPntArray->AddVertex(aP1);
   return true;
 }
 
index ffe5415706593c1afda0dcc02bd9efb4d04a2d06..d304031fe09647fafe1a4ae4ad28b62e017c0ce7 100644 (file)
@@ -48,7 +48,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 
 private:
   bool myIsHorisontal;
index af78d67e810e4454db868f2fd4f1e1ac59ec3b56..df7590a1c37e377752ab42cedbdca0f1cce5ebf5 100755 (executable)
@@ -42,13 +42,14 @@ bool SketcherPrs_Middle::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Middle::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Middle::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
   ObjectPtr aPointObject;
 
   // find a line result to set middle symbol near it
+  myPntArray = new Graphic3d_ArrayOfPoints(1, withColor);
   AttributePtr anAttribute =
     SketcherPrs_Tools::getAttribute(myConstraint, SketchPlugin_Constraint::ENTITY_A());
   if (!anAttribute.get()) {
index 25c97b43035af50f289692087a0fede2aa5dfbc2..e01aa66c1877264d41602b98b542c3b0232b46fb 100755 (executable)
@@ -41,7 +41,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 
   /// Draw shape of the object. Find shape result if the object is feature
   void drawLine(const Handle(Prs3d_Presentation)& thePrs, Quantity_Color theColor,
index 28ecf09cdd6e43896b122158c9fa54b53117a45c..e78dc668e7762624396a25f19ce83f943bf4f1a8 100644 (file)
@@ -59,7 +59,7 @@ bool SketcherPrs_Mirror::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Mirror::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Mirror::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
@@ -79,7 +79,7 @@ bool SketcherPrs_Mirror::updateIfReadyToDisplay(double theStep) const
   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
   int aNb = anAttrB->size();
 
-  myPntArray = new Graphic3d_ArrayOfPoints(2 * aNb);
+  myPntArray = new Graphic3d_ArrayOfPoints(2 * aNb, withColor);
   int i;
   ObjectPtr aObj;
   gp_Pnt aP1;
index 3c57b95b0b61c953a7a2fd7620c784f314bb8414..4d7f7335e4910e80eea3ccd5a58f184cd436d597 100644 (file)
@@ -40,7 +40,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 };
 
 #endif
\ No newline at end of file
index 430d8818abc7512385441eed813be9049d4e12d1..770df4e2a7f54d8422dee9c893594995c2ac2625 100644 (file)
@@ -23,10 +23,6 @@ SketcherPrs_Parallel::SketcherPrs_Parallel(ModelAPI_Feature* theConstraint,
                                            const std::shared_ptr<GeomAPI_Ax3>& thePlane)
  : SketcherPrs_SymbolPrs(theConstraint, thePlane)
 {
-  // Create default array
-  myPntArray = new Graphic3d_ArrayOfPoints(2);
-  myPntArray->AddVertex(0., 0., 0.);
-  myPntArray->AddVertex(0., 0., 0.);
 }
 
 bool SketcherPrs_Parallel::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
@@ -44,7 +40,7 @@ bool SketcherPrs_Parallel::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Parallel::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Parallel::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
@@ -58,8 +54,9 @@ bool SketcherPrs_Parallel::updateIfReadyToDisplay(double theStep) const
   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
   gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep);
   gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
-  myPntArray->SetVertice(1, aP1);
-  myPntArray->SetVertice(2, aP2);
+  myPntArray = new Graphic3d_ArrayOfPoints(2, withColor);
+  myPntArray->AddVertex(aP1);
+  myPntArray->AddVertex(aP2);
   return true;
 }
 
index 83ff20bb85e3683d0c480dde1b37e22dda256e85..2b2f7128fa45fc803179ed24edc01e3dd77c5af1 100644 (file)
@@ -41,7 +41,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 };
 
 #endif
\ No newline at end of file
index a0bda9731d6080b0783260789dc6e6a722bc60b2..54d263498796490e505be32fc3da848f28c60c83 100644 (file)
@@ -23,10 +23,6 @@ SketcherPrs_Perpendicular::SketcherPrs_Perpendicular(ModelAPI_Feature* theConstr
                                                      const std::shared_ptr<GeomAPI_Ax3>& thePlane)
  : SketcherPrs_SymbolPrs(theConstraint, thePlane)
 {
-  // Create default array
-  myPntArray = new Graphic3d_ArrayOfPoints(2);
-  myPntArray->AddVertex(0., 0., 0.);
-  myPntArray->AddVertex(0., 0., 0.);
 }
 
 bool SketcherPrs_Perpendicular::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
@@ -44,7 +40,7 @@ bool SketcherPrs_Perpendicular::IsReadyToDisplay(ModelAPI_Feature* theConstraint
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Perpendicular::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Perpendicular::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
@@ -58,8 +54,9 @@ bool SketcherPrs_Perpendicular::updateIfReadyToDisplay(double theStep) const
   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
   gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep);
   gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
-  myPntArray->SetVertice(1, aP1);
-  myPntArray->SetVertice(2, aP2);
+  myPntArray = new Graphic3d_ArrayOfPoints(2, withColor);
+  myPntArray->AddVertex(aP1);
+  myPntArray->AddVertex(aP2);
   return true;
 }
 
index 3b07a25e8d544583e092c668b29baed368547e1c..337f996bef14649dcb41f3d8203b6d7784b6d548 100644 (file)
@@ -46,7 +46,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 };
 
 #endif
\ No newline at end of file
index a430ef2c1728c28672fbe1e22a79d94481cbd5a5..8b0ccb425fa0ed3ceab85c80a590278be7c55e97 100644 (file)
@@ -65,11 +65,12 @@ bool SketcherPrs_Rigid::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Rigid::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Rigid::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
 
+  myPntArray = new Graphic3d_ArrayOfPoints(1, withColor);
   std::shared_ptr<ModelAPI_Data> aData = myConstraint->data();
   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
     aData->refattr(SketchPlugin_Constraint::ENTITY_A());
@@ -80,13 +81,13 @@ bool SketcherPrs_Rigid::updateIfReadyToDisplay(double theStep) const
 
     SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
     gp_Pnt aP1 = aMgr->getPosition(aObj, this, theStep);
-    myPntArray->SetVertice(1, aP1);
+    myPntArray->AddVertex(aP1);
   } else {
     // The constraint attached to a point
     std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(myConstraint,
                                                   SketchPlugin_Constraint::ENTITY_A());
     std::shared_ptr<GeomAPI_Pnt> aPoint = myPlane->to3D(aPnt->x(), aPnt->y() + theStep);
-    myPntArray->SetVertice(1, aPoint->impl<gp_Pnt>());
+    myPntArray->AddVertex(aPoint->impl<gp_Pnt>());
   }
   return true;
 }
index d430148553443edf5fb608f395adbd96bab3d6b6..c944297a143fc855e1a9a5fadc42f868fc3dbdce 100644 (file)
@@ -47,7 +47,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 
 };
 
index 1e7d5f6a8e5f89ab21668bdad43e081391283b85..2dfcc68f31301bfdc554c0ffa75ec82388715767 100644 (file)
@@ -63,7 +63,7 @@ public:
       Handle(OpenGl_View) aView = theWorkspace->View();
       double aScale = aView->Camera()->Scale();
       // Update points coordinate taking the viewer scale into account
-      myObj->updateIfReadyToDisplay(MyDist * aScale);
+      myObj->updateIfReadyToDisplay(MyDist * aScale, myObj->myIsCustomColor);
       if (myIsVboInit) {
         if (myVboAttribs) {
           const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
@@ -103,11 +103,9 @@ std::map<const char*, Handle(Image_AlienPixMap)> SketcherPrs_SymbolPrs::myIconsM
 
 SketcherPrs_SymbolPrs::SketcherPrs_SymbolPrs(ModelAPI_Feature* theConstraint,
                                              const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : AIS_InteractiveObject(), myConstraint(theConstraint), myPlane(thePlane), myIsConflicting(false)
+ : AIS_InteractiveObject(), myConstraint(theConstraint), myPlane(thePlane), myIsCustomColor(false)
 {
   SetAutoHilight(Standard_False);
-  myPntArray = new Graphic3d_ArrayOfPoints(1);
-  myPntArray->AddVertex(0., 0., 0.);
 }
 
 //*********************************************************************************
@@ -165,6 +163,8 @@ void SketcherPrs_SymbolPrs::prepareAspect()
       myAspect = new Graphic3d_AspectMarker3d();
     else
       myAspect = new Graphic3d_AspectMarker3d(aIcon);
+
+    myAspect->SetColor(myCustomColor);
   }
 }
 
@@ -240,7 +240,7 @@ void SketcherPrs_SymbolPrs::Compute(
   // it updates array of points if the presentation is ready to display, or the array of points
   // contains the previous values
 
-  bool aReadyToDisplay = updateIfReadyToDisplay(20);
+  bool aReadyToDisplay = updateIfReadyToDisplay(20, myIsCustomColor);
 
   int aNbVertex = myPntArray->VertexNumber();
   if (myOwner.IsNull()) {
@@ -252,9 +252,12 @@ void SketcherPrs_SymbolPrs::Compute(
   for (int i = 1; i <= aNbVertex; i++) {
     Handle(SketcherPrs_SensitivePoint) aSP = new SketcherPrs_SensitivePoint(myOwner, i);
     mySPoints.Append(aSP);
+    if (myIsCustomColor)
+      myPntArray->SetVertexColor(i, myCustomColor);
   }
 
-  Handle(OpenGl_Group) aGroup = Handle(OpenGl_Group)::DownCast(thePresentation->NewGroup());
+  Handle(OpenGl_Group) aGroup =
+    Handle(OpenGl_Group)::DownCast(Prs3d_Root::CurrentGroup (thePresentation));
   aGroup->SetPrimitivesAspect(myAspect);
 
   // Recompute boundary box of the group
@@ -292,22 +295,17 @@ void SketcherPrs_SymbolPrs::ComputeSelection(const Handle(SelectMgr_Selection)&
 }
 
 //*********************************************************************************
-void SketcherPrs_SymbolPrs::SetConflictingConstraint(const bool& theConflicting,
-                                                     const std::vector<int>& theColor)
+void SketcherPrs_SymbolPrs::SetCustomColor(const std::vector<int>& theColor)
 {
-  if (theConflicting)
-  {
-    if (!myAspect.IsNull())
-      myAspect->SetColor (Quantity_Color (theColor[0] / 255., theColor[1] / 255.,
-                          theColor[2] / 255., Quantity_TOC_RGB));
-    myIsConflicting = true;
-  }
+  myIsCustomColor = !theColor.empty();
+  if (myIsCustomColor)
+    myCustomColor = Quantity_Color(theColor[0] / 255., theColor[1] / 255.,
+                                   theColor[2] / 255., Quantity_TOC_RGB);
   else
-  {
-    if (!myAspect.IsNull())
-      myAspect->SetColor (Quantity_Color (1.0, 1.0, 0.0, Quantity_TOC_RGB));
-    myIsConflicting = false;
-  }
+    myCustomColor = Quantity_Color (1.0, 1.0, 0.0, Quantity_TOC_RGB);
+
+  if (!myAspect.IsNull())
+    myAspect->SetColor (myCustomColor);
 }
 
 //*********************************************************************************
index affd9d07409356c4e9d7ede33b96d7675ca13878..c672b4ea7a3e3a67a7484f3d5badb3aefface604 100644 (file)
@@ -68,10 +68,8 @@ public:
   /// Set state of the presentation, in case of conflicting state, the icon of the presentation is
   /// visualized in error color. The state is stored in an internal field, so should be changed
   /// when constraint become not conflicting
-  /// \param theConflicting a state
   /// \param theColor a color for conflicting object
-  Standard_EXPORT void SetConflictingConstraint(const bool& theConflicting,
-                                                const std::vector<int>& theColor);
+  Standard_EXPORT void SetCustomColor(const std::vector<int>& theColor);
 
   /// Add a bounding box of the presentation to common bounding box
   /// \param theBndBox the common bounding box to update
@@ -113,7 +111,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const { return true; }
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const { return true; }
 
   /// Draw a shape into the given presentation scene
   /// \param theShape the shape to draw
@@ -149,7 +147,10 @@ private:
 
   Select3D_EntitySequence mySPoints;
 
-  bool myIsConflicting; /// state if the presentation is visualized in error state
+  bool myIsCustomColor; /// state if the presentation is visualized in custom color
+  Quantity_Color myCustomColor; /// the color of mid ring if there is a conflict
+
+  //bool myIsConflicting; /// state if the presentation is visualized in error state
   Handle(Image_AlienPixMap) myErrorIcon;
   Handle(Graphic3d_MarkerImage) myErrorImage;
 
index 5f657b8aacf660a4f364f405ba28ff5b3624eff2..7704d95cffa51766b87b7326797ded96457b92a4 100644 (file)
@@ -26,10 +26,6 @@ SketcherPrs_Tangent::SketcherPrs_Tangent(ModelAPI_Feature* theConstraint,
                                            const std::shared_ptr<GeomAPI_Ax3>& thePlane)
  : SketcherPrs_SymbolPrs(theConstraint, thePlane)
 {
-  // Init default points
-  myPntArray = new Graphic3d_ArrayOfPoints(2);
-  myPntArray->AddVertex(0., 0., 0.);
-  myPntArray->AddVertex(0., 0., 0.);
 }
 
 bool SketcherPrs_Tangent::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
@@ -48,7 +44,7 @@ bool SketcherPrs_Tangent::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Tangent::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Tangent::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
@@ -62,8 +58,9 @@ bool SketcherPrs_Tangent::updateIfReadyToDisplay(double theStep) const
   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
   gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep);
   gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
-  myPntArray->SetVertice(1, aP1);
-  myPntArray->SetVertice(2, aP2);
+  myPntArray = new Graphic3d_ArrayOfPoints(2, withColor);
+  myPntArray->AddVertex(aP1);
+  myPntArray->AddVertex(aP2);
   return true;
 }
 
index a3bdf4a44862b917864b47231ae3c3c0b94382e2..00c3e9c2ed998c5592783e92ceb344c54346e261 100644 (file)
@@ -43,7 +43,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 };
 
 #endif
\ No newline at end of file
index 285133c84bbe670ef7ae4bae6d9736c643cbccc0..9d6061e2618716ae575a26353fe8597cd4945736 100644 (file)
@@ -71,7 +71,7 @@ bool SketcherPrs_Transformation::IsReadyToDisplay(ModelAPI_Feature* theConstrain
   return aReadyToDisplay;
 }
 
-bool SketcherPrs_Transformation::updateIfReadyToDisplay(double theStep) const
+bool SketcherPrs_Transformation::updateIfReadyToDisplay(double theStep, bool withColor) const
 {
   if (!IsReadyToDisplay(myConstraint, myPlane))
     return false;
@@ -91,7 +91,7 @@ bool SketcherPrs_Transformation::updateIfReadyToDisplay(double theStep) const
   }
 
   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
-  myPntArray = new Graphic3d_ArrayOfPoints(aNbB);
+  myPntArray = new Graphic3d_ArrayOfPoints(aNbB, withColor);
 
   int i;
   ObjectPtr aObj;
index 7ac6360f7ada81f83994746e673549fdee4bd5ce..e8cb4ab774ea556446ae45e1467e31dd2292e46c 100644 (file)
@@ -47,7 +47,7 @@ protected:
 
   /// Update myPntArray according to presentation positions
   /// \return true in case of success
-  virtual bool updateIfReadyToDisplay(double theStep) const;
+  virtual bool updateIfReadyToDisplay(double theStep, bool withColor) const;
 
 private:
   bool myIsTranslation;
index 3970d8b32b2a6758e6e19fb8d6dd463ce2ec40a8..dafd6dd98246261e97fd705e1bee84c3c9d399e4 100644 (file)
@@ -1373,6 +1373,8 @@ bool XGUI_Displayer::customizeObject(ObjectPtr theObject)
   }
   bool isCustomized = aCustomPrs.get() &&
                       aCustomPrs->customisePresentation(aResult, anAISObj, myCustomPrs);
+  isCustomized = myWorkshop->module()->afterCustomisePresentation(aResult, anAISObj, myCustomPrs)
+                 || isCustomized;
   return isCustomized;
 }
 
index 3a320c4b0e807877a5c53b532230a6a78f504ca8..f9ad34c09fff0e3d0b39a3d309c22606ddeeb069 100644 (file)
@@ -38,7 +38,7 @@ public:
 
   /// Update actions for the given feature
   /// \param theFeature a feature
-  void updateActions(const FeaturePtr& theFeature);
+  virtual void updateActions(const FeaturePtr& theFeature);
 
   /// Update enable state of AcceptAll action if the feature uses it
   /// \param theFeature a feature
index 7231a1b28c33b8e790775019ebcbffb6ae3befcb..e6b6cf73fe249565817b83988643a47659e149df 100644 (file)
@@ -13,6 +13,7 @@
 #include "XGUI_Displayer.h"
 #include "XGUI_PropertyPanel.h"
 #include "XGUI_ActionsMgr.h"
+#include "XGUI_ErrorMgr.h"
 
 #include <ModuleBase_IModule.h>
 #include <ModuleBase_ViewerPrs.h>
@@ -58,6 +59,11 @@ ModuleBase_IPropertyPanel* XGUI_ModuleConnector::propertyPanel() const
   return myWorkshop->propertyPanel();
 }
 
+ModuleBase_IErrorMgr* XGUI_ModuleConnector::errorMgr() const
+{
+  return myWorkshop->errorMgr();
+}
+
 ModuleBase_Operation* XGUI_ModuleConnector::currentOperation() const
 {
   return myWorkshop->operationMgr()->currentOperation();
index b86c0ef8ba2277515b1536837e83ce0e74421613..eb4c37c4f27de2caeda07fe73b2ef6b94c45e589 100644 (file)
@@ -50,6 +50,9 @@ Q_OBJECT
   //! Returns property panel
   virtual ModuleBase_IPropertyPanel* propertyPanel() const;
 
+  //! Returns error manager
+  virtual ModuleBase_IErrorMgr* errorMgr() const;
+
   //! Returns currently active operation
   virtual ModuleBase_Operation* currentOperation() const;
 
index b1afa6e610e86693617bece4208efbea650a161b..e1e9364e750e72b559ea3d98672cd34a87df9b38 100644 (file)
@@ -1,5 +1,5 @@
 """
-Test case for Primitive Cylinder feature. 
+Test case for Primitive Cylinder feature.
 Written on High API.
 """
 #from ModelAPI import *
@@ -23,6 +23,7 @@ SketchLine_3 = Sketch_1.addLine(44.70109718071649, 32.40093347950982, 40.1917811
 SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
 SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
 SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+model.do()
 
 # Extrusion
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f")], model.selection(), 100, 0)
@@ -55,7 +56,7 @@ Cylinder_8 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "InvalidNam
 Cylinder_9 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "InvalidName"), 5, 10)
 Cylinder_10 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_3s-SketchLine_2e"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), 50, 120)
 Cylinder_11 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Vertex_1_1"), model.selection("EDGE", "Edge_1_1"), 60, 100)
-Cylinder_12 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"), 5, 10)
+Cylinder_12 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"), 5, 10)
 Cylinder_13 = model.addCylinder(Part_1_doc, "r", "h")
 Cylinder_14 = model.addCylinder(Part_1_doc, 5, 10, 45)
 Cylinder_15 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Point_1"), model.selection("EDGE", "PartSet/OX"), 5, 10, 90)
@@ -72,7 +73,7 @@ Cylinder_25 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "InvalidNa
 Cylinder_26 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "InvalidName"), 5, 10, 90)
 Cylinder_27 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_2s-SketchLine_1e"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), 50, 120, 90)
 Cylinder_28 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Vertex_1_1"), model.selection("EDGE", "Edge_2_1"), 60, 100, 180)
-Cylinder_29 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_5&Extrusion_1_1/Generated_Face_4&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/To_Face_1"), 5, 10, 120)
+Cylinder_29 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_3&Extrusion_2_1/Generated_Face_2&Extrusion_2_1/To_Face_1"), model.selection("EDGE", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/To_Face_1"), 5, 10, 120)
 Cylinder_30 = model.addCylinder(Part_1_doc, "r2", "h2", "angle")
 
 model.do()
index 2bfbcb9f29adcf4289be8fcdd1d8a32d32b5726b..ffd838e9ec5c2ceeafd5da45ced964561c48e84f 100644 (file)
@@ -184,7 +184,6 @@ SketchLine_33.setName("SketchLine_32")
 SketchLine_33.result().setName("SketchLine_32")
 SketchConstraintDistance_10 = Sketch_4.setDistance(SketchLine_22.startPoint(), SketchLine_32.result(), 4.5)
 SketchConstraintDistance_10.setName("SketchConstraintDistance_13")
-SketchPoint_2 = Sketch_4.addPoint(0.0367430766441097, 12.3548825983447)
 SketchLine_34 = Sketch_4.addLine(-8.5, 12.23281708580693, 8.5, 12.23281708580693)
 SketchLine_34.setName("SketchLine_33")
 SketchLine_34.result().setName("SketchLine_33")
@@ -323,6 +322,12 @@ SketchConstraintDistance_17 = Sketch_4.setDistance(SketchLine_21.result(), Sketc
 SketchConstraintDistance_17.setName("SketchConstraintDistance_18")
 SketchConstraintDistance_18 = Sketch_4.setDistance(SketchLine_30.endPoint(), SketchLine_20.result(), 6.1)
 SketchConstraintDistance_18.setName("SketchConstraintDistance_19")
+SketchConstraintCoincidence_67 = Sketch_4.setCoincident(SketchArc_3.center(), SketchCircle_3.center())
+SketchConstraintCoincidence_67.setName("SketchConstraintCoincidence_149")
+SketchConstraintCoincidence_68 = Sketch_4.setCoincident(SketchArc_4.center(), SketchArc_3.center())
+SketchConstraintCoincidence_68.setName("SketchConstraintCoincidence_150")
+SketchConstraintDistance_19 = Sketch_4.setDistance(SketchArc_4.center(), SketchLine_34.result(), 12)
+SketchConstraintDistance_19.setName("SketchConstraintDistance_43")
 model.do()
 Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_4")], model.selection(), 50, 30)
 Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_3")], model.selection(), 22, 22)
@@ -753,9 +758,9 @@ from GeomAPI import GeomAPI_Shape
 model.testNbResults(Boolean_7, 1)
 model.testNbSubResults(Boolean_7, [0])
 model.testNbSubShapes(Boolean_7, GeomAPI_Shape.SOLID, [1])
-model.testNbSubShapes(Boolean_7, GeomAPI_Shape.FACE, [49])
-model.testNbSubShapes(Boolean_7, GeomAPI_Shape.EDGE, [263])
-model.testNbSubShapes(Boolean_7, GeomAPI_Shape.VERTEX, [526])
-model.testResultsVolumes(Boolean_7, [157000.328896829247241839766502380])
+model.testNbSubShapes(Boolean_7, GeomAPI_Shape.FACE, [50])
+model.testNbSubShapes(Boolean_7, GeomAPI_Shape.EDGE, [266])
+model.testNbSubShapes(Boolean_7, GeomAPI_Shape.VERTEX, [532])
+model.testResultsVolumes(Boolean_7, [156999.218330596777377650141716003])
 
 assert(model.checkPythonDump)
index 13a6de7505887625c369eee5a292bf7d91bb21f7..2e14ae35c974bd53b49332b751d26afcc0a0efb7 100644 (file)
@@ -3,6 +3,7 @@ from salome.shaper import model
 model.begin()
 partSet = model.moduleDocument()
 Part_1 = model.addPart(partSet)
+Part_1.result().setColor(255, 85, 0)
 Part_1_doc = Part_1.document()
 Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
 SketchLine_1 = Sketch_1.addLine(0, 0, 60, 0)
@@ -165,7 +166,7 @@ SketchLine_21 = Sketch_3.addLine(28, -6, -4.270492394552598, -6.000000000000001)
 SketchLine_21.setName("SketchLine_23")
 SketchLine_21.result().setName("SketchLine_23")
 SketchLine_21.setAuxiliary(True)
-SketchLine_22 = Sketch_3.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_5"))
+SketchLine_22 = Sketch_3.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/Generated_Face_4"))
 SketchLine_22.setName("SketchLine_24")
 SketchLine_22.result().setName("SketchLine_24")
 SketchConstraintCoincidence_27 = Sketch_3.setCoincident(SketchLine_21.startPoint(), SketchLine_22.result())
@@ -276,7 +277,7 @@ SketchConstraintCoincidence_49 = Sketch_3.setCoincident(SketchLine_30.startPoint
 SketchConstraintCoincidence_49.setName("SketchConstraintCoincidence_53")
 SketchConstraintCoincidence_50 = Sketch_3.setCoincident(SketchLine_33.endPoint(), SketchLine_34.endPoint())
 SketchConstraintCoincidence_50.setName("SketchConstraintCoincidence_54")
-SketchPoint_4 = Sketch_3.addPoint(16.50014787857639, -6)
+SketchPoint_4 = Sketch_3.addPoint(16.50014787857639, -5.999999999999999)
 SketchPoint_4.setAuxiliary(True)
 SketchConstraintCoincidence_51 = Sketch_3.setCoincident(SketchPoint_4.coordinates(), SketchLine_34.result())
 SketchConstraintCoincidence_51.setName("SketchConstraintCoincidence_55")
@@ -339,6 +340,8 @@ SketchLine_46.setName("SketchLine_49")
 SketchLine_46.result().setName("SketchLine_49")
 SketchLine_45.setName("SketchLine_48")
 SketchLine_45.result().setName("SketchLine_48")
+SketchLine_44.setName("SketchLine_46")
+SketchLine_44.result().setName("SketchLine_46")
 SketchLine_43.setName("SketchLine_47")
 SketchLine_43.result().setName("SketchLine_47")
 SketchLine_42.setName("SketchLine_46")
@@ -443,33 +446,31 @@ SketchLine_56.result().setName("SketchLine_58")
 model.do()
 ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_6")], model.selection(), model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_7f-SketchArc_1_2f-SketchLine_8f-SketchLine_9f-SketchLine_10r-SketchLine_11r-SketchLine_12r-SketchLine_14r-SketchArc_2_2r"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_5_1")])
 Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_12"))
-SketchLine_64 = Sketch_7.addLine(50.25000013028279, -4.499999999999999, 31.24999999998802, -4.499999999999997)
+SketchLine_64 = Sketch_7.addLine(50.25000000000001, -4.5, 31.24999999998802, -4.499999999999997)
 SketchLine_64.setName("SketchLine_76")
 SketchLine_64.result().setName("SketchLine_76")
-SketchLine_65 = Sketch_7.addLine(51.00000000000001, -6.750000215087569, 51.00000000000001, -5.24999997149696)
+SketchLine_65 = Sketch_7.addLine(51.00000000000001, -6.749999999999998, 51.00000000000001, -5.24999997149696)
 SketchLine_65.setName("SketchLine_78")
 SketchLine_65.result().setName("SketchLine_78")
-SketchLine_66 = Sketch_7.addLine(31, -4.750000022881151, 31.00000000000001, -7.249995609843254)
+SketchLine_66 = Sketch_7.addLine(31, -4.750000022881151, 31, -7.249999999972618)
 SketchLine_66.setName("SketchLine_80")
 SketchLine_66.result().setName("SketchLine_80")
-SketchLine_67 = Sketch_7.addLine(31.25000370007456, -7.499999999999999, 50.24999994039248, -7.5)
+SketchLine_67 = Sketch_7.addLine(31.25000000003855, -7.5, 50.24999994039248, -7.5)
 SketchLine_67.setName("SketchLine_79")
 SketchLine_67.result().setName("SketchLine_79")
-SketchLine_69 = Sketch_7.addLine(51, -4.5, 31, -4.5)
-SketchLine_69.setName("SketchLine_66")
-SketchLine_69.result().setName("SketchLine_66")
-SketchLine_69.setAuxiliary(True)
-SketchLine_68 = Sketch_7.addLine(51, -7.5, 51, -4.5)
-SketchLine_68.setName("SketchLine_69")
-SketchLine_68.result().setName("SketchLine_69")
+SketchLine_68 = Sketch_7.addLine(51, -4.5, 31, -4.5)
+SketchLine_68.setName("SketchLine_66")
+SketchLine_68.result().setName("SketchLine_66")
 SketchLine_68.setAuxiliary(True)
-SketchConstraintCoincidence_74 = Sketch_7.setCoincident(SketchLine_68.endPoint(), SketchLine_69.startPoint())
+SketchLine_69 = Sketch_7.addLine(51, -7.5, 51, -4.5)
+SketchLine_69.setAuxiliary(True)
+SketchConstraintCoincidence_74 = Sketch_7.setCoincident(SketchLine_69.endPoint(), SketchLine_68.startPoint())
 SketchConstraintCoincidence_74.setName("SketchConstraintCoincidence_78")
 SketchLine_70 = Sketch_7.addLine(31, -4.5, 31, -7.5)
 SketchLine_70.setName("SketchLine_67")
 SketchLine_70.result().setName("SketchLine_67")
 SketchLine_70.setAuxiliary(True)
-SketchConstraintCoincidence_75 = Sketch_7.setCoincident(SketchLine_69.endPoint(), SketchLine_70.startPoint())
+SketchConstraintCoincidence_75 = Sketch_7.setCoincident(SketchLine_68.endPoint(), SketchLine_70.startPoint())
 SketchConstraintCoincidence_75.setName("SketchConstraintCoincidence_79")
 SketchLine_71 = Sketch_7.addLine(31, -7.5, 51, -7.5)
 SketchLine_71.setName("SketchLine_68")
@@ -477,14 +478,14 @@ SketchLine_71.result().setName("SketchLine_68")
 SketchLine_71.setAuxiliary(True)
 SketchConstraintCoincidence_76 = Sketch_7.setCoincident(SketchLine_70.endPoint(), SketchLine_71.startPoint())
 SketchConstraintCoincidence_76.setName("SketchConstraintCoincidence_80")
-SketchConstraintCoincidence_77 = Sketch_7.setCoincident(SketchLine_71.endPoint(), SketchLine_68.startPoint())
+SketchConstraintCoincidence_77 = Sketch_7.setCoincident(SketchLine_71.endPoint(), SketchLine_69.startPoint())
 SketchConstraintCoincidence_77.setName("SketchConstraintCoincidence_81")
-SketchConstraintHorizontal_12 = Sketch_7.setHorizontal(SketchLine_69.result())
+SketchConstraintHorizontal_12 = Sketch_7.setHorizontal(SketchLine_68.result())
 SketchConstraintHorizontal_12.setName("SketchConstraintHorizontal_13")
 SketchConstraintVertical_12 = Sketch_7.setVertical(SketchLine_70.result())
 SketchConstraintHorizontal_13 = Sketch_7.setHorizontal(SketchLine_71.result())
 SketchConstraintHorizontal_13.setName("SketchConstraintHorizontal_14")
-SketchConstraintVertical_13 = Sketch_7.setVertical(SketchLine_68.result())
+SketchConstraintVertical_13 = Sketch_7.setVertical(SketchLine_69.result())
 SketchLine_72 = Sketch_7.addLine(31, -7.5, 51, -4.5)
 SketchLine_72.setName("SketchLine_70")
 SketchLine_72.result().setName("SketchLine_70")
@@ -494,16 +495,16 @@ SketchConstraintCoincidence_78.setName("SketchConstraintCoincidence_82")
 SketchConstraintCoincidence_79 = Sketch_7.setCoincident(SketchLine_71.startPoint(), SketchLine_72.startPoint())
 SketchConstraintCoincidence_79.setName("SketchConstraintCoincidence_83")
 SketchPoint_8 = Sketch_7.addPoint(51, -4.5)
-SketchConstraintCoincidence_80 = Sketch_7.setCoincident(SketchLine_69.startPoint(), SketchPoint_8.coordinates())
+SketchConstraintCoincidence_80 = Sketch_7.setCoincident(SketchLine_68.startPoint(), SketchPoint_8.coordinates())
 SketchConstraintCoincidence_80.setName("SketchConstraintCoincidence_84")
-SketchConstraintCoincidence_81 = Sketch_7.setCoincident(SketchLine_68.endPoint(), SketchPoint_8.coordinates())
+SketchConstraintCoincidence_81 = Sketch_7.setCoincident(SketchLine_69.endPoint(), SketchPoint_8.coordinates())
 SketchConstraintCoincidence_81.setName("SketchConstraintCoincidence_85")
 SketchPoint_9 = Sketch_7.addPoint(41, -6)
 SketchPoint_9.setAuxiliary(True)
 SketchConstraintCoincidence_82 = Sketch_7.setCoincident(SketchPoint_9.coordinates(), SketchLine_72.result())
 SketchConstraintCoincidence_82.setName("SketchConstraintCoincidence_86")
 SketchConstraintMiddle_3 = Sketch_7.setMiddlePoint(SketchLine_72.result(), SketchPoint_9.coordinates())
-SketchPoint_10 = Sketch_7.addPoint(21.00014787857639, -6)
+SketchPoint_10 = Sketch_7.addPoint(21.00014787857639, -5.999999999999999)
 SketchPoint_10.setAuxiliary(True)
 SketchLine_73 = Sketch_7.addLine(21.00014787857639, -10.5, 21.00014787857639, -1.499999999999999)
 SketchLine_73.setName("SketchLine_71")
@@ -523,24 +524,24 @@ SketchConstraintCoincidence_85 = Sketch_7.setCoincident(SketchPoint_9.coordinate
 SketchConstraintCoincidence_85.setName("SketchConstraintCoincidence_89")
 SketchConstraintHorizontal_14 = Sketch_7.setHorizontal(SketchLine_74.result())
 SketchConstraintHorizontal_14.setName("SketchConstraintHorizontal_15")
-SketchConstraintCoincidence_86 = Sketch_7.setCoincident(SketchLine_72.endPoint(), SketchLine_69.startPoint())
+SketchConstraintCoincidence_86 = Sketch_7.setCoincident(SketchLine_72.endPoint(), SketchLine_68.startPoint())
 SketchConstraintCoincidence_86.setName("SketchConstraintCoincidence_90")
-SketchConstraintLength_12 = Sketch_7.setLength(SketchLine_68.result(), 3)
+SketchConstraintLength_12 = Sketch_7.setLength(SketchLine_69.result(), 3)
 SketchConstraintLength_12.setName("SketchConstraintLength_13")
-SketchConstraintLength_13 = Sketch_7.setLength(SketchLine_69.result(), 20)
+SketchConstraintLength_13 = Sketch_7.setLength(SketchLine_68.result(), 20)
 SketchConstraintLength_13.setName("SketchConstraintLength_14")
 SketchPoint_11 = Sketch_7.addPoint(29, -10.5)
 SketchConstraintDistance_13 = Sketch_7.setDistance(SketchPoint_11.coordinates(), SketchLine_70.result(), 2)
 SketchConstraintRigid_6 = Sketch_7.setFixed(SketchPoint_11.result())
 SketchConstraintRigid_6.setName("SketchConstraintRigid_15")
-SketchArc_14 = Sketch_7.addArc(50.24999999999999, -5.250000000000003, 51.00000000000001, -5.24999997149696, 50.25000013028279, -4.499999999999999, False)
+SketchArc_14 = Sketch_7.addArc(50.24999999999999, -5.250000000000003, 51.00000000000001, -5.24999997149696, 50.25000000000001, -4.5, False)
 SketchLine_75 = Sketch_7.addLine(51, -7.5, 51.00000000000001, -5.24999997149696)
 SketchLine_75.setName("SketchLine_74")
 SketchLine_75.result().setName("SketchLine_74")
 SketchLine_75.setAuxiliary(True)
 SketchConstraintCoincidence_87 = Sketch_7.setCoincident(SketchArc_14.startPoint(), SketchLine_75.endPoint())
 SketchConstraintCoincidence_87.setName("SketchConstraintCoincidence_91")
-SketchLine_76 = Sketch_7.addLine(50.25000013028279, -4.499999999999999, 31, -4.5)
+SketchLine_76 = Sketch_7.addLine(50.25000000000001, -4.5, 31, -4.5)
 SketchLine_76.setName("SketchLine_73")
 SketchLine_76.result().setName("SketchLine_73")
 SketchLine_76.setAuxiliary(True)
@@ -548,13 +549,13 @@ SketchConstraintCoincidence_88 = Sketch_7.setCoincident(SketchArc_14.endPoint(),
 SketchConstraintCoincidence_88.setName("SketchConstraintCoincidence_92")
 SketchConstraintTangent_1 = Sketch_7.setTangent(SketchArc_14.results()[1], SketchLine_76.result())
 SketchConstraintTangent_2 = Sketch_7.setTangent(SketchArc_14.results()[1], SketchLine_75.result())
-SketchConstraintCoincidence_89 = Sketch_7.setCoincident(SketchLine_69.endPoint(), SketchLine_76.endPoint())
+SketchConstraintCoincidence_89 = Sketch_7.setCoincident(SketchLine_68.endPoint(), SketchLine_76.endPoint())
 SketchConstraintCoincidence_89.setName("SketchConstraintCoincidence_93")
-SketchConstraintCoincidence_90 = Sketch_7.setCoincident(SketchLine_68.startPoint(), SketchLine_75.startPoint())
+SketchConstraintCoincidence_90 = Sketch_7.setCoincident(SketchLine_69.startPoint(), SketchLine_75.startPoint())
 SketchConstraintCoincidence_90.setName("SketchConstraintCoincidence_94")
-SketchConstraintCoincidence_91 = Sketch_7.setCoincident(SketchLine_76.startPoint(), SketchLine_69.result())
+SketchConstraintCoincidence_91 = Sketch_7.setCoincident(SketchLine_76.startPoint(), SketchLine_68.result())
 SketchConstraintCoincidence_91.setName("SketchConstraintCoincidence_95")
-SketchConstraintCoincidence_92 = Sketch_7.setCoincident(SketchLine_75.endPoint(), SketchLine_68.result())
+SketchConstraintCoincidence_92 = Sketch_7.setCoincident(SketchLine_75.endPoint(), SketchLine_69.result())
 SketchConstraintCoincidence_92.setName("SketchConstraintCoincidence_96")
 SketchArc_15 = Sketch_7.addArc(31.25000000000067, -4.750000000000669, 31.24999999998802, -4.499999999999997, 31, -4.750000022881151, False)
 SketchConstraintCoincidence_93 = Sketch_7.setCoincident(SketchArc_15.startPoint(), SketchLine_64.endPoint())
@@ -575,7 +576,7 @@ SketchConstraintCoincidence_97 = Sketch_7.setCoincident(SketchLine_77.startPoint
 SketchConstraintCoincidence_97.setName("SketchConstraintCoincidence_101")
 SketchConstraintCoincidence_98 = Sketch_7.setCoincident(SketchLine_64.endPoint(), SketchLine_76.result())
 SketchConstraintCoincidence_98.setName("SketchConstraintCoincidence_102")
-SketchArc_16 = Sketch_7.addArc(50.25, -6.749999999999999, 50.24999994039248, -7.5, 51.00000000000001, -6.750000215087569, False)
+SketchArc_16 = Sketch_7.addArc(50.25, -6.749999999999999, 50.24999994039248, -7.5, 51.00000000000001, -6.749999999999998, False)
 SketchLine_78 = Sketch_7.addLine(31, -7.5, 50.24999994039248, -7.5)
 SketchLine_78.setName("SketchLine_77")
 SketchLine_78.result().setName("SketchLine_77")
@@ -594,7 +595,7 @@ SketchConstraintCoincidence_103 = Sketch_7.setCoincident(SketchLine_78.endPoint(
 SketchConstraintCoincidence_103.setName("SketchConstraintCoincidence_107")
 SketchConstraintCoincidence_104 = Sketch_7.setCoincident(SketchLine_65.startPoint(), SketchLine_75.result())
 SketchConstraintCoincidence_104.setName("SketchConstraintCoincidence_108")
-SketchArc_17 = Sketch_7.addArc(31.25000000000003, -7.250000000000001, 31.00000000000001, -7.249995609843254, 31.25000370007456, -7.499999999999999, False)
+SketchArc_17 = Sketch_7.addArc(31.25000000000003, -7.250000000000001, 31, -7.249999999972618, 31.25000000003855, -7.5, False)
 SketchConstraintCoincidence_105 = Sketch_7.setCoincident(SketchArc_17.startPoint(), SketchLine_66.endPoint())
 SketchConstraintCoincidence_105.setName("SketchConstraintCoincidence_109")
 SketchConstraintCoincidence_106 = Sketch_7.setCoincident(SketchArc_17.endPoint(), SketchLine_67.startPoint())
@@ -933,16 +934,959 @@ SketchConstraintDistance_17 = Sketch_10.setDistance(SketchLine_105.result(), Ske
 model.do()
 ExtrusionCut_9 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_10/Wire-SketchCircle_1_2f")], model.selection(), 0, 0.75, [model.selection("SOLID", "ExtrusionCut_8_1")])
 model.do()
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Sketch_11 = model.addSketch(Part_2_doc, model.defaultPlane("XOY"))
+SketchLine_107 = Sketch_11.addLine(0, 0, 60, 0)
+SketchPoint_25 = Sketch_11.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchConstraintCoincidence_174 = Sketch_11.setCoincident(SketchLine_107.startPoint(), SketchPoint_25.result())
+SketchLine_108 = Sketch_11.addLine(60, 0, 60, 1.5)
+SketchLine_108.setName("SketchLine_3")
+SketchLine_108.result().setName("SketchLine_3")
+SketchConstraintCoincidence_175 = Sketch_11.setCoincident(SketchLine_107.endPoint(), SketchLine_108.startPoint())
+SketchConstraintCoincidence_175.setName("SketchConstraintCoincidence_3")
+SketchLine_109 = Sketch_11.addLine(60, 1.5, 57, 1.5)
+SketchLine_109.setName("SketchLine_4")
+SketchLine_109.result().setName("SketchLine_4")
+SketchConstraintCoincidence_176 = Sketch_11.setCoincident(SketchLine_108.endPoint(), SketchLine_109.startPoint())
+SketchConstraintCoincidence_176.setName("SketchConstraintCoincidence_4")
+SketchLine_110 = Sketch_11.addLine(57, 1.5, 29, 7.5)
+SketchLine_110.setName("SketchLine_5")
+SketchLine_110.result().setName("SketchLine_5")
+SketchConstraintCoincidence_177 = Sketch_11.setCoincident(SketchLine_109.endPoint(), SketchLine_110.startPoint())
+SketchConstraintCoincidence_177.setName("SketchConstraintCoincidence_5")
+SketchLine_111 = Sketch_11.addLine(28, 7.5, 28, 8)
+SketchLine_111.setName("SketchLine_7")
+SketchLine_111.result().setName("SketchLine_7")
+SketchArc_24 = Sketch_11.addArc(25.00007393928819, 7.9789374678129, 28, 8, 22.00014787857639, 8, False)
+SketchLine_112 = Sketch_11.addLine(22.00014787857639, 8, 22.00014787857639, 7.5)
+SketchLine_112.setName("SketchLine_8")
+SketchLine_112.result().setName("SketchLine_8")
+SketchConstraintCoincidence_178 = Sketch_11.setCoincident(SketchArc_24.endPoint(), SketchLine_112.startPoint())
+SketchConstraintCoincidence_178.setName("SketchConstraintCoincidence_8")
+SketchLine_113 = Sketch_11.addLine(22.00014787857639, 7.5, 21.00014787857639, 7.5)
+SketchLine_113.setName("SketchLine_9")
+SketchLine_113.result().setName("SketchLine_9")
+SketchConstraintCoincidence_179 = Sketch_11.setCoincident(SketchLine_112.endPoint(), SketchLine_113.startPoint())
+SketchConstraintCoincidence_179.setName("SketchConstraintCoincidence_9")
+SketchLine_114 = Sketch_11.addLine(0, 0, 0, 3.499999999999999)
+SketchLine_114.setName("SketchLine_10")
+SketchLine_114.result().setName("SketchLine_10")
+SketchConstraintCoincidence_180 = Sketch_11.setCoincident(SketchLine_107.startPoint(), SketchLine_114.startPoint())
+SketchConstraintCoincidence_180.setName("SketchConstraintCoincidence_10")
+SketchConstraintCoincidence_181 = Sketch_11.setCoincident(SketchPoint_25.coordinates(), SketchLine_114.startPoint())
+SketchConstraintCoincidence_181.setName("SketchConstraintCoincidence_11")
+SketchLine_115 = Sketch_11.addLine(0, 3.499999999999999, 8, 5)
+SketchLine_115.setName("SketchLine_11")
+SketchLine_115.result().setName("SketchLine_11")
+SketchConstraintCoincidence_182 = Sketch_11.setCoincident(SketchLine_114.endPoint(), SketchLine_115.startPoint())
+SketchConstraintCoincidence_182.setName("SketchConstraintCoincidence_13")
+SketchLine_116 = Sketch_11.addLine(8, 5, 10.426976887961, 4.40018070612629)
+SketchLine_116.setName("SketchLine_12")
+SketchLine_116.result().setName("SketchLine_12")
+SketchConstraintCoincidence_183 = Sketch_11.setCoincident(SketchLine_115.endPoint(), SketchLine_116.startPoint())
+SketchConstraintCoincidence_183.setName("SketchConstraintCoincidence_14")
+SketchConstraintLength_18 = Sketch_11.setLength(SketchLine_107.result(), 60)
+SketchConstraintHorizontal_23 = Sketch_11.setHorizontal(SketchLine_107.result())
+SketchConstraintVertical_20 = Sketch_11.setVertical(SketchLine_108.result())
+SketchConstraintHorizontal_24 = Sketch_11.setHorizontal(SketchLine_109.result())
+SketchConstraintHorizontal_25 = Sketch_11.setHorizontal(SketchLine_113.result())
+SketchConstraintHorizontal_25.setName("SketchConstraintHorizontal_4")
+SketchConstraintVertical_21 = Sketch_11.setVertical(SketchLine_111.result())
+SketchConstraintVertical_22 = Sketch_11.setVertical(SketchLine_112.result())
+SketchConstraintCoincidence_184 = Sketch_11.setCoincident(SketchLine_111.endPoint(), SketchArc_24.startPoint())
+SketchConstraintCoincidence_184.setName("SketchConstraintCoincidence_15")
+SketchConstraintVertical_23 = Sketch_11.setVertical(SketchLine_114.result())
+SketchConstraintDistance_18 = Sketch_11.setDistance(SketchLine_114.endPoint(), SketchLine_107.result(), 3.5)
+SketchConstraintDistance_19 = Sketch_11.setDistance(SketchLine_115.endPoint(), SketchLine_114.result(), 8)
+SketchConstraintLength_19 = Sketch_11.setLength(SketchLine_116.result(), 2.5)
+SketchConstraintRadius_12 = Sketch_11.setRadius(SketchArc_24.results()[1], 3)
+SketchConstraintLength_20 = Sketch_11.setLength(SketchLine_112.result(), 0.5)
+SketchConstraintLength_21 = Sketch_11.setLength(SketchLine_113.result(), 1)
+SketchConstraintLength_22 = Sketch_11.setLength(SketchLine_111.result(), 0.5)
+SketchConstraintDistance_20 = Sketch_11.setDistance(SketchLine_112.endPoint(), SketchLine_107.result(), 7.5)
+SketchConstraintLength_23 = Sketch_11.setLength(SketchLine_109.result(), 3)
+SketchConstraintLength_23.setName("SketchConstraintLength_7")
+SketchConstraintLength_24 = Sketch_11.setLength(SketchLine_108.result(), 1.5)
+SketchConstraintLength_24.setName("SketchConstraintLength_8")
+SketchConstraintDistance_21 = Sketch_11.setDistance(SketchLine_115.endPoint(), SketchLine_107.result(), 5)
+SketchConstraintDistance_22 = Sketch_11.setDistance(SketchLine_111.startPoint(), SketchLine_107.result(), 7.5)
+SketchLine_117 = Sketch_11.addLine(12.81710695710752, 0, 12.81710695710752, 7.765286531476907)
+SketchLine_117.setName("SketchLine_13")
+SketchLine_117.result().setName("SketchLine_13")
+SketchLine_117.setAuxiliary(True)
+SketchConstraintCoincidence_185 = Sketch_11.setCoincident(SketchLine_117.startPoint(), SketchLine_107.result())
+SketchConstraintCoincidence_185.setName("SketchConstraintCoincidence_16")
+SketchConstraintVertical_24 = Sketch_11.setVertical(SketchLine_117.result())
+SketchPoint_26 = Sketch_11.addPoint(12.81710695710752, 3)
+SketchPoint_26.setAuxiliary(True)
+SketchConstraintCoincidence_186 = Sketch_11.setCoincident(SketchPoint_26.coordinates(), SketchLine_117.result())
+SketchConstraintCoincidence_186.setName("SketchConstraintCoincidence_17")
+SketchConstraintDistance_23 = Sketch_11.setDistance(SketchPoint_26.coordinates(), SketchLine_107.result(), 3)
+SketchLine_118 = Sketch_11.addLine(28, 7.5, 29, 7.5)
+SketchLine_118.setName("SketchLine_14")
+SketchLine_118.result().setName("SketchLine_14")
+SketchConstraintCoincidence_187 = Sketch_11.setCoincident(SketchLine_111.startPoint(), SketchLine_118.startPoint())
+SketchConstraintCoincidence_187.setName("SketchConstraintCoincidence_18")
+SketchConstraintCoincidence_188 = Sketch_11.setCoincident(SketchLine_110.endPoint(), SketchLine_118.endPoint())
+SketchConstraintCoincidence_188.setName("SketchConstraintCoincidence_19")
+SketchConstraintLength_25 = Sketch_11.setLength(SketchLine_118.result(), 1)
+SketchConstraintLength_25.setName("SketchConstraintLength_9")
+SketchArc_25 = Sketch_11.addArc(14.78851987160339, 9.105317068618911, 10.426976887961, 4.40018070612629, 21.00014787857639, 7.5, False)
+SketchConstraintCoincidence_189 = Sketch_11.setCoincident(SketchLine_116.endPoint(), SketchArc_25.startPoint())
+SketchConstraintCoincidence_189.setName("SketchConstraintCoincidence_20")
+SketchConstraintCoincidence_190 = Sketch_11.setCoincident(SketchLine_113.endPoint(), SketchArc_25.endPoint())
+SketchConstraintCoincidence_190.setName("SketchConstraintCoincidence_21")
+SketchConstraintCoincidence_191 = Sketch_11.setCoincident(SketchPoint_26.coordinates(), SketchArc_25.results()[1])
+SketchConstraintCoincidence_191.setName("SketchConstraintCoincidence_22")
+SketchConstraintHorizontal_26 = Sketch_11.setHorizontal(SketchLine_118.result())
+SketchConstraintHorizontal_26.setName("SketchConstraintHorizontal_9")
+SketchConstraintDistance_24 = Sketch_11.setDistance(SketchLine_111.startPoint(), SketchLine_108.result(), 32)
+SketchConstraintDistance_24.setName("SketchConstraintDistance_9")
+model.do()
+Extrusion_2 = model.addExtrusion(Part_2_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_7f-SketchArc_1_2f-SketchLine_8f-SketchLine_9f-SketchLine_10r-SketchLine_11r-SketchLine_12r-SketchLine_14r-SketchArc_2_2r")], model.selection(), 12, 0)
+Sketch_12 = model.addSketch(Part_2_doc, model.selection("FACE", "PartSet/XOZ"))
+SketchArc_26 = Sketch_12.addArc(53.99996594708078, 6.000000000028422, 54, 12, 53.99994409538203, -3.231174267785264e-027, True)
+SketchLine_119 = Sketch_12.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_13&Extrusion_1_1/To_Face_1"))
+SketchLine_119.setName("SketchLine_15")
+SketchLine_119.result().setName("SketchLine_15")
+SketchConstraintCoincidence_192 = Sketch_12.setCoincident(SketchArc_26.startPoint(), SketchLine_119.result())
+SketchConstraintCoincidence_192.setName("SketchConstraintCoincidence_23")
+SketchLine_120 = Sketch_12.addLine(model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"))
+SketchLine_120.setName("SketchLine_16")
+SketchLine_120.result().setName("SketchLine_16")
+SketchConstraintCoincidence_193 = Sketch_12.setCoincident(SketchArc_26.endPoint(), SketchLine_120.result())
+SketchConstraintCoincidence_193.setName("SketchConstraintCoincidence_24")
+SketchConstraintRadius_13 = Sketch_12.setRadius(SketchArc_26.results()[1], 6)
+SketchLine_121 = Sketch_12.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_13&Extrusion_1_1/Generated_Face_1"))
+SketchLine_121.setName("SketchLine_17")
+SketchLine_121.result().setName("SketchLine_17")
+SketchConstraintDistance_25 = Sketch_12.setDistance(SketchArc_26.startPoint(), SketchLine_121.result(), 6)
+SketchConstraintDistance_25.setName("SketchConstraintDistance_7")
+SketchLine_122 = Sketch_12.addLine(54, 12, 53.10174978726379, 13.92603605930655)
+SketchLine_122.setName("SketchLine_18")
+SketchLine_122.result().setName("SketchLine_18")
+SketchConstraintCoincidence_194 = Sketch_12.setCoincident(SketchArc_26.startPoint(), SketchLine_122.startPoint())
+SketchConstraintCoincidence_194.setName("SketchConstraintCoincidence_25")
+SketchLine_123 = Sketch_12.addLine(53.10174978726379, 13.92603605930655, 63.82610057919769, 13.82486293862793)
+SketchLine_123.setName("SketchLine_19")
+SketchLine_123.result().setName("SketchLine_19")
+SketchConstraintCoincidence_195 = Sketch_12.setCoincident(SketchLine_122.endPoint(), SketchLine_123.startPoint())
+SketchConstraintCoincidence_195.setName("SketchConstraintCoincidence_26")
+SketchLine_124 = Sketch_12.addLine(63.82610057919769, 13.82486293862793, 62.66260969139353, -3.07104821470189)
+SketchLine_124.setName("SketchLine_20")
+SketchLine_124.result().setName("SketchLine_20")
+SketchConstraintCoincidence_196 = Sketch_12.setCoincident(SketchLine_123.endPoint(), SketchLine_124.startPoint())
+SketchConstraintCoincidence_196.setName("SketchConstraintCoincidence_27")
+SketchLine_125 = Sketch_12.addLine(62.66260969139353, -3.07104821470189, 53.10174978726379, -2.868701973344648)
+SketchLine_125.setName("SketchLine_21")
+SketchLine_125.result().setName("SketchLine_21")
+SketchConstraintCoincidence_197 = Sketch_12.setCoincident(SketchLine_124.endPoint(), SketchLine_125.startPoint())
+SketchConstraintCoincidence_197.setName("SketchConstraintCoincidence_28")
+SketchLine_126 = Sketch_12.addLine(53.10174978726379, -2.868701973344648, 53.99994409538203, -3.231174267785264e-027)
+SketchLine_126.setName("SketchLine_22")
+SketchLine_126.result().setName("SketchLine_22")
+SketchConstraintCoincidence_198 = Sketch_12.setCoincident(SketchLine_125.endPoint(), SketchLine_126.startPoint())
+SketchConstraintCoincidence_198.setName("SketchConstraintCoincidence_29")
+SketchConstraintCoincidence_199 = Sketch_12.setCoincident(SketchArc_26.endPoint(), SketchLine_126.endPoint())
+SketchConstraintCoincidence_199.setName("SketchConstraintCoincidence_30")
+model.do()
+ExtrusionCut_10 = model.addExtrusionCut(Part_2_doc, [model.selection("FACE", "Sketch_2/Face-SketchArc_3_2r-SketchLine_18r-SketchLine_19r-SketchLine_20r-SketchLine_21r-SketchLine_22r")], model.selection(), 7, 15, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_13 = model.addSketch(Part_2_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"))
+SketchLine_127 = Sketch_13.addLine(28, -6, -4.270492394552598, -6.000000000000001)
+SketchLine_127.setName("SketchLine_23")
+SketchLine_127.result().setName("SketchLine_23")
+SketchLine_127.setAuxiliary(True)
+SketchLine_128 = Sketch_13.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/Generated_Face_4"))
+SketchLine_128.setName("SketchLine_24")
+SketchLine_128.result().setName("SketchLine_24")
+SketchConstraintCoincidence_200 = Sketch_13.setCoincident(SketchLine_127.startPoint(), SketchLine_128.result())
+SketchConstraintCoincidence_200.setName("SketchConstraintCoincidence_31")
+SketchConstraintHorizontal_27 = Sketch_13.setHorizontal(SketchLine_127.result())
+SketchLine_129 = Sketch_13.addLine(28, -6, 63.78468475453244, -6.000000000000001)
+SketchLine_129.setName("SketchLine_25")
+SketchLine_129.result().setName("SketchLine_25")
+SketchLine_129.setAuxiliary(True)
+SketchConstraintCoincidence_201 = Sketch_13.setCoincident(SketchLine_127.startPoint(), SketchLine_129.startPoint())
+SketchConstraintCoincidence_201.setName("SketchConstraintCoincidence_32")
+SketchConstraintHorizontal_28 = Sketch_13.setHorizontal(SketchLine_129.result())
+SketchLine_130 = Sketch_13.addLine(60, -1.500000000000001, 29, -1.500000000000001)
+SketchLine_130.setName("SketchLine_26")
+SketchLine_130.result().setName("SketchLine_26")
+SketchLine_131 = Sketch_13.addLine(29, -1.500000000000001, 29, -10.5)
+SketchLine_131.setName("SketchLine_27")
+SketchLine_131.result().setName("SketchLine_27")
+SketchLine_132 = Sketch_13.addLine(29, -10.5, 60, -10.5)
+SketchLine_132.setName("SketchLine_28")
+SketchLine_132.result().setName("SketchLine_28")
+SketchLine_133 = Sketch_13.addLine(60, -10.5, 60, -1.500000000000001)
+SketchLine_133.setName("SketchLine_29")
+SketchLine_133.result().setName("SketchLine_29")
+SketchConstraintCoincidence_202 = Sketch_13.setCoincident(SketchLine_133.endPoint(), SketchLine_130.startPoint())
+SketchConstraintCoincidence_202.setName("SketchConstraintCoincidence_33")
+SketchConstraintCoincidence_203 = Sketch_13.setCoincident(SketchLine_130.endPoint(), SketchLine_131.startPoint())
+SketchConstraintCoincidence_203.setName("SketchConstraintCoincidence_34")
+SketchConstraintCoincidence_204 = Sketch_13.setCoincident(SketchLine_131.endPoint(), SketchLine_132.startPoint())
+SketchConstraintCoincidence_204.setName("SketchConstraintCoincidence_35")
+SketchConstraintCoincidence_205 = Sketch_13.setCoincident(SketchLine_132.endPoint(), SketchLine_133.startPoint())
+SketchConstraintCoincidence_205.setName("SketchConstraintCoincidence_36")
+SketchConstraintHorizontal_29 = Sketch_13.setHorizontal(SketchLine_130.result())
+SketchConstraintVertical_25 = Sketch_13.setVertical(SketchLine_131.result())
+SketchConstraintHorizontal_30 = Sketch_13.setHorizontal(SketchLine_132.result())
+SketchConstraintVertical_26 = Sketch_13.setVertical(SketchLine_133.result())
+SketchLine_134 = Sketch_13.addLine(29, -10.5, 60, -1.500000000000001)
+SketchLine_134.setName("SketchLine_30")
+SketchLine_134.result().setName("SketchLine_30")
+SketchLine_134.setAuxiliary(True)
+SketchConstraintCoincidence_206 = Sketch_13.setCoincident(SketchLine_131.endPoint(), SketchLine_134.startPoint())
+SketchConstraintCoincidence_206.setName("SketchConstraintCoincidence_37")
+SketchConstraintCoincidence_207 = Sketch_13.setCoincident(SketchLine_132.startPoint(), SketchLine_134.startPoint())
+SketchConstraintCoincidence_207.setName("SketchConstraintCoincidence_38")
+SketchConstraintCoincidence_208 = Sketch_13.setCoincident(SketchLine_130.startPoint(), SketchLine_134.endPoint())
+SketchConstraintCoincidence_208.setName("SketchConstraintCoincidence_39")
+SketchConstraintCoincidence_209 = Sketch_13.setCoincident(SketchLine_133.endPoint(), SketchLine_134.endPoint())
+SketchConstraintCoincidence_209.setName("SketchConstraintCoincidence_40")
+SketchLine_135 = Sketch_13.addLine(29, -1.500000000000001, 60, -10.5)
+SketchLine_135.setName("SketchLine_31")
+SketchLine_135.result().setName("SketchLine_31")
+SketchLine_135.setAuxiliary(True)
+SketchConstraintCoincidence_210 = Sketch_13.setCoincident(SketchLine_130.endPoint(), SketchLine_135.startPoint())
+SketchConstraintCoincidence_210.setName("SketchConstraintCoincidence_41")
+SketchConstraintCoincidence_211 = Sketch_13.setCoincident(SketchLine_131.startPoint(), SketchLine_135.startPoint())
+SketchConstraintCoincidence_211.setName("SketchConstraintCoincidence_42")
+SketchConstraintCoincidence_212 = Sketch_13.setCoincident(SketchLine_132.endPoint(), SketchLine_135.endPoint())
+SketchConstraintCoincidence_212.setName("SketchConstraintCoincidence_43")
+SketchConstraintCoincidence_213 = Sketch_13.setCoincident(SketchLine_133.startPoint(), SketchLine_135.endPoint())
+SketchConstraintCoincidence_213.setName("SketchConstraintCoincidence_44")
+SketchPoint_27 = Sketch_13.addPoint(44.5, -6.000000000000001)
+SketchPoint_27.setAuxiliary(True)
+SketchConstraintCoincidence_214 = Sketch_13.setCoincident(SketchPoint_27.coordinates(), SketchLine_135.result())
+SketchConstraintCoincidence_214.setName("SketchConstraintCoincidence_45")
+SketchConstraintMiddle_9 = Sketch_13.setMiddlePoint(SketchPoint_27.coordinates(), SketchLine_135.result())
+SketchConstraintCoincidence_215 = Sketch_13.setCoincident(SketchPoint_27.coordinates(), SketchLine_129.result())
+SketchConstraintCoincidence_215.setName("SketchConstraintCoincidence_46")
+SketchConstraintDistance_26 = Sketch_13.setDistance(SketchLine_128.startPoint(), SketchLine_129.result(), 6)
+SketchConstraintDistance_26.setName("SketchConstraintDistance_8")
+SketchConstraintLength_26 = Sketch_13.setLength(SketchLine_133.result(), 9)
+SketchConstraintLength_26.setName("SketchConstraintLength_10")
+SketchLine_136 = Sketch_13.addLine(21.00014787857639, -1.499999999999999, 12.00014787857639, -1.499999999999999)
+SketchLine_136.setName("SketchLine_32")
+SketchLine_136.result().setName("SketchLine_32")
+SketchLine_137 = Sketch_13.addLine(12.00014787857639, -1.499999999999999, 12.00014787857639, -10.5)
+SketchLine_137.setName("SketchLine_33")
+SketchLine_137.result().setName("SketchLine_33")
+SketchLine_138 = Sketch_13.addLine(12.00014787857639, -10.5, 21.00014787857639, -10.5)
+SketchLine_138.setName("SketchLine_34")
+SketchLine_138.result().setName("SketchLine_34")
+SketchLine_139 = Sketch_13.addLine(21.00014787857639, -10.5, 21.00014787857639, -1.499999999999999)
+SketchLine_139.setName("SketchLine_35")
+SketchLine_139.result().setName("SketchLine_35")
+SketchConstraintCoincidence_216 = Sketch_13.setCoincident(SketchLine_139.endPoint(), SketchLine_136.startPoint())
+SketchConstraintCoincidence_216.setName("SketchConstraintCoincidence_47")
+SketchConstraintCoincidence_217 = Sketch_13.setCoincident(SketchLine_136.endPoint(), SketchLine_137.startPoint())
+SketchConstraintCoincidence_217.setName("SketchConstraintCoincidence_48")
+SketchConstraintCoincidence_218 = Sketch_13.setCoincident(SketchLine_137.endPoint(), SketchLine_138.startPoint())
+SketchConstraintCoincidence_218.setName("SketchConstraintCoincidence_49")
+SketchConstraintCoincidence_219 = Sketch_13.setCoincident(SketchLine_138.endPoint(), SketchLine_139.startPoint())
+SketchConstraintCoincidence_219.setName("SketchConstraintCoincidence_50")
+SketchConstraintHorizontal_31 = Sketch_13.setHorizontal(SketchLine_136.result())
+SketchConstraintHorizontal_31.setName("SketchConstraintHorizontal_10")
+SketchConstraintVertical_27 = Sketch_13.setVertical(SketchLine_137.result())
+SketchConstraintHorizontal_32 = Sketch_13.setHorizontal(SketchLine_138.result())
+SketchConstraintHorizontal_32.setName("SketchConstraintHorizontal_11")
+SketchConstraintVertical_28 = Sketch_13.setVertical(SketchLine_139.result())
+SketchConstraintEqual_4 = Sketch_13.setEqual(SketchLine_131.result(), SketchLine_139.result())
+SketchLine_140 = Sketch_13.addLine(12.00014787857639, -10.5, 21.00014787857639, -1.499999999999999)
+SketchLine_140.setName("SketchLine_36")
+SketchLine_140.result().setName("SketchLine_36")
+SketchLine_140.setAuxiliary(True)
+SketchConstraintCoincidence_220 = Sketch_13.setCoincident(SketchLine_137.endPoint(), SketchLine_140.startPoint())
+SketchConstraintCoincidence_220.setName("SketchConstraintCoincidence_51")
+SketchConstraintCoincidence_221 = Sketch_13.setCoincident(SketchLine_138.startPoint(), SketchLine_140.startPoint())
+SketchConstraintCoincidence_221.setName("SketchConstraintCoincidence_52")
+SketchConstraintCoincidence_222 = Sketch_13.setCoincident(SketchLine_136.startPoint(), SketchLine_140.endPoint())
+SketchConstraintCoincidence_222.setName("SketchConstraintCoincidence_53")
+SketchConstraintCoincidence_223 = Sketch_13.setCoincident(SketchLine_139.endPoint(), SketchLine_140.endPoint())
+SketchConstraintCoincidence_223.setName("SketchConstraintCoincidence_54")
+SketchPoint_28 = Sketch_13.addPoint(16.50014787857639, -5.999999999999999)
+SketchPoint_28.setAuxiliary(True)
+SketchConstraintCoincidence_224 = Sketch_13.setCoincident(SketchPoint_28.coordinates(), SketchLine_140.result())
+SketchConstraintCoincidence_224.setName("SketchConstraintCoincidence_55")
+SketchConstraintMiddle_10 = Sketch_13.setMiddlePoint(SketchLine_140.result(), SketchPoint_28.coordinates())
+SketchConstraintCoincidence_225 = Sketch_13.setCoincident(SketchPoint_28.coordinates(), SketchLine_127.result())
+SketchConstraintCoincidence_225.setName("SketchConstraintCoincidence_56")
+SketchLine_141 = Sketch_13.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&ExtrusionCut_1_1/Modfied_4"))
+SketchLine_141.setName("SketchLine_37")
+SketchLine_141.result().setName("SketchLine_37")
+SketchConstraintCoincidence_226 = Sketch_13.setCoincident(SketchLine_131.startPoint(), SketchLine_141.result())
+SketchConstraintCoincidence_226.setName("SketchConstraintCoincidence_57")
+SketchConstraintLength_27 = Sketch_13.setLength(SketchLine_130.result(), 31)
+SketchConstraintLength_27.setName("SketchConstraintLength_11")
+SketchLine_142 = Sketch_13.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/Generated_Face_8"))
+SketchLine_142.setName("SketchLine_38")
+SketchLine_142.result().setName("SketchLine_38")
+SketchConstraintCoincidence_227 = Sketch_13.setCoincident(SketchLine_136.startPoint(), SketchLine_142.result())
+SketchConstraintCoincidence_227.setName("SketchConstraintCoincidence_58")
+SketchConstraintEqual_5 = Sketch_13.setEqual(SketchLine_136.result(), SketchLine_131.result())
+model.do()
+ExtrusionCut_11 = model.addExtrusionCut(Part_2_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_32f-SketchLine_33f-SketchLine_34f-SketchLine_35f"), model.selection("FACE", "Sketch_3/Face-SketchLine_26f-SketchLine_27f-SketchLine_28f-SketchLine_29f")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_3"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
+Sketch_14 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_1"))
+SketchLine_143 = Sketch_14.addLine(0.4324637622511017, 3.581086955422081, 1.55585595716119, 2.812450190483599)
+SketchLine_143.setName("SketchLine_39")
+SketchLine_143.result().setName("SketchLine_39")
+SketchLine_144 = Sketch_14.addLine(model.selection("EDGE", "ExtrusionCut_1_1/Modfied_1&Extrusion_1_1/Generated_Face_11"))
+SketchLine_144.setName("SketchLine_40")
+SketchLine_144.result().setName("SketchLine_40")
+SketchConstraintCoincidence_228 = Sketch_14.setCoincident(SketchLine_143.startPoint(), SketchLine_144.result())
+SketchConstraintCoincidence_228.setName("SketchConstraintCoincidence_59")
+SketchLine_145 = Sketch_14.addLine(1.55585595716119, 2.812450190483599, 2.324492722099671, 3.935842385393688)
+SketchLine_145.setName("SketchLine_41")
+SketchLine_145.result().setName("SketchLine_41")
+SketchConstraintCoincidence_229 = Sketch_14.setCoincident(SketchLine_143.endPoint(), SketchLine_145.startPoint())
+SketchConstraintCoincidence_229.setName("SketchConstraintCoincidence_60")
+SketchConstraintCoincidence_230 = Sketch_14.setCoincident(SketchLine_145.endPoint(), SketchLine_144.result())
+SketchConstraintCoincidence_230.setName("SketchConstraintCoincidence_61")
+SketchLine_146 = Sketch_14.addLine(2.324492722099671, 3.935842385393688, 0.4324637622511017, 3.581086955422081)
+SketchLine_146.setName("SketchLine_42")
+SketchLine_146.result().setName("SketchLine_42")
+SketchConstraintCoincidence_231 = Sketch_14.setCoincident(SketchLine_145.endPoint(), SketchLine_146.startPoint())
+SketchConstraintCoincidence_231.setName("SketchConstraintCoincidence_62")
+SketchConstraintCoincidence_232 = Sketch_14.setCoincident(SketchLine_143.startPoint(), SketchLine_146.endPoint())
+SketchConstraintCoincidence_232.setName("SketchConstraintCoincidence_63")
+SketchConstraintLength_28 = Sketch_14.setLength(SketchLine_146.result(), 1.925)
+SketchConstraintLength_28.setName("SketchConstraintLength_12")
+SketchConstraintEqual_6 = Sketch_14.setEqual(SketchLine_143.result(), SketchLine_145.result())
+SketchConstraintPerpendicular_2 = Sketch_14.setPerpendicular(SketchLine_143.result(), SketchLine_145.result())
+SketchConstraintDistance_27 = Sketch_14.setDistance(SketchLine_144.startPoint(), SketchLine_143.startPoint(), 0.44)
+SketchMultiTranslation_3_objects = [SketchLine_143.result(), SketchLine_146.result(), SketchLine_145.result()]
+SketchMultiTranslation_3 = Sketch_14.addTranslation(SketchMultiTranslation_3_objects, SketchLine_146.startPoint(), SketchLine_144.endPoint(), 4, True)
+[SketchLine_147, SketchLine_148, SketchLine_149, SketchLine_150, SketchLine_151, SketchLine_152, SketchLine_153, SketchLine_154, SketchLine_155] = SketchMultiTranslation_3.translated()
+SketchLine_155.setName("SketchLine_51")
+SketchLine_155.result().setName("SketchLine_51")
+SketchLine_154.setName("SketchLine_50")
+SketchLine_154.result().setName("SketchLine_50")
+SketchLine_153.setName("SketchLine_45")
+SketchLine_153.result().setName("SketchLine_45")
+SketchLine_152.setName("SketchLine_49")
+SketchLine_152.result().setName("SketchLine_49")
+SketchLine_151.setName("SketchLine_48")
+SketchLine_151.result().setName("SketchLine_48")
+SketchLine_150.setName("SketchLine_46")
+SketchLine_150.result().setName("SketchLine_46")
+SketchLine_149.setName("SketchLine_47")
+SketchLine_149.result().setName("SketchLine_47")
+SketchLine_148.setName("SketchLine_46")
+SketchLine_148.result().setName("SketchLine_46")
+SketchLine_147.setName("SketchLine_43")
+SketchLine_147.result().setName("SketchLine_43")
+model.do()
+ExtrusionCut_12 = model.addExtrusionCut(Part_2_doc, [model.selection("COMPOUND", "Sketch_4")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_2"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
+Plane_9 = model.addPlane(Part_2_doc, model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_12"), model.selection("VERTEX", "ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_6"), model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_2_1/Modfied_9&ExtrusionCut_3_1/Modfied_3"))
+Sketch_15 = model.addSketch(Part_2_doc, model.selection("FACE", "Plane_1"))
+SketchArc_27 = Sketch_15.addArc(25.00007393928819, -7.521062532210847, 22.00014787857639, -7.5, 28, -7.5, True)
+SketchPoint_29 = Sketch_15.addPoint(22.00014787857639, -7.5)
+SketchConstraintRigid_14 = Sketch_15.setFixed(SketchPoint_29.result())
+SketchConstraintRigid_14.setName("SketchConstraintRigid_10")
+SketchConstraintCoincidence_233 = Sketch_15.setCoincident(SketchArc_27.startPoint(), SketchPoint_29.result())
+SketchConstraintCoincidence_233.setName("SketchConstraintCoincidence_64")
+SketchPoint_30 = Sketch_15.addPoint(28, -7.5)
+SketchConstraintRigid_15 = Sketch_15.setFixed(SketchPoint_30.result())
+SketchConstraintRigid_15.setName("SketchConstraintRigid_11")
+SketchConstraintCoincidence_234 = Sketch_15.setCoincident(SketchArc_27.endPoint(), SketchPoint_30.result())
+SketchConstraintCoincidence_234.setName("SketchConstraintCoincidence_65")
+SketchConstraintRadius_14 = Sketch_15.setRadius(SketchArc_27.results()[1], 3)
+SketchLine_156 = Sketch_15.addLine(22.00014787857639, -7.5, 22.00014787857639, -11.56094005408083)
+SketchLine_156.setName("SketchLine_52")
+SketchLine_156.result().setName("SketchLine_52")
+SketchConstraintCoincidence_235 = Sketch_15.setCoincident(SketchArc_27.startPoint(), SketchLine_156.startPoint())
+SketchConstraintCoincidence_235.setName("SketchConstraintCoincidence_66")
+SketchConstraintCoincidence_236 = Sketch_15.setCoincident(SketchPoint_29.coordinates(), SketchLine_156.startPoint())
+SketchConstraintCoincidence_236.setName("SketchConstraintCoincidence_67")
+SketchLine_157 = Sketch_15.addLine(22.00014787857639, -11.56094005408083, 28, -11.56094005408083)
+SketchLine_157.setName("SketchLine_53")
+SketchLine_157.result().setName("SketchLine_53")
+SketchConstraintCoincidence_237 = Sketch_15.setCoincident(SketchLine_156.endPoint(), SketchLine_157.startPoint())
+SketchConstraintCoincidence_237.setName("SketchConstraintCoincidence_68")
+SketchLine_158 = Sketch_15.addLine(28, -11.56094005408083, 28, -7.5)
+SketchLine_158.setName("SketchLine_54")
+SketchLine_158.result().setName("SketchLine_54")
+SketchConstraintCoincidence_238 = Sketch_15.setCoincident(SketchLine_157.endPoint(), SketchLine_158.startPoint())
+SketchConstraintCoincidence_238.setName("SketchConstraintCoincidence_69")
+SketchConstraintCoincidence_239 = Sketch_15.setCoincident(SketchArc_27.endPoint(), SketchLine_158.endPoint())
+SketchConstraintCoincidence_239.setName("SketchConstraintCoincidence_70")
+SketchConstraintCoincidence_240 = Sketch_15.setCoincident(SketchPoint_30.coordinates(), SketchLine_158.endPoint())
+SketchConstraintCoincidence_240.setName("SketchConstraintCoincidence_71")
+SketchConstraintVertical_29 = Sketch_15.setVertical(SketchLine_156.result())
+SketchConstraintVertical_30 = Sketch_15.setVertical(SketchLine_158.result())
+SketchConstraintHorizontal_33 = Sketch_15.setHorizontal(SketchLine_157.result())
+SketchConstraintHorizontal_33.setName("SketchConstraintHorizontal_12")
+model.do()
+Plane_10 = model.addPlane(Part_2_doc, model.selection("FACE", "ExtrusionCut_3_1/Modfied_3"), 6, True)
+Plane_11 = model.addPlane(Part_2_doc, model.selection("FACE", "Plane_2"), 3, True)
+ExtrusionCut_13 = model.addExtrusionCut(Part_2_doc, [model.selection("FACE", "Sketch_5/Face-SketchArc_4_2f-SketchLine_52f-SketchLine_53f-SketchLine_54f")], model.selection(), 3, 0, [model.selection("SOLID", "ExtrusionCut_3_1")])
+ExtrusionCut_14 = model.addExtrusionCut(Part_2_doc, [model.selection("FACE", "Sketch_5/Face-SketchArc_4_2f-SketchLine_52f-SketchLine_53f-SketchLine_54f")], model.selection(), model.selection("FACE", "Plane_3"), 0, model.selection("FACE", "Plane_2"), 0, [model.selection("SOLID", "ExtrusionCut_4_1")])
+Sketch_16 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_4_1/Modfied_6"))
+SketchArc_28 = Sketch_16.addArc(45.99999999999999, 0, 45.49999999999999, 8.91700958118717e-020, 46.49999999999999, 8.280962276646116e-019, False)
+SketchLine_159 = Sketch_16.addLine(0, 0, 54, 0)
+SketchLine_159.setName("SketchLine_55")
+SketchLine_159.result().setName("SketchLine_55")
+SketchConstraintRigid_16 = Sketch_16.setFixed(SketchLine_159.result())
+SketchConstraintRigid_16.setName("SketchConstraintRigid_12")
+SketchConstraintCoincidence_241 = Sketch_16.setCoincident(SketchArc_28.center(), SketchLine_159.result())
+SketchConstraintCoincidence_241.setName("SketchConstraintCoincidence_72")
+SketchConstraintCoincidence_242 = Sketch_16.setCoincident(SketchArc_28.startPoint(), SketchLine_159.result())
+SketchConstraintCoincidence_242.setName("SketchConstraintCoincidence_73")
+SketchConstraintCoincidence_243 = Sketch_16.setCoincident(SketchArc_28.endPoint(), SketchLine_159.result())
+SketchConstraintCoincidence_243.setName("SketchConstraintCoincidence_74")
+SketchLine_160 = Sketch_16.addLine(45.49999999999999, 8.91700958118717e-020, 46.49999999999999, 8.280962276646116e-019)
+SketchLine_160.setName("SketchLine_56")
+SketchLine_160.result().setName("SketchLine_56")
+SketchConstraintCoincidence_244 = Sketch_16.setCoincident(SketchArc_28.startPoint(), SketchLine_160.startPoint())
+SketchConstraintCoincidence_244.setName("SketchConstraintCoincidence_75")
+SketchConstraintCoincidence_245 = Sketch_16.setCoincident(SketchArc_28.endPoint(), SketchLine_160.endPoint())
+SketchConstraintCoincidence_245.setName("SketchConstraintCoincidence_76")
+SketchConstraintRadius_15 = Sketch_16.setRadius(SketchArc_28.results()[1], 0.5)
+SketchLine_161 = Sketch_16.addLine(0, 0, 0, 3.499999999999999)
+SketchLine_161.setName("SketchLine_57")
+SketchLine_161.result().setName("SketchLine_57")
+SketchConstraintDistance_28 = Sketch_16.setDistance(SketchArc_28.center(), SketchLine_161.result(), 46)
+SketchConstraintRigid_17 = Sketch_16.setFixed(SketchLine_161.result())
+SketchConstraintRigid_17.setName("SketchConstraintRigid_13")
+SketchPoint_31 = Sketch_16.addPoint(58, 0)
+SketchConstraintCoincidence_246 = Sketch_16.setCoincident(SketchPoint_31.coordinates(), SketchLine_159.result())
+SketchConstraintCoincidence_246.setName("SketchConstraintCoincidence_77")
+SketchConstraintDistance_29 = Sketch_16.setDistance(SketchArc_28.center(), SketchPoint_31.coordinates(), 12)
+SketchMultiTranslation_4 = Sketch_16.addTranslation([SketchLine_160.result(), SketchArc_28.results()[1]], SketchArc_28.center(), SketchPoint_31.coordinates(), 9, True)
+[SketchLine_162, SketchLine_163, SketchLine_164, SketchLine_165, SketchLine_166, SketchLine_167, SketchLine_168, SketchLine_169, SketchArc_29, SketchArc_30, SketchArc_31, SketchArc_32, SketchArc_33, SketchArc_34, SketchArc_35, SketchArc_36] = SketchMultiTranslation_4.translated()
+SketchLine_169.setName("SketchLine_65")
+SketchLine_169.result().setName("SketchLine_65")
+SketchLine_168.setName("SketchLine_64")
+SketchLine_168.result().setName("SketchLine_64")
+SketchLine_167.setName("SketchLine_63")
+SketchLine_167.result().setName("SketchLine_63")
+SketchLine_166.setName("SketchLine_62")
+SketchLine_166.result().setName("SketchLine_62")
+SketchLine_165.setName("SketchLine_61")
+SketchLine_165.result().setName("SketchLine_61")
+SketchLine_164.setName("SketchLine_60")
+SketchLine_164.result().setName("SketchLine_60")
+SketchLine_163.setName("SketchLine_59")
+SketchLine_163.result().setName("SketchLine_59")
+SketchLine_162.setName("SketchLine_58")
+SketchLine_162.result().setName("SketchLine_58")
+model.do()
+ExtrusionFuse_2 = model.addExtrusionFuse(Part_2_doc, [model.selection("COMPOUND", "Sketch_6")], model.selection(), model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_7f-SketchArc_1_2f-SketchLine_8f-SketchLine_9f-SketchLine_10r-SketchLine_11r-SketchLine_12r-SketchLine_14r-SketchArc_2_2r"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_5_1")])
+Sketch_17 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_12"))
+SketchLine_170 = Sketch_17.addLine(50.25000000000001, -4.5, 31.24999999998802, -4.499999999999997)
+SketchLine_170.setName("SketchLine_76")
+SketchLine_170.result().setName("SketchLine_76")
+SketchLine_171 = Sketch_17.addLine(51.00000000000001, -6.749999999999998, 51.00000000000001, -5.24999997149696)
+SketchLine_171.setName("SketchLine_78")
+SketchLine_171.result().setName("SketchLine_78")
+SketchLine_172 = Sketch_17.addLine(31, -4.750000022881151, 31, -7.249999999972618)
+SketchLine_172.setName("SketchLine_80")
+SketchLine_172.result().setName("SketchLine_80")
+SketchLine_173 = Sketch_17.addLine(31.25000000003855, -7.5, 50.24999994039248, -7.5)
+SketchLine_173.setName("SketchLine_79")
+SketchLine_173.result().setName("SketchLine_79")
+SketchLine_174 = Sketch_17.addLine(51, -4.5, 31, -4.5)
+SketchLine_174.setName("SketchLine_66")
+SketchLine_174.result().setName("SketchLine_66")
+SketchLine_174.setAuxiliary(True)
+SketchLine_175 = Sketch_17.addLine(51, -7.5, 51, -4.5)
+SketchLine_175.setAuxiliary(True)
+SketchConstraintCoincidence_247 = Sketch_17.setCoincident(SketchLine_175.endPoint(), SketchLine_174.startPoint())
+SketchConstraintCoincidence_247.setName("SketchConstraintCoincidence_78")
+SketchLine_176 = Sketch_17.addLine(31, -4.5, 31, -7.5)
+SketchLine_176.setName("SketchLine_67")
+SketchLine_176.result().setName("SketchLine_67")
+SketchLine_176.setAuxiliary(True)
+SketchConstraintCoincidence_248 = Sketch_17.setCoincident(SketchLine_174.endPoint(), SketchLine_176.startPoint())
+SketchConstraintCoincidence_248.setName("SketchConstraintCoincidence_79")
+SketchLine_177 = Sketch_17.addLine(31, -7.5, 51, -7.5)
+SketchLine_177.setName("SketchLine_68")
+SketchLine_177.result().setName("SketchLine_68")
+SketchLine_177.setAuxiliary(True)
+SketchConstraintCoincidence_249 = Sketch_17.setCoincident(SketchLine_176.endPoint(), SketchLine_177.startPoint())
+SketchConstraintCoincidence_249.setName("SketchConstraintCoincidence_80")
+SketchConstraintCoincidence_250 = Sketch_17.setCoincident(SketchLine_177.endPoint(), SketchLine_175.startPoint())
+SketchConstraintCoincidence_250.setName("SketchConstraintCoincidence_81")
+SketchConstraintHorizontal_34 = Sketch_17.setHorizontal(SketchLine_174.result())
+SketchConstraintHorizontal_34.setName("SketchConstraintHorizontal_13")
+SketchConstraintVertical_31 = Sketch_17.setVertical(SketchLine_176.result())
+SketchConstraintHorizontal_35 = Sketch_17.setHorizontal(SketchLine_177.result())
+SketchConstraintHorizontal_35.setName("SketchConstraintHorizontal_14")
+SketchConstraintVertical_32 = Sketch_17.setVertical(SketchLine_175.result())
+SketchLine_178 = Sketch_17.addLine(31, -7.5, 51, -4.5)
+SketchLine_178.setName("SketchLine_70")
+SketchLine_178.result().setName("SketchLine_70")
+SketchLine_178.setAuxiliary(True)
+SketchConstraintCoincidence_251 = Sketch_17.setCoincident(SketchLine_176.endPoint(), SketchLine_178.startPoint())
+SketchConstraintCoincidence_251.setName("SketchConstraintCoincidence_82")
+SketchConstraintCoincidence_252 = Sketch_17.setCoincident(SketchLine_177.startPoint(), SketchLine_178.startPoint())
+SketchConstraintCoincidence_252.setName("SketchConstraintCoincidence_83")
+SketchPoint_32 = Sketch_17.addPoint(51, -4.5)
+SketchConstraintCoincidence_253 = Sketch_17.setCoincident(SketchLine_174.startPoint(), SketchPoint_32.coordinates())
+SketchConstraintCoincidence_253.setName("SketchConstraintCoincidence_84")
+SketchConstraintCoincidence_254 = Sketch_17.setCoincident(SketchLine_175.endPoint(), SketchPoint_32.coordinates())
+SketchConstraintCoincidence_254.setName("SketchConstraintCoincidence_85")
+SketchPoint_33 = Sketch_17.addPoint(41, -6)
+SketchPoint_33.setAuxiliary(True)
+SketchConstraintCoincidence_255 = Sketch_17.setCoincident(SketchPoint_33.coordinates(), SketchLine_178.result())
+SketchConstraintCoincidence_255.setName("SketchConstraintCoincidence_86")
+SketchConstraintMiddle_11 = Sketch_17.setMiddlePoint(SketchLine_178.result(), SketchPoint_33.coordinates())
+SketchPoint_34 = Sketch_17.addPoint(21.00014787857639, -5.999999999999999)
+SketchPoint_34.setAuxiliary(True)
+SketchLine_179 = Sketch_17.addLine(21.00014787857639, -10.5, 21.00014787857639, -1.499999999999999)
+SketchLine_179.setName("SketchLine_71")
+SketchLine_179.result().setName("SketchLine_71")
+SketchConstraintRigid_18 = Sketch_17.setFixed(SketchLine_179.result())
+SketchConstraintRigid_18.setName("SketchConstraintRigid_14")
+SketchConstraintCoincidence_256 = Sketch_17.setCoincident(SketchPoint_34.coordinates(), SketchLine_179.result())
+SketchConstraintCoincidence_256.setName("SketchConstraintCoincidence_87")
+SketchConstraintMiddle_12 = Sketch_17.setMiddlePoint(SketchPoint_34.coordinates(), SketchLine_179.result())
+SketchLine_180 = Sketch_17.addLine(21.00014787857639, -6, 41, -5.999999999999999)
+SketchLine_180.setName("SketchLine_72")
+SketchLine_180.result().setName("SketchLine_72")
+SketchLine_180.setAuxiliary(True)
+SketchConstraintCoincidence_257 = Sketch_17.setCoincident(SketchPoint_34.coordinates(), SketchLine_180.startPoint())
+SketchConstraintCoincidence_257.setName("SketchConstraintCoincidence_88")
+SketchConstraintCoincidence_258 = Sketch_17.setCoincident(SketchPoint_33.coordinates(), SketchLine_180.endPoint())
+SketchConstraintCoincidence_258.setName("SketchConstraintCoincidence_89")
+SketchConstraintHorizontal_36 = Sketch_17.setHorizontal(SketchLine_180.result())
+SketchConstraintHorizontal_36.setName("SketchConstraintHorizontal_15")
+SketchConstraintCoincidence_259 = Sketch_17.setCoincident(SketchLine_178.endPoint(), SketchLine_174.startPoint())
+SketchConstraintCoincidence_259.setName("SketchConstraintCoincidence_90")
+SketchConstraintLength_29 = Sketch_17.setLength(SketchLine_175.result(), 3)
+SketchConstraintLength_29.setName("SketchConstraintLength_13")
+SketchConstraintLength_30 = Sketch_17.setLength(SketchLine_174.result(), 20)
+SketchConstraintLength_30.setName("SketchConstraintLength_14")
+SketchPoint_35 = Sketch_17.addPoint(29, -10.5)
+SketchConstraintDistance_30 = Sketch_17.setDistance(SketchPoint_35.coordinates(), SketchLine_176.result(), 2)
+SketchConstraintRigid_19 = Sketch_17.setFixed(SketchPoint_35.result())
+SketchConstraintRigid_19.setName("SketchConstraintRigid_15")
+SketchArc_37 = Sketch_17.addArc(50.24999999999999, -5.250000000000003, 51.00000000000001, -5.24999997149696, 50.25000000000001, -4.5, False)
+SketchLine_181 = Sketch_17.addLine(51, -7.5, 51.00000000000001, -5.24999997149696)
+SketchLine_181.setName("SketchLine_74")
+SketchLine_181.result().setName("SketchLine_74")
+SketchLine_181.setAuxiliary(True)
+SketchConstraintCoincidence_260 = Sketch_17.setCoincident(SketchArc_37.startPoint(), SketchLine_181.endPoint())
+SketchConstraintCoincidence_260.setName("SketchConstraintCoincidence_91")
+SketchLine_182 = Sketch_17.addLine(50.25000000000001, -4.5, 31, -4.5)
+SketchLine_182.setName("SketchLine_73")
+SketchLine_182.result().setName("SketchLine_73")
+SketchLine_182.setAuxiliary(True)
+SketchConstraintCoincidence_261 = Sketch_17.setCoincident(SketchArc_37.endPoint(), SketchLine_182.startPoint())
+SketchConstraintCoincidence_261.setName("SketchConstraintCoincidence_92")
+SketchConstraintTangent_15 = Sketch_17.setTangent(SketchArc_37.results()[1], SketchLine_182.result())
+SketchConstraintTangent_16 = Sketch_17.setTangent(SketchArc_37.results()[1], SketchLine_181.result())
+SketchConstraintCoincidence_262 = Sketch_17.setCoincident(SketchLine_174.endPoint(), SketchLine_182.endPoint())
+SketchConstraintCoincidence_262.setName("SketchConstraintCoincidence_93")
+SketchConstraintCoincidence_263 = Sketch_17.setCoincident(SketchLine_175.startPoint(), SketchLine_181.startPoint())
+SketchConstraintCoincidence_263.setName("SketchConstraintCoincidence_94")
+SketchConstraintCoincidence_264 = Sketch_17.setCoincident(SketchLine_182.startPoint(), SketchLine_174.result())
+SketchConstraintCoincidence_264.setName("SketchConstraintCoincidence_95")
+SketchConstraintCoincidence_265 = Sketch_17.setCoincident(SketchLine_181.endPoint(), SketchLine_175.result())
+SketchConstraintCoincidence_265.setName("SketchConstraintCoincidence_96")
+SketchArc_38 = Sketch_17.addArc(31.25000000000067, -4.750000000000669, 31.24999999998802, -4.499999999999997, 31, -4.750000022881151, False)
+SketchConstraintCoincidence_266 = Sketch_17.setCoincident(SketchArc_38.startPoint(), SketchLine_170.endPoint())
+SketchConstraintCoincidence_266.setName("SketchConstraintCoincidence_97")
+SketchLine_183 = Sketch_17.addLine(31, -4.750000022881151, 31, -7.5)
+SketchLine_183.setName("SketchLine_75")
+SketchLine_183.result().setName("SketchLine_75")
+SketchLine_183.setAuxiliary(True)
+SketchConstraintCoincidence_267 = Sketch_17.setCoincident(SketchArc_38.endPoint(), SketchLine_183.startPoint())
+SketchConstraintCoincidence_267.setName("SketchConstraintCoincidence_98")
+SketchConstraintTangent_17 = Sketch_17.setTangent(SketchArc_38.results()[1], SketchLine_183.result())
+SketchConstraintTangent_18 = Sketch_17.setTangent(SketchArc_38.results()[1], SketchLine_170.result())
+SketchConstraintCoincidence_268 = Sketch_17.setCoincident(SketchLine_176.endPoint(), SketchLine_183.endPoint())
+SketchConstraintCoincidence_268.setName("SketchConstraintCoincidence_99")
+SketchConstraintCoincidence_269 = Sketch_17.setCoincident(SketchLine_182.startPoint(), SketchLine_170.startPoint())
+SketchConstraintCoincidence_269.setName("SketchConstraintCoincidence_100")
+SketchConstraintCoincidence_270 = Sketch_17.setCoincident(SketchLine_183.startPoint(), SketchLine_176.result())
+SketchConstraintCoincidence_270.setName("SketchConstraintCoincidence_101")
+SketchConstraintCoincidence_271 = Sketch_17.setCoincident(SketchLine_170.endPoint(), SketchLine_182.result())
+SketchConstraintCoincidence_271.setName("SketchConstraintCoincidence_102")
+SketchArc_39 = Sketch_17.addArc(50.25, -6.749999999999999, 50.24999994039248, -7.5, 51.00000000000001, -6.749999999999998, False)
+SketchLine_184 = Sketch_17.addLine(31, -7.5, 50.24999994039248, -7.5)
+SketchLine_184.setName("SketchLine_77")
+SketchLine_184.result().setName("SketchLine_77")
+SketchLine_184.setAuxiliary(True)
+SketchConstraintCoincidence_272 = Sketch_17.setCoincident(SketchArc_39.startPoint(), SketchLine_184.endPoint())
+SketchConstraintCoincidence_272.setName("SketchConstraintCoincidence_103")
+SketchConstraintCoincidence_273 = Sketch_17.setCoincident(SketchArc_39.endPoint(), SketchLine_171.startPoint())
+SketchConstraintCoincidence_273.setName("SketchConstraintCoincidence_104")
+SketchConstraintTangent_19 = Sketch_17.setTangent(SketchArc_39.results()[1], SketchLine_184.result())
+SketchConstraintTangent_20 = Sketch_17.setTangent(SketchArc_39.results()[1], SketchLine_171.result())
+SketchConstraintCoincidence_274 = Sketch_17.setCoincident(SketchLine_177.startPoint(), SketchLine_184.startPoint())
+SketchConstraintCoincidence_274.setName("SketchConstraintCoincidence_105")
+SketchConstraintCoincidence_275 = Sketch_17.setCoincident(SketchLine_181.endPoint(), SketchLine_171.endPoint())
+SketchConstraintCoincidence_275.setName("SketchConstraintCoincidence_106")
+SketchConstraintCoincidence_276 = Sketch_17.setCoincident(SketchLine_184.endPoint(), SketchLine_177.result())
+SketchConstraintCoincidence_276.setName("SketchConstraintCoincidence_107")
+SketchConstraintCoincidence_277 = Sketch_17.setCoincident(SketchLine_171.startPoint(), SketchLine_181.result())
+SketchConstraintCoincidence_277.setName("SketchConstraintCoincidence_108")
+SketchArc_40 = Sketch_17.addArc(31.25000000000003, -7.250000000000001, 31, -7.249999999972618, 31.25000000003855, -7.5, False)
+SketchConstraintCoincidence_278 = Sketch_17.setCoincident(SketchArc_40.startPoint(), SketchLine_172.endPoint())
+SketchConstraintCoincidence_278.setName("SketchConstraintCoincidence_109")
+SketchConstraintCoincidence_279 = Sketch_17.setCoincident(SketchArc_40.endPoint(), SketchLine_173.startPoint())
+SketchConstraintCoincidence_279.setName("SketchConstraintCoincidence_110")
+SketchConstraintTangent_21 = Sketch_17.setTangent(SketchArc_40.results()[1], SketchLine_173.result())
+SketchConstraintTangent_22 = Sketch_17.setTangent(SketchArc_40.results()[1], SketchLine_172.result())
+SketchConstraintCoincidence_280 = Sketch_17.setCoincident(SketchLine_184.endPoint(), SketchLine_173.endPoint())
+SketchConstraintCoincidence_280.setName("SketchConstraintCoincidence_111")
+SketchConstraintCoincidence_281 = Sketch_17.setCoincident(SketchLine_183.startPoint(), SketchLine_172.startPoint())
+SketchConstraintCoincidence_281.setName("SketchConstraintCoincidence_112")
+SketchConstraintCoincidence_282 = Sketch_17.setCoincident(SketchLine_173.startPoint(), SketchLine_184.result())
+SketchConstraintCoincidence_282.setName("SketchConstraintCoincidence_113")
+SketchConstraintCoincidence_283 = Sketch_17.setCoincident(SketchLine_172.endPoint(), SketchLine_183.result())
+SketchConstraintCoincidence_283.setName("SketchConstraintCoincidence_114")
+SketchConstraintRadius_16 = Sketch_17.setRadius(SketchArc_37.results()[1], 0.75)
+SketchConstraintRadius_17 = Sketch_17.setRadius(SketchArc_39.results()[1], 0.75)
+SketchConstraintRadius_18 = Sketch_17.setRadius(SketchArc_38.results()[1], 0.25)
+SketchConstraintRadius_19 = Sketch_17.setRadius(SketchArc_40.results()[1], 0.25)
+model.do()
+ExtrusionCut_15 = model.addExtrusionCut(Part_2_doc, [model.selection("COMPOUND", "Sketch_7")], model.selection(), 0, 20, [model.selection("SOLID", "ExtrusionFuse_1_1")])
+Sketch_18 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_6_1/Modfied_17"))
+SketchPoint_36 = Sketch_18.addPoint(53.99994409538203, -1.615587133892632e-027)
+SketchPoint_37 = Sketch_18.addPoint(53.99994409538203, -1.615587133892632e-027)
+SketchConstraintRigid_20 = Sketch_18.setFixed(SketchPoint_37.result())
+SketchConstraintRigid_20.setName("SketchConstraintRigid_16")
+SketchConstraintCoincidence_284 = Sketch_18.setCoincident(SketchPoint_36.coordinates(), SketchPoint_37.result())
+SketchConstraintCoincidence_284.setName("SketchConstraintCoincidence_115")
+SketchPoint_38 = Sketch_18.addPoint(54, 12)
+SketchLine_185 = Sketch_18.addLine(54, 12, 53.99994409538203, -1.615587133892632e-027)
+SketchLine_185.setName("SketchLine_81")
+SketchLine_185.result().setName("SketchLine_81")
+SketchLine_185.setAuxiliary(True)
+SketchConstraintCoincidence_285 = Sketch_18.setCoincident(SketchPoint_38.coordinates(), SketchLine_185.startPoint())
+SketchConstraintCoincidence_285.setName("SketchConstraintCoincidence_116")
+SketchConstraintCoincidence_286 = Sketch_18.setCoincident(SketchPoint_36.coordinates(), SketchLine_185.endPoint())
+SketchConstraintCoincidence_286.setName("SketchConstraintCoincidence_117")
+SketchConstraintCoincidence_287 = Sketch_18.setCoincident(SketchPoint_37.coordinates(), SketchLine_185.endPoint())
+SketchConstraintCoincidence_287.setName("SketchConstraintCoincidence_118")
+SketchPoint_39 = Sketch_18.addPoint(53.99999534128184, 11.00000000001085)
+SketchConstraintCoincidence_288 = Sketch_18.setCoincident(SketchPoint_39.coordinates(), SketchLine_185.result())
+SketchConstraintCoincidence_288.setName("SketchConstraintCoincidence_119")
+SketchPoint_40 = Sketch_18.addPoint(53.99994875410019, 0.9999999999891482)
+SketchConstraintCoincidence_289 = Sketch_18.setCoincident(SketchPoint_40.coordinates(), SketchLine_185.result())
+SketchConstraintCoincidence_289.setName("SketchConstraintCoincidence_120")
+SketchConstraintDistance_31 = Sketch_18.setDistance(SketchPoint_36.coordinates(), SketchPoint_40.coordinates(), 1)
+SketchConstraintDistance_32 = Sketch_18.setDistance(SketchPoint_38.coordinates(), SketchPoint_39.coordinates(), 1)
+SketchPoint_41 = Sketch_18.addPoint(54, 12)
+SketchConstraintCoincidence_290 = Sketch_18.setCoincident(SketchPoint_38.coordinates(), SketchPoint_41.coordinates())
+SketchConstraintCoincidence_290.setName("SketchConstraintCoincidence_121")
+SketchConstraintRigid_21 = Sketch_18.setFixed(SketchPoint_41.result())
+SketchConstraintRigid_21.setName("SketchConstraintRigid_17")
+SketchLine_186 = Sketch_18.addLine(53.99999534128184, 11.00000000001085, 43.53696016024325, 11.00000000001085)
+SketchLine_186.setName("SketchLine_82")
+SketchLine_186.result().setName("SketchLine_82")
+SketchConstraintCoincidence_291 = Sketch_18.setCoincident(SketchPoint_39.coordinates(), SketchLine_186.startPoint())
+SketchConstraintCoincidence_291.setName("SketchConstraintCoincidence_122")
+SketchLine_187 = Sketch_18.addLine(43.53696016024325, 11.00000000001085, 43.56530536601203, 13.47539228785809)
+SketchLine_187.setName("SketchLine_83")
+SketchLine_187.result().setName("SketchLine_83")
+SketchConstraintCoincidence_292 = Sketch_18.setCoincident(SketchLine_186.endPoint(), SketchLine_187.startPoint())
+SketchConstraintCoincidence_292.setName("SketchConstraintCoincidence_123")
+SketchLine_188 = Sketch_18.addLine(43.56530536601203, 13.47539228785809, 63.09515214070713, 13.47539228785809)
+SketchLine_188.setName("SketchLine_84")
+SketchLine_188.result().setName("SketchLine_84")
+SketchConstraintCoincidence_293 = Sketch_18.setCoincident(SketchLine_187.endPoint(), SketchLine_188.startPoint())
+SketchConstraintCoincidence_293.setName("SketchConstraintCoincidence_124")
+SketchLine_189 = Sketch_18.addLine(63.09515214070713, 13.47539228785809, 63.12349734647592, -1.774328415749978)
+SketchLine_189.setName("SketchLine_85")
+SketchLine_189.result().setName("SketchLine_85")
+SketchConstraintCoincidence_294 = Sketch_18.setCoincident(SketchLine_188.endPoint(), SketchLine_189.startPoint())
+SketchConstraintCoincidence_294.setName("SketchConstraintCoincidence_125")
+SketchLine_190 = Sketch_18.addLine(63.12349734647592, -1.774328415749978, 43.82041221793113, -1.802673621518767)
+SketchLine_190.setName("SketchLine_86")
+SketchLine_190.result().setName("SketchLine_86")
+SketchConstraintCoincidence_295 = Sketch_18.setCoincident(SketchLine_189.endPoint(), SketchLine_190.startPoint())
+SketchConstraintCoincidence_295.setName("SketchConstraintCoincidence_126")
+SketchLine_191 = Sketch_18.addLine(43.82041221793113, -1.802673621518767, 43.79206701216234, 0.9999999999891482)
+SketchLine_191.setName("SketchLine_87")
+SketchLine_191.result().setName("SketchLine_87")
+SketchConstraintCoincidence_296 = Sketch_18.setCoincident(SketchLine_190.endPoint(), SketchLine_191.startPoint())
+SketchConstraintCoincidence_296.setName("SketchConstraintCoincidence_127")
+SketchLine_192 = Sketch_18.addLine(53.99994875410019, 0.9999999999891482, 43.79206701216234, 0.9999999999891482)
+SketchLine_192.setName("SketchLine_88")
+SketchLine_192.result().setName("SketchLine_88")
+SketchConstraintCoincidence_297 = Sketch_18.setCoincident(SketchPoint_40.coordinates(), SketchLine_192.startPoint())
+SketchConstraintCoincidence_297.setName("SketchConstraintCoincidence_128")
+SketchConstraintHorizontal_37 = Sketch_18.setHorizontal(SketchLine_192.result())
+SketchConstraintHorizontal_37.setName("SketchConstraintHorizontal_16")
+SketchConstraintHorizontal_38 = Sketch_18.setHorizontal(SketchLine_186.result())
+SketchConstraintHorizontal_38.setName("SketchConstraintHorizontal_17")
+SketchConstraintCoincidence_298 = Sketch_18.setCoincident(SketchLine_191.endPoint(), SketchLine_192.endPoint())
+SketchConstraintCoincidence_298.setName("SketchConstraintCoincidence_129")
+SketchArc_41 = Sketch_18.addArc(53.99995774377268, 6.000000000066637, 53.99999534128184, 11.00000000001085, 53.99994875410019, 0.9999999999891482, True)
+SketchConstraintCoincidence_299 = Sketch_18.setCoincident(SketchPoint_39.coordinates(), SketchArc_41.startPoint())
+SketchConstraintCoincidence_299.setName("SketchConstraintCoincidence_130")
+SketchConstraintCoincidence_300 = Sketch_18.setCoincident(SketchLine_186.startPoint(), SketchArc_41.startPoint())
+SketchConstraintCoincidence_300.setName("SketchConstraintCoincidence_131")
+SketchConstraintCoincidence_301 = Sketch_18.setCoincident(SketchPoint_40.coordinates(), SketchArc_41.endPoint())
+SketchConstraintCoincidence_301.setName("SketchConstraintCoincidence_132")
+SketchConstraintCoincidence_302 = Sketch_18.setCoincident(SketchLine_192.startPoint(), SketchArc_41.endPoint())
+SketchConstraintCoincidence_302.setName("SketchConstraintCoincidence_133")
+SketchConstraintRadius_20 = Sketch_18.setRadius(SketchArc_41.results()[1], 5)
+SketchLine_193 = Sketch_18.addLine(43.50261344273609, 8.249999999999998, 43.50261344273609, 3.749999999999998)
+SketchLine_193.setName("SketchLine_90")
+SketchLine_193.result().setName("SketchLine_90")
+SketchConstraintVertical_33 = Sketch_18.setVertical(SketchLine_193.result())
+SketchConstraintLength_31 = Sketch_18.setLength(SketchLine_193.result(), 4.5)
+SketchConstraintLength_31.setName("SketchConstraintLength_15")
+SketchPoint_42 = Sketch_18.addPoint(43.50261344273609, 5.999999999999998)
+SketchConstraintMiddle_13 = Sketch_18.setMiddlePoint(SketchPoint_42.coordinates(), SketchLine_193.result())
+SketchPoint_43 = Sketch_18.addPoint(0, 6)
+SketchPoint_43.setAuxiliary(True)
+SketchLine_194 = Sketch_18.addLine(0, 0, 0, 12)
+SketchLine_194.setName("SketchLine_94")
+SketchLine_194.result().setName("SketchLine_94")
+SketchConstraintRigid_22 = Sketch_18.setFixed(SketchLine_194.result())
+SketchConstraintRigid_22.setName("SketchConstraintRigid_19")
+SketchConstraintCoincidence_303 = Sketch_18.setCoincident(SketchPoint_43.coordinates(), SketchLine_194.result())
+SketchConstraintCoincidence_303.setName("SketchConstraintCoincidence_139")
+SketchConstraintMiddle_14 = Sketch_18.setMiddlePoint(SketchLine_194.result(), SketchPoint_43.coordinates())
+SketchLine_195 = Sketch_18.addLine(0, 6, 68.8619738308997, 6)
+SketchLine_195.setName("SketchLine_95")
+SketchLine_195.result().setName("SketchLine_95")
+SketchLine_195.setAuxiliary(True)
+SketchConstraintCoincidence_304 = Sketch_18.setCoincident(SketchPoint_43.coordinates(), SketchLine_195.startPoint())
+SketchConstraintCoincidence_304.setName("SketchConstraintCoincidence_140")
+SketchConstraintHorizontal_39 = Sketch_18.setHorizontal(SketchLine_195.result())
+SketchConstraintHorizontal_39.setName("SketchConstraintHorizontal_20")
+SketchPoint_44 = Sketch_18.addPoint(48.00130672136804, 6)
+SketchConstraintCoincidence_305 = Sketch_18.setCoincident(SketchPoint_44.coordinates(), SketchLine_195.result())
+SketchConstraintCoincidence_305.setName("SketchConstraintCoincidence_146")
+SketchLine_196 = Sketch_18.addLine(43.50261344273609, 8.249999999999998, 51.26978940411676, 8.249999999999998)
+SketchLine_196.setName("SketchLine_92")
+SketchLine_196.result().setName("SketchLine_92")
+SketchConstraintCoincidence_306 = Sketch_18.setCoincident(SketchLine_193.startPoint(), SketchLine_196.startPoint())
+SketchConstraintCoincidence_306.setName("SketchConstraintCoincidence_135")
+SketchLine_197 = Sketch_18.addLine(51.26978940411676, 8.249999999999998, 51.26978940411676, 3.749999999999998)
+SketchLine_197.setName("SketchLine_97")
+SketchLine_197.result().setName("SketchLine_97")
+SketchConstraintCoincidence_307 = Sketch_18.setCoincident(SketchLine_196.endPoint(), SketchLine_197.startPoint())
+SketchConstraintCoincidence_307.setName("SketchConstraintCoincidence_136")
+SketchLine_198 = Sketch_18.addLine(51.26978940411676, 3.749999999999998, 43.50261344273609, 3.749999999999998)
+SketchLine_198.setName("SketchLine_98")
+SketchLine_198.result().setName("SketchLine_98")
+SketchConstraintCoincidence_308 = Sketch_18.setCoincident(SketchLine_197.endPoint(), SketchLine_198.startPoint())
+SketchConstraintCoincidence_308.setName("SketchConstraintCoincidence_137")
+SketchConstraintCoincidence_309 = Sketch_18.setCoincident(SketchLine_193.endPoint(), SketchLine_198.endPoint())
+SketchConstraintCoincidence_309.setName("SketchConstraintCoincidence_138")
+SketchConstraintHorizontal_40 = Sketch_18.setHorizontal(SketchLine_198.result())
+SketchConstraintHorizontal_41 = Sketch_18.setHorizontal(SketchLine_196.result())
+SketchConstraintVertical_34 = Sketch_18.setVertical(SketchLine_197.result())
+SketchLine_199 = Sketch_18.addLine(43.50261344273609, 3.749999999999998, 51.26978940411676, 8.249999999999998)
+SketchLine_199.setAuxiliary(True)
+SketchConstraintCoincidence_310 = Sketch_18.setCoincident(SketchLine_193.endPoint(), SketchLine_199.startPoint())
+SketchConstraintCoincidence_310.setName("SketchConstraintCoincidence_141")
+SketchConstraintCoincidence_311 = Sketch_18.setCoincident(SketchLine_198.endPoint(), SketchLine_199.startPoint())
+SketchConstraintCoincidence_311.setName("SketchConstraintCoincidence_142")
+SketchConstraintCoincidence_312 = Sketch_18.setCoincident(SketchLine_197.startPoint(), SketchLine_199.endPoint())
+SketchConstraintCoincidence_312.setName("SketchConstraintCoincidence_143")
+SketchPoint_45 = Sketch_18.addPoint(47.38620142342643, 5.999999999999998)
+SketchPoint_45.setAuxiliary(True)
+SketchConstraintCoincidence_313 = Sketch_18.setCoincident(SketchPoint_45.coordinates(), SketchLine_199.result())
+SketchConstraintCoincidence_313.setName("SketchConstraintCoincidence_144")
+SketchConstraintMiddle_15 = Sketch_18.setMiddlePoint(SketchPoint_45.coordinates(), SketchLine_199.result())
+SketchConstraintCoincidence_314 = Sketch_18.setCoincident(SketchPoint_45.coordinates(), SketchLine_195.result())
+SketchConstraintCoincidence_314.setName("SketchConstraintCoincidence_145")
+model.do()
+ExtrusionCut_16 = model.addExtrusionCut(Part_2_doc, [model.selection("COMPOUND", "Sketch_8")], model.selection(), 10, 0, [model.selection("SOLID", "ExtrusionCut_6_1")])
+Sketch_19 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_7_1/Modfied_56"))
+SketchLine_200 = Sketch_19.addLine(21.00014787857639, 4.163450069699051, 21.00014787857639, 0)
+SketchLine_200.setName("SketchLine_107")
+SketchLine_200.result().setName("SketchLine_107")
+SketchLine_201 = Sketch_19.addLine(29, 5, 21.00014787857639, 5)
+SketchLine_201.setName("SketchLine_96")
+SketchLine_201.result().setName("SketchLine_96")
+SketchLine_201.setAuxiliary(True)
+SketchArc_42 = Sketch_19.addArc(25.00007393928819, 8.000098583186649, 21.53790262696343, 4.392693725936027, 28.46224525161297, 4.392693725936026, False)
+SketchArc_42.setName("SketchArc_22")
+SketchArc_42.result().setName("SketchArc_22")
+SketchArc_42.results()[1].setName("SketchArc_22_2")
+SketchLine_202 = Sketch_19.addLine(21.00014787857639, 0, 29, 0)
+SketchLine_202.setName("SketchLine_100")
+SketchLine_202.result().setName("SketchLine_100")
+SketchLine_203 = Sketch_19.addLine(29, 0, 29, 4.163450069699049)
+SketchLine_203.setName("SketchLine_108")
+SketchLine_203.result().setName("SketchLine_108")
+SketchLine_204 = Sketch_19.addLine(29, 0, 29, 5)
+SketchLine_204.setName("SketchLine_101")
+SketchLine_204.result().setName("SketchLine_101")
+SketchLine_204.setAuxiliary(True)
+SketchConstraintCoincidence_315 = Sketch_19.setCoincident(SketchLine_204.endPoint(), SketchLine_201.startPoint())
+SketchConstraintCoincidence_315.setName("SketchConstraintCoincidence_147")
+SketchLine_205 = Sketch_19.addLine(21.00014787857639, 5, 21.00014787857639, 0)
+SketchLine_205.setAuxiliary(True)
+SketchConstraintCoincidence_316 = Sketch_19.setCoincident(SketchLine_201.endPoint(), SketchLine_205.startPoint())
+SketchConstraintCoincidence_316.setName("SketchConstraintCoincidence_148")
+SketchConstraintCoincidence_317 = Sketch_19.setCoincident(SketchLine_205.endPoint(), SketchLine_202.startPoint())
+SketchConstraintCoincidence_317.setName("SketchConstraintCoincidence_149")
+SketchConstraintCoincidence_318 = Sketch_19.setCoincident(SketchLine_202.endPoint(), SketchLine_204.startPoint())
+SketchConstraintCoincidence_318.setName("SketchConstraintCoincidence_150")
+SketchConstraintHorizontal_42 = Sketch_19.setHorizontal(SketchLine_201.result())
+SketchConstraintHorizontal_42.setName("SketchConstraintHorizontal_21")
+SketchConstraintVertical_35 = Sketch_19.setVertical(SketchLine_205.result())
+SketchConstraintHorizontal_43 = Sketch_19.setHorizontal(SketchLine_202.result())
+SketchConstraintHorizontal_43.setName("SketchConstraintHorizontal_22")
+SketchConstraintVertical_36 = Sketch_19.setVertical(SketchLine_204.result())
+SketchPoint_46 = Sketch_19.addPoint(21.00014787857639, 7.5)
+SketchConstraintCoincidence_319 = Sketch_19.setCoincident(SketchLine_205.result(), SketchPoint_46.coordinates())
+SketchConstraintCoincidence_319.setName("SketchConstraintCoincidence_151")
+SketchConstraintRigid_23 = Sketch_19.setFixed(SketchPoint_46.result())
+SketchConstraintRigid_23.setName("SketchConstraintRigid_18")
+SketchPoint_47 = Sketch_19.addPoint(29, 7.5)
+SketchConstraintCoincidence_320 = Sketch_19.setCoincident(SketchLine_204.result(), SketchPoint_47.coordinates())
+SketchConstraintCoincidence_320.setName("SketchConstraintCoincidence_152")
+SketchConstraintRigid_24 = Sketch_19.setFixed(SketchPoint_47.result())
+SketchConstraintRigid_24.setName("SketchConstraintRigid_20")
+SketchConstraintLength_32 = Sketch_19.setLength(SketchLine_205.result(), 5)
+SketchConstraintLength_32.setName("SketchConstraintLength_16")
+SketchLine_206 = Sketch_19.addLine(0, 0, 45.49999999999999, 0)
+SketchLine_206.setName("SketchLine_102")
+SketchLine_206.result().setName("SketchLine_102")
+SketchConstraintCoincidence_321 = Sketch_19.setCoincident(SketchLine_205.endPoint(), SketchLine_206.result())
+SketchConstraintCoincidence_321.setName("SketchConstraintCoincidence_153")
+SketchConstraintRigid_25 = Sketch_19.setFixed(SketchLine_206.result())
+SketchConstraintRigid_25.setName("SketchConstraintRigid_21")
+SketchArc_43 = Sketch_19.addArc(25.00007393928819, 8.000098583186649, 21.00014787857639, 5, 29, 5, False)
+SketchArc_43.setName("SketchArc_19")
+SketchArc_43.result().setName("SketchArc_19")
+SketchArc_43.results()[1].setName("SketchArc_19_2")
+SketchArc_43.setAuxiliary(True)
+SketchConstraintCoincidence_322 = Sketch_19.setCoincident(SketchLine_201.endPoint(), SketchArc_43.startPoint())
+SketchConstraintCoincidence_322.setName("SketchConstraintCoincidence_154")
+SketchConstraintCoincidence_323 = Sketch_19.setCoincident(SketchLine_205.startPoint(), SketchArc_43.startPoint())
+SketchConstraintCoincidence_323.setName("SketchConstraintCoincidence_155")
+SketchConstraintCoincidence_324 = Sketch_19.setCoincident(SketchLine_201.startPoint(), SketchArc_43.endPoint())
+SketchConstraintCoincidence_324.setName("SketchConstraintCoincidence_156")
+SketchConstraintCoincidence_325 = Sketch_19.setCoincident(SketchLine_204.endPoint(), SketchArc_43.endPoint())
+SketchConstraintCoincidence_325.setName("SketchConstraintCoincidence_157")
+SketchConstraintRadius_21 = Sketch_19.setRadius(SketchArc_43.results()[1], 5)
+SketchLine_207 = Sketch_19.addLine(1, 0, 1, 1.8)
+SketchLine_207.setName("SketchLine_103")
+SketchLine_207.result().setName("SketchLine_103")
+SketchConstraintCoincidence_326 = Sketch_19.setCoincident(SketchLine_207.startPoint(), SketchLine_206.result())
+SketchConstraintCoincidence_326.setName("SketchConstraintCoincidence_158")
+SketchLine_208 = Sketch_19.addLine(1, 1.8, 8, 3.389761862250954)
+SketchLine_208.setName("SketchLine_104")
+SketchLine_208.result().setName("SketchLine_104")
+SketchConstraintCoincidence_327 = Sketch_19.setCoincident(SketchLine_207.endPoint(), SketchLine_208.startPoint())
+SketchConstraintCoincidence_327.setName("SketchConstraintCoincidence_159")
+SketchLine_209 = Sketch_19.addLine(8, 3.389761862250954, 8, 0)
+SketchLine_209.setName("SketchLine_105")
+SketchLine_209.result().setName("SketchLine_105")
+SketchConstraintCoincidence_328 = Sketch_19.setCoincident(SketchLine_208.endPoint(), SketchLine_209.startPoint())
+SketchConstraintCoincidence_328.setName("SketchConstraintCoincidence_160")
+SketchLine_210 = Sketch_19.addLine(8, 0, 1, 0)
+SketchLine_210.setName("SketchLine_106")
+SketchLine_210.result().setName("SketchLine_106")
+SketchConstraintCoincidence_329 = Sketch_19.setCoincident(SketchLine_209.endPoint(), SketchLine_210.startPoint())
+SketchConstraintCoincidence_329.setName("SketchConstraintCoincidence_161")
+SketchConstraintCoincidence_330 = Sketch_19.setCoincident(SketchLine_207.startPoint(), SketchLine_210.endPoint())
+SketchConstraintCoincidence_330.setName("SketchConstraintCoincidence_162")
+SketchConstraintCoincidence_331 = Sketch_19.setCoincident(SketchLine_210.startPoint(), SketchLine_206.result())
+SketchConstraintCoincidence_331.setName("SketchConstraintCoincidence_163")
+SketchConstraintVertical_37 = Sketch_19.setVertical(SketchLine_209.result())
+SketchConstraintVertical_38 = Sketch_19.setVertical(SketchLine_207.result())
+SketchConstraintLength_33 = Sketch_19.setLength(SketchLine_210.result(), 7)
+SketchConstraintLength_33.setName("SketchConstraintLength_17")
+SketchConstraintDistance_33 = Sketch_19.setDistance(SketchLine_207.result(), SketchLine_206.startPoint(), 1)
+SketchConstraintLength_34 = Sketch_19.setLength(SketchLine_207.result(), 1.8)
+SketchConstraintLength_34.setName("SketchConstraintLength_18")
+SketchArc_44 = Sketch_19.addArc(21.3178882838101, 4.163450069699051, 21.53790262696343, 4.392693725936027, 21.00014787857639, 4.163450069699051, False)
+SketchArc_45 = Sketch_19.addArc(25.00007393928819, 8.000098583186649, 21.53790262696343, 4.392693725936027, 29, 5, False)
+SketchArc_45.setName("SketchArc_20")
+SketchArc_45.result().setName("SketchArc_20")
+SketchArc_45.results()[1].setName("SketchArc_20_2")
+SketchArc_45.setAuxiliary(True)
+SketchConstraintCoincidence_332 = Sketch_19.setCoincident(SketchArc_44.startPoint(), SketchArc_45.startPoint())
+SketchConstraintCoincidence_332.setName("SketchConstraintCoincidence_164")
+SketchConstraintCoincidence_333 = Sketch_19.setCoincident(SketchArc_44.endPoint(), SketchLine_200.startPoint())
+SketchConstraintCoincidence_333.setName("SketchConstraintCoincidence_165")
+SketchConstraintTangent_23 = Sketch_19.setTangent(SketchArc_44.results()[1], SketchLine_200.result())
+SketchConstraintTangent_24 = Sketch_19.setTangent(SketchArc_44.results()[1], SketchArc_45.results()[1])
+SketchConstraintCoincidence_334 = Sketch_19.setCoincident(SketchLine_205.endPoint(), SketchLine_200.endPoint())
+SketchConstraintCoincidence_334.setName("SketchConstraintCoincidence_166")
+SketchConstraintCoincidence_335 = Sketch_19.setCoincident(SketchArc_43.endPoint(), SketchArc_45.endPoint())
+SketchConstraintCoincidence_335.setName("SketchConstraintCoincidence_167")
+SketchConstraintTangent_25 = Sketch_19.setTangent(SketchArc_43.results()[1], SketchArc_45.results()[1])
+SketchConstraintCoincidence_336 = Sketch_19.setCoincident(SketchLine_200.startPoint(), SketchLine_205.result())
+SketchConstraintCoincidence_336.setName("SketchConstraintCoincidence_168")
+SketchConstraintCoincidence_337 = Sketch_19.setCoincident(SketchArc_45.startPoint(), SketchArc_43.results()[1])
+SketchConstraintCoincidence_337.setName("SketchConstraintCoincidence_169")
+SketchArc_46 = Sketch_19.addArc(28.68225959476629, 4.163450069699049, 29, 4.163450069699049, 28.46224525161297, 4.392693725936026, False)
+SketchConstraintCoincidence_338 = Sketch_19.setCoincident(SketchArc_46.startPoint(), SketchLine_203.endPoint())
+SketchConstraintCoincidence_338.setName("SketchConstraintCoincidence_170")
+SketchConstraintCoincidence_339 = Sketch_19.setCoincident(SketchArc_46.endPoint(), SketchArc_42.endPoint())
+SketchConstraintCoincidence_339.setName("SketchConstraintCoincidence_171")
+SketchConstraintTangent_26 = Sketch_19.setTangent(SketchArc_46.results()[1], SketchArc_42.results()[1])
+SketchConstraintTangent_27 = Sketch_19.setTangent(SketchArc_46.results()[1], SketchLine_203.result())
+SketchConstraintCoincidence_340 = Sketch_19.setCoincident(SketchArc_45.startPoint(), SketchArc_42.startPoint())
+SketchConstraintCoincidence_340.setName("SketchConstraintCoincidence_172")
+SketchConstraintCoincidence_341 = Sketch_19.setCoincident(SketchLine_204.startPoint(), SketchLine_203.startPoint())
+SketchConstraintCoincidence_341.setName("SketchConstraintCoincidence_173")
+SketchConstraintTangent_28 = Sketch_19.setTangent(SketchArc_45.results()[1], SketchArc_42.results()[1])
+SketchConstraintCoincidence_342 = Sketch_19.setCoincident(SketchArc_42.endPoint(), SketchArc_45.results()[1])
+SketchConstraintCoincidence_342.setName("SketchConstraintCoincidence_174")
+SketchConstraintCoincidence_343 = Sketch_19.setCoincident(SketchLine_203.endPoint(), SketchLine_204.result())
+SketchConstraintCoincidence_343.setName("SketchConstraintCoincidence_175")
+model.do()
+Plane_12 = model.addPlane(Part_2_doc, model.selection("FACE", "Plane_2"), 4, False)
+Plane_13 = model.addPlane(Part_2_doc, model.selection("FACE", "Plane_2"), 4, True)
+ExtrusionCut_17 = model.addExtrusionCut(Part_2_doc, [model.selection("COMPOUND", "Sketch_9")], model.selection(), model.selection("FACE", "Plane_5"), 0, model.selection("FACE", "Plane_4"), 0, [model.selection("SOLID", "ExtrusionCut_7_1")])
+Sketch_20 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_8_1/Modfied_5"))
+SketchCircle_2 = Sketch_20.addCircle(12, 6, 1)
+SketchConstraintRadius_22 = Sketch_20.setRadius(SketchCircle_2.results()[1], 1)
+SketchPoint_48 = Sketch_20.addPoint(0, 6)
+SketchPoint_48.setAuxiliary(True)
+SketchLine_211 = Sketch_20.addLine(0, 0, 0, 12)
+SketchLine_211.setName("SketchLine_109")
+SketchLine_211.result().setName("SketchLine_109")
+SketchConstraintRigid_26 = Sketch_20.setFixed(SketchLine_211.result())
+SketchConstraintRigid_26.setName("SketchConstraintRigid_22")
+SketchConstraintCoincidence_344 = Sketch_20.setCoincident(SketchPoint_48.coordinates(), SketchLine_211.result())
+SketchConstraintCoincidence_344.setName("SketchConstraintCoincidence_176")
+SketchConstraintMiddle_16 = Sketch_20.setMiddlePoint(SketchLine_211.result(), SketchPoint_48.coordinates())
+SketchLine_212 = Sketch_20.addLine(0, 6, 17.31036191565843, 6)
+SketchLine_212.setName("SketchLine_110")
+SketchLine_212.result().setName("SketchLine_110")
+SketchLine_212.setAuxiliary(True)
+SketchConstraintCoincidence_345 = Sketch_20.setCoincident(SketchPoint_48.coordinates(), SketchLine_212.startPoint())
+SketchConstraintCoincidence_345.setName("SketchConstraintCoincidence_177")
+SketchConstraintHorizontal_44 = Sketch_20.setHorizontal(SketchLine_212.result())
+SketchConstraintHorizontal_44.setName("SketchConstraintHorizontal_23")
+SketchConstraintCoincidence_346 = Sketch_20.setCoincident(SketchCircle_2.center(), SketchLine_212.result())
+SketchConstraintCoincidence_346.setName("SketchConstraintCoincidence_178")
+SketchConstraintDistance_34 = Sketch_20.setDistance(SketchLine_211.result(), SketchCircle_2.center(), 12)
+model.do()
+ExtrusionCut_18 = model.addExtrusionCut(Part_2_doc, [model.selection("WIRE", "Sketch_10/Wire-SketchCircle_1_2f")], model.selection(), 0, 0.75, [model.selection("SOLID", "ExtrusionCut_8_1")])
+model.do()
+Rotation_1 = model.addRotation(partSet, [model.selection("COMPOUND", "Part_2/")], model.selection("EDGE", "Part_1/ExtrusionCut_9_1/Modfied_1&ExtrusionCut_7_1/Modfied_57"), 180)
+Placement_1 = model.addPlacement(partSet, [model.selection("COMPOUND", "Rotation_1/")], model.selection("FACE", "Rotation_1/ExtrusionCut_5_1/Modfied_1"), model.selection("FACE", "Part_1/ExtrusionCut_5_1/Modfied_1"), False, True)
+Rotation_2 = model.addRotation(partSet, [model.selection("COMPOUND", "Placement_1/")], model.selection("EDGE", "Part_1/ExtrusionCut_5_1/Modfied_8&ExtrusionCut_8_1/Modfied_3"), 7)
+Rotation_2.result().setColor(255, 85, 0)
 model.end()
 
 from GeomAPI import GeomAPI_Shape
 
-model.testNbResults(ExtrusionCut_9, 1)
-model.testNbSubResults(ExtrusionCut_9, [0])
-model.testNbSubShapes(ExtrusionCut_9, GeomAPI_Shape.SOLID, [1])
-model.testNbSubShapes(ExtrusionCut_9, GeomAPI_Shape.FACE, [172])
-model.testNbSubShapes(ExtrusionCut_9, GeomAPI_Shape.EDGE, [804])
-model.testNbSubShapes(ExtrusionCut_9, GeomAPI_Shape.VERTEX, [1608])
-model.testResultsVolumes(ExtrusionCut_9, [1876.328652945095427639898844063])
+model.testNbResults(Part_1, 1)
+model.testNbSubResults(Part_1, [0])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.FACE, [172])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.EDGE, [804])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.VERTEX, [1608])
+model.testResultsVolumes(Part_1, [1876.328652945015164732467383146])
+
+model.testNbResults(Rotation_2, 1)
+model.testNbSubResults(Rotation_2, [0])
+model.testNbSubShapes(Rotation_2, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Rotation_2, GeomAPI_Shape.FACE, [172])
+model.testNbSubShapes(Rotation_2, GeomAPI_Shape.EDGE, [804])
+model.testNbSubShapes(Rotation_2, GeomAPI_Shape.VERTEX, [1608])
+model.testResultsVolumes(Rotation_2, [1876.328652945015846853493712842])
 
-assert(model.checkPythonDump)
+assert(model.checkPythonDump())
index bb803520362bfb4fbcce27c3110f16c6621dff4a..641060991b09ed64a3dfb11cb7d4e39e2a641989 100644 (file)
@@ -244,6 +244,6 @@ model.testNbSubShapes(Boolean_1, GeomAPI_Shape.SOLID, [1])
 model.testNbSubShapes(Boolean_1, GeomAPI_Shape.FACE, [35])
 model.testNbSubShapes(Boolean_1, GeomAPI_Shape.EDGE, [162])
 model.testNbSubShapes(Boolean_1, GeomAPI_Shape.VERTEX, [324])
-model.testResultsVolumes(Boolean_1, [2053931.555419394280761480331420898])
+model.testResultsVolumes(Boolean_1, [2053931.913933836854994297027587891])
 
 assert(model.checkPythonDump())
index 7e4ecaa96227b631283cda3c4be85a7859ce9fc9..2227b8971325ae750159d2de53d158bf26c46ccd 100644 (file)
@@ -9,7 +9,7 @@ def sketch():
     
     mouseClick(waitForObject(":OpenParts*_AppElements_ViewPort"), annotaion_point[0], annotaion_point[1], 0, Qt.LeftButton)
     waitFor("object.exists(':Distance.First object_QLineEdit')", 20000)
-    test.compare(str(findObject(":Distance.First object_QLineEdit").text), "SketchPoint_1/PointCoordindates")
+    test.compare(str(findObject(":Distance.First object_QLineEdit").text), "SketchPoint_1/PointCoordinates")
     waitFor("object.exists(':Distance.Second object_QLineEdit')", 20000)
     test.compare(str(findObject(":Distance.Second object_QLineEdit").text), "SketchLine_1")
     waitFor("object.exists(':Distance.ConstraintValue_ModuleBase_ParamSpinBox')", 20000)