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