Salome HOME
Merge remote-tracking branch 'remotes/origin/master' into CEA_2019
[modules/shaper.git] / src / SketchAPI / SketchAPI_Sketch.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_Sketch.h"
21 //--------------------------------------------------------------------------------------
22 #include <SketchPlugin_Constraint.h>
23 #include <SketchPlugin_ConstraintAngle.h>
24 #include <SketchPlugin_ConstraintCoincidence.h>
25 #include <SketchPlugin_ConstraintCollinear.h>
26 #include <SketchPlugin_ConstraintDistance.h>
27 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
28 #include <SketchPlugin_ConstraintDistanceVertical.h>
29 #include <SketchPlugin_ConstraintEqual.h>
30 #include <SketchPlugin_Fillet.h>
31 #include <SketchPlugin_ConstraintHorizontal.h>
32 #include <SketchPlugin_ConstraintLength.h>
33 #include <SketchPlugin_ConstraintMiddle.h>
34 #include <SketchPlugin_ConstraintMirror.h>
35 #include <SketchPlugin_ConstraintParallel.h>
36 #include <SketchPlugin_ConstraintPerpendicular.h>
37 #include <SketchPlugin_ConstraintRadius.h>
38 #include <SketchPlugin_ConstraintRigid.h>
39 #include <SketchPlugin_Trim.h>
40 #include <SketchPlugin_Split.h>
41 #include <SketchPlugin_ConstraintTangent.h>
42 #include <SketchPlugin_ConstraintVertical.h>
43 #include <SketcherPrs_Tools.h>
44 //--------------------------------------------------------------------------------------
45 #include <ModelAPI_Events.h>
46 #include <ModelAPI_CompositeFeature.h>
47 #include <ModelAPI_ResultConstruction.h>
48 #include <ModelHighAPI_Double.h>
49 #include <ModelHighAPI_Dumper.h>
50 #include <ModelHighAPI_RefAttr.h>
51 #include <ModelHighAPI_Selection.h>
52 #include <ModelHighAPI_Services.h>
53 #include <ModelHighAPI_Tools.h>
54 //--------------------------------------------------------------------------------------
55 #include "SketchAPI_Arc.h"
56 #include "SketchAPI_MacroArc.h"
57 #include "SketchAPI_Circle.h"
58 #include "SketchAPI_IntersectionPoint.h"
59 #include "SketchAPI_Line.h"
60 #include "SketchAPI_MacroCircle.h"
61 #include "SketchAPI_Mirror.h"
62 #include "SketchAPI_Point.h"
63 #include "SketchAPI_Projection.h"
64 #include "SketchAPI_Rectangle.h"
65 #include "SketchAPI_Rotation.h"
66 #include "SketchAPI_Translation.h"
67 //--------------------------------------------------------------------------------------
68 #include <GeomAPI_Curve.h>
69 #include <GeomAPI_Dir2d.h>
70 #include <GeomAPI_PlanarEdges.h>
71 #include <GeomAPI_ShapeExplorer.h>
72 #include <GeomAPI_XY.h>
73 #include <GeomAlgoAPI_SketchBuilder.h>
74 #include <cmath>
75 //--------------------------------------------------------------------------------------
76 SketchAPI_Sketch::SketchAPI_Sketch(
77     const std::shared_ptr<ModelAPI_Feature> & theFeature)
78 : ModelHighAPI_Interface(theFeature)
79 {
80   initialize();
81 }
82
83 SketchAPI_Sketch::SketchAPI_Sketch(
84     const std::shared_ptr<ModelAPI_Feature> & theFeature,
85     const std::shared_ptr<GeomAPI_Ax3> & thePlane)
86 : ModelHighAPI_Interface(theFeature)
87 {
88   if (initialize()) {
89     setPlane(thePlane);
90   }
91 }
92
93 SketchAPI_Sketch::SketchAPI_Sketch(
94     const std::shared_ptr<ModelAPI_Feature> & theFeature,
95     const ModelHighAPI_Selection & theExternal)
96 : ModelHighAPI_Interface(theFeature)
97 {
98   if (initialize()) {
99     setExternal(theExternal);
100   }
101 }
102
103 SketchAPI_Sketch::SketchAPI_Sketch(
104     const std::shared_ptr<ModelAPI_Feature> & theFeature,
105     std::shared_ptr<ModelAPI_Object> thePlaneObject)
106 : ModelHighAPI_Interface(theFeature)
107 {
108   if (initialize()) {
109     setExternal(thePlaneObject);
110   }
111 }
112
113 SketchAPI_Sketch::~SketchAPI_Sketch()
114 {
115
116 }
117
118 //--------------------------------------------------------------------------------------
119 std::shared_ptr<ModelAPI_CompositeFeature> SketchAPI_Sketch::compositeFeature() const
120 {
121   return std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(feature());
122 }
123
124 //--------------------------------------------------------------------------------------
125 void SketchAPI_Sketch::setPlane(const std::shared_ptr<GeomAPI_Ax3> & thePlane)
126 {
127   fillAttribute(thePlane->origin(), myorigin);
128   fillAttribute(thePlane->dirX(), mydirX);
129   fillAttribute(thePlane->normal(), mynormal);
130
131   execute();
132 }
133
134 void SketchAPI_Sketch::setPlane(const ModelHighAPI_Selection & thePlane,
135                                 bool theRemoveExternalDependency)
136 {
137   FeaturePtr aSketch = feature();
138
139   DocumentPtr aDoc = aSketch->document();
140   bool useVisible = false;
141   FeaturePtr aCurFeatureBefore = aDoc->currentFeature(useVisible);
142   aDoc->setCurrentFeature(aSketch, useVisible);
143
144   if (theRemoveExternalDependency)
145     aSketch->customAction(SketchPlugin_Sketch::ACTION_REMOVE_EXTERNAL());
146
147   setExternal(thePlane);
148
149   aDoc->setCurrentFeature(aCurFeatureBefore, useVisible);
150 }
151
152 //--------------------------------------------------------------------------------------
153 void SketchAPI_Sketch::setExternal(const ModelHighAPI_Selection & theExternal)
154 {
155   fillAttribute(theExternal, myexternal);
156
157   execute();
158 }
159
160 void SketchAPI_Sketch::setExternal(std::shared_ptr<ModelAPI_Object> thePlaneObject)
161 {
162   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(thePlaneObject);
163   ModelHighAPI_Selection aSel(aRes);
164   setExternal(aSel);
165 }
166
167 //--------------------------------------------------------------------------------------
168 void SketchAPI_Sketch::setValue(
169     const std::shared_ptr<ModelHighAPI_Interface> & theConstraint,
170     const ModelHighAPI_Double & theValue)
171 {
172   fillAttribute(theValue, theConstraint->feature()->real(SketchPlugin_Constraint::VALUE()));
173
174 //  theConstraint->execute();
175 }
176
177 //--------------------------------------------------------------------------------------
178 std::list<ModelHighAPI_Selection> SketchAPI_Sketch::selectFace() const
179 {
180   const_cast<SketchAPI_Sketch*>(this)->execute();
181
182   std::list<ModelHighAPI_Selection> aSelectionList;
183
184   ResultConstructionPtr aResultConstruction =
185       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->firstResult());
186   if (aResultConstruction.get() == NULL)
187     return aSelectionList;
188
189   for (int anIndex = 0; anIndex < aResultConstruction->facesNum(); ++anIndex) {
190     aSelectionList.push_back(
191         ModelHighAPI_Selection(aResultConstruction,
192                                aResultConstruction->face(anIndex)));
193   }
194
195   return aSelectionList;
196 }
197
198 //--------------------------------------------------------------------------------------
199 SketchPtr addSketch(const std::shared_ptr<ModelAPI_Document> & thePart,
200                     const std::shared_ptr<GeomAPI_Ax3> & thePlane)
201 {
202   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(SketchAPI_Sketch::ID());
203   return SketchPtr(new SketchAPI_Sketch(aFeature, thePlane));
204 }
205
206 SketchPtr addSketch(const std::shared_ptr<ModelAPI_Document> & thePart,
207                     const ModelHighAPI_Selection & theExternal)
208 {
209   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(SketchAPI_Sketch::ID());
210   return SketchPtr(new SketchAPI_Sketch(aFeature, theExternal));
211 }
212
213 SketchPtr addSketch(const std::shared_ptr<ModelAPI_Document> & thePart,
214                     const std::string & theExternalName)
215 {
216   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(SketchAPI_Sketch::ID());
217   return SketchPtr(
218     new SketchAPI_Sketch(aFeature, ModelHighAPI_Selection("FACE", theExternalName)));
219 }
220
221 SketchPtr addSketch(const std::shared_ptr<ModelAPI_Document> & thePart,
222                     std::shared_ptr<ModelAPI_Object> thePlaneObject)
223 {
224   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(SketchAPI_Sketch::ID());
225   return SketchPtr(new SketchAPI_Sketch(aFeature, thePlaneObject));
226 }
227
228
229 //--------------------------------------------------------------------------------------
230 std::list< std::shared_ptr<SketchAPI_Point> > SketchAPI_Sketch::getFreePoints()
231 {
232   std::list< std::shared_ptr<SketchAPI_Point> > aFreePoints;
233   std::list<ResultPtr> aPoints = SketcherPrs_Tools::getFreePoints(compositeFeature());
234   for (std::list<ResultPtr>::iterator anIt = aPoints.begin(); anIt != aPoints.end(); ++anIt) {
235     FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
236     PointPtr aPoint(new SketchAPI_Point(aFeature));
237     aFreePoints.push_back(aPoint);
238   }
239   return aFreePoints;
240 }
241
242 //--------------------------------------------------------------------------------------
243 static GeomCurvePtr untrimmedCurve(GeomShapePtr theShape)
244 {
245   GeomCurvePtr aCurve(new GeomAPI_Curve(theShape));
246   if (aCurve->isTrimmed())
247     aCurve = aCurve->basisCurve();
248   return aCurve;
249 }
250
251 void SketchAPI_Sketch::changeFacesOrder(
252     const std::list<std::list<ModelHighAPI_Selection> >& theFaces)
253 {
254   // collect faces of the sketch
255   ResultConstructionPtr aSketchResult =
256       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
257   if (!aSketchResult) {
258     // sketch is nested to a boolean operation, thus, it has no result yet.
259     feature()->execute();
260     aSketchResult =
261         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
262   }
263   std::list<GeomFacePtr> aFaces;
264   int aFacesNum = aSketchResult->facesNum();
265   for (int i = 0; i < aFacesNum; ++i)
266     aFaces.push_back(aSketchResult->face(i));
267   // find new faces order according to the given lists of edges
268   std::list<GeomFacePtr> aNewFacesOrder;
269   std::list<std::list<ModelHighAPI_Selection> >::const_iterator anIt = theFaces.begin();
270   for (; anIt != theFaces.end(); ++anIt) {
271     // find the appropriate face
272     std::list<GeomFacePtr>::iterator aFIt = aFaces.begin();
273     for (; aFIt != aFaces.end(); ++aFIt) {
274       std::list<ModelHighAPI_Selection>::const_iterator aEdgeIt = anIt->begin();
275       GeomAPI_ShapeExplorer aFExp(*aFIt, GeomAPI_Shape::EDGE);
276       for (; aEdgeIt != anIt->end() && aFExp.more(); ++aEdgeIt, aFExp.next()) {
277         ResultPtr aCurRes = aEdgeIt->resultSubShapePair().first;
278         if (!aCurRes)
279           break;
280         GeomCurvePtr aCurve1 = untrimmedCurve(aCurRes->shape());
281         GeomCurvePtr aCurve2 = untrimmedCurve(aFExp.current());
282         if (!aCurve1->isEqual(aCurve2))
283           break;
284       }
285
286       if (aEdgeIt == anIt->end() && !aFExp.more()) {
287         // face is found
288         aNewFacesOrder.push_back(*aFIt);
289         aFaces.erase(aFIt);
290         break;
291       }
292     }
293   }
294   // place the rest faces at the end of new faces list
295   if (!aFaces.empty())
296     aNewFacesOrder.insert(aNewFacesOrder.end(), aFaces.begin(), aFaces.end());
297   // update the result of the sketch with the new order of faces
298   aSketchResult->setFacesOrder(aNewFacesOrder);
299 }
300
301 //--------------------------------------------------------------------------------------
302 std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(
303     double theX, double theY)
304 {
305   std::shared_ptr<ModelAPI_Feature> aFeature =
306     compositeFeature()->addFeature(SketchPlugin_Point::ID());
307   return PointPtr(new SketchAPI_Point(aFeature, theX, theY));
308 }
309 std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(
310     const std::shared_ptr<GeomAPI_Pnt2d> & thePoint)
311 {
312   std::shared_ptr<ModelAPI_Feature> aFeature =
313     compositeFeature()->addFeature(SketchPlugin_Point::ID());
314   return PointPtr(new SketchAPI_Point(aFeature, thePoint));
315 }
316 std::shared_ptr<SketchAPI_Point>
317   SketchAPI_Sketch::addPoint(const ModelHighAPI_Selection & theExternal)
318 {
319   std::shared_ptr<ModelAPI_Feature> aFeature =
320     compositeFeature()->addFeature(SketchPlugin_Point::ID());
321   return PointPtr(new SketchAPI_Point(aFeature, theExternal));
322 }
323 std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(const std::string & theExternalName)
324 {
325   std::shared_ptr<ModelAPI_Feature> aFeature =
326     compositeFeature()->addFeature(SketchPlugin_Point::ID());
327   return PointPtr(new SketchAPI_Point(aFeature, theExternalName));
328 }
329
330 //--------------------------------------------------------------------------------------
331 std::shared_ptr<SketchAPI_IntersectionPoint> SketchAPI_Sketch::addIntersectionPoint(
332     const ModelHighAPI_Selection & theExternal,
333     bool theKeepResult)
334 {
335   std::shared_ptr<ModelAPI_Feature> aFeature =
336     compositeFeature()->addFeature(SketchPlugin_IntersectionPoint::ID());
337   IntersectionPointPtr anIntersection(new SketchAPI_IntersectionPoint(aFeature, theExternal));
338   anIntersection->setIncludeToResult(theKeepResult);
339   return anIntersection;
340 }
341 std::shared_ptr<SketchAPI_IntersectionPoint> SketchAPI_Sketch::addIntersectionPoint(
342     const std::string & theExternalName,
343     bool theKeepResult)
344 {
345   std::shared_ptr<ModelAPI_Feature> aFeature =
346     compositeFeature()->addFeature(SketchPlugin_IntersectionPoint::ID());
347   IntersectionPointPtr anIntersection(new SketchAPI_IntersectionPoint(aFeature, theExternalName));
348   anIntersection->setIncludeToResult(theKeepResult);
349   return anIntersection;
350 }
351
352 //--------------------------------------------------------------------------------------
353 std::shared_ptr<SketchAPI_Line> SketchAPI_Sketch::addLine(double theX1, double theY1,
354                                                           double theX2, double theY2)
355 {
356   std::shared_ptr<ModelAPI_Feature> aFeature =
357     compositeFeature()->addFeature(SketchPlugin_Line::ID());
358   return LinePtr(new SketchAPI_Line(aFeature, theX1, theY1, theX2, theY2));
359 }
360 std::shared_ptr<SketchAPI_Line> SketchAPI_Sketch::addLine(
361     const std::shared_ptr<GeomAPI_Pnt2d> & theStartPoint,
362     const std::shared_ptr<GeomAPI_Pnt2d> & theEndPoint)
363 {
364   std::shared_ptr<ModelAPI_Feature> aFeature =
365     compositeFeature()->addFeature(SketchPlugin_Line::ID());
366   return LinePtr(new SketchAPI_Line(aFeature, theStartPoint, theEndPoint));
367 }
368 std::shared_ptr<SketchAPI_Line>
369   SketchAPI_Sketch::addLine(const ModelHighAPI_Selection & theExternal)
370 {
371   std::shared_ptr<ModelAPI_Feature> aFeature =
372     compositeFeature()->addFeature(SketchPlugin_Line::ID());
373   return LinePtr(new SketchAPI_Line(aFeature, theExternal));
374 }
375 std::shared_ptr<SketchAPI_Line> SketchAPI_Sketch::addLine(const std::string & theExternalName)
376 {
377   std::shared_ptr<ModelAPI_Feature> aFeature =
378     compositeFeature()->addFeature(SketchPlugin_Line::ID());
379   return LinePtr(new SketchAPI_Line(aFeature, theExternalName));
380 }
381
382 //--------------------------------------------------------------------------------------
383 std::shared_ptr<SketchAPI_Rectangle> SketchAPI_Sketch::addRectangle(double theX1, double theY1,
384                                                                     double theX2, double theY2)
385 {
386   std::shared_ptr<ModelAPI_Feature> aFeature =
387     compositeFeature()->addFeature(SketchAPI_Rectangle::ID());
388   return RectanglePtr(new SketchAPI_Rectangle(aFeature, theX1, theY1, theX2, theY2));
389 }
390 std::shared_ptr<SketchAPI_Rectangle> SketchAPI_Sketch::addRectangle(
391     const std::shared_ptr<GeomAPI_Pnt2d> & theStartPoint,
392     const std::shared_ptr<GeomAPI_Pnt2d> & theEndPoint)
393 {
394   std::shared_ptr<ModelAPI_Feature> aFeature =
395     compositeFeature()->addFeature(SketchAPI_Rectangle::ID());
396   return RectanglePtr(new SketchAPI_Rectangle(aFeature, theStartPoint, theEndPoint));
397 }
398
399 //--------------------------------------------------------------------------------------
400 std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(double theCenterX,
401                                                               double theCenterY,
402                                                               double theRadius)
403 {
404   std::shared_ptr<ModelAPI_Feature> aFeature =
405     compositeFeature()->addFeature(SketchPlugin_Circle::ID());
406   return CirclePtr(new SketchAPI_Circle(aFeature, theCenterX, theCenterY, theRadius));
407 }
408
409 std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(
410                                     const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
411                                     double theRadius)
412 {
413   std::shared_ptr<ModelAPI_Feature> aFeature =
414     compositeFeature()->addFeature(SketchPlugin_Circle::ID());
415   return CirclePtr(new SketchAPI_Circle(aFeature, theCenter, theRadius));
416 }
417
418 std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(double theCenterX,
419                                                                    double theCenterY,
420                                                                    double thePassedX,
421                                                                    double thePassedY)
422 {
423   std::shared_ptr<ModelAPI_Feature> aFeature =
424     compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
425   return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterX, theCenterY,
426                                                             thePassedX, thePassedY));
427 }
428
429 std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(
430     const std::shared_ptr<GeomAPI_Pnt2d>& theCenterPoint,
431     const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint)
432 {
433   std::shared_ptr<ModelAPI_Feature> aFeature =
434     compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
435   return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterPoint, thePassedPoint));
436 }
437
438 std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(double theX1, double theY1,
439                                                                    double theX2, double theY2,
440                                                                    double theX3, double theY3)
441 {
442   std::shared_ptr<ModelAPI_Feature> aFeature =
443     compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
444   return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theX1, theY1,
445                                                             theX2, theY2,
446                                                             theX3, theY3));
447 }
448
449 std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(
450     const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
451     const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
452     const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3)
453 {
454   std::shared_ptr<ModelAPI_Feature> aFeature =
455     compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
456   return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, thePoint1, thePoint2, thePoint3));
457 }
458
459 std::shared_ptr<SketchAPI_Circle>
460   SketchAPI_Sketch::addCircle(const ModelHighAPI_Selection & theExternal)
461 {
462   std::shared_ptr<ModelAPI_Feature> aFeature =
463     compositeFeature()->addFeature(SketchPlugin_Circle::ID());
464   return CirclePtr(new SketchAPI_Circle(aFeature, theExternal));
465 }
466
467 std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(const std::string & theExternalName)
468 {
469   // TODO(spo): Add constraint SketchConstraintRigid like in PythonAPI. Is it necessary?
470   std::shared_ptr<ModelAPI_Feature> aFeature =
471     compositeFeature()->addFeature(SketchPlugin_Circle::ID());
472   return CirclePtr(new SketchAPI_Circle(aFeature, theExternalName));
473 }
474
475 //--------------------------------------------------------------------------------------
476 std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(double theCenterX, double theCenterY,
477                                                         double theStartX, double theStartY,
478                                                         double theEndX, double theEndY,
479                                                         bool theInversed)
480 {
481   std::shared_ptr<ModelAPI_Feature> aFeature =
482     compositeFeature()->addFeature(SketchPlugin_Arc::ID());
483   return ArcPtr(new SketchAPI_Arc(aFeature,
484                                   theCenterX, theCenterY,
485                                   theStartX, theStartY,
486                                   theEndX, theEndY,
487                                   theInversed));
488 }
489
490 std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(
491                                               const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
492                                               const std::shared_ptr<GeomAPI_Pnt2d>& theStart,
493                                               const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
494                                               bool theInversed)
495 {
496   std::shared_ptr<ModelAPI_Feature> aFeature =
497     compositeFeature()->addFeature(SketchPlugin_Arc::ID());
498   return ArcPtr(new SketchAPI_Arc(aFeature, theCenter, theStart, theEnd, theInversed));
499 }
500
501 std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(double theStartX, double theStartY,
502                                                         double theEndX, double theEndY,
503                                                         double thePassedX, double thePassedY)
504 {
505   std::shared_ptr<ModelAPI_Feature> aFeature =
506     compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
507   return MacroArcPtr(new SketchAPI_MacroArc(aFeature,
508                                        theStartX, theStartY,
509                                        theEndX, theEndY,
510                                        thePassedX, thePassedY));
511 }
512
513 std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
514                                                 const std::shared_ptr<GeomAPI_Pnt2d>& theStart,
515                                                 const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
516                                                 const std::shared_ptr<GeomAPI_Pnt2d>& thePassed)
517 {
518   std::shared_ptr<ModelAPI_Feature> aFeature =
519     compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
520   return MacroArcPtr(new SketchAPI_MacroArc(aFeature, theStart, theEnd, thePassed));
521 }
522
523 std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
524                                                 const ModelHighAPI_RefAttr& theTangentPoint,
525                                                 double theEndX, double theEndY,
526                                                 bool theInversed,
527                                                 bool theTransversal)
528 {
529   std::shared_ptr<ModelAPI_Feature> aFeature =
530     compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
531   MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
532   if (theTransversal)
533     aMacroArc->setByTransversal(theTangentPoint, theEndX, theEndY, theInversed);
534   else
535     aMacroArc->setByTangent(theTangentPoint, theEndX, theEndY, theInversed);
536   return aMacroArc;
537 }
538
539 std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
540                                               const ModelHighAPI_RefAttr& theTangentPoint,
541                                               const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
542                                               bool theInversed,
543                                               bool theTransversal)
544 {
545   std::shared_ptr<ModelAPI_Feature> aFeature =
546     compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
547   MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
548   if (theTransversal)
549     aMacroArc->setByTransversal(theTangentPoint, theEnd, theInversed);
550   else
551     aMacroArc->setByTangent(theTangentPoint, theEnd, theInversed);
552   return aMacroArc;
553 }
554
555 std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const ModelHighAPI_Selection & theExternal)
556 {
557   std::shared_ptr<ModelAPI_Feature> aFeature =
558     compositeFeature()->addFeature(SketchPlugin_Arc::ID());
559   return ArcPtr(new SketchAPI_Arc(aFeature, theExternal));
560 }
561
562 std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const std::string & theExternalName)
563 {
564   // TODO(spo): Add constraint SketchConstraintRigid like in PythonAPI. Is it necessary?
565   std::shared_ptr<ModelAPI_Feature> aFeature =
566     compositeFeature()->addFeature(SketchPlugin_Arc::ID());
567   return ArcPtr(new SketchAPI_Arc(aFeature, theExternalName));
568 }
569
570 //--------------------------------------------------------------------------------------
571 std::shared_ptr<SketchAPI_Projection> SketchAPI_Sketch::addProjection(
572     const ModelHighAPI_Selection & theExternalFeature,
573     bool theKeepResult)
574 {
575   std::shared_ptr<ModelAPI_Feature> aFeature =
576     compositeFeature()->addFeature(SketchPlugin_Projection::ID());
577   ProjectionPtr aProjection(new SketchAPI_Projection(aFeature, theExternalFeature));
578   aProjection->setIncludeToResult(theKeepResult);
579   return aProjection;
580 }
581
582 std::shared_ptr<SketchAPI_Projection> SketchAPI_Sketch::addProjection(
583     const std::string & theExternalName,
584     bool theKeepResult)
585 {
586   std::shared_ptr<ModelAPI_Feature> aFeature =
587     compositeFeature()->addFeature(SketchPlugin_Projection::ID());
588   ProjectionPtr aProjection(new SketchAPI_Projection(aFeature, theExternalName));
589   aProjection->setIncludeToResult(theKeepResult);
590   return aProjection;
591 }
592
593 //--------------------------------------------------------------------------------------
594 std::shared_ptr<SketchAPI_Mirror> SketchAPI_Sketch::addMirror(
595     const ModelHighAPI_RefAttr & theMirrorLine,
596     const std::list<std::shared_ptr<ModelAPI_Object> > & theObjects)
597 {
598   std::shared_ptr<ModelAPI_Feature> aFeature =
599     compositeFeature()->addFeature(SketchPlugin_ConstraintMirror::ID());
600   return MirrorPtr(new SketchAPI_Mirror(aFeature, theMirrorLine, theObjects));
601 }
602
603 //--------------------------------------------------------------------------------------
604 std::shared_ptr<SketchAPI_Translation> SketchAPI_Sketch::addTranslation(
605     const std::list<std::shared_ptr<ModelAPI_Object> > & theObjects,
606     const ModelHighAPI_RefAttr & thePoint1,
607     const ModelHighAPI_RefAttr & thePoint2,
608     const ModelHighAPI_Integer & theNumberOfObjects,
609     bool theFullValue)
610 {
611   std::shared_ptr<ModelAPI_Feature> aFeature =
612     compositeFeature()->addFeature(SketchPlugin_MultiTranslation::ID());
613   return TranslationPtr(new SketchAPI_Translation(aFeature, theObjects, thePoint1,
614                                                   thePoint2, theNumberOfObjects, theFullValue));
615 }
616
617 //--------------------------------------------------------------------------------------
618 std::shared_ptr<SketchAPI_Rotation> SketchAPI_Sketch::addRotation(
619     const std::list<std::shared_ptr<ModelAPI_Object> > & theObjects,
620     const ModelHighAPI_RefAttr & theCenter,
621     const ModelHighAPI_Double & theAngle,
622     const ModelHighAPI_Integer & theNumberOfObjects,
623     bool theFullValue,
624     bool theReversed)
625 {
626   std::shared_ptr<ModelAPI_Feature> aFeature =
627     compositeFeature()->addFeature(SketchPlugin_MultiRotation::ID());
628   return RotationPtr(
629     new SketchAPI_Rotation(aFeature, theObjects, theCenter,
630                            theAngle, theNumberOfObjects, theFullValue, theReversed));
631 }
632
633 //--------------------------------------------------------------------------------------
634 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::addSplit(
635                                           const ModelHighAPI_Reference& theFeature,
636                                           const std::shared_ptr<GeomAPI_Pnt2d>& thePositionPoint)
637 {
638   std::shared_ptr<ModelAPI_Feature> aFeature =
639     compositeFeature()->addFeature(SketchPlugin_Split::ID());
640   fillAttribute(theFeature, aFeature->reference(SketchPlugin_Split::SELECTED_OBJECT()));
641
642   AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Split::SELECTED_POINT());
643   if (anAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) {
644     AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
645     fillAttribute(thePositionPoint, aPointAttr);
646   }
647
648   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
649 }
650
651 //--------------------------------------------------------------------------------------
652 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::addTrim(
653                                         const ModelHighAPI_Reference& theFeature,
654                                         const std::shared_ptr<GeomAPI_Pnt2d>& thePositionPoint)
655 {
656   std::shared_ptr<ModelAPI_Feature> aFeature =
657     compositeFeature()->addFeature(SketchPlugin_Trim::ID());
658   fillAttribute(theFeature, aFeature->reference(SketchPlugin_Trim::SELECTED_OBJECT()));
659
660   AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Trim::SELECTED_POINT());
661   if (anAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) {
662     AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
663     fillAttribute(thePositionPoint, aPointAttr);
664   }
665
666   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
667 }
668
669 //--------------------------------------------------------------------------------------
670 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setAngle(
671     const ModelHighAPI_RefAttr & theLine1,
672     const ModelHighAPI_RefAttr & theLine2,
673     const ModelHighAPI_Double & theValue)
674 {
675   std::shared_ptr<ModelAPI_Feature> aFeature =
676       compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID());
677   fillAttribute(SketcherPrs_Tools::ANGLE_DIRECT,
678       aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID()));
679   // fill the value before llines to avoid calculation of angle value by the Angle feature
680   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
681   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
682   fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
683   aFeature->execute();
684   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
685 }
686
687 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setAngleComplementary(
688     const ModelHighAPI_RefAttr & theLine1,
689     const ModelHighAPI_RefAttr & theLine2,
690     const ModelHighAPI_Double & theValue)
691 {
692   std::shared_ptr<ModelAPI_Feature> aFeature =
693       compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID());
694   fillAttribute(SketcherPrs_Tools::ANGLE_COMPLEMENTARY,
695       aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID()));
696   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
697   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
698   fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
699   aFeature->execute();
700   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
701 }
702
703 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setAngleBackward(
704     const ModelHighAPI_RefAttr & theLine1,
705     const ModelHighAPI_RefAttr & theLine2,
706     const ModelHighAPI_Double & theValue)
707 {
708   std::shared_ptr<ModelAPI_Feature> aFeature =
709       compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID());
710   fillAttribute(SketcherPrs_Tools::ANGLE_BACKWARD,
711       aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID()));
712   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
713   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
714   fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
715   aFeature->execute();
716   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
717 }
718
719 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setCoincident(
720     const ModelHighAPI_RefAttr & thePoint1,
721     const ModelHighAPI_RefAttr & thePoint2)
722 {
723   std::shared_ptr<ModelAPI_Feature> aFeature =
724       compositeFeature()->addFeature(SketchPlugin_ConstraintCoincidence::ID());
725   fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
726   fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
727   aFeature->execute();
728   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
729 }
730
731 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setCollinear(
732     const ModelHighAPI_RefAttr & theLine1,
733     const ModelHighAPI_RefAttr & theLine2)
734 {
735   std::shared_ptr<ModelAPI_Feature> aFeature =
736       compositeFeature()->addFeature(SketchPlugin_ConstraintCollinear::ID());
737   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
738   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
739   aFeature->execute();
740   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
741 }
742
743 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setDistance(
744     const ModelHighAPI_RefAttr & thePoint,
745     const ModelHighAPI_RefAttr & thePointOrLine,
746     const ModelHighAPI_Double & theValue,
747     bool isSigned)
748 {
749   std::shared_ptr<ModelAPI_Feature> aFeature =
750       compositeFeature()->addFeature(SketchPlugin_ConstraintDistance::ID());
751   fillAttribute(thePoint, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
752   fillAttribute(thePointOrLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
753   fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
754   fillAttribute(isSigned, aFeature->boolean(SketchPlugin_ConstraintDistance::SIGNED()));
755   aFeature->execute();
756   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
757 }
758
759 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setSignedDistance(
760     const ModelHighAPI_RefAttr & thePoint,
761     const ModelHighAPI_RefAttr & thePointOrLine,
762     const ModelHighAPI_Double & theValue)
763 {
764   return setDistance(thePoint, thePointOrLine, theValue, true);
765 }
766
767 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setUnsignedDistance(
768     const ModelHighAPI_RefAttr & thePoint,
769     const ModelHighAPI_RefAttr & thePointOrLine,
770     const ModelHighAPI_Double & theValue)
771 {
772   return setDistance(thePoint, thePointOrLine, theValue, false);
773 }
774
775 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setHorizontalDistance(
776     const ModelHighAPI_RefAttr & thePoint1,
777     const ModelHighAPI_RefAttr & thePoint2,
778     const ModelHighAPI_Double & theValue)
779 {
780   std::shared_ptr<ModelAPI_Feature> aFeature =
781       compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceHorizontal::ID());
782   fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
783   fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
784   fillAttribute(theValue,
785       aFeature->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()));
786   aFeature->execute();
787   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
788 }
789
790 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setVerticalDistance(
791     const ModelHighAPI_RefAttr & thePoint1,
792     const ModelHighAPI_RefAttr & thePoint2,
793     const ModelHighAPI_Double & theValue)
794 {
795   std::shared_ptr<ModelAPI_Feature> aFeature =
796       compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceVertical::ID());
797   fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
798   fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
799   fillAttribute(theValue,
800       aFeature->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()));
801   aFeature->execute();
802   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
803 }
804
805 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setEqual(
806     const ModelHighAPI_RefAttr & theObject1,
807     const ModelHighAPI_RefAttr & theObject2)
808 {
809   std::shared_ptr<ModelAPI_Feature> aFeature =
810       compositeFeature()->addFeature(SketchPlugin_ConstraintEqual::ID());
811   fillAttribute(theObject1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
812   fillAttribute(theObject2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
813   aFeature->execute();
814   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
815 }
816
817 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setFillet(
818     const ModelHighAPI_RefAttr & thePoint)
819 {
820   std::shared_ptr<ModelAPI_Feature> aFeature =
821       compositeFeature()->addFeature(SketchPlugin_Fillet::ID());
822   fillAttribute(thePoint, aFeature->data()->refattr(SketchPlugin_Fillet::FILLET_POINT_ID()));
823   apply(); // finish operation to remove Fillet feature correcly
824   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
825 }
826
827 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setFilletWithRadius(
828     const ModelHighAPI_RefAttr & thePoint,
829     const ModelHighAPI_Double & theRadius)
830 {
831   CompositeFeaturePtr aSketch = compositeFeature();
832   int aNbSubs = aSketch->numberOfSubs();
833
834   // create fillet
835   InterfacePtr aFilletFeature = setFillet(thePoint);
836
837   // set radius for just created arc
838   FeaturePtr anArc = aSketch->subFeature(aNbSubs - 1);
839   if (anArc->getKind() == SketchPlugin_Arc::ID())
840     setRadius(ModelHighAPI_RefAttr(ObjectPtr(anArc->lastResult())), ModelHighAPI_Double(theRadius));
841
842   return aFilletFeature;
843 }
844
845 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setFixed(
846     const ModelHighAPI_RefAttr & theObject)
847 {
848   std::shared_ptr<ModelAPI_Feature> aFeature =
849       compositeFeature()->addFeature(SketchPlugin_ConstraintRigid::ID());
850   fillAttribute(theObject, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
851   aFeature->execute();
852   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
853 }
854
855 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setHorizontal(
856     const ModelHighAPI_RefAttr & theLine)
857 {
858   std::shared_ptr<ModelAPI_Feature> aFeature =
859       compositeFeature()->addFeature(SketchPlugin_ConstraintHorizontal::ID());
860   fillAttribute(theLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
861   aFeature->execute();
862   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
863 }
864
865 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setLength(
866     const ModelHighAPI_RefAttr & theLine,
867     const ModelHighAPI_Double & theValue)
868 {
869   std::shared_ptr<ModelAPI_Feature> aFeature =
870       compositeFeature()->addFeature(SketchPlugin_ConstraintLength::ID());
871   fillAttribute(theLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
872   fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
873   aFeature->execute();
874   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
875 }
876
877 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setMiddlePoint(
878     const ModelHighAPI_RefAttr & thePoint,
879     const ModelHighAPI_RefAttr & theLine)
880 {
881   std::shared_ptr<ModelAPI_Feature> aFeature =
882       compositeFeature()->addFeature(SketchPlugin_ConstraintMiddle::ID());
883   fillAttribute(thePoint, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
884   fillAttribute(theLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
885   aFeature->execute();
886   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
887 }
888
889 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setParallel(
890     const ModelHighAPI_RefAttr & theLine1,
891     const ModelHighAPI_RefAttr & theLine2)
892 {
893   std::shared_ptr<ModelAPI_Feature> aFeature =
894       compositeFeature()->addFeature(SketchPlugin_ConstraintParallel::ID());
895   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
896   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
897   aFeature->execute();
898   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
899 }
900
901 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setPerpendicular(
902     const ModelHighAPI_RefAttr & theLine1,
903     const ModelHighAPI_RefAttr & theLine2)
904 {
905   std::shared_ptr<ModelAPI_Feature> aFeature =
906       compositeFeature()->addFeature(SketchPlugin_ConstraintPerpendicular::ID());
907   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
908   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
909   aFeature->execute();
910   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
911 }
912
913 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setRadius(
914     const ModelHighAPI_RefAttr & theCircleOrArc,
915     const ModelHighAPI_Double & theValue)
916 {
917   std::shared_ptr<ModelAPI_Feature> aFeature =
918       compositeFeature()->addFeature(SketchPlugin_ConstraintRadius::ID());
919   fillAttribute(theCircleOrArc, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
920   fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
921   aFeature->execute();
922   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
923 }
924
925 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setTangent(
926     const ModelHighAPI_RefAttr & theLine,
927     const ModelHighAPI_RefAttr & theCircle)
928 {
929   std::shared_ptr<ModelAPI_Feature> aFeature =
930       compositeFeature()->addFeature(SketchPlugin_ConstraintTangent::ID());
931   fillAttribute(theLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
932   fillAttribute(theCircle, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
933   aFeature->execute();
934   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
935 }
936
937 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setVertical(
938     const ModelHighAPI_RefAttr & theLine)
939 {
940   std::shared_ptr<ModelAPI_Feature> aFeature =
941       compositeFeature()->addFeature(SketchPlugin_ConstraintVertical::ID());
942   fillAttribute(theLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
943   aFeature->execute();
944   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
945 }
946
947 //--------------------------------------------------------------------------------------
948
949 static std::shared_ptr<GeomAPI_Pnt2d> pointCoordinates(const AttributePtr& thePoint)
950 {
951   AttributePoint2DPtr aPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint);
952   return aPnt ? aPnt->pnt() : std::shared_ptr<GeomAPI_Pnt2d>();
953 }
954
955 static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnLine(const FeaturePtr& theFeature)
956 {
957   AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
958       theFeature->attribute(SketchPlugin_Line::START_ID()));
959   AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
960       theFeature->attribute(SketchPlugin_Line::END_ID()));
961
962   if (!aStartAttr || !aEndAttr)
963     return std::shared_ptr<GeomAPI_Pnt2d>();
964
965   std::shared_ptr<GeomAPI_XY> aStartPoint = aStartAttr->pnt()->xy();
966   std::shared_ptr<GeomAPI_XY> aEndPoint = aEndAttr->pnt()->xy();
967   return std::shared_ptr<GeomAPI_Pnt2d>(
968       new GeomAPI_Pnt2d(aStartPoint->added(aEndPoint)->multiplied(0.5)));
969 }
970
971 static std::shared_ptr<GeomAPI_Pnt2d> pointOnCircle(const FeaturePtr& theFeature)
972 {
973   AttributePoint2DPtr aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
974       theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
975   AttributeDoublePtr aRadius = theFeature->real(SketchPlugin_Circle::RADIUS_ID());
976
977   if (!aCenter || !aRadius)
978     return std::shared_ptr<GeomAPI_Pnt2d>();
979
980   return std::shared_ptr<GeomAPI_Pnt2d>(
981       new GeomAPI_Pnt2d(aCenter->x() + aRadius->value(), aCenter->y()));
982 }
983
984 static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnArc(const FeaturePtr& theFeature)
985 {
986   static const double PI = 3.141592653589793238463;
987
988   AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
989       theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
990   AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
991       theFeature->attribute(SketchPlugin_Arc::START_ID()));
992   AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
993       theFeature->attribute(SketchPlugin_Arc::END_ID()));
994
995   if (!aCenterAttr || !aStartAttr || !aEndAttr)
996     return std::shared_ptr<GeomAPI_Pnt2d>();
997
998   std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
999       aStartAttr->x() - aCenterAttr->x(), aStartAttr->y() - aCenterAttr->y()));
1000   std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
1001       aEndAttr->x() - aCenterAttr->x(), aEndAttr->y() - aCenterAttr->y()));
1002
1003   double anAngle = aStartDir->angle(aEndDir);
1004   bool isReversed = theFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
1005   if (isReversed && anAngle > 0.)
1006     anAngle -= 2.0 * PI;
1007   else if (!isReversed && anAngle <= 0.)
1008     anAngle += 2.0 * PI;
1009
1010   double cosA = cos(anAngle);
1011   double sinA = sin(anAngle);
1012
1013   // rotate start dir to find middle point on arc
1014   double aRadius = aStartAttr->pnt()->distance(aCenterAttr->pnt());
1015   double x = aCenterAttr->x() + aRadius * (aStartDir->x() * cosA - aStartDir->y() * sinA);
1016   double y = aCenterAttr->y() + aRadius * (aStartDir->x() * sinA + aStartDir->y() * cosA);
1017
1018   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(x, y));
1019 }
1020
1021 static std::shared_ptr<GeomAPI_Pnt2d> middlePoint(const ObjectPtr& theObject)
1022 {
1023   std::shared_ptr<GeomAPI_Pnt2d> aMiddlePoint;
1024   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1025   if (aFeature) {
1026     // move only features of the following types
1027     const std::string& aFeatureKind = aFeature->getKind();
1028     if (aFeatureKind == SketchPlugin_Point::ID())
1029       aMiddlePoint = pointCoordinates(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
1030     else if (aFeatureKind == SketchPlugin_Line::ID())
1031       aMiddlePoint = middlePointOnLine(aFeature);
1032     else if (aFeatureKind == SketchPlugin_Circle::ID())
1033       aMiddlePoint = pointOnCircle(aFeature);
1034     else if (aFeatureKind == SketchPlugin_Arc::ID())
1035       aMiddlePoint = middlePointOnArc(aFeature);
1036   }
1037   return aMiddlePoint;
1038 }
1039
1040 void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
1041                             const std::shared_ptr<GeomAPI_Pnt2d>& theTargetPoint)
1042 {
1043   std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage(new ModelAPI_ObjectMovedMessage);
1044   theMovedEntity.fillMessage(aMessage);
1045
1046   std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition;
1047   if (aMessage->movedAttribute())
1048     anOriginalPosition = pointCoordinates(aMessage->movedAttribute());
1049   else
1050     anOriginalPosition = middlePoint(aMessage->movedObject());
1051
1052   if (!anOriginalPosition)
1053     return; // something has gone wrong, do not process movement
1054
1055   aMessage->setOriginalPosition(anOriginalPosition);
1056   aMessage->setCurrentPosition(theTargetPoint);
1057   Events_Loop::loop()->send(aMessage);
1058 }
1059
1060 void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
1061                             double theTargetX, double theTargetY)
1062 {
1063   std::shared_ptr<GeomAPI_Pnt2d> aTargetPoint(new GeomAPI_Pnt2d(theTargetX, theTargetY));
1064   move(theMovedEntity, aTargetPoint);
1065 }
1066
1067 //--------------------------------------------------------------------------------------
1068
1069 std::shared_ptr<GeomAPI_Pnt2d> SketchAPI_Sketch::to2D(const std::shared_ptr<GeomAPI_Pnt>& thePoint)
1070 {
1071   FeaturePtr aBase = feature();
1072   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1073       aBase->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
1074   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1075       aBase->attribute(SketchPlugin_Sketch::NORM_ID()));
1076   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1077       aBase->attribute(SketchPlugin_Sketch::DIRX_ID()));
1078   std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
1079
1080   return thePoint->to2D(aC->pnt(), aX->dir(), aY);
1081 }
1082
1083 //--------------------------------------------------------------------------------------
1084
1085 static bool isDifferent(GeomFacePtr theFace1, GeomFacePtr theFace2)
1086 {
1087   // collect edges of the first face
1088   std::list<GeomShapePtr> anEdges1;
1089   for (GeomAPI_ShapeExplorer anExp(theFace1, GeomAPI_Shape::EDGE); anExp.more(); anExp.next())
1090     anEdges1.push_back(anExp.current());
1091   // compare edges of faces
1092   for (GeomAPI_ShapeExplorer anExp(theFace2, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
1093     GeomShapePtr aCurrent = anExp.current();
1094     bool isFound = false;
1095     std::list<GeomShapePtr>::iterator anIt1 = anEdges1.begin();
1096     for (; anIt1 != anEdges1.end(); ++anIt1)
1097       if (aCurrent->isSameGeometry(*anIt1)) {
1098         isFound = true;
1099         anEdges1.erase(anIt1);
1100         break;
1101       }
1102     if (!isFound)
1103       return true;
1104   }
1105   return !anEdges1.empty();
1106 }
1107
1108 static bool isCustomFacesOrder(CompositeFeaturePtr theSketch)
1109 {
1110   ResultConstructionPtr aSketchResult =
1111       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
1112   if (!aSketchResult)
1113     return false;
1114
1115   std::shared_ptr<GeomAPI_PlanarEdges> aWires =
1116       std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aSketchResult->shape());
1117   if (!aWires)
1118     return false;
1119
1120   // collect faces constructed by SketchBuilder algorithm
1121   GeomAlgoAPI_SketchBuilder aSketchBuilder(aWires->origin(), aWires->dirX(),
1122                                            aWires->norm(), aWires);
1123   const ListOfShape& aFaces = aSketchBuilder.faces();
1124
1125   // compare faces stored in sketch with faces generated by SketchBuilder
1126   int aNbSketchFaces = aSketchResult->facesNum();
1127   int aFaceIndex = 0;
1128   for (ListOfShape::const_iterator aFIt = aFaces.begin();
1129        aFIt != aFaces.end() && aFaceIndex < aNbSketchFaces;
1130        ++aFIt, ++aFaceIndex) {
1131     GeomFacePtr aSketchFace = aSketchResult->face(aFaceIndex);
1132     GeomFacePtr aCurFace = (*aFIt)->face();
1133     if (isDifferent(aSketchFace, aCurFace))
1134       return true;
1135   }
1136   return false;
1137 }
1138
1139 static void edgesOfSketchFaces(CompositeFeaturePtr theSketch,
1140                                std::list<std::list<ResultPtr> >& theEdges)
1141 {
1142   ResultConstructionPtr aSketchResult =
1143       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
1144   if (!aSketchResult)
1145     return;
1146
1147   // collect curves of the sketch
1148   std::map<GeomCurvePtr, ResultPtr, GeomAPI_Curve::Comparator> aCurves;
1149   int aSubNum = theSketch->numberOfSubs();
1150   for (int a = 0; a < aSubNum; ++a) {
1151     FeaturePtr aSub = theSketch->subFeature(a);
1152     const std::list<ResultPtr>& aResults = aSub->results();
1153     std::list<ResultPtr>::const_iterator aRes = aResults.cbegin();
1154     for (; aRes != aResults.cend(); aRes++) {
1155       GeomShapePtr aCurShape = (*aRes)->shape();
1156       if (aCurShape && aCurShape->isEdge())
1157         aCurves[untrimmedCurve(aCurShape)] = *aRes;
1158     }
1159   }
1160
1161   // convert each face to the list of results of its edges
1162   int aFacesNum = aSketchResult->facesNum();
1163   for (int a = 0; a < aFacesNum; ++a) {
1164     theEdges.push_back(std::list<ResultPtr>());
1165     std::list<ResultPtr>& aCurEdges = theEdges.back();
1166
1167     GeomFacePtr aFace = aSketchResult->face(a);
1168     for (GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::EDGE);
1169          anExp.more(); anExp.next()) {
1170       GeomCurvePtr aCurrent = untrimmedCurve(anExp.current());
1171       aCurEdges.push_back(aCurves[aCurrent]);
1172     }
1173   }
1174 }
1175
1176 //--------------------------------------------------------------------------------------
1177
1178 void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
1179 {
1180   FeaturePtr aBase = feature();
1181   const std::string& aDocName = theDumper.name(aBase->document());
1182
1183   AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
1184   if (anExternal->value()) {
1185     theDumper << aBase << " = model.addSketch(" << aDocName <<
1186       ", " << anExternal << ")" << std::endl;
1187   } else {
1188     // Sketch is base on a plane.
1189     std::shared_ptr<GeomAPI_Pnt> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1190         aBase->attribute(SketchPlugin_Sketch::ORIGIN_ID()))->pnt();
1191     std::shared_ptr<GeomAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1192         aBase->attribute(SketchPlugin_Sketch::NORM_ID()))->dir();
1193     std::shared_ptr<GeomAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1194         aBase->attribute(SketchPlugin_Sketch::DIRX_ID()))->dir();
1195
1196     // Check the plane is coordinate plane
1197     std::string aPlaneName = defaultPlane(anOrigin, aNormal, aDirX);
1198     if(anExternal->context()) { // checking for selected planes
1199       if (!aPlaneName.empty()
1200           && anExternal->context()->data()
1201           && anExternal->context()->data()->name() == aPlaneName) {
1202         // dump sketch based on coordinate plane
1203         theDumper << aBase << " = model.addSketch(" << aDocName
1204                   << ", model.standardPlane(\"" << aPlaneName << "\"))" << std::endl;
1205       } else { // some other plane
1206         theDumper << aBase << " = model.addSketch(" << aDocName <<
1207           ", " << anExternal<< ")" << std::endl;
1208       }
1209     } else {
1210       if (aPlaneName.empty()) {
1211         // needs import additional module
1212         theDumper.importModule("GeomAPI");
1213         // dump plane parameters
1214         const std::string& aSketchName = theDumper.name(aBase);
1215         std::string anOriginName = aSketchName + "_origin";
1216         std::string aNormalName  = aSketchName + "_norm";
1217         std::string aDirXName    = aSketchName + "_dirx";
1218         // use "\n" instead of std::endl to avoid automatic dumping sketch here
1219         // and then dumplicate dumping it in the next line
1220         theDumper << anOriginName << " = " << anOrigin << "\n"
1221                   << aNormalName  << " = " << aNormal  << "\n"
1222                   << aDirXName    << " = " << aDirX    << "\n";
1223         // dump sketch based on arbitrary plane
1224         theDumper << aBase << " = model.addSketch(" << aDocName << ", GeomAPI_Ax3("
1225                   << anOriginName << ", " << aDirXName << ", " << aNormalName << "))" << std::endl;
1226       } else {
1227         // dump sketch based on coordinate plane
1228         theDumper << aBase << " = model.addSketch(" << aDocName
1229                   << ", model.defaultPlane(\"" << aPlaneName << "\"))" << std::endl;
1230       }
1231     }
1232   }
1233
1234   // dump sketch's subfeatures
1235   CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aBase);
1236   theDumper.processSubs(aCompFeat, true);
1237
1238   // if face order differs to the order generated by SketchBuilder,
1239   // dump the list of faces for correct execution of the script
1240   if (isCustomFacesOrder(aCompFeat)) {
1241     std::list<std::list<ResultPtr> > aFaces;
1242     edgesOfSketchFaces(aCompFeat, aFaces);
1243
1244     const std::string& aSketchName = theDumper.name(aBase);
1245     std::string aMethodName(".changeFacesOrder");
1246     std::string aSpaceShift(aSketchName.size() + aMethodName.size(), ' ');
1247
1248     theDumper << aSketchName << aMethodName << "([";
1249     for (std::list<std::list<ResultPtr> >::iterator aFIt = aFaces.begin();
1250          aFIt != aFaces.end(); ++aFIt) {
1251       if (aFIt != aFaces.begin())
1252         theDumper << ",\n" << aSpaceShift << "  ";
1253       theDumper << *aFIt;
1254     }
1255     theDumper << "\n" << aSpaceShift << " ])" << std::endl;
1256   }
1257 }