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