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