Salome HOME
Issue #1343 Fixes
[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   if (theArguments.size() != 2) {
185     theError = "Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
186     return false;
187   }
188   // first argument is for the base attribute, second - for skipping feature kind
189   std::list<std::string>::const_iterator anIt = theArguments.begin();
190   std::string aBaseAttributeId = *anIt;
191   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
192   AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);
193   if (!aBaseAttribute.get()) {
194     theError = "Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
195     return false;
196   }
197   if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
198     // this validator is not necessary anymore
199     return true;
200
201   anIt++;
202   std::string aFeatureAttributeKind = *anIt;
203   GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
204   // check whether the selection is on the sketch
205   std::list<std::string> anArguments;
206   anArguments.push_back(aFeatureAttributeKind);
207
208   bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);
209   bool aPlanarFace = false;
210   // check if selection has Face selected
211   GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
212   anArguments.clear();
213   anArguments.push_back("face");
214   aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
215
216   bool aValid = !aFeatureKind && aPlanarFace;
217   return aValid;
218 }
219
220 //=================================================================================================
221 bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
222                                                  const std::list<std::string>& theArguments,
223                                                  std::string& theError) const
224 {
225   if(theArguments.size() != 2) {
226     theError = "Validator should be used with 2 parameters for extrusion.";
227     return false;
228   }
229
230   std::list<std::string>::const_iterator anArgsIt = theArguments.begin(), aLast = theArguments.end();
231
232   AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
233   ++anArgsIt;
234
235   if(isShapesCanBeEmpty(aCheckAttribute, theError)) {
236     return true;
237   }
238
239   AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
240   if(!aSelAttr.get()) {
241     theError = "Could not get selection attribute \"" + *anArgsIt + "\".";
242     return false;
243   }
244
245   GeomShapePtr aShape = aSelAttr->value();
246   if(!aShape.get()) {
247     ResultPtr aContext = aSelAttr->context();
248     if(!aContext.get()) {
249       theError = "Selection attribute \"" + *anArgsIt + "\" can not be empty.";
250       return false;
251     }
252
253     aShape = aContext->shape();
254   }
255
256   if(!aShape.get()) {
257     theError = "Selection attribute \"" + *anArgsIt + "\" can not be empty.";
258     return false;
259   }
260
261   return true;
262 }
263
264 //=================================================================================================
265 bool FeaturesPlugin_ValidatorCanBeEmpty::isNotObligatory(std::string theFeature, std::string theAttribute)
266 {
267   return false;
268 }
269
270 //=================================================================================================
271 bool FeaturesPlugin_ValidatorCanBeEmpty::isShapesCanBeEmpty(const AttributePtr& theAttribute,
272                                                             std::string& theError) const
273 {
274   if(!theAttribute.get()) {
275     return true;
276   }
277
278   std::string anAttributeType = theAttribute->attributeType();
279   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
280     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
281     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
282       // If at least one attribute is invalid, the result is false.
283       if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
284         return false;
285       }
286     }
287   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
288     // Getting context.
289     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
290     ResultPtr aContext = anAttr->context();
291     if(!aContext.get()) {
292       return false;
293     }
294
295     GeomShapePtr aShape = anAttr->value();
296     GeomShapePtr aContextShape = aContext->shape();
297     if(!aShape.get()) {
298       aShape = aContextShape;
299     }
300     if(!aShape.get()) {
301       return false;
302     }
303
304     if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
305        aShape->shapeType() == GeomAPI_Shape::EDGE ||
306        !aShape->isPlanar()) {
307       return false;
308     }
309   } else {
310     return false;
311   }
312
313   return true;
314 }