Salome HOME
Show "not loaded" suffix for names of not loaded parts
[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_ResultBody.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 bool PartSet_IntersectionSelection::isValid(const ModuleBase_ISelection* theSelection,
411                                      ModuleBase_Operation* theOperation) const
412 {
413   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
414     return isEmptySelectionValid(theOperation);
415   } else {
416     int aCount = shapesNbLines(theSelection);
417     return aCount == 0;
418   }
419 }
420
421
422 std::string PartSet_DifferentObjectsValidator::errorMessage(
423                          const PartSet_DifferentObjectsValidator::ErrorType& theType,
424                          const std::string& thEqualObject, const std::string& theFirstAttribute,
425                          const std::string& theSecondAttribute) const
426 {
427   std::string anError;
428   switch (theType) {
429     case EqualObjects:
430       anError = "The feature uses one " + thEqualObject + " object in " +
431                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
432       break;
433     case EqualAttributes:
434       anError = "The feature uses reference to one " + thEqualObject + " attribute in " +
435                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
436       break;
437     case EqualShapes:
438       anError = "The feature uses one shape in " +
439                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
440       break;
441     case EmptyShapes:
442       anError = "The feature uses empty shapes in " +
443                 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
444       break;
445       break;
446     default:
447       break;
448   }
449   return anError;
450 }
451
452 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
453                                                 const std::list<std::string>& theArguments,
454                                                 Events_InfoMessage& theError) const
455 {
456   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
457
458   // the type of validated attributes should be equal, attributes with
459   // different types are not validated
460   // Check RefAttr attributes
461   std::string anAttrType = theAttribute->attributeType();
462   std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
463
464   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
465     AttributeRefAttrPtr anAttr =
466       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
467     bool isObject = anAttr->isObject();
468     ObjectPtr anObject = anAttr->object();
469
470     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
471     if (anAttrs.size() > 0) {
472       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
473       for(; anAttrIter != anAttrs.end(); anAttrIter++) {
474       if ((*anAttrIter).get() && (*anAttrIter)->id() != theAttribute->id()) {
475           std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
476                               std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
477           if (aRef->isObject() != isObject)
478             continue;
479           if (isObject) {
480             if (aRef->object() == anObject) {
481               theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
482                                       theAttribute->id(), aRef->id());
483               return false;
484             }
485           }
486           else { // the attribute reference
487             AttributePtr anAttributeAttr = anAttr->attr();
488             if (aRef->attr() == anAttributeAttr) {
489               theError = errorMessage(EqualAttributes,
490                                       anAttributeAttr.get() ? anAttributeAttr->id() : "",
491                                       theAttribute->id(), aRef->id());
492               return false;
493             }
494           }
495         }
496       }
497     }
498   }
499   else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
500     AttributeSelectionPtr anAttr =
501       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
502     ResultPtr aContext = anAttr->context();
503     FeaturePtr aContextFeature = anAttr->contextFeature();
504     GeomShapePtr aShape = anAttr->value();
505
506     // Check selection attributes
507     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
508     if (anAttrs.size() > 0) {
509       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
510       for(; anAttr != anAttrs.end(); anAttr++) {
511         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
512           std::shared_ptr<ModelAPI_AttributeSelection> aRef =
513                               std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
514           // check the object is already presented
515           if (aRef->context() == aContext) {
516             bool aHasShape = aShape.get() != NULL;
517             if (!aHasShape || aRef->value()->isEqual(aShape)) {
518               theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
519               return false;
520             }
521           }
522           // check the whole selected feature contains the result
523           if (aContextFeature.get()) {
524             if (aRef->contextFeature().get()) {
525               if (aContextFeature == aRef->contextFeature()) {
526                 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
527                 return false;
528               }
529             } else if (aRef->context().get() &&
530                 aRef->context()->document()->feature(aRef->context()) == aContextFeature) {
531               theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
532               return false;
533             }
534           } else if (aRef->contextFeature().get() && aContext.get()) {
535             if (aContext->document()->feature(aContext) == aRef->contextFeature()) {
536               theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
537               return false;
538             }
539           }
540         }
541       }
542     }
543   }
544   else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
545     AttributeReferencePtr anAttr =
546       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
547     ObjectPtr anObject = anAttr->value();
548     // Check selection attributes
549     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
550     if (anAttrs.size() > 0) {
551       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
552       for(; anAttr != anAttrs.end(); anAttr++) {
553         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
554           std::shared_ptr<ModelAPI_AttributeReference> aRef =
555             std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
556           // check the object is already presented
557           if (aRef->value() == anObject) {
558             theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
559                                     theAttribute->id(), aRef->id());
560             return false;
561           }
562         }
563         return true;
564       }
565     }
566   }
567   else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
568     std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
569             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
570     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
571     if(anAttrs.size() > 0) {
572       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
573       for(; anAttrItr != anAttrs.end(); anAttrItr++){
574         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
575           std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
576             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
577           for(int i = 0; i < aCurSelList->size(); i++) {
578             std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
579             ResultPtr aCurSelContext = aCurSel->context();
580             FeaturePtr aCurSelFeature = aCurSel->contextFeature();
581             ResultBodyPtr aCurSelCompSolidPtr = ModelAPI_Tools::bodyOwner(aCurSelContext);
582             std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
583             if(aCurSelCompSolidPtr.get()) {
584               aCurSelCompSolid = aCurSelCompSolidPtr->shape();
585             }
586             for(int j = 0; j < aRefSelList->size(); j++) {
587               std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
588               ResultPtr aRefSelContext = aRefSel->context();
589               FeaturePtr aRefSelFeature = aRefSel->contextFeature();
590               ResultBodyPtr aRefSelCompSolidPtr =
591                 ModelAPI_Tools::bodyOwner(aRefSelContext);
592               std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
593               if (aRefSelCompSolidPtr.get()) {
594                 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
595               }
596               if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value()))
597                 || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) {
598                 theError = errorMessage(EqualShapes, "", theAttribute->id(),
599                   aRefSel->id());
600                 return false;
601               }
602               if (aCurSelContext == aRefSelContext) {
603                 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
604                   theError = errorMessage(EmptyShapes, "", theAttribute->id(), aRefSel->id());
605                   return false;
606                 }
607                 if (aCurSel->value()->isEqual(aRefSel->value())) {
608                   theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
609                   return false;
610                 }
611               }
612
613               // check the whole selected feature contains the result
614               if (aCurSelFeature.get()) {
615                 if (aRefSelFeature.get()) {
616                   if (aCurSelFeature == aRefSelFeature) {
617                     theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
618                     return false;
619                   }
620                 }
621                 else if (aRefSelContext.get() &&
622                   aRefSelContext->document()->feature(aRefSelContext) == aCurSelFeature) {
623                   theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
624                   return false;
625                 }
626               }
627               else if (aRefSelFeature.get() && aCurSelContext.get()) {
628                 if (aCurSelContext->document()->feature(aCurSelContext) == aRefSelFeature) {
629                   theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
630                   return false;
631                 }
632               }
633             }
634           }
635         }
636       }
637     }
638   }
639   else if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
640     std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
641       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
642     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId());
643     if (anAttrs.size() > 0) {
644       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
645       for (; anAttrItr != anAttrs.end(); anAttrItr++){
646         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
647           std::shared_ptr<ModelAPI_AttributeRefList> aRefSelList =
648             std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrItr);
649           for (int i = 0; i < aCurSelList->size(); i++) {
650             ObjectPtr aCurSelObject = aCurSelList->object(i);
651             for (int j = 0; j < aRefSelList->size(); j++) {
652               if (aCurSelObject == aRefSelList->object(j)) {
653                 theError = errorMessage(EqualObjects,
654                               aCurSelObject.get() ? aCurSelObject->data()->name() : "",
655                               theAttribute->id(), aCurSelList->id());
656                 return false;
657               }
658             }
659           }
660         }
661       }
662     }
663   }
664   return true;
665 }
666
667 bool PartSet_DifferentPointsValidator::isValid(const AttributePtr& theAttribute,
668                                                const std::list<std::string>& theArguments,
669                                                Events_InfoMessage& theError) const
670 {
671   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
672
673   // the type of validated attributes should be equal, attributes with
674   // different types are not validated
675   // Check RefAttr attributes
676   std::string anAttrType = theAttribute->attributeType();
677   std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
678   if (anAttrType != ModelAPI_AttributeRefAttr::typeId())
679     return true;
680
681   // obtain point of the given attribute
682   AttributePoint2DPtr anAttributePoint = getRefPointAttribute(theAttribute);
683   if (!anAttributePoint.get() || !anAttributePoint->isInitialized())
684     return true;
685
686   // obtain point of the parameter attribute
687   AttributePoint2DPtr anArgumentPoint = getRefPointAttribute
688                                               (aFeature->attribute(theArguments.front()));
689
690   if (!anArgumentPoint.get() || !anArgumentPoint->isInitialized())
691     return true;
692
693   return !anAttributePoint->pnt()->isEqual(anArgumentPoint->pnt());
694 }
695
696 AttributePoint2DPtr PartSet_DifferentPointsValidator::getRefPointAttribute
697                                                      (const AttributePtr& theAttribute) const
698 {
699   AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
700
701   AttributePoint2DPtr aPointAttribute;
702   if (anAttr->isObject()) {
703     ObjectPtr anObject  = anAttr->object();
704     if (anObject.get()) {
705       FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
706       if (aFeature->getKind() == SketchPlugin_Point::ID())
707         aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>
708                                           (aFeature->attribute(SketchPlugin_Point::COORD_ID()));
709     }
710   }
711   else {
712     aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
713   }
714   return aPointAttribute;
715 }
716
717 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
718                                      const std::list<std::string>& theArguments,
719                                      Events_InfoMessage& theError) const
720 {
721   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
722     theError = "The attribute with the %1 type is not processed";
723     theError.arg(theAttribute->attributeType());
724     return false;
725   }
726
727   // there is a check whether the feature contains a point and a linear edge or two point values
728   std::string aParamA = theArguments.front();
729   SessionPtr aMgr = ModelAPI_Session::get();
730   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
731
732   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
733   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
734   QList<FeaturePtr> aCoinsideLines;
735   QList<FeaturePtr> aCoins;
736
737   bool isObject = aRefAttr->isObject();
738   ObjectPtr anObject = aRefAttr->object();
739   if (isObject && anObject) {
740     FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
741     AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
742     ObjectPtr aOtherObject = aOtherAttr->object();
743     // if the other attribute is not filled still, the result is true
744     if (!aOtherObject.get())
745       return true;
746     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
747
748     // check that both have coincidence
749     FeaturePtr aConstrFeature;
750     std::set<FeaturePtr> aCoinList;
751     const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
752     std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
753     for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
754       std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
755       aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
756       if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
757         AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
758         AttributePtr aAR = aRAttr->attr();
759         if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
760           aCoinList.insert(aConstrFeature);
761           QList<bool> anIsAttributes;
762           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
763                                           SketchPlugin_ConstraintCoincidence::ENTITY_A(),
764                                           anIsAttributes);
765           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
766                                           SketchPlugin_ConstraintCoincidence::ENTITY_B(),
767                                           anIsAttributes);
768       }
769     }
770     // if there is no coincidence then it is not valid
771     if (aCoinList.size() > 0) {
772       QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
773       bool aValid = false;
774       for (; anIt != aLast && !aValid; anIt++) {
775         aValid = *anIt == aOtherFea;
776       }
777       if (aValid)
778         return true;
779     }
780   }
781   theError = "There is no a common coincident point.";
782   return false;
783 }