]> SALOME platform Git repositories - modules/shaper.git/blob - src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
Salome HOME
Issue #1367: Fill feature.
[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_AttributeInteger.h>
11 #include <ModelAPI_AttributeSelectionList.h>
12 #include <ModelAPI_AttributeString.h>
13 #include <ModelAPI_AttributeReference.h>
14 #include <ModelAPI_Feature.h>
15 #include <ModelAPI_ResultConstruction.h>
16
17 #include <Events_Error.h>
18
19 #include <GeomValidators_FeatureKind.h>
20 #include <GeomValidators_ShapeType.h>
21
22 #include <GeomAPI_DataMapOfShapeShape.h>
23 #include <GeomAPI_PlanarEdges.h>
24 #include <GeomAPI_ShapeExplorer.h>
25 #include <GeomAlgoAPI_WireBuilder.h>
26
27 //==================================================================================================
28 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
29                                                     const std::list<std::string>& theArguments,
30                                                     std::string& theError) const
31 {
32   static const std::string aCreationMethodID = "creation_method";
33   static const std::string aBaseObjectsID = "base_objects";
34   static const std::string aLocationsID = "locations_objects";
35
36   if(theFeature->getKind() != "Pipe") {
37     theError = "Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
38     return false;
39   }
40
41   AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
42   if(!aCreationMethodAttr.get()) {
43     theError = "Could not get \"" + aCreationMethodID + "\" attribute.";
44     return false;
45   }
46
47   if(aCreationMethodAttr->value() != "locations") {
48     return true;
49   }
50
51   AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
52   if(!aBaseObjectsSelectionList.get()) {
53     theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
54     return false;
55   }
56
57   AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
58   if(!aLocationsSelectionList.get()) {
59     theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
60     return false;
61   }
62
63   if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
64     theError = "Number of locations should be the same as base objects.";
65     return false;
66   }
67
68   return true;
69 }
70
71 //==================================================================================================
72 bool FeaturesPlugin_ValidatorPipeLocations::isNotObligatory(std::string theFeature, std::string theAttribute)
73 {
74   return false;
75 }
76
77 //==================================================================================================
78 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
79                                                         const std::list<std::string>& theArguments,
80                                                         std::string& theError) const
81 {
82   if(theArguments.empty()) {
83     theError = "Validator parameters is empty.";
84     return false;
85   }
86
87   // Checking attribute.
88   if(!isValidAttribute(theAttribute, theArguments, theError)) {
89     if(theError.empty()) {
90       theError = "Attribute contains unacceptable shape.";
91     }
92     return false;
93   }
94
95   std::set<ResultConstructionPtr> aSelectedSketches;
96   std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;
97   GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;
98   std::string anAttributeType = theAttribute->attributeType();
99   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
100     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
101     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
102       AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
103       ResultConstructionPtr aContext = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelectionAttr->context());
104       if(!aContext.get()) {
105         // It is not a result construction, continue.
106         continue;
107       }
108
109       GeomShapePtr aShape = aSelectionAttr->value();
110       GeomShapePtr aContextShape = aContext->shape();
111       if(!aShape.get()) {
112         // Whole sketch selected.
113         if(aSelectedSketchesFromObjects.find(aContext) != aSelectedSketchesFromObjects.cend()) {
114           theError = "Object from this sketch is already selected. Sketch is not allowed for selection.";
115           return false;
116         }
117
118         aSelectedSketches.insert(aContext);
119       } else {
120         // Object from sketch selected.
121         if(aSelectedSketches.find(aContext) != aSelectedSketches.cend()) {
122           theError = "Whole sketch with this object is already selected. Don't allow to select this object.";
123           return false;
124         }
125
126         for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
127           GeomShapePtr aWire = anExp.current();
128           if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
129             theError = "Wire with wrong orientation selected.";
130             return false;
131           }
132
133           if(aSelectedWiresFromObjects.isBound(aWire)) {
134             theError = "Objects with such wire already selected. Don't allow to select this object.";
135             return false;
136           }
137
138           aSelectedWiresFromObjects.bind(aWire, aWire);
139           aSelectedSketchesFromObjects.insert(aContext);
140         }
141       }
142     }
143   }
144
145   return true;
146 }
147
148 //==================================================================================================
149 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
150                                                                  const std::list<std::string>& theArguments,
151                                                                  std::string& theError) const
152 {
153   if(!theAttribute.get()) {
154     theError = "Empty attribute.";
155     return false;
156   }
157
158   std::string anAttributeType = theAttribute->attributeType();
159   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
160     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
161     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
162       // If at least one attribute is invalid, the result is false.
163       if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {
164         return false;
165       }
166     }
167   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
168     // Getting context.
169     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
170     ResultPtr aContext = anAttr->context();
171     if(!aContext.get()) {
172       theError = "Attribute have empty context.";
173       return false;
174     }
175
176     GeomShapePtr aShape = anAttr->value();
177     GeomShapePtr aContextShape = aContext->shape();
178     if(!aShape.get()) {
179       aShape = aContextShape;
180     }
181     if(!aShape.get()) {
182       theError = "Empty shape selected";
183       return false;
184     }
185
186     ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
187     if(aConstruction.get()) {
188       // Construciotn selected. Check that is is not infinite.
189       if(aConstruction->isInfinite()) {
190         theError = "Infinite constructions is not allowed as base.";
191         return false;
192       }
193
194       if(aShape->isEqual(aContextShape)) {
195         // Whole construction selected. Check that it have faces.
196         if(aConstruction->facesNum() > 0) {
197           return true;
198         }
199       } else {
200         // Shape on construction selected. Check that it is a face or wire.
201         if(aShape->shapeType() == GeomAPI_Shape::WIRE || aShape->shapeType() == GeomAPI_Shape::FACE) {
202           return true;
203         }
204       }
205
206       return false;
207     }
208
209     if(!aShape->isEqual(aContextShape)) {
210       // Local selection on body does not allowed.
211       theError = "Selected shape is in the local selection. Only global selection is allowed.";
212       return false;
213     }
214
215     // Check that object is a shape with allowed type.
216     GeomValidators_ShapeType aShapeTypeValidator;
217     if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
218       theError = "Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, "
219                  "whole sketch(if it has at least one face), and whole objects with shape types: ";
220       std::list<std::string>::const_iterator anIt = theArguments.cbegin();
221       theError += *anIt;
222       for(++anIt; anIt != theArguments.cend(); ++anIt) {
223         theError += ", " + *anIt;
224       }
225       return false;
226     }
227
228   } else {
229     theError = "Following attribute does not supported: " + anAttributeType + ".";
230     return false;
231   }
232
233   return true;
234 }
235
236 //==================================================================================================
237 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
238                                                         const std::list<std::string>& theArguments,
239                                                         std::string& theError) const
240 {
241   if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
242     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
243     return false;
244   }
245   if (theArguments.size() != 2) {
246     theError = "Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
247     return false;
248   }
249   // first argument is for the base attribute, second - for skipping feature kind
250   std::list<std::string>::const_iterator anIt = theArguments.begin();
251   std::string aBaseAttributeId = *anIt;
252   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
253   AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);
254   if (!aBaseAttribute.get()) {
255     theError = "Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
256     return false;
257   }
258   if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
259     // this validator is not necessary anymore
260     return true;
261
262   anIt++;
263   std::string aFeatureAttributeKind = *anIt;
264   GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
265   // check whether the selection is on the sketch
266   std::list<std::string> anArguments;
267   anArguments.push_back(aFeatureAttributeKind);
268
269   bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);
270   bool aPlanarFace = false;
271   // check if selection has Face selected
272   GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
273   anArguments.clear();
274   anArguments.push_back("face");
275   aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
276
277   bool aValid = !aFeatureKind && aPlanarFace;
278   return aValid;
279 }
280
281 //==================================================================================================
282 bool FeaturesPlugin_ValidatorCanBeEmpty::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
283                                                  const std::list<std::string>& theArguments,
284                                                  std::string& theError) const
285 {
286   if(theArguments.size() != 2) {
287     theError = "Validator should be used with 2 parameters for extrusion.";
288     return false;
289   }
290
291   std::list<std::string>::const_iterator anArgsIt = theArguments.begin(), aLast = theArguments.end();
292
293   AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
294   ++anArgsIt;
295
296   if(isShapesCanBeEmpty(aCheckAttribute, theError)) {
297     return true;
298   }
299
300   AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
301   if(!aSelAttr.get()) {
302     theError = "Could not get selection attribute \"" + *anArgsIt + "\".";
303     return false;
304   }
305
306   GeomShapePtr aShape = aSelAttr->value();
307   if(!aShape.get()) {
308     ResultPtr aContext = aSelAttr->context();
309     if(!aContext.get()) {
310       theError = "Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
311                + "\" can not be used with default value. Select direction for extrusion.";
312       return false;
313     }
314
315     aShape = aContext->shape();
316   }
317
318   if(!aShape.get()) {
319     theError = "Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
320               + "\" can not be used with default value. Select direction for extrusion.";
321     return false;
322   }
323
324   return true;
325 }
326
327 //==================================================================================================
328 bool FeaturesPlugin_ValidatorCanBeEmpty::isNotObligatory(std::string theFeature, std::string theAttribute)
329 {
330   return false;
331 }
332
333 //==================================================================================================
334 bool FeaturesPlugin_ValidatorCanBeEmpty::isShapesCanBeEmpty(const AttributePtr& theAttribute,
335                                                             std::string& theError) const
336 {
337   if(!theAttribute.get()) {
338     return true;
339   }
340
341   std::string anAttributeType = theAttribute->attributeType();
342   if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
343     AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
344     for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
345       // If at least one attribute is invalid, the result is false.
346       if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
347         return false;
348       }
349     }
350   } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
351     // Getting context.
352     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
353     ResultPtr aContext = anAttr->context();
354     if(!aContext.get()) {
355       return false;
356     }
357
358     GeomShapePtr aShape = anAttr->value();
359     GeomShapePtr aContextShape = aContext->shape();
360     if(!aShape.get()) {
361       aShape = aContextShape;
362     }
363     if(!aShape.get()) {
364       return false;
365     }
366
367     if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
368        aShape->shapeType() == GeomAPI_Shape::EDGE ||
369        !aShape->isPlanar()) {
370       return false;
371     }
372   } else {
373     return false;
374   }
375
376   return true;
377 }
378
379 //==================================================================================================
380 bool FeaturesPlugin_ValidatorBaseForWire::isValid(const AttributePtr& theAttribute,
381                                                   const std::list<std::string>& theArguments,
382                                                   std::string& theError) const
383 {
384   // Get base objects list.
385   if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) {
386     Events_Error::send("Validator does not support attribute type \"" + theAttribute->attributeType()
387       + "\"\n Only \"" + ModelAPI_AttributeSelectionList::typeId() + "\" supported.");
388     return false;
389   }
390   AttributeSelectionListPtr aSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
391   if(!aSelectionList.get()) {
392     theError = "Could not get selection list.";
393     return false;
394   }
395   if(aSelectionList->size() == 0) {
396     theError = "Empty selection list.";
397     return false;
398   }
399
400   // Collect base shapes.
401   ListOfShape aListOfShapes;
402   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
403     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
404     if(!aSelection.get()) {
405       theError = "Could not get selection.";
406       return false;
407     }
408     ResultPtr aContext = aSelection->context();
409     if(!aContext.get()) {
410       theError = "Attribute have empty context.";
411       return false;
412     }
413
414     GeomShapePtr aShape = aSelection->value();
415     GeomShapePtr aContextShape = aContext->shape();
416     if(!aShape.get()) {
417       aShape = aContextShape;
418     }
419     if(!aShape.get()) {
420       theError = "Empty shape selected.";
421       return false;
422     }
423
424     // Check that shape has acceptable type.
425     if(aShape->shapeType() != GeomAPI_Shape::EDGE && aShape->shapeType() != GeomAPI_Shape::WIRE) {
426       theError = "Selected shape has wrong type. Only edges and wires acceptable.";
427       return false;
428     }
429
430     // Check that it is edge on sketch.
431     ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
432     if(aConstruction.get()) {
433       if(aConstruction->isInfinite()) {
434         theError = "Inifinte objects not acceptable.";
435         return false;
436       }
437
438       std::shared_ptr<GeomAPI_PlanarEdges> anEdges = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContextShape);
439       if(!anEdges.get()) {
440         // It is not an edge on the sketch.
441         // Check that it is not local selection.
442         if(!aShape->isEqual(aContextShape)) {
443           // Local selection on body does not allowed.
444           theError = "Selected shape is in the local selection. Only global selection is allowed.";
445           return false;
446         }
447       }
448     }
449
450     aListOfShapes.push_back(aShape);
451   }
452
453   // Create wire.
454   GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes);
455   if(!aWire.get()) {
456     theError = "Result wire empty. Probably it has disconnected edges or non-manifold.";
457     return false;
458   }
459
460   return true;
461 }
462
463 //==================================================================================================
464 bool FeaturesPlugin_BooleanSelection::isValid(const AttributePtr& theAttribute,
465                                               const std::list<std::string>& theArguments,
466                                               std::string& theError) const
467 {
468   AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
469   if(!anAttrSelectionList.get()) {
470     theError = "Error: this validator can only work with selection list attributes in Boolean feature.";
471     return false;
472   }
473   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
474   int anOperationType = aFeature->integer("bool_type")->value();
475
476   for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
477     AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
478     if(!anAttrSelection.get()) {
479       theError = "Error: empty attribute selection.";
480       return false;
481     }
482     ResultPtr aContext = anAttrSelection->context();
483     if(!aContext.get()) {
484       theError = "Error: empty selection context.";
485       return false;
486     }
487     ResultConstructionPtr aResultConstruction =
488       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
489     if(aResultConstruction.get()) {
490       theError = "Error: Result construction not allowed for selection.";
491       return false;
492     }
493     std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
494     if(!aShape.get()) {
495       aShape = aContext->shape();
496     }
497     if(!aShape.get()) {
498       theError = "Error: empty shape.";
499       return false;
500     }
501     int aShapeType = aShape->shapeType();
502     if(anOperationType == 1) {
503       // Fuse operation. Allow to select edges, faces and solids.
504       if(aShapeType != GeomAPI_Shape::EDGE &&
505          aShapeType != GeomAPI_Shape::FACE &&
506          aShapeType != GeomAPI_Shape::SOLID &&
507          aShapeType != GeomAPI_Shape::COMPSOLID &&
508          aShapeType != GeomAPI_Shape::COMPOUND) {
509         theError = "Error: selected shape has the wrong type.";
510         return false;
511       }
512     } else {
513       if(aShapeType != GeomAPI_Shape::SOLID &&
514          aShapeType != GeomAPI_Shape::COMPSOLID &&
515          aShapeType != GeomAPI_Shape::COMPOUND) {
516         theError = "Error: selected shape has the wrong type.";
517         return false;
518       }
519     }
520   }
521
522   return true;
523 }