Salome HOME
Get rid of compilation warnings. Part I.
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Tools.cpp
1 // Copyright (C) 2014-2020  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 "SketchPlugin_Tools.h"
21
22 #include "SketchPlugin_Arc.h"
23 #include "SketchPlugin_Circle.h"
24 #include "SketchPlugin_ConstraintCoincidence.h"
25 #include "SketchPlugin_ConstraintCoincidenceInternal.h"
26 #include "SketchPlugin_ConstraintLength.h"
27 #include "SketchPlugin_ConstraintTangent.h"
28 #include "SketchPlugin_Ellipse.h"
29 #include "SketchPlugin_EllipticArc.h"
30 #include "SketchPlugin_Line.h"
31 #include "SketchPlugin_Point.h"
32 #include "SketchPlugin_Projection.h"
33 #include "SketchPlugin_SketchEntity.h"
34 #include "SketchPlugin_Split.h"
35 #include "SketchPlugin_Trim.h"
36
37 #include <SketcherPrs_Tools.h>
38
39 #include <ModelAPI_AttributeDouble.h>
40
41 #include <ModelGeomAlgo_Point2D.h>
42 #include <ModelGeomAlgo_Shape.h>
43
44 #include <GeomAPI_Dir2d.h>
45 #include <GeomAPI_Edge.h>
46 #include <GeomAPI_Pnt2d.h>
47 #include <GeomAPI_XY.h>
48
49 #include <GeomAlgoAPI_CompoundBuilder.h>
50 #include <GeomAlgoAPI_ShapeTools.h>
51
52 #include <GeomDataAPI_Point.h>
53 #include <GeomDataAPI_Point2D.h>
54
55 #ifdef DEBUG_TRIM
56 #include <iostream>
57 #endif
58
59 namespace SketchPlugin_Tools {
60
61 void clearExpressions(AttributeDoublePtr theAttribute)
62 {
63   theAttribute->setText(std::string());
64 }
65
66 void clearExpressions(AttributePointPtr theAttribute)
67 {
68   theAttribute->setText(std::string(), std::string(), std::string());
69 }
70
71 void clearExpressions(AttributePoint2DPtr theAttribute)
72 {
73   theAttribute->setText(std::string(), std::string());
74 }
75
76 void clearExpressions(AttributePtr theAttribute)
77 {
78   // Double
79   AttributeDoublePtr anAttributeDouble =
80       std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
81   if (anAttributeDouble.get())
82     clearExpressions(anAttributeDouble);
83   // Point
84   AttributePointPtr anAttributePoint =
85       std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
86   if (anAttributePoint.get())
87     clearExpressions(anAttributePoint);
88   // Point2D
89   AttributePoint2DPtr anAttributePoint2D =
90       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
91   if (anAttributePoint2D.get())
92     clearExpressions(anAttributePoint2D);
93 }
94
95 void clearExpressions(FeaturePtr theFeature)
96 {
97   if (!theFeature.get())
98     return;
99
100   std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
101   std::list<AttributePtr>::iterator anAttributeIt = anAttributes.begin();
102   for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
103     clearExpressions(*anAttributeIt);
104   }
105 }
106
107 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
108 {
109   std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
110                                                           SketchPlugin_Constraint::ENTITY_A());
111   if (aPnt.get() == NULL)
112     aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
113   return aPnt;
114 }
115
116 std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
117 {
118   std::set<FeaturePtr> aCoincident;
119   const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
120   std::set<AttributePtr>::const_iterator aIt;
121   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
122     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
123     if (aConstrFeature && (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
124         aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()))
125       aCoincident.insert(aConstrFeature);
126   }
127   return aCoincident;
128 }
129
130 void findCoincidences(const FeaturePtr theStartCoin,
131                       const std::string& theAttr,
132                       std::set<FeaturePtr>& theList,
133                       const bool theIsAttrOnly)
134 {
135   AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
136   if(!aPnt) {
137     return;
138   }
139   FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
140   if(theList.find(aObj) == theList.end()) {
141     std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
142     if(aOrig.get() == NULL) {
143       return;
144     }
145     if(!theIsAttrOnly || !aPnt->isObject()) {
146       theList.insert(aObj);
147     }
148     std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
149     std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
150     for (; aCIt != aCoincidences.end(); ++aCIt) {
151       FeaturePtr aConstrFeature = *aCIt;
152       std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
153       if(aPnt.get() && aOrig->isEqual(aPnt)) {
154         findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
155                          theList, theIsAttrOnly);
156         findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
157                          theList, theIsAttrOnly);
158       }
159     }
160   }
161 }
162
163 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
164 {
165   std::set<FeaturePtr> aCoincidentFeatures;
166
167   FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
168   aCoincidentFeatures.insert(anOwner);
169
170   std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
171   std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
172   for (; aCIt != aCoincidences.end(); ++aCIt) {
173     bool isPointUsedInCoincidence = false;
174     AttributeRefAttrPtr anOtherCoincidentAttr;
175     for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
176       AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
177       if (!aRefAttr)
178         continue;
179       if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
180         isPointUsedInCoincidence = true;
181       else
182         anOtherCoincidentAttr = aRefAttr;
183     }
184
185     if (isPointUsedInCoincidence) {
186       ObjectPtr anObj;
187       if (anOtherCoincidentAttr->isObject())
188         anObj = anOtherCoincidentAttr->object();
189       else
190         anObj = anOtherCoincidentAttr->attr()->owner();
191       aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
192     }
193   }
194
195   return aCoincidentFeatures;
196 }
197
198 // Container for point-point coincidences.
199 // Useful to find points coincident to a given point.
200 class CoincidentPoints
201 {
202 public:
203   void addCoincidence(const AttributePoint2DPtr& thePoint1,
204                       const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
205   {
206     std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
207     std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
208     if (aFound1 == myCoincidentPoints.end()) {
209       if (aFound2 == myCoincidentPoints.end()) {
210         std::set<AttributePoint2DPtr> aNewSet;
211         aNewSet.insert(thePoint1);
212         if (thePoint2)
213           aNewSet.insert(thePoint2);
214         myCoincidentPoints.push_back(aNewSet);
215       } else
216         aFound2->insert(thePoint1);
217     } else if (aFound2 == myCoincidentPoints.end()) {
218       if (thePoint2)
219         aFound1->insert(thePoint2);
220     } else {
221       aFound1->insert(aFound2->begin(), aFound2->end());
222       myCoincidentPoints.erase(aFound2);
223     }
224   }
225
226   std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
227   {
228     collectCoincidentPoints(thePoint);
229
230     std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
231     if (aFound == myCoincidentPoints.end())
232       return std::set<AttributePoint2DPtr>();
233     return *aFound;
234   }
235
236 private:
237   void coincidences(const FeaturePtr& theFeature,
238                     std::set<FeaturePtr>& theCoincidences) const
239   {
240     // iterate through coincideces for the given feature
241     std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
242     std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
243     for (; aCIt != aCoincidences.end(); ++aCIt)
244     {
245       if (theCoincidences.find(*aCIt) != theCoincidences.end())
246         continue; // already processed
247       theCoincidences.insert(*aCIt);
248       // iterate on coincident attributes
249       for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
250         AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
251         if (aRefAttr && !aRefAttr->isObject())
252         {
253           FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
254           if (anOwner != theFeature)
255             coincidences(anOwner, theCoincidences);
256         }
257       }
258     }
259   }
260
261   // Iteratively search points coincident to the given point
262   // (two points may be coincident through the third point)
263   void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
264   {
265     AttributePoint2DPtr aPoints[2];
266
267     FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
268     std::set<FeaturePtr> aCoincidences;
269     coincidences(anOwner, aCoincidences);
270
271     std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
272     for (; aCIt != aCoincidences.end(); ++aCIt) {
273       aPoints[0] = AttributePoint2DPtr();
274       aPoints[1] = AttributePoint2DPtr();
275       for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
276         AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
277         if (aRefAttr && !aRefAttr->isObject())
278           aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
279       }
280
281       if (aPoints[0] && aPoints[1])
282         addCoincidence(aPoints[0], aPoints[1]);
283     }
284   }
285
286   std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
287   {
288     std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
289     for (; aSeek != myCoincidentPoints.end(); ++aSeek)
290       if (aSeek->find(thePoint) != aSeek->end())
291         return aSeek;
292     return myCoincidentPoints.end();
293   }
294
295 private:
296   std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
297 };
298
299 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
300 {
301   CoincidentPoints aCoincidentPoints;
302   return aCoincidentPoints.coincidentPoints(thePoint);
303 }
304
305 void resetAttribute(SketchPlugin_Feature* theFeature,
306                     const std::string& theId)
307 {
308   AttributePtr anAttr = theFeature->attribute(theId);
309   if(anAttr.get()) {
310     anAttr->reset();
311   }
312 }
313
314 void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
315                                  const std::string& theId,
316                                  const AttributePtr theAttr,
317                                  const ObjectPtr theObject,
318                                  const bool theIsCanBeTangent)
319 {
320   AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
321   if(aRefAttr.get() && aRefAttr->isInitialized()) {
322     FeaturePtr aConstraint;
323     if(!theIsCanBeTangent) {
324       aConstraint = theFeature->sketch()
325                               ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
326     } else {
327       if(aRefAttr->isObject()) {
328         ObjectPtr anObject = aRefAttr->object();
329         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
330         if(aFeature->getKind() == SketchPlugin_Point::ID()) {
331           aConstraint = theFeature->sketch()
332                                   ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
333         } else {
334           aConstraint = theFeature->sketch()
335                                   ->addFeature(SketchPlugin_ConstraintTangent::ID());
336         }
337       } else {
338         aConstraint = theFeature->sketch()
339                                 ->addFeature(SketchPlugin_ConstraintCoincidence::ID());
340       }
341     }
342     AttributeRefAttrPtr aRefAttrA = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
343     aRefAttr->isObject() ? aRefAttrA->setObject(aRefAttr->object())
344                          : aRefAttrA->setAttr(aRefAttr->attr());
345     AttributeRefAttrPtr aRefAttrB = aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
346     if(theObject.get()) {
347       aRefAttrB->setObject(theObject);
348     } else if(theAttr.get()) {
349       aRefAttrB->setAttr(theAttr);
350     }
351   }
352 }
353
354 void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr&      theRefAttr,
355                                          const AttributePtr&             theDefaultAttr,
356                                          std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
357                                          std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
358 {
359   AttributePtr anAttr = theDefaultAttr;
360   if (theRefAttr->isObject()) {
361     FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
362     if (aTgFeature) {
363       if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
364         theTangentCurve = aTgFeature->lastResult()->shape();
365         return;
366       }
367       anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
368     }
369   } else
370     anAttr = theRefAttr->attr();
371
372   thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
373 }
374
375
376 FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
377                                     const std::string& theConstraintId,
378                                     const AttributePtr& theFirstAttribute,
379                                     const AttributePtr& theSecondAttribute)
380 {
381   FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
382   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
383                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
384   aRefAttr->setAttr(theFirstAttribute);
385
386   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
387                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
388   aRefAttr->setAttr(theSecondAttribute);
389
390 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
391   std::cout << "<createConstraint to attribute> :"
392             << " first attribute - " << theFirstAttribute->id()
393             << " second attribute - " << theSecondAttribute->id()
394             << std::endl;
395 #endif
396
397   return aConstraint;
398 }
399
400 FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
401                                       const std::string& theConstraintId,
402                                       const AttributePtr& theFirstAttribute,
403                                       const ObjectPtr& theSecondObject)
404 {
405   FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
406   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
407                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
408   aRefAttr->setAttr(theFirstAttribute);
409
410   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
411                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
412   aRefAttr->setObject(theSecondObject);
413
414 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
415   std::cout << "<createConstraint to attribute> :"
416             << " first attribute - " << theFirstAttribute->id()
417             << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
418             << std::endl;
419 #endif
420
421   return aConstraint;
422 }
423
424 FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
425                                         const std::string& theConstraintId,
426                                         const ObjectPtr& theFirstObject,
427                                         const ObjectPtr& theSecondObject)
428 {
429   FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
430   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
431                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
432   aRefAttr->setObject(theFirstObject);
433
434   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
435                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
436   aRefAttr->setObject(theSecondObject);
437
438 #if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
439   std::cout << "<createConstraint to attribute> :"
440             << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
441             << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
442             << std::endl;
443 #endif
444
445   return aConstraint;
446 }
447
448 void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
449                                    const std::string& theEllipsePoint)
450 {
451   SketchPlugin_Sketch* aSketch =
452       std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
453
454   FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
455   aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
456   aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
457
458   AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
459     theEllipseFeature->attribute(theEllipsePoint));
460
461   AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
462     aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
463   aCoord->setValue(anElPoint->x(), anElPoint->y());
464
465   aPointFeature->execute();
466   std::string aName = theEllipseFeature->name() + "_" + theEllipsePoint;
467   aPointFeature->data()->setName(aName);
468   aPointFeature->lastResult()->data()->setName(aName);
469
470   createConstraintAttrAttr(aSketch,
471       SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord);
472 }
473
474 void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
475                                   const std::string& theStartPoint,
476                                   const std::string& theEndPoint)
477 {
478   SketchPlugin_Sketch* aSketch =
479       std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
480
481   FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID());
482   aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
483   aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
484
485   AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
486     theEllipseFeature->attribute(theStartPoint));
487   AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
488     theEllipseFeature->attribute(theEndPoint));
489
490   AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
491     aLineFeature->attribute(SketchPlugin_Line::START_ID()));
492   aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
493
494   AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
495     aLineFeature->attribute(SketchPlugin_Line::END_ID()));
496   aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
497
498   aLineFeature->execute();
499   std::string aName = theEllipseFeature->name() + "_" +
500     (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? "major_axis" : "minor_axis");
501   aLineFeature->data()->setName(aName);
502   aLineFeature->lastResult()->data()->setName(aName);
503
504   createConstraintAttrAttr(aSketch,
505       SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart);
506   createConstraintAttrAttr(aSketch,
507       SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd);
508 }
509
510 GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
511 {
512   // currently process Length constraints only
513   if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
514     return GeomPnt2dPtr();
515
516   AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
517   if (!aLineAttr || !aLineAttr->isObject())
518     return GeomPnt2dPtr();
519   FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
520   if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
521     return GeomPnt2dPtr();
522
523   std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
524       aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
525   std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
526       aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
527
528   std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
529       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
530       theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
531   std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
532
533   std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
534
535   double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
536   double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
537
538   return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
539 }
540
541
542 void customizeFeaturePrs(const AISObjectPtr& thePrs, bool isAxiliary)
543 {
544   std::vector<int> aColor;
545   int aWidth = 1;
546   if (isAxiliary) {
547     thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY());
548     aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
549     aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY();
550   }
551   else {
552     thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE());
553     aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
554     aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
555   }
556   thePrs->setWidth(aWidth);
557   thePrs->setColor(aColor[0], aColor[1], aColor[2]);
558 }
559
560 void setDimensionColor(const AISObjectPtr& theDimPrs)
561 {
562   std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_dimension_color");
563   if (aColor.size() == 3)
564     theDimPrs->setColor(aColor[0], aColor[1], aColor[2]);
565 }
566
567 void replaceInName(ObjectPtr theObject, const std::string& theSource, const std::string& theDest)
568 {
569   std::string aName = theObject->data()->name();
570   size_t aPos = aName.find(theSource);
571   if (aPos != std::string::npos) {
572     std::string aNewName = aName.substr(0, aPos) + theDest
573                          + aName.substr(aPos + theSource.size());
574     theObject->data()->setName(aNewName);
575   }
576 }
577
578 } // namespace SketchPlugin_Tools
579
580
581 // =================================================================================================
582 //                 namespace SketchPlugin_SegmentationTools
583 // =================================================================================================
584
585 void SketchPlugin_SegmentationTools::getFeaturePoints(const FeaturePtr& theFeature,
586                                                       AttributePoint2DPtr& theStartPointAttr,
587                                                       AttributePoint2DPtr& theEndPointAttr)
588 {
589   std::string aFeatureKind = theFeature->getKind();
590   std::string aStartAttributeName, anEndAttributeName;
591   if (aFeatureKind == SketchPlugin_Line::ID()) {
592     aStartAttributeName = SketchPlugin_Line::START_ID();
593     anEndAttributeName = SketchPlugin_Line::END_ID();
594   }
595   else if (aFeatureKind == SketchPlugin_Arc::ID()) {
596     aStartAttributeName = SketchPlugin_Arc::START_ID();
597     anEndAttributeName = SketchPlugin_Arc::END_ID();
598   }
599   else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
600     aStartAttributeName = SketchPlugin_EllipticArc::START_POINT_ID();
601     anEndAttributeName = SketchPlugin_EllipticArc::END_POINT_ID();
602   }
603   if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
604     theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
605         theFeature->attribute(aStartAttributeName));
606     theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
607         theFeature->attribute(anEndAttributeName));
608   }
609 }
610
611
612 void SketchPlugin_SegmentationTools::getRefAttributes(
613     const FeaturePtr& theFeature,
614     std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
615     std::list<AttributePtr>& theRefsToFeature)
616 {
617   theRefs.clear();
618
619   std::list<AttributePtr> aPointAttributes =
620     theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
621   std::set<AttributePtr> aPointAttributesSet;
622
623   std::list<AttributePtr>::const_iterator aPIt =
624     aPointAttributes.begin(), aPLast = aPointAttributes.end();
625   for (; aPIt != aPLast; aPIt++)
626     aPointAttributesSet.insert(*aPIt);
627
628   std::set<AttributePtr> aRefsAttributes = theFeature->lastResult()->data()->refsToMe();
629   std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
630   aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
631
632   std::set<AttributePtr>::const_iterator aIt;
633   for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
634     AttributePtr anAttr = (*aIt);
635     FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
636     if (!anAttrFeature->isMacro() && // <- skip reference from Trim or Split feature
637         anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
638       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
639       if (!aRefAttr->isObject()) { // find attributes referenced to feature point attributes
640         AttributePtr anAttrInRef = aRefAttr->attr();
641         if (anAttrInRef.get() &&
642             aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
643           if (theRefs.find(anAttrInRef) != theRefs.end())
644             theRefs[anAttrInRef].push_back(aRefAttr);
645           else {
646             std::list<AttributePtr> anAttrList;
647             anAttrList.push_back(aRefAttr);
648             theRefs[anAttrInRef] = anAttrList;
649           }
650         }
651       }
652       else { // find attributes referenced to feature itself
653         theRefsToFeature.push_back(anAttr);
654       }
655     }
656   }
657 }
658
659 GeomShapePtr SketchPlugin_SegmentationTools::getSubShape(
660     SketchPlugin_Feature* theFeature,
661     const std::string& theObjectAttributeId,
662     const std::string& thePointAttributeId,
663     std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
664     std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
665 {
666   GeomShapePtr aBaseShape;
667
668   AttributeReferencePtr anObjectAttr = theFeature->reference(theObjectAttributeId);
669   ObjectPtr aBaseObject = anObjectAttr->value();
670   if (!aBaseObject.get())
671     return aBaseShape;
672
673   // point on feature
674   AttributePoint2DPtr aPointAttr =
675       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(thePointAttributeId));
676   std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
677   std::shared_ptr<GeomAPI_Pnt> anAttributePnt =
678       theFeature->sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y());
679
680   if (theCashedShapes.find(aBaseObject) == theCashedShapes.end())
681     fillObjectShapes(theFeature, aBaseObject, theCashedShapes, theObjectToPoints);
682
683   std::shared_ptr<GeomAPI_Pnt> aStartPoint;
684   std::shared_ptr<GeomAPI_Pnt> aSecondPoint;
685   const std::set<GeomShapePtr>& aShapes = theCashedShapes[aBaseObject];
686   std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
687   for (; anIt != aLast; anIt++) {
688     GeomShapePtr aCurrentShape = *anIt;
689     std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
690     if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) {
691       if (theFeature->getKind() == SketchPlugin_Split::ID()) {
692         // for Split operation collect start and end points of the shape
693         if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) {
694           std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aCurrentShape));
695           aStartPoint = anEdge->firstPoint();
696           aSecondPoint = anEdge->lastPoint();
697         }
698       }
699       else
700         aBaseShape = aCurrentShape;
701       break;
702     }
703   }
704
705   if (!aStartPoint.get() || !aSecondPoint.get())
706     return aBaseShape;
707
708   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
709   if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) {
710     ResultPtr aResult = aBaseFeature->lastResult();
711     GeomShapePtr aResultShape = aResult->shape();
712     std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
713
714     aPoints.push_back(aStartPoint);
715     aPoints.push_back(aSecondPoint);
716
717     std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
718     GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes);
719     aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
720   }
721   return aBaseShape;
722 }
723
724 void SketchPlugin_SegmentationTools::fillObjectShapes(
725     SketchPlugin_Feature* theOpFeature,
726     const ObjectPtr& theObject,
727     std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
728     std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
729 {
730   SketchPlugin_Sketch* aSketch = theOpFeature->sketch();
731
732   GeomAlgoAPI_ShapeTools::PointToRefsMap aPoints;
733   std::set<GeomShapePtr> aShapes;
734
735   std::set<AttributePoint2DPtr > aRefAttributes;
736   // current feature
737   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
738   std::set<ResultPtr> anEdgeShapes;
739   // edges on feature
740   ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
741   if (!anEdgeShapes.empty()) {
742     GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
743
744     // coincidences to the feature
745     ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
746                          aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
747     // layed on feature coincidences to divide it on several shapes
748     std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
749     std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
750         aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
751     std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
752         aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
753     std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
754         aData->attribute(SketchPlugin_Sketch::NORM_ID()));
755     std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
756
757     ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
758                                                   aX->dir(), aY, aPoints);
759
760     if (theOpFeature->getKind() == SketchPlugin_Trim::ID()) {
761       // collect all intersection points with other edges for Trim operation only
762       std::list<FeaturePtr> aFeatures;
763       for (int i = 0; i < aSketch->numberOfSubs(); i++) {
764         FeaturePtr aFeature = aSketch->subFeature(i);
765         if (aFeature.get() && aFeature->getKind() != SketchPlugin_Projection::ID())
766           aFeatures.push_back(aFeature);
767       }
768       ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints);
769     }
770
771     if (!aPoints.empty())
772       GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes);
773   }
774   theObjectToPoints[theObject] = aPoints;
775   theCashedShapes[theObject] = aShapes;
776 }
777
778 void SketchPlugin_SegmentationTools::updateRefAttConstraints(
779     const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
780     const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
781 {
782 #if defined DEBUG_SPLIT || defined DEBUG_TRIM
783   std::cout << "updateRefAttConstraints" << std::endl;
784 #endif
785
786   std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
787     anIt = theModifiedAttributes.begin(),  aLast = theModifiedAttributes.end();
788   for (; anIt != aLast; anIt++) {
789     AttributePtr anAttribute = anIt->first;
790     AttributePtr aNewAttribute = anIt->second;
791
792     // not found in references
793     if (!aNewAttribute.get() ||
794         theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
795       continue;
796     std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
797     std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
798                                             aRLast = aRefAttributes.end();
799
800     for (; aRefIt != aRLast; aRefIt++) {
801       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
802       if (aRefAttr.get()) {
803         aRefAttr->setAttr(aNewAttribute);
804 #ifdef DEBUG_SPLIT
805         FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
806         std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
807 #endif
808       }
809     }
810   }
811 }
812
813 void SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(
814     const std::set<FeaturePtr>& theFeaturesToUpdate)
815 {
816   std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
817                                        aLast = theFeaturesToUpdate.end();
818   for (; anIt != aLast; anIt++) {
819     FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
820     std::string aRefFeatureKind = aRefFeature->getKind();
821     if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
822       std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
823                               std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
824       if (aLenghtFeature.get()) {
825         std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
826             ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
827         double aValue;
828         if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
829           aValueAttr->setValue(aValue);
830       }
831     }
832   }
833 }
834
835 AISObjectPtr SketchPlugin_SegmentationTools::getAISObject(
836     AISObjectPtr thePrevious,
837     SketchPlugin_Feature* theOpFeature,
838     const std::string& thePreviewObjectAttrName,
839     const std::string& thePreviewPointAttrName,
840     const std::string& theSelectedObjectAttrName,
841     const std::string& theSelectedPointAttrName)
842 {
843 #if defined DEBUG_SPLIT || defined DEBUG_TRIM_METHODS
844   std::cout << "getAISObject: " << theOpFeature->data()->name() << std::endl;
845 #endif
846
847   AISObjectPtr anAIS = thePrevious;
848
849   std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
850   std::map<ObjectPtr, std::set<GeomShapePtr> > aCashedShapes;
851   std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap> aObjectToPoints;
852   GeomShapePtr aPreviewShape = getSubShape(theOpFeature,
853       thePreviewObjectAttrName, thePreviewPointAttrName, aCashedShapes, aObjectToPoints);
854   if (aPreviewShape.get())
855     aShapes.push_back(aPreviewShape);
856   GeomShapePtr aSelectedShape = getSubShape(theOpFeature,
857       theSelectedObjectAttrName, theSelectedPointAttrName, aCashedShapes, aObjectToPoints);
858   if (aSelectedShape.get())
859     aShapes.push_back(aSelectedShape);
860
861   if (aShapes.empty())
862     return AISObjectPtr();
863
864   GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
865   if (!aBaseShape.get())
866     return AISObjectPtr();
867
868   if (aBaseShape.get()) {
869     if (!anAIS)
870       anAIS = AISObjectPtr(new GeomAPI_AISObject);
871     anAIS->createShape(aBaseShape);
872
873     std::vector<int> aColor;
874     aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
875     double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
876     int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
877     anAIS->setColor(aColor[0], aColor[1], aColor[2]);
878     // width when there is not base object should be extened in several points
879     // in order to see this preview over highlight
880     anAIS->setWidth(aWidth+4);
881     anAIS->setLineStyle(aLineStyle);
882   }
883   else
884     anAIS = AISObjectPtr();
885   return anAIS;
886 }
887
888 #define GEOM_DATA_POINT2D(f, a) std::dynamic_pointer_cast<GeomDataAPI_Point2D>((f)->attribute(a))
889
890 FeaturePtr SketchPlugin_SegmentationTools::createLineFeature(
891     const FeaturePtr& theBaseFeature,
892     const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
893     const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
894 {
895   FeaturePtr aFeature;
896   std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
897       std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
898   SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
899   if (!aSketch || !theBaseFeature.get())
900     return aFeature;
901
902   aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
903
904   GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::START_ID())->setValue(theFirstPoint);
905   GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::END_ID())->setValue(theSecondPoint);
906
907   aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
908       theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
909   aFeature->execute(); // to obtain result
910
911   return aFeature;
912 }
913
914 struct ArcAttributes
915 {
916   std::string myKind;
917   std::string myCenter;
918   std::string myFocus;
919   std::string myStart;
920   std::string myEnd;
921   std::string myReversed;
922
923   ArcAttributes() {}
924
925   ArcAttributes(const std::string& theKind) : myKind(theKind)
926   {
927     if (myKind == SketchPlugin_Arc::ID()) {
928       myCenter = SketchPlugin_Arc::CENTER_ID();
929       myStart = SketchPlugin_Arc::START_ID();
930       myEnd = SketchPlugin_Arc::END_ID();
931       myReversed = SketchPlugin_Arc::REVERSED_ID();
932     }
933     else if (myKind == SketchPlugin_Circle::ID()) {
934       myCenter = SketchPlugin_Circle::CENTER_ID();
935     }
936     else if (myKind == SketchPlugin_Ellipse::ID()) {
937       myCenter = SketchPlugin_Ellipse::CENTER_ID();
938       myFocus = SketchPlugin_Ellipse::FIRST_FOCUS_ID();
939     }
940     else if (myKind == SketchPlugin_EllipticArc::ID()) {
941       myCenter = SketchPlugin_EllipticArc::CENTER_ID();
942       myFocus = SketchPlugin_EllipticArc::FIRST_FOCUS_ID();
943       myStart = SketchPlugin_EllipticArc::START_POINT_ID();
944       myEnd = SketchPlugin_EllipticArc::END_POINT_ID();
945       myReversed = SketchPlugin_EllipticArc::REVERSED_ID();
946     }
947   }
948 };
949
950 FeaturePtr SketchPlugin_SegmentationTools::createArcFeature(
951     const FeaturePtr& theBaseFeature,
952     const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
953     const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
954 {
955   FeaturePtr aFeature;
956   std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
957       std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
958   SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
959   if (!aSketch || !theBaseFeature.get())
960     return aFeature;
961
962   ArcAttributes aBaseAttrs(theBaseFeature->getKind());
963   ArcAttributes aTargetAttrs;
964   if (aBaseAttrs.myKind == SketchPlugin_Arc::ID() ||
965       aBaseAttrs.myKind == SketchPlugin_Circle::ID())
966     aTargetAttrs = ArcAttributes(SketchPlugin_Arc::ID());
967   else if (aBaseAttrs.myKind == SketchPlugin_Ellipse::ID() ||
968            aBaseAttrs.myKind == SketchPlugin_EllipticArc::ID())
969     aTargetAttrs = ArcAttributes(SketchPlugin_EllipticArc::ID());
970
971   if (aTargetAttrs.myKind.empty())
972     return aFeature;
973
974   aFeature = aSketch->addFeature(aTargetAttrs.myKind);
975   // update fillet arc: make the arc correct for sure, so, it is not needed to process
976   // the "attribute updated"
977   // by arc; moreover, it may cause cyclicity in hte mechanism of updater
978   bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
979
980   GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myCenter)->setValue(
981       GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myCenter)->pnt());
982   if (!aTargetAttrs.myFocus.empty()) {
983     GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myFocus)->setValue(
984         GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myFocus)->pnt());
985   }
986   GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myStart)->setValue(theFirstPoint);
987   GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myEnd)->setValue(theSecondPoint);
988
989   aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
990       theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
991
992   /// fill referersed state of created arc as it is on the base arc
993   bool aReversed = aBaseAttrs.myReversed.empty() ? false :
994                    theBaseFeature->boolean(aBaseAttrs.myReversed)->value();
995   aFeature->boolean(aTargetAttrs.myReversed)->setValue(aReversed);
996
997   aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
998   aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
999
1000   return aFeature;
1001 }