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