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