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