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