]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_Trim.cpp
Salome HOME
Issue #2082: Sketch multiple rotation does not work as expected
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Trim.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:    SketchPlugin_Trim.cpp
4 // Created: 22 Feb 2017
5 // Author:  Natalia ERMOLAEVA
6
7 #include "SketchPlugin_Trim.h"
8
9 #include <GeomAPI_Dir2d.h>
10 #include <GeomAPI_Edge.h>
11 #include <GeomAPI_Pnt2d.h>
12 #include <GeomAPI_XY.h>
13 #include <GeomDataAPI_Point2D.h>
14 #include <GeomAlgoAPI_ShapeTools.h>
15 #include <GeomAlgoAPI_CompoundBuilder.h>
16
17 #include <ModelAPI_AttributeReference.h>
18 #include <ModelAPI_AttributeString.h>
19 #include <ModelAPI_AttributeRefAttr.h>
20 #include <ModelAPI_Tools.h>
21 #include <ModelAPI_AttributeBoolean.h>
22
23 #include <ModelAPI_Validator.h>
24 #include <ModelAPI_Session.h>
25 #include <ModelAPI_AttributeDouble.h>
26
27 #include <ModelGeomAlgo_Shape.h>
28
29 #include <SketchPlugin_Arc.h>
30 #include <SketchPlugin_ConstraintMiddle.h>
31 #include <SketchPlugin_Circle.h>
32 #include <SketchPlugin_ConstraintCoincidence.h>
33 #include <SketchPlugin_ConstraintEqual.h>
34 //#include <SketchPlugin_ConstraintParallel.h>
35 #include <SketchPlugin_ConstraintTangent.h>
36 #include <SketchPlugin_ConstraintLength.h>
37 #include <SketchPlugin_ConstraintMirror.h>
38 #include <SketchPlugin_ConstraintCollinear.h>
39 #include <SketchPlugin_Line.h>
40 #include <SketchPlugin_MultiRotation.h>
41 #include <SketchPlugin_MultiTranslation.h>
42 #include <SketchPlugin_Point.h>
43
44 #include <ModelAPI_EventReentrantMessage.h>
45
46 #include <ModelAPI_Events.h>
47 #include <SketchPlugin_Line.h>
48 #include <SketchPlugin_Arc.h>
49 #include <SketchPlugin_Circle.h>
50
51 #include <ModelGeomAlgo_Point2D.h>
52 #include <Events_Loop.h>
53
54 #include <cmath>
55
56 //#define DEBUG_TRIM_METHODS
57 //#define DEBUG_TRIM
58
59 #ifdef DEBUG_TRIM
60 #include <iostream>
61 #endif
62
63 #ifdef DEBUG_TRIM_METHODS
64 #include <iostream>
65 #endif
66
67 static const double PI = 3.141592653589793238463;
68
69 static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; }
70 static const std::string OPERATION_REMOVE_FEATURE_COLOR() { return "255, 174, 201"; }
71
72 SketchPlugin_Trim::SketchPlugin_Trim()
73 {
74 }
75
76 void SketchPlugin_Trim::initAttributes()
77 {
78   data()->addAttribute(SketchPlugin_Trim::SELECTED_OBJECT(),
79                        ModelAPI_AttributeReference::typeId());
80   data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId());
81
82   data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId());
83   data()->addAttribute(PREVIEW_OBJECT(), ModelAPI_AttributeReference::typeId());
84
85   data()->attribute(PREVIEW_POINT())->setIsArgument(false);
86   data()->attribute(SELECTED_POINT())->setIsArgument(false);
87   data()->attribute(PREVIEW_OBJECT())->setIsArgument(false);
88
89   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT());
90   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT());
91 }
92
93 void SketchPlugin_Trim::findShapePoints(const std::string& theObjectAttributeId,
94                                         const std::string& thePointAttributeId,
95                                         std::shared_ptr<GeomAPI_Pnt>& aStartPoint,
96                                         std::shared_ptr<GeomAPI_Pnt>& aLastPoint)
97 {
98   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
99                                             data()->attribute(theObjectAttributeId));
100   ObjectPtr aBaseObject = aBaseObjectAttr->value();
101
102   AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
103                                               data()->attribute(thePointAttributeId));
104   std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPoint->pnt();
105   std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
106                                                                anAttributePnt2d->y());
107
108   if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
109     fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
110
111   const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
112   if (!aShapes.empty()) {
113     std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
114     for (; anIt != aLast; anIt++) {
115       GeomShapePtr aBaseShape = *anIt;
116       std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
117       if (ModelGeomAlgo_Point2D::isPointOnEdge(aBaseShape, anAttributePnt, aProjectedPoint)) {
118
119         if (aBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
120           std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aBaseShape));
121           //GeomAPI_Shape::Orientation anOrientation = anEdge->orientation();
122           //if (anOrientation == GeomAPI_Shape::REVERSED) {
123             aStartPoint = anEdge->lastPoint();
124             aLastPoint = anEdge->firstPoint();
125           //}
126           //else {
127             //aStartPoint = anEdge->firstPoint();
128             //aLastPoint = anEdge->lastPoint();
129           //}
130         }
131       }
132     }
133   }
134 #ifdef DEBUG_TRIM
135   std::cout << "<findShapePoints> => "
136     << std::endl << "Attribute point: "
137     << anAttributePnt->x() << ", " << anAttributePnt->y() << ", " << anAttributePnt->z() << "]"
138     << std::endl << "Start Point: ["
139     << aStartPoint->x() << ", " << aStartPoint->y() << ", " << aStartPoint->z() << "]"
140     << std::endl << "Last Point: ["
141     << aLastPoint->x() << ", " << aLastPoint->y() << ", " << aLastPoint->z() << "]"
142     << std::endl;
143 #endif
144 }
145
146 std::shared_ptr<GeomAPI_Pnt2d> SketchPlugin_Trim::convertPoint(
147                                                    const std::shared_ptr<GeomAPI_Pnt>& thePoint)
148 {
149   std::shared_ptr<GeomAPI_Pnt2d> aPoint;
150   if (!thePoint.get())
151     return aPoint;
152
153   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
154                                         data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
155   ObjectPtr aBaseObject = aBaseObjectAttr->value();
156   if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end())
157     fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
158
159   bool aFound = false;
160   const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
161   for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
162        aPointIt != aRefsMap.end() && !aFound; aPointIt++) {
163     if (aPointIt->first->isEqual(thePoint)) {
164       const std::pair<std::list<AttributePoint2DPtr >,
165                std::list<ObjectPtr > >& anInfo = aPointIt->second;
166       const std::list<AttributePoint2DPtr >& anAttributes = anInfo.first;
167       if (!anAttributes.empty()) {
168         aPoint = anAttributes.front()->pnt();
169         aFound = true;
170       }
171       else {
172         aPoint = sketch()->to2D(thePoint);
173         aFound = true;
174       }
175     }
176   }
177   if (!aFound) {
178     // returns an end of the shape to define direction of split if feature's attribute
179     // participates
180     aPoint = sketch()->to2D(thePoint);
181   }
182   return aPoint;
183 }
184
185 void SketchPlugin_Trim::execute()
186 {
187 #ifdef DEBUG_TRIM_METHODS
188   std::cout << "SketchPlugin_Trim::execute: " << data()->name() << std::endl;
189 #endif
190
191   SketchPlugin_Sketch* aSketch = sketch();
192   if (!aSketch) {
193     setError("Error: Sketch object is empty.");
194     return;
195   }
196
197   // Check the base objects are initialized.
198   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
199                                         data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
200   if(!aBaseObjectAttr->isInitialized()) {
201     setError("Error: Base object is not initialized.");
202     return;
203   }
204   ObjectPtr aBaseObject = aBaseObjectAttr->value();
205   if (!aBaseObject.get()) {
206     setError("Error: Base object is not initialized.");
207     return;
208   }
209   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
210
211   /// Remove reference of this feature to feature used in preview, it is not necessary anymore
212   /// as trim will be removed after execute
213   AttributeReferencePtr aPreviewObjectAttr =
214                      std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
215                      data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
216
217   ObjectPtr aPreviewObject = aPreviewObjectAttr->value();
218   AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
219                                            data()->attribute(PREVIEW_POINT()));
220   std::shared_ptr<GeomAPI_Pnt2d> aPreviewPnt2d = aPoint->pnt();
221   // nullify pointer of preview attribute
222   aPreviewObjectAttr->setValue(ResultPtr());
223
224   bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject;
225
226   /// points of trim
227   std::shared_ptr<GeomAPI_Pnt> aStartShapePoint, aLastShapePoint;
228 #ifdef DEBUG_TRIM
229   std::cout << " Base Feature: " << aBaseFeature->data()->name() << std::endl;
230 #endif
231   findShapePoints(SELECTED_OBJECT(), SELECTED_POINT(), aStartShapePoint, aLastShapePoint);
232
233   std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint2d = convertPoint(aStartShapePoint);
234   std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint2d = convertPoint(aLastShapePoint);
235
236   std::set<FeaturePtr> aFeaturesToDelete;
237   getConstraints(aFeaturesToDelete);
238
239   std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
240   std::list<AttributePtr> aRefsToFeature;
241   getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature);
242 #ifdef DEBUG_TRIM
243   std::cout << "---- getRefAttributes ----" << std::endl;
244   std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
245     aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end();
246   std::cout << std::endl << "References to attributes of base feature [" <<
247     aBaseRefAttributes.size() << "]" << std::endl;
248   for (; aRefIt != aRefLast; aRefIt++) {
249     AttributePtr aBaseAttr = aRefIt->first;
250     std::list<AttributePtr> aRefAttributes = aRefIt->second;
251     std::string aRefsInfo;
252     std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
253                                             aRefAttrLast = aRefAttributes.end();
254     for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
255       if (!aRefsInfo.empty())
256         aRefsInfo.append(",");
257       AttributePtr aRAttr = *aRefAttrIt;
258       aRefsInfo.append(aRAttr->id());
259       FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
260       aRefsInfo.append("(" + aRFeature->name() + ") ");
261     }
262     std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
263       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
264     std::cout << aPointAttr->id().c_str() <<
265       ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
266   }
267   std::cout << std::endl;
268   std::cout << std::endl << "References to base feature [" <<
269     aRefsToFeature.size() << "]" << std::endl;
270   std::list<AttributePtr>::const_iterator aRefAttrIt = aRefsToFeature.begin(),
271                                           aRefAttrLast = aRefsToFeature.end();
272   std::string aRefsInfo;
273   for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
274     if (!aRefsInfo.empty())
275       aRefsInfo.append(",");
276     AttributePtr aRAttr = *aRefAttrIt;
277     aRefsInfo.append(aRAttr->id());
278     FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
279     aRefsInfo.append("(" + aRFeature->name() + ") ");
280   }
281   std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl;
282   std::cout << "---- getRefAttributes:end ----" << std::endl;
283 #endif
284   // coincidence to result points
285   // find coincidences to the base object, it should be used when attribute is found
286   // in myObjectToPoints
287   //std::map<AttributePtr, FeaturePtr> aCoincidencesToBaseFeature;
288   //getCoincidencesToObject(aBaseObject, aCoincidencesToBaseFeature);
289
290   std::set<AttributePoint2DPtr> aFurtherCoincidences;
291   std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
292   const std::string& aKind = aBaseFeature->getKind();
293   FeaturePtr aReplacingFeature, aNewFeature;
294   if (aKind == SketchPlugin_Circle::ID()) {
295     aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d,
296                aFurtherCoincidences, aModifiedAttributes);
297
298     aFeaturesToDelete.insert(aBaseFeature);
299     // as circle is removed, erase it from dependencies(arguments) of this feature
300     // otherwise Trim feature will be removed with the circle before
301     // this operation is finished
302     aBaseObjectAttr->setObject(ResultPtr());
303   }
304   else if (aKind == SketchPlugin_Line::ID()) {
305     aNewFeature = trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
306                            aFurtherCoincidences, aModifiedAttributes);
307   }
308   else if (aKind == SketchPlugin_Arc::ID()) {
309     aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
310                           aFurtherCoincidences, aModifiedAttributes);
311   }
312
313   // constraints to end points of trim feature
314   if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end())
315     fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
316
317   // create coincidence to objects, intersected the base object
318   const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
319   for (std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
320                                                      aLast = aFurtherCoincidences.end();
321        anIt != aLast; anIt++) {
322     AttributePoint2DPtr aPointAttribute = (*anIt);
323     std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
324
325 #ifdef DEBUG_TRIM
326     std::cout << "<compare Points> => " << std::endl
327             << "aPoint2d: [" << aPoint2d->x() << ", " << aPoint2d->y() << "]" << std::endl;
328     if (aStartShapePoint2d.get())
329       std::cout << "Start Point: [" << aStartShapePoint2d->x() << ", " << aStartShapePoint2d->y()
330                 << "]" << std::endl;
331     if (aLastShapePoint2d.get())
332       std::cout << "Last Point: [" << aLastShapePoint2d->x() << ", " << aLastShapePoint2d->y()
333                 << "]" << std::endl;
334 #endif
335
336     std::shared_ptr<GeomAPI_Pnt> aPoint;
337     if (aStartShapePoint2d.get() && aPoint2d->isEqual(aStartShapePoint2d))
338       aPoint = aStartShapePoint;
339     else if (aLastShapePoint2d.get() && aPoint2d->isEqual(aLastShapePoint2d))
340       aPoint = aLastShapePoint;
341
342     if (!aPoint.get())
343       continue;
344
345     std::pair<std::list<AttributePoint2DPtr >, std::list<ObjectPtr > > anInfo;
346     for (PointToRefsMap::const_iterator aRefIt = aRefsMap.begin(); aRefIt != aRefsMap.end();
347          aRefIt++)
348     {
349       if (aRefIt->first->isEqual(aPoint)) {
350         anInfo = aRefIt->second;
351         break;
352       }
353     }
354     const std::list<ObjectPtr>& anObjects = anInfo.second;
355     for (std::list<ObjectPtr>::const_iterator anObjectIt = anObjects.begin();
356       anObjectIt != anObjects.end(); anObjectIt++) {
357       createConstraintToObject(SketchPlugin_ConstraintCoincidence::ID(), aPointAttribute,
358                                *anObjectIt);
359     }
360   }
361
362   // move constraints from base feature to replacing feature: ignore coincidences to feature
363   // if attributes of coincidence participated in split
364   ResultPtr aReplacingResult;
365   if (aReplacingFeature.get()) {
366     aReplacingFeature->execute(); // need it to obtain result
367     aReplacingResult = getFeatureResult(aReplacingFeature);
368   }
369   for(std::list<AttributePtr>::const_iterator anIt = aRefsToFeature.begin(),
370                                           aLast = aRefsToFeature.end();
371       anIt != aLast; anIt++) {
372     AttributePtr anAttribute = *anIt;
373
374     //if (replaceCoincidenceAttribute(anAttribute, aModifiedAttributes))
375     //  continue;
376
377     if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences))
378       continue;
379
380     if (aReplacingResult.get()) {
381       AttributeRefAttrPtr aRefAttr =
382           std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
383       if (aRefAttr.get())
384         aRefAttr->setObject(aReplacingResult);
385       else {
386         AttributeReferencePtr aReferenceAttr =
387                              std::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttribute);
388         if (aReferenceAttr.get())
389           aReferenceAttr->setObject(aReplacingResult);
390       }
391     }
392   }
393
394   updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete);
395
396   // Wait all constraints being created, then send update events
397   static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
398   bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
399   if (isUpdateFlushed)
400     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
401
402   // delete constraints
403 #ifdef DEBUG_TRIM
404   if (aFeaturesToDelete.size() > 0) {
405     std::cout << "after SPlit: removeFeaturesAndReferences: " << std::endl;
406     std::string aValue;
407     for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
408          anIt != aFeaturesToDelete.end(); anIt++) {
409       FeaturePtr aFeature = *anIt;
410       std::cout << aFeature->data()->name() << std::endl;
411     }
412   }
413 #endif
414   ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
415   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
416
417   // Send events to update the sub-features by the solver.
418   if(isUpdateFlushed) {
419     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
420   }
421
422   if (anIsEqualPreviewAndSelected) {
423     // equal preview and selected objects
424     // nothing to do if the preview and selected objects are different
425     if (aReplacingResult.get()) { // base object was removed
426       aPreviewObject = aReplacingResult;
427       //aMessage->setSelectedObject(aReplacingResult);
428
429       GeomShapePtr aSelectedShape = aReplacingResult->shape();
430       std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
431                                                                 aPreviewPnt2d->y());
432       std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
433       if (ModelGeomAlgo_Point2D::isPointOnEdge(aSelectedShape, aPreviewPnt, aProjectedPoint)) {
434         bool aValue = true;
435       }
436       //aBaseShape = aShape;
437
438 #ifdef DEBUG_TRIM_METHODS
439       if (!aSelectedShape.get())
440         std::cout << "Set empty selected object" << std::endl;
441       else
442         std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
443 #endif
444       bool aValue = true;
445     }
446     else {
447       aPreviewObject = ObjectPtr();
448
449       aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
450       aBaseObject = getFeatureResult(aBaseFeature);
451       std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
452                                                                 aPreviewPnt2d->y());
453       ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
454       if (aBaseResult) {
455         GeomShapePtr aShape = aBaseResult->shape();
456         std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
457         if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
458           aPreviewObject = aBaseResult;
459       }
460       if (!aPreviewObject.get() && aNewFeature.get()) {
461         ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature);
462         if (aNewFeatureResult.get()) {
463           GeomShapePtr aShape = aNewFeatureResult->shape();
464           std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
465           if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
466             aPreviewObject = aNewFeatureResult;
467         }
468       }
469     }
470   }
471   if (aPreviewObject.get()) {
472     std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
473       <ModelAPI_EventReentrantMessage>(new ModelAPI_EventReentrantMessage(
474                                            ModelAPI_EventReentrantMessage::eventId(), this));
475     aMessage->setSelectedObject(aPreviewObject);
476     Events_Loop::loop()->send(aMessage);
477   }
478 #ifdef DEBUG_TRIM
479   std::cout << "SketchPlugin_Trim::done" << std::endl;
480 #endif
481 }
482
483 std::string SketchPlugin_Trim::processEvent(const std::shared_ptr<Events_Message>& theMessage)
484 {
485 #ifdef DEBUG_TRIM_METHODS
486   std::cout << "SketchPlugin_Trim::processEvent:" << data()->name() << std::endl;
487 #endif
488   std::string aFilledAttributeName;
489
490   std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage =
491         std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
492   if (aMessage.get()) {
493     ObjectPtr anObject = aMessage->selectedObject();
494     std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
495
496     if (anObject.get() && aPoint.get()) {
497       if (myCashedShapes.find(anObject) == myCashedShapes.end())
498         fillObjectShapes(anObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
499       const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
500       if (aShapes.size() > 1) {
501         std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
502                               std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
503                               data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
504         std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
505                               std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
506                               data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()));
507         aRefSelectedAttr->setValue(anObject);
508         aRefPreviewAttr->setValue(anObject);
509
510         std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
511                               std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
512                               data()->attribute(SketchPlugin_Trim::SELECTED_POINT()));
513         std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
514                               std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
515                               data()->attribute(SketchPlugin_Trim::PREVIEW_POINT()));
516         aPointSelectedAttr->setValue(aPoint);
517         aPointPreviewAttr->setValue(aPoint);
518
519         Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
520
521         GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
522   #ifdef DEBUG_TRIM_METHODS
523         if (!aSelectedShape.get())
524           std::cout << "Set empty selected object" << std::endl;
525         else
526           std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
527   #endif
528         aFilledAttributeName = SketchPlugin_Trim::SELECTED_OBJECT();
529       }
530     }
531   }
532   return aFilledAttributeName;
533 }
534
535 bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute,
536                                 const std::set<AttributePoint2DPtr>& theFurtherCoincidences)
537 {
538   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
539   if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
540     return false;
541
542   AttributePoint2DPtr aRefPointAttr = SketchPlugin_ConstraintCoincidence::getPoint(aFeature);
543   if (!aRefPointAttr.get())
544     return false;
545   std::shared_ptr<GeomAPI_Pnt2d> aRefPnt2d = aRefPointAttr->pnt();
546
547   std::set<AttributePoint2DPtr>::const_iterator anIt = theFurtherCoincidences.begin(),
548                                                 aLast = theFurtherCoincidences.end();
549   bool aFoundPoint = false;
550   for (; anIt != aLast && !aFoundPoint; anIt++) {
551     AttributePoint2DPtr aPointAttribute = (*anIt);
552     std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
553     if (aPoint2d->isEqual(aRefPnt2d)) {
554       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
555                                                                            theAttribute);
556       if (aRefAttr.get()) {
557         aRefAttr->setAttr(aPointAttribute);
558         aFoundPoint = true;
559       }
560     }
561   }
562   return aFoundPoint;
563 }
564
565 bool SketchPlugin_Trim::replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute,
566                    const std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
567 {
568   FeaturePtr aCoincidenceFeature = ModelAPI_Feature::feature(theCoincidenceAttribute->owner());
569   if (aCoincidenceFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
570     return false;
571
572   AttributeRefAttrPtr aCAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
573                          aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
574   AttributeRefAttrPtr aCAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
575                          aCoincidenceFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
576   AttributePtr aCAttrRefA = aCAttrA->attr();
577   AttributePtr aCAttrRefB = aCAttrB->attr();
578
579   bool isProcessed = false;
580   for (std::set<std::pair<AttributePtr, AttributePtr>>::const_iterator
581        anIt = theModifiedAttributes.begin(); anIt != theModifiedAttributes.end(); anIt++) {
582     AttributePtr anAttributeBefore = anIt->first;
583     if (anAttributeBefore == aCAttrRefA) {
584       aCAttrA->setAttr(anIt->second);
585       isProcessed = true;
586     }
587     if (anAttributeBefore == aCAttrRefB) {
588       aCAttrB->setAttr(anIt->second);
589       isProcessed = true;
590     }
591   }
592   return isProcessed;
593 }
594
595 bool SketchPlugin_Trim::isMacro() const
596 {
597   return true;
598 }
599
600 AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious)
601 {
602 #ifdef DEBUG_TRIM_METHODS
603   std::cout << "SketchPlugin_Trim::getAISObject: " << data()->name() << std::endl;
604 #endif
605
606   AISObjectPtr anAIS = thePrevious;
607
608   std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
609   GeomShapePtr aPreviewShape = getSubShape(PREVIEW_OBJECT(), PREVIEW_POINT());
610   if (aPreviewShape.get())
611     aShapes.push_back(aPreviewShape);
612   GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
613   if (aSelectedShape.get())
614     aShapes.push_back(aSelectedShape);
615
616   if (aShapes.empty())
617     return AISObjectPtr();
618
619   GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
620   if (!aBaseShape.get())
621     return AISObjectPtr();
622
623   if (aBaseShape.get()) {
624     if (!anAIS)
625       anAIS = AISObjectPtr(new GeomAPI_AISObject);
626     anAIS->createShape(aBaseShape);
627
628     std::vector<int> aColor;
629     aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
630     double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
631     int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
632     anAIS->setColor(aColor[0], aColor[1], aColor[2]);
633     // width when there is not base object should be extened in several points
634     // in order to see this preview over highlight
635     anAIS->setWidth(aWidth+4);
636     anAIS->setLineStyle(aLineStyle);
637   }
638   else
639     anAIS = AISObjectPtr();
640
641   return anAIS;
642 }
643
644 GeomShapePtr SketchPlugin_Trim::getSubShape(const std::string& theObjectAttributeId,
645                                             const std::string& thePointAttributeId)
646 {
647   GeomShapePtr aBaseShape;
648
649   AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
650                                                        data()->attribute(theObjectAttributeId));
651   ObjectPtr aBaseObject = anObjectAttr->value();
652   if (!aBaseObject.get())
653     return aBaseShape;
654
655   // point on feature
656   AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
657                                            data()->attribute(thePointAttributeId));
658   std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPoint->pnt();
659   std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
660                                                                anAttributePnt2d->y());
661
662   if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
663     fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
664
665   const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
666   if (!aShapes.empty()) {
667     std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
668     for (; anIt != aLast; anIt++) {
669       GeomShapePtr aShape = *anIt;
670       std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
671       if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, anAttributePnt, aProjectedPoint))
672         aBaseShape = aShape;
673     }
674   }
675   return aBaseShape;
676 }
677
678 void SketchPlugin_Trim::getFeaturePoints(const FeaturePtr& theFeature,
679                                          AttributePoint2DPtr& theStartPointAttr,
680                                          AttributePoint2DPtr& theEndPointAttr)
681 {
682   std::string aFeatureKind = theFeature->getKind();
683   std::string aStartAttributeName, anEndAttributeName;
684   if (aFeatureKind == SketchPlugin_Line::ID()) {
685     aStartAttributeName = SketchPlugin_Line::START_ID();
686     anEndAttributeName = SketchPlugin_Line::END_ID();
687   }
688   else if (aFeatureKind == SketchPlugin_Arc::ID()) {
689     aStartAttributeName = SketchPlugin_Arc::START_ID();
690     anEndAttributeName = SketchPlugin_Arc::END_ID();
691   }
692   if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
693     theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
694                                          theFeature->attribute(aStartAttributeName));
695     theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
696                                          theFeature->attribute(anEndAttributeName));
697   }
698 }
699
700 void SketchPlugin_Trim::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete)
701 {
702   std::shared_ptr<ModelAPI_Data> aData = data();
703
704   // Check the base objects are initialized.
705   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
706                                          aData->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
707   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
708   ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
709
710   std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
711   std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
712   aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
713
714   std::set<AttributePtr>::const_iterator aIt;
715   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
716     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
717     FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
718     std::string aRefFeatureKind = aRefFeature->getKind();
719     if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
720         aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
721         aRefFeatureKind == SketchPlugin_MultiTranslation::ID() ||
722         aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID())
723       theFeaturesToDelete.insert(aRefFeature);
724   }
725 }
726
727 void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature,
728                                     std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
729                                     std::list<AttributePtr>& theRefsToFeature)
730 {
731   theRefs.clear();
732
733   std::list<AttributePtr> aPointAttributes =
734     theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
735   std::set<AttributePtr> aPointAttributesSet;
736
737   std::list<AttributePtr>::const_iterator aPIt =
738     aPointAttributes.begin(), aPLast = aPointAttributes.end();
739   for (; aPIt != aPLast; aPIt++)
740     aPointAttributesSet.insert(*aPIt);
741
742   std::set<AttributePtr> aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe();
743   std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
744   aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
745
746   std::set<AttributePtr>::const_iterator aIt;
747   for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
748     AttributePtr anAttr = (*aIt);
749     FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
750     if (anAttrFeature.get() != this &&
751         anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
752       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
753       if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes
754         AttributePtr anAttrInRef = aRefAttr->attr();
755         if (anAttrInRef.get() &&
756             aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
757           if (theRefs.find(anAttrInRef) != theRefs.end())
758             theRefs[anAttrInRef].push_back(aRefAttr);
759           else {
760             std::list<AttributePtr> anAttrList;
761             anAttrList.push_back(aRefAttr);
762             theRefs[anAttrInRef] = anAttrList;
763           }
764         }
765       }
766       else { /// find attributes referenced to feature itself
767         theRefsToFeature.push_back(anAttr);
768       }
769     }
770   }
771 }
772
773 /*void SketchPlugin_Trim::getCoincidencesToObject(const ObjectPtr& theObject,
774                    std::map<AttributePtr, FeaturePtr>& theCoincidencesToBaseFeature)
775 {
776   const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
777   std::set<AttributePtr>::const_iterator aIt;
778   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
779     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
780     FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
781     if (aRefFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
782       continue;
783     AttributePtr anAttribute;
784     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
785                                   (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
786     if (aRefAttr->isObject() && aRefAttr->object() == theObject)
787     {
788       anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B());
789     }
790     else {
791       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
792                                     (aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
793       if (aRefAttr->isObject() && aRefAttr->object() == theObject)
794         anAttribute = aRefFeature->attribute(SketchPlugin_Constraint::ENTITY_A());
795     }
796     if (!anAttribute.get())
797       continue;
798
799     aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
800     if (aRefAttr->isObject())
801       continue; // one of attributes of coincidence contains link to an attribute
802
803     anAttribute = aRefAttr->attr();
804     if (anAttribute.get())
805     {
806       theCoincidencesToBaseFeature[anAttribute] = aRefFeature;
807     }
808   }
809 }*/
810
811 void SketchPlugin_Trim::updateRefAttConstraints(
812                     const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
813                     const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes,
814                     std::set<FeaturePtr>& theFeaturesToDelete)
815 {
816 #ifdef DEBUG_TRIM
817   std::cout << "SketchPlugin_Trim::updateRefAttConstraints" << std::endl;
818 #endif
819
820   std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
821     anIt = theModifiedAttributes.begin(),  aLast = theModifiedAttributes.end();
822   for (; anIt != aLast; anIt++) {
823     AttributePtr anAttribute = anIt->first;
824
825     /// not found in references
826     if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
827       continue;
828     std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
829     std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
830                                             aRLast = aRefAttributes.end();
831
832     AttributePtr aNewAttribute = anIt->second;
833     if (aNewAttribute.get()) {
834       for (; aRefIt != aRLast; aRefIt++) {
835         AttributeRefAttrPtr aRefAttr =
836                         std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
837         if (aRefAttr.get()) {
838             aRefAttr->setAttr(aNewAttribute);
839         }
840       }
841     }
842   }
843 }
844
845 void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttribute,
846                   std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes)
847 {
848   /// not found in references
849   if (theBaseRefAttributes.find(theAttribute) == theBaseRefAttributes.end())
850     return;
851
852   std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(theAttribute);
853   std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
854                                           aRLast = aRefAttributes.end();
855
856   std::set<FeaturePtr> aFeaturesToDelete;
857   for (; aRefIt != aRLast; aRefIt++) {
858     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
859     if (aRefAttr.get()) {
860       aFeaturesToDelete.insert(ModelAPI_Feature::feature(aRefAttr->owner()));
861     }
862   }
863
864 #ifdef DEBUG_TRIM
865   // delete constraints
866   if (aFeaturesToDelete.size() > 0) {
867     std::cout << "removeReferencesToAttribute: " << std::endl;
868     std::string aValue;
869     for (std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin();
870          anIt != aFeaturesToDelete.end(); anIt++) {
871       FeaturePtr aFeature = *anIt;
872       std::cout << aFeature->data()->name() << std::endl;
873     }
874   }
875 #endif
876   ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
877   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
878 }
879
880 FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
881                   const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
882                   std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
883                   std::set<AttributePoint2DPtr>& thePoints,
884                   std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
885 {
886   FeaturePtr anNewFeature;
887
888   // Check the base objects are initialized.
889   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
890                                         data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
891   ObjectPtr aBaseObject = aBaseObjectAttr->value();
892   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
893
894   /// points of trim
895   AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
896   getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
897
898   std::shared_ptr<GeomAPI_Pnt2d> aStartFeaturePoint = aStartPointAttrOfBase->pnt();
899   std::shared_ptr<GeomAPI_Pnt2d> aLastFeaturePoint = anEndPointAttrOfBase->pnt();
900
901   std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
902   std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
903   arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase,
904                       aStartShapePoint, aLastShapePoint);
905 #ifdef DEBUG_TRIM
906   std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
907   if (aStartShapePoint.get())
908     std::cout << "Start point: [" << aStartShapePoint->x() << ", " <<
909                                        aStartShapePoint->y() << "]" << std::endl;
910   std::cout << "1st point:   [" << aStartFeaturePoint->x() << ", " <<
911                                    aStartFeaturePoint->y() << "]" << std::endl;
912   if (aLastShapePoint.get())
913     std::cout << "2st point:   [" << aLastShapePoint->x() << ", " <<
914                                      aLastShapePoint->y() << "]" << std::endl;
915   std::cout << "End point:   [" << aLastFeaturePoint->x() << ", " <<
916                                    aLastFeaturePoint->y() << "]" << std::endl;
917 #endif
918
919   bool isStartPoint = !aStartShapePoint.get() || aStartFeaturePoint->isEqual(aStartShapePoint);
920   bool isLastPoint = !aLastShapePoint.get() || aLastFeaturePoint->isEqual(aLastShapePoint);
921   if (isStartPoint || isLastPoint) {
922     // result is one line: changed existing line
923     std::string aModifiedAttribute = isStartPoint ? SketchPlugin_Line::START_ID()
924                                                   : SketchPlugin_Line::END_ID();
925     std::shared_ptr<GeomAPI_Pnt2d> aPoint;
926     if (aStartShapePoint.get() && aLastShapePoint.get())
927       aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
928     else
929       aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
930
931     // it is important to delete references before the feature modification because
932     // if deletion will be after the feature modification, solver returns the feature back
933     removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
934                                 theBaseRefAttributes);
935
936     fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
937     //theModifiedAttributes.insert(
938     //  std::make_pair(aBaseFeature->attribute(aModifiedAttribute), AttributePtr()));
939
940     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
941                                (aBaseFeature->attribute(aModifiedAttribute)));
942   }
943   else {
944     // result is two lines: start line point - start shape point,
945     // last shape point - last line point
946     // create second line
947     anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint);
948     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
949                                (anNewFeature->attribute(SketchPlugin_Line::START_ID())));
950
951     std::string aModifiedAttribute = SketchPlugin_Line::END_ID();
952     theModifiedAttributes.insert(
953       std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
954                                    anNewFeature->attribute(SketchPlugin_Line::END_ID())));
955
956     // modify base arc
957     fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
958
959     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
960                                (aBaseFeature->attribute(aModifiedAttribute)));
961
962     // Collinear constraint for lines
963     createConstraintForObjects(SketchPlugin_ConstraintCollinear::ID(),
964                                getFeatureResult(aBaseFeature),
965                                getFeatureResult(anNewFeature));
966
967   }
968   return anNewFeature;
969 }
970
971 FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
972                  const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
973                  std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
974                  std::set<AttributePoint2DPtr>& thePoints,
975                  std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
976 {
977   FeaturePtr anNewFeature;
978   // Check the base objects are initialized.
979   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
980                                         data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
981   ObjectPtr aBaseObject = aBaseObjectAttr->value();
982   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
983
984   /// points of trim
985   AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
986   getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
987
988   std::shared_ptr<GeomAPI_Pnt2d> aStartArcPoint = aStartPointAttrOfBase->pnt();
989   std::shared_ptr<GeomAPI_Pnt2d> aLastArcPoint = anEndPointAttrOfBase->pnt();
990
991   std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
992   std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
993   arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
994                      aStartShapePoint, aLastShapePoint);
995 #ifdef DEBUG_TRIM
996   std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
997   if (aStartShapePoint.get())
998     std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
999                                        aStartShapePoint->y() << "]" << std::endl;
1000   std::cout << "Start arc attribute point:   [" << aStartArcPoint->x() << ", " <<
1001                                    aStartArcPoint->y() << "]" << std::endl;
1002   if (aLastShapePoint.get())
1003     std::cout << "Last shape point:   [" << aLastShapePoint->x() << ", " <<
1004                                      aLastShapePoint->y() << "]" << std::endl;
1005   std::cout << "Last arc attribute point:   [" << aLastArcPoint->x() << ", " <<
1006                                    aLastArcPoint->y() << "]" << std::endl;
1007 #endif
1008
1009   bool isStartPoint = !aStartShapePoint.get() || aStartArcPoint->isEqual(aStartShapePoint);
1010   bool isLastPoint = !aLastShapePoint.get() || aLastArcPoint->isEqual(aLastShapePoint);
1011   if (isStartPoint || isLastPoint) {
1012     // result is one arc: changed existing arc
1013     std::string aModifiedAttribute = isStartPoint ? SketchPlugin_Arc::START_ID()
1014                                                   : SketchPlugin_Arc::END_ID();
1015     std::shared_ptr<GeomAPI_Pnt2d> aPoint;
1016     if (aStartShapePoint.get() && aLastShapePoint.get())
1017       aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
1018     else
1019       aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
1020
1021     removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
1022                                 theBaseRefAttributes);
1023
1024     fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
1025
1026     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1027                                (aBaseFeature->attribute(aModifiedAttribute)));
1028   }
1029   else {
1030     // result is two arcs: start arc point - start shape point, last shape point - last arc point
1031     // create second arc
1032     anNewFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint);
1033     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1034                                (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
1035
1036     std::string aModifiedAttribute = SketchPlugin_Arc::END_ID();
1037     theModifiedAttributes.insert(
1038       std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
1039                                    anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
1040
1041     // modify base arc
1042     fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
1043
1044     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1045                                (aBaseFeature->attribute(aModifiedAttribute)));
1046
1047     // equal Radius constraint for arcs
1048     createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
1049                                getFeatureResult(aBaseFeature),
1050                                getFeatureResult(anNewFeature));
1051     // coincident centers constraint
1052     createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
1053                      aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
1054                      anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
1055
1056 #ifdef DEBUG_TRIM
1057     std::cout << "Created arc on points:" << std::endl;
1058     std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
1059                                            aStartShapePoint->y() << "]" << std::endl;
1060 #endif
1061   }
1062   return anNewFeature;
1063 }
1064
1065 FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
1066                                    const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
1067                                    std::set<AttributePoint2DPtr>& thePoints,
1068                  std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
1069 {
1070   // Check the base objects are initialized.
1071   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1072                                         data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
1073   ObjectPtr aBaseObject = aBaseObjectAttr->value();
1074   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
1075
1076   /// points of trim
1077   //AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
1078   //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
1079
1080   /// trim feature
1081   FeaturePtr anNewFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint);
1082   // arc created by trim of circle is always correct, that means that it is not inversed
1083   anNewFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false);
1084
1085   theModifiedAttributes.insert(
1086     std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
1087                    anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
1088
1089   thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1090                              (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
1091   thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1092                              (anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
1093
1094   return anNewFeature;
1095 }
1096
1097 void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr,
1098                                             const AttributePoint2DPtr& theEndPointAttr,
1099                                             std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1100                                             std::shared_ptr<GeomAPI_Pnt2d>& theLastPoint) const
1101 {
1102   if (!theFirstPoint.get() || !theLastPoint.get())
1103     return;
1104
1105   // if first point is closer to last point, swap first and last values
1106   if (theStartPointAttr->pnt()->distance(theFirstPoint) >
1107       theStartPointAttr->pnt()->distance(theLastPoint)) {
1108     std::shared_ptr<GeomAPI_Pnt2d> aTmpPoint = theFirstPoint;
1109     theFirstPoint = theLastPoint;
1110     theLastPoint = aTmpPoint;
1111   }
1112 }
1113
1114 void SketchPlugin_Trim::arrangePointsOnArc(const FeaturePtr& theArc,
1115                                   const AttributePoint2DPtr& theStartPointAttr,
1116                                   const AttributePoint2DPtr& theEndPointAttr,
1117                                   std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1118                                   std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint) const
1119 {
1120   if (!theFirstPoint.get() || !theSecondPoint.get())
1121     return;
1122
1123   static const double anAngleTol = 1.e-12;
1124
1125   std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1126       theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
1127   bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
1128
1129   // collect directions to each point
1130   std::shared_ptr<GeomAPI_Dir2d> aStartDir(
1131       new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1132   std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
1133       new GeomAPI_Dir2d(theFirstPoint->xy()->decreased(aCenter->xy())));
1134   std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
1135       new GeomAPI_Dir2d(theSecondPoint->xy()->decreased(aCenter->xy())));
1136
1137   // sort points by their angular values
1138   double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
1139   double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
1140   double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
1141   if (fabs(aFirstPtAngle) > anAngleTol && isReversed == (aFirstPtAngle > 0.))
1142     aFirstPtAngle += aPeriod;
1143   if (fabs(aSecondPtAngle) > anAngleTol && isReversed == (aSecondPtAngle > 0.))
1144     aSecondPtAngle += aPeriod;
1145
1146   if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
1147     std::shared_ptr<GeomAPI_Pnt2d> aTmpPoint = theFirstPoint;
1148     theFirstPoint = theSecondPoint;
1149     theSecondPoint = aTmpPoint;
1150   }
1151 }
1152
1153 void SketchPlugin_Trim::fillPointAttribute(const AttributePtr& theModifiedAttribute,
1154                                            const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
1155 {
1156   std::string anAttributeType = theModifiedAttribute->attributeType();
1157   if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1158     AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1159                                               theModifiedAttribute);
1160     aModifiedAttribute->setValue(thePoint);
1161
1162 #ifdef DEBUG_TRIM
1163     FeaturePtr aFeature = ModelAPI_Feature::feature(theModifiedAttribute->owner());
1164     std::cout << "<fillPointAttribute[" << aFeature->data()->name() << ": " <<
1165       theModifiedAttribute->id() <<
1166       "]> => Pnt2d - [" << thePoint->x() << ", " << thePoint->y() << "]" << std::endl;
1167 #endif
1168   }
1169 }
1170
1171
1172 void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute,
1173                                       const AttributePtr& theSourceAttribute)
1174 {
1175   std::string anAttributeType = theModifiedAttribute->attributeType();
1176   if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1177     AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1178                                               theModifiedAttribute);
1179     AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1180                                               theSourceAttribute);
1181
1182     if (aModifiedAttribute.get() && aSourceAttribute.get())
1183       aModifiedAttribute->setValue(aSourceAttribute->pnt());
1184   }
1185   else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) {
1186     AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1187                                               theModifiedAttribute);
1188     AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1189                                               theSourceAttribute);
1190
1191     if (aModifiedAttribute.get() && aSourceAttribute.get())
1192       aModifiedAttribute->setValue(aSourceAttribute->value());
1193   }
1194   else if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
1195     AttributeRefAttrPtr aRefAttributeToFill = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1196                                                                              theModifiedAttribute);
1197     AttributeRefAttrPtr aSourceRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1198                                          theSourceAttribute);
1199     if (!aSourceRefAttr.get())
1200       aRefAttributeToFill->setAttr(theSourceAttribute);
1201     else {
1202       if (aSourceRefAttr->isObject())
1203         aRefAttributeToFill->setObject(aSourceRefAttr->object());
1204       else
1205         aRefAttributeToFill->setAttr(aSourceRefAttr->attr());
1206     }
1207   }
1208 }
1209
1210 FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature,
1211                                         const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1212                                         const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1213 {
1214 #ifdef DEBUG_TRIM
1215   std::cout << "---- createLineFeature ---" << std::endl;
1216 #endif
1217
1218   FeaturePtr aFeature;
1219   SketchPlugin_Sketch* aSketch = sketch();
1220   if (!aSketch || !theBaseFeature.get())
1221     return aFeature;
1222
1223   aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
1224
1225   fillPointAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPoint);
1226   fillPointAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPoint);
1227
1228   fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
1229                 theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
1230
1231   aFeature->execute(); // to obtain result
1232
1233 #ifdef DEBUG_TRIM
1234   std::cout << "---- createLineFeature:end ---" << std::endl;
1235 #endif
1236
1237   return aFeature;
1238 }
1239
1240 FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature,
1241                                                const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
1242                                                const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
1243 {
1244   FeaturePtr aFeature;
1245   SketchPlugin_Sketch* aSketch = sketch();
1246   if (!aSketch || !theBaseFeature.get())
1247     return aFeature;
1248
1249   std::string aCenterAttributeId;
1250   if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
1251     aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
1252   else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
1253     aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
1254
1255   if (aCenterAttributeId.empty())
1256     return aFeature;
1257
1258 #ifdef DEBUG_TRIM
1259   std::cout << "---- createArcFeature ---" << std::endl;
1260 #endif
1261
1262   aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
1263   // update fillet arc: make the arc correct for sure, so, it is not needed to process
1264   // the "attribute updated"
1265   // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1266   bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
1267
1268   fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
1269                 theBaseFeature->attribute(aCenterAttributeId));
1270   fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPoint);
1271   fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPoint);
1272
1273   fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
1274                 theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
1275
1276   /// fill referersed state of created arc as it is on the base arc
1277   if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
1278     bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
1279     aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed);
1280   }
1281   aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
1282   aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
1283
1284   #ifdef DEBUG_TRIM
1285   std::cout << "---- createArcFeature:end ---" << std::endl;
1286   #endif
1287
1288   return aFeature;
1289 }
1290
1291 FeaturePtr SketchPlugin_Trim::createConstraint(const std::string& theConstraintId,
1292                                                const AttributePtr& theFirstAttribute,
1293                                                const AttributePtr& theSecondAttribute)
1294 {
1295   FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1296   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1297                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1298   aRefAttr->setAttr(theFirstAttribute);
1299
1300   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1301                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1302   aRefAttr->setAttr(theSecondAttribute);
1303
1304 #ifdef DEBUG_TRIM
1305   std::cout << "<createConstraint to attribute> :"
1306             << "first attribute - " << theFirstAttribute->id()
1307             << "second attribute - " << theSecondAttribute->id()
1308             << std::endl;
1309 #endif
1310
1311   return aConstraint;
1312 }
1313
1314 FeaturePtr SketchPlugin_Trim::createConstraintToObject(const std::string& theConstraintId,
1315                                                const AttributePtr& theFirstAttribute,
1316                                                const ObjectPtr& theSecondObject)
1317 {
1318   FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1319   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1320                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1321   aRefAttr->setAttr(theFirstAttribute);
1322
1323   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1324                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1325   aRefAttr->setObject(theSecondObject);
1326
1327 #ifdef DEBUG_TRIM
1328   std::cout << "<createConstraint to attribute> :"
1329             << "first attribute - " << theFirstAttribute->id()
1330             << "second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
1331             << std::endl;
1332 #endif
1333
1334   return aConstraint;
1335 }
1336
1337 FeaturePtr SketchPlugin_Trim::createConstraintForObjects(
1338                                                     const std::string& theConstraintId,
1339                                                     const ObjectPtr& theFirstObject,
1340                                                     const ObjectPtr& theSecondObject)
1341 {
1342   FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1343   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1344                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1345   aRefAttr->setObject(theFirstObject);
1346
1347   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1348                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1349   aRefAttr->setObject(theSecondObject);
1350
1351   return aConstraint;
1352 }
1353
1354 std::shared_ptr<ModelAPI_Result> SketchPlugin_Trim::getFeatureResult(
1355                                     const std::shared_ptr<ModelAPI_Feature>& theFeature)
1356 {
1357   std::shared_ptr<ModelAPI_Result> aResult;
1358
1359   std::string aFeatureKind = theFeature->getKind();
1360   if (aFeatureKind == SketchPlugin_Line::ID())
1361     aResult = theFeature->firstResult();
1362   else if (aFeatureKind == SketchPlugin_Arc::ID())
1363     aResult = theFeature->lastResult();
1364   else if (aFeatureKind == SketchPlugin_Circle::ID())
1365     aResult = theFeature->lastResult();
1366
1367   return aResult;
1368 }
1369
1370 //********************************************************************
1371 void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject,
1372                 const ObjectPtr& theSketch,
1373                 std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
1374                 std::map<ObjectPtr, PointToRefsMap>& theObjectToPoints)
1375 {
1376   PointToRefsMap aPointsInfo;
1377
1378   std::set<std::shared_ptr<GeomAPI_Shape> > aShapes;
1379   std::map<std::shared_ptr<GeomAPI_Pnt>,
1380                            std::list< AttributePoint2DPtr > > aPointToAttributes;
1381   std::map<std::shared_ptr<GeomAPI_Pnt>,
1382                            std::list< ObjectPtr > > aPointToObjects;
1383
1384   std::set<AttributePoint2DPtr > aRefAttributes;
1385   // current feature
1386   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1387   std::set<ResultPtr> anEdgeShapes;
1388   // edges on feature
1389   ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
1390   if (!anEdgeShapes.empty()) {
1391     GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
1392
1393     // coincidences to the feature
1394     ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
1395                          aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
1396     // layed on feature coincidences to divide it on several shapes
1397     //SketchPlugin_Sketch* aSketch = sketch();
1398     std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
1399     std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
1400         aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
1401     std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1402         aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
1403     std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
1404         aData->attribute(SketchPlugin_Sketch::NORM_ID()));
1405     std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
1406
1407     ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
1408                                                 aX->dir(), aY, aPointsInfo);
1409
1410     std::list<FeaturePtr> aFeatures;
1411     CompositeFeaturePtr aSketchComposite =
1412                          std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theSketch);
1413     for (int i = 0; i < aSketchComposite->numberOfSubs(); i++) {
1414       FeaturePtr aFeature = aSketchComposite->subFeature(i);
1415       if (aFeature.get())
1416         aFeatures.push_back(aFeature);
1417     }
1418     ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPointsInfo);
1419
1420     GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPointsInfo, aShapes);
1421   }
1422   theObjectToPoints[theObject] = aPointsInfo;
1423   theCashedShapes[theObject] = aShapes;
1424 }