1 // Copyright (C) 2014-2020 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 <Locale_Convert.h>
26 #include <ModelHighAPI_Dumper.h>
27 #include <ModelHighAPI_Selection.h>
28 #include <ModelHighAPI_Tools.h>
30 #include <ModelAPI_Tools.h>
32 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
33 #include <SketchPlugin_Line.h>
34 #include <SketchPlugin_Point.h>
36 static const std::wstring AUXILIARY_VALUE = L"aux";
37 static const std::string MAJOR_AXIS_ID = "majorAxis";
38 static const std::string MINOR_AXIS_ID = "minorAxis";
40 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature> & theFeature)
41 : SketchAPI_SketchEntity(theFeature)
46 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
47 double theCenterX, double theCenterY,
48 double theFocusX, double theFocusY,
49 double theMinorRadius)
50 : SketchAPI_SketchEntity(theFeature)
53 setByCenterFocusAndRadius(theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius);
57 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
58 const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
59 const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
60 double theMinorRadius)
61 : SketchAPI_SketchEntity(theFeature)
64 setByCenterFocusAndRadius(theCenter, theFocus, theMinorRadius);
68 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
69 const ModelHighAPI_Selection& theExternal)
70 : SketchAPI_SketchEntity(theFeature)
73 setByExternal(theExternal);
77 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
78 const std::wstring& theExternalName)
79 : SketchAPI_SketchEntity(theFeature)
82 setByExternalName(theExternalName);
86 SketchAPI_Ellipse::~SketchAPI_Ellipse()
90 void SketchAPI_Ellipse::setByCenterFocusAndRadius(double theCenterX, double theCenterY,
91 double theFocusX, double theFocusY,
92 double theMinorRadius)
94 fillAttribute(center(), theCenterX, theCenterY);
95 fillAttribute(firstFocus(), theFocusX, theFocusY);
96 fillAttribute(theMinorRadius, myminorRadius);
101 void SketchAPI_Ellipse::setByCenterFocusAndRadius(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
102 const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
103 double theMinorRadius)
105 fillAttribute(theCenter, mycenter);
106 fillAttribute(theFocus, myfirstFocus);
107 fillAttribute(theMinorRadius, myminorRadius);
112 void SketchAPI_Ellipse::setByExternal(const ModelHighAPI_Selection & theExternal)
114 fillAttribute(theExternal, external());
118 void SketchAPI_Ellipse::setByExternalName(const std::wstring & theExternalName)
120 fillAttribute(ModelHighAPI_Selection("EDGE", theExternalName), external());
124 void SketchAPI_Ellipse::setCenter(double theX, double theY)
126 fillAttribute(center(), theX, theY);
130 void SketchAPI_Ellipse::setCenter(const std::shared_ptr<GeomAPI_Pnt2d> & theCenter)
132 fillAttribute(theCenter, mycenter);
136 void SketchAPI_Ellipse::setFocus(double theX, double theY)
138 fillAttribute(firstFocus(), theX, theY);
142 void SketchAPI_Ellipse::setFocus(const std::shared_ptr<GeomAPI_Pnt2d> & theFocus)
144 fillAttribute(theFocus, myfirstFocus);
148 void SketchAPI_Ellipse::setMinorRadius(double theMinorRadius)
150 fillAttribute(theMinorRadius, myminorRadius);
154 static const std::list<PairOfStrings>& ellipseAttrAndDumpNames()
156 static std::list<PairOfStrings> anAttributes;
157 if (anAttributes.empty()) {
158 anAttributes.push_back(
159 PairOfStrings(SketchPlugin_Ellipse::CENTER_ID(), "center"));
160 anAttributes.push_back(
161 PairOfStrings(SketchPlugin_Ellipse::FIRST_FOCUS_ID(), "firstFocus"));
162 anAttributes.push_back(
163 PairOfStrings(SketchPlugin_Ellipse::SECOND_FOCUS_ID(), "secondFocus"));
164 anAttributes.push_back(
165 PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(), "majorAxisStart"));
166 anAttributes.push_back(
167 PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), "majorAxisEnd"));
168 anAttributes.push_back(
169 PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(), "minorAxisStart"));
170 anAttributes.push_back(
171 PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), "minorAxisEnd"));
176 static CompositeFeaturePtr sketchForFeature(FeaturePtr theFeature)
178 const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
179 for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt)
180 if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID())
181 return std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
182 return CompositeFeaturePtr();
185 static void createInternalConstraint(const CompositeFeaturePtr& theSketch,
186 const AttributePoint2DPtr& thePoint1,
187 const AttributePoint2DPtr& thePoint2)
189 FeaturePtr aConstraint = theSketch->addFeature(SketchPlugin_ConstraintCoincidenceInternal::ID());
190 aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(thePoint1);
191 aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(thePoint2);
192 aConstraint->execute();
195 static void createPoint(const CompositeFeaturePtr& theSketch,
196 const FeaturePtr& theEllipse,
197 const std::string& theCoincident,
198 const std::wstring& theAuxOrName,
199 std::list<FeaturePtr>& theEntities)
201 if (theAuxOrName.empty())
204 AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
205 theEllipse->attribute(theCoincident));
207 FeaturePtr aPointFeature = theSketch->addFeature(SketchPlugin_Point::ID());
208 AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
209 aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
210 aCoord->setValue(anElPoint->x(), anElPoint->y());
211 aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
212 aPointFeature->execute();
214 std::wstring aName = theEllipse->name() + L"_" + Locale::Convert::toWString(theCoincident);
215 aPointFeature->data()->setName(aName);
216 aPointFeature->lastResult()->data()->setName(aName);
218 if (theAuxOrName == AUXILIARY_VALUE)
219 aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
220 else if (!theAuxOrName.empty()) {
221 aPointFeature->data()->setName(theAuxOrName);
222 aPointFeature->lastResult()->data()->setName(theAuxOrName);
225 createInternalConstraint(theSketch, anElPoint, aCoord);
227 theEntities.push_back(aPointFeature);
230 static void createAxis(const CompositeFeaturePtr& theSketch,
231 const FeaturePtr& theEllipse,
232 const std::string& theCoincidentStart,
233 const std::string& theCoincidentEnd,
234 const std::wstring& theAuxOrName,
235 std::list<FeaturePtr>& theEntities)
237 if (theAuxOrName.empty())
240 AttributePoint2DPtr aStartPoint =
241 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentStart));
242 AttributePoint2DPtr aEndPoint =
243 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentEnd));
245 FeaturePtr aLineFeature = theSketch->addFeature(SketchPlugin_Line::ID());
246 AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
247 aLineFeature->attribute(SketchPlugin_Line::START_ID()));
248 aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
249 AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
250 aLineFeature->attribute(SketchPlugin_Line::END_ID()));
251 aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
252 aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
253 aLineFeature->execute();
255 std::wstring aName = theEllipse->name() + L"_" +
256 (theCoincidentStart == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ?
257 L"major_axis" : L"minor_axis");
258 aLineFeature->data()->setName(aName);
259 aLineFeature->lastResult()->data()->setName(aName);
261 if (theAuxOrName == AUXILIARY_VALUE)
262 aLineFeature->boolean(SketchPlugin_Line::AUXILIARY_ID())->setValue(true);
263 else if (!theAuxOrName.empty()) {
264 aLineFeature->data()->setName(theAuxOrName);
265 aLineFeature->lastResult()->data()->setName(theAuxOrName);
268 createInternalConstraint(theSketch, aStartPoint, aLineStart);
269 createInternalConstraint(theSketch, aEndPoint, aLineEnd);
271 theEntities.push_back(aLineFeature);
274 std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::construction(
275 const std::wstring& center,
276 const std::wstring& firstFocus,
277 const std::wstring& secondFocus,
278 const std::wstring& majorAxisStart,
279 const std::wstring& majorAxisEnd,
280 const std::wstring& minorAxisStart,
281 const std::wstring& minorAxisEnd,
282 const std::wstring& majorAxis,
283 const std::wstring& minorAxis) const
285 FeaturePtr anEllipse = feature();
287 std::list<PairOfStrings> anAttributes = ellipseAttrAndDumpNames();
288 // append start and end attributes for axes
289 anAttributes.push_back(PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
290 SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()));
291 anAttributes.push_back(PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
292 SketchPlugin_Ellipse::MINOR_AXIS_END_ID()));
294 return buildConstructionEntities(anEllipse, anAttributes, center, firstFocus, secondFocus,
295 majorAxisStart, majorAxisEnd, minorAxisStart, minorAxisEnd, majorAxis, minorAxis);
298 std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::buildConstructionEntities(
299 const FeaturePtr& theEllipse,
300 const std::list<PairOfStrings>& theAttributes,
301 const std::wstring& theCenter,
302 const std::wstring& theFirstFocus,
303 const std::wstring& theSecondFocus,
304 const std::wstring& theMajorAxisStart,
305 const std::wstring& theMajorAxisEnd,
306 const std::wstring& theMinorAxisStart,
307 const std::wstring& theMinorAxisEnd,
308 const std::wstring& theMajorAxis,
309 const std::wstring& theMinorAxis)
311 CompositeFeaturePtr aSketch = sketchForFeature(theEllipse);
313 std::list<FeaturePtr> anEntities;
314 std::list<PairOfStrings>::const_iterator anAttrIt = theAttributes.begin();
315 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theCenter, anEntities);
316 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theFirstFocus, anEntities);
317 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theSecondFocus, anEntities);
318 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMajorAxisStart, anEntities);
319 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMajorAxisEnd, anEntities);
320 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMinorAxisStart, anEntities);
321 createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMinorAxisEnd, anEntities);
323 createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMajorAxis, anEntities);
325 createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMinorAxis, anEntities);
327 return SketchAPI_SketchEntity::wrap(anEntities);
330 static void ellipseAttributeAndAuxiliaryFeature(
331 const FeaturePtr& theInternalConstraint,
332 const std::pair<std::string, std::string>& theMajorAxisStartEnd,
333 const std::pair<std::string, std::string>& theMinorAxisStartEnd,
334 std::map<std::string, FeaturePtr>& theAttrToFeature)
336 AttributeRefAttrPtr aRefAttrA =
337 theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
338 AttributeRefAttrPtr aRefAttrB =
339 theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
340 // the first point is usually an ellipse attribute
341 // and the second point is an attribute of the auxiliary feature
342 ObjectPtr anAuxObject;
343 if (aRefAttrB->isObject())
344 anAuxObject = aRefAttrB->object();
346 anAuxObject = aRefAttrB->attr()->owner();
348 FeaturePtr anAuxFeature = ModelAPI_Feature::feature(anAuxObject);
349 if (anAuxFeature->getKind() == SketchPlugin_Point::ID())
350 theAttrToFeature[aRefAttrA->attr()->id()] = anAuxFeature;
352 const std::string& anAttrID = aRefAttrA->attr()->id();
353 if (anAttrID == theMajorAxisStartEnd.first || anAttrID == theMajorAxisStartEnd.second)
354 theAttrToFeature[MAJOR_AXIS_ID] = anAuxFeature;
355 else if (anAttrID == theMinorAxisStartEnd.first || anAttrID == theMinorAxisStartEnd.second)
356 theAttrToFeature[MINOR_AXIS_ID] = anAuxFeature;
360 void SketchAPI_Ellipse::collectAuxiliaryFeatures(
361 FeaturePtr theEllipse,
362 const std::pair<std::string, std::string>& theMajorAxis,
363 const std::pair<std::string, std::string>& theMinorAxis,
364 std::map<std::string, FeaturePtr>& theAttrToFeature)
366 const std::set<AttributePtr>& aRefs = theEllipse->data()->refsToMe();
367 for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
368 aRefIt != aRefs.end(); ++aRefIt) {
369 FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
370 if (anOwner->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
371 // process internal constraints only
372 ellipseAttributeAndAuxiliaryFeature(anOwner, theMajorAxis, theMinorAxis, theAttrToFeature);
377 void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const
380 return; // no need to dump copied feature
382 FeaturePtr aBase = feature();
383 const std::string& aSketchName = theDumper.parentName(aBase);
385 AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
386 if (anExternal->context()) {
387 // circle is external
388 theDumper << aBase << " = " << aSketchName << ".addEllipse(" << anExternal << ")" << std::endl;
390 // ellipse given by center, focus and radius
391 theDumper << aBase << " = " << aSketchName << ".addEllipse("
392 << center() << ", " << firstFocus() << ", " << minorRadius() << ")" << std::endl;
394 // dump "auxiliary" flag if necessary
395 SketchAPI_SketchEntity::dump(theDumper);
397 // dump auxiliary features produced by ellipse
398 std::map<std::string, FeaturePtr> anAuxFeatures;
399 static const std::pair<std::string, std::string> aMajorAxis(
400 SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
401 SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
402 static const std::pair<std::string, std::string> aMinorAxis(
403 SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
404 SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
405 collectAuxiliaryFeatures(aBase, aMajorAxis, aMinorAxis, anAuxFeatures);
407 if (!anAuxFeatures.empty()) {
408 // a list of attributes to write features in special order
409 const std::list<PairOfStrings>& anAttributes = ellipseAttrAndDumpNames();
410 dumpConstructionEntities(theDumper, aBase, anAttributes, anAuxFeatures);
414 void SketchAPI_Ellipse::dumpConstructionEntities(
415 ModelHighAPI_Dumper& theDumper,
416 const FeaturePtr& theEllipse,
417 const std::list<PairOfStrings>& theAttributes,
418 const std::map<std::string, FeaturePtr>& theAuxFeatures)
420 std::list<PairOfStrings> anAttributes = theAttributes;
422 anAttributes.push_back(PairOfStrings(MAJOR_AXIS_ID, MAJOR_AXIS_ID));
423 anAttributes.push_back(PairOfStrings(MINOR_AXIS_ID, MINOR_AXIS_ID));
427 for (std::list<PairOfStrings>::iterator anIt = anAttributes.begin();
428 anIt != anAttributes.end(); ++anIt) {
429 std::map<std::string, FeaturePtr>::const_iterator aFound = theAuxFeatures.find(anIt->first);
430 if (aFound == theAuxFeatures.end())
434 theDumper << theDumper.name(aFound->second, false);
435 theDumper.doNotDumpFeature(aFound->second);
438 theDumper << "] = " << theDumper.name(theEllipse) << ".construction(";
440 for (std::list<PairOfStrings>::iterator anIt = anAttributes.begin();
441 anIt != anAttributes.end(); ++anIt) {
442 std::map<std::string, FeaturePtr>::const_iterator aFound = theAuxFeatures.find(anIt->first);
443 if (aFound == theAuxFeatures.end())
448 theDumper << anIt->second << " = \"";
449 if (aFound->second->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value())
450 theDumper << AUXILIARY_VALUE;
452 theDumper << aFound->second->name();
455 theDumper << ")" << std::endl;