]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_Validators.cpp
Salome HOME
55e2eee2939b80ab1dc5e9c133460f0227cc35cd
[modules/shaper.git] / src / PartSet / PartSet_Validators.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        PartSet_Validators.cpp
4 // Created:     09 July 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "PartSet_Validators.h"
8
9 #include "PartSet_Tools.h"
10 #include "PartSet_SketcherMgr.h"
11
12 #include <TopoDS.hxx>
13 #include <TopoDS_Edge.hxx>
14 #include <BRep_Tool.hxx>
15 #include <GeomAdaptor_Curve.hxx>
16 #include <GeomAbs_CurveType.hxx>
17 #include <ModuleBase_ISelection.h>
18 #include <ModuleBase_WidgetShapeSelector.h>
19 #include <ModuleBase_OperationFeature.h>
20 #include <ModuleBase_ViewerPrs.h>
21
22 #include <Events_InfoMessage.h>
23
24 #include <ModelAPI_AttributeRefAttr.h>
25 #include <ModelAPI_AttributeSelection.h>
26 #include <ModelAPI_AttributeReference.h>
27 #include <ModelAPI_AttributeSelectionList.h>
28 #include <ModelAPI_AttributeRefList.h>
29 #include <ModelAPI_Object.h>
30 #include <ModelAPI_ResultCompSolid.h>
31 #include <ModelAPI_Session.h>
32 #include <ModelAPI_Tools.h>
33
34 #include <SketchPlugin_Sketch.h>
35 #include <SketchPlugin_ConstraintCoincidence.h>
36 #include <SketchPlugin_Arc.h>
37 #include <GeomAPI_Edge.h>
38
39 #include <list>
40 #ifdef _DEBUG
41 #include <iostream>
42 #endif
43
44 int shapesNbPoints(const ModuleBase_ISelection* theSelection)
45 {
46   QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
47   ModuleBase_ISelection::filterSelectionOnEqualPoints(aList);
48
49   int aCount = 0;
50   foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
51     const GeomShapePtr& aShape = aPrs->shape();
52     if (aShape.get() && !aShape->isNull()) {
53       if (aShape->shapeType() == GeomAPI_Shape::VERTEX)
54         aCount++;
55     }
56   }
57   return aCount;
58 }
59
60 int shapesNbLines(const ModuleBase_ISelection* theSelection)
61 {
62   QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
63   int aCount = 0;
64   foreach(ModuleBase_ViewerPrsPtr aPrs, aList) {
65     const GeomShapePtr& aShape = aPrs->shape();
66     if (aShape.get() && !aShape->isNull()) {
67       if (aShape->shapeType() == GeomAPI_Shape::EDGE) {
68         const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
69         TopoDS_Edge aEdge = TopoDS::Edge(aTDShape);
70         Standard_Real aStart, aEnd;
71         Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
72         GeomAdaptor_Curve aAdaptor(aCurve);
73         if (aAdaptor.GetType() == GeomAbs_Line)
74           aCount++;
75       }
76     }
77   }
78   return aCount;
79 }
80
81
82 std::shared_ptr<GeomAPI_Pln> sketcherPlane(ModuleBase_Operation* theOperation)
83 {
84   std::shared_ptr<GeomAPI_Pln> aEmptyPln;
85   if (theOperation) {
86     ModuleBase_OperationFeature* aFeatureOp =
87       dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
88     if (aFeatureOp) {
89       CompositeFeaturePtr aFeature =
90         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeatureOp->feature());
91       if (aFeature && (aFeature->getKind() == SketchPlugin_Sketch::ID()))
92         return PartSet_Tools::sketchPlane(aFeature);
93     }
94   }
95   return aEmptyPln;
96 }
97
98
99 bool isEmptySelectionValid(ModuleBase_Operation* theOperation)
100 {
101   ModuleBase_OperationFeature* aFeatureOp =
102     dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
103   // during the create operation empty selection is always valid
104   if (!aFeatureOp->isEditOperation()) {
105     return true;
106   }
107   else {
108     if (PartSet_SketcherMgr::isSketchOperation(aFeatureOp)) {
109       std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
110       if (aPlane.get())
111         return true;
112       else
113         return false;
114     }
115     else
116       // in edit operation an empty selection is always valid, performed for re-entrant operrations
117       return true;
118   }
119 }
120
121 bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection,
122                                         ModuleBase_Operation* theOperation) const
123 {
124   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
125     return isEmptySelectionValid(theOperation);
126   } else {
127     int aCount = shapesNbPoints(theSelection) + shapesNbLines(theSelection);
128     return (aCount > 0) && (aCount < 3);
129   }
130 }
131
132 bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection,
133                                       ModuleBase_Operation* theOperation) const
134 {
135   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
136     return isEmptySelectionValid(theOperation);
137   } else {
138     int aCount = shapesNbLines(theSelection);
139     return (aCount == 1);
140   }
141 }
142
143 bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection,
144                                              ModuleBase_Operation* theOperation) const
145 {
146   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
147     return isEmptySelectionValid(theOperation);
148   } else {
149     int aCount = shapesNbLines(theSelection);
150     return (aCount > 0) && (aCount < 3);
151   }
152 }
153
154 bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection,
155                                         ModuleBase_Operation* theOperation) const
156 {
157   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
158     return isEmptySelectionValid(theOperation);
159   } else {
160     int aCount = shapesNbLines(theSelection);
161     return (aCount > 0) && (aCount < 3);
162   }
163 }
164
165 bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection,
166                                       ModuleBase_Operation* theOperation) const
167 {
168   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
169     return isEmptySelectionValid(theOperation);
170   } else {
171     QList<ModuleBase_ViewerPrsPtr> aList =
172       theSelection->getSelected(ModuleBase_ISelection::Viewer);
173     int aCount = 0;
174     foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
175       const GeomShapePtr& aShape = aPrs->shape();
176       if (aShape.get() && !aShape->isNull()) {
177         if (aShape->shapeType() == GeomAPI_Shape::EDGE) {
178           const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
179           TopoDS_Edge aEdge = TopoDS::Edge(aTDShape);
180           Standard_Real aStart, aEnd;
181           Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
182           GeomAdaptor_Curve aAdaptor(aCurve);
183           if (aAdaptor.GetType() == GeomAbs_Circle)
184             aCount++;
185         }
186       }
187     }
188     return (aCount == 1);
189   }
190 }
191
192 bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection,
193                                      ModuleBase_Operation* theOperation) const
194 {
195   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
196     return isEmptySelectionValid(theOperation);
197   } else {
198     QList<ModuleBase_ViewerPrsPtr> aList =
199       theSelection->getSelected(ModuleBase_ISelection::Viewer);
200     int aCount = 0;
201     foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
202       ObjectPtr aObj = aPrs->object();
203       if (aObj.get()) {
204         FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
205         if (aFeature.get()) {
206           CompositeFeaturePtr aComp = ModelAPI_Tools::compositeOwner(aFeature);
207           if (aComp.get() && (aComp->getKind() == SketchPlugin_Sketch::ID()))
208             aCount++;
209         }
210       }
211     }
212     return (aCount == 1);
213   }
214 }
215
216
217 bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection,
218                                           ModuleBase_Operation* theOperation) const
219 {
220   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
221     return isEmptySelectionValid(theOperation);
222   } else {
223     // Coincident can be applied to points and to lines
224     int aCount = shapesNbPoints(theSelection);
225     aCount += shapesNbLines(theSelection);
226     return (aCount > 0) && (aCount < 3);
227   }
228 }
229
230 bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection,
231                                      ModuleBase_Operation* theOperation) const
232 {
233   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
234     return isEmptySelectionValid(theOperation);
235   } else {
236     int aCount = shapesNbLines(theSelection);
237     return (aCount == 1);
238   }
239 }
240
241 bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection,
242                                       ModuleBase_Operation* theOperation) const
243 {
244   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
245     return isEmptySelectionValid(theOperation);
246   } else {
247     int aCount = shapesNbPoints(theSelection);
248     return aCount > 1;
249   }
250 }
251
252 bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection,
253                                        ModuleBase_Operation* theOperation) const
254 {
255   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
256     return isEmptySelectionValid(theOperation);
257   } else {
258     QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
259     if ((aList.size() == 0) || (aList.size() > 2))
260       return false;
261
262     ModuleBase_ViewerPrsPtr aPrs = aList.first();
263     const GeomShapePtr& aShape = aPrs->shape();
264     if (!aShape.get() || aShape->isNull() || aShape->shapeType() != GeomAPI_Shape::EDGE)
265       return false;
266     GeomAPI_Edge aEdge1(aShape);
267
268     if (aEdge1.isLine() || aEdge1.isArc()) {
269       if (aList.size() == 2) {
270         // Check second selection
271         aPrs = aList.last();
272         const GeomShapePtr& aShape2 = aPrs->shape();
273         if (!aShape2.get() || aShape2->isNull() || aShape2->shapeType() != GeomAPI_Shape::EDGE)
274           return false;
275         GeomAPI_Edge aEdge2(aShape2);
276
277         if (aEdge1.isLine() && aEdge2.isArc())
278           return true;
279         else if (aEdge1.isArc() && aEdge2.isLine())
280           return true;
281         else
282           return false;
283       } else
284         return true;
285     }
286     return false;
287   }
288 }
289
290 bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection,
291                                      ModuleBase_Operation* theOperation) const
292 {
293   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
294     return isEmptySelectionValid(theOperation);
295   } else {
296     int aCount = shapesNbLines(theSelection);
297     return (aCount > 0) && (aCount < 3);
298   }
299 }
300
301 bool PartSet_EqualSelection::isValid(const ModuleBase_ISelection* theSelection,
302                                      ModuleBase_Operation* theOperation) const
303 {
304   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
305     return isEmptySelectionValid(theOperation);
306   } else {
307     QList<ModuleBase_ViewerPrsPtr> aList =
308       theSelection->getSelected(ModuleBase_ISelection::Viewer);
309     int aCount = 0;
310     int aType = 0;
311     foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
312       GeomShapePtr aShape = aPrs->shape();
313       if (aShape.get() && aShape->isEdge()) {
314         aCount++;
315         GeomAPI_Edge aEdge(aShape);
316         if (aEdge.isLine()) {
317           if (aCount == 1)
318             aType = 1;
319           else if (aType != 1)
320             return false;
321         } else if (aEdge.isCircle()) {
322           if (aCount == 1)
323             aType = 2;
324           else if (aType != 2)
325             return false;
326         } else if (aEdge.isArc()) {
327           if (aCount == 1)
328             aType = 3;
329           else if (aType != 3)
330             return false;
331         }
332       } else
333         return false;
334     }
335     return (aCount > 0) && (aCount < 3);
336   }
337 }
338
339 bool PartSet_CollinearSelection::isValid(const ModuleBase_ISelection* theSelection,
340                                          ModuleBase_Operation* theOperation) const
341 {
342   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
343     return isEmptySelectionValid(theOperation);
344   } else {
345     int aCount = shapesNbLines(theSelection);
346     return (aCount > 0) && (aCount < 3);
347   }
348 }
349
350 bool PartSet_MiddlePointSelection::isValid(const ModuleBase_ISelection* theSelection,
351                                            ModuleBase_Operation* theOperation) const
352 {
353   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0)
354     return isEmptySelectionValid(theOperation);
355   else
356     return shapesNbLines(theSelection) == 1 || shapesNbPoints(theSelection) == 1;
357 }
358
359 bool PartSet_MultyTranslationSelection::isValid(const ModuleBase_ISelection* theSelection,
360                                      ModuleBase_Operation* theOperation) const
361 {
362   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
363     return isEmptySelectionValid(theOperation);
364   } else {
365     int aCount = shapesNbLines(theSelection);
366     return aCount > 0;
367   }
368 }
369
370 bool PartSet_SplitSelection::isValid(const ModuleBase_ISelection* theSelection,
371                                      ModuleBase_Operation* theOperation) const
372 {
373   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
374     return isEmptySelectionValid(theOperation);
375   } else {
376     int aCount = shapesNbLines(theSelection);
377     return aCount > 0;
378   }
379 }
380
381 bool PartSet_ProjectionSelection::isValid(const ModuleBase_ISelection* theSelection,
382                                      ModuleBase_Operation* theOperation) const
383 {
384   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
385     return isEmptySelectionValid(theOperation);
386   } else {
387     int aCount = shapesNbLines(theSelection);
388     return aCount > 0;
389   }
390 }
391
392
393 std::string PartSet_DifferentObjectsValidator::errorMessage(
394                          const PartSet_DifferentObjectsValidator::ErrorType& theType,
395                          const std::string& thEqualObject, const std::string& theFirstAttribute,
396                          const std::string& theSecondAttribute) const
397 {
398   std::string anError;
399   switch (theType) {
400     case EqualObjects:
401       anError = "The feature uses one " + thEqualObject + " object in " +
402                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
403       break;
404     case EqualAttributes:
405       anError = "The feature uses reference to one " + thEqualObject + " attribute in " +
406                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
407       break;
408     case EqualShapes:
409       anError = "The feature uses one shape in " +
410                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
411       break;
412     case EmptyShapes:
413       anError = "The feature uses empty shapes in " +
414                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
415       break;
416       break;
417     default:
418       break;
419   }
420   return anError;
421 }
422
423 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
424                                                 const std::list<std::string>& theArguments,
425                                                 Events_InfoMessage& theError) const
426 {
427   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
428
429   // the type of validated attributes should be equal, attributes with
430   // different types are not validated
431   // Check RefAttr attributes
432   std::string anAttrType = theAttribute->attributeType();
433   std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
434
435   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
436     AttributeRefAttrPtr anAttr =
437       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
438     bool isObject = anAttr->isObject();
439     ObjectPtr anObject = anAttr->object();
440
441     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
442     if (anAttrs.size() > 0) {
443       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
444       for(; anAttrIter != anAttrs.end(); anAttrIter++) {
445       if ((*anAttrIter).get() && (*anAttrIter)->id() != theAttribute->id()) {
446           std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
447                               std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
448           if (aRef->isObject() != isObject)
449             continue;
450           if (isObject) {
451             if (aRef->object() == anObject) {
452               theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
453                                       theAttribute->id(), aRef->id());
454               return false;
455             }
456           }
457           else { // the attribute reference
458             AttributePtr anAttributeAttr = anAttr->attr();
459             if (aRef->attr() == anAttributeAttr) {
460               theError = errorMessage(EqualAttributes,
461                                       anAttributeAttr.get() ? anAttributeAttr->id() : "",
462                                       theAttribute->id(), aRef->id());
463               return false;
464             }
465           }
466         }
467       }
468     }
469   }
470   else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
471     AttributeSelectionPtr anAttr =
472       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
473     ResultPtr aContext = anAttr->context();
474     GeomShapePtr aShape = anAttr->value();
475
476     // Check selection attributes
477     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
478     if (anAttrs.size() > 0) {
479       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
480       for(; anAttr != anAttrs.end(); anAttr++) {
481         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
482           std::shared_ptr<ModelAPI_AttributeSelection> aRef =
483                               std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
484           // check the object is already presented
485           if (aRef->context() == aContext) {
486             bool aHasShape = aShape.get() != NULL;
487             if (!aHasShape || aRef->value()->isEqual(aShape)) {
488               theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
489               return false;
490             }
491           }
492         }
493       }
494     }
495   }
496   else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
497     AttributeReferencePtr anAttr =
498       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
499     ObjectPtr anObject = anAttr->value();
500     // Check selection attributes
501     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
502     if (anAttrs.size() > 0) {
503       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
504       for(; anAttr != anAttrs.end(); anAttr++) {
505         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
506           std::shared_ptr<ModelAPI_AttributeReference> aRef =
507             std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
508           // check the object is already presented
509           if (aRef->value() == anObject) {
510             theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
511                                     theAttribute->id(), aRef->id());
512             return false;
513           }
514         }
515         return true;
516       }
517     }
518   }
519   else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
520     std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
521             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
522     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
523     if(anAttrs.size() > 0) {
524       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
525       for(; anAttrItr != anAttrs.end(); anAttrItr++){
526         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
527           std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
528             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
529           for(int i = 0; i < aCurSelList->size(); i++) {
530             std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
531             ResultPtr aCurSelContext = aCurSel->context();
532             ResultCompSolidPtr aCurSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aCurSelContext);
533             std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
534             if(aCurSelCompSolidPtr.get()) {
535               aCurSelCompSolid = aCurSelCompSolidPtr->shape();
536             }
537             for(int j = 0; j < aRefSelList->size(); j++) {
538               std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
539               ResultPtr aRefSelContext = aRefSel->context();
540               ResultCompSolidPtr aRefSelCompSolidPtr =
541                 ModelAPI_Tools::compSolidOwner(aRefSelContext);
542               std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
543               if(aRefSelCompSolidPtr.get()) {
544                 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
545               }
546               if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value()))
547                 || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) {
548                   theError = errorMessage(EqualShapes, "", theAttribute->id(),
549                                           aRefSel->id());
550                   return false;
551               }
552               if(aCurSelContext == aRefSelContext) {
553                 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
554                   theError = errorMessage(EmptyShapes, "", theAttribute->id(),
555                                           aRefSel->id());
556                   return false;
557                 }
558                 if (aCurSel->value()->isEqual(aRefSel->value())) {
559                   theError = errorMessage(EqualShapes, "", theAttribute->id(),
560                                           aRefSel->id());
561                   return false;
562                 }
563               }
564             }
565           }
566         }
567       }
568     }
569   }
570   else if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
571     std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
572       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
573     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId());
574     if (anAttrs.size() > 0) {
575       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
576       for (; anAttrItr != anAttrs.end(); anAttrItr++){
577         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
578           std::shared_ptr<ModelAPI_AttributeRefList> aRefSelList =
579             std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrItr);
580           for (int i = 0; i < aCurSelList->size(); i++) {
581             ObjectPtr aCurSelObject = aCurSelList->object(i);
582             for (int j = 0; j < aRefSelList->size(); j++) {
583               if (aCurSelObject == aRefSelList->object(j)) {
584                 theError = errorMessage(EqualObjects,
585                               aCurSelObject.get() ? aCurSelObject->data()->name() : "",
586                               theAttribute->id(), aCurSelList->id());
587                 return false;
588               }
589             }
590           }
591         }
592       }
593     }
594   }
595   return true;
596 }
597
598 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
599                                      const std::list<std::string>& theArguments,
600                                      Events_InfoMessage& theError) const
601 {
602   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
603     theError = "The attribute with the %1 type is not processed";
604     theError.arg(theAttribute->attributeType());
605     return false;
606   }
607
608   // there is a check whether the feature contains a point and a linear edge or two point values
609   std::string aParamA = theArguments.front();
610   SessionPtr aMgr = ModelAPI_Session::get();
611   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
612
613   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
614   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
615   QList<FeaturePtr> aCoinsideLines;
616   QList<FeaturePtr> aCoins;
617
618   bool isObject = aRefAttr->isObject();
619   ObjectPtr anObject = aRefAttr->object();
620   if (isObject && anObject) {
621     FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
622     AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
623     ObjectPtr aOtherObject = aOtherAttr->object();
624     // if the other attribute is not filled still, the result is true
625     if (!aOtherObject.get())
626       return true;
627     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
628
629     // check that both have coincidence
630     FeaturePtr aConstrFeature;
631     std::set<FeaturePtr> aCoinList;
632     const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
633     std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
634     for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
635       std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
636       aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
637       if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
638         AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
639         AttributePtr aAR = aRAttr->attr();
640         if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
641           aCoinList.insert(aConstrFeature);
642           QList<bool> anIsAttributes;
643           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
644                                           SketchPlugin_ConstraintCoincidence::ENTITY_A(),
645                                           anIsAttributes);
646           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
647                                           SketchPlugin_ConstraintCoincidence::ENTITY_B(),
648                                           anIsAttributes);
649       }
650     }
651     // if there is no coincidence then it is not valid
652     if (aCoinList.size() > 0) {
653       QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
654       bool aValid = false;
655       for (; anIt != aLast && !aValid; anIt++) {
656         aValid = *anIt == aOtherFea;
657       }
658       if (aValid)
659         return true;
660     }
661   }
662   theError = "There is no a common coincident point.";
663   return false;
664 }