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