]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_Validators.cpp
Salome HOME
Fix for registering of parameters in command line.
[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     int aCount = 0;
200     foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
201       ObjectPtr aObj = aPrs->object();
202       if (aObj.get()) {
203         FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
204         if (aFeature.get()) {
205           CompositeFeaturePtr aComp = ModelAPI_Tools::compositeOwner(aFeature);
206           if (aComp.get() && (aComp->getKind() == SketchPlugin_Sketch::ID()))
207             aCount++;
208         }
209       }
210     }
211     return (aCount == 1);
212   }
213 }
214
215
216 bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection,
217                                           ModuleBase_Operation* theOperation) const
218 {
219   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
220     return isEmptySelectionValid(theOperation);
221   } else {
222     // Coincident can be applied to points and to lines
223     int aCount = shapesNbPoints(theSelection);
224     aCount += shapesNbLines(theSelection);
225     return (aCount > 0) && (aCount < 3);
226   }
227 }
228
229 bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection,
230                                      ModuleBase_Operation* theOperation) const
231 {
232   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
233     return isEmptySelectionValid(theOperation);
234   } else {
235     int aCount = shapesNbLines(theSelection);
236     return (aCount == 1);
237   }
238 }
239
240 bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection,
241                                       ModuleBase_Operation* theOperation) const
242 {
243   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
244     return isEmptySelectionValid(theOperation);
245   } else {
246     int aCount = shapesNbPoints(theSelection);
247     return aCount > 1;
248   }
249 }
250
251 bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection,
252                                        ModuleBase_Operation* theOperation) const
253 {
254   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
255     return isEmptySelectionValid(theOperation);
256   } else {
257     QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
258     if ((aList.size() == 0) || (aList.size() > 2))
259       return false;
260
261     ModuleBase_ViewerPrsPtr aPrs = aList.first();
262     const GeomShapePtr& aShape = aPrs->shape();
263     if (!aShape.get() || aShape->isNull() || aShape->shapeType() != GeomAPI_Shape::EDGE)
264       return false;
265     GeomAPI_Edge aEdge1(aShape);
266
267     if (aEdge1.isLine() || aEdge1.isArc()) {
268       if (aList.size() == 2) {
269         // Check second selection
270         aPrs = aList.last();
271         const GeomShapePtr& aShape2 = aPrs->shape();
272         if (!aShape2.get() || aShape2->isNull() || aShape2->shapeType() != GeomAPI_Shape::EDGE)
273           return false;
274         GeomAPI_Edge aEdge2(aShape2);
275
276         if (aEdge1.isLine() && aEdge2.isArc())
277           return true;
278         else if (aEdge1.isArc() && aEdge2.isLine())
279           return true;
280         else
281           return false;
282       } else
283         return true;
284     }
285     return false;
286   }
287 }
288
289 bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection,
290                                      ModuleBase_Operation* theOperation) const
291 {
292   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
293     return isEmptySelectionValid(theOperation);
294   } else {
295     int aCount = shapesNbLines(theSelection);
296     return (aCount > 0) && (aCount < 3);
297   }
298 }
299
300 bool PartSet_EqualSelection::isValid(const ModuleBase_ISelection* theSelection,
301                                      ModuleBase_Operation* theOperation) const
302 {
303   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
304     return isEmptySelectionValid(theOperation);
305   } else {
306     QList<ModuleBase_ViewerPrsPtr> aList =
307       theSelection->getSelected(ModuleBase_ISelection::Viewer);
308     int aCount = 0;
309     int aType = 0;
310     foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
311       GeomShapePtr aShape = aPrs->shape();
312       if (aShape.get() && aShape->isEdge()) {
313         aCount++;
314         GeomAPI_Edge aEdge(aShape);
315         if (aEdge.isLine()) {
316           if (aCount == 1)
317             aType = 1;
318           else if (aType != 1)
319             return false;
320         } else if (aEdge.isCircle()) {
321           if (aCount == 1)
322             aType = 2;
323           else if (aType != 2)
324             return false;
325         } else if (aEdge.isArc()) {
326           if (aCount == 1)
327             aType = 3;
328           else if (aType != 3)
329             return false;
330         }
331       } else
332         return false;
333     }
334     return (aCount > 0) && (aCount < 3);
335   }
336 }
337
338 bool PartSet_CollinearSelection::isValid(const ModuleBase_ISelection* theSelection,
339                                          ModuleBase_Operation* theOperation) const
340 {
341   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
342     return isEmptySelectionValid(theOperation);
343   } else {
344     int aCount = shapesNbLines(theSelection);
345     return (aCount > 0) && (aCount < 3);
346   }
347 }
348
349 bool PartSet_MiddlePointSelection::isValid(const ModuleBase_ISelection* theSelection,
350                                            ModuleBase_Operation* theOperation) const
351 {
352   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0)
353     return isEmptySelectionValid(theOperation);
354   else
355     return shapesNbLines(theSelection) == 1 || shapesNbPoints(theSelection) == 1;
356 }
357
358 bool PartSet_MultyTranslationSelection::isValid(const ModuleBase_ISelection* theSelection,
359                                      ModuleBase_Operation* theOperation) const
360 {
361   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
362     return isEmptySelectionValid(theOperation);
363   } else {
364     int aCount = shapesNbLines(theSelection);
365     return aCount > 0;
366   }
367 }
368
369 bool PartSet_SplitSelection::isValid(const ModuleBase_ISelection* theSelection,
370                                      ModuleBase_Operation* theOperation) const
371 {
372   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
373     return isEmptySelectionValid(theOperation);
374   } else {
375     int aCount = shapesNbLines(theSelection);
376     return aCount > 0;
377   }
378 }
379
380 bool PartSet_ProjectionSelection::isValid(const ModuleBase_ISelection* theSelection,
381                                      ModuleBase_Operation* theOperation) const
382 {
383   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
384     return isEmptySelectionValid(theOperation);
385   } else {
386     int aCount = shapesNbLines(theSelection);
387     return aCount > 0;
388   }
389 }
390
391
392 std::string PartSet_DifferentObjectsValidator::errorMessage(
393                          const PartSet_DifferentObjectsValidator::ErrorType& theType,
394                          const std::string& thEqualObject, const std::string& theFirstAttribute,
395                          const std::string& theSecondAttribute) const
396 {
397   std::string anError;
398   switch (theType) {
399     case EqualObjects:
400       anError = "The feature uses one " + thEqualObject + " object in " +
401                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
402       break;
403     case EqualAttributes:
404       anError = "The feature uses reference to one " + thEqualObject + " attribute in " +
405                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
406       break;
407     case EqualShapes:
408       anError = "The feature uses one shape in " +
409                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
410       break;
411     case EmptyShapes:
412       anError = "The feature uses empty shapes in " +
413                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
414       break;
415       break;
416     default:
417       break;
418   }
419   return anError;
420 }
421
422 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
423                                                 const std::list<std::string>& theArguments,
424                                                 Events_InfoMessage& theError) const
425 {
426   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
427
428   // the type of validated attributes should be equal, attributes with
429   // different types are not validated
430   // Check RefAttr attributes
431   std::string anAttrType = theAttribute->attributeType();
432   std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
433
434   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
435     AttributeRefAttrPtr anAttr =
436       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
437     bool isObject = anAttr->isObject();
438     ObjectPtr anObject = anAttr->object();
439
440     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
441     if (anAttrs.size() > 0) {
442       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
443       for(; anAttrIter != anAttrs.end(); anAttrIter++) {
444       if ((*anAttrIter).get() && (*anAttrIter)->id() != theAttribute->id()) {
445           std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
446                               std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
447           if (aRef->isObject() != isObject)
448             continue;
449           if (isObject) {
450             if (aRef->object() == anObject) {
451               theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
452                                       theAttribute->id(), aRef->id());
453               return false;
454             }
455           }
456           else { // the attribute reference
457             AttributePtr anAttributeAttr = anAttr->attr();
458             if (aRef->attr() == anAttributeAttr) {
459               theError = errorMessage(EqualAttributes,
460                                       anAttributeAttr.get() ? anAttributeAttr->id() : "",
461                                       theAttribute->id(), aRef->id());
462               return false;
463             }
464           }
465         }
466       }
467     }
468   }
469   else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
470     AttributeSelectionPtr anAttr =
471       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
472     ResultPtr aContext = anAttr->context();
473     GeomShapePtr aShape = anAttr->value();
474
475     // Check selection attributes
476     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
477     if (anAttrs.size() > 0) {
478       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
479       for(; anAttr != anAttrs.end(); anAttr++) {
480         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
481           std::shared_ptr<ModelAPI_AttributeSelection> aRef =
482                               std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
483           // check the object is already presented
484           if (aRef->context() == aContext) {
485             bool aHasShape = aShape.get() != NULL;
486             if (!aHasShape || aRef->value()->isEqual(aShape)) {
487               theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
488               return false;
489             }
490           }
491         }
492       }
493     }
494   }
495   else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
496     AttributeReferencePtr anAttr =
497       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
498     ObjectPtr anObject = anAttr->value();
499     // Check selection attributes
500     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
501     if (anAttrs.size() > 0) {
502       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
503       for(; anAttr != anAttrs.end(); anAttr++) {
504         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
505           std::shared_ptr<ModelAPI_AttributeReference> aRef =
506             std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
507           // check the object is already presented
508           if (aRef->value() == anObject) {
509             theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
510                                     theAttribute->id(), aRef->id());
511             return false;
512           }
513         }
514         return true;
515       }
516     }
517   }
518   else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
519     std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
520             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
521     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
522     if(anAttrs.size() > 0) {
523       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
524       for(; anAttrItr != anAttrs.end(); anAttrItr++){
525         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
526           std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
527             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
528           for(int i = 0; i < aCurSelList->size(); i++) {
529             std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
530             ResultPtr aCurSelContext = aCurSel->context();
531             ResultCompSolidPtr aCurSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aCurSelContext);
532             std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
533             if(aCurSelCompSolidPtr.get()) {
534               aCurSelCompSolid = aCurSelCompSolidPtr->shape();
535             }
536             for(int j = 0; j < aRefSelList->size(); j++) {
537               std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
538               ResultPtr aRefSelContext = aRefSel->context();
539               ResultCompSolidPtr aRefSelCompSolidPtr =
540                 ModelAPI_Tools::compSolidOwner(aRefSelContext);
541               std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
542               if(aRefSelCompSolidPtr.get()) {
543                 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
544               }
545               if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value()))
546                 || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) {
547                   theError = errorMessage(EqualShapes, "", theAttribute->id(),
548                                           aRefSel->id());
549                   return false;
550               }
551               if(aCurSelContext == aRefSelContext) {
552                 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
553                   theError = errorMessage(EmptyShapes, "", theAttribute->id(),
554                                           aRefSel->id());
555                   return false;
556                 }
557                 if (aCurSel->value()->isEqual(aRefSel->value())) {
558                   theError = errorMessage(EqualShapes, "", theAttribute->id(),
559                                           aRefSel->id());
560                   return false;
561                 }
562               }
563             }
564           }
565         }
566       }
567     }
568   }
569   else if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
570     std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
571       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
572     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId());
573     if (anAttrs.size() > 0) {
574       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
575       for (; anAttrItr != anAttrs.end(); anAttrItr++){
576         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
577           std::shared_ptr<ModelAPI_AttributeRefList> aRefSelList =
578             std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrItr);
579           for (int i = 0; i < aCurSelList->size(); i++) {
580             ObjectPtr aCurSelObject = aCurSelList->object(i);
581             for (int j = 0; j < aRefSelList->size(); j++) {
582               if (aCurSelObject == aRefSelList->object(j)) {
583                 theError = errorMessage(EqualObjects,
584                               aCurSelObject.get() ? aCurSelObject->data()->name() : "",
585                               theAttribute->id(), aCurSelList->id());
586                 return false;
587               }
588             }
589           }
590         }
591       }
592     }
593   }
594   return true;
595 }
596
597 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
598                                      const std::list<std::string>& theArguments,
599                                      Events_InfoMessage& theError) const
600 {
601   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
602     theError = "The attribute with the %1 type is not processed";
603     theError.arg(theAttribute->attributeType());
604     return false;
605   }
606
607   // there is a check whether the feature contains a point and a linear edge or two point values
608   std::string aParamA = theArguments.front();
609   SessionPtr aMgr = ModelAPI_Session::get();
610   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
611
612   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
613   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
614   QList<FeaturePtr> aCoinsideLines;
615   QList<FeaturePtr> aCoins;
616
617   bool isObject = aRefAttr->isObject();
618   ObjectPtr anObject = aRefAttr->object();
619   if (isObject && anObject) {
620     FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
621     AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
622     ObjectPtr aOtherObject = aOtherAttr->object();
623     // if the other attribute is not filled still, the result is true
624     if (!aOtherObject.get())
625       return true;
626     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
627
628     // check that both have coincidence
629     FeaturePtr aConstrFeature;
630     std::set<FeaturePtr> aCoinList;
631     const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
632     std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
633     for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
634       std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
635       aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
636       if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
637         AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
638         AttributePtr aAR = aRAttr->attr();
639         if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
640           aCoinList.insert(aConstrFeature);
641           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
642                                           SketchPlugin_ConstraintCoincidence::ENTITY_A());
643           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
644                                           SketchPlugin_ConstraintCoincidence::ENTITY_B());
645       }
646     }
647     // if there is no coincidence then it is not valid
648     if (aCoinList.size() > 0) {
649       QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
650       bool aValid = false;
651       for (; anIt != aLast && !aValid; anIt++) {
652         aValid = *anIt == aOtherFea;
653       }
654       if (aValid)
655         return true;
656     }
657   }
658   theError = "There is no a common coincident point.";
659   return false;
660 }