Salome HOME
e5147561b74f6ff56915de2ac55469bde86dda35
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Validators.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->\r
2 \r
3 // File:        FeaturesPlugin_Validators.cpp\r
4 // Created:     22 March 2016\r
5 // Author:      Dmitry Bobylev\r
6 \r
7 #include "FeaturesPlugin_Validators.h"\r
8 \r
9 #include "FeaturesPlugin_Union.h"\r
10 \r
11 #include <Events_InfoMessage.h>\r
12 \r
13 #include <ModelAPI_Attribute.h>\r
14 #include <ModelAPI_AttributeInteger.h>\r
15 #include <ModelAPI_AttributeSelectionList.h>\r
16 #include <ModelAPI_AttributeString.h>\r
17 #include <ModelAPI_AttributeReference.h>\r
18 #include <ModelAPI_AttributeRefList.h>\r
19 #include <ModelAPI_Feature.h>\r
20 #include <ModelAPI_ResultCompSolid.h>\r
21 #include <ModelAPI_ResultConstruction.h>\r
22 #include <ModelAPI_Tools.h>\r
23 \r
24 #include <GeomValidators_BodyShapes.h>\r
25 #include <GeomValidators_FeatureKind.h>\r
26 #include <GeomValidators_ShapeType.h>\r
27 \r
28 #include <GeomAPI_DataMapOfShapeShape.h>\r
29 #include <GeomAPI_Lin.h>\r
30 #include <GeomAPI_PlanarEdges.h>\r
31 #include <GeomAPI_ShapeExplorer.h>\r
32 #include <GeomAPI_ShapeIterator.h>\r
33 \r
34 #include <GeomAlgoAPI_CompoundBuilder.h>\r
35 #include <GeomAlgoAPI_ShapeBuilder.h>\r
36 #include <GeomAlgoAPI_ShapeTools.h>\r
37 #include <GeomAlgoAPI_WireBuilder.h>\r
38 \r
39 #define _USE_MATH_DEFINES\r
40 #include <math.h>\r
41 \r
42 //==================================================================================================\r
43 bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,\r
44                                                const std::list<std::string>& theArguments,\r
45                                                Events_InfoMessage& theError) const\r
46 {\r
47   AttributeSelectionPtr aPathAttrSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);\r
48   if(!aPathAttrSelection.get()) {\r
49     theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";\r
50     return false;\r
51   }\r
52 \r
53   GeomShapePtr aPathShape = aPathAttrSelection->value();\r
54   ResultPtr aContext = aPathAttrSelection->context();\r
55   if(!aContext.get()) {\r
56     theError = "Error: Empty context.";\r
57     return false;\r
58   }\r
59   GeomShapePtr aContextShape = aContext->shape();\r
60   if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE && !aPathShape->isEqual(aContextShape)) {\r
61     theError = "Error: Local selection of wires not allowed.";\r
62     return false;\r
63   }\r
64 \r
65   return true;\r
66 }\r
67 \r
68 //==================================================================================================\r
69 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,\r
70                                                     const std::list<std::string>& theArguments,\r
71                                                     Events_InfoMessage& theError) const\r
72 {\r
73   static const std::string aCreationMethodID = "creation_method";\r
74   static const std::string aBaseObjectsID = "base_objects";\r
75   static const std::string aLocationsID = "locations_objects";\r
76 \r
77   if(theFeature->getKind() != "Pipe") {\r
78     theError = "Error: Feature \"%1\" does not supported by this validator.";\r
79     theError.arg(theFeature->getKind());\r
80     return false;\r
81   }\r
82 \r
83   AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);\r
84   if(!aCreationMethodAttr.get()) {\r
85     theError = "Error: Could not get \"%1\" attribute.";\r
86     theError.arg(aCreationMethodID);\r
87     return false;\r
88   }\r
89 \r
90   if(aCreationMethodAttr->value() != "locations") {\r
91     return true;\r
92   }\r
93 \r
94   AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);\r
95   if(!aBaseObjectsSelectionList.get()) {\r
96     theError = "Error: Could not get \"%1\" attribute.";\r
97     theError.arg(aBaseObjectsID);\r
98     return false;\r
99   }\r
100 \r
101   AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);\r
102   if(!aLocationsSelectionList.get()) {\r
103     theError = "Error: Could not get \"%1\" attribute.";\r
104     theError.arg(aBaseObjectsID);\r
105     return false;\r
106   }\r
107 \r
108   if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {\r
109     theError = "Error: Number of locations should be the same as base objects.";\r
110     return false;\r
111   }\r
112 \r
113   return true;\r
114 }\r
115 \r
116 //==================================================================================================\r
117 bool FeaturesPlugin_ValidatorPipeLocations::isNotObligatory(std::string theFeature, std::string theAttribute)\r
118 {\r
119   return false;\r
120 }\r
121 \r
122 //==================================================================================================\r
123 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,\r
124                                                         const std::list<std::string>& theArguments,\r
125                                                         Events_InfoMessage& theError) const\r
126 {\r
127   if(theArguments.empty()) {\r
128     theError = "Error: Validator parameters is empty.";\r
129     return false;\r
130   }\r
131 \r
132   // Checking attribute.\r
133   if(!isValidAttribute(theAttribute, theArguments, theError)) {\r
134     if(theError.empty()) {\r
135       theError = "Error: Attribute contains unacceptable shape.";\r
136     }\r
137     return false;\r
138   }\r
139 \r
140   std::set<ResultConstructionPtr> aSelectedSketches;\r
141   std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;\r
142   GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;\r
143   std::string anAttributeType = theAttribute->attributeType();\r
144   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {\r
145     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);\r
146     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {\r
147       AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);\r
148       ResultPtr aContext = aSelectionAttr->context();\r
149       if(!aContext.get()) {\r
150         theError = "Error: Empty context.";\r
151         return false;\r
152       }\r
153 \r
154       ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);\r
155       if(!aResultConstruction.get()) {\r
156         // It is not a result construction. If shape is compound check that it contains only faces and edges.\r
157         GeomShapePtr aShape = aSelectionAttr->value();\r
158         if(!aShape.get()) {\r
159           aShape = aContext->shape();\r
160         }\r
161 \r
162         if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {\r
163           for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {\r
164             GeomShapePtr aSubShape = anIt.current();\r
165             if(aSubShape->shapeType() != GeomAPI_Shape::EDGE\r
166                 && aSubShape->shapeType() != GeomAPI_Shape::FACE) {\r
167               theError = "Error: Compound should contain only faces and edges.";\r
168               return false;\r
169             }\r
170           }\r
171         }\r
172 \r
173         continue;\r
174       }\r
175 \r
176       GeomShapePtr aShape = aSelectionAttr->value();\r
177       GeomShapePtr aContextShape = aResultConstruction->shape();\r
178       if(!aShape.get()) {\r
179         // Whole sketch selected.\r
180         if(aSelectedSketchesFromObjects.find(aResultConstruction) != aSelectedSketchesFromObjects.cend()) {\r
181           theError = "Error: Object from this sketch is already selected. Sketch is not allowed for selection.";\r
182           return false;\r
183         }\r
184 \r
185         aSelectedSketches.insert(aResultConstruction);\r
186       } else {\r
187         // Object from sketch selected.\r
188         if(aSelectedSketches.find(aResultConstruction) != aSelectedSketches.cend()) {\r
189           theError = "Error: Whole sketch with this object is already selected. Don't allow to select this object.";\r
190           return false;\r
191         }\r
192 \r
193         for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {\r
194           GeomShapePtr aWire = anExp.current();\r
195           if(aWire->orientation() != GeomAPI_Shape::FORWARD) {\r
196             theError = "Error: Wire with wrong orientation selected.";\r
197             return false;\r
198           }\r
199 \r
200           if(aSelectedWiresFromObjects.isBound(aWire)) {\r
201             theError = "Error: Objects with such wire already selected. Don't allow to select this object.";\r
202             return false;\r
203           }\r
204 \r
205           aSelectedWiresFromObjects.bind(aWire, aWire);\r
206           aSelectedSketchesFromObjects.insert(aResultConstruction);\r
207         }\r
208       }\r
209     }\r
210   }\r
211 \r
212   return true;\r
213 }\r
214 \r
215 //==================================================================================================\r
216 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,\r
217                                                                  const std::list<std::string>& theArguments,\r
218                                                                  Events_InfoMessage& theError) const\r
219 {\r
220   if(!theAttribute.get()) {\r
221     theError = "Error: Empty attribute.";\r
222     return false;\r
223   }\r
224 \r
225   std::string anAttributeType = theAttribute->attributeType();\r
226   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {\r
227     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);\r
228     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {\r
229       // If at least one attribute is invalid, the result is false.\r
230       if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {\r
231         return false;\r
232       }\r
233     }\r
234   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {\r
235     // Getting context.\r
236     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);\r
237     ResultPtr aContext = anAttr->context();\r
238     if(!aContext.get()) {\r
239       theError = "Error: Attribute have empty context.";\r
240       return false;\r
241     }\r
242 \r
243     GeomShapePtr aShape = anAttr->value();\r
244     GeomShapePtr aContextShape = aContext->shape();\r
245     if(!aShape.get()) {\r
246       aShape = aContextShape;\r
247     }\r
248     if(!aShape.get()) {\r
249       theError = "Error: Empty shape selected";\r
250       return false;\r
251     }\r
252 \r
253     ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);\r
254     if(aConstruction.get()) {\r
255       // Construciotn selected. Check that is is not infinite.\r
256       if(aConstruction->isInfinite()) {\r
257         theError = "Error: Infinite constructions is not allowed as base.";\r
258         return false;\r
259       }\r
260 \r
261       if(aShape->isEqual(aContextShape)) {\r
262         // Whole construction selected. Check that it have faces.\r
263         if(aConstruction->facesNum() > 0) {\r
264           return true;\r
265         }\r
266       } else {\r
267         // Shape on construction selected. Check that it is a face or wire.\r
268         if(aShape->shapeType() == GeomAPI_Shape::WIRE || aShape->shapeType() == GeomAPI_Shape::FACE) {\r
269           return true;\r
270         }\r
271       }\r
272 \r
273       return false;\r
274     }\r
275 \r
276     if(!aShape->isEqual(aContextShape)) {\r
277       // Local selection on body does not allowed.\r
278       theError = "Error: Selected shape is in the local selection. Only global selection is allowed.";\r
279       return false;\r
280     }\r
281 \r
282     // Check that object is a shape with allowed type.\r
283     GeomValidators_ShapeType aShapeTypeValidator;\r
284     if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {\r
285       theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch(if it has at least one face), and whole objects with shape types: %1";\r
286       std::string anArgumentString;\r
287       for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {\r
288         if (!anArgumentString.empty())\r
289           anArgumentString += ", ";\r
290         anArgumentString += *anIt;\r
291       }\r
292       theError.arg(anArgumentString);\r
293       return false;\r
294     }\r
295 \r
296   } else {\r
297     theError = "Error: Attribute \"%1\" does not supported by this validator.";\r
298     theError.arg(anAttributeType);\r
299     return false;\r
300   }\r
301 \r
302   return true;\r
303 }\r
304 \r
305 //==================================================================================================\r
306 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,\r
307                                                         const std::list<std::string>& theArguments,\r
308                                                         Events_InfoMessage& theError) const\r
309 {\r
310   if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {\r
311     theError = "Error: The attribute with the %1 type is not processed";\r
312     theError.arg(theAttribute->attributeType());\r
313     return false;\r
314   }\r
315   if (theArguments.size() != 2) {\r
316     theError = "Error: Wrong parameters in XML definition for %1 type";\r
317     theError.arg(theAttribute->attributeType());\r
318     return false;\r
319   }\r
320   // first argument is for the base attribute, second - for skipping feature kind\r
321   std::list<std::string>::const_iterator anIt = theArguments.begin();\r
322   std::string aBaseAttributeId = *anIt;\r
323   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());\r
324   AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);\r
325   if (!aBaseAttribute.get()) {\r
326     theError = "Wrong parameters in XML definition for %1 type";\r
327     theError.arg(theAttribute->attributeType());\r
328     return false;\r
329   }\r
330   if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,\r
331     // this validator is not necessary anymore\r
332     return true;\r
333 \r
334   anIt++;\r
335   std::string aFeatureAttributeKind = *anIt;\r
336   GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();\r
337   // check whether the selection is on the sketch\r
338   std::list<std::string> anArguments;\r
339   anArguments.push_back(aFeatureAttributeKind);\r
340 \r
341   bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);\r
342   bool aPlanarFace = false;\r
343   // check if selection has Face selected\r
344   GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();\r
345   anArguments.clear();\r
346   anArguments.push_back("face");\r
347   aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);\r
348 \r
349   bool aValid = !aFeatureKind && aPlanarFace;\r
350   return aValid;\r
351 }\r
352 \r
353 //==================================================================================================\r
354 bool FeaturesPlugin_ValidatorExtrusionDir::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,\r
355                                                  const std::list<std::string>& theArguments,\r
356                                                  Events_InfoMessage& theError) const\r
357 {\r
358   if(theArguments.size() != 2) {\r
359     theError = "Error: Validator should be used with 2 parameters for extrusion.";\r
360     return false;\r
361   }\r
362 \r
363   std::list<std::string>::const_iterator anArgsIt = theArguments.begin(), aLast = theArguments.end();\r
364 \r
365   AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);\r
366   ++anArgsIt;\r
367 \r
368   GeomShapePtr aDirShape;\r
369   AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);\r
370   if(aSelAttr.get()) {\r
371     aDirShape = aSelAttr->value();\r
372     if(!aDirShape.get()) {\r
373       ResultPtr aContext = aSelAttr->context();\r
374       if(aContext.get()) {\r
375         aDirShape = aContext->shape();\r
376       }\r
377     }\r
378   }\r
379 \r
380   if(!aDirShape.get()) {\r
381     // Check that dir can be empty.\r
382     if(!isShapesCanBeEmpty(aCheckAttribute, theError)) {\r
383       theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" can not be used with default value. Select direction for extrusion.";\r
384       theError.arg(*anArgsIt);\r
385       return false;\r
386     } else {\r
387       return true;\r
388     }\r
389   }\r
390 \r
391   std::shared_ptr<GeomAPI_Edge> aDirEdge(new GeomAPI_Edge(aDirShape));\r
392 \r
393   // If faces selected check that direction not parallel with them.\r
394   AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aCheckAttribute);\r
395   for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {\r
396     AttributeSelectionPtr anAttr = aListAttr->value(anIndex);\r
397     GeomShapePtr aShapeInList = anAttr->value();\r
398     if(!aShapeInList.get()) {\r
399       aShapeInList = anAttr->context()->shape();\r
400     }\r
401     bool isParallel = true;\r
402     if(aShapeInList->shapeType() == GeomAPI_Shape::FACE || aShapeInList->shapeType() == GeomAPI_Shape::SHELL) {\r
403       for(GeomAPI_ShapeExplorer anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {\r
404         std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(anExp.current()));\r
405         isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace);\r
406         if(isParallel) {\r
407           break;\r
408         }\r
409       }\r
410     } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) {\r
411       std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShapeInList);\r
412       if(aPlanarEdges.get()) {\r
413         std::shared_ptr<GeomAPI_Dir> aSketchDir = aPlanarEdges->norm();\r
414         if(aDirEdge->isLine()) {\r
415           std::shared_ptr<GeomAPI_Dir> aDir = aDirEdge->line()->direction();\r
416           isParallel = abs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7;\r
417         } else {\r
418           isParallel = false;\r
419         }\r
420       } else {\r
421         isParallel = false;\r
422       }\r
423     } else {\r
424       isParallel = false;\r
425     }\r
426     if(isParallel) {\r
427       theError = "Error: Direction is parallel to one of the selected face or face on selected shell.";\r
428       return false;\r
429     }\r
430   }\r
431 \r
432   return true;\r
433 }\r
434 \r
435 //==================================================================================================\r
436 bool FeaturesPlugin_ValidatorExtrusionDir::isNotObligatory(std::string theFeature, std::string theAttribute)\r
437 {\r
438   return false;\r
439 }\r
440 \r
441 //==================================================================================================\r
442 bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute,\r
443                                                               Events_InfoMessage& theError) const\r
444 {\r
445   if(!theAttribute.get()) {\r
446     return true;\r
447   }\r
448 \r
449   std::string anAttributeType = theAttribute->attributeType();\r
450   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {\r
451     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);\r
452     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {\r
453       // If at least one attribute is invalid, the result is false.\r
454       if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {\r
455         return false;\r
456       }\r
457     }\r
458   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {\r
459     // Getting context.\r
460     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);\r
461     ResultPtr aContext = anAttr->context();\r
462     if(!aContext.get()) {\r
463       return false;\r
464     }\r
465 \r
466     GeomShapePtr aShape = anAttr->value();\r
467     GeomShapePtr aContextShape = aContext->shape();\r
468     if(!aShape.get()) {\r
469       aShape = aContextShape;\r
470     }\r
471     if(!aShape.get()) {\r
472       return false;\r
473     }\r
474 \r
475     if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||\r
476        aShape->shapeType() == GeomAPI_Shape::EDGE ||\r
477        !aShape->isPlanar()) {\r
478       return false;\r
479     }\r
480   } else {\r
481     return false;\r
482   }\r
483 \r
484   return true;\r
485 }\r
486 \r
487 //==================================================================================================\r
488 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,\r
489                                                        const std::list<std::string>& theArguments,\r
490                                                        Events_InfoMessage& theError) const\r
491 {\r
492   AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);\r
493   if(!anAttrSelectionList.get()) {\r
494     theError = "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";\r
495     return false;\r
496   }\r
497   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());\r
498   int anOperationType = aFeature->integer("bool_type")->value();\r
499 \r
500   for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {\r
501     AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);\r
502     if(!anAttrSelection.get()) {\r
503       theError = "Error: Empty attribute selection.";\r
504       return false;\r
505     }\r
506     ResultPtr aContext = anAttrSelection->context();\r
507     if(!aContext.get()) {\r
508       theError = "Error: Empty selection context.";\r
509       return false;\r
510     }\r
511     ResultConstructionPtr aResultConstruction =\r
512       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);\r
513     if(aResultConstruction.get()) {\r
514       theError = "Error: Result construction not allowed for selection.";\r
515       return false;\r
516     }\r
517     std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();\r
518     GeomShapePtr aContextShape = aContext->shape();\r
519     if(!aShape.get()) {\r
520       aShape = aContextShape;\r
521     }\r
522     if(!aShape.get()) {\r
523       theError = "Error: Empty shape.";\r
524       return false;\r
525     }\r
526     if(!aShape->isEqual(aContextShape)) {\r
527       theError = "Error: Local selection not allowed.";\r
528       return false;\r
529     }\r
530 \r
531     int aShapeType = aShape->shapeType();\r
532     if(anOperationType == 1) {\r
533       // Fuse operation. Allow to select edges, faces and solids.\r
534       if(aShapeType != GeomAPI_Shape::EDGE &&\r
535          aShapeType != GeomAPI_Shape::FACE &&\r
536          aShapeType != GeomAPI_Shape::SOLID &&\r
537          aShapeType != GeomAPI_Shape::COMPSOLID &&\r
538          aShapeType != GeomAPI_Shape::COMPOUND) {\r
539         theError = "Error: Selected shape has the wrong type.";\r
540         return false;\r
541       }\r
542     } else {\r
543       if(aShapeType != GeomAPI_Shape::SOLID &&\r
544          aShapeType != GeomAPI_Shape::COMPSOLID &&\r
545          aShapeType != GeomAPI_Shape::COMPOUND) {\r
546         theError = "Error: Selected shape has the wrong type.";\r
547         return false;\r
548       }\r
549     }\r
550   }\r
551 \r
552   return true;\r
553 }\r
554 \r
555 //==================================================================================================\r
556 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,\r
557                                                          const std::list<std::string>& theArguments,\r
558                                                          Events_InfoMessage& theError) const\r
559 {\r
560   AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);\r
561   if(!anAttrSelectionList.get()) {\r
562     theError = "Error: This validator can only work with selection list in \"Partition\" feature.";\r
563     return false;\r
564   }\r
565 \r
566   for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {\r
567     AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);\r
568 \r
569     //GeomValidators_BodyShapes aBodyValidator;\r
570     //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {\r
571     //  continue;\r
572     //}\r
573 \r
574     GeomValidators_FeatureKind aFeatureKindValidator;\r
575     if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {\r
576       continue;\r
577     }\r
578 \r
579     ResultPtr aContext = aSelectAttr->context();\r
580     ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);\r
581     if(aResultConstruction.get()) {\r
582       theError = "Error: Only body shapes and construction planes are allowed for selection.";\r
583       return false;\r
584     }\r
585 \r
586     ResultCompSolidPtr aResultCompsolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);\r
587     if(aResultCompsolid.get()) {\r
588       continue;\r
589     }\r
590 \r
591     theError = "Error: Only body shapes and construction planes are allowed for selection.";\r
592     return false;\r
593   }\r
594 \r
595   theError = "";\r
596   return true;\r
597 }\r
598 \r
599 //==================================================================================================\r
600 bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,\r
601                                                                const std::list<std::string>& theArguments,\r
602                                                                Events_InfoMessage& theError) const\r
603 {\r
604   AttributeSelectionListPtr aSubShapesAttrList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);\r
605   if(!aSubShapesAttrList.get()) {\r
606     theError = "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";\r
607     return false;\r
608   }\r
609 \r
610   static const std::string aBaseShapeID = "base_shape";\r
611   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());\r
612   AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);\r
613 \r
614   if(!aShapeAttrSelection.get()) {\r
615     theError = "Error: Could not get \"%1\" attribute.";\r
616     theError.arg(aBaseShapeID);\r
617     return false;\r
618   }\r
619 \r
620   GeomShapePtr aBaseShape = aShapeAttrSelection->value();\r
621   ResultPtr aContext = aShapeAttrSelection->context();\r
622   if(!aContext.get()) {\r
623     theError = "Error: Empty context.";\r
624     return false;\r
625   }\r
626   if(!aBaseShape.get()) {\r
627     aBaseShape = aContext->shape();\r
628   }\r
629   if(!aBaseShape.get()) {\r
630     theError = "Error: Empty base shape.";\r
631     return false;\r
632   }\r
633 \r
634   for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {\r
635     bool isSameFound = false;\r
636     AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);\r
637     GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();\r
638     for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {\r
639       if(anIt.current()->isEqual(aShapeToAdd)) {\r
640         isSameFound = true;\r
641         break;\r
642       }\r
643     }\r
644     if(!isSameFound) {\r
645       theError = "Error: Only sub-shapes of selected shape is allowed for selection.";\r
646       return false;\r
647     }\r
648   }\r
649 \r
650   return true;\r
651 }\r
652 \r
653 //==================================================================================================\r
654 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,\r
655                                                             const std::list<std::string>& theArguments,\r
656                                                             Events_InfoMessage& theError) const\r
657 {\r
658   static const std::string aBaseShapeID = "base_shape";\r
659   static const std::string aSubShapesID = "subshapes";\r
660 \r
661   if(theFeature->getKind() != "Remove_SubShapes") {\r
662     theError = "Error: Feature \"%1\" does not supported by this validator.";\r
663     theError.arg(theFeature->getKind());\r
664     return false;\r
665   }\r
666 \r
667   AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);\r
668   if(!aShapeAttrSelection.get()) {\r
669     theError = "Error: Could not get \"%1\" attribute.";\r
670     theError.arg(aBaseShapeID);\r
671     return false;\r
672   }\r
673 \r
674   AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);\r
675   if(!aSubShapesAttrList.get()) {\r
676     theError = "Error: Could not get \"%1\" attribute.";\r
677     theError.arg(aSubShapesID);\r
678     return false;\r
679   }\r
680 \r
681   // Copy base shape.\r
682   GeomShapePtr aBaseShape = aShapeAttrSelection->value();\r
683   if(!aBaseShape.get()) {\r
684     theError = "Error: Base shape is empty.";\r
685     return false;\r
686   }\r
687   GeomShapePtr aResultShape = aBaseShape->emptyCopied();\r
688 \r
689   // Copy sub-shapes from list to new shape.\r
690   for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {\r
691     AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);\r
692     GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();\r
693     GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);\r
694   }\r
695 \r
696   // Check new shape.\r
697   if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {\r
698     theError = "Error: Resulting shape is not valid.";\r
699     return false;\r
700   }\r
701 \r
702   return true;\r
703 }\r
704 \r
705 //==================================================================================================\r
706 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isNotObligatory(std::string theFeature,\r
707                                                                     std::string theAttribute)\r
708 {\r
709   return false;\r
710 }\r
711 \r
712 //==================================================================================================\r
713 bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute,\r
714                                                      const std::list<std::string>& theArguments,\r
715                                                      Events_InfoMessage& theError) const\r
716 {\r
717   AttributeSelectionListPtr aBaseObjectsAttrList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);\r
718   if(!aBaseObjectsAttrList.get()) {\r
719     theError = "Error: This validator can only work with selection list in \"%1\" feature.";\r
720     theError.arg(FeaturesPlugin_Union::ID());\r
721     return false;\r
722   }\r
723 \r
724   for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {\r
725     bool isSameFound = false;\r
726     AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);\r
727     ResultCompSolidPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(anAttrSelectionInList->context());\r
728     if(!aResult.get()) {\r
729       continue;\r
730     }\r
731     if(aResult->numberOfSubs() > 0) {\r
732       theError = "Error: Whole compsolids not allowed for selection.";\r
733       return false;\r
734     }\r
735   }\r
736 \r
737   return true;\r
738 }\r
739 \r
740 //==================================================================================================\r
741 bool FeaturesPlugin_ValidatorUnionArguments::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,\r
742                                                      const std::list<std::string>& theArguments,\r
743                                                      Events_InfoMessage& theError) const\r
744 {\r
745   // Check feature kind.\r
746   if(theFeature->getKind() != FeaturesPlugin_Union::ID()) {\r
747     theError = "Error: This validator supports only \"%1\" feature.";\r
748     theError.arg(FeaturesPlugin_Union::ID());\r
749     return false;\r
750   }\r
751 \r
752   // Get base objects attribute list.\r
753   AttributeSelectionListPtr aBaseObejctsAttrList = theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());\r
754   if(!aBaseObejctsAttrList.get()) {\r
755     theError = "Error: Could not get \"%1\" attribute.";\r
756     theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID());\r
757     return false;\r
758   }\r
759 \r
760   // Get all shapes.\r
761   ListOfShape aBaseShapesList;\r
762   for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {\r
763     AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);\r
764     GeomShapePtr aShape = anAttrSelectionInList->value();\r
765     aBaseShapesList.push_back(aShape);\r
766   }\r
767 \r
768   // Make componud and find connected.\r
769   GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);\r
770   ListOfShape aCombined, aFree;\r
771   GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCombined, aFree);\r
772 \r
773   if(aFree.size() > 0 || aCombined.size() > 1) {\r
774     theError = "Error: Not all shapes have shared topology.";\r
775     return false;\r
776   }\r
777 \r
778   return true;\r
779 }\r
780 \r
781 //==================================================================================================\r
782 bool FeaturesPlugin_ValidatorUnionArguments::isNotObligatory(std::string theFeature,\r
783                                                              std::string theAttribute)\r
784 {\r
785   return false;\r
786 }\r
787 \r
788 bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute,\r
789                                             const std::list<std::string>& theArguments,\r
790                                             Events_InfoMessage& theError) const\r
791 {\r
792   if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {\r
793     theError = "Error: The attribute with the %1 type is not processed";\r
794     theError.arg(theAttribute->attributeType());\r
795     return false;\r
796   }\r
797 \r
798   AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeReference>\r
799                                                                                (theAttribute);\r
800   ObjectPtr aRefObject = aRefAttribute->value();\r
801   if (!aRefObject.get()) {\r
802     theError = "Error: Empty feature.";\r
803     return false;\r
804   }\r
805 \r
806   FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aRefObject);\r
807   if (!aRefFeature.get()) {\r
808     theError = "Error: Empty feature.";\r
809     return false;\r
810   }\r
811   std::list<std::shared_ptr<ModelAPI_Result> > aResults;\r
812   ModelAPI_Tools::getConcealedResults(aRefFeature, aResults);\r
813 \r
814   size_t aConcealedResults = aResults.size();\r
815   if (!aConcealedResults && !theArguments.empty()) {\r
816     // find if these results are touched by the feature in another attribute\r
817     std::list<std::string>::const_iterator anIt = theArguments.begin();\r
818     std::string aRecoveredList = *anIt;\r
819     if (!aRecoveredList.empty()) {\r
820       std::shared_ptr<ModelAPI_AttributeRefList> aParameterList =\r
821                                  theAttribute->owner()->data()->reflist(aRecoveredList);\r
822       if (aParameterList.get())\r
823         aConcealedResults = aParameterList->size();\r
824     }\r
825   }\r
826 \r
827   if (aConcealedResults == 0)\r
828     theError = "Error: No concealed results.";\r
829 \r
830   return theError.empty();\r
831 }\r