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