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