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