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