Salome HOME
Issue #1834: Fix length of lines
[modules/shaper.git] / src / BuildPlugin / BuildPlugin_Validators.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        BuildPlugin_Validators.cpp
4 // Created:     22 March 2016
5 // Author:      Dmitry Bobylev
6
7 #include "BuildPlugin_Validators.h"
8
9 #include <ModelAPI_AttributeSelectionList.h>
10 #include <ModelAPI_ResultConstruction.h>
11
12 #include <GeomAPI_PlanarEdges.h>
13 #include <GeomAPI_Pln.h>
14 #include <GeomAPI_ShapeExplorer.h>
15
16 #include <GeomAlgoAPI_CompoundBuilder.h>
17 #include <GeomAlgoAPI_PaveFiller.h>
18 #include <GeomAlgoAPI_ShapeBuilder.h>
19 #include <GeomAlgoAPI_ShapeTools.h>
20 #include <GeomAlgoAPI_SketchBuilder.h>
21 #include <GeomAlgoAPI_WireBuilder.h>
22
23 #include <GeomValidators_FeatureKind.h>
24 #include <GeomValidators_ShapeType.h>
25
26 #include <Events_InfoMessage.h>
27
28 //=================================================================================================
29 bool BuildPlugin_ValidatorBaseForBuild::isValid(const AttributePtr& theAttribute,
30                                                 const std::list<std::string>& theArguments,
31                                                 Events_InfoMessage& theError) const
32 {
33   // Get base objects list.
34   if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) {
35     std::string aMsg = "Error: BuildPlugin_ValidatorBaseForBuild does "
36                        "not support attribute type '%1'\nOnly '%2' is supported.";
37     Events_InfoMessage("BuildPlugin_Validators", aMsg).
38       arg(theAttribute->attributeType()).arg(ModelAPI_AttributeSelectionList::typeId()).send();
39     return false;
40   }
41   AttributeSelectionListPtr aSelectionList =
42     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
43   if(!aSelectionList.get()) {
44     theError = "Could not get selection list.";
45     return false;
46   }
47   if(aSelectionList->size() == 0) {
48     theError = "Empty selection list.";
49     return false;
50   }
51
52   // Collect base shapes.
53   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
54     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
55     if(!aSelection.get()) {
56       theError = "Could not get selection.";
57       return false;
58     }
59     ResultPtr aContext = aSelection->context();
60     if(!aContext.get()) {
61       theError = "Attribute have empty context.";
62       return false;
63     }
64
65     GeomShapePtr aShape = aSelection->value();
66     GeomShapePtr aContextShape = aContext->shape();
67     if(!aShape.get()) {
68       aShape = aContextShape;
69     }
70     if(!aShape.get()) {
71       theError = "Empty shape selected.";
72       return false;
73     }
74
75     // Check that shapes has acceptable type.
76     GeomValidators_ShapeType aValidatorShapeType;
77     if(!aValidatorShapeType.isValid(aSelection, theArguments, theError)) {
78       return false;
79     }
80
81     // Check that it is shape on sketch.
82     ResultConstructionPtr aConstruction = 
83       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
84     if(aConstruction.get()) {
85       if(aConstruction->isInfinite()) {
86         theError = "Inifinte objects not acceptable.";
87         return false;
88       }
89
90       std::shared_ptr<GeomAPI_PlanarEdges> anEdges = 
91         std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContextShape);
92       if(anEdges.get()) {
93         if(aShape->isEqual(aContextShape)) {
94           // It is whole sketch.
95           return false;
96         }
97
98         continue;
99       }
100     }
101
102     if(!aShape->isEqual(aContextShape)) {
103       // Local selection on body does not allowed.
104       theError = "Selected shape is in the local selection. Only global selection is allowed.";
105       return false;
106     }
107   }
108
109   return true;
110 }
111
112 //=================================================================================================
113 bool BuildPlugin_ValidatorBaseForWire::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
114                                                const std::list<std::string>& theArguments,
115                                                Events_InfoMessage& theError) const
116 {
117   // Get attribute.
118   if(theArguments.size() != 1) {
119     std::string aMsg = "Error: BuildPlugin_ValidatorBaseForWire should be used only "
120                        "with 1 parameter (ID of base objects list).";
121     Events_InfoMessage("BuildPlugin_Validators", aMsg).send();
122     return false;
123   }
124   AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front());
125   if(!aSelectionList.get()) {
126     theError = "Empty attribute \"%1\".";
127     theError.arg(theArguments.front());
128     return false;
129   }
130
131
132   // Collect base shapes.
133   ListOfShape aListOfShapes;
134   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
135     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
136     GeomShapePtr aShape = aSelection->value();
137     if(!aShape.get()) {
138       aShape = aSelection->context()->shape();
139     }
140     aListOfShapes.push_back(aShape);
141   }
142
143   // Create wire.
144   GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes);
145   if(!aWire.get()) {
146     theError = "Result wire empty. Probably it has disconnected edges or non-manifold.";
147     return false;
148   }
149
150   return true;
151 }
152
153 //=================================================================================================
154 bool BuildPlugin_ValidatorBaseForWire::isNotObligatory(std::string theFeature,
155                                                        std::string theAttribute)
156 {
157   return false;
158 }
159
160 //=================================================================================================
161 bool BuildPlugin_ValidatorBaseForFace::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
162                                                const std::list<std::string>& theArguments,
163                                                Events_InfoMessage& theError) const
164 {
165   // Get attribute.
166   if(theArguments.size() != 1) {
167     std::string aMsg = "Error: BuildPlugin_ValidatorBaseForFace should be used only with "
168       "1 parameter (ID of base objects list).";
169     Events_InfoMessage("BuildPlugin_Validators", aMsg).send();
170     return false;
171   }
172   AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front());
173   if(!aSelectionList.get()) {
174     theError = "Empty attribute \"%1\".";
175     theError.arg(theArguments.front());
176     return false;
177   }
178
179   // Collect base shapes.
180   ListOfShape anEdges;
181   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
182     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
183     GeomShapePtr aShape = aSelection->value();
184     if(!aShape.get()) {
185       aShape = aSelection->context()->shape();
186     }
187     for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
188       GeomShapePtr anEdge = anExp.current();
189       anEdges.push_back(anEdge);
190     }
191   }
192
193   // Check that edges does not have intersections.
194   if(anEdges.size() > 1) {
195     GeomAlgoAPI_PaveFiller aPaveFiller(anEdges, false);
196     if(!aPaveFiller.isDone()) {
197       theError = "Error while checking if edges intersects.";
198       return false;
199     }
200     GeomShapePtr aSectedEdges = aPaveFiller.shape();
201
202     int anEdgesNum = 0;
203     for(GeomAPI_ShapeExplorer 
204         anExp(aSectedEdges, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
205       anEdgesNum++;
206     }
207     if(anEdgesNum != anEdges.size()) {
208       theError = "Selected objects have intersections.";
209       return false;
210     }
211   }
212
213   // Check that they are planar.
214   std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
215   if(!aPln.get()) {
216     theError = "Selected objects are not planar.";
217     return false;
218   }
219
220   // Check that selected objects have closed contours.
221   ListOfShape aFaces;
222   GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(), 
223                                          aPln->direction(), anEdges, aFaces);
224   if(aFaces.empty()) {
225     theError = "Selected objects does not have closed contours.";
226     return false;
227   }
228
229   return true;
230 }
231
232 //=================================================================================================
233 bool BuildPlugin_ValidatorBaseForFace::isNotObligatory(std::string theFeature, 
234                                                        std::string theAttribute)
235 {
236   return false;
237 }
238
239 //=================================================================================================
240 bool BuildPlugin_ValidatorSubShapesSelection::isValid(const AttributePtr& theAttribute,
241                                                       const std::list<std::string>& theArguments,
242                                                       Events_InfoMessage& theError) const
243 {
244   if(theArguments.size() != 1) {
245     std::string aMsg = "Error: BuildPlugin_ValidatorSubShapesSelection should be used only with "
246       "1 parameter(Sketch feature id).";
247     Events_InfoMessage("BuildPlugin_Validators", aMsg).send();
248     return false;
249   }
250
251   // Get base objects list.
252   if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) {
253     std::string aMsg = 
254       "Error: BuildPlugin_ValidatorSubShapesSelection does not support attribute type \""
255       "%1\"\n Only \"%2\" supported.";
256     Events_InfoMessage("BuildPlugin_Validators", aMsg).
257       arg(theAttribute->attributeType()).arg(ModelAPI_AttributeSelectionList::typeId()).send();
258     return false;
259   }
260   AttributeSelectionListPtr aSelectionList =
261     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
262   if(!aSelectionList.get()) {
263     theError = "Could not get selection list.";
264     return false;
265   }
266
267   // Get base shape.
268   const std::string aBaseShapeId = "base_shape";
269   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
270   AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeId);
271
272   if(!aShapeAttrSelection.get()) {
273     theError = "Base shape is empty.";
274     return false;
275   }
276
277   ResultPtr aBaseContext = aShapeAttrSelection->context();
278
279   GeomShapePtr aBaseShape  = aShapeAttrSelection->value();
280   if(!aBaseShape.get()) {
281     theError = "Base shape is empty.";
282     return false;
283   }
284
285   GeomAlgoAPI_ShapeBuilder aBuilder;
286   aBuilder.removeInternal(aBaseShape);
287   aBaseShape = aBuilder.shape();
288
289   // If selected shape is wire allow to select only vertices. If face - allow vertices and edges.
290   std::set<GeomAPI_Shape::ShapeType> anAllowedTypes;
291   switch(aBaseShape->shapeType()) {
292     case GeomAPI_Shape::FACE: anAllowedTypes.insert(GeomAPI_Shape::EDGE);
293     case GeomAPI_Shape::WIRE: anAllowedTypes.insert(GeomAPI_Shape::VERTEX);
294     default: break;
295   }
296
297   // Check selected shapes.
298   GeomValidators_FeatureKind aFeatureKindValidator;
299   std::list<std::string> anArguments;
300   anArguments.push_back(theArguments.front());
301   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
302     AttributeSelectionPtr aSelectionAttrInList = aSelectionList->value(anIndex);
303     if(!aSelectionAttrInList.get()) {
304       theError = "Empty attribute in list.";
305       return false;
306     }
307
308     // If context of selection same skip.
309     if(aBaseContext == aSelectionAttrInList->context()) {
310       continue;
311     }
312
313     // Check that it is a selection on Sketch.
314     if(!aFeatureKindValidator.isValid(aSelectionAttrInList, anArguments, theError)) {
315       return false;
316     }
317
318     // Check shape type.
319     GeomShapePtr aShapeInList = aSelectionAttrInList->value();
320     if(!aShapeInList.get()) {
321       aShapeInList = aSelectionAttrInList->context()->shape();
322     }
323     if(anAllowedTypes.find(aShapeInList->shapeType()) == anAllowedTypes.cend()) {
324       theError = "Selected shape has unacceptable type.";
325       return false;
326     }
327
328     // Check that shape inside wire or face.
329     if(!GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aShapeInList, aBaseShape)) {
330       theError = "Selected shape is not inside base face.";
331       return false;
332     }
333   }
334
335   return true;
336 }