Salome HOME
An arc moving correction for dragging it by the center point.
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_ConstraintRadius.cpp
index fd429a544a241b97a99501dc5dd58b63a0e2938b..135b6bbdb285d2b66a5671251c11866f814a2869 100644 (file)
@@ -1,3 +1,5 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
 // File:    SketchPlugin_ConstraintRadius.cpp
 // Created: 26 May 2014
 // Author:  Artem ZHIDKOV
@@ -34,105 +36,119 @@ void SketchPlugin_ConstraintRadius::initAttributes()
 
 void SketchPlugin_ConstraintRadius::execute()
 {
-  boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef = boost::dynamic_pointer_cast<
+  std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = std::dynamic_pointer_cast<
       ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
   FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
   if (aFeature) {
     double aRadius = 0;
-    boost::shared_ptr<ModelAPI_Data> aData = aFeature->data();
+    std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
     if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
-      AttributeDoublePtr anAttribute = boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+      AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
           aData->attribute(SketchPlugin_Circle::RADIUS_ID()));
       if (anAttribute)
         aRadius = anAttribute->value();
     } else if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
-      boost::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = boost::dynamic_pointer_cast<
+      std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
           GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::CENTER_ID()));
-      boost::shared_ptr<GeomDataAPI_Point2D> aStartAttr = boost::dynamic_pointer_cast<
+      std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
           GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::START_ID()));
       if (aCenterAttr && aStartAttr)
         aRadius = aCenterAttr->pnt()->distance(aStartAttr->pnt());
     }
-    boost::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = boost::dynamic_pointer_cast<
-        ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
-    if(!aValueAttr->isInitialized()) {
-      aValueAttr->setValue(aRadius);
-    }
+    //std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
+    //    ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
+    //if(!aValueAttr->isInitialized()) {
+    //  aValueAttr->setValue(aRadius);
+    //}
   }
 }
 
-AISObjectPtr SketchPlugin_ConstraintRadius::getAISObject(AISObjectPtr thePrevious)
+double SketchPlugin_ConstraintRadius::circleRadius(std::shared_ptr<ModelAPI_Feature>& theCirc)
 {
+  static const double kErrorResult = -1.;
   if (!sketch())
-    return thePrevious;
+    return kErrorResult;
 
-  boost::shared_ptr<ModelAPI_Data> aData = data();
-  boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = boost::dynamic_pointer_cast<
+  std::shared_ptr<ModelAPI_Data> aData = data();
+  std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
   if (!anAttr)
-    return thePrevious;
-  FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->object());
-  std::string aKind = aFeature ? aFeature->getKind() : "";
+    return kErrorResult;
+  theCirc = ModelAPI_Feature::feature(anAttr->object());
+  std::string aKind = theCirc ? theCirc->getKind() : "";
   if (aKind != SketchPlugin_Circle::ID() && aKind != SketchPlugin_Arc::ID())
