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 <ModelAPI_Tools.h>
30 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
31 #include <SketchPlugin_Line.h>
32 #include <SketchPlugin_Point.h>
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";
38 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature> & theFeature)
39 : SketchAPI_SketchEntity(theFeature)
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)
51 setByCenterFocusAndRadius(theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius);
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)
62 setByCenterFocusAndRadius(theCenter, theFocus, theMinorRadius);
66 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
67 const ModelHighAPI_Selection& theExternal)
68 : SketchAPI_SketchEntity(theFeature)
71 setByExternal(theExternal);
75 SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
76 const std::wstring& theExternalName)
77 : SketchAPI_SketchEntity(theFeature)
80 setByExternalName(theExternalName);
84 SketchAPI_Ellipse::~SketchAPI_Ellipse()
88 void SketchAPI_Ellipse::setByCenterFocusAndRadius(double theCenterX, double theCenterY,
89 double theFocusX, double theFocusY,
90 double theMinorRadius)
92 fillAttribute(center(), theCenterX, theCenterY);
93 fillAttribute(firstFocus(), theFocusX, theFocusY);
94 fillAttribute(theMinorRadius, myminorRadius);
99 void SketchAPI_Ellipse::setByCenterFocusAndRadius(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
100 const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
101 double theMinorRadius)
103 fillAttribute(theCenter, mycenter);
104 fillAttribute(theFocus, myfirstFocus);
105 fillAttribute(theMinorRadius, myminorRadius);
110 void SketchAPI_Ellipse::setByExternal(const ModelHighAPI_Selection & theExternal)
112 fillAttribute(theExternal, external());
116 void SketchAPI_Ellipse::setByExternalName(const std::wstring & theExternalName)
118 fillAttribute(ModelHighAPI_Selection("EDGE", theExternalName), external());
122 void SketchAPI_Ellipse::setCenter(double theX, double theY)
124 fillAttribute(center(), theX, theY);
128 void SketchAPI_Ellipse::setCenter(const std::shared_ptr<GeomAPI_Pnt2d> & theCenter)
130 fillAttribute(theCenter, mycenter);
134 void SketchAPI_Ellipse::setFocus(double theX, double theY)
136 fillAttribute(firstFocus(), theX, theY);
140 void SketchAPI_Ellipse::setFocus(const std::shared_ptr<GeomAPI_Pnt2d> & theFocus)
142 fillAttribute(theFocus, myfirstFocus);
146 void SketchAPI_Ellipse::setMinorRadius(double theMinorRadius)
148 fillAttribute(theMinorRadius, myminorRadius);
152 static const std::list<PairOfStrings>& ellipseAttrAndDumpNames()
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"));
174 static CompositeFeaturePtr sketchForFeature(FeaturePtr theFeature)
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();
183 static void createInternalConstraint(const CompositeFeaturePtr& theSketch,
184 const AttributePoint2DPtr& thePoint1,
185 const AttributePoint2DPtr& thePoint2)
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();
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)
199 if (theAuxOrName.empty())
202 AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
203 theEllipse->attribute(theCoincident));
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();
212 std::wstring aName = theEllipse->name() + L"_" + ModelAPI_Tools::toWString(theCoincident);
213 aPointFeature->data()->setName(aName);
214 aPointFeature->lastResult()->data()->setName(aName);
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);
223 createInternalConstraint(theSketch, anElPoint, aCoord);
225 theEntities.push_back(aPointFeature);
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)
235 if (theAuxOrName.empty())
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));
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();
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);
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);
266 createInternalConstraint(theSketch, aStartPoint, aLineStart);
267 createInternalConstraint(theSketch, aEndPoint, aLineEnd);
269 theEntities.push_back(aLineFeature);
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
283 FeaturePtr anEllipse = feature();
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()));
292 return buildConstructionEntities(anEllipse, anAttributes, center, firstFocus, secondFocus,
293 majorAxisStart, majorAxisEnd, minorAxisStart, minorAxisEnd, majorAxis, minorAxis);
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)
309 CompositeFeaturePtr aSketch = sketchForFeature(theEllipse);
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);
321 createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMajorAxis, anEntities);
323 createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMinorAxis, anEntities);
325 return SketchAPI_SketchEntity::wrap(anEntities);
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)
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();
344 anAuxObject = aRefAttrB->attr()->owner();
346 FeaturePtr anAuxFeature = ModelAPI_Feature::feature(anAuxObject);
347 if (anAuxFeature->getKind() == SketchPlugin_Point::ID())
348 theAttrToFeature[aRefAttrA->attr()->id()] = anAuxFeature;
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;
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)
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);
375 void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const
378 return; // no need to dump copied feature
380 FeaturePtr aBase = feature();
381 const std::string& aSketchName = theDumper.parentName(aBase);
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;
388 // ellipse given by center, focus and radius
389 theDumper << aBase << " = " << aSketchName << ".addEllipse("
390 << center() << ", " << firstFocus() << ", " << minorRadius() << ")" << std::endl;
392 // dump "auxiliary" flag if necessary
393 SketchAPI_SketchEntity::dump(theDumper);
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);
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);
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)
418 std::list<PairOfStrings> anAttributes = theAttributes;
420 anAttributes.push_back(PairOfStrings(MAJOR_AXIS_ID, MAJOR_AXIS_ID));
421 anAttributes.push_back(PairOfStrings(MINOR_AXIS_ID, MINOR_AXIS_ID));
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())
432 theDumper << theDumper.name(aFound->second, false);
433 theDumper.doNotDumpFeature(aFound->second);
436 theDumper << "] = " << theDumper.name(theEllipse) << ".construction(";
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())
446 theDumper << anIt->second << " = \"";
447 if (aFound->second->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value())
448 theDumper << AUXILIARY_VALUE;
450 theDumper << aFound->second->name();
453 theDumper << ")" << std::endl;