1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "FeaturesPlugin_Validators.h"
23 #include "FeaturesPlugin_Boolean.h"
24 #include "FeaturesPlugin_BooleanSmash.h"
25 #include "FeaturesPlugin_Union.h"
27 #include <Events_InfoMessage.h>
29 #include <ModelAPI_Attribute.h>
30 #include <ModelAPI_AttributeInteger.h>
31 #include <ModelAPI_AttributeSelectionList.h>
32 #include <ModelAPI_AttributeString.h>
33 #include <ModelAPI_AttributeReference.h>
34 #include <ModelAPI_AttributeRefList.h>
35 #include <ModelAPI_Feature.h>
36 #include <ModelAPI_ResultCompSolid.h>
37 #include <ModelAPI_ResultConstruction.h>
38 #include <ModelAPI_Tools.h>
40 #include <GeomValidators_BodyShapes.h>
41 #include <GeomValidators_Face.h>
42 #include <GeomValidators_FeatureKind.h>
43 #include <GeomValidators_ShapeType.h>
45 #include <GeomAPI_DataMapOfShapeShape.h>
46 #include <GeomAPI_Lin.h>
47 #include <GeomAPI_PlanarEdges.h>
48 #include <GeomAPI_Pln.h>
49 #include <GeomAPI_ShapeExplorer.h>
50 #include <GeomAPI_ShapeIterator.h>
52 #include <GeomAlgoAPI_CompoundBuilder.h>
53 #include <GeomAlgoAPI_ShapeBuilder.h>
54 #include <GeomAlgoAPI_ShapeTools.h>
55 #include <GeomAlgoAPI_WireBuilder.h>
57 #define _USE_MATH_DEFINES
60 //==================================================================================================
61 bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
62 const std::list<std::string>& theArguments,
63 Events_InfoMessage& theError) const
65 AttributeSelectionPtr aPathAttrSelection =
66 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
67 if(!aPathAttrSelection.get()) {
68 theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
72 GeomShapePtr aPathShape = aPathAttrSelection->value();
73 ResultPtr aContext = aPathAttrSelection->context();
75 theError = "Error: Empty context.";
78 GeomShapePtr aContextShape = aContext->shape();
79 if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE &&
80 !aPathShape->isEqual(aContextShape)) {
81 theError = "Error: Local selection of wires not allowed.";
88 //==================================================================================================
89 bool FeaturesPlugin_ValidatorPipeLocations::isValid(
90 const std::shared_ptr<ModelAPI_Feature>& theFeature,
91 const std::list<std::string>& theArguments,
92 Events_InfoMessage& theError) const
94 static const std::string aCreationMethodID = "creation_method";
95 static const std::string aBaseObjectsID = "base_objects";
96 static const std::string aLocationsID = "locations_objects";
98 if(theFeature->getKind() != "Pipe") {
99 theError = "Error: Feature \"%1\" does not supported by this validator.";
100 theError.arg(theFeature->getKind());
104 AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
105 if(!aCreationMethodAttr.get()) {
106 theError = "Error: Could not get \"%1\" attribute.";
107 theError.arg(aCreationMethodID);
111 if(aCreationMethodAttr->value() != "locations") {
115 AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
116 if(!aBaseObjectsSelectionList.get()) {
117 theError = "Error: Could not get \"%1\" attribute.";
118 theError.arg(aBaseObjectsID);
122 AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
123 if(!aLocationsSelectionList.get()) {
124 theError = "Error: Could not get \"%1\" attribute.";
125 theError.arg(aBaseObjectsID);
129 if(aLocationsSelectionList->size() > 0 &&
130 aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
131 theError = "Error: Number of locations should be the same as base objects.";
138 //==================================================================================================
139 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
140 const std::list<std::string>& theArguments,
141 Events_InfoMessage& theError) const
143 if(theArguments.empty()) {
144 theError = "Error: Validator parameters is empty.";
148 // Checking attribute.
149 if(!isValidAttribute(theAttribute, theArguments, theError)) {
150 if(theError.empty()) {
151 theError = "Error: Attribute contains unacceptable shape.";
156 GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;
157 std::string anAttributeType = theAttribute->attributeType();
158 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
159 AttributeSelectionListPtr aListAttr =
160 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
161 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
162 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
163 ResultPtr aContext = aSelectionAttr->context();
164 if(!aContext.get()) {
165 theError = "Error: Empty context.";
169 ResultConstructionPtr aResultConstruction =
170 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
171 if(!aResultConstruction.get()) {
172 // It is not a result construction.
173 // If shape is compound check that it contains only faces and edges.
174 GeomShapePtr aShape = aSelectionAttr->value();
176 aShape = aContext->shape();
179 if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
180 for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
181 GeomShapePtr aSubShape = anIt.current();
182 if(aSubShape->shapeType() != GeomAPI_Shape::EDGE
183 && aSubShape->shapeType() != GeomAPI_Shape::FACE) {
184 theError = "Error: Compound should contain only faces and edges.";
193 GeomShapePtr aShape = aSelectionAttr->value();
194 GeomShapePtr aContextShape = aResultConstruction->shape();
196 // Whole sketch selected.
199 // Object from sketch selected.
200 for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
201 GeomShapePtr aWire = anExp.current();
202 if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
203 theError = "Error: Wire with wrong orientation selected.";
207 if(aSelectedWiresFromObjects.isBound(aWire)) {
209 "Error: Objects with such wire already selected. Don't allow to select this object.";
213 aSelectedWiresFromObjects.bind(aWire, aWire);
222 //==================================================================================================
223 bool FeaturesPlugin_ValidatorBaseForGenerationSketchOrSketchObjects::isValid(
224 const std::shared_ptr<ModelAPI_Feature>& theFeature,
225 const std::list<std::string>& theArguments,
226 Events_InfoMessage& theError) const
228 const std::string aBaseObjectsID = theArguments.front();
230 AttributeSelectionListPtr aListAttr = theFeature->selectionList(aBaseObjectsID);
231 if(!aListAttr.get()) {
232 theError = "Error: Could not get \"%1\" attribute.";
233 theError.arg(aBaseObjectsID);
237 std::set<ResultConstructionPtr> aSelectedSketches;
238 std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;
240 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
241 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
242 ResultPtr aContext = aSelectionAttr->context();
243 if(!aContext.get()) {
244 theError = "Error: Empty context.";
248 ResultConstructionPtr aResultConstruction =
249 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
250 if(!aResultConstruction.get()) {
251 // It is not a result construction.
255 GeomShapePtr aShape = aSelectionAttr->value();
256 GeomShapePtr aContextShape = aResultConstruction->shape();
258 // Whole sketch selected.
259 aSelectedSketches.insert(aResultConstruction);
261 // Object from sketch selected.
262 aSelectedSketchesFromObjects.insert(aResultConstruction);
267 for(std::set<ResultConstructionPtr>::const_iterator anIt = aSelectedSketches.cbegin();
268 anIt != aSelectedSketches.cend();
270 ResultConstructionPtr aResultConstruction = *anIt;
271 if(aSelectedSketchesFromObjects.find(aResultConstruction) !=
272 aSelectedSketchesFromObjects.cend()) {
273 theError = "Sketch and objects from it can not be selected at the same time.";
281 //==================================================================================================
282 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
283 const std::list<std::string>& theArguments,
284 Events_InfoMessage& theError) const
286 if(!theAttribute.get()) {
287 theError = "Error: Empty attribute.";
291 std::string anAttributeType = theAttribute->attributeType();
292 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
293 AttributeSelectionListPtr aListAttr =
294 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
295 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
296 // If at least one attribute is invalid, the result is false.
297 if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {
301 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
303 AttributeSelectionPtr anAttr =
304 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
305 ResultPtr aContext = anAttr->context();
306 if(!aContext.get()) {
307 theError = "Error: Attribute have empty context.";
311 GeomShapePtr aShape = anAttr->value();
312 GeomShapePtr aContextShape = aContext->shape();
314 aShape = aContextShape;
317 theError = "Error: Empty shape selected";
321 ResultConstructionPtr aConstruction =
322 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
323 if(aConstruction.get()) {
324 // Construciotn selected. Check that is is not infinite.
325 if(aConstruction->isInfinite()) {
326 theError = "Error: Infinite constructions is not allowed as base.";
330 if(aShape->isEqual(aContextShape)) {
331 // Whole construction selected. Check that it have faces.
332 if(aConstruction->facesNum() > 0) {
336 // Shape on construction selected. Check that it is a face or wire.
337 if(aShape->shapeType() == GeomAPI_Shape::WIRE ||
338 aShape->shapeType() == GeomAPI_Shape::FACE) {
346 if(!aShape->isEqual(aContextShape)) {
347 // Local selection on body does not allowed.
349 "Error: Selected shape is in the local selection. Only global selection is allowed.";
353 // Check that object is a shape with allowed type.
354 GeomValidators_ShapeType aShapeTypeValidator;
355 if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
356 theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or "
357 "wires on sketch, whole sketch(if it has at least one face), "
358 "and whole objects with shape types: %1";
359 std::string anArgumentString;
360 for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {
361 if (!anArgumentString.empty())
362 anArgumentString += ", ";
363 anArgumentString += *anIt;
365 theError.arg(anArgumentString);
370 theError = "Error: Attribute \"%1\" does not supported by this validator.";
371 theError.arg(anAttributeType);
378 //==================================================================================================
379 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
380 const std::list<std::string>& theArguments,
381 Events_InfoMessage& theError) const
383 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
384 theError = "Error: The attribute with the %1 type is not processed";
385 theError.arg(theAttribute->attributeType());
388 if (theArguments.size() != 2) {
389 theError = "Error: Wrong parameters in XML definition for %1 type";
390 theError.arg(theAttribute->attributeType());
393 // first argument is for the base attribute, second - for skipping feature kind
394 std::list<std::string>::const_iterator anIt = theArguments.begin();
395 std::string aBaseAttributeId = *anIt;
396 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
397 AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);
398 if (!aBaseAttribute.get()) {
399 theError = "Wrong parameters in XML definition for %1 type";
400 theError.arg(theAttribute->attributeType());
403 if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
404 // this validator is not necessary anymore
408 std::string aFeatureAttributeKind = *anIt;
409 GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
410 // check whether the selection is on the sketch
411 std::list<std::string> anArguments;
412 anArguments.push_back(aFeatureAttributeKind);
414 bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);
415 bool aPlanarFace = false;
416 // check if selection has Face selected
417 GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
419 anArguments.push_back("face");
420 aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
422 bool aValid = !aFeatureKind && aPlanarFace;
426 //==================================================================================================
427 bool FeaturesPlugin_ValidatorExtrusionDir::isValid(
428 const std::shared_ptr<ModelAPI_Feature>& theFeature,
429 const std::list<std::string>& theArguments,
430 Events_InfoMessage& theError) const
432 if(theArguments.size() != 2) {
433 theError = "Error: Validator should be used with 2 parameters for extrusion.";
437 std::list<std::string>::const_iterator
438 anArgsIt = theArguments.begin(), aLast = theArguments.end();
440 AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
443 GeomShapePtr aDirShape;
444 AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
446 aDirShape = aSelAttr->value();
447 if(!aDirShape.get()) {
448 ResultPtr aContext = aSelAttr->context();
450 aDirShape = aContext->shape();
455 if(!aDirShape.get()) {
456 // Check that dir can be empty.
457 if(!isShapesCanBeEmpty(aCheckAttribute, theError)) {
458 theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" "
459 "can not be used with default value. Select direction for extrusion.";
460 theError.arg(*anArgsIt);
467 std::shared_ptr<GeomAPI_Edge> aDirEdge(new GeomAPI_Edge(aDirShape));
469 // If faces selected check that direction not parallel with them.
470 AttributeSelectionListPtr aListAttr =
471 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aCheckAttribute);
472 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
473 AttributeSelectionPtr anAttr = aListAttr->value(anIndex);
474 GeomShapePtr aShapeInList = anAttr->value();
475 if(!aShapeInList.get()) {
476 aShapeInList = anAttr->context()->shape();
478 bool isParallel = true;
479 if(aShapeInList->shapeType() == GeomAPI_Shape::FACE ||
480 aShapeInList->shapeType() == GeomAPI_Shape::SHELL) {
481 for(GeomAPI_ShapeExplorer
482 anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
483 std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(anExp.current()));
484 isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace);
489 } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) {
490 std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges =
491 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShapeInList);
492 if(aPlanarEdges.get()) {
493 std::shared_ptr<GeomAPI_Dir> aSketchDir = aPlanarEdges->norm();
494 if(aDirEdge->isLine()) {
495 std::shared_ptr<GeomAPI_Dir> aDir = aDirEdge->line()->direction();
496 isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7;
508 "Error: Direction is parallel to one of the selected face or face on selected shell.";
516 //==================================================================================================
517 bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute,
518 Events_InfoMessage& theError) const
520 if(!theAttribute.get()) {
524 std::string anAttributeType = theAttribute->attributeType();
525 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
526 AttributeSelectionListPtr aListAttr =
527 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
528 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
529 // If at least one attribute is invalid, the result is false.
530 if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
534 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
536 AttributeSelectionPtr anAttr =
537 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
538 ResultPtr aContext = anAttr->context();
539 if(!aContext.get()) {
543 GeomShapePtr aShape = anAttr->value();
544 GeomShapePtr aContextShape = aContext->shape();
546 aShape = aContextShape;
552 if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
553 aShape->shapeType() == GeomAPI_Shape::EDGE ||
554 !aShape->isPlanar()) {
564 //==================================================================================================
565 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
566 const std::list<std::string>& theArguments,
567 Events_InfoMessage& theError) const
569 AttributeSelectionListPtr anAttrSelectionList =
570 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
571 if(!anAttrSelectionList.get()) {
573 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
576 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
577 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theAttribute->owner());
578 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
580 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
581 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
582 if(!anAttrSelection.get()) {
583 theError = "Error: Empty attribute selection.";
586 ResultPtr aContext = anAttrSelection->context();
587 if(!aContext.get()) {
588 theError = "Error: Empty selection context.";
591 ResultConstructionPtr aResultConstruction =
592 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
593 if(aResultConstruction.get()) {
594 if (anOperationType != FeaturesPlugin_Boolean::BOOL_FILL
595 || theAttribute->id() != FeaturesPlugin_Boolean::TOOL_LIST_ID()) {
596 theError = "Error: Result construction not allowed for selection.";
600 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
601 GeomShapePtr aContextShape = aContext->shape();
603 aShape = aContextShape;
606 theError = "Error: Empty shape.";
609 if(!aShape->isEqual(aContextShape)) {
610 theError = "Error: Local selection not allowed.";
614 GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType();
615 std::set<GeomAPI_Shape::ShapeType> anAllowedTypes;
616 if(anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE) {
617 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
618 anAllowedTypes.insert(GeomAPI_Shape::FACE);
619 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
620 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
621 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
622 } else if (anOperationType == FeaturesPlugin_Boolean::BOOL_FILL
623 || anOperationType == FeaturesPlugin_Boolean::BOOL_CUT)
625 anAllowedTypes.insert(GeomAPI_Shape::VERTEX);
626 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
627 anAllowedTypes.insert(GeomAPI_Shape::WIRE);
628 anAllowedTypes.insert(GeomAPI_Shape::FACE);
629 anAllowedTypes.insert(GeomAPI_Shape::SHELL);
630 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
631 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
632 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
634 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
635 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
636 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
639 if(anAllowedTypes.find(aShapeType) == anAllowedTypes.end()
640 || (aResultConstruction.get() && aShapeType != GeomAPI_Shape::FACE)) {
641 theError = "Error: Selected shape has the wrong type.";
650 //==================================================================================================
651 bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute,
652 const std::list<std::string>& theArguments,
653 Events_InfoMessage& theError) const
655 AttributeSelectionListPtr anAttrSelectionList =
656 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
657 if(!anAttrSelectionList.get()) {
659 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
663 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
664 // Check all selected entities are sub-shapes of single solid
665 GeomShapePtr aBaseSolid;
666 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
667 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
668 if(!anAttrSelection.get()) {
669 theError = "Error: Empty attribute selection.";
672 ResultPtr aContext = anAttrSelection->context();
673 if(!aContext.get()) {
674 theError = "Error: Empty selection context.";
678 ResultCompSolidPtr aContextOwner = ModelAPI_Tools::compSolidOwner(aContext);
679 GeomShapePtr anOwner = aContextOwner.get() ? aContextOwner->shape() : aContext->shape();
681 if (anOwner->shapeType() != GeomAPI_Shape::SOLID &&
682 anOwner->shapeType() != GeomAPI_Shape::COMPSOLID) {
683 theError = "Error: Not all selected shapes are sub-shapes of solids";
688 aBaseSolid = anOwner;
689 else if (!aBaseSolid->isEqual(anOwner)) {
690 theError = "Error: Sub-shapes of different solids have been selected.";
698 //==================================================================================================
699 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
700 const std::list<std::string>& theArguments,
701 Events_InfoMessage& theError) const
703 AttributeSelectionListPtr anAttrSelectionList =
704 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
705 if(!anAttrSelectionList.get()) {
706 theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
710 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
711 AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
713 //GeomValidators_BodyShapes aBodyValidator;
714 //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
718 GeomValidators_FeatureKind aFeatureKindValidator;
719 if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
723 ResultPtr aContext = aSelectAttr->context();
724 ResultConstructionPtr aResultConstruction =
725 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
726 if(aResultConstruction.get()) {
727 theError = "Error: Only body shapes and construction planes are allowed for selection.";
731 ResultCompSolidPtr aResultCompsolid =
732 std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
733 if(aResultCompsolid.get()) {
737 theError = "Error: Only body shapes and construction planes are allowed for selection.";
745 //==================================================================================================
746 bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
747 const std::list<std::string>& theArguments,
748 Events_InfoMessage& theError) const
750 AttributeSelectionListPtr aSubShapesAttrList =
751 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
752 if(!aSubShapesAttrList.get()) {
754 "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
758 static const std::string aBaseShapeID = "base_shape";
759 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
760 AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
762 if(!aShapeAttrSelection.get()) {
763 theError = "Error: Could not get \"%1\" attribute.";
764 theError.arg(aBaseShapeID);
768 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
769 ResultPtr aContext = aShapeAttrSelection->context();
770 if(!aContext.get()) {
771 theError = "Error: Empty context.";
774 if(!aBaseShape.get()) {
775 aBaseShape = aContext->shape();
777 if(!aBaseShape.get()) {
778 theError = "Error: Empty base shape.";
782 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
783 bool isSameFound = false;
784 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
785 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
786 for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
787 if(anIt.current()->isEqual(aShapeToAdd)) {
793 theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
801 //==================================================================================================
802 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(
803 const std::shared_ptr<ModelAPI_Feature>& theFeature,
804 const std::list<std::string>& theArguments,
805 Events_InfoMessage& theError) const
807 static const std::string aBaseShapeID = "base_shape";
808 static const std::string aSubShapesID = "subshapes_to_keep";
810 if(theFeature->getKind() != "Remove_SubShapes") {
811 theError = "Error: Feature \"%1\" does not supported by this validator.";
812 theError.arg(theFeature->getKind());
816 AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
817 if(!aShapeAttrSelection.get()) {
818 theError = "Error: Could not get \"%1\" attribute.";
819 theError.arg(aBaseShapeID);
823 AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
824 if(!aSubShapesAttrList.get()) {
825 theError = "Error: Could not get \"%1\" attribute.";
826 theError.arg(aSubShapesID);
831 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
832 if(!aBaseShape.get()) {
833 theError = "Error: Base shape is empty.";
836 GeomShapePtr aResultShape = aBaseShape->emptyCopied();
838 if (aSubShapesAttrList->size() == 0) {
839 theError = "Error: Resulting shape is not valid.";
843 // Copy sub-shapes from list to new shape.
844 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
845 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
846 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
847 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
851 if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
852 theError = "Error: Resulting shape is not valid.";
859 //==================================================================================================
860 bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute,
861 const std::list<std::string>& theArguments,
862 Events_InfoMessage& theError) const
864 AttributeSelectionListPtr aBaseObjectsAttrList =
865 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
866 if(!aBaseObjectsAttrList.get()) {
867 theError = "Error: This validator can only work with selection list in \"%1\" feature.";
868 theError.arg(FeaturesPlugin_Union::ID());
872 for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {
873 bool isSameFound = false;
874 AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
875 ResultPtr aContext = anAttrSelectionInList->context();
876 if (!aContext.get()) {
877 theError = "Error: selection is invalid.";
881 ResultConstructionPtr aConstruction =
882 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
883 if(aConstruction.get()) {
884 theError = "Error: Result construction not allowed for selection.";
888 GeomShapePtr aShape = anAttrSelectionInList->value();
889 GeomShapePtr aContextShape = aContext->shape();
890 if (aShape.get() && aContextShape.get() && !aContextShape->isEqual(aShape)) {
891 theError = "Error: Local selection not allowed.";
895 ResultCompSolidPtr aResult =
896 std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
901 if(aResult->numberOfSubs() > 0) {
902 theError = "Error: Whole compsolids not allowed for selection.";
910 //==================================================================================================
911 bool FeaturesPlugin_ValidatorUnionArguments::isValid(
912 const std::shared_ptr<ModelAPI_Feature>& theFeature,
913 const std::list<std::string>& theArguments,
914 Events_InfoMessage& theError) const
916 // Check feature kind.
917 if(theFeature->getKind() != FeaturesPlugin_Union::ID()) {
918 theError = "Error: This validator supports only \"%1\" feature.";
919 theError.arg(FeaturesPlugin_Union::ID());
923 // Get base objects attribute list.
924 AttributeSelectionListPtr aBaseObejctsAttrList =
925 theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());
926 if(!aBaseObejctsAttrList.get()) {
927 theError = "Error: Could not get \"%1\" attribute.";
928 theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID());
933 GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::COMPSOLID;
934 ListOfShape aBaseShapesList;
935 for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {
936 AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);
937 GeomShapePtr aShape = anAttrSelectionInList->value();
941 aBaseShapesList.push_back(aShape);
942 aType = aShape->shapeType() == GeomAPI_Shape::FACE ? GeomAPI_Shape::SHELL :
943 GeomAPI_Shape::COMPSOLID;
946 // Make compound and find connected.
947 GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);
948 ListOfShape aCombined, aFree;
949 GeomAlgoAPI_ShapeTools::combineShapes(
955 if(aFree.size() > 0 || aCombined.size() > 1) {
956 theError = "Error: Not all shapes have shared topology.";
963 bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute,
964 const std::list<std::string>& theArguments,
965 Events_InfoMessage& theError) const
967 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
968 theError = "Error: The attribute with the %1 type is not processed";
969 theError.arg(theAttribute->attributeType());
973 AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeReference>
975 ObjectPtr aRefObject = aRefAttribute->value();
976 if (!aRefObject.get()) {
977 theError = "Error: Empty feature.";
981 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aRefObject);
982 if (!aRefFeature.get()) {
983 theError = "Error: Empty feature.";
986 std::list<std::shared_ptr<ModelAPI_Result> > aResults;
987 ModelAPI_Tools::getConcealedResults(aRefFeature, aResults);
989 size_t aConcealedResults = aResults.size();
990 if (!aConcealedResults && !theArguments.empty()) {
991 // find if these results are touched by the feature in another attribute
992 std::list<std::string>::const_iterator anIt = theArguments.begin();
993 std::string aRecoveredList = *anIt;
994 if (!aRecoveredList.empty()) {
995 std::shared_ptr<ModelAPI_AttributeRefList> aParameterList =
996 theAttribute->owner()->data()->reflist(aRecoveredList);
997 if (aParameterList.get())
998 aConcealedResults = aParameterList->size();
1002 if (aConcealedResults == 0)
1003 theError = "Error: No concealed results.";
1005 return theError.empty();
1008 bool FeaturesPlugin_ValidatorCircular::isValid(const AttributePtr& theAttribute,
1009 const std::list<std::string>& theArguments,
1010 Events_InfoMessage& theError) const
1012 static std::list<std::string> aEdgeArg(1, "circle");
1013 static std::list<std::string> aFaceArg(1, "cylinder");
1015 Events_InfoMessage aError;
1016 bool isValid = GeomValidators_ShapeType().isValid(theAttribute, aEdgeArg, aError);
1018 isValid = GeomValidators_Face().isValid(theAttribute, aFaceArg, aError);
1020 theError = "The shape neither circle nor cylinder";
1025 //=================================================================================================
1026 bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
1027 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1028 const std::list<std::string>& theArguments,
1029 Events_InfoMessage& theError) const
1031 if (theArguments.size() != 2)
1033 theError = "Wrong number of arguments (expected 2).";
1037 int anObjectsNb = 0, aToolsNb = 0;
1038 //int anOperationType = 0;
1040 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1042 bool isAllInSameCompSolid = true;
1043 ResultCompSolidPtr aCompSolid;
1045 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1048 anObjectsNb = anAttrSelList->size();
1049 for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex)
1051 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1052 ResultPtr aContext = anAttr->context();
1053 ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
1054 if (aResCompSolidPtr.get())
1056 if (aCompSolid.get())
1058 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1062 aCompSolid = aResCompSolidPtr;
1067 isAllInSameCompSolid = false;
1075 anAttrSelList = theFeature->selectionList(*anIt);
1078 aToolsNb = anAttrSelList->size();
1079 if (isAllInSameCompSolid)
1081 for (int anIndex = 0; anIndex < aToolsNb; ++anIndex)
1083 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1084 ResultPtr aContext = anAttr->context();
1085 ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
1086 if (aResCompSolidPtr.get())
1088 if (aCompSolid.get())
1090 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1094 aCompSolid = aResCompSolidPtr;
1099 isAllInSameCompSolid = false;
1107 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
1108 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theFeature);
1109 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
1111 if (anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE)
1114 if (anObjectsNb + aToolsNb < 2)
1116 theError = "Not enough arguments for Fuse operation.";
1119 else if (isAllInSameCompSolid)
1121 theError = "Operations only between sub-shapes of the same shape not allowed.";
1127 if (anObjectsNb < 1)
1129 theError = "Objects not selected.";
1134 theError = "Tools not selected.";
1137 if (isAllInSameCompSolid)
1139 theError = "Operations only between sub-shapes of the same shape not allowed.";
1147 //=================================================================================================
1148 bool FeaturesPlugin_ValidatorBooleanArguments::isNotObligatory(std::string theFeature,
1149 std::string theAttribute)
1151 if (theAttribute == "main_objects" || theAttribute == "tool_objects")
1159 //==================================================================================================
1160 bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
1161 const AttributePtr& theAttribute,
1162 const std::list<std::string>& theArguments,
1163 Events_InfoMessage& theError) const
1165 std::shared_ptr<FeaturesPlugin_BooleanSmash> aFeature =
1166 std::dynamic_pointer_cast<FeaturesPlugin_BooleanSmash>(theAttribute->owner());
1168 AttributeSelectionListPtr anAttrSelectionList =
1169 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1170 if (!aFeature.get() || !anAttrSelectionList.get()) {
1172 "Error: Validator used in wrong feature or attribute";
1176 AttributeSelectionListPtr anOtherAttrSelectionList;
1177 if (theAttribute->id() == FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()) {
1178 anOtherAttrSelectionList =
1179 aFeature->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID());
1181 anOtherAttrSelectionList =
1182 aFeature->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID());
1185 GeomAPI_Shape::ShapeType aSelectedShapesType = GeomAPI_Shape::SHAPE;
1186 GeomAPI_DataMapOfShapeShape aSelectedCompSolidsInOtherList;
1187 GeomPlanePtr aFacesPln;
1189 for (int anIndex = 0; anIndex < anOtherAttrSelectionList->size(); ++anIndex) {
1190 AttributeSelectionPtr anAttrSelection = anOtherAttrSelectionList->value(anIndex);
1191 ResultPtr aContext = anAttrSelection->context();
1192 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1193 GeomShapePtr aContextShape = aContext->shape();
1194 if (!aShape.get()) {
1195 aShape = aContextShape;
1198 if (aShape->isSolid() || aShape->isCompSolid()) {
1199 aSelectedShapesType = GeomAPI_Shape::SOLID;
1200 ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
1201 if (aResCompSolidPtr.get()) {
1202 GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
1203 aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape);
1206 aSelectedShapesType = GeomAPI_Shape::FACE;
1207 GeomAPI_Face aFace(aShape);
1208 aFacesPln = aFace.getPlane();
1213 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1214 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1215 if (!anAttrSelection.get()) {
1216 theError = "Error: Empty attribute selection.";
1219 ResultPtr aContext = anAttrSelection->context();
1220 if (!aContext.get()) {
1221 theError = "Error: Empty selection context.";
1224 ResultConstructionPtr aResultConstruction =
1225 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1226 if (aResultConstruction.get()) {
1227 theError = "Error: Result construction not allowed for selection.";
1230 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1231 GeomShapePtr aContextShape = aContext->shape();
1232 if (!aShape.get()) {
1233 aShape = aContextShape;
1235 if (!aShape.get()) {
1236 theError = "Error: Empty shape.";
1239 if (!aShape->isEqual(aContextShape)) {
1240 theError = "Error: Local selection not allowed.";
1244 if (aSelectedShapesType == GeomAPI_Shape::SHAPE) {
1245 // Other list is empty.
1246 if (aShape->isSolid() || aShape->isCompSolid()) {
1247 aSelectedShapesType = GeomAPI_Shape::SOLID;
1249 aSelectedShapesType = GeomAPI_Shape::FACE;
1250 GeomAPI_Face aFace(aShape);
1251 aFacesPln = aFace.getPlane();
1253 if (!aFacesPln.get()) {
1254 theError = "Error: Only planar faces allowed.";
1260 } else if (aSelectedShapesType == GeomAPI_Shape::SOLID) {
1261 if (!aShape->isSolid() && !aShape->isCompSolid()) {
1262 theError = "Error: Selected shapes should have the same type.";
1266 ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
1267 if (aResCompSolidPtr.get()) {
1268 GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
1269 if (aSelectedCompSolidsInOtherList.isBound(aCompSolidShape)) {
1270 theError = "Error: Solids from compsolid in other list not allowed.";
1275 GeomAPI_Face aFace(aShape);
1276 GeomPlanePtr aPln = aFace.getPlane();
1279 theError = "Error: Only planar faces allowed.";
1283 if (!aFacesPln->isCoincident(aPln)) {
1284 theError = "Error: Only coincident faces allowed.";
1293 //==================================================================================================
1294 bool FeaturesPlugin_IntersectionSelection::isValid(const AttributePtr& theAttribute,
1295 const std::list<std::string>& theArguments,
1296 Events_InfoMessage& theError) const
1298 if (!theAttribute.get()) {
1299 theError = "Error: empty selection.";
1302 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1303 AttributeSelectionListPtr anAttrSelectionList =
1304 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1305 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1306 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1307 if (!anAttrSelection.get()) {
1308 theError = "Error: empty attribute selection.";
1311 ResultPtr aContext = anAttrSelection->context();
1312 if (!aContext.get()) {
1313 theError = "Error: empty selection context.";
1316 FeaturePtr aFeature = ModelAPI_Feature::feature(aContext);
1317 if (!aFeature.get()) {
1318 theError = "Error: empty feature.";
1321 std::string aFeatureKind = aFeature->getKind();
1322 if (aFeatureKind == "Sketch" ||
1323 aFeatureKind == "Plane" ||
1324 aFeatureKind == "Axis") {
1325 theError = "Error: %1 shape is not allowed for selection.";
1326 theError.arg(aFeatureKind);
1329 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1330 GeomShapePtr aContextShape = aContext->shape();
1331 if (!aShape.get()) {
1332 aShape = aContextShape;
1334 if (!aShape.get()) {
1335 theError = "Error: empty shape.";
1338 if (!aShape->isEqual(aContextShape)) {
1339 theError = "Error: Local selection not allowed.";
1343 int aShapeType = aShape->shapeType();
1344 // Allow to select edges, faces and solids.
1345 if (aShapeType != GeomAPI_Shape::EDGE &&
1346 aShapeType != GeomAPI_Shape::FACE &&
1347 aShapeType != GeomAPI_Shape::SOLID &&
1348 aShapeType != GeomAPI_Shape::COMPSOLID &&
1349 aShapeType != GeomAPI_Shape::COMPOUND) {
1350 theError = "Error: selected shape has the wrong type.";