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