Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
[modules/shaper.git] / src / SketchAPI / SketchAPI_Ellipse.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SketchAPI_Ellipse.h"
21
22 #include <GeomAPI_Pnt2d.h>
23
24 #include <ModelHighAPI_Dumper.h>
25 #include <ModelHighAPI_Selection.h>
26 #include <ModelHighAPI_Tools.h>
27
28 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
29 #include <SketchPlugin_Line.h>
30 #include <SketchPlugin_Point.h>
31
32 static const std::string AUXILIARY_VALUE = "aux";
33 static const std::string MAJOR_AXIS_ID = "majorAxis";
34 static const std::string MINOR_AXIS_ID = "minorAxis";
35
36 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature> & theFeature)
37   : SketchAPI_SketchEntity(theFeature)
38 {
39   initialize();
40 }
41
42 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
43                                      double theCenterX, double theCenterY,
44                                      double theFocusX, double theFocusY,
45                                      double theMinorRadius)
46   : SketchAPI_SketchEntity(theFeature)
47 {
48   if(initialize()) {
49     setByCenterFocusAndRadius(theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius);
50   }
51 }
52
53 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
54                                      const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
55                                      const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
56                                      double theMinorRadius)
57 : SketchAPI_SketchEntity(theFeature)
58 {
59   if(initialize()) {
60     setByCenterFocusAndRadius(theCenter, theFocus, theMinorRadius);
61   }
62 }
63
64 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
65                                      const ModelHighAPI_Selection& theExternal)
66   : SketchAPI_SketchEntity(theFeature)
67 {
68   if (initialize()) {
69     setByExternal(theExternal);
70   }
71 }
72
73 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
74                                      const std::string& theExternalName)
75   : SketchAPI_SketchEntity(theFeature)
76 {
77   if (initialize()) {
78     setByExternalName(theExternalName);
79   }
80 }
81
82 SketchAPI_Ellipse::~SketchAPI_Ellipse()
83 {
84 }
85
86 void SketchAPI_Ellipse::setByCenterFocusAndRadius(double theCenterX, double theCenterY,
87                                                   double theFocusX, double theFocusY,
88                                                   double theMinorRadius)
89 {
90   fillAttribute(center(), theCenterX, theCenterY);
91   fillAttribute(firstFocus(), theFocusX, theFocusY);
92   fillAttribute(theMinorRadius, myminorRadius);
93
94   execute();
95 }
96
97 void SketchAPI_Ellipse::setByCenterFocusAndRadius(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
98                                                   const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
99                                                   double theMinorRadius)
100 {
101   fillAttribute(theCenter, mycenter);
102   fillAttribute(theFocus, myfirstFocus);
103   fillAttribute(theMinorRadius, myminorRadius);
104
105   execute();
106 }
107
108 void SketchAPI_Ellipse::setByExternal(const ModelHighAPI_Selection & theExternal)
109 {
110   fillAttribute(theExternal, external());
111   execute();
112 }
113
114 void SketchAPI_Ellipse::setByExternalName(const std::string & theExternalName)
115 {
116   fillAttribute(ModelHighAPI_Selection("EDGE", theExternalName), external());
117   execute();
118 }
119
120 void SketchAPI_Ellipse::setCenter(double theX, double theY)
121 {
122   fillAttribute(center(), theX, theY);
123   execute();
124 }
125
126 void SketchAPI_Ellipse::setCenter(const std::shared_ptr<GeomAPI_Pnt2d> & theCenter)
127 {
128   fillAttribute(theCenter, mycenter);
129   execute();
130 }
131
132 void SketchAPI_Ellipse::setFocus(double theX, double theY)
133 {
134   fillAttribute(firstFocus(), theX, theY);
135   execute();
136 }
137
138 void SketchAPI_Ellipse::setFocus(const std::shared_ptr<GeomAPI_Pnt2d> & theFocus)
139 {
140   fillAttribute(theFocus, myfirstFocus);
141   execute();
142 }
143
144 void SketchAPI_Ellipse::setMinorRadius(double theMinorRadius)
145 {
146   fillAttribute(theMinorRadius, myminorRadius);
147   execute();
148 }
149
150 ModelHighAPI_Selection SketchAPI_Ellipse::majorAxis() const
151 {
152   return ModelHighAPI_Selection();
153 }
154
155 ModelHighAPI_Selection SketchAPI_Ellipse::minorAxis() const
156 {
157   return ModelHighAPI_Selection();
158 }
159
160 static CompositeFeaturePtr sketchForFeature(FeaturePtr theFeature)
161 {
162   const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
163   for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt)
164     if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID())
165       return std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
166   return CompositeFeaturePtr();
167 }
168
169 static void createInternalConstraint(const CompositeFeaturePtr& theSketch,
170                                      const AttributePoint2DPtr& thePoint1,
171                                      const AttributePoint2DPtr& thePoint2)
172 {
173   FeaturePtr aConstraint = theSketch->addFeature(SketchPlugin_ConstraintCoincidenceInternal::ID());
174   aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(thePoint1);
175   aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(thePoint2);
176   aConstraint->execute();
177 }
178
179 static FeaturePtr createPoint(const CompositeFeaturePtr& theSketch,
180                               const AttributePtr& theCoincident,
181                               const std::string& theAuxOrName)
182 {
183   AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theCoincident);
184
185   FeaturePtr aPointFeature = theSketch->addFeature(SketchPlugin_Point::ID());
186   AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
187       aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
188   aCoord->setValue(anElPoint->x(), anElPoint->y());
189   aPointFeature->execute();
190
191   if (theAuxOrName == AUXILIARY_VALUE)
192     aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
193   else if (!theAuxOrName.empty()) {
194     aPointFeature->data()->setName(theAuxOrName);
195     aPointFeature->lastResult()->data()->setName(theAuxOrName);
196   }
197
198   createInternalConstraint(theSketch, anElPoint, aCoord);
199
200   return aPointFeature;
201 }
202
203 static FeaturePtr createAxis(const CompositeFeaturePtr& theSketch,
204                              const AttributePtr& theCoincidentStart,
205                              const AttributePtr& theCoincidentEnd,
206                              const std::string& theAuxOrName)
207 {
208   AttributePoint2DPtr aStartPoint =
209       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theCoincidentStart);
210   AttributePoint2DPtr aEndPoint =
211       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theCoincidentEnd);
212
213   FeaturePtr aLineFeature = theSketch->addFeature(SketchPlugin_Line::ID());
214   AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
215       aLineFeature->attribute(SketchPlugin_Line::START_ID()));
216   aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
217   AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
218       aLineFeature->attribute(SketchPlugin_Line::END_ID()));
219   aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
220   aLineFeature->execute();
221
222   if (theAuxOrName == AUXILIARY_VALUE)
223     aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
224   else if (!theAuxOrName.empty()) {
225     aLineFeature->data()->setName(theAuxOrName);
226     aLineFeature->lastResult()->data()->setName(theAuxOrName);
227   }
228
229   createInternalConstraint(theSketch, aStartPoint, aLineStart);
230   createInternalConstraint(theSketch, aEndPoint, aLineEnd);
231
232   return aLineFeature;
233 }
234
235 std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::construction(
236     const std::string& center,
237     const std::string& firstFocus,
238     const std::string& secondFocus,
239     const std::string& majorAxisStart,
240     const std::string& majorAxisEnd,
241     const std::string& minorAxisStart,
242     const std::string& minorAxisEnd,
243     const std::string& majorAxis,
244     const std::string& minorAxis) const
245 {
246   FeaturePtr anEllipse = feature();
247   CompositeFeaturePtr aSketch = sketchForFeature(anEllipse);
248
249   std::list<FeaturePtr> anEntities;
250   if (!center.empty()) {
251     AttributePtr aCenterAttr = anEllipse->attribute(SketchPlugin_Ellipse::CENTER_ID());
252     anEntities.push_back(createPoint(aSketch, aCenterAttr, center));
253   }
254   if (!firstFocus.empty()) {
255     AttributePtr aFocusAttr = anEllipse->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID());
256     anEntities.push_back(createPoint(aSketch, aFocusAttr, firstFocus));
257   }
258   if (!secondFocus.empty()) {
259     AttributePtr aFocusAttr = anEllipse->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID());
260     anEntities.push_back(createPoint(aSketch, aFocusAttr, secondFocus));
261   }
262   if (!majorAxisStart.empty()) {
263     AttributePtr aStartAttr = anEllipse->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
264     anEntities.push_back(createPoint(aSketch, aStartAttr, majorAxisStart));
265   }
266   if (!majorAxisEnd.empty()) {
267     AttributePtr aEndAttr = anEllipse->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
268     anEntities.push_back(createPoint(aSketch, aEndAttr, majorAxisEnd));
269   }
270   if (!minorAxisStart.empty()) {
271     AttributePtr aStartAttr = anEllipse->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID());
272     anEntities.push_back(createPoint(aSketch, aStartAttr, minorAxisStart));
273   }
274   if (!minorAxisEnd.empty()) {
275     AttributePtr aEndAttr = anEllipse->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
276     anEntities.push_back(createPoint(aSketch, aEndAttr, minorAxisEnd));
277   }
278   if (!majorAxis.empty()) {
279     AttributePtr aStartAttr = anEllipse->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
280     AttributePtr aEndAttr = anEllipse->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
281     anEntities.push_back(createAxis(aSketch, aStartAttr, aEndAttr, majorAxis));
282   }
283   if (!minorAxis.empty()) {
284     AttributePtr aStartAttr = anEllipse->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID());
285     AttributePtr aEndAttr = anEllipse->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
286     anEntities.push_back(createAxis(aSketch, aStartAttr, aEndAttr, minorAxis));
287   }
288
289   return SketchAPI_SketchEntity::wrap(anEntities);
290 }
291
292 static void ellipseAttributeAndAuxiliaryFeature(
293     const FeaturePtr& theInternalConstraint,
294     std::map<std::string, FeaturePtr>& theAttrToFeature)
295 {
296   AttributeRefAttrPtr aRefAttrA =
297       theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
298   AttributeRefAttrPtr aRefAttrB =
299       theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
300   // the first point is usually an ellipse attribute
301   // and the second point is an attribute of the auxiliary feature
302   ObjectPtr anAuxObject;
303   if (aRefAttrB->isObject())
304     anAuxObject = aRefAttrB->object();
305   else
306     anAuxObject = aRefAttrB->attr()->owner();
307
308   FeaturePtr anAuxFeature = ModelAPI_Feature::feature(anAuxObject);
309   if (anAuxFeature->getKind() == SketchPlugin_Point::ID())
310     theAttrToFeature[aRefAttrA->attr()->id()] = anAuxFeature;
311   else {
312     const std::string& anAttrID = aRefAttrA->attr()->id();
313     if (anAttrID == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ||
314         anAttrID == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID())
315       theAttrToFeature[MAJOR_AXIS_ID] = anAuxFeature;
316     else if (anAttrID == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() ||
317              anAttrID == SketchPlugin_Ellipse::MINOR_AXIS_END_ID())
318       theAttrToFeature[MINOR_AXIS_ID] = anAuxFeature;
319   }
320 }
321
322 void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const
323 {
324   if (isCopy())
325     return; // no need to dump copied feature
326
327   FeaturePtr aBase = feature();
328   const std::string& aSketchName = theDumper.parentName(aBase);
329
330   AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
331   if (anExternal->context()) {
332     // circle is external
333     theDumper << aBase << " = " << aSketchName << ".addEllipse(" << anExternal << ")" << std::endl;
334   } else {
335     // ellipse given by center, focus and radius
336     theDumper << aBase << " = " << aSketchName << ".addEllipse("
337               << center() << ", " << firstFocus() << ", " << minorRadius() << ")" << std::endl;
338   }
339   // dump "auxiliary" flag if necessary
340   SketchAPI_SketchEntity::dump(theDumper);
341
342   // dump auxiliary features produced by ellipse
343   std::map<std::string, FeaturePtr> anAuxFeatures;
344   const std::set<AttributePtr>& aRefs = aBase->data()->refsToMe();
345   for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
346        aRefIt != aRefs.end(); ++aRefIt) {
347     FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
348     if (anOwner->getKind() != SketchPlugin_ConstraintCoincidenceInternal::ID())
349       continue; // process internal constraints only
350     ellipseAttributeAndAuxiliaryFeature(anOwner, anAuxFeatures);
351   }
352   if (!anAuxFeatures.empty()) {
353     typedef std::pair<std::string, std::string> PairOfStrings;
354     static PairOfStrings anAttributes[] = {
355         PairOfStrings(SketchPlugin_Ellipse::CENTER_ID(), "center"),
356         PairOfStrings(SketchPlugin_Ellipse::FIRST_FOCUS_ID(), "firstFocus"),
357         PairOfStrings(SketchPlugin_Ellipse::SECOND_FOCUS_ID(), "secondFocus"),
358         PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(), "majorAxisStart"),
359         PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), "majorAxisEnd"),
360         PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(), "minorAxisStart"),
361         PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), "minorAxisEnd"),
362         PairOfStrings(MAJOR_AXIS_ID, MAJOR_AXIS_ID),
363         PairOfStrings(MINOR_AXIS_ID, MINOR_AXIS_ID)
364     };
365
366     theDumper << "[";
367     bool isFirst = true;
368     for (PairOfStrings* anIt = std::begin(anAttributes);
369          anIt != std::end(anAttributes); ++anIt) {
370       std::map<std::string, FeaturePtr>::iterator aFound = anAuxFeatures.find(anIt->first);
371       if (aFound == anAuxFeatures.end())
372         continue;
373       if (!isFirst)
374         theDumper << ", ";
375       theDumper << theDumper.name(aFound->second, false);
376       theDumper.doNotDumpFeature(aFound->second);
377       isFirst = false;
378     }
379     theDumper << "] = " << theDumper.name(aBase) << ".construction(";
380     isFirst = true;
381     for (PairOfStrings* anIt = std::begin(anAttributes);
382          anIt != std::end(anAttributes); ++anIt) {
383       std::map<std::string, FeaturePtr>::iterator aFound = anAuxFeatures.find(anIt->first);
384       if (aFound == anAuxFeatures.end())
385         continue;
386       if (!isFirst)
387         theDumper << ", ";
388       isFirst = false;
389       theDumper << anIt->second << " = \"";
390       if (aFound->second->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value())
391         theDumper << AUXILIARY_VALUE;
392       else
393         theDumper << aFound->second->name();
394       theDumper << "\"";
395     }
396     theDumper << ")" << std::endl;
397   }
398 }