1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: FeaturesPlugin_Validators.cpp
4 // Created: 22 March 2016
5 // Author: Dmitry Bobylev
7 #include "FeaturesPlugin_Validators.h"
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>
17 #include <Events_Error.h>
19 #include <GeomValidators_FeatureKind.h>
20 #include <GeomValidators_ShapeType.h>
22 #include <GeomAPI_DataMapOfShapeShape.h>
23 #include <GeomAPI_PlanarEdges.h>
24 #include <GeomAPI_ShapeExplorer.h>
25 #include <GeomAlgoAPI_WireBuilder.h>
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
32 static const std::string aCreationMethodID = "creation_method";
33 static const std::string aBaseObjectsID = "base_objects";
34 static const std::string aLocationsID = "locations_objects";
36 if(theFeature->getKind() != "Pipe") {
37 theError = "Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
41 AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
42 if(!aCreationMethodAttr.get()) {
43 theError = "Could not get \"" + aCreationMethodID + "\" attribute.";
47 if(aCreationMethodAttr->value() != "locations") {
51 AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
52 if(!aBaseObjectsSelectionList.get()) {
53 theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
57 AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
58 if(!aLocationsSelectionList.get()) {
59 theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
63 if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
64 theError = "Number of locations should be the same as base objects.";
71 //==================================================================================================
72 bool FeaturesPlugin_ValidatorPipeLocations::isNotObligatory(std::string theFeature, std::string theAttribute)
77 //==================================================================================================
78 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
79 const std::list<std::string>& theArguments,
80 std::string& theError) const
82 if(theArguments.empty()) {
83 theError = "Validator parameters is empty.";
87 // Checking attribute.
88 if(!isValidAttribute(theAttribute, theArguments, theError)) {
89 if(theError.empty()) {
90 theError = "Attribute contains unacceptable shape.";
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.
109 GeomShapePtr aShape = aSelectionAttr->value();
110 GeomShapePtr aContextShape = aContext->shape();
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.";
118 aSelectedSketches.insert(aContext);
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.";
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.";
133 if(aSelectedWiresFromObjects.isBound(aWire)) {
134 theError = "Objects with such wire already selected. Don't allow to select this object.";
138 aSelectedWiresFromObjects.bind(aWire, aWire);
139 aSelectedSketchesFromObjects.insert(aContext);
148 //==================================================================================================
149 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
150 const std::list<std::string>& theArguments,
151 std::string& theError) const
153 if(!theAttribute.get()) {
154 theError = "Empty attribute.";
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)) {
167 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
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.";
176 GeomShapePtr aShape = anAttr->value();
177 GeomShapePtr aContextShape = aContext->shape();
179 aShape = aContextShape;
182 theError = "Empty shape selected";
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.";
194 if(aShape->isEqual(aContextShape)) {
195 // Whole construction selected. Check that it have faces.
196 if(aConstruction->facesNum() > 0) {
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) {
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.";
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();
222 for(++anIt; anIt != theArguments.cend(); ++anIt) {
223 theError += ", " + *anIt;
229 theError = "Following attribute does not supported: " + anAttributeType + ".";
236 //==================================================================================================
237 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
238 const std::list<std::string>& theArguments,
239 std::string& theError) const
241 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
242 theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
245 if (theArguments.size() != 2) {
246 theError = "Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
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";
258 if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
259 // this validator is not necessary anymore
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);
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();
274 anArguments.push_back("face");
275 aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
277 bool aValid = !aFeatureKind && aPlanarFace;
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
286 if(theArguments.size() != 2) {
287 theError = "Validator should be used with 2 parameters for extrusion.";
291 std::list<std::string>::const_iterator anArgsIt = theArguments.begin(), aLast = theArguments.end();
293 AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
296 if(isShapesCanBeEmpty(aCheckAttribute, theError)) {
300 AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
301 if(!aSelAttr.get()) {
302 theError = "Could not get selection attribute \"" + *anArgsIt + "\".";
306 GeomShapePtr aShape = aSelAttr->value();
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.";
315 aShape = aContext->shape();
319 theError = "Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
320 + "\" can not be used with default value. Select direction for extrusion.";
327 //==================================================================================================
328 bool FeaturesPlugin_ValidatorCanBeEmpty::isNotObligatory(std::string theFeature, std::string theAttribute)
333 //==================================================================================================
334 bool FeaturesPlugin_ValidatorCanBeEmpty::isShapesCanBeEmpty(const AttributePtr& theAttribute,
335 std::string& theError) const
337 if(!theAttribute.get()) {
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)) {
350 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
352 AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
353 ResultPtr aContext = anAttr->context();
354 if(!aContext.get()) {
358 GeomShapePtr aShape = anAttr->value();
359 GeomShapePtr aContextShape = aContext->shape();
361 aShape = aContextShape;
367 if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
368 aShape->shapeType() == GeomAPI_Shape::EDGE ||
369 !aShape->isPlanar()) {
379 //==================================================================================================
380 bool FeaturesPlugin_ValidatorBaseForWire::isValid(const AttributePtr& theAttribute,
381 const std::list<std::string>& theArguments,
382 std::string& theError) const
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.");
390 AttributeSelectionListPtr aSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
391 if(!aSelectionList.get()) {
392 theError = "Could not get selection list.";
395 if(aSelectionList->size() == 0) {
396 theError = "Empty selection list.";
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.";
408 ResultPtr aContext = aSelection->context();
409 if(!aContext.get()) {
410 theError = "Attribute have empty context.";
414 GeomShapePtr aShape = aSelection->value();
415 GeomShapePtr aContextShape = aContext->shape();
417 aShape = aContextShape;
420 theError = "Empty shape selected.";
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.";
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.";
438 std::shared_ptr<GeomAPI_PlanarEdges> anEdges = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContextShape);
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.";
450 aListOfShapes.push_back(aShape);
454 GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes);
456 theError = "Result wire empty. Probably it has disconnected edges or non-manifold.";
463 //==================================================================================================
464 bool FeaturesPlugin_BooleanSelection::isValid(const AttributePtr& theAttribute,
465 const std::list<std::string>& theArguments,
466 std::string& theError) const
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.";
473 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
474 int anOperationType = aFeature->integer("bool_type")->value();
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.";
482 ResultPtr aContext = anAttrSelection->context();
483 if(!aContext.get()) {
484 theError = "Error: empty selection context.";
487 ResultConstructionPtr aResultConstruction =
488 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
489 if(aResultConstruction.get()) {
490 theError = "Error: Result construction not allowed for selection.";
493 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
495 aShape = aContext->shape();
498 theError = "Error: empty shape.";
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.";
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.";