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