Salome HOME
Merge branch 'master' of newgeom:newgeom.git
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_ConstraintRadius.cpp
1 // File:    SketchPlugin_ConstraintRadius.cpp
2 // Created: 26 May 2014
3 // Author:  Artem ZHIDKOV
4
5 #include "SketchPlugin_ConstraintRadius.h"
6
7 #include <SketchPlugin_Arc.h>
8 #include <SketchPlugin_Circle.h>
9 #include <SketchPlugin_Point.h>
10
11 #include <ModelAPI_AttributeDouble.h>
12 #include <ModelAPI_Data.h>
13
14 #include <GeomAPI_Pnt2d.h>
15 #include <GeomAPI_Circ.h>
16 #include <GeomAPI_Circ2d.h>
17 #include <GeomAPI_Dir.h>
18 #include <GeomAPI_XYZ.h>
19 #include <GeomDataAPI_Point2D.h>
20 #include <GeomDataAPI_Dir.h>
21
22 SketchPlugin_ConstraintRadius::SketchPlugin_ConstraintRadius()
23 {
24 }
25
26 void SketchPlugin_ConstraintRadius::initAttributes()
27 {
28   data()->addAttribute(SketchPlugin_Constraint::VALUE(),    ModelAPI_AttributeDouble::type());
29   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type());
30   data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::type());
31 }
32
33 void SketchPlugin_ConstraintRadius::execute()
34 {
35   if (data()->attribute(SketchPlugin_Constraint::ENTITY_A())->isInitialized() &&
36       !data()->attribute(SketchPlugin_Constraint::VALUE())->isInitialized()) {
37
38     boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
39       boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
40     FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(aRef->object());
41     if (aFeature) {
42       double aRadius = 0;
43       boost::shared_ptr<ModelAPI_Data> aData = aFeature->data();
44       if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
45         AttributeDoublePtr anAttribute = boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>
46                                             (aData->attribute(SketchPlugin_Circle::RADIUS_ID()));
47         if (anAttribute)
48           aRadius = anAttribute->value();
49       }
50       else if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
51         boost::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = 
52           boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::CENTER_ID()));
53         boost::shared_ptr<GeomDataAPI_Point2D> aStartAttr = 
54           boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::START_ID()));
55         if (aCenterAttr && aStartAttr)
56           aRadius = aCenterAttr->pnt()->distance(aStartAttr->pnt());
57       }
58       boost::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = 
59         boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
60       aValueAttr->setValue(aRadius);
61     }
62   }
63 }
64
65 boost::shared_ptr<GeomAPI_AISObject> SketchPlugin_ConstraintRadius::getAISObject(
66                     boost::shared_ptr<GeomAPI_AISObject> thePrevious)
67 {
68   if (!sketch())
69     return thePrevious;
70
71   boost::shared_ptr<ModelAPI_Data> aData = data();
72   boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = 
73     boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
74   if (!anAttr)
75     return thePrevious;
76   FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->object());
77   std::string aKind = aFeature ? aFeature->getKind() : "";
78   if (aKind != SketchPlugin_Circle::ID() && aKind != SketchPlugin_Arc::ID())
79     return thePrevious;
80
81   // Flyout point
82   boost::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = 
83     boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
84   if (!aFlyoutAttr->isInitialized())
85     return thePrevious;
86   boost::shared_ptr<GeomAPI_Pnt> aFlyoutPnt = sketch()->to3D(aFlyoutAttr->x(), aFlyoutAttr->y());
87
88   // Prepare a circle
89   aData = aFeature->data();
90   boost::shared_ptr<GeomDataAPI_Point2D> aCenterAttr;
91   double aRadius;
92   if (aKind == SketchPlugin_Circle::ID()) {
93     aCenterAttr = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Circle::CENTER_ID()));
94     AttributeDoublePtr aCircRadius = 
95       boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Circle::RADIUS_ID()));
96     aRadius = aCircRadius->value();
97   }
98   else if (aKind == SketchPlugin_Arc::ID()) {
99     aCenterAttr = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::CENTER_ID()));
100     boost::shared_ptr<GeomDataAPI_Point2D> aStartAttr = 
101       boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Arc::START_ID()));
102     aRadius = aCenterAttr->pnt()->distance(aStartAttr->pnt());
103   }
104
105   boost::shared_ptr<GeomAPI_Pnt> aCenter = sketch()->to3D(aCenterAttr->x(), aCenterAttr->y());
106   boost::shared_ptr<GeomDataAPI_Dir> aNDir = 
107     boost::dynamic_pointer_cast<GeomDataAPI_Dir>(sketch()->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
108   boost::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
109   boost::shared_ptr<GeomAPI_Circ> aCircle(new GeomAPI_Circ(aCenter, aNormal, aRadius));
110
111   // Value
112   boost::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = 
113     boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE()));
114   double aValue = aRadius;
115   if (aValueAttr && aValueAttr->isInitialized())
116    aValue = aValueAttr->value();
117
118   boost::shared_ptr<GeomAPI_AISObject> anAIS = thePrevious;
119   if (!anAIS)
120     anAIS = boost::shared_ptr<GeomAPI_AISObject>(new GeomAPI_AISObject);
121   anAIS->createRadius(aCircle, aFlyoutPnt, aValue);
122   return anAIS;
123 }
124
125 void SketchPlugin_ConstraintRadius::move(double theDeltaX, double theDeltaY)
126 {
127   boost::shared_ptr<ModelAPI_Data> aData = data();
128   if (!aData->isValid())
129     return;
130
131   boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
132     boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
133   FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(aRef->object());
134   if (!aFeature)
135     return;
136   std::string aCenterAttrName;
137   if (aFeature->getKind() == SketchPlugin_Circle::ID())
138     aCenterAttrName = SketchPlugin_Circle::CENTER_ID();
139   else if (aFeature->getKind() == SketchPlugin_Arc::ID())
140     aCenterAttrName = SketchPlugin_Arc::CENTER_ID();
141   boost::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = 
142     boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aFeature->data()->attribute(aCenterAttrName));
143   boost::shared_ptr<GeomAPI_Pnt2d> aCenter = aCenterAttr->pnt();
144
145   // The specified delta applied on the circle curve, 
146   // so it will be scaled due to distance between flyout and center points
147   boost::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
148     boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
149   boost::shared_ptr<GeomAPI_Pnt2d> aFlyout = aFlyoutAttr->pnt();
150
151   boost::shared_ptr<ModelAPI_AttributeDouble> aRadius =
152     boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE()));
153   double aScale = aFlyout->distance(aCenter) / aRadius->value();
154
155   boost::shared_ptr<GeomAPI_Circ2d> aCircle(new GeomAPI_Circ2d(aCenter, aFlyout));
156   aFlyout->setX(aFlyout->x() + aScale * theDeltaX);
157   aFlyout->setY(aFlyout->y() + aScale * theDeltaY);
158   aFlyout = aCircle->project(aFlyout);
159
160   aFlyoutAttr->setValue(aFlyout->x(), aFlyout->y());
161 }