]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_Projection.cpp
Salome HOME
Projection of outer edge onto the sketch plane (improvement #1297)
[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   bool hasResult = lastResult();
57
58   std::shared_ptr<GeomAPI_Edge> anEdge;
59   if (aProjection->getKind() == SketchPlugin_Line::ID()) {
60     std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
61         aProjection->attribute(SketchPlugin_Line::START_ID()));
62     std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
63         aProjection->attribute(SketchPlugin_Line::END_ID()));
64
65     // edge to store result
66     std::shared_ptr<GeomAPI_Pnt> aFirst = sketch()->to3D(aStartPnt->x(), aStartPnt->y());
67     std::shared_ptr<GeomAPI_Pnt> aLast = sketch()->to3D(aEndPnt->x(), aEndPnt->y());
68     anEdge = GeomAlgoAPI_EdgeBuilder::line(aFirst, aLast);
69   }
70   else {
71     std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
72     std::shared_ptr<GeomAPI_Dir> aNormal = aSketchPlane->direction();
73
74     if (aProjection->getKind() == SketchPlugin_Circle::ID()) {
75       std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
76           aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
77
78       // edge to store result
79       std::shared_ptr<GeomAPI_Pnt> aCenter = sketch()->to3D(aCenterPnt->x(), aCenterPnt->y());
80       double aRadius = aProjection->real(SketchPlugin_Circle::RADIUS_ID())->value();
81       anEdge = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
82     }
83     else if (aProjection->getKind() == SketchPlugin_Arc::ID()) {
84       std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
85           aProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
86       std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
87           aProjection->attribute(SketchPlugin_Arc::START_ID()));
88       std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
89           aProjection->attribute(SketchPlugin_Arc::END_ID()));
90
91       // edge to store result
92       std::shared_ptr<GeomAPI_Pnt> aCenter = sketch()->to3D(aCenterPnt->x(), aCenterPnt->y());
93       std::shared_ptr<GeomAPI_Pnt> aFirst = sketch()->to3D(aStartPnt->x(), aStartPnt->y());
94       std::shared_ptr<GeomAPI_Pnt> aLast = sketch()->to3D(aEndPnt->x(), aEndPnt->y());
95       anEdge = GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aFirst, aLast, aNormal);
96     }
97   }
98
99   std::shared_ptr<ModelAPI_ResultConstruction> aConstr = document()->createConstruction(data());
100   aConstr->setShape(anEdge);
101   aConstr->setIsInHistory(false);
102   setResult(aConstr);
103
104   if (!hasResult)
105     aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
106 }
107
108 void SketchPlugin_Projection::move(double theDeltaX, double theDeltaY)
109 {
110   // feature cannot be moved
111 }
112
113 void SketchPlugin_Projection::attributeChanged(const std::string& theID)
114 {
115   if ((theID == EXTERNAL_FEATURE_ID() || theID == EXTERNAL_ID()) && !myIsComputing) {
116     myIsComputing = true;
117     computeProjection(theID);
118     myIsComputing = false;
119   }
120 }
121
122 void SketchPlugin_Projection::computeProjection(const std::string& theID)
123 {
124   AttributeSelectionPtr aExtFeature =
125       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(attribute(EXTERNAL_FEATURE_ID()));
126
127   std::shared_ptr<GeomAPI_Edge> anEdge;
128   if (aExtFeature && aExtFeature->value() && aExtFeature->value()->isEdge()) {
129     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aExtFeature->value()));
130   } else if (aExtFeature->context() && aExtFeature->context()->shape() && aExtFeature->context()->shape()->isEdge()) {
131     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aExtFeature->context()->shape()));
132   }
133   if (!anEdge.get())
134     return;
135
136   AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
137   FeaturePtr aProjection;
138   if (aRefAttr && aRefAttr->isInitialized())
139     aProjection = ModelAPI_Feature::feature(aRefAttr->object());
140
141   // if the type of feature differs with already selected, remove it and create once again
142   if (aProjection) {
143     if ((anEdge->isLine() && aProjection->getKind() != SketchPlugin_Line::ID()) ||
144         (anEdge->isCircle() && aProjection->getKind() != SketchPlugin_Circle::ID()) ||
145         (anEdge->isArc() && aProjection->getKind() != SketchPlugin_Arc::ID())) {
146       DocumentPtr aDoc = sketch()->document();
147       aDoc->removeFeature(aProjection);
148       aProjection = FeaturePtr();
149       aRefAttr->setObject(aProjection);
150     }
151   }
152
153   std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
154
155   if (anEdge->isLine()) {
156     std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
157     std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
158
159     std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
160     std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
161     if (aFirstInSketch->distance(aLastInSketch) < tolerance)
162       return; // line is semi-orthogonal to the sketch plane
163
164     if (!aProjection)
165       aProjection = sketch()->addFeature(SketchPlugin_Line::ID());
166
167     // update attributes of projection
168     std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
169         aProjection->attribute(SketchPlugin_Line::START_ID()));
170     std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
171         aProjection->attribute(SketchPlugin_Line::END_ID()));
172     aStartPnt->setValue(aFirstInSketch);
173     aEndPnt->setValue(aLastInSketch);
174   }
175   else if (anEdge->isCircle()) {
176     std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
177     double aRadius = aCircle->radius();
178
179     std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
180     std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
181
182     if (!aProjection)
183       aProjection = sketch()->addFeature(SketchPlugin_Circle::ID());
184
185     // update attributes of projection
186     std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
187         aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
188     aCenterPnt->setValue(aCenterInSketch);
189     aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aRadius);
190   }
191   else if (anEdge->isArc()) {
192     std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
193     std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
194     std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
195     std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
196
197     std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
198     std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
199     std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
200
201     if (!aProjection)
202       aProjection = sketch()->addFeature(SketchPlugin_Arc::ID());
203
204     // update attributes of projection
205     std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
206         aProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
207     std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
208         aProjection->attribute(SketchPlugin_Arc::START_ID()));
209     std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
210         aProjection->attribute(SketchPlugin_Arc::END_ID()));
211     aStartPnt->setValue(aFirstInSketch);
212     aEndPnt->setValue(aLastInSketch);
213     aCenterPnt->setValue(aCenterInSketch);
214   }
215
216   aProjection->execute();
217   aRefAttr->setObject(aProjection);
218
219   if (theID == EXTERNAL_FEATURE_ID())
220     selection(EXTERNAL_ID())->setValue(aExtFeature->context(), aExtFeature->context()->shape());
221 }