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