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