Salome HOME
Edge filter
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_ConstraintRadius.cpp
index 31b253d542b8010d97f6f19e47fe16f2cc34fef0..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
@@ -27,100 +29,126 @@ SketchPlugin_ConstraintRadius::SketchPlugin_ConstraintRadius()
 
 void SketchPlugin_ConstraintRadius::initAttributes()
 {
-  data()->addAttribute(SketchPlugin_Constraint::VALUE(),    ModelAPI_AttributeDouble::type());
+  data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::type());
   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type());
   data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::type());
 }
 
 void SketchPlugin_ConstraintRadius::execute()
 {
-  if (data()->attribute(SketchPlugin_Constraint::ENTITY_A())->isInitialized() &&
-      !data()->attribute(SketchPlugin_Constraint::VALUE())->isInitialized()) {
-
-    boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
-      boost::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();
-      if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
-        AttributeDoublePtr anAttribute = boost::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<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()));
-        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()));
-      aValueAttr->setValue(aRadius);
+  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;
+    std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
+    if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
+      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()) {
+      std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
+          GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::CENTER_ID()));
+      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());
     }
+    //std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
+    //    ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
+    //if(!aValueAttr->isInitialized()) {
+    //  aValueAttr->setValue(aRadius);
+    //}
   }
 }
 
-boost::shared_ptr<GeomAPI_AISObject> SketchPlugin_ConstraintRadius::getAISObject(
-                    boost::shared_ptr<GeomAPI_AISObject> 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<ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  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()));
-  if (!aFlyoutAttr->isInitialized())
-    return thePrevious;
-  boost::shared_ptr<GeomAPI_Pnt> aFlyoutPnt = sketch()->to3D(aFlyoutAttr->x(), aFlyoutAttr->y());
+  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();
-  }
-  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());
+  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;
+      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 { // arc
+    aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+        aCyrcFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
+    if (!aFlyoutPnt) {
+      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>(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_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()));
+  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();
-
-  boost::shared_ptr<GeomAPI_AISObject> anAIS = thePrevious;
+  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 = boost::shared_ptr<GeomAPI_AISObject>(new GeomAPI_AISObject);
-  anAIS->createRadius(aCircle, aFlyoutPnt, aValue);
+    anAIS = AISObjectPtr(new GeomAPI_AISObject);
+  anAIS->createRadius(aCircle, aFlyoutPnt, aRadius);
 
   // Set color from preferences
   std::vector<int> aRGB = Config_PropManager::color("Visualization", "radius_color", RADIUS_COLOR);
@@ -130,12 +158,12 @@ boost::shared_ptr<GeomAPI_AISObject> SketchPlugin_ConstraintRadius::getAISObject
 
 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<ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  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)
     return;
@@ -144,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<GeomDataAPI_Point2D>(aFeature->data()->attribute(aCenterAttrName));
-  boost::shared_ptr<GeomAPI_Pnt2d> aCenter = aCenterAttr->pnt();
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
+      GeomDataAPI_Point2D>(aFeature->data()->attribute(aCenterAttrName));
+  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<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
-  boost::shared_ptr<GeomAPI_Pnt2d> aFlyout = aFlyoutAttr->pnt();
+  std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = std::dynamic_pointer_cast<
+      GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+  std::shared_ptr<GeomAPI_Pnt2d> aFlyout = aFlyoutAttr->pnt();
 
-  boost::shared_ptr<ModelAPI_AttributeDouble> aRadius =
-    boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE()));
+  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);
+      }
+    }
+  }
+}