1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SketchAPI_Ellipse.h"
22 #include <GeomAPI_Pnt2d.h>
24 #include <ModelHighAPI_Dumper.h>
25 #include <ModelHighAPI_Selection.h>
26 #include <ModelHighAPI_Tools.h>
28 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
29 #include <SketchPlugin_Line.h>
30 #include <SketchPlugin_Point.h>
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";
36 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature> & theFeature)
37 : SketchAPI_SketchEntity(theFeature)
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)
49 setByCenterFocusAndRadius(theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius);
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)
60 setByCenterFocusAndRadius(theCenter, theFocus, theMinorRadius);
64 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
65 const ModelHighAPI_Selection& theExternal)
66 : SketchAPI_SketchEntity(theFeature)
69 setByExternal(theExternal);
73 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
74 const std::string& theExternalName)
75 : SketchAPI_SketchEntity(theFeature)
78 setByExternalName(theExternalName);
82 SketchAPI_Ellipse::~SketchAPI_Ellipse()
86 void SketchAPI_Ellipse::setByCenterFocusAndRadius(double theCenterX, double theCenterY,
87 double theFocusX, double theFocusY,
88 double theMinorRadius)
90 fillAttribute(center(), theCenterX, theCenterY);
91 fillAttribute(firstFocus(), theFocusX, theFocusY);
92 fillAttribute(theMinorRadius, myminorRadius);
97 void SketchAPI_Ellipse::setByCenterFocusAndRadius(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
98 const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
99 double theMinorRadius)
101 fillAttribute(theCenter, mycenter);
102 fillAttribute(theFocus, myfirstFocus);
103 fillAttribute(theMinorRadius, myminorRadius);
108 void SketchAPI_Ellipse::setByExternal(const ModelHighAPI_Selection & theExternal)
110 fillAttribute(theExternal, external());
114 void SketchAPI_Ellipse::setByExternalName(const std::string & theExternalName)
116 fillAttribute(ModelHighAPI_Selection("EDGE", theExternalName), external());
120 void SketchAPI_Ellipse::setCenter(double theX, double theY)
122 fillAttribute(center(), theX, theY);
126 void SketchAPI_Ellipse::setCenter(const std::shared_ptr<GeomAPI_Pnt2d> & theCenter)
128 fillAttribute(theCenter, mycenter);
132 void SketchAPI_Ellipse::setFocus(double theX, double theY)
134 fillAttribute(firstFocus(), theX, theY);
138 void SketchAPI_Ellipse::setFocus(const std::shared_ptr<GeomAPI_Pnt2d> & theFocus)
140 fillAttribute(theFocus, myfirstFocus);
144 void SketchAPI_Ellipse::setMinorRadius(double theMinorRadius)
146 fillAttribute(theMinorRadius, myminorRadius);
150 static const std::list<PairOfStrings>& ellipseAttrAndDumpNames()
152 static std::list<PairOfStrings> anAttributes;
153 if (anAttributes.empty()) {
154 anAttributes.push_back(
155 PairOfStrings(SketchPlugin_Ellipse::CENTER_ID(), "center"));
156 anAttributes.push_back(
157 PairOfStrings(SketchPlugin_Ellipse::FIRST_FOCUS_ID(), "firstFocus"));
158 anAttributes.push_back(
159 PairOfStrings(SketchPlugin_Ellipse::SECOND_FOCUS_ID(), "secondFocus"));
160 anAttributes.push_back(
161 PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(), "majorAxisStart"));
162 anAttributes.push_back(
163 PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), "majorAxisEnd"));
164 anAttributes.push_back(
165 PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(), "minorAxisStart"));
166 anAttributes.push_back(
167 PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), "minorAxisEnd"));
172 static CompositeFeaturePtr sketchForFeature(FeaturePtr theFeature)
174 const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
175 for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt)
176 if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID())
177 return std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
178 return CompositeFeaturePtr();
181 static void createInternalConstraint(const CompositeFeaturePtr& theSketch,
182 const AttributePoint2DPtr& thePoint1,
183 const AttributePoint2DPtr& thePoint2)
185 FeaturePtr aConstraint = theSketch->addFeature(SketchPlugin_ConstraintCoincidenceInternal::ID());
186 aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(thePoint1);
187 aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(thePoint2);
188 aConstraint->execute();
191 static void createPoint(const CompositeFeaturePtr& theSketch,
192 const FeaturePtr& theEllipse,
193 const std::string& theCoincident,
194 const std::string& theAuxOrName,
195 std::list<FeaturePtr>& theEntities)
197 if (theAuxOrName.empty())
200 AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
201 theEllipse->attribute(theCoincident));
203 FeaturePtr aPointFeature = theSketch->addFeature(SketchPlugin_Point::ID());
204 AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
205 aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
206 aCoord->setValue(anElPoint->x(), anElPoint->y());
207 aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
208 aPointFeature->execute();
210 std::string aName = theEllipse->name() + "_" + theCoincident;
211 aPointFeature->data()->setName(aName);
212 aPointFeature->lastResult()->data()->setName(aName);
214 if (theAuxOrName == AUXILIARY_VALUE)
215 aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
216 else if (!theAuxOrName.empty()) {
217 aPointFeature->data()->setName(theAuxOrName);
218 aPointFeature->lastResult()->data()->setName(theAuxOrName);
221 createInternalConstraint(theSketch, anElPoint, aCoord);
223 theEntities.push_back(aPointFeature);
226 static void createAxis(const CompositeFeaturePtr& theSketch,
227 const FeaturePtr& theEllipse,
228 const std::string& theCoincidentStart,
229 const std::string& theCoincidentEnd,
230 const std::string& theAuxOrName,
231 std::list<FeaturePtr>& theEntities)
233 if (theAuxOrName.empty())
236 AttributePoint2DPtr aStartPoint =
237 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentStart));
238 AttributePoint2DPtr aEndPoint =
239 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentEnd));
241 FeaturePtr aLineFeature = theSketch->addFeature(SketchPlugin_Line::ID());
242 AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
243 aLineFeature->attribute(SketchPlugin_Line::START_ID()));
244 aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
245 AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
246 aLineFeature->attribute(SketchPlugin_Line::END_ID()));
247 aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
248 aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
249 aLineFeature->execute();
251 std::string aName = theEllipse->name() + "_" +
252 (theCoincidentStart == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ?
253 "major_axis" : "minor_axis");
254 aLineFeature->data()->setName(aName);
255 aLineFeature->lastResult()->data()->setName(aName);
257 if (theAuxOrName == AUXILIARY_VALUE)
258 aLineFeature->boolean(SketchPlugin_Line::AUXILIARY_ID())->setValue(true);
259 else if (!theAuxOrName.empty()) {
260 aLineFeature->data()->setName(theAuxOrName);
261 aLineFeature->lastResult()->data()->setName(theAuxOrName);
264 createInternalConstraint(theSketch, aStartPoint, aLineStart);
265 createInternalConstraint(theSketch, aEndPoint, aLineEnd);
267 theEntities.push_back(aLineFeature);
270 std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::construction(
271 const std::string& center,
272 const std::string& firstFocus,
273 const std::string& secondFocus,
274 const std::string& majorAxisStart,
275 const std::string& majorAxisEnd,
276 const std::string& minorAxisStart,
277 const std::string& minorAxisEnd,
278 const std::string& majorAxis,
279 const std::string& minorAxis) const
281 FeaturePtr anEllipse = feature();
283 std::list<PairOfStrings> anAttributes = ellipseAttrAndDumpNames();
284 // append start and end attributes for axes
285 anAttributes.push_back(PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
286 SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()));
287 anAttributes.push_back(PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
288 SketchPlugin_Ellipse::MINOR_AXIS_END_ID()));
290 return buildConstructionEntities(anEllipse, anAttributes, center, firstFocus, secondFocus,
291 majorAxisStart, majorAxisEnd, minorAxisStart, minorAxisEnd, majorAxis, minorAxis);
294 std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::buildConstructionEntities(
295 const FeaturePtr& theEllipse,
296 const std::list<PairOfStrings>& theAttributes,
297 const std::string& theCenter,
298 const std::string& theFirstFocus,
299 const std::string& theSecondFocus,
300 const std::string& theMajorAxisStart,
301 const std::string& theMajorAxisEnd,
302 const std::string& theMinorAxisStart,
303 const std::string& theMinorAxisEnd,
304 const std::string& theMajorAxis,
305 const std::string& theMinorAxis)
307 CompositeFeaturePtr aSketch = sketchForFeature(theEllipse);
309 std::list<FeaturePtr> anEntities;
310 std::list<PairOfStrings>::const_iterator anAttrIt = theAttributes.begin();
311 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theCenter, anEntities);
312 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theFirstFocus, anEntities);
313 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theSecondFocus, anEntities);
314 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMajorAxisStart, anEntities);
315 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMajorAxisEnd, anEntities);
316 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMinorAxisStart, anEntities);
317 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMinorAxisEnd, anEntities);
319 createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMajorAxis, anEntities);
321 createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMinorAxis, anEntities);
323 return SketchAPI_SketchEntity::wrap(anEntities);
326 static void ellipseAttributeAndAuxiliaryFeature(
327 const FeaturePtr& theInternalConstraint,
328 const std::pair<std::string, std::string>& theMajorAxisStartEnd,
329 const std::pair<std::string, std::string>& theMinorAxisStartEnd,
330 std::map<std::string, FeaturePtr>& theAttrToFeature)
332 AttributeRefAttrPtr aRefAttrA =
333 theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
334 AttributeRefAttrPtr aRefAttrB =
335 theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
336 // the first point is usually an ellipse attribute
337 // and the second point is an attribute of the auxiliary feature
338 ObjectPtr anAuxObject;
339 if (aRefAttrB->isObject())
340 anAuxObject = aRefAttrB->object();
342 anAuxObject = aRefAttrB->attr()->owner();
344 FeaturePtr anAuxFeature = ModelAPI_Feature::feature(anAuxObject);
345 if (anAuxFeature->getKind() == SketchPlugin_Point::ID())
346 theAttrToFeature[aRefAttrA->attr()->id()] = anAuxFeature;
348 const std::string& anAttrID = aRefAttrA->attr()->id();
349 if (anAttrID == theMajorAxisStartEnd.first || anAttrID == theMajorAxisStartEnd.second)
350 theAttrToFeature[MAJOR_AXIS_ID] = anAuxFeature;
351 else if (anAttrID == theMinorAxisStartEnd.first || anAttrID == theMinorAxisStartEnd.second)
352 theAttrToFeature[MINOR_AXIS_ID] = anAuxFeature;
356 void SketchAPI_Ellipse::collectAuxiliaryFeatures(
357 FeaturePtr theEllipse,
358 const std::pair<std::string, std::string>& theMajorAxis,
359 const std::pair<std::string, std::string>& theMinorAxis,
360 std::map<std::string, FeaturePtr>& theAttrToFeature)
362 const std::set<AttributePtr>& aRefs = theEllipse->data()->refsToMe();
363 for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
364 aRefIt != aRefs.end(); ++aRefIt) {
365 FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
366 if (anOwner->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
367 // process internal constraints only
368 ellipseAttributeAndAuxiliaryFeature(anOwner, theMajorAxis, theMinorAxis, theAttrToFeature);
373 void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const
376 return; // no need to dump copied feature
378 FeaturePtr aBase = feature();
379 const std::string& aSketchName = theDumper.parentName(aBase);
381 AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
382 if (anExternal->context()) {
383 // circle is external
384 theDumper << aBase << " = " << aSketchName << ".addEllipse(" << anExternal << ")" << std::endl;
386 // ellipse given by center, focus and radius
387 theDumper << aBase << " = " << aSketchName << ".addEllipse("
388 << center() << ", " << firstFocus() << ", " << minorRadius() << ")" << std::endl;
390 // dump "auxiliary" flag if necessary
391 SketchAPI_SketchEntity::dump(theDumper);
393 // dump auxiliary features produced by ellipse
394 std::map<std::string, FeaturePtr> anAuxFeatures;
395 static const std::pair<std::string, std::string> aMajorAxis(
396 SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
397 SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
398 static const std::pair<std::string, std::string> aMinorAxis(
399 SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
400 SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
401 collectAuxiliaryFeatures(aBase, aMajorAxis, aMinorAxis, anAuxFeatures);
403 if (!anAuxFeatures.empty()) {
404 // a list of attributes to write features in special order
405 const std::list<PairOfStrings>& anAttributes = ellipseAttrAndDumpNames();
406 dumpConstructionEntities(theDumper, aBase, anAttributes, anAuxFeatures);
410 void SketchAPI_Ellipse::dumpConstructionEntities(
411 ModelHighAPI_Dumper& theDumper,
412 const FeaturePtr& theEllipse,
413 const std::list<PairOfStrings>& theAttributes,
414 const std::map<std::string, FeaturePtr>& theAuxFeatures)
416 std::list<PairOfStrings> anAttributes = theAttributes;
418 anAttributes.push_back(PairOfStrings(MAJOR_AXIS_ID, MAJOR_AXIS_ID));
419 anAttributes.push_back(PairOfStrings(MINOR_AXIS_ID, MINOR_AXIS_ID));
423 for (std::list<PairOfStrings>::iterator anIt = anAttributes.begin();
424 anIt != anAttributes.end(); ++anIt) {
425 std::map<std::string, FeaturePtr>::const_iterator aFound = theAuxFeatures.find(anIt->first);
426 if (aFound == theAuxFeatures.end())
430 theDumper << theDumper.name(aFound->second, false);
431 theDumper.doNotDumpFeature(aFound->second);
434 theDumper << "] = " << theDumper.name(theEllipse) << ".construction(";
436 for (std::list<PairOfStrings>::iterator anIt = anAttributes.begin();
437 anIt != anAttributes.end(); ++anIt) {
438 std::map<std::string, FeaturePtr>::const_iterator aFound = theAuxFeatures.find(anIt->first);
439 if (aFound == theAuxFeatures.end())
444 theDumper << anIt->second << " = \"";
445 if (aFound->second->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value())
446 theDumper << AUXILIARY_VALUE;
448 theDumper << aFound->second->name();
451 theDumper << ")" << std::endl;