Salome HOME
Update copyrights
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_MacroCircle.cpp
index e0c178ddd78f70f2a940676330d8b2a8bbd3e132..0bcabf4ff4731a90b7d26c7f2f34fffe07ca4cc9 100644 (file)
@@ -1,8 +1,21 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-// File:        SketchPlugin_MacroCircle.cpp
-// Created:     26 May 2014
-// Author:      Artem ZHIDKOV
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 #include "SketchPlugin_MacroCircle.h"
 
@@ -97,7 +110,7 @@ void SketchPlugin_MacroCircle::execute()
   // 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));
+    <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, this));
 
   std::string anEditType = string(EDIT_CIRCLE_TYPE())->value();
   aMessage->setTypeOfCreation(!anEditType.empty() ? anEditType : aType);
@@ -105,6 +118,7 @@ void SketchPlugin_MacroCircle::execute()
   Events_Loop::loop()->send(aMessage);
 }
 
+// LCOV_EXCL_START
 std::string SketchPlugin_MacroCircle::processEvent(
                                               const std::shared_ptr<Events_Message>& theMessage)
 {
@@ -140,16 +154,25 @@ std::string SketchPlugin_MacroCircle::processEvent(
       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()) {
+        if (anAttribute.get()) {
+          if (!anAttribute->owner().get() || !anAttribute->owner()->data()->isValid()) {
             FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
-            anObject = aCreatedFeature->lastResult();
+            if (aCreatedFeature.get()) {
+              std::string anID = anAttribute->id();
+              std::string anArcID;
+              if (anID == CENTER_POINT_ID())
+                anArcID = SketchPlugin_Circle::CENTER_ID();
+              anAttribute = aCreatedFeature->attribute(anArcID);
+            }
           }
-          aRefAttr->setObject(anObject);
+          aRefAttr->setAttr(anAttribute);
+        }
+        else if (anObject.get()) {
+          // if attribute is NULL, only object is defined, it should be processed outside
+          // the feature because it might be an external feature, that will be
+          // removed/created again after restart operation
+          // #2468 - Crash when sketching circles successively on a repetition
+          aFilledAttributeName = CIRCLE_TYPE();
         }
       }
     }
@@ -157,15 +180,16 @@ std::string SketchPlugin_MacroCircle::processEvent(
   }
   return aFilledAttributeName;
 }
+// LCOV_EXCL_STOP
 
 void SketchPlugin_MacroCircle::constraintsForCircleByCenterAndPassed(FeaturePtr theCircleFeature)
 {
   // Create constraints.
-  SketchPlugin_Tools::createConstraint(
+  SketchPlugin_Tools::createCoincidenceOrTangency(
       this, CENTER_POINT_REF_ID(),
       theCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
       ObjectPtr(), false);
-  SketchPlugin_Tools::createConstraint(
+  SketchPlugin_Tools::createCoincidenceOrTangency(
       this, PASSED_POINT_REF_ID(), AttributePtr(),
       theCircleFeature->lastResult(), true);
 }
@@ -178,8 +202,10 @@ void SketchPlugin_MacroCircle::constraintsForCircleByThreePoints(FeaturePtr theC
 
   // Create constraints.
   ResultPtr aCircleResult = theCircleFeature->lastResult();
-  for (int i = 0; i < 3; ++i)
-    SketchPlugin_Tools::createConstraint(this, aPointRef[i], AttributePtr(), aCircleResult, true);
+  for (int i = 0; i < 3; ++i) {
+    SketchPlugin_Tools::createCoincidenceOrTangency(
+        this, aPointRef[i], AttributePtr(), aCircleResult, true);
+  }
 }
 
 FeaturePtr SketchPlugin_MacroCircle::createCircleFeature()
@@ -202,10 +228,15 @@ void SketchPlugin_MacroCircle::fillByCenterAndPassed()
   if (!aCenterAttr->isInitialized() || !aPassedAttr->isInitialized())
     return;
 
-  AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID());
   // Calculate circle parameters
-  std::shared_ptr<GeomAPI_Pnt2d> aCenter =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aCenterAttr)->pnt();
+  AttributeRefAttrPtr aCenterRef = refattr(CENTER_POINT_REF_ID());
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter;
+  std::shared_ptr<GeomAPI_Shape> aCurve;
+  SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+      aCenterRef, aCenterAttr, aCurve, aCenter);
+  if (!aCenter)
+    aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aCenterAttr)->pnt();
+  AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID());
   std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
   std::shared_ptr<GeomAPI_Shape> aTangentCurve;
   SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
@@ -400,6 +431,11 @@ void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) {
 
   AttributeDoublePtr aRadiusAttr = real(CIRCLE_RADIUS_ID());
   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);
+  }
   aRadiusAttr->setValue(myRadius);
   data()->blockSendAttributeUpdated(aWasBlocked, false);
 }