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