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