Salome HOME
Fix compilation on Debian 7
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Projection.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:    SketchPlugin_Projection.cpp
4 // Created: 07 May 2014
5 // Author:  Artem ZHIDKOV
6
7 #include <SketchPlugin_Projection.h>
8
9 #include <SketchPlugin_Arc.h>
10 #include <SketchPlugin_Circle.h>
11 #include <SketchPlugin_Line.h>
12 #include <SketchPlugin_Sketch.h>
13
14 #include <ModelAPI_AttributeRefAttr.h>
15 #include <ModelAPI_AttributeSelection.h>
16 #include <ModelAPI_AttributeDouble.h>
17 #include <ModelAPI_ResultConstruction.h>
18 #include <ModelAPI_Session.h>
19 #include <ModelAPI_Validator.h>
20
21 #include <GeomAPI_Circ.h>
22 #include <GeomAPI_Edge.h>
23 #include <GeomAPI_Lin.h>
24 #include <GeomAPI_Pnt.h>
25 #include <GeomAPI_Pnt2d.h>
26 #include <GeomAlgoAPI_EdgeBuilder.h>
27 #include <GeomDataAPI_Point2D.h>
28
29 #include <cmath>
30
31 static const double tolerance = 1.e-7;
32
33 SketchPlugin_Projection::SketchPlugin_Projection()
34     : SketchPlugin_SketchEntity(),
35       myIsComputing(false)
36 {
37 }
38
39 void SketchPlugin_Projection::initDerivedClassAttributes()
40 {
41   data()->addAttribute(EXTERNAL_FEATURE_ID(), ModelAPI_AttributeSelection::typeId());
42   data()->addAttribute(PROJECTED_FEATURE_ID(), ModelAPI_AttributeRefAttr::typeId());
43   data()->attribute(PROJECTED_FEATURE_ID())->setIsArgument(false);
44
45   data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
46   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
47 }
48
49 void SketchPlugin_Projection::execute()
50 {
51   AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
52   if (!aRefAttr || !aRefAttr->isInitialized())
53     return;
54   FeaturePtr aProjection = ModelAPI_Feature::feature(aRefAttr->object());
55
56   if (!lastResult().get()) {
57     ResultConstructionPtr aConstr = document()->createConstruction(data());
58     aConstr->setShape(std::shared_ptr<GeomAPI_Edge>());
59     aConstr->setIsInHistory(false);
60     setResult(aConstr);
61
62     aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
63   }
64 }
65
66 void SketchPlugin_Projection::move(double theDeltaX, double theDeltaY)
67 {
68   // feature cannot be moved
69 }
70
71 void SketchPlugin_Projection::attributeChanged(const std::string& theID)
72 {
73   if ((theID == EXTERNAL_FEATURE_ID() || theID == EXTERNAL_ID()) && !myIsComputing) {
74     myIsComputing = true;
75     computeProjection(theID);
76     myIsComputing = false;
77   }
78 }
79
80 void SketchPlugin_Projection::computeProjection(const std::string& theID)
81 {
82   AttributeSelectionPtr aExtFeature =
83       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(attribute(EXTERNAL_FEATURE_ID()));
84
85   std::shared_ptr<GeomAPI_Edge> anEdge;
86   if (aExtFeature && aExtFeature->value() && aExtFeature->value()->isEdge()) {
87     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aExtFeature->value()));
88   } else if (aExtFeature->context() && aExtFeature->context()->shape() && aExtFeature->context()->shape()->isEdge()) {
89     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aExtFeature->context()->shape()));
90   }
91   if (!anEdge.get())
92     return;
93
94   AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
95   FeaturePtr aProjection;
96   if (aRefAttr && aRefAttr->isInitialized())
97     aProjection = ModelAPI_Feature::feature(aRefAttr->object());
98
99   // if the type of feature differs with already selected, remove it and create once again
100   if (aProjection) {
101     if ((anEdge->isLine() && aProjection->getKind() != SketchPlugin_Line::ID()) ||
102         (anEdge->isCircle() && aProjection->getKind() != SketchPlugin_Circle::ID()) ||
103         (anEdge->isArc() && aProjection->getKind() != SketchPlugin_Arc::ID())) {
104       DocumentPtr aDoc = sketch()->document();
105       aDoc->removeFeature(aProjection);
106       aProjection = FeaturePtr();
107       aRefAttr->setObject(aProjection);
108     }
109   }
110
111   std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
112
113   if (anEdge->isLine()) {
114     std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
115     std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
116
117     std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
118     std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
119     if (aFirstInSketch->distance(aLastInSketch) < tolerance)
120       return; // line is semi-orthogonal to the sketch plane
121
122     if (!aProjection)
123       aProjection = sketch()->addFeature(SketchPlugin_Line::ID());
124
125     // update attributes of projection
126     std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
127         aProjection->attribute(SketchPlugin_Line::START_ID()));
128     std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
129         aProjection->attribute(SketchPlugin_Line::END_ID()));
130     aStartPnt->setValue(aFirstInSketch);
131     aEndPnt->setValue(aLastInSketch);
132   }
133   else if (anEdge->isCircle()) {
134     std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
135     double aRadius = aCircle->radius();
136
137     std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
138     std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
139
140     if (!aProjection)
141       aProjection = sketch()->addFeature(SketchPlugin_Circle::ID());
142
143     // update attributes of projection
144     std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
145         aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
146     aCenterPnt->setValue(aCenterInSketch);
147     aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aRadius);
148   }
149   else if (anEdge->isArc()) {
150     std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
151     std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
152     std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
153     std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
154
155     std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
156     std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
157     std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
158
159     if (!aProjection)
160       aProjection = sketch()->addFeature(SketchPlugin_Arc::ID());
161
162     // update attributes of projection
163     std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
164         aProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
165     std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
166         aProjection->attribute(SketchPlugin_Arc::START_ID()));
167     std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
168         aProjection->attribute(SketchPlugin_Arc::END_ID()));
169     aStartPnt->setValue(aFirstInSketch);
170     aEndPnt->setValue(aLastInSketch);
171     aCenterPnt->setValue(aCenterInSketch);
172   }
173
174   aProjection->execute();
175   aRefAttr->setObject(aProjection);
176
177   if (theID == EXTERNAL_FEATURE_ID())
178     selection(EXTERNAL_ID())->setValue(aExtFeature->context(), aExtFeature->context()->shape());
179 }