Salome HOME
Support of wide string
[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 <ModelAPI_Tools.h>
29
30 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
31 #include <SketchPlugin_Line.h>
32 #include <SketchPlugin_Point.h>
33
34 static const std::wstring AUXILIARY_VALUE = L"aux";
35 static const std::string MAJOR_AXIS_ID = "majorAxis";
36 static const std::string MINOR_AXIS_ID = "minorAxis";
37
38 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature> & theFeature)
39   : SketchAPI_SketchEntity(theFeature)
40 {
41   initialize();
42 }
43
44 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
45                                      double theCenterX, double theCenterY,
46                                      double theFocusX, double theFocusY,
47                                      double theMinorRadius)
48   : SketchAPI_SketchEntity(theFeature)
49 {
50   if(initialize()) {
51     setByCenterFocusAndRadius(theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius);
52   }
53 }
54
55 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
56                                      const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
57                                      const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
58                                      double theMinorRadius)
59 : SketchAPI_SketchEntity(theFeature)
60 {
61   if(initialize()) {
62     setByCenterFocusAndRadius(theCenter, theFocus, theMinorRadius);
63   }
64 }
65
66 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
67                                      const ModelHighAPI_Selection& theExternal)
68   : SketchAPI_SketchEntity(theFeature)
69 {
70   if (initialize()) {
71     setByExternal(theExternal);
72   }
73 }
74
75 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
76                                      const std::wstring& theExternalName)
77   : SketchAPI_SketchEntity(theFeature)
78 {
79   if (initialize()) {
80     setByExternalName(theExternalName);
81   }
82 }
83
84 SketchAPI_Ellipse::~SketchAPI_Ellipse()
85 {
86 }
87
88 void SketchAPI_Ellipse::setByCenterFocusAndRadius(double theCenterX, double theCenterY,
89                                                   double theFocusX, double theFocusY,
90                                                   double theMinorRadius)
91 {
92   fillAttribute(center(), theCenterX, theCenterY);
93   fillAttribute(firstFocus(), theFocusX, theFocusY);
94   fillAttribute(theMinorRadius, myminorRadius);
95
96   execute();
97 }
98
99 void SketchAPI_Ellipse::setByCenterFocusAndRadius(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
100                                                   const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
101                                                   double theMinorRadius)
102 {
103   fillAttribute(theCenter, mycenter);
104   fillAttribute(theFocus, myfirstFocus);
105   fillAttribute(theMinorRadius, myminorRadius);
106
107   execute();
108 }
109
110 void SketchAPI_Ellipse::setByExternal(const ModelHighAPI_Selection & theExternal)
111 {
112   fillAttribute(theExternal, external());
113   execute();
114 }
115
116 void SketchAPI_Ellipse::setByExternalName(const std::wstring & theExternalName)
117 {
118   fillAttribute(ModelHighAPI_Selection("EDGE", theExternalName), external());
119   execute();
120 }
121
122 void SketchAPI_Ellipse::setCenter(double theX, double theY)
123 {
124   fillAttribute(center(), theX, theY);
125   execute();
126 }
127
128 void SketchAPI_Ellipse::setCenter(const std::shared_ptr<GeomAPI_Pnt2d> & theCenter)
129 {
130   fillAttribute(theCenter, mycenter);
131   execute();
132 }
133
134 void SketchAPI_Ellipse::setFocus(double theX, double theY)
135 {
136   fillAttribute(firstFocus(), theX, theY);
137   execute();
138 }
139
140 void SketchAPI_Ellipse::setFocus(const std::shared_ptr<GeomAPI_Pnt2d> & theFocus)
141 {
142   fillAttribute(theFocus, myfirstFocus);
143   execute();
144 }
145
146 void SketchAPI_Ellipse::setMinorRadius(double theMinorRadius)
147 {
148   fillAttribute(theMinorRadius, myminorRadius);
149   execute();
150 }
151
152 static const std::list<PairOfStrings>& ellipseAttrAndDumpNames()
153 {
154   static std::list<PairOfStrings> anAttributes;
155   if (anAttributes.empty()) {
156     anAttributes.push_back(
157         PairOfStrings(SketchPlugin_Ellipse::CENTER_ID(), "center"));
158     anAttributes.push_back(
159         PairOfStrings(SketchPlugin_Ellipse::FIRST_FOCUS_ID(), "firstFocus"));
160     anAttributes.push_back(
161         PairOfStrings(SketchPlugin_Ellipse::SECOND_FOCUS_ID(), "secondFocus"));
162     anAttributes.push_back(
163         PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(), "majorAxisStart"));
164     anAttributes.push_back(
165         PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), "majorAxisEnd"));
166     anAttributes.push_back(
167         PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(), "minorAxisStart"));
168     anAttributes.push_back(
169         PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), "minorAxisEnd"));
170   }
171   return anAttributes;
172 }
173
174 static CompositeFeaturePtr sketchForFeature(FeaturePtr theFeature)
175 {
176   const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
177   for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt)
178     if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID())
179       return std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
180   return CompositeFeaturePtr();
181 }
182
183 static void createInternalConstraint(const CompositeFeaturePtr& theSketch,
184                                      const AttributePoint2DPtr& thePoint1,
185                                      const AttributePoint2DPtr& thePoint2)
186 {
187   FeaturePtr aConstraint = theSketch->addFeature(SketchPlugin_ConstraintCoincidenceInternal::ID());
188   aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(thePoint1);
189   aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(thePoint2);
190   aConstraint->execute();
191 }
192
193 static void createPoint(const CompositeFeaturePtr& theSketch,
194                         const FeaturePtr& theEllipse,
195                         const std::string& theCoincident,
196                         const std::wstring& theAuxOrName,
197                         std::list<FeaturePtr>& theEntities)
198 {
199   if (theAuxOrName.empty())
200     return;
201
202   AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
203       theEllipse->attribute(theCoincident));
204
205   FeaturePtr aPointFeature = theSketch->addFeature(SketchPlugin_Point::ID());
206   AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
207       aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
208   aCoord->setValue(anElPoint->x(), anElPoint->y());
209   aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
210   aPointFeature->execute();
211
212   std::wstring aName = theEllipse->name() + L"_" + ModelAPI_Tools::toWString(theCoincident);
213   aPointFeature->data()->setName(aName);
214   aPointFeature->lastResult()->data()->setName(aName);
215
216   if (theAuxOrName == AUXILIARY_VALUE)
217     aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
218   else if (!theAuxOrName.empty()) {
219     aPointFeature->data()->setName(theAuxOrName);
220     aPointFeature->lastResult()->data()->setName(theAuxOrName);
221   }
222
223   createInternalConstraint(theSketch, anElPoint, aCoord);
224
225   theEntities.push_back(aPointFeature);
226 }
227
228 static void createAxis(const CompositeFeaturePtr& theSketch,
229                        const FeaturePtr& theEllipse,
230                        const std::string& theCoincidentStart,
231                        const std::string& theCoincidentEnd,
232                        const std::wstring& theAuxOrName,
233                        std::list<FeaturePtr>& theEntities)
234 {
235   if (theAuxOrName.empty())
236     return;
237
238   AttributePoint2DPtr aStartPoint =
239       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentStart));
240   AttributePoint2DPtr aEndPoint =
241       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentEnd));
242
243   FeaturePtr aLineFeature = theSketch->addFeature(SketchPlugin_Line::ID());
244   AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
245       aLineFeature->attribute(SketchPlugin_Line::START_ID()));
246   aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
247   AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
248       aLineFeature->attribute(SketchPlugin_Line::END_ID()));
249   aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
250   aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
251   aLineFeature->execute();
252
253   std::wstring aName = theEllipse->name() + L"_" +
254       (theCoincidentStart == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ?
255        L"major_axis" : L"minor_axis");
256   aLineFeature->data()->setName(aName);
257   aLineFeature->lastResult()->data()->setName(aName);
258
259   if (theAuxOrName == AUXILIARY_VALUE)
260     aLineFeature->boolean(SketchPlugin_Line::AUXILIARY_ID())->setValue(true);
261   else if (!theAuxOrName.empty()) {
262     aLineFeature->data()->setName(theAuxOrName);
263     aLineFeature->lastResult()->data()->setName(theAuxOrName);
264   }
265
266   createInternalConstraint(theSketch, aStartPoint, aLineStart);
267   createInternalConstraint(theSketch, aEndPoint, aLineEnd);
268
269   theEntities.push_back(aLineFeature);
270 }
271
272 std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::construction(
273     const std::wstring& center,
274     const std::wstring& firstFocus,
275     const std::wstring& secondFocus,
276     const std::wstring& majorAxisStart,
277     const std::wstring& majorAxisEnd,
278     const std::wstring& minorAxisStart,
279     const std::wstring& minorAxisEnd,
280     const std::wstring& majorAxis,
281     const std::wstring& minorAxis) const
282 {
283   FeaturePtr anEllipse = feature();
284
285   std::list<PairOfStrings> anAttributes = ellipseAttrAndDumpNames();
286   // append start and end attributes for axes
287   anAttributes.push_back(PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
288                                        SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()));
289   anAttributes.push_back(PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
290                                        SketchPlugin_Ellipse::MINOR_AXIS_END_ID()));
291
292   return buildConstructionEntities(anEllipse, anAttributes, center, firstFocus, secondFocus,
293             majorAxisStart, majorAxisEnd, minorAxisStart, minorAxisEnd, majorAxis, minorAxis);
294 }
295
296 std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::buildConstructionEntities(
297       const FeaturePtr& theEllipse,
298       const std::list<PairOfStrings>& theAttributes,
299       const std::wstring& theCenter,
300       const std::wstring& theFirstFocus,
301       const std::wstring& theSecondFocus,
302       const std::wstring& theMajorAxisStart,
303       const std::wstring& theMajorAxisEnd,
304       const std::wstring& theMinorAxisStart,
305       const std::wstring& theMinorAxisEnd,
306       const std::wstring& theMajorAxis,
307       const std::wstring& theMinorAxis)
308 {
309   CompositeFeaturePtr aSketch = sketchForFeature(theEllipse);
310
311   std::list<FeaturePtr> anEntities;
312   std::list<PairOfStrings>::const_iterator anAttrIt = theAttributes.begin();
313   createPoint(aSketch, theEllipse, (anAttrIt++)->first, theCenter, anEntities);
314   createPoint(aSketch, theEllipse, (anAttrIt++)->first, theFirstFocus, anEntities);
315   createPoint(aSketch, theEllipse, (anAttrIt++)->first, theSecondFocus, anEntities);
316   createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMajorAxisStart, anEntities);
317   createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMajorAxisEnd, anEntities);
318   createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMinorAxisStart, anEntities);
319   createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMinorAxisEnd, anEntities);
320
321   createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMajorAxis, anEntities);
322   ++anAttrIt;
323   createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMinorAxis, anEntities);
324
325   return SketchAPI_SketchEntity::wrap(anEntities);
326 }
327
328 static void ellipseAttributeAndAuxiliaryFeature(
329     const FeaturePtr& theInternalConstraint,
330     const std::pair<std::string, std::string>& theMajorAxisStartEnd,
331     const std::pair<std::string, std::string>& theMinorAxisStartEnd,
332     std::map<std::string, FeaturePtr>& theAttrToFeature)
333 {
334   AttributeRefAttrPtr aRefAttrA =
335       theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
336   AttributeRefAttrPtr aRefAttrB =
337       theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
338   // the first point is usually an ellipse attribute
339   // and the second point is an attribute of the auxiliary feature
340   ObjectPtr anAuxObject;
341   if (aRefAttrB->isObject())
342     anAuxObject = aRefAttrB->object();
343   else
344     anAuxObject = aRefAttrB->attr()->owner();
345
346   FeaturePtr anAuxFeature = ModelAPI_Feature::feature(anAuxObject);
347   if (anAuxFeature->getKind() == SketchPlugin_Point::ID())
348     theAttrToFeature[aRefAttrA->attr()->id()] = anAuxFeature;
349   else {
350     const std::string& anAttrID = aRefAttrA->attr()->id();
351     if (anAttrID == theMajorAxisStartEnd.first || anAttrID == theMajorAxisStartEnd.second)
352       theAttrToFeature[MAJOR_AXIS_ID] = anAuxFeature;
353     else if (anAttrID == theMinorAxisStartEnd.first || anAttrID == theMinorAxisStartEnd.second)
354       theAttrToFeature[MINOR_AXIS_ID] = anAuxFeature;
355   }
356 }
357
358 void SketchAPI_Ellipse::collectAuxiliaryFeatures(
359     FeaturePtr theEllipse,
360     const std::pair<std::string, std::string>& theMajorAxis,
361     const std::pair<std::string, std::string>& theMinorAxis,
362     std::map<std::string, FeaturePtr>& theAttrToFeature)
363 {
364   const std::set<AttributePtr>& aRefs = theEllipse->data()->refsToMe();
365   for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
366        aRefIt != aRefs.end(); ++aRefIt) {
367     FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
368     if (anOwner->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
369       // process internal constraints only
370       ellipseAttributeAndAuxiliaryFeature(anOwner, theMajorAxis, theMinorAxis, theAttrToFeature);
371     }
372   }
373 }
374
375 void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const
376 {
377   if (isCopy())
378     return; // no need to dump copied feature
379
380   FeaturePtr aBase = feature();
381   const std::string& aSketchName = theDumper.parentName(aBase);
382
383   AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
384   if (anExternal->context()) {
385     // circle is external
386     theDumper << aBase << " = " << aSketchName << ".addEllipse(" << anExternal << ")" << std::endl;
387   } else {
388     // ellipse given by center, focus and radius
389     theDumper << aBase << " = " << aSketchName << ".addEllipse("
390               << center() << ", " << firstFocus() << ", " << minorRadius() << ")" << std::endl;
391   }
392   // dump "auxiliary" flag if necessary
393   SketchAPI_SketchEntity::dump(theDumper);
394
395   // dump auxiliary features produced by ellipse
396   std::map<std::string, FeaturePtr> anAuxFeatures;
397   static const std::pair<std::string, std::string> aMajorAxis(
398       SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
399       SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
400   static const std::pair<std::string, std::string> aMinorAxis(
401       SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
402       SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
403   collectAuxiliaryFeatures(aBase, aMajorAxis, aMinorAxis, anAuxFeatures);
404
405   if (!anAuxFeatures.empty()) {
406     // a list of attributes to write features in special order
407     const std::list<PairOfStrings>& anAttributes = ellipseAttrAndDumpNames();
408     dumpConstructionEntities(theDumper, aBase, anAttributes, anAuxFeatures);
409   }
410 }
411
412 void SketchAPI_Ellipse::dumpConstructionEntities(
413     ModelHighAPI_Dumper& theDumper,
414     const FeaturePtr& theEllipse,
415     const std::list<PairOfStrings>& theAttributes,
416     const std::map<std::string, FeaturePtr>& theAuxFeatures)
417 {
418   std::list<PairOfStrings> anAttributes = theAttributes;
419   // append axes
420   anAttributes.push_back(PairOfStrings(MAJOR_AXIS_ID, MAJOR_AXIS_ID));
421   anAttributes.push_back(PairOfStrings(MINOR_AXIS_ID, MINOR_AXIS_ID));
422
423   theDumper << "[";
424   bool isFirst = true;
425   for (std::list<PairOfStrings>::iterator anIt = anAttributes.begin();
426         anIt != anAttributes.end(); ++anIt) {
427     std::map<std::string, FeaturePtr>::const_iterator aFound = theAuxFeatures.find(anIt->first);
428     if (aFound == theAuxFeatures.end())
429       continue;
430     if (!isFirst)
431       theDumper << ", ";
432     theDumper << theDumper.name(aFound->second, false);
433     theDumper.doNotDumpFeature(aFound->second);
434     isFirst = false;
435   }
436   theDumper << "] = " << theDumper.name(theEllipse) << ".construction(";
437   isFirst = true;
438   for (std::list<PairOfStrings>::iterator anIt = anAttributes.begin();
439         anIt != anAttributes.end(); ++anIt) {
440     std::map<std::string, FeaturePtr>::const_iterator aFound = theAuxFeatures.find(anIt->first);
441     if (aFound == theAuxFeatures.end())
442       continue;
443     if (!isFirst)
444       theDumper << ", ";
445     isFirst = false;
446     theDumper << anIt->second << " = \"";
447     if (aFound->second->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value())
448       theDumper << AUXILIARY_VALUE;
449     else
450       theDumper << aFound->second->name();
451     theDumper << "\"";
452   }
453   theDumper << ")" << std::endl;
454 }