Salome HOME
Issue #1343. Improvement of Extrusion and Revolution operations: sketch creator setSe...
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Validators.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        FeaturesPlugin_Validators.cpp
4 // Created:     22 March 2016
5 // Author:      Dmitry Bobylev
6
7 #include "FeaturesPlugin_Validators.h"
8
9 #include <ModelAPI_Attribute.h>
10 #include <ModelAPI_AttributeSelectionList.h>
11 #include <ModelAPI_AttributeString.h>
12 #include <ModelAPI_ResultConstruction.h>
13 #include <ModelAPI_AttributeReference.h>
14
15 #include <GeomValidators_FeatureKind.h>
16 #include <GeomValidators_ShapeType.h>
17
18 //=================================================================================================
19 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
20                                                     const std::list<std::string>& theArguments,
21                                                     std::string& theError) const
22 {
23   static const std::string aCreationMethodID = "creation_method";
24   static const std::string aBaseObjectsID = "base_objects";
25   static const std::string aLocationsID = "locations_objects";
26
27   if(theFeature->getKind() != "Pipe") {
28     theError = "Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
29     return false;
30   }
31
32   AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
33   if(!aCreationMethodAttr.get()) {
34     theError = "Could not get \"" + aCreationMethodID + "\" attribute.";
35     return false;
36   }
37
38   if(aCreationMethodAttr->value() != "locations") {
39     return true;
40   }
41
42   AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
43   if(!aBaseObjectsSelectionList.get()) {
44     theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
45     return false;
46   }
47
48   AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
49   if(!aLocationsSelectionList.get()) {
50     theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
51     return false;
52   }
53
54   if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
55     theError = "Number of locations should be the same as base objects.";
56     return false;
57   }
58
59   return true;
60 }
61
62 //=================================================================================================
63 bool FeaturesPlugin_ValidatorPipeLocations::isNotObligatory(std::string theFeature, std::string theAttribute)
64 {
65   return false;
66 }
67
68 //=================================================================================================
69 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
70                                                         const std::list<std::string>& theArguments,
71                                                         std::string& theError) const
72 {
73   if(theArguments.empty()) {
74     theError = "Validator parameters is empty.";
75     return false;
76   }
77
78   // Checking attribute.
79   if(!isValidAttribute(theAttribute, theArguments, theError)) {
80     if(theError.empty()) {
81       theError = "Attribute contains unacceptable shape.";
82     }
83     return false;
84   }
85
86   return true;
87 }
88
89 //=================================================================================================
90 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
91                                                                  const std::list<std::string>& theArguments,
92                                                                  std::string& theError) const
93 {
94   if(!theAttribute.get()) {
95     theError = "Empty attribute.";
96     return false;
97   }
98
99   std::string anAttributeType = theAttribute->attributeType();
100   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
101     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
102     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
103       // If at least one attribute is invalid, the result is false.
104       if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {
105         return false;
106       }
107     }
108   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
109     // Getting context.
110     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
111     ResultPtr aContext = anAttr->context();
112     if(!aContext.get()) {
113       theError = "Attribute have empty context.";
114       return false;
115     }
116
117     GeomShapePtr aShape = anAttr->value();
118     GeomShapePtr aContextShape = aContext->shape();
119     if(!aShape.get()) {
120       aShape = aContextShape;
121     }
122     if(!aShape.get()) {
123       theError = "Empty shape selected";
124       return false;
125     }
126
127     ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
128     if(aConstruction.get()) {
129       // Construciotn selected. Check that is is not infinite.
130       if(aConstruction->isInfinite()) {
131         theError = "Infinite constructions is not allowed as base.";
132         return false;
133       }
134
135       if(aShape->isEqual(aContextShape)) {
136         // Whole construction selected. Check that it have faces.
137         if(aConstruction->facesNum() > 0) {
138           return true;
139         }
140       } else {
141         // Shape on construction selected. Check that it is a face or wire.
142         if(aShape->shapeType() == GeomAPI_Shape::WIRE || aShape->shapeType() == GeomAPI_Shape::FACE) {
143           return true;
144         }
145       }
146     }
147
148     if(!aShape->isEqual(aContextShape)) {
149       // Local selection on body does not allowed.
150       theError = "Selected shape is in the local selection. Only global selection is allowed.";
151       return false;
152     }
153
154     // Check that object is a shape with allowed type.
155     GeomValidators_ShapeType aShapeTypeValidator;
156     if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
157       theError = "Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, \
158                   whole sketch(if it has at least one face), and whole objects with shape types: ";
159       std::list<std::string>::const_iterator anIt = theArguments.cbegin();
160       theError += *anIt;
161       for(++anIt; anIt != theArguments.cend(); ++anIt) {
162         theError += ", " + *anIt;
163       }
164       return false;
165     }
166
167   } else {
168     theError = "Following attribute does not supported: " + anAttributeType + ".";
169     return false;
170   }
171
172   return true;
173 }
174
175 //=================================================================================================
176 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
177                                                         const std::list<std::string>& theArguments,
178                                                         std::string& theError) const
179 {
180   if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
181     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
182     return false;
183   }
184
185   bool aValid = true;
186   GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
187   // check whether the selection is on the sketch
188   bool aFeatureKindValid = aValidator->isValid(theAttribute, theArguments, theError);
189   if (!aFeatureKindValid) {
190     // check if selection has Face selected
191     GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
192     std::list<std::string> anArguments;
193     anArguments.push_back("face");
194     aValid = aShapeType->isValid(theAttribute, anArguments, theError);
195   }
196   return aValid;
197 }
198
199 //=================================================================================================
200 bool FeaturesPlugin_ValidatorCompositeLauncher_::isValid(const AttributePtr& theAttribute,
201                                                         const std::list<std::string>& theArguments,
202                                                         std::string& theError) const
203 {
204   FeaturesPlugin_ValidatorBaseForGeneration aBaseValidator;
205
206   if(aBaseValidator.isValid(theAttribute, theArguments, theError)) {
207     return true;
208   }
209
210   // Check that face selected.
211   GeomValidators_ShapeType aShapeType;
212   std::list<std::string> anArguments;
213   anArguments.push_back("face");
214   if(aShapeType.isValid(theAttribute, anArguments, theError)) {
215     return true;
216   }
217
218   theError = "Selected shape is not suitable for this operation";
219
220   return false;
221 }
222
223 //=================================================================================================
224 bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
225                                                  const std::list<std::string>& theArguments,
226                                                  std::string& theError) const
227 {
228   if(theArguments.size() != 5 && theArguments.size() != 6) {
229     theError = "Validator should be used with 6 parameters for extrusion and with 5 for revolution.";
230     return false;
231   }
232
233   std::list<std::string>::const_iterator anArgsIt = theArguments.begin(), aLast = theArguments.end();
234
235   std::string aSelectedMethod;
236   if(theFeature->string(*anArgsIt)) {
237     aSelectedMethod = theFeature->string(*anArgsIt)->value();
238   }
239   ++anArgsIt;
240   std::string aCreationMethod = *anArgsIt;
241   ++anArgsIt;
242
243   AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
244   ++anArgsIt;
245
246   if(isShapesCanBeEmpty(aCheckAttribute, theError)) {
247     return true;
248   }
249
250   if(aSelectedMethod == aCreationMethod) {
251     ++anArgsIt;
252     ++anArgsIt;
253   }
254
255   for(; anArgsIt != theArguments.cend(); ++anArgsIt) {
256     AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
257     if(!aSelAttr.get()) {
258       theError = "Could not get selection attribute \"" + *anArgsIt + "\".";
259       return false;
260     }
261
262     GeomShapePtr aShape = aSelAttr->value();
263     if(!aShape.get()) {
264       ResultPtr aContext = aSelAttr->context();
265       if(!aContext.get()) {
266         theError = "Selection attribute \"" + *anArgsIt + "\" can not be empty.";
267         return false;
268       }
269
270       aShape = aContext->shape();
271     }
272
273     if(!aShape.get()) {
274       theError = "Selection attribute \"" + *anArgsIt + "\" can not be empty.";
275       return false;
276     }
277   }
278
279   return true;
280 }
281
282 //=================================================================================================
283 bool FeaturesPlugin_ValidatorCanBeEmpty::isNotObligatory(std::string theFeature, std::string theAttribute)
284 {
285   return false;
286 }
287
288 //=================================================================================================
289 bool FeaturesPlugin_ValidatorCanBeEmpty::isShapesCanBeEmpty(const AttributePtr& theAttribute,
290                                                             std::string& theError) const
291 {
292   if(!theAttribute.get()) {
293     return true;
294   }
295
296   std::string anAttributeType = theAttribute->attributeType();
297   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
298     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
299     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
300       // If at least one attribute is invalid, the result is false.
301       if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
302         return false;
303       }
304     }
305   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
306     // Getting context.
307     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
308     ResultPtr aContext = anAttr->context();
309     if(!aContext.get()) {
310       return false;
311     }
312
313     GeomShapePtr aShape = anAttr->value();
314     GeomShapePtr aContextShape = aContext->shape();
315     if(!aShape.get()) {
316       aShape = aContextShape;
317     }
318     if(!aShape.get()) {
319       return false;
320     }
321
322     if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
323        aShape->shapeType() == GeomAPI_Shape::EDGE ||
324        !aShape->isPlanar()) {
325       return false;
326     }
327   } else {
328     return false;
329   }
330
331   return true;
332 }