-    return thePrevious;
+    return kErrorResult;
+
+  DataPtr aCircData = theCirc->data();
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr;
+  if (aKind == SketchPlugin_Circle::ID()) {
+    AttributeDoublePtr aCircRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+        aCircData->attribute(SketchPlugin_Circle::RADIUS_ID()));
+    return aCircRadius->value();
+  } else {
+    aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+        aCircData->attribute(SketchPlugin_Arc::CENTER_ID()));
+    std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
+        GeomDataAPI_Point2D>(aCircData->attribute(SketchPlugin_Arc::START_ID()));
+    return aCenterAttr->pnt()->distance(aStartAttr->pnt());
+  }
+  return kErrorResult;
+}
+
+AISObjectPtr SketchPlugin_ConstraintRadius::getAISObject(AISObjectPtr thePrevious)
+{
+  std::shared_ptr<ModelAPI_Feature> aCyrcFeature;
+  double aRadius = circleRadius(aCyrcFeature);
+  if (aRadius < 0)
+    return thePrevious; // can not create a good presentation
 
   // Flyout point
-  boost::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = boost::dynamic_pointer_cast<
-      GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
-  boost::shared_ptr<GeomAPI_Pnt> aFlyoutPnt;
+  std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = std::dynamic_pointer_cast<
+      GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+  std::shared_ptr<GeomAPI_Pnt> aFlyoutPnt;
   if (aFlyoutAttr->isInitialized()) {
     aFlyoutPnt = sketch()->to3D(aFlyoutAttr->x(), aFlyoutAttr->y());
   } 
 
   // Prepare a circle
-  aData = aFeature->data();
-  boost::shared_ptr<GeomDataAPI_Point2D> aCenterAttr;
-  double aRadius;
-  if (aKind == SketchPlugin_Circle::ID()) {
-    aCenterAttr = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-        aData->attribute(SketchPlugin_Circle::CENTER_ID()));
-    AttributeDoublePtr aCircRadius = boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-        aData->attribute(SketchPlugin_Circle::RADIUS_ID()));
-    aRadius = aCircRadius->value();
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr;
+  if (aCyrcFeature->getKind() == SketchPlugin_Circle::ID()) { // circle
+    aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+        aCyrcFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
     if (!aFlyoutPnt) {
       double aShift = aRadius * 1.1;
-      boost::shared_ptr<GeomAPI_Pnt2d> aPnt = aCenterAttr->pnt();
-      boost::shared_ptr<GeomAPI_Pnt2d> aFPnt = 
-        boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aPnt->x() + aShift, aPnt->y() + aShift));
+      std::shared_ptr<GeomAPI_Pnt2d> aPnt = aCenterAttr->pnt();
+      std::shared_ptr<GeomAPI_Pnt2d> aFPnt = 
+        std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aPnt->x() + aShift, aPnt->y() + aShift));
       aFlyoutAttr->setValue(aFPnt);
       aFlyoutPnt = sketch()->to3D(aFPnt->x(), aFPnt->y());
     }
-  } else if (aKind == SketchPlugin_Arc::ID()) {
-    aCenterAttr = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-        aData->attribute(SketchPlugin_Arc::CENTER_ID()));
-    boost::shared_ptr<GeomDataAPI_Point2D> aStartAttr = boost::dynamic_pointer_cast<
-        GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::START_ID()));
-    aRadius = aCenterAttr->pnt()->distance(aStartAttr->pnt());
+  } else { // arc
+    aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+        aCyrcFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
     if (!aFlyoutPnt) {
-      boost::shared_ptr<GeomDataAPI_Point2D> aStartAttr = boost::dynamic_pointer_cast<
-        GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::START_ID()));      
+      std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
+        GeomDataAPI_Point2D>(aCyrcFeature->data()->attribute(SketchPlugin_Arc::START_ID()));      
       aFlyoutAttr->setValue(aStartAttr->pnt());
       aFlyoutPnt = sketch()->to3D(aStartAttr->pnt()->x(), aStartAttr->pnt()->y());
     }
   }
 
-  boost::shared_ptr<GeomAPI_Pnt> aCenter = sketch()->to3D(aCenterAttr->x(), aCenterAttr->y());
-  boost::shared_ptr<GeomDataAPI_Dir> aNDir = boost::dynamic_pointer_cast<GeomDataAPI_Dir>(
+  std::shared_ptr<GeomAPI_Pnt> aCenter = sketch()->to3D(aCenterAttr->x(), aCenterAttr->y());
+  std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
       sketch()->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
-  boost::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
-  boost::shared_ptr<GeomAPI_Circ> aCircle(new GeomAPI_Circ(aCenter, aNormal, aRadius));
+  std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
+  std::shared_ptr<GeomAPI_Circ> aCircle(new GeomAPI_Circ(aCenter, aNormal, aRadius));
 
   // Value
-  boost::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = boost::dynamic_pointer_cast<
-      ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE()));
-  double aValue = aRadius;
-  if (aValueAttr && aValueAttr->isInitialized())
-    aValue = aValueAttr->value();
-
+  std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
+      ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
+  if (aValueAttr->isInitialized())
+    aRadius = aValueAttr->value();
   AISObjectPtr anAIS = thePrevious;
   if (!anAIS)
     anAIS = AISObjectPtr(new GeomAPI_AISObject);
-  anAIS->createRadius(aCircle, aFlyoutPnt, aValue);
+  anAIS->createRadius(aCircle, aFlyoutPnt, aRadius);
 
   // Set color from preferences
   std::vector<int> aRGB = Config_PropManager::color("Visualization", "radius_color", RADIUS_COLOR);
@@ -142,11 +158,11 @@ AISObjectPtr SketchPlugin_ConstraintRadius::getAISObject(AISObjectPtr thePreviou
 
 void SketchPlugin_ConstraintRadius::move(double theDeltaX, double theDeltaY)
 {
-  boost::shared_ptr<ModelAPI_Data> aData = data();
+  std::shared_ptr<ModelAPI_Data> aData = data();
   if (!aData->isValid())
     return;
 
-  boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef = boost::dynamic_pointer_cast<
+  std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = std::dynamic_pointer_cast<
       ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
   FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
   if (!aFeature)
@@ -156,24 +172,38 @@ void SketchPlugin_ConstraintRadius::move(double theDeltaX, double theDeltaY)
     aCenterAttrName = SketchPlugin_Circle::CENTER_ID();
   else if (aFeature->getKind() == SketchPlugin_Arc::ID())
     aCenterAttrName = SketchPlugin_Arc::CENTER_ID();
-  boost::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = boost::dynamic_pointer_cast<
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
       GeomDataAPI_Point2D>(aFeature->data()->attribute(aCenterAttrName));
-  boost::shared_ptr<GeomAPI_Pnt2d> aCenter = aCenterAttr->pnt();
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter = aCenterAttr->pnt();
 
   // The specified delta applied on the circle curve, 
   // so it will be scaled due to distance between flyout and center points
-  boost::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = boost::dynamic_pointer_cast<
+  std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = std::dynamic_pointer_cast<
       GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
-  boost::shared_ptr<GeomAPI_Pnt2d> aFlyout = aFlyoutAttr->pnt();
+  std::shared_ptr<GeomAPI_Pnt2d> aFlyout = aFlyoutAttr->pnt();
 
-  boost::shared_ptr<ModelAPI_AttributeDouble> aRadius = boost::dynamic_pointer_cast<
+  std::shared_ptr<ModelAPI_AttributeDouble> aRadius = std::dynamic_pointer_cast<
       ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE()));
   double aScale = aFlyout->distance(aCenter) / aRadius->value();
 
-  boost::shared_ptr<GeomAPI_Circ2d> aCircle(new GeomAPI_Circ2d(aCenter, aFlyout));
+  std::shared_ptr<GeomAPI_Circ2d> aCircle(new GeomAPI_Circ2d(aCenter, aFlyout));
   aFlyout->setX(aFlyout->x() + aScale * theDeltaX);
   aFlyout->setY(aFlyout->y() + aScale * theDeltaY);
   aFlyout = aCircle->project(aFlyout);
 
   aFlyoutAttr->setValue(aFlyout->x(), aFlyout->y());
 }
+
+void SketchPlugin_ConstraintRadius::attributeChanged(const std::string& theID) {
+  if (theID == SketchPlugin_Constraint::ENTITY_A()) {
+    std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
+        ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
+    if (!aValueAttr->isInitialized()) { // only if it is not initialized, try to compute the current value
+      std::shared_ptr<ModelAPI_Feature> aCyrcFeature;
+      double aRadius = circleRadius(aCyrcFeature);
+      if (aRadius > 0) { // set as value the radius of updated reference to another circle
+        aValueAttr->setValue(aRadius);
+      }
+    }
+  }
+}