]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchAPI/SketchAPI_Ellipse.cpp
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 FeaturePtr& theEllipse,
181                               const std::string& theCoincident,
182                               const std::string& theAuxOrName)
183 {
184   AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
185       theEllipse->attribute(theCoincident));
186
187   FeaturePtr aPointFeature = theSketch->addFeature(SketchPlugin_Point::ID());
188   AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
189       aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
190   aCoord->setValue(anElPoint->x(), anElPoint->y());
191   aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
192   aPointFeature->execute();
193
194   std::string aName = theEllipse->name() + "_" + theCoincident;
195   aPointFeature->data()->setName(aName);
196   aPointFeature->lastResult()->data()->setName(aName);
197
198   if (theAuxOrName == AUXILIARY_VALUE)
199     aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
200   else if (!theAuxOrName.empty()) {
201     aPointFeature->data()->setName(theAuxOrName);
202     aPointFeature->lastResult()->data()->setName(theAuxOrName);
203   }
204
205   createInternalConstraint(theSketch, anElPoint, aCoord);
206
207   return aPointFeature;
208 }
209
210 static FeaturePtr createAxis(const CompositeFeaturePtr& theSketch,
211                              const FeaturePtr& theEllipse,
212                              const std::string& theCoincidentStart,
213                              const std::string& theCoincidentEnd,
214                              const std::string& theAuxOrName)
215 {
216   AttributePoint2DPtr aStartPoint =
217       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentStart));
218   AttributePoint2DPtr aEndPoint =
219       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentEnd));
220
221   FeaturePtr aLineFeature = theSketch->addFeature(SketchPlugin_Line::ID());
222   AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
223       aLineFeature->attribute(SketchPlugin_Line::START_ID()));
224   aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
225   AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
226       aLineFeature->attribute(SketchPlugin_Line::END_ID()));
227   aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
228   aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
229   aLineFeature->execute();
230
231   std::string aName = theEllipse->name() + "_" +
232       (theCoincidentStart == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ?
233        "major_axis" : "minor_axis");
234   aLineFeature->data()->setName(aName);
235   aLineFeature->lastResult()->data()->setName(aName);
236
237   if (theAuxOrName == AUXILIARY_VALUE)
238     aLineFeature->boolean(SketchPlugin_Line::AUXILIARY_ID())->setValue(true);
239   else if (!theAuxOrName.empty()) {
240     aLineFeature->data()->setName(theAuxOrName);
241     aLineFeature->lastResult()->data()->setName(theAuxOrName);
242   }
243
244   createInternalConstraint(theSketch, aStartPoint, aLineStart);
245   createInternalConstraint(theSketch, aEndPoint, aLineEnd);
246
247   return aLineFeature;
248 }
249
250 std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::construction(
251     const std::string& center,
252     const std::string& firstFocus,
253     const std::string& secondFocus,
254     const std::string& majorAxisStart,
255     const std::string& majorAxisEnd,
256     const std::string& minorAxisStart,
257     const std::string& minorAxisEnd,
258     const std::string& majorAxis,
259     const std::string& minorAxis) const
260 {
261   FeaturePtr anEllipse = feature();
262   CompositeFeaturePtr aSketch = sketchForFeature(anEllipse);
263
264   std::list<FeaturePtr> anEntities;
265   if (!center.empty()) {
266     anEntities.push_back(
267         createPoint(aSketch, anEllipse, SketchPlugin_Ellipse::CENTER_ID(), center));
268   }
269   if (!firstFocus.empty()) {
270     anEntities.push_back(
271         createPoint(aSketch, anEllipse, SketchPlugin_Ellipse::FIRST_FOCUS_ID(), firstFocus));
272   }
273   if (!secondFocus.empty()) {
274     anEntities.push_back(
275         createPoint(aSketch, anEllipse, SketchPlugin_Ellipse::SECOND_FOCUS_ID(), secondFocus));
276   }
277   if (!majorAxisStart.empty()) {
278     anEntities.push_back(
279         createPoint(aSketch, anEllipse, SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(), majorAxisStart));
280   }
281   if (!majorAxisEnd.empty()) {
282     anEntities.push_back(
283         createPoint(aSketch, anEllipse, SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), majorAxisEnd));
284   }
285   if (!minorAxisStart.empty()) {
286     anEntities.push_back(
287         createPoint(aSketch, anEllipse, SketchPlugin_Ellipse::MINOR_AXIS_START_ID(), minorAxisStart));
288   }
289   if (!minorAxisEnd.empty()) {
290     anEntities.push_back(
291         createPoint(aSketch, anEllipse, SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), minorAxisEnd));
292   }
293   if (!majorAxis.empty()) {
294     anEntities.push_back(createAxis(aSketch, anEllipse, SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
295                                     SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), majorAxis));
296   }
297   if (!minorAxis.empty()) {
298     anEntities.push_back(createAxis(aSketch, anEllipse, SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
299                                     SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), minorAxis));
300   }
301
302   return SketchAPI_SketchEntity::wrap(anEntities);
303 }
304
305 static void ellipseAttributeAndAuxiliaryFeature(
306     const FeaturePtr& theInternalConstraint,
307     std::map<std::string, FeaturePtr>& theAttrToFeature)
308 {
309   AttributeRefAttrPtr aRefAttrA =
310       theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
311   AttributeRefAttrPtr aRefAttrB =
312       theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
313   // the first point is usually an ellipse attribute
314   // and the second point is an attribute of the auxiliary feature
315   ObjectPtr anAuxObject;
316   if (aRefAttrB->isObject())
317     anAuxObject = aRefAttrB->object();
318   else
319     anAuxObject = aRefAttrB->attr()->owner();
320
321   FeaturePtr anAuxFeature = ModelAPI_Feature::feature(anAuxObject);
322   if (anAuxFeature->getKind() == SketchPlugin_Point::ID())
323     theAttrToFeature[aRefAttrA->attr()->id()] = anAuxFeature;
324   else {
325     const std::string& anAttrID = aRefAttrA->attr()->id();
326     if (anAttrID == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ||
327         anAttrID == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID())
328       theAttrToFeature[MAJOR_AXIS_ID] = anAuxFeature;
329     else if (anAttrID == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() ||
330              anAttrID == SketchPlugin_Ellipse::MINOR_AXIS_END_ID())
331       theAttrToFeature[MINOR_AXIS_ID] = anAuxFeature;
332   }
333 }
334
335 void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const
336 {
337   if (isCopy())
338     return; // no need to dump copied feature
339
340   FeaturePtr aBase = feature();
341   const std::string& aSketchName = theDumper.parentName(aBase);
342
343   AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
344   if (anExternal->context()) {
345     // circle is external
346     theDumper << aBase << " = " << aSketchName << ".addEllipse(" << anExternal << ")" << std::endl;
347   } else {
348     // ellipse given by center, focus and radius
349     theDumper << aBase << " = " << aSketchName << ".addEllipse("
350               << center() << ", " << firstFocus() << ", " << minorRadius() << ")" << std::endl;
351   }
352   // dump "auxiliary" flag if necessary
353   SketchAPI_SketchEntity::dump(theDumper);
354
355   // dump auxiliary features produced by ellipse
356   std::map<std::string, FeaturePtr> anAuxFeatures;
357   const std::set<AttributePtr>& aRefs = aBase->data()->refsToMe();
358   for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
359        aRefIt != aRefs.end(); ++aRefIt) {
360     FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
361     if (anOwner->getKind() != SketchPlugin_ConstraintCoincidenceInternal::ID())
362       continue; // process internal constraints only
363     ellipseAttributeAndAuxiliaryFeature(anOwner, anAuxFeatures);
364   }
365   if (!anAuxFeatures.empty()) {
366     typedef std::pair<std::string, std::string> PairOfStrings;
367     static PairOfStrings anAttributes[] = {
368         PairOfStrings(SketchPlugin_Ellipse::CENTER_ID(), "center"),
369         PairOfStrings(SketchPlugin_Ellipse::FIRST_FOCUS_ID(), "firstFocus"),
370         PairOfStrings(SketchPlugin_Ellipse::SECOND_FOCUS_ID(), "secondFocus"),
371         PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(), "majorAxisStart"),
372         PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), "majorAxisEnd"),
373         PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(), "minorAxisStart"),
374         PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), "minorAxisEnd"),
375         PairOfStrings(MAJOR_AXIS_ID, MAJOR_AXIS_ID),
376         PairOfStrings(MINOR_AXIS_ID, MINOR_AXIS_ID)
377     };
378
379     theDumper << "[";
380     bool 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       theDumper << theDumper.name(aFound->second, false);
389       theDumper.doNotDumpFeature(aFound->second);
390       isFirst = false;
391     }
392     theDumper << "] = " << theDumper.name(aBase) << ".construction(";
393     isFirst = true;
394     for (PairOfStrings* anIt = std::begin(anAttributes);
395          anIt != std::end(anAttributes); ++anIt) {
396       std::map<std::string, FeaturePtr>::iterator aFound = anAuxFeatures.find(anIt->first);
397       if (aFound == anAuxFeatures.end())
398         continue;
399       if (!isFirst)
400         theDumper << ", ";
401       isFirst = false;
402       theDumper << anIt->second << " = \"";
403       if (aFound->second->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value())
404         theDumper << AUXILIARY_VALUE;
405       else
406         theDumper << aFound->second->name();
407       theDumper << "\"";
408     }
409     theDumper << ")" << std::endl;
410   }
411 }