]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_Split.cpp
Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Split.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
18 //
19
20 #include "SketchPlugin_Split.h"
21
22 #include <Events_Message.h>
23
24 #include <GeomAPI_Dir2d.h>
25 #include <GeomAPI_Edge.h>
26 #include <GeomAPI_Pnt2d.h>
27 #include <GeomAPI_XY.h>
28 #include <GeomDataAPI_Point2D.h>
29 #include <GeomAlgoAPI_ShapeTools.h>
30 #include <GeomAlgoAPI_CompoundBuilder.h>
31
32 #include <ModelAPI_AttributeBoolean.h>
33 #include <ModelAPI_AttributeDouble.h>
34 #include <ModelAPI_AttributeRefAttr.h>
35 #include <ModelAPI_AttributeReference.h>
36 #include <ModelAPI_AttributeString.h>
37 #include <ModelAPI_Events.h>
38 #include <ModelAPI_Validator.h>
39 #include <ModelAPI_Session.h>
40 #include <ModelAPI_Tools.h>
41
42 #include <ModelGeomAlgo_Shape.h>
43
44 #include <SketchPlugin_Arc.h>
45 #include <SketchPlugin_Circle.h>
46 #include <SketchPlugin_ConstraintCoincidence.h>
47 #include <SketchPlugin_ConstraintEqual.h>
48 #include <SketchPlugin_ConstraintLength.h>
49 #include <SketchPlugin_ConstraintMiddle.h>
50 #include <SketchPlugin_ConstraintMirror.h>
51 #include <SketchPlugin_ConstraintParallel.h>
52 #include <SketchPlugin_ConstraintTangent.h>
53 #include <SketchPlugin_Line.h>
54 #include <SketchPlugin_MultiRotation.h>
55 #include <SketchPlugin_MultiTranslation.h>
56 #include <SketchPlugin_Point.h>
57
58 #include <ModelGeomAlgo_Point2D.h>
59 #include <ModelAPI_EventReentrantMessage.h>
60 #include <Events_Loop.h>
61
62 #include <cmath>
63
64 //#define CREATE_CONSTRAINTS
65
66 //#define DEBUG_SPLIT
67 #ifdef DEBUG_SPLIT
68 #include <iostream>
69 #endif
70
71 static const double PI = 3.141592653589793238463;
72
73 SketchPlugin_Split::SketchPlugin_Split()
74 {
75 }
76
77 void SketchPlugin_Split::initAttributes()
78 {
79   data()->addAttribute(SELECTED_OBJECT(), ModelAPI_AttributeReference::typeId());
80   data()->addAttribute(SELECTED_POINT(), GeomDataAPI_Point2D::typeId());
81
82   data()->addAttribute(PREVIEW_POINT(), GeomDataAPI_Point2D::typeId());
83   data()->addAttribute(PREVIEW_OBJECT(), ModelAPI_AttributeReference::typeId());
84
85   data()->attribute(PREVIEW_POINT())->setIsArgument(false);
86   data()->attribute(SELECTED_POINT())->setIsArgument(false);
87   data()->attribute(PREVIEW_OBJECT())->setIsArgument(false);
88
89   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT());
90   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT());
91
92   // TODO: remove
93   //data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeReference::typeId());
94   //data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
95   //data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
96 }
97
98 void SketchPlugin_Split::execute()
99 {
100   std::shared_ptr<ModelAPI_Data> aData = data();
101
102   // Check the base objects are initialized.
103   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
104                                                            data()->attribute(SELECTED_OBJECT()));
105   //ObjectPtr aBaseObject = anObjectAttr->value();
106   //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
107   //                                          aData->attribute(SketchPlugin_Constraint::VALUE()));
108   if(!aBaseObjectAttr->isInitialized()) {
109     setError("Error: Base object is not initialized.");
110     return;
111   }
112   ObjectPtr aBaseObject = aBaseObjectAttr->value();
113   AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
114   //  getPointOfRefAttr(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
115   AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
116   //  getPointOfRefAttr(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
117   if (!aFirstPointAttrOfSplit.get() || !aFirstPointAttrOfSplit->isInitialized() ||
118       !aSecondPointAttrOfSplit.get() || !aSecondPointAttrOfSplit->isInitialized()) {
119     setError("Error: Sub-shape is not initialized.");
120     return;
121   }
122
123   /// Remove reference of this feature to feature used in preview, it is not necessary anymore
124   /// as trim will be removed after execute
125   AttributeReferencePtr aPreviewObjectAttr =
126                      std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
127                      data()->attribute(PREVIEW_OBJECT()));
128
129   ObjectPtr aPreviewObject = aPreviewObjectAttr->value();
130   AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
131                                            data()->attribute(PREVIEW_POINT()));
132   std::shared_ptr<GeomAPI_Pnt2d> aPreviewPnt2d = aPoint->pnt();
133   // nullify pointer of preview attribute
134   aPreviewObjectAttr->setValue(ResultPtr());
135   bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject;
136
137   // Wait all constraints being created, then send update events
138   static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
139   bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
140   if (isUpdateFlushed)
141     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
142
143   // Find feature constraints
144   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
145   ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
146   std::set<FeaturePtr> aFeaturesToDelete, aFeaturesToUpdate;
147
148   //std::map<FeaturePtr, IdToPointPair> aTangentFeatures;
149   std::map<FeaturePtr, IdToPointPair> aCoincidenceToFeature;
150   getConstraints(aFeaturesToDelete, aFeaturesToUpdate, /*aTangentFeatures, */
151                  aCoincidenceToFeature);
152
153   std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
154   std::list<AttributePtr> aRefsToFeature;
155   getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature);
156
157   std::map<AttributePtr, AttributePtr> aBasePointModifiedAttributes;
158
159 #ifdef DEBUG_SPLIT
160   std::cout << std::endl;
161   std::cout << "SketchPlugin_Split::execute()" << std::endl;
162   std::cout << std::endl;
163
164   SketchPlugin_Sketch* aSketch = sketch();
165   std::cout << "SKETCH FEATURES (before split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
166   for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
167     std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
168   }
169
170   std::cout << std::endl;
171   std::cout << "---- IN PARAMETERS ----" << std::endl;
172   std::cout << "Base feature:" << getFeatureInfo(aBaseFeature) << std::endl;
173   std::cout << std::endl;
174
175   if (!aCoincidenceToFeature.empty()) {
176     std::cout << "Coincidences to base feature[" <<
177       aCoincidenceToFeature.size() << "]: " << std::endl;
178     std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aCoincidenceToFeature.begin(),
179                                                         aLast = aCoincidenceToFeature.end();
180     for (int i = 1; anIt != aLast; anIt++, i++) {
181       FeaturePtr aFeature = (*anIt).first;
182       std::string anAttributeId = (*anIt).second.first;
183       std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
184
185       std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
186       std::cout <<     " -Attribute to correct:" << anAttributeId << std::endl;
187       std::cout <<     " -Point attribute:" <<
188         ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
189     }
190   }
191
192   std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
193     aRefIt = aBaseRefAttributes.begin(), aRefLast = aBaseRefAttributes.end();
194   std::cout << std::endl << "References to attributes of base feature [" <<
195     aBaseRefAttributes.size() << "]" << std::endl;
196   for (; aRefIt != aRefLast; aRefIt++) {
197     AttributePtr aBaseAttr = aRefIt->first;
198     std::list<AttributePtr> aRefAttributes = aRefIt->second;
199     std::string aRefsInfo;
200     std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
201                                             aRefAttrLast = aRefAttributes.end();
202     for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
203       if (!aRefsInfo.empty())
204         aRefsInfo.append(",");
205       AttributePtr aRAttr = *aRefAttrIt;
206       aRefsInfo.append(aRAttr->id());
207       FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
208       aRefsInfo.append("(" + aRFeature->name() + ") ");
209     }
210     std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
211       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
212     std::cout << aPointAttr->id().c_str() <<
213       ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
214   }
215   std::cout << std::endl;
216   std::cout << std::endl << "References to base feature [" <<
217     aRefsToFeature.size() << "]" << std::endl;
218   std::list<AttributePtr>::const_iterator aRefAttrIt = aRefsToFeature.begin(),
219                                           aRefAttrLast = aRefsToFeature.end();
220   std::string aRefsInfo;
221   for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
222     if (!aRefsInfo.empty())
223       aRefsInfo.append(",");
224     AttributePtr aRAttr = *aRefAttrIt;
225     aRefsInfo.append(aRAttr->id());
226     FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
227     aRefsInfo.append("(" + aRFeature->name() + ") ");
228   }
229   std::cout << "[" << aRefsToFeature.size() << "] " << aRefsInfo << std::endl;
230
231
232   std::cout << std::endl;
233   std::cout << "---- SPLIT ----" << std::endl;
234   std::cout << std::endl;
235 #endif
236
237   std::string aFeatureKind = aBaseFeature->getKind();
238   FeaturePtr aSplitFeature, anAfterFeature;
239   std::set<AttributePoint2DPtr> aFurtherCoincidences;
240   std::set<FeaturePtr> aCreatedFeatures;
241   std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
242   FeaturePtr aReplacingFeature, aNewFeature;
243   if (aFeatureKind == SketchPlugin_Line::ID())
244     aNewFeature = splitLine(aSplitFeature, aBaseFeature, anAfterFeature,
245                             aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
246   else if (aFeatureKind == SketchPlugin_Arc::ID())
247     aNewFeature = splitArc(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences,
248                            aCreatedFeatures, aModifiedAttributes);
249   if (aFeatureKind == SketchPlugin_Circle::ID()) {
250     FeaturePtr aCircleFeature = aBaseFeature;
251     aReplacingFeature = splitCircle(aSplitFeature, aBaseFeature, anAfterFeature,
252                                     aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
253
254     updateRefFeatureConstraints(getFeatureResult(aBaseFeature), aRefsToFeature);
255
256     AttributePtr aCenterAttr = aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID());
257     aFeaturesToDelete.insert(aCircleFeature);
258     // as circle is removed, temporary fill this attribute*/
259     aBaseObjectAttr->setObject(ResultPtr());
260   }
261
262 #ifdef DEBUG_SPLIT
263   std::cout << "---- OUT PARAMETERS ----" << std::endl;
264   std::cout << "Base modified feature:" << getFeatureInfo(aBaseFeature) << std::endl;
265   std::cout << "Split feature:" << getFeatureInfo(aSplitFeature) << std::endl;
266   std::cout << "After feature:" << getFeatureInfo(anAfterFeature) << std::endl;
267   std::cout << std::endl;
268
269   std::cout << "Created features by split:[" << aCreatedFeatures.size() << "]" << std::endl;
270   std::set<FeaturePtr>::const_iterator aFIt = aCreatedFeatures.begin(),
271                                        aFLast = aCreatedFeatures.end();
272   for (; aFIt != aFLast; aFIt++) {
273     std::cout << getFeatureInfo(*aFIt) << std::endl;
274   }
275   std::cout << std::endl;
276
277   std::cout << "Attributes for further Coincidences:" << std::endl;
278   std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
279                                                 aLast = aFurtherCoincidences.end();
280   for (; anIt != aLast; anIt++) {
281     AttributePtr anAttribute = *anIt;
282     FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
283     std::cout << ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute)
284               << " [" << getFeatureInfo(aFeature, false) << "]" << std::endl;
285   }
286
287   std::cout << "Modifed attributes (constraints to attributes are moved here):" << std::endl;
288   std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
289     aPIt = aModifiedAttributes.begin(), aPLast = aModifiedAttributes.end();
290   std::string aResInfo;
291   for (; aPIt != aPLast; aPIt++) {
292     if (!aResInfo.empty())
293       aResInfo += "\n";
294
295     std::pair<AttributePtr, AttributePtr> aPair = *aPIt;
296
297     AttributePtr anAttr = aPair.first;
298     aResInfo.append(anAttr->id());
299     FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->owner());
300     aResInfo.append("(" + aFeature->name() + ") ");
301
302     aResInfo.append("  - is modified to -  ");
303
304     anAttr = aPair.second;
305     aResInfo.append(anAttr->id());
306     aFeature = ModelAPI_Feature::feature(anAttr->owner());
307     aResInfo.append("(" + aFeature->name() + ") ");
308   }
309   std::cout << aResInfo << std::endl;
310 #endif
311
312   std::set<ResultPtr> aFeatureResults;
313   aFeatureResults.insert(getFeatureResult(aBaseFeature));
314   if (anAfterFeature.get() && anAfterFeature != aBaseFeature)
315     aFeatureResults.insert(getFeatureResult(anAfterFeature));
316
317   // coincidence to feature
318   updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences,
319                                         aFeatureResults, aSplitFeature);
320
321   updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
322
323   // delete constraints
324 #ifdef DEBUG_SPLIT
325   std::cout << "remove features and references:" << std::endl;
326   std::set<FeaturePtr>::const_iterator aDIt = aFeaturesToDelete.begin(),
327                                        aDLast = aFeaturesToDelete.end();
328   for (; aDIt != aDLast; aDIt++) {
329     std::cout << getFeatureInfo(*aDIt, false) << std::endl;
330     std::cout << std::endl;
331   }
332 #endif
333   ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
334   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
335
336 #ifdef DEBUG_SPLIT
337   std::cout << "update features after split:" << std::endl;
338   std::set<FeaturePtr>::const_iterator anUIt = aFeaturesToUpdate.begin(),
339                                        anULast = aFeaturesToUpdate.end();
340   for (; anUIt != anULast; anUIt++) {
341     std::cout << getFeatureInfo(*anUIt, false) << std::endl;
342     std::cout << std::endl;
343   }
344 #endif
345   updateFeaturesAfterSplit(aFeaturesToUpdate);
346
347   // Send events to update the sub-features by the solver.
348   if(isUpdateFlushed) {
349     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
350   }
351
352     if (anIsEqualPreviewAndSelected) {
353     // equal preview and selected objects
354     // nothing to do if the preview and selected objects are different
355     ResultPtr aReplacingResult;
356     if (aReplacingFeature.get()) {
357       aReplacingFeature->execute(); // need it to obtain result
358       aReplacingResult = getFeatureResult(aReplacingFeature);
359     }
360     if (aReplacingResult.get()) { // base object was removed
361       aPreviewObject = aReplacingResult;
362       //aMessage->setSelectedObject(aReplacingResult);
363
364       //GeomShapePtr aSelectedShape = aReplacingResult->shape();
365       //std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
366       //                                                          aPreviewPnt2d->y());
367       //std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
368       //if (ModelGeomAlgo_Point2D::isPointOnEdge(aSelectedShape, aPreviewPnt, aProjectedPoint)) {
369         //bool aValue = true;
370       //}
371       //aBaseShape = aShape;
372
373 #ifdef DEBUG_TRIM_METHODS
374       if (!aSelectedShape.get())
375         std::cout << "Set empty selected object" << std::endl;
376       else
377         std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
378 #endif
379       //bool aValue = true;
380     }
381     else {
382       aPreviewObject = ObjectPtr();
383
384       aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
385       aBaseObject = getFeatureResult(aBaseFeature);
386       std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
387                                                                 aPreviewPnt2d->y());
388       ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
389       if (aBaseResult) {
390         GeomShapePtr aShape = aBaseResult->shape();
391         std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
392         if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
393           aPreviewObject = aBaseResult;
394       }
395       if (!aPreviewObject.get() && aNewFeature.get()) {
396         ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature);
397         if (aNewFeatureResult.get()) {
398           GeomShapePtr aShape = aNewFeatureResult->shape();
399           std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
400           if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint))
401             aPreviewObject = aNewFeatureResult;
402         }
403       }
404     }
405   }
406   if (aPreviewObject.get()) {
407     std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
408       <ModelAPI_EventReentrantMessage>(new ModelAPI_EventReentrantMessage(
409                                            ModelAPI_EventReentrantMessage::eventId(), this));
410     aMessage->setSelectedObject(aPreviewObject);
411     Events_Loop::loop()->send(aMessage);
412   }
413
414
415 #ifdef DEBUG_SPLIT
416   std::cout << "SKETCH FEATURES (after split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
417   for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
418     std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
419   }
420 #endif
421 }
422
423 std::string SketchPlugin_Split::processEvent(const std::shared_ptr<Events_Message>& theMessage)
424 {
425 #ifdef DEBUG_TRIM_METHODS
426   std::cout << "SketchPlugin_Trim::processEvent:" << data()->name() << std::endl;
427 #endif
428   std::string aFilledAttributeName;
429
430   std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage =
431         std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
432   if (aMessage.get()) {
433     ObjectPtr anObject = aMessage->selectedObject();
434     std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
435
436     if (anObject.get() && aPoint.get()) {
437       //if (myCashedShapes.find(anObject) == myCashedShapes.end())
438       //  fillObjectShapes(anObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
439       if (myCashedShapes.find(anObject) == myCashedShapes.end())
440         fillObjectShapes(anObject, sketch()->data()->owner());
441       const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
442       if (aShapes.size() > 1) {
443         std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
444                               std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
445                               data()->attribute(SELECTED_OBJECT()));
446         std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
447                               std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
448                               data()->attribute(PREVIEW_OBJECT()));
449         aRefSelectedAttr->setValue(anObject);
450         aRefPreviewAttr->setValue(anObject);
451
452         std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
453                               std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
454                               data()->attribute(SELECTED_POINT()));
455         std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
456                               std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
457                               data()->attribute(PREVIEW_POINT()));
458         aPointSelectedAttr->setValue(aPoint);
459         aPointPreviewAttr->setValue(aPoint);
460
461         Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
462
463         GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
464   #ifdef DEBUG_TRIM_METHODS
465         if (!aSelectedShape.get())
466           std::cout << "Set empty selected object" << std::endl;
467         else
468           std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl;
469   #endif
470         aFilledAttributeName = SELECTED_OBJECT();
471       }
472     }
473   }
474   return aFilledAttributeName;
475 }
476
477 AISObjectPtr SketchPlugin_Split::getAISObject(AISObjectPtr thePrevious)
478 {
479   /*AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
480                                            data()->attribute(SketchPlugin_Constraint::VALUE()));
481   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
482
483   AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(
484                                         data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
485   AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(
486                                         data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
487
488   if (aBaseObjectAttr->isInitialized() && aBaseFeature.get() &&
489       aFirstPointAttrOfSplit->isInitialized() &&
490       aSecondPointAttrOfSplit->isInitialized()) {
491
492     ResultPtr aResult = getFeatureResult(aBaseFeature);
493     GeomShapePtr aBaseShape = aResult->shape();
494     std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
495
496     std::shared_ptr<GeomAPI_Pnt2d> aStartPnt2d = aFirstPointAttrOfSplit->pnt();
497     std::shared_ptr<GeomAPI_Pnt> aStartPoint = sketch()->to3D(aStartPnt2d->x(), aStartPnt2d->y());
498     aPoints.push_back(aStartPoint);
499
500     std::shared_ptr<GeomAPI_Pnt2d> aSecondPnt2d = aSecondPointAttrOfSplit->pnt();
501     std::shared_ptr<GeomAPI_Pnt> aSecondPoint =
502       sketch()->to3D(aSecondPnt2d->x(), aSecondPnt2d->y());
503     aPoints.push_back(aSecondPoint);
504
505     std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
506
507     GeomAlgoAPI_ShapeTools::splitShape_p(aBaseShape, aPoints, aSplitShapes);
508     std::shared_ptr<GeomAPI_Shape> aShape =
509       GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
510
511     AISObjectPtr anAIS = thePrevious;
512     if (aShape) {
513       if (!anAIS)
514         anAIS = AISObjectPtr(new GeomAPI_AISObject);
515       anAIS->createShape(aShape);
516       std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
517              aBaseFeature->data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID());
518
519       bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value();
520
521       std::vector<int> aColor;
522       double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
523       int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
524       if (isConstruction) {
525         aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
526         aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY();
527         aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY();
528       }
529       else {
530         aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
531       }
532       anAIS->setColor(aColor[0], aColor[1], aColor[2]);
533       anAIS->setWidth(aWidth + 1);
534       anAIS->setLineStyle(aLineStyle);
535     }
536     return anAIS;
537   }
538   return AISObjectPtr();*/
539 #ifdef DEBUG_TRIM_METHODS
540   std::cout << "SketchPlugin_Trim::getAISObject: " << data()->name() << std::endl;
541 #endif
542
543   AISObjectPtr anAIS = thePrevious;
544
545   std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
546   GeomShapePtr aPreviewShape = getSubShape(PREVIEW_OBJECT(), PREVIEW_POINT());
547   if (aPreviewShape.get())
548     aShapes.push_back(aPreviewShape);
549   GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
550   if (aSelectedShape.get())
551     aShapes.push_back(aSelectedShape);
552
553   if (aShapes.empty())
554     return AISObjectPtr();
555
556   GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
557   if (!aBaseShape.get())
558     return AISObjectPtr();
559
560   if (aBaseShape.get()) {
561     if (!anAIS)
562       anAIS = AISObjectPtr(new GeomAPI_AISObject);
563     anAIS->createShape(aBaseShape);
564
565     std::vector<int> aColor;
566     aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
567     double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
568     int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
569     anAIS->setColor(aColor[0], aColor[1], aColor[2]);
570     // width when there is not base object should be extened in several points
571     // in order to see this preview over highlight
572     anAIS->setWidth(aWidth+4);
573     anAIS->setLineStyle(aLineStyle);
574   }
575   else
576     anAIS = AISObjectPtr();
577   return anAIS;
578 }
579
580 //********************************************************************
581 void SketchPlugin_Split::fillObjectShapes(const ObjectPtr& theObject,
582                                           const ObjectPtr& theSketch)
583 {
584   std::set<std::shared_ptr<GeomAPI_Shape> > aShapes;
585   std::map<std::shared_ptr<GeomDataAPI_Point2D>, std::shared_ptr<GeomAPI_Pnt> > aPointToAttributes;
586   std::set<std::shared_ptr<GeomDataAPI_Point2D> > aRefAttributes;
587   // current feature
588   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
589   // edges on feature
590   std::set<ResultPtr> anEdgeResults;
591   ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeResults);
592   if (!anEdgeResults.empty()) {
593     GeomShapePtr aFeatureShape = (*anEdgeResults.begin())->shape();
594
595     // coincidences to the feature
596     ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
597                          aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
598     // layed on feature coincidences to divide it on several shapes
599     std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
600     std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
601         aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
602     std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
603         aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
604     std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
605         aData->attribute(SketchPlugin_Sketch::NORM_ID()));
606     std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
607     std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
608     ModelGeomAlgo_Point2D::getPointsInsideShape_p(aFeatureShape, aRefAttributes, aC->pnt(),
609                                                 aX->dir(), aY, aPoints, aPointToAttributes);
610
611     GeomAlgoAPI_ShapeTools::splitShape_p(aFeatureShape, aPoints, aShapes);
612   }
613   myCashedShapes[theObject] = aShapes;
614   myCashedReferences[theObject] = aPointToAttributes;
615 }
616
617 GeomShapePtr SketchPlugin_Split::getSubShape(const std::string& theObjectAttributeId,
618                                              const std::string& thePointAttributeId)
619 {
620   GeomShapePtr aBaseShape;
621
622   AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
623                                                        data()->attribute(theObjectAttributeId));
624   ObjectPtr aBaseObject = anObjectAttr->value();
625   if (!aBaseObject.get())
626     return aBaseShape;
627
628   // point on feature
629   AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
630                                            data()->attribute(thePointAttributeId));
631   std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
632   std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
633                                                                anAttributePnt2d->y());
634
635 #ifdef TRIM_SHAPE
636   if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
637     fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
638
639   const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
640   if (!aShapes.empty()) {
641     std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
642     for (; anIt != aLast; anIt++) {
643       GeomShapePtr aShape = *anIt;
644       std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
645       if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, anAttributePnt, aProjectedPoint))
646         aBaseShape = aShape;
647     }
648   }
649 #else
650   if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
651     fillObjectShapes(aBaseObject, sketch()->data()->owner());
652
653   std::shared_ptr<GeomAPI_Pnt> aStartPoint;
654   std::shared_ptr<GeomAPI_Pnt> aSecondPoint;
655   const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
656   std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
657   for (; anIt != aLast; anIt++) {
658     GeomShapePtr aCurrentShape = *anIt;
659     std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
660     if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) {
661       if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) {
662         std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aCurrentShape));
663         aStartPoint = anEdge->firstPoint();
664         aSecondPoint = anEdge->lastPoint();
665       }
666       break;
667     }
668   }
669
670   if (!aStartPoint.get() || !aSecondPoint.get())
671     return aBaseShape;
672
673   //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
674   //                                         data()->attribute(SketchPlugin_Constraint::VALUE()));
675   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject/*aBaseObjectAttr->value()*/);
676
677   //AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(
678   //                                      data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
679   //AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(
680   //                                      data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
681   if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) {
682       //aFirstPointAttrOfSplit->isInitialized() &&
683       //aSecondPointAttrOfSplit->isInitialized()) {
684     ResultPtr aResult = getFeatureResult(aBaseFeature);
685     GeomShapePtr aResultShape = aResult->shape();
686     std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
687
688     //std::shared_ptr<GeomAPI_Pnt2d> aStartPnt2d = aFirstPointAttrOfSplit->pnt();
689     //std::shared_ptr<GeomAPI_Pnt> aStartPoint = sketch()->to3D(aStartPnt2d->x(), aStartPnt2d->y());
690     aPoints.push_back(aStartPoint);
691
692     //std::shared_ptr<GeomAPI_Pnt2d> aSecondPnt2d = aSecondPointAttrOfSplit->pnt();
693     //std::shared_ptr<GeomAPI_Pnt> aSecondPoint =
694     //  sketch()->to3D(aSecondPnt2d->x(), aSecondPnt2d->y());
695     aPoints.push_back(aSecondPoint);
696
697     std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
698     GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes);
699     aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
700 #endif
701   }
702   return aBaseShape;
703 }
704
705 std::shared_ptr<GeomDataAPI_Point2D> SketchPlugin_Split::getPointOfRefAttr(
706                                                       const AttributePtr& theAttribute)
707 {
708   AttributePoint2DPtr aPointAttribute;
709
710   if (theAttribute->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
711     AttributeRefAttrPtr aRefAttr =
712       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
713     if (aRefAttr.get() && aRefAttr->isInitialized()) {
714       AttributePtr anAttribute = aRefAttr->attr();
715       if (anAttribute.get() && anAttribute->attributeType() == GeomDataAPI_Point2D::typeId())
716         aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
717     }
718   }
719   return aPointAttribute;
720 }
721
722 void SketchPlugin_Split::getFeaturePoints(const FeaturePtr& theFeature,
723                                                     AttributePoint2DPtr& theStartPointAttr,
724                                                     AttributePoint2DPtr& theEndPointAttr)
725 {
726   std::string aFeatureKind = theFeature->getKind();
727   std::string aStartAttributeName, anEndAttributeName;
728   if (aFeatureKind == SketchPlugin_Line::ID()) {
729     aStartAttributeName = SketchPlugin_Line::START_ID();
730     anEndAttributeName = SketchPlugin_Line::END_ID();
731   }
732   else if (aFeatureKind == SketchPlugin_Arc::ID()) {
733     aStartAttributeName = SketchPlugin_Arc::START_ID();
734     anEndAttributeName = SketchPlugin_Arc::END_ID();
735   }
736   if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
737     theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
738                                          theFeature->attribute(aStartAttributeName));
739     theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
740                                          theFeature->attribute(anEndAttributeName));
741   }
742 }
743
744 void SketchPlugin_Split::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
745                                     std::set<FeaturePtr>& theFeaturesToUpdate,
746                                     std::map<FeaturePtr, IdToPointPair>& theCoincidenceToFeature)
747 {
748   std::shared_ptr<ModelAPI_Data> aData = data();
749
750   // Check the base objects are initialized.
751   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
752                                                            data()->attribute(SELECTED_OBJECT()));
753   //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
754   //                                          aData->attribute(SketchPlugin_Constraint::VALUE()));
755   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
756   ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
757
758   std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
759   std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
760   aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
761
762   std::set<AttributePtr>::const_iterator aIt;
763   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
764     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
765     FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
766     std::string aRefFeatureKind = aRefFeature->getKind();
767     if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
768         aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
769         aRefFeatureKind == SketchPlugin_MultiTranslation::ID() ||
770         aRefFeatureKind == SketchPlugin_ConstraintMiddle::ID())
771       theFeaturesToDelete.insert(aRefFeature);
772     else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID())
773       theFeaturesToUpdate.insert(aRefFeature);
774     else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) {
775       std::string anAttributeToBeModified;
776       AttributePoint2DPtr aCoincidentPoint;
777       AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A());
778       AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B());
779       bool isToFeature = false;
780       if (anAttrA->isObject() || anAttrB->isObject()) { /// coincidence to base feature
781         FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object())
782                                                   : FeaturePtr();
783         isToFeature = aFeature.get() && aFeature == aBaseFeature;
784         anAttributeToBeModified = anAttrA->id();
785         if (!isToFeature) {
786           aFeature = anAttrB->isObject() ? ModelAPI_Feature::feature(anAttrB->object())
787                                          : FeaturePtr();
788           isToFeature = aFeature.get() && aFeature == aBaseFeature;
789           anAttributeToBeModified = anAttrB->id();
790         }
791         if (isToFeature)
792           aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature);
793       }
794       if (!isToFeature) { /// coincidence to point on base feature
795         AttributePtr anAttribute;
796
797         if (!anAttrA->isObject()) {
798           AttributePtr aCurAttribute = anAttrA->attr();
799           if (aCurAttribute.get()) {
800             FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
801             if (aCurFeature.get() && aCurFeature == aBaseFeature) {
802               anAttribute = anAttrB->attr();
803               anAttributeToBeModified = anAttrA->id();
804             }
805           }
806         }
807         if (!anAttribute.get() && !anAttrB->isObject()) {
808           AttributePtr aCurAttribute = anAttrB->attr();
809           if (aCurAttribute.get()) {
810             FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
811             if (aCurFeature.get() && aCurFeature == aBaseFeature) {
812               anAttribute = anAttrA->attr();
813               anAttributeToBeModified = anAttrB->id();
814             }
815           }
816         }
817         if (anAttribute.get())
818           aCoincidentPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
819       }
820       if (aCoincidentPoint.get() && isToFeature)
821         theCoincidenceToFeature[aRefFeature] = std::make_pair(anAttributeToBeModified,
822                                                               aCoincidentPoint);
823     }
824   }
825 }
826
827 void SketchPlugin_Split::getRefAttributes(const FeaturePtr& theFeature,
828                                     std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
829                                     std::list<AttributePtr>& theRefsToFeature)
830 {
831   theRefs.clear();
832
833   std::list<AttributePtr> aPointAttributes =
834     theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
835   std::set<AttributePtr> aPointAttributesSet;
836
837   std::list<AttributePtr>::const_iterator aPIt =
838     aPointAttributes.begin(), aPLast = aPointAttributes.end();
839   for (; aPIt != aPLast; aPIt++)
840     aPointAttributesSet.insert(*aPIt);
841
842   std::set<AttributePtr> aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe();
843   std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
844   aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
845
846   std::set<AttributePtr>::const_iterator aIt;
847   for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
848     AttributePtr anAttr = (*aIt);
849     FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
850     if (anAttrFeature.get() != this &&
851         anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
852       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
853       if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes
854         AttributePtr anAttrInRef = aRefAttr->attr();
855         if (anAttrInRef.get() &&
856             aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
857           if (theRefs.find(anAttrInRef) != theRefs.end())
858             theRefs[anAttrInRef].push_back(aRefAttr);
859           else {
860             std::list<AttributePtr> anAttrList;
861             anAttrList.push_back(aRefAttr);
862             theRefs[anAttrInRef] = anAttrList;
863           }
864         }
865       }
866       else { /// find attributes referenced to feature itself
867         theRefsToFeature.push_back(anAttr);
868       }
869     }
870   }
871 }
872
873 void SketchPlugin_Split::updateCoincidenceConstraintsToFeature(
874       const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
875       const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
876       const std::set<ResultPtr>& theFeatureResults,
877       const FeaturePtr& theSplitFeature)
878 {
879   if (theCoincidenceToFeature.empty())
880     return;
881
882   // we should build coincidence constraints to end of the split feature
883   std::set<std::shared_ptr<GeomDataAPI_Point2D> > aNewCoincidencesToSplitFeature;
884   AttributePoint2DPtr aStartPointAttr, anEndPointAttr;
885   getFeaturePoints(theSplitFeature, aStartPointAttr, anEndPointAttr);
886   if (theFurtherCoincidences.find(aStartPointAttr) == theFurtherCoincidences.end())
887     aNewCoincidencesToSplitFeature.insert(aStartPointAttr);
888   if (theFurtherCoincidences.find(anEndPointAttr) == theFurtherCoincidences.end())
889     aNewCoincidencesToSplitFeature.insert(anEndPointAttr);
890
891   std::map<FeaturePtr, IdToPointPair>::const_iterator aCIt = theCoincidenceToFeature.begin(),
892                                                             aCLast = theCoincidenceToFeature.end();
893 #ifdef DEBUG_SPLIT
894   std::cout << std::endl;
895   std::cout << "Coincidences to feature(modified):"<< std::endl;
896 #endif
897   for (; aCIt != aCLast; aCIt++) {
898     FeaturePtr aCoincFeature = aCIt->first;
899     std::string anAttributeId = aCIt->second.first;
900     AttributePoint2DPtr aCoincPoint = aCIt->second.second;
901     std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
902                                                   aFCLast = theFurtherCoincidences.end();
903     std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aCoincPoint->pnt();
904     AttributePoint2DPtr aFeaturePointAttribute;
905     for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
906       AttributePoint2DPtr aFCAttribute = *aFCIt;
907       if (aCoincPnt->isEqual(aFCAttribute->pnt()))
908         aFeaturePointAttribute = aFCAttribute;
909     }
910     if (aFeaturePointAttribute.get()) {
911       aCoincFeature->refattr(anAttributeId)->setObject(ResultPtr());
912       aCoincFeature->refattr(anAttributeId)->setAttr(aFeaturePointAttribute);
913       // create new coincidences to split feature points
914       std::set<AttributePoint2DPtr>::const_iterator aSFIt = aNewCoincidencesToSplitFeature.begin(),
915                                                     aSFLast = aNewCoincidencesToSplitFeature.end();
916       for (; aSFIt != aSFLast; aSFIt++) {
917         AttributePoint2DPtr aSFAttribute = *aSFIt;
918         if (aCoincPnt->isEqual(aSFAttribute->pnt())) {
919           std::string aSecondAttribute = SketchPlugin_Constraint::ENTITY_A();
920           if (anAttributeId == SketchPlugin_Constraint::ENTITY_A())
921             aSecondAttribute = SketchPlugin_Constraint::ENTITY_B();
922           createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
923                            aSFAttribute, aCoincFeature->refattr(aSecondAttribute)->attr());
924         }
925       }
926     }
927     else {
928       /// find feature by shape intersected the point
929       ResultPtr aResultForCoincidence = *(theFeatureResults.begin());
930
931       if (theFeatureResults.size() > 1) { // try to find point on additional feature
932         ResultPtr anAddtionalResult = *(theFeatureResults.begin()++);
933         GeomShapePtr aShape = anAddtionalResult->shape();
934
935         std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = aCoincPoint->pnt();
936         std::shared_ptr<GeomAPI_Pnt> aPoint = sketch()->to3D(aPnt2d->x(), aPnt2d->y());
937
938         std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
939         if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPoint, aProjectedPoint))
940           aResultForCoincidence = anAddtionalResult;
941       }
942       aCoincFeature->refattr(anAttributeId)->setObject(aResultForCoincidence);
943     }
944 #ifdef DEBUG_SPLIT
945   std::cout << " -" << getFeatureInfo(aCoincFeature) << std::endl;
946 #endif
947   }
948 }
949
950 void SketchPlugin_Split::updateRefFeatureConstraints(
951                                                   const ResultPtr& theFeatureBaseResult,
952                                                   const std::list<AttributePtr>& theRefsToFeature)
953 {
954   std::list<AttributePtr>::const_iterator anIt = theRefsToFeature.begin(),
955                                           aLast = theRefsToFeature.end();
956   for (; anIt != aLast; anIt++) {
957     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
958     if (aRefAttr.get())
959       aRefAttr->setObject(theFeatureBaseResult);
960   }
961 }
962
963 void SketchPlugin_Split::updateRefAttConstraints(
964                     const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
965                     const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
966 {
967 #ifdef DEBUG_SPLIT
968   std::cout << "SketchPlugin_Split::updateRefAttConstraints" << std::endl;
969 #endif
970
971   std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
972     anIt = theModifiedAttributes.begin(),  aLast = theModifiedAttributes.end();
973   for (; anIt != aLast; anIt++) {
974     AttributePtr anAttribute = anIt->first;
975
976     /// not found in references
977     if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
978       continue;
979     std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
980     std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
981                                             aRLast = aRefAttributes.end();
982
983     AttributePtr aNewAttribute = anIt->second;
984     for (; aRefIt != aRLast; aRefIt++) {
985       AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
986       if (aRefAttr.get()) {
987         aRefAttr->setAttr(aNewAttribute);
988 #ifdef DEBUG_SPLIT
989         FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
990         std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
991 #endif
992       }
993     }
994   }
995 }
996
997 FeaturePtr SketchPlugin_Split::splitLine(FeaturePtr& theSplitFeature,
998                                              FeaturePtr& theBaseFeatureModified,
999                                              FeaturePtr& theAfterFeature,
1000                                              std::set<AttributePoint2DPtr>& thePoints,
1001                                              std::set<FeaturePtr>& theCreatedFeatures,
1002                  std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
1003 {
1004   FeaturePtr anNewFeature;
1005
1006   std::set<FeaturePtr> aCreatedFeatures;
1007   FeaturePtr aConstraintFeature;
1008   theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
1009
1010   SketchPlugin_Sketch* aSketch = sketch();
1011   if (!aSketch)
1012     return anNewFeature;
1013
1014   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1015                                                            data()->attribute(SELECTED_OBJECT()));
1016   //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1017   //                                         data()->attribute(SketchPlugin_Constraint::VALUE()));
1018   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
1019   std::string aFeatureKind = aBaseFeature->getKind();
1020   if (aFeatureKind != SketchPlugin_Line::ID())
1021     return anNewFeature;
1022
1023   AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
1024     //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
1025   AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
1026     //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
1027   AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
1028
1029   getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
1030   if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
1031     setError("Error: Feature has no start and end points.");
1032     return anNewFeature;
1033   }
1034
1035   arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase,
1036                       aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
1037
1038 #ifdef DEBUG_SPLIT
1039   std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
1040   std::cout << "Start point: " <<
1041     ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
1042   std::cout << "1st point:   " <<
1043     ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
1044   std::cout << "2nd point:   " <<
1045     ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
1046   std::cout << "End point:   " <<
1047     ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
1048 #endif
1049
1050   /// create a split feature
1051   theSplitFeature =
1052     createLineFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
1053   theCreatedFeatures.insert(theSplitFeature);
1054
1055   // before split feature
1056   if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
1057     theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
1058                                         theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
1059   }
1060   else {
1061     theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
1062     /// move end arc point to start of split
1063   }
1064
1065   // after split feature
1066   if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
1067     FeaturePtr aFeature;
1068     if (!theBaseFeatureModified.get()) {
1069       aFeature = aBaseFeature; ///< use base feature to store all constraints here
1070       fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), aSecondPointAttrOfSplit);
1071       aFeature->execute(); // to update result
1072     }
1073     else {
1074       aFeature = createLineFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
1075       theCreatedFeatures.insert(aFeature);
1076       theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
1077                                              aFeature->attribute(SketchPlugin_Line::END_ID())));
1078       anNewFeature = aFeature;
1079     }
1080     aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
1081                      theSplitFeature->attribute(SketchPlugin_Line::END_ID()),
1082                      aFeature->attribute(SketchPlugin_Line::START_ID()));
1083     theCreatedFeatures.insert(aConstraintFeature);
1084
1085     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1086                                 (aFeature->attribute(SketchPlugin_Line::START_ID())));
1087     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1088                                 (aFeature->attribute(SketchPlugin_Line::END_ID())));
1089
1090     if (!theBaseFeatureModified.get())
1091       theBaseFeatureModified = aFeature;
1092     else
1093       theAfterFeature = aFeature;
1094   }
1095   else {
1096     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1097                                   (theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
1098     theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
1099                                    theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
1100   }
1101   // base split, that is defined before split feature should be changed at end
1102   // (after the after feature creation). Otherwise modified value will be used in after feature
1103   // before split feature
1104   if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
1105     /// move end arc point to start of split
1106     fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
1107                                                     aFirstPointAttrOfSplit);
1108     theBaseFeatureModified->execute(); // to update result
1109     aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
1110                      theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
1111                      theSplitFeature->attribute(SketchPlugin_Line::START_ID()));
1112     theCreatedFeatures.insert(aConstraintFeature);
1113
1114     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1115                              (theBaseFeatureModified->attribute(SketchPlugin_Line::START_ID())));
1116     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1117                                (theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID())));
1118   }
1119   else
1120     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1121                                        (theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
1122
1123 #ifdef CREATE_CONSTRAINTS
1124   // additional constraints between split and base features
1125   aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
1126                                                        getFeatureResult(aBaseFeature),
1127                                                        getFeatureResult(theSplitFeature));
1128   theCreatedFeatures.insert(aConstraintFeature);
1129   if (theAfterFeature.get()) {
1130     aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
1131                                                     getFeatureResult(aBaseFeature),
1132                                                     getFeatureResult(theAfterFeature));
1133     theCreatedFeatures.insert(aConstraintFeature);
1134   }
1135 #endif
1136   return anNewFeature;
1137 }
1138
1139 FeaturePtr SketchPlugin_Split::splitArc(FeaturePtr& theSplitFeature,
1140                                             FeaturePtr& theBaseFeatureModified,
1141                                             FeaturePtr& theAfterFeature,
1142                                             std::set<AttributePoint2DPtr>& thePoints,
1143                                             std::set<FeaturePtr>& theCreatedFeatures,
1144                  std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
1145 {
1146   FeaturePtr anNewFeature;
1147
1148   std::set<FeaturePtr> aCreatedFeatures;
1149   FeaturePtr aConstraintFeature;
1150   theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
1151
1152   SketchPlugin_Sketch* aSketch = sketch();
1153   if (!aSketch)
1154     return anNewFeature;
1155
1156   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1157                                                            data()->attribute(SELECTED_OBJECT()));
1158   //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1159   //                                         data()->attribute(SketchPlugin_Constraint::VALUE()));
1160   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
1161   std::string aFeatureKind = aBaseFeature->getKind();
1162   if (aFeatureKind != SketchPlugin_Arc::ID())
1163     return anNewFeature;
1164
1165   AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
1166     //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
1167   AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
1168     //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
1169   AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
1170   getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
1171   if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
1172     setError("Error: Feature has no start and end points.");
1173     return anNewFeature;
1174   }
1175
1176   arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
1177                      aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
1178 #ifdef DEBUG_SPLIT
1179   std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
1180   std::cout << "Start point: " <<
1181     ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
1182   std::cout << "1st point:   " <<
1183     ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
1184   std::cout << "2nd point:   " <<
1185     ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
1186   std::cout << "End point:   " <<
1187     ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
1188 #endif
1189
1190   /// split feature
1191   theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
1192   theCreatedFeatures.insert(theSplitFeature);
1193
1194   // before split feature
1195   if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
1196     theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
1197                                   theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
1198   }
1199   else {
1200     theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
1201     /// move end arc point to start of split
1202   }
1203
1204   // after split feature
1205   if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
1206     FeaturePtr aFeature;
1207     if (!theBaseFeatureModified.get()) {
1208       aFeature = aBaseFeature; ///< use base feature to store all constraints here
1209       fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
1210       aFeature->execute(); // to update result
1211     }
1212     else {
1213       aFeature = createArcFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
1214       theCreatedFeatures.insert(aFeature);
1215       theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
1216                                                   aFeature->attribute(SketchPlugin_Arc::END_ID())));
1217       anNewFeature = aFeature;
1218     }
1219     aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
1220                      theSplitFeature->attribute(SketchPlugin_Arc::END_ID()),
1221                      aFeature->attribute(SketchPlugin_Arc::START_ID()));
1222     theCreatedFeatures.insert(aConstraintFeature);
1223
1224     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1225                                 (aFeature->attribute(SketchPlugin_Arc::START_ID())));
1226     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1227                                 (aFeature->attribute(SketchPlugin_Arc::END_ID())));
1228
1229     if (!theBaseFeatureModified.get())
1230       theBaseFeatureModified = aFeature;
1231     else
1232       theAfterFeature = aFeature;
1233   }
1234   else {
1235     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1236                                   (theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
1237     theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
1238                                    theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
1239   }
1240   // base split, that is defined before split feature should be changed at end
1241   // (after the after feature creation). Otherwise modified value will be used in after feature
1242   // before split feature
1243   if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
1244     /// move end arc point to start of split
1245     fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
1246                                                     aFirstPointAttrOfSplit);
1247     theBaseFeatureModified->execute(); // to update result
1248     aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
1249                      theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
1250                      theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
1251     theCreatedFeatures.insert(aConstraintFeature);
1252
1253     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1254                              (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
1255     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1256                                (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
1257   }
1258   else
1259     thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1260                                        (theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
1261
1262   // additional constraints between split and base features
1263 #ifdef CREATE_CONSTRAINTS
1264   aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
1265                                                        getFeatureResult(aBaseFeature),
1266                                                        getFeatureResult(theSplitFeature));
1267   theCreatedFeatures.insert(aConstraintFeature);
1268   aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
1269                                                        getFeatureResult(theSplitFeature),
1270                                                        getFeatureResult(aBaseFeature));
1271   theCreatedFeatures.insert(aConstraintFeature);
1272   if (theAfterFeature.get()) {
1273     aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
1274                                                     getFeatureResult(aBaseFeature),
1275                                                     getFeatureResult(theAfterFeature));
1276     theCreatedFeatures.insert(aConstraintFeature);
1277     aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
1278                                                     getFeatureResult(theSplitFeature),
1279                                                     getFeatureResult(theAfterFeature));
1280     theCreatedFeatures.insert(aConstraintFeature);
1281   }
1282 #endif
1283   return anNewFeature;
1284 }
1285
1286 FeaturePtr SketchPlugin_Split::splitCircle(FeaturePtr& theSplitFeature,
1287                                                FeaturePtr& theBaseFeatureModified,
1288                                                FeaturePtr& theAfterFeature,
1289                                                std::set<AttributePoint2DPtr>& thePoints,
1290                                                std::set<FeaturePtr>& theCreatedFeatures,
1291                  std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
1292 {
1293   FeaturePtr anNewFeature;
1294
1295   std::set<FeaturePtr> aCreatedFeatures;
1296   FeaturePtr aConstraintFeature;
1297   theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
1298
1299   SketchPlugin_Sketch* aSketch = sketch();
1300   if (!aSketch)
1301     return anNewFeature;
1302
1303   AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1304                                                            data()->attribute(SELECTED_OBJECT()));
1305   //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1306   //                                         data()->attribute(SketchPlugin_Constraint::VALUE()));
1307   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
1308   std::string aFeatureKind = aBaseFeature->getKind();
1309   if (aFeatureKind != SketchPlugin_Circle::ID())
1310     return anNewFeature;
1311
1312   AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
1313     //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
1314   AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
1315     //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
1316
1317   /// split feature
1318   theSplitFeature =
1319     createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
1320   bool aSplitReversed = std::dynamic_pointer_cast<SketchPlugin_Arc>(theSplitFeature)->isReversed();
1321   theCreatedFeatures.insert(theSplitFeature);
1322
1323   /// base feature is a left part of the circle
1324   theBaseFeatureModified = createArcFeature(aBaseFeature,
1325     aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
1326   anNewFeature = theBaseFeatureModified;
1327   std::dynamic_pointer_cast<SketchPlugin_Arc>(
1328     theBaseFeatureModified)->setReversed(!aSplitReversed);
1329   theBaseFeatureModified->execute();
1330
1331   theModifiedAttributes.insert(
1332     std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
1333                   theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
1334
1335   theCreatedFeatures.insert(theBaseFeatureModified);
1336
1337   thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1338                              (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
1339   thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
1340                              (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
1341
1342   // additional constraints between split and base features
1343   aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
1344                      theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
1345                      theSplitFeature->attribute(SketchPlugin_Arc::END_ID()));
1346   theCreatedFeatures.insert(aConstraintFeature);
1347   aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
1348                      theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()),
1349                      theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
1350   theCreatedFeatures.insert(aConstraintFeature);
1351
1352 #ifdef CREATE_CONSTRAINTS
1353   aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
1354                                                        getFeatureResult(theSplitFeature),
1355                                                        getFeatureResult(theBaseFeatureModified));
1356   theCreatedFeatures.insert(aConstraintFeature);
1357 #endif
1358   return anNewFeature;
1359 }
1360
1361 void SketchPlugin_Split::arrangePointsOnLine(
1362     const AttributePoint2DPtr& theStartPointAttr,
1363     const AttributePoint2DPtr& theEndPointAttr,
1364     AttributePoint2DPtr& theFirstPointAttr,
1365     AttributePoint2DPtr& theLastPointAttr) const
1366 {
1367   // if first point is closer to last point, swap first and last values
1368   if (theStartPointAttr->pnt()->distance(theFirstPointAttr->pnt()) >
1369       theStartPointAttr->pnt()->distance(theLastPointAttr->pnt())) {
1370     AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
1371     theFirstPointAttr = theLastPointAttr;
1372     theLastPointAttr = aTmpPoint;
1373   }
1374 }
1375
1376 void SketchPlugin_Split::arrangePointsOnArc(
1377     const FeaturePtr& theArc,
1378     const std::shared_ptr<GeomDataAPI_Point2D>& theStartPointAttr,
1379     const std::shared_ptr<GeomDataAPI_Point2D>& theEndPointAttr,
1380     std::shared_ptr<GeomDataAPI_Point2D>& theFirstPointAttr,
1381     std::shared_ptr<GeomDataAPI_Point2D>& theSecondPointAttr) const
1382 {
1383   static const double anAngleTol = 1.e-12;
1384
1385   std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1386       theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
1387   bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
1388
1389   // collect directions to each point
1390   std::shared_ptr<GeomAPI_Dir2d> aStartDir(
1391       new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1392   std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
1393       new GeomAPI_Dir2d(theFirstPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1394   std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
1395       new GeomAPI_Dir2d(theSecondPointAttr->pnt()->xy()->decreased(aCenter->xy())));
1396
1397   // sort points by their angular values
1398   double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
1399   double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
1400   double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
1401   if (fabs(aFirstPtAngle) > anAngleTol && isReversed == (aFirstPtAngle > 0.))
1402     aFirstPtAngle += aPeriod;
1403   if (fabs(aSecondPtAngle) > anAngleTol && isReversed == (aSecondPtAngle > 0.))
1404     aSecondPtAngle += aPeriod;
1405
1406   if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
1407     AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
1408     theFirstPointAttr = theSecondPointAttr;
1409     theSecondPointAttr = aTmpPoint;
1410   }
1411 }
1412
1413 void SketchPlugin_Split::fillAttribute(const AttributePtr& theModifiedAttribute,
1414                                                  const AttributePtr& theSourceAttribute)
1415 {
1416   std::string anAttributeType = theModifiedAttribute->attributeType();
1417   if (anAttributeType == GeomDataAPI_Point2D::typeId()) {
1418     AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1419                                               theModifiedAttribute);
1420     AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1421                                               theSourceAttribute);
1422
1423     if (aModifiedAttribute.get() && aSourceAttribute.get())
1424       aModifiedAttribute->setValue(aSourceAttribute->pnt());
1425   }
1426   else if (anAttributeType == ModelAPI_AttributeBoolean::typeId()) {
1427     AttributeBooleanPtr aModifiedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1428                                               theModifiedAttribute);
1429     AttributeBooleanPtr aSourceAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
1430                                               theSourceAttribute);
1431
1432     if (aModifiedAttribute.get() && aSourceAttribute.get())
1433       aModifiedAttribute->setValue(aSourceAttribute->value());
1434   }
1435 }
1436
1437 FeaturePtr SketchPlugin_Split::createLineFeature(const FeaturePtr& theBaseFeature,
1438                                                            const AttributePtr& theFirstPointAttr,
1439                                                            const AttributePtr& theSecondPointAttr)
1440 {
1441   FeaturePtr aFeature;
1442   SketchPlugin_Sketch* aSketch = sketch();
1443   if (!aSketch || !theBaseFeature.get())
1444     return aFeature;
1445
1446   aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
1447
1448   fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPointAttr);
1449   fillAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPointAttr);
1450
1451   fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
1452                 theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
1453
1454   aFeature->execute(); // to obtain result
1455
1456   return aFeature;
1457 }
1458
1459 FeaturePtr SketchPlugin_Split::createArcFeature(const FeaturePtr& theBaseFeature,
1460                                                           const AttributePtr& theFirstPointAttr,
1461                                                           const AttributePtr& theSecondPointAttr)
1462 {
1463   FeaturePtr aFeature;
1464   SketchPlugin_Sketch* aSketch = sketch();
1465   if (!aSketch || !theBaseFeature.get())
1466     return aFeature;
1467
1468   std::string aCenterAttributeId;
1469   if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
1470     aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
1471   else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
1472     aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
1473
1474   if (aCenterAttributeId.empty())
1475     return aFeature;
1476
1477   aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
1478   // update fillet arc: make the arc correct for sure, so, it is not needed to process
1479   // the "attribute updated"
1480   // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1481   bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
1482
1483   fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
1484                 theBaseFeature->attribute(aCenterAttributeId));
1485   fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPointAttr);
1486   fillAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPointAttr);
1487
1488   fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
1489                 theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
1490
1491   /// fill referersed state of created arc as it is on the base arc
1492   if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
1493     bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
1494     aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed);
1495   }
1496   aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
1497   aFeature->execute(); // to obtain result
1498
1499   return aFeature;
1500 }
1501
1502 FeaturePtr SketchPlugin_Split::createConstraint(const std::string& theConstraintId,
1503                                                     const AttributePtr& theFirstAttribute,
1504                                                     const AttributePtr& theSecondAttribute)
1505 {
1506   FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1507   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1508                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1509   aRefAttr->setAttr(theFirstAttribute);
1510
1511   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1512                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1513   aRefAttr->setAttr(theSecondAttribute);
1514
1515   return aConstraint;
1516 }
1517
1518 FeaturePtr SketchPlugin_Split::createConstraintForObjects(
1519                                                     const std::string& theConstraintId,
1520                                                     const ObjectPtr& theFirstObject,
1521                                                     const ObjectPtr& theSecondObject)
1522 {
1523   FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1524   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1525                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1526   aRefAttr->setObject(theFirstObject);
1527
1528   aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1529                                  aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1530   aRefAttr->setObject(theSecondObject);
1531
1532   return aConstraint;
1533 }
1534
1535 void SketchPlugin_Split::updateFeaturesAfterSplit(
1536                                                    const std::set<FeaturePtr>& theFeaturesToUpdate)
1537 {
1538   std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
1539                                        aLast = theFeaturesToUpdate.end();
1540   for (; anIt != aLast; anIt++) {
1541     FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
1542     std::string aRefFeatureKind = aRefFeature->getKind();
1543     if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
1544       std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
1545                               std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
1546       if (aLenghtFeature.get()) {
1547         std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
1548             ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
1549         double aValue;
1550         if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
1551           aValueAttr->setValue(aValue);
1552       }
1553     }
1554   }
1555 }
1556
1557 std::shared_ptr<ModelAPI_Result> SketchPlugin_Split::getFeatureResult(
1558                                     const std::shared_ptr<ModelAPI_Feature>& theFeature)
1559 {
1560   std::shared_ptr<ModelAPI_Result> aResult;
1561
1562   std::string aFeatureKind = theFeature->getKind();
1563   if (aFeatureKind == SketchPlugin_Line::ID())
1564     aResult = theFeature->firstResult();
1565   else if (aFeatureKind == SketchPlugin_Arc::ID())
1566     aResult = theFeature->lastResult();
1567   else if (aFeatureKind == SketchPlugin_Circle::ID())
1568     aResult = theFeature->lastResult();
1569
1570   return aResult;
1571 }
1572
1573 std::set<std::shared_ptr<ModelAPI_Attribute> > SketchPlugin_Split::getEdgeAttributes(
1574                                            const std::shared_ptr<ModelAPI_Feature>& theFeature)
1575 {
1576   std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
1577
1578   std::string aFeatureKind = theFeature->getKind();
1579   if (aFeatureKind == SketchPlugin_Line::ID()) {
1580     anAttributes.insert(theFeature->attribute(SketchPlugin_Line::START_ID()));
1581     anAttributes.insert(theFeature->attribute(SketchPlugin_Line::END_ID()));
1582   }
1583   else if (aFeatureKind == SketchPlugin_Arc::ID()) {
1584     anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::START_ID()));
1585     anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::END_ID()));
1586   }
1587   else if (aFeatureKind == SketchPlugin_Circle::ID()) {
1588   }
1589
1590   return anAttributes;
1591 }
1592
1593 std::shared_ptr<GeomDataAPI_Point2D> SketchPlugin_Split::getPointAttribute
1594                                                               (const bool isFirstAttribute)
1595 {
1596   std::shared_ptr<GeomDataAPI_Point2D> anAttribute;
1597
1598   GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
1599   if (!aSelectedShape.get())
1600     return anAttribute;
1601
1602   if (aSelectedShape->shapeType() != GeomAPI_Shape::EDGE)
1603     return anAttribute;
1604
1605   AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
1606                                                        data()->attribute(SELECTED_OBJECT()));
1607   ObjectPtr aBaseObject = anObjectAttr->value();
1608   if (!aBaseObject.get())
1609     return anAttribute;
1610
1611   std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aSelectedShape));
1612
1613   std::shared_ptr<GeomAPI_Pnt> aFirstPnt = anEdge->firstPoint();
1614   std::shared_ptr<GeomAPI_Pnt> aLastPnt = anEdge->lastPoint();
1615
1616   std::shared_ptr<GeomDataAPI_Point2D> aFirstPointAttr, aLastPointAttr;
1617   /// find the points in feature attributes
1618   FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
1619   std::list<AttributePtr> a2DPointAttributes = aBaseFeature->data()->attributes(
1620                                                     GeomDataAPI_Point2D::typeId());
1621   std::list<AttributePtr>::const_iterator anIt = a2DPointAttributes.begin(),
1622                                           aLast = a2DPointAttributes.end();
1623   for (; anIt != aLast; anIt++) {
1624     std::shared_ptr<GeomDataAPI_Point2D> anAttributePoint =
1625                                   std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
1626     std::shared_ptr<GeomAPI_Pnt2d> aPoint2D = anAttributePoint->pnt();
1627     std::shared_ptr<GeomAPI_Pnt> aPoint3D = sketch()->to3D(aPoint2D->x(), aPoint2D->y());
1628     if (aFirstPnt->isEqual(aPoint3D))
1629       aFirstPointAttr = anAttributePoint;
1630     else if (aLastPnt->isEqual(aPoint3D))
1631       aLastPointAttr = anAttributePoint;
1632   }
1633
1634   /// find the points in coincident features
1635   PntToAttributesMap aRefAttributes = myCashedReferences[aBaseObject];
1636   PntToAttributesMap::const_iterator
1637     aRIt = aRefAttributes.begin(), aRLast = aRefAttributes.end();
1638   for (; aRIt != aRLast; aRIt++) {
1639     std::shared_ptr<GeomDataAPI_Point2D> anAttribute = aRIt->first;
1640     std::shared_ptr<GeomAPI_Pnt> aPoint = aRIt->second;
1641     if (!aFirstPointAttr.get() && aFirstPnt->isEqual(aPoint))
1642       aFirstPointAttr = anAttribute;
1643     if (!aLastPointAttr.get() && aLastPnt->isEqual(aPoint))
1644       aLastPointAttr = anAttribute;
1645     if (aFirstPointAttr.get() && aLastPointAttr.get())
1646       break;
1647   }
1648   if (!aFirstPointAttr.get() || !aLastPointAttr)
1649     return anAttribute;
1650
1651   return isFirstAttribute ? aFirstPointAttr : aLastPointAttr;
1652 }
1653
1654 #ifdef _DEBUG
1655 std::string SketchPlugin_Split::getFeatureInfo(const std::shared_ptr<ModelAPI_Feature>& theFeature,
1656                                                const bool isUseAttributesInfo)
1657 {
1658   std::string anInfo;
1659   if (!theFeature.get()) {
1660     return "none";
1661   }
1662
1663   if (theFeature->data()->isValid())
1664     anInfo.append(theFeature->data()->name().c_str());
1665
1666   if (isUseAttributesInfo) {
1667     std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(theFeature,
1668                                                              getEdgeAttributes(theFeature));
1669     /// processing of feature with point 2d attributes, like line, arc, circle
1670     if (!aPointsInfo.empty()) {
1671       anInfo += ": ";
1672       anInfo += "\n";
1673       anInfo += aPointsInfo;
1674     }
1675     else { /// process constraint coincidence, find points in ref attr attributes
1676       std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
1677                                                        ModelAPI_AttributeRefAttr::typeId());
1678       std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
1679       std::string anAttributesInfo;
1680       for(; anIt != aLast; anIt++) {
1681         if (!anAttributesInfo.empty()) {
1682           anAttributesInfo.append(", ");
1683           anAttributesInfo += "\n";
1684         }
1685         AttributePtr anAttr = *anIt;
1686         std::string aValue = "not defined";
1687         std::string aType = anAttr->attributeType();
1688         if (aType == ModelAPI_AttributeRefAttr::typeId()) {
1689           std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
1690                              std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
1691           if (aRefAttr.get()) {
1692             if (aRefAttr->isObject()) {
1693               FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
1694               aValue = "<object:>" + getFeatureInfo(aFeature, false);
1695             }
1696             else {
1697               AttributePtr anAttribute = aRefAttr->attr();
1698               if (anAttribute.get()) {
1699                 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
1700                 aValue = "<attr:>" + ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute) +
1701                          " [" + getFeatureInfo(aFeature, false) + "]";
1702               }
1703             }
1704           }
1705         }
1706         anAttributesInfo.append("    " + anAttr->id() + ": " + aValue);
1707       }
1708       if (!anAttributesInfo.empty())
1709         anInfo = anInfo + "\n" + anAttributesInfo;
1710     }
1711   }
1712   return anInfo;
1713 }
1714 #endif