Salome HOME
Issue #273: Add copyright string
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_ConstraintRadius.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:    SketchPlugin_ConstraintRadius.cpp
4 // Created: 26 May 2014
5 // Author:  Artem ZHIDKOV
6
7 #include "SketchPlugin_ConstraintRadius.h"
8
9 #include <SketchPlugin_Arc.h>
10 #include <SketchPlugin_Circle.h>
11 #include <SketchPlugin_Point.h>
12
13 #include <ModelAPI_AttributeDouble.h>
14 #include <ModelAPI_Data.h>
15
16 #include <GeomAPI_Pnt2d.h>
17 #include <GeomAPI_Circ.h>
18 #include <GeomAPI_Circ2d.h>
19 #include <GeomAPI_Dir.h>
20 #include <GeomAPI_XYZ.h>
21 #include <GeomDataAPI_Point2D.h>
22 #include <GeomDataAPI_Dir.h>
23
24 #include <Config_PropManager.h>
25
26 SketchPlugin_ConstraintRadius::SketchPlugin_ConstraintRadius()
27 {
28 }
29
30 void SketchPlugin_ConstraintRadius::initAttributes()
31 {
32   data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::type());
33   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type());
34   data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::type());
35 }
36
37 void SketchPlugin_ConstraintRadius::execute()
38 {
39   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = std::dynamic_pointer_cast<
40       ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
41   FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
42   if (aFeature) {
43     double aRadius = 0;
44     std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
45     if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
46       AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
47           aData->attribute(SketchPlugin_Circle::RADIUS_ID()));
48       if (anAttribute)
49         aRadius = anAttribute->value();
50     } else if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
51       std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
52           GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::CENTER_ID()));
53       std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
54           GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::START_ID()));
55       if (aCenterAttr && aStartAttr)
56         aRadius = aCenterAttr->pnt()->distance(aStartAttr->pnt());
57     }
58     //std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
59     //    ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
60     //if(!aValueAttr->isInitialized()) {
61     //  aValueAttr->setValue(aRadius);
62     //}
63   }
64 }
65
66 double SketchPlugin_ConstraintRadius::circleRadius(std::shared_ptr<ModelAPI_Feature>& theCirc)
67 {
68   static const double kErrorResult = -1.;
69   if (!sketch())
70     return kErrorResult;
71
72   std::shared_ptr<ModelAPI_Data> aData = data();
73   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
74       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
75   if (!anAttr)
76     return kErrorResult;
77   theCirc = ModelAPI_Feature::feature(anAttr->object());
78   std::string aKind = theCirc ? theCirc->getKind() : "";
79   if (aKind != SketchPlugin_Circle::ID() && aKind != SketchPlugin_Arc::ID())
80     return kErrorResult;
81
82   DataPtr aCircData = theCirc->data();
83   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr;
84   if (aKind == SketchPlugin_Circle::ID()) {
85     AttributeDoublePtr aCircRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
86         aCircData->attribute(SketchPlugin_Circle::RADIUS_ID()));
87     return aCircRadius->value();
88   } else {
89     aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
90         aCircData->attribute(SketchPlugin_Arc::CENTER_ID()));
91     std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
92         GeomDataAPI_Point2D>(aCircData->attribute(SketchPlugin_Arc::START_ID()));
93     return aCenterAttr->pnt()->distance(aStartAttr->pnt());
94   }
95   return kErrorResult;
96 }
97
98 AISObjectPtr SketchPlugin_ConstraintRadius::getAISObject(AISObjectPtr thePrevious)
99 {
100   std::shared_ptr<ModelAPI_Feature> aCyrcFeature;
101   double aRadius = circleRadius(aCyrcFeature);
102   if (aRadius < 0)
103     return thePrevious; // can not create a good presentation
104
105   // Flyout point
106   std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = std::dynamic_pointer_cast<
107       GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
108   std::shared_ptr<GeomAPI_Pnt> aFlyoutPnt;
109   if (aFlyoutAttr->isInitialized()) {
110     aFlyoutPnt = sketch()->to3D(aFlyoutAttr->x(), aFlyoutAttr->y());
111   } 
112
113   // Prepare a circle
114   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr;
115   if (aCyrcFeature->getKind() == SketchPlugin_Circle::ID()) { // circle
116     aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
117         aCyrcFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
118     if (!aFlyoutPnt) {
119       double aShift = aRadius * 1.1;
120       std::shared_ptr<GeomAPI_Pnt2d> aPnt = aCenterAttr->pnt();
121       std::shared_ptr<GeomAPI_Pnt2d> aFPnt = 
122         std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aPnt->x() + aShift, aPnt->y() + aShift));
123       aFlyoutAttr->setValue(aFPnt);
124       aFlyoutPnt = sketch()->to3D(aFPnt->x(), aFPnt->y());
125     }
126   } else { // arc
127     aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
128         aCyrcFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
129     if (!aFlyoutPnt) {
130       std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
131         GeomDataAPI_Point2D>(aCyrcFeature->data()->attribute(SketchPlugin_Arc::START_ID()));      
132       aFlyoutAttr->setValue(aStartAttr->pnt());
133       aFlyoutPnt = sketch()->to3D(aStartAttr->pnt()->x(), aStartAttr->pnt()->y());
134     }
135   }
136
137   std::shared_ptr<GeomAPI_Pnt> aCenter = sketch()->to3D(aCenterAttr->x(), aCenterAttr->y());
138   std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
139       sketch()->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
140   std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
141   std::shared_ptr<GeomAPI_Circ> aCircle(new GeomAPI_Circ(aCenter, aNormal, aRadius));
142
143   // Value
144   std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
145       ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
146   if (aValueAttr->isInitialized())
147     aRadius = aValueAttr->value();
148   AISObjectPtr anAIS = thePrevious;
149   if (!anAIS)
150     anAIS = AISObjectPtr(new GeomAPI_AISObject);
151   anAIS->createRadius(aCircle, aFlyoutPnt, aRadius);
152
153   // Set color from preferences
154   std::vector<int> aRGB = Config_PropManager::color("Visualization", "radius_color", RADIUS_COLOR);
155   anAIS->setColor(aRGB[0], aRGB[1], aRGB[2]);
156   return anAIS;
157 }
158
159 void SketchPlugin_ConstraintRadius::move(double theDeltaX, double theDeltaY)
160 {
161   std::shared_ptr<ModelAPI_Data> aData = data();
162   if (!aData->isValid())
163     return;
164
165   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = std::dynamic_pointer_cast<
166       ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
167   FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
168   if (!aFeature)
169     return;
170   std::string aCenterAttrName;
171   if (aFeature->getKind() == SketchPlugin_Circle::ID())
172     aCenterAttrName = SketchPlugin_Circle::CENTER_ID();
173   else if (aFeature->getKind() == SketchPlugin_Arc::ID())
174     aCenterAttrName = SketchPlugin_Arc::CENTER_ID();
175   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
176       GeomDataAPI_Point2D>(aFeature->data()->attribute(aCenterAttrName));
177   std::shared_ptr<GeomAPI_Pnt2d> aCenter = aCenterAttr->pnt();
178
179   // The specified delta applied on the circle curve, 
180   // so it will be scaled due to distance between flyout and center points
181   std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = std::dynamic_pointer_cast<
182       GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
183   std::shared_ptr<GeomAPI_Pnt2d> aFlyout = aFlyoutAttr->pnt();
184
185   std::shared_ptr<ModelAPI_AttributeDouble> aRadius = std::dynamic_pointer_cast<
186       ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE()));
187   double aScale = aFlyout->distance(aCenter) / aRadius->value();
188
189   std::shared_ptr<GeomAPI_Circ2d> aCircle(new GeomAPI_Circ2d(aCenter, aFlyout));
190   aFlyout->setX(aFlyout->x() + aScale * theDeltaX);
191   aFlyout->setY(aFlyout->y() + aScale * theDeltaY);
192   aFlyout = aCircle->project(aFlyout);
193
194   aFlyoutAttr->setValue(aFlyout->x(), aFlyout->y());
195 }
196
197 void SketchPlugin_ConstraintRadius::attributeChanged(const std::string& theID) {
198   if (theID == SketchPlugin_Constraint::ENTITY_A()) {
199     std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
200         ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
201     if (!aValueAttr->isInitialized()) { // only if it is not initialized, try to compute the current value
202       std::shared_ptr<ModelAPI_Feature> aCyrcFeature;
203       double aRadius = circleRadius(aCyrcFeature);
204       if (aRadius > 0) { // set as value the radius of updated reference to another circle
205         aValueAttr->setValue(aRadius);
206       }
207     }
208   }
209 }