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