1 // Copyright (C) 2014-2020 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 email : webmaster.salome@opencascade.com
20 #include "FeaturesPlugin_Validators.h"
22 #include "FeaturesPlugin_Boolean.h"
23 #include "FeaturesPlugin_BooleanFuse.h"
24 #include "FeaturesPlugin_BooleanCommon.h"
25 #include "FeaturesPlugin_BooleanSmash.h"
26 #include "FeaturesPlugin_CompositeBoolean.h"
27 #include "FeaturesPlugin_Extrusion.h"
28 #include "FeaturesPlugin_Pipe.h"
29 #include "FeaturesPlugin_Union.h"
31 #include <Events_InfoMessage.h>
33 #include <ModelAPI_Attribute.h>
34 #include <ModelAPI_AttributeDouble.h>
35 #include <ModelAPI_AttributeInteger.h>
36 #include <ModelAPI_AttributeSelectionList.h>
37 #include <ModelAPI_AttributeString.h>
38 #include <ModelAPI_AttributeReference.h>
39 #include <ModelAPI_AttributeRefList.h>
40 #include <ModelAPI_Feature.h>
41 #include <ModelAPI_ResultBody.h>
42 #include <ModelAPI_ResultConstruction.h>
43 #include <ModelAPI_Tools.h>
45 #include <GeomValidators_BodyShapes.h>
46 #include <GeomValidators_Face.h>
47 #include <GeomValidators_FeatureKind.h>
48 #include <GeomValidators_ShapeType.h>
50 #include <GeomAPI_DataMapOfShapeShape.h>
51 #include <GeomAPI_Lin.h>
52 #include <GeomAPI_PlanarEdges.h>
53 #include <GeomAPI_Pln.h>
54 #include <GeomAPI_ShapeExplorer.h>
55 #include <GeomAPI_ShapeIterator.h>
57 #include <GeomAlgoAPI_CompoundBuilder.h>
58 #include <GeomAlgoAPI_MapShapesAndAncestors.h>
59 #include <GeomAlgoAPI_Prism.h>
60 #include <GeomAlgoAPI_ShapeBuilder.h>
61 #include <GeomAlgoAPI_ShapeTools.h>
62 #include <GeomAlgoAPI_WireBuilder.h>
64 #define _USE_MATH_DEFINES
68 #pragma warning(disable: 4100)
71 //==================================================================================================
72 bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
73 const std::list<std::string>& theArguments,
74 Events_InfoMessage& theError) const
76 AttributeSelectionPtr aPathAttrSelection =
77 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
78 if(!aPathAttrSelection.get()) {
80 theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
85 GeomShapePtr aPathShape = aPathAttrSelection->value();
86 ResultPtr aContext = aPathAttrSelection->context();
88 theError = "Error: Empty context.";
91 GeomShapePtr aContextShape = aContext->shape();
92 if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE &&
93 !aPathShape->isEqual(aContextShape)) {
94 theError = "Error: Local selection of wires not allowed.";
101 //==================================================================================================
102 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const AttributePtr& theAttribute,
103 const std::list<std::string>& theArguments,
104 Events_InfoMessage& theError) const
106 AttributeSelectionListPtr anAttrSelectionList =
107 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
108 if(!anAttrSelectionList.get()) {
111 "Error: This validator can only work with selection list attributes in \"Pipe\" feature.";
115 std::shared_ptr<FeaturesPlugin_Pipe> aFeature =
116 std::dynamic_pointer_cast<FeaturesPlugin_Pipe>(theAttribute->owner());
118 AttributeSelectionPtr aPathSelection = aFeature->selection(FeaturesPlugin_Pipe::PATH_OBJECT_ID());
119 if (!aPathSelection.get()) {
121 theError = "Error: Path not selected.";
126 GeomShapePtr aPathShape = aPathSelection->value();
127 if (!aPathShape.get()) {
128 ResultPtr aContext = aPathSelection->context();
129 if (!aContext.get()) {
130 FeaturePtr aContFeat = aPathSelection->contextFeature();
131 if (!aContFeat.get() || !aContFeat->results().size()) {
132 theError = "Error: Empty selection context.";
136 aPathShape = aContext->shape();
139 if (!aPathShape.get()) {
140 theError = "Error: Empty path shape.";
144 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
145 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
146 if (!anAttrSelection.get()) {
147 theError = "Error: Empty attribute selection.";
150 ResultPtr aContext = anAttrSelection->context();
151 if (!aContext.get()) {
152 FeaturePtr aContFeat = anAttrSelection->contextFeature();
153 if (!aContFeat.get() || !aContFeat->results().size()) {
154 theError = "Error: Empty selection context.";
158 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
159 if (!aShape.get() && aContext.get()) {
160 GeomShapePtr aContextShape = aContext->shape();
161 aShape = aContextShape;
164 theError = "Error: Empty shape.";
168 if (!aPathShape->isSubShape(aShape)) {
169 theError = "Error: Location should be a vertex subshape from path shape.";
177 //==================================================================================================
179 bool FeaturesPlugin_ValidatorPipeLocationsNumber::isValid(
180 const std::shared_ptr<ModelAPI_Feature>& theFeature,
181 const std::list<std::string>& theArguments,
182 Events_InfoMessage& theError) const
184 static const std::string aCreationMethodID = "creation_method";
185 static const std::string aBaseObjectsID = "base_objects";
186 static const std::string aLocationsID = "locations_objects";
188 if(theFeature->getKind() != "Pipe") {
189 theError = "Error: Feature \"%1\" does not supported by this validator.";
190 theError.arg(theFeature->getKind());
194 AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
195 if(!aCreationMethodAttr.get()) {
196 theError = "Error: Could not get \"%1\" attribute.";
197 theError.arg(aCreationMethodID);
201 if(aCreationMethodAttr->value() != "locations") {
205 AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
206 if(!aBaseObjectsSelectionList.get()) {
207 theError = "Error: Could not get \"%1\" attribute.";
208 theError.arg(aBaseObjectsID);
212 AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
213 if(!aLocationsSelectionList.get()) {
214 theError = "Error: Could not get \"%1\" attribute.";
215 theError.arg(aBaseObjectsID);
219 if(aLocationsSelectionList->size() > 0 &&
220 aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
221 theError = "Error: Number of locations should be the same as base objects.";
229 //==================================================================================================
230 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
231 const std::list<std::string>& theArguments,
232 Events_InfoMessage& theError) const
235 if(theArguments.empty()) {
236 theError = "Error: Validator parameters is empty.";
241 // Checking attribute.
242 if(!isValidAttribute(theAttribute, theArguments, theError)) {
243 if(theError.empty()) {
244 theError = "Error: Attribute contains unacceptable shape.";
249 GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;
250 std::string anAttributeType = theAttribute->attributeType();
251 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
252 AttributeSelectionListPtr aListAttr =
253 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
254 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
255 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
256 ResultPtr aContext = aSelectionAttr->context();
257 if(!aContext.get() && !aSelectionAttr->contextFeature().get()) {
258 theError = "Error: Empty context.";
262 ResultConstructionPtr aResultConstruction =
263 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
264 if(!aResultConstruction.get()) {
265 // It is not a result construction.
266 // If shape is compound check that it contains only faces, edges or vertices.
267 GeomShapePtr aShape = aSelectionAttr->value();
269 if (aContext.get()) {
270 aShape = aContext->shape();
272 theError = "Error: Empty context.";
277 if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
278 for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
279 GeomShapePtr aSubShape = anIt.current();
280 if (aSubShape->shapeType() > GeomAPI_Shape::VERTEX ||
281 aSubShape->shapeType() < GeomAPI_Shape::FACE) {
282 theError = "Error: Compound should contain only faces, edges or vertices.";
291 GeomShapePtr aShape = aSelectionAttr->value();
292 GeomShapePtr aContextShape = aResultConstruction->shape();
294 // Whole sketch selected.
297 // Object from sketch selected.
298 for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
299 GeomShapePtr aWire = anExp.current();
300 if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
301 theError = "Error: Wire with wrong orientation selected.";
305 if(aSelectedWiresFromObjects.isBound(aWire)) {
307 "Error: Objects with this wire already selected. Don't allow to select this object.";
311 aSelectedWiresFromObjects.bind(aWire, aWire);
320 //==================================================================================================
321 bool FeaturesPlugin_ValidatorBaseForGenerationSketchOrSketchObjects::isValid(
322 const std::shared_ptr<ModelAPI_Feature>& theFeature,
323 const std::list<std::string>& theArguments,
324 Events_InfoMessage& theError) const
326 const std::string aBaseObjectsID = theArguments.front();
328 AttributeSelectionListPtr aListAttr = theFeature->selectionList(aBaseObjectsID);
329 if(!aListAttr.get()) {
331 theError = "Error: Could not get \"%1\" attribute.";
332 theError.arg(aBaseObjectsID);
337 std::set<ResultConstructionPtr> aSelectedSketches;
338 std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;
340 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
341 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
342 ResultPtr aContext = aSelectionAttr->context();
343 if(!aContext.get()) {
344 FeaturePtr aFeature = aSelectionAttr->contextFeature();
345 if (!aFeature.get() || aFeature->results().empty()) {
346 theError = "Error: Empty context.";
349 aContext = aFeature->firstResult();
353 ResultConstructionPtr aResultConstruction =
354 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
355 if(!aResultConstruction.get()) {
356 // It is not a result construction.
360 GeomShapePtr aShape = aSelectionAttr->value();
361 GeomShapePtr aContextShape = aResultConstruction->shape();
363 // Whole sketch selected.
364 aSelectedSketches.insert(aResultConstruction);
366 // Object from sketch selected.
367 aSelectedSketchesFromObjects.insert(aResultConstruction);
372 for(std::set<ResultConstructionPtr>::const_iterator anIt = aSelectedSketches.cbegin();
373 anIt != aSelectedSketches.cend();
375 ResultConstructionPtr aResultConstruction = *anIt;
376 if(aSelectedSketchesFromObjects.find(aResultConstruction) !=
377 aSelectedSketchesFromObjects.cend()) {
378 theError = "Sketch and objects from it can not be selected at the same time.";
386 //==================================================================================================
387 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
388 const std::list<std::string>& theArguments,
389 Events_InfoMessage& theError) const
391 if(!theAttribute.get()) {
393 theError = "Error: Empty attribute.";
398 std::string anAttributeType = theAttribute->attributeType();
399 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
400 AttributeSelectionListPtr aListAttr =
401 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
402 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
403 // If at least one attribute is invalid, the result is false.
404 if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {
408 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
410 AttributeSelectionPtr anAttr =
411 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
412 ResultPtr aContext = anAttr->context();
413 if(!aContext.get() && !anAttr->contextFeature().get()) {
414 theError = "Error: Attribute have empty context.";
418 GeomShapePtr aShape = anAttr->value();
419 GeomShapePtr aContextShape;
420 if(!aShape.get() && aContext.get()) {
421 aContextShape = aContext->shape();
422 aShape = aContextShape;
425 theError = "Error: Empty shape selected";
429 ResultConstructionPtr aConstruction;
430 if (!aContext.get() && anAttr->contextFeature()->results().size() == 1) {
431 aContext = anAttr->contextFeature()->firstResult();
434 aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
435 if(aConstruction.get()) {
436 // Construction selected. Check that it is not infinite.
437 if(aConstruction->isInfinite()) {
438 theError = "Error: Infinite constructions is not allowed as base.";
442 aContextShape = aContext->shape();
443 if(aShape->isEqual(aContextShape)) {
444 // Whole construction selected. Check that it have faces.
445 if(aConstruction->facesNum() > 0) {
449 // CUT operation supports only FACE or WIRE as a tool base
450 std::shared_ptr<FeaturesPlugin_CompositeBoolean> aComposite =
451 std::dynamic_pointer_cast<FeaturesPlugin_CompositeBoolean>(
452 ModelAPI_Feature::feature(theAttribute->owner()));
454 aComposite->operationType() == FeaturesPlugin_CompositeBoolean::BOOL_CUT) {
455 return aShape->shapeType() == GeomAPI_Shape::WIRE ||
456 aShape->shapeType() == GeomAPI_Shape::FACE;
461 if(!aConstruction && aContextShape.get() && !aShape->isEqual(aContextShape)) {
462 // Local selection on body does not allowed.
464 "Error: Selected shape is in the local selection. Only global selection is allowed.";
468 // Check that object is a shape with allowed type.
469 GeomValidators_ShapeType aShapeTypeValidator;
470 if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
471 theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or "
472 "wires on sketch, whole sketch (if it has at least one face), "
473 "and whole objects with shape types: %1";
474 std::string anArgumentString;
475 for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {
476 if (!anArgumentString.empty())
477 anArgumentString += ", ";
478 anArgumentString += *anIt;
480 theError.arg(anArgumentString);
486 theError = "Error: Attribute \"%1\" does not supported by this validator.";
487 theError.arg(anAttributeType);
495 //==================================================================================================
497 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
498 const std::list<std::string>& theArguments,
499 Events_InfoMessage& theError) const
501 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
502 theError = "Error: The attribute with the %1 type is not processed";
503 theError.arg(theAttribute->attributeType());
506 if (theArguments.size() != 2) {
507 theError = "Error: Wrong parameters in XML definition for %1 type";
508 theError.arg(theAttribute->attributeType());
511 // first argument is for the base attribute, second - for skipping feature kind
512 std::list<std::string>::const_iterator anIt = theArguments.begin();
513 std::string aBaseAttributeId = *anIt;
514 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
515 AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);
516 if (!aBaseAttribute.get()) {
517 theError = "Wrong parameters in XML definition for %1 type";
518 theError.arg(theAttribute->attributeType());
521 if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
522 // this validator is not necessary anymore
526 std::string aFeatureAttributeKind = *anIt;
527 GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
528 // check whether the selection is on the sketch
529 std::list<std::string> anArguments;
530 anArguments.push_back(aFeatureAttributeKind);
532 bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);
533 bool aPlanarFace = false;
534 // check if selection has Face selected
535 GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
537 anArguments.push_back("face");
538 aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
540 bool aValid = !aFeatureKind && aPlanarFace;
545 //==================================================================================================
546 bool FeaturesPlugin_ValidatorExtrusionDir::isValid(
547 const std::shared_ptr<ModelAPI_Feature>& theFeature,
548 const std::list<std::string>& theArguments,
549 Events_InfoMessage& theError) const
551 if(theArguments.size() != 2) {
553 theError = "Error: Validator should be used with 2 parameters for extrusion.";
558 std::list<std::string>::const_iterator anArgsIt = theArguments.begin();
560 AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
563 GeomShapePtr aDirShape;
564 AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
566 aDirShape = aSelAttr->value();
567 if(!aDirShape.get()) {
568 ResultPtr aContext = aSelAttr->context();
569 if(!aContext.get()) {
570 FeaturePtr aFeature = aSelAttr->contextFeature();
571 if (aFeature.get() && !aFeature->results().empty()) {
572 aContext = aFeature->firstResult();
577 aDirShape = aContext->shape();
580 if (aDirShape.get() && aDirShape->isCompound()) {
581 GeomAPI_ShapeIterator anIt(aDirShape);
582 aDirShape = anIt.current();
587 if(!aDirShape.get() || aDirShape->isNull() ||
588 aDirShape->shapeType() != GeomAPI_Shape::EDGE) {
589 // Check that dir can be empty.
590 if(!isShapesCanBeEmpty(aCheckAttribute, theError)) {
591 theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" "
592 "can not be used with default value. Select direction for extrusion.";
593 theError.arg(*anArgsIt);
600 std::shared_ptr<GeomAPI_Edge> aDirEdge(new GeomAPI_Edge(aDirShape));
602 // If faces selected check that direction not parallel with them.
603 AttributeSelectionListPtr aListAttr =
604 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aCheckAttribute);
605 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
606 AttributeSelectionPtr anAttr = aListAttr->value(anIndex);
607 GeomShapePtr aShapeInList = anAttr->value();
608 if(!aShapeInList.get()) {
609 aShapeInList = anAttr->context()->shape();
611 bool isParallel = true;
612 if(aShapeInList->shapeType() == GeomAPI_Shape::FACE ||
613 aShapeInList->shapeType() == GeomAPI_Shape::SHELL) {
614 for(GeomAPI_ShapeExplorer
615 anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
616 std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(anExp.current()));
617 isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace);
622 } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) {
623 std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges =
624 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShapeInList);
625 if(aPlanarEdges.get()) {
626 std::shared_ptr<GeomAPI_Dir> aSketchDir = aPlanarEdges->norm();
627 if(aDirEdge->isLine()) {
628 std::shared_ptr<GeomAPI_Dir> aDir = aDirEdge->line()->direction();
629 isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7;
641 "Error: Direction is parallel to one of the selected face or face on selected shell.";
649 //==================================================================================================
650 bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute,
651 Events_InfoMessage& theError) const
654 if(!theAttribute.get()) {
659 std::string anAttributeType = theAttribute->attributeType();
660 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
661 AttributeSelectionListPtr aListAttr =
662 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
663 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
664 // If at least one attribute is invalid, the result is false.
665 if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
669 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
671 AttributeSelectionPtr anAttr =
672 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
673 ResultPtr aContext = anAttr->context();
674 if(!aContext.get() && !anAttr->contextFeature().get()) {
678 GeomShapePtr aShape = anAttr->value();
679 if(!aShape.get() && aContext.get()) {
680 GeomShapePtr aContextShape = aContext->shape();
681 aShape = aContextShape;
687 if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
688 aShape->shapeType() == GeomAPI_Shape::EDGE ||
689 !aShape->isPlanar()) {
699 //==================================================================================================
700 bool FeaturesPlugin_ValidatorExtrusionBoundaryFace::isValid(
701 const AttributePtr& theAttribute,
702 const std::list<std::string>& theArguments,
703 Events_InfoMessage& theError) const
705 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
707 // Collect all necessary attributes and try to build prism
710 AttributeSelectionListPtr aBaseShapeAttr =
711 aFeature->selectionList(FeaturesPlugin_Extrusion::BASE_OBJECTS_ID());
712 ListOfShape aBaseShapeList;
714 if (!FeaturesPlugin_Tools::getShape(aBaseShapeAttr, true, aBaseShapeList, anError)) {
720 AttributeSelectionPtr aSelection =
721 aFeature->selection(FeaturesPlugin_Extrusion::DIRECTION_OBJECT_ID());
722 GeomShapePtr aShape = aSelection->value();
723 if (!aShape.get() && aSelection->context().get())
724 aShape = aSelection->context()->shape();
728 if (aShape->isEdge())
729 anEdge = aShape->edge();
730 else if (aShape->isCompound()) {
731 GeomAPI_ShapeIterator anIt(aShape);
732 anEdge = anIt.current()->edge();
736 std::shared_ptr<GeomAPI_Dir> aDir;
737 if (anEdge.get() && anEdge->isLine())
738 aDir = anEdge->line()->direction();
741 GeomShapePtr aFromShape, aToShape;
742 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
743 if (aSelection.get()) {
744 aToShape = aSelection->value();
745 if (!aToShape.get() && aSelection->context().get())
746 aToShape = aSelection->context()->shape();
747 if (aToShape.get() && aToShape->isCompound()) {
748 GeomAPI_ShapeIterator anIt(aToShape);
749 aToShape = anIt.current();
751 if (aToShape.get() && !aToShape->isFace()) {
752 theError = "\"To\" shape is not a face";
756 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
757 if (aSelection.get()) {
758 aFromShape = aSelection->value();
759 if (!aFromShape.get() && aSelection->context().get())
760 aFromShape = aSelection->context()->shape();
761 if (aFromShape.get() && aFromShape->isCompound()) {
762 GeomAPI_ShapeIterator anIt(aFromShape);
763 aFromShape = anIt.current();
765 if (aFromShape.get() && !aFromShape->isFace()) {
766 theError = "\"From\" shape is not a face";
771 double aToSize = aFeature->real(FeaturesPlugin_Extrusion::TO_OFFSET_ID())->value();
772 double aFromSize = aFeature->real(FeaturesPlugin_Extrusion::FROM_OFFSET_ID())->value();
775 for (ListOfShape::iterator anIt = aBaseShapeList.begin(); anIt != aBaseShapeList.end(); anIt++) {
776 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIt;
778 std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo(
779 new GeomAlgoAPI_Prism(aBaseShape, aDir, aToShape, aToSize, aFromShape, aFromSize));
780 bool isFailed = GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPrismAlgo,
781 FeaturesPlugin_Extrusion::ID(),
792 //==================================================================================================
793 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
794 const std::list<std::string>& theArguments,
795 Events_InfoMessage& theError) const
797 AttributeSelectionListPtr anAttrSelectionList =
798 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
799 if(!anAttrSelectionList.get()) {
802 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
806 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
807 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theAttribute->owner());
808 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
810 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
811 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
812 if(!anAttrSelection.get()) {
813 theError = "Error: Empty attribute selection.";
816 ResultPtr aContext = anAttrSelection->context();
817 if(!aContext.get()) {
818 FeaturePtr aContFeat = anAttrSelection->contextFeature();
819 if (!aContFeat.get() || !aContFeat->results().size()) {
820 theError = "Error: Empty selection context.";
824 ResultConstructionPtr aResultConstruction =
825 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
826 if(aResultConstruction.get()) {
827 if (anOperationType != FeaturesPlugin_Boolean::BOOL_FILL
828 || theAttribute->id() != FeaturesPlugin_Boolean::TOOL_LIST_ID()) {
829 theError = "Error: Result construction not allowed for selection.";
833 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
834 if(!aShape.get() && aContext.get()) {
835 GeomShapePtr aContextShape = aContext->shape();
836 aShape = aContextShape;
839 theError = "Error: Empty shape.";
842 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
843 theError = "Error: Local selection not allowed.";
847 GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType();
848 std::set<GeomAPI_Shape::ShapeType> anAllowedTypes;
849 if(anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE) {
850 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
851 anAllowedTypes.insert(GeomAPI_Shape::FACE);
852 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
853 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
854 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
855 } else if (anOperationType == FeaturesPlugin_Boolean::BOOL_FILL
856 || anOperationType == FeaturesPlugin_Boolean::BOOL_CUT)
858 anAllowedTypes.insert(GeomAPI_Shape::VERTEX);
859 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
860 anAllowedTypes.insert(GeomAPI_Shape::WIRE);
861 anAllowedTypes.insert(GeomAPI_Shape::FACE);
862 anAllowedTypes.insert(GeomAPI_Shape::SHELL);
863 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
864 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
865 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
867 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
868 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
869 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
872 if(anAllowedTypes.find(aShapeType) == anAllowedTypes.end()
873 || (aResultConstruction.get() && aShapeType != GeomAPI_Shape::FACE)) {
874 theError = "Error: Selected shape has the wrong type.";
883 //==================================================================================================
884 bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute,
885 const std::list<std::string>& theArguments,
886 Events_InfoMessage& theError) const
888 AttributeSelectionListPtr anAttrSelectionList =
889 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
890 if(!anAttrSelectionList.get()) {
893 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
898 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
899 // Check all selected entities are sub-shapes of single solid
900 GeomShapePtr aBaseSolid;
901 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
902 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
903 if(!anAttrSelection.get()) {
904 theError = "Error: Empty attribute selection.";
907 ResultPtr aContext = anAttrSelection->context();
908 if(!aContext.get()) {
909 FeaturePtr aContFeat = anAttrSelection->contextFeature();
910 if (!aContFeat.get() || !aContFeat->results().size() ||
911 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
912 theError = "Error: Empty selection context.";
915 if (aContFeat->results().size() == 1)
916 aContext = aContFeat->firstResult();
918 theError = "Error: Too many shapes selected.";
923 ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext, true);
924 GeomShapePtr anOwner = aContext->shape();
925 GeomShapePtr aTopLevelOwner = aContextOwner.get() ? aContextOwner->shape() : anOwner;
928 theError = "Error: wrong feature is selected.";
932 if (anOwner->shapeType() != GeomAPI_Shape::SOLID &&
933 anOwner->shapeType() != GeomAPI_Shape::COMPSOLID) {
934 theError = "Error: Not all selected shapes are sub-shapes of solids.";
939 aBaseSolid = aTopLevelOwner;
940 else if (!aBaseSolid->isEqual(aTopLevelOwner)) {
941 theError = "Error: Sub-shapes of different solids have been selected.";
950 //==================================================================================================
951 bool FeaturesPlugin_ValidatorFillet1DSelection::isValid(const AttributePtr& theAttribute,
952 const std::list<std::string>& theArguments,
953 Events_InfoMessage& theError) const
955 AttributeSelectionListPtr anAttrSelectionList =
956 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
957 if (!anAttrSelectionList.get()) {
960 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
965 // check each selected vertex is a sharp corner between adjacent edges,
966 // and these edges are in the same plane
967 std::map<GeomShapePtr, MapShapeToShapes> aWireSubshapes;
968 int aNbSel = anAttrSelectionList->size();
969 for (int ind = 0; ind < aNbSel; ++ind) {
970 AttributeSelectionPtr aCurSel = anAttrSelectionList->value(ind);
971 GeomShapePtr aContext = aCurSel->context()->shape();
972 GeomShapePtr aVertex = aCurSel->value();
973 // check wire already processed, if not, store all vertices and edges, sharing them
974 std::map<GeomShapePtr, MapShapeToShapes>::iterator aProcessed = aWireSubshapes.find(aContext);
975 if (aProcessed == aWireSubshapes.end()) {
976 if (aContext->shapeType() != GeomAPI_Shape::WIRE) {
977 theError = "Selected vertex is not a wire corner";
980 if (aVertex->shapeType() != GeomAPI_Shape::VERTEX) {
981 theError = "Selected shape is not a vertex";
985 GeomAlgoAPI_MapShapesAndAncestors aMapVE(aContext, GeomAPI_Shape::VERTEX,
986 GeomAPI_Shape::EDGE);
987 aWireSubshapes[aContext] = aMapVE.map();
988 aProcessed = aWireSubshapes.find(aContext);
992 MapShapeToShapes::iterator aFound = aProcessed->second.find(aVertex);
993 if (aFound == aProcessed->second.end()) {
994 theError = "Selected vertex does not exist in the wire";
997 else if (aFound->second.size() != 2) {
998 theError = "Vertex should be shared between 2 edges exactly";
1002 ListOfShape anEdges;
1003 anEdges.insert(anEdges.end(), aFound->second.begin(), aFound->second.end());
1004 GeomPlanePtr aPlane = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
1006 theError = "Error: Edges are not planar";
1010 GeomEdgePtr anEdge1(new GeomAPI_Edge(anEdges.front()));
1011 GeomEdgePtr anEdge2(new GeomAPI_Edge(anEdges.back()));
1012 GeomVertexPtr aSharedVertex(new GeomAPI_Vertex(aVertex));
1013 if (GeomAlgoAPI_ShapeTools::isTangent(anEdge1, anEdge2, aSharedVertex)) {
1014 theError = "Error: Edges are tangent";
1022 //==================================================================================================
1023 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
1024 const std::list<std::string>& theArguments,
1025 Events_InfoMessage& theError) const
1027 AttributeSelectionListPtr anAttrSelectionList =
1028 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1029 if(!anAttrSelectionList.get()) {
1031 theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
1036 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1037 AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
1039 //GeomValidators_BodyShapes aBodyValidator;
1040 //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
1044 GeomValidators_FeatureKind aFeatureKindValidator;
1045 if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
1049 ResultPtr aContext = aSelectAttr->context();
1050 ResultConstructionPtr aResultConstruction =
1051 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1052 if(aResultConstruction.get()) {
1053 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1057 ResultBodyPtr aResultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1058 if(aResultBody.get()) {
1061 FeaturePtr aResultFeature = aSelectAttr->contextFeature();
1062 if(aResultFeature.get()) {
1063 bool aOkRes = false;
1064 std::list<ResultPtr>::const_iterator aFRes = aResultFeature->results().cbegin();
1065 for(; aFRes != aResultFeature->results().cend() && !aOkRes; aFRes++) {
1066 ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aFRes);
1067 if (aBody.get() && !aBody->isDisabled())
1074 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1082 //==================================================================================================
1083 bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
1084 const std::list<std::string>& theArguments,
1085 Events_InfoMessage& theError) const
1087 AttributeSelectionListPtr aSubShapesAttrList =
1088 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1089 if(!aSubShapesAttrList.get()) {
1092 "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
1097 static const std::string aBaseShapeID = "base_shape";
1098 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1099 AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
1101 if(!aShapeAttrSelection.get()) {
1103 theError = "Error: Could not get \"%1\" attribute.";
1104 theError.arg(aBaseShapeID);
1109 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1110 ResultPtr aContext = aShapeAttrSelection->context();
1111 if(!aContext.get()) {
1112 theError = "Error: Empty context.";
1115 if(!aBaseShape.get()) {
1116 aBaseShape = aContext->shape();
1118 if(!aBaseShape.get()) {
1119 theError = "Error: Empty base shape.";
1123 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
1124 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1125 bool isSameFound = false;
1126 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1127 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1128 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
1130 if ((*anIt)->isEqual(aShapeToAdd)) {
1136 theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
1144 //==================================================================================================
1145 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(
1146 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1147 const std::list<std::string>& theArguments,
1148 Events_InfoMessage& theError) const
1150 static const std::string aBaseShapeID = "base_shape";
1151 static const std::string aSubShapesID = "subshapes_to_keep";
1154 if(theFeature->getKind() != "Remove_SubShapes") {
1155 theError = "Error: Feature \"%1\" does not supported by this validator.";
1156 theError.arg(theFeature->getKind());
1160 AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
1161 if(!aShapeAttrSelection.get()) {
1162 theError = "Error: Could not get \"%1\" attribute.";
1163 theError.arg(aBaseShapeID);
1167 AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
1168 if(!aSubShapesAttrList.get()) {
1169 theError = "Error: Could not get \"%1\" attribute.";
1170 theError.arg(aSubShapesID);
1176 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1177 if(!aBaseShape.get()) {
1178 theError = "Error: Base shape is empty.";
1181 GeomShapePtr aResultShape = aBaseShape->emptyCopied();
1183 if (aSubShapesAttrList->size() == 0) {
1184 theError = "Error: Resulting shape is not valid.";
1188 // Copy sub-shapes from list to new shape.
1189 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1190 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1191 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1192 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
1196 if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
1197 theError = "Error: Resulting shape is not valid.";
1204 //==================================================================================================
1206 bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute,
1207 const std::list<std::string>& theArguments,
1208 Events_InfoMessage& theError) const
1210 AttributeSelectionListPtr aBaseObjectsAttrList =
1211 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1212 if(!aBaseObjectsAttrList.get()) {
1213 theError = "Error: This validator can only work with selection list in \"%1\" feature.";
1214 theError.arg(FeaturesPlugin_Union::ID());
1218 for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {
1219 AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
1220 ResultPtr aContext = anAttrSelectionInList->context();
1221 if (!aContext.get()) {
1222 theError = "Error: selection is invalid.";
1226 ResultConstructionPtr aConstruction =
1227 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1228 if(aConstruction.get()) {
1229 theError = "Error: Result construction not allowed for selection.";
1233 GeomShapePtr aShape = anAttrSelectionInList->value();
1234 GeomShapePtr aContextShape = aContext->shape();
1235 if (aShape.get() && aContextShape.get() && !aContextShape->isEqual(aShape)) {
1236 theError = "Error: Local selection not allowed.";
1240 ResultBodyPtr aResult =
1241 std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1242 if(!aResult.get()) {
1246 if(aResult->numberOfSubs() > 0) {
1247 theError = "Error: Whole compsolids not allowed for selection.";
1256 //==================================================================================================
1257 bool FeaturesPlugin_ValidatorUnionArguments::isValid(
1258 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1259 const std::list<std::string>& theArguments,
1260 Events_InfoMessage& theError) const
1263 // Check feature kind.
1264 if(theFeature->getKind() != FeaturesPlugin_Union::ID()) {
1265 theError = "Error: This validator supports only \"%1\" feature.";
1266 theError.arg(FeaturesPlugin_Union::ID());
1270 // Get base objects attribute list.
1271 AttributeSelectionListPtr aBaseObejctsAttrList =
1272 theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1273 if(!aBaseObejctsAttrList.get()) {
1274 theError = "Error: Could not get \"%1\" attribute.";
1275 theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1281 GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::COMPSOLID;
1282 ListOfShape aBaseShapesList;
1283 for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {
1284 AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);
1285 GeomShapePtr aShape = anAttrSelectionInList->value();
1286 if (!aShape.get()) {
1289 aBaseShapesList.push_back(aShape);
1290 aType = aShape->shapeType() == GeomAPI_Shape::FACE ? GeomAPI_Shape::SHELL :
1291 GeomAPI_Shape::COMPSOLID;
1294 // Make compound and find connected.
1295 GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);
1296 ListOfShape aResults;
1297 GeomAlgoAPI_ShapeTools::combineShapes(aCompound, aType, aResults);
1299 if(aResults.size() > 1 || (aResults.size() == 1 && aResults.front()->shapeType() > aType)) {
1300 theError = "Error: Not all shapes have shared topology.";
1307 bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute,
1308 const std::list<std::string>& theArguments,
1309 Events_InfoMessage& theError) const
1311 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
1313 theError = "Error: The attribute with the %1 type is not processed";
1314 theError.arg(theAttribute->attributeType());
1319 AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeReference>
1321 ObjectPtr aRefObject = aRefAttribute->value();
1322 if (!aRefObject.get()) {
1323 theError = "Error: Empty feature.";
1327 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aRefObject);
1328 if (!aRefFeature.get()) {
1329 theError = "Error: Empty feature.";
1332 std::list<std::shared_ptr<ModelAPI_Result> > aResults;
1333 ModelAPI_Tools::getConcealedResults(aRefFeature, aResults);
1335 size_t aConcealedResults = aResults.size();
1336 if (!aConcealedResults && !theArguments.empty()) {
1337 // find if these results are touched by the feature in another attribute
1338 std::list<std::string>::const_iterator anIt = theArguments.begin();
1339 std::string aRecoveredList = *anIt;
1340 if (!aRecoveredList.empty()) {
1341 std::shared_ptr<ModelAPI_AttributeRefList> aParameterList =
1342 theAttribute->owner()->data()->reflist(aRecoveredList);
1343 if (aParameterList.get())
1344 aConcealedResults = aParameterList->size();
1348 if (aConcealedResults == 0)
1349 theError = "Error: No concealed results.";
1351 return theError.empty();
1354 bool FeaturesPlugin_ValidatorCircular::isValid(const AttributePtr& theAttribute,
1355 const std::list<std::string>& theArguments,
1356 Events_InfoMessage& theError) const
1358 static std::list<std::string> aEdgeArg(1, "circle");
1359 static std::list<std::string> aFaceArg(1, "cylinder");
1361 Events_InfoMessage aError;
1362 bool isValid = GeomValidators_ShapeType().isValid(theAttribute, aEdgeArg, aError);
1364 isValid = GeomValidators_Face().isValid(theAttribute, aFaceArg, aError);
1366 theError = "The shape neither circle nor cylinder";
1371 //=================================================================================================
1372 bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
1373 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1374 const std::list<std::string>& theArguments,
1375 Events_InfoMessage& theError) const
1378 if (theArguments.size() != 2)
1380 theError = "Wrong number of arguments (expected 2).";
1385 int anObjectsToolsNb[2] = { 0, 0 };
1387 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1389 bool isAllInSameCompSolid = true;
1390 ResultBodyPtr aCompSolid;
1392 for (int* anArgNbIt = anObjectsToolsNb; anIt != aLast; ++anIt, ++anArgNbIt) {
1393 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1396 *anArgNbIt = anAttrSelList->size();
1397 if (isAllInSameCompSolid) {
1398 for (int anIndex = 0; anIndex < *anArgNbIt; ++anIndex)
1400 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1401 ResultPtr aContext = anAttr->context();
1402 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1403 if (aResCompSolidPtr.get())
1405 if (aCompSolid.get())
1407 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1411 aCompSolid = aResCompSolidPtr;
1416 isAllInSameCompSolid = false;
1424 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
1425 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theFeature);
1426 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
1428 if (anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE)
1431 if (anObjectsToolsNb[0] + anObjectsToolsNb[1] < 2)
1433 theError = "Not enough arguments for Fuse operation.";
1436 else if (isAllInSameCompSolid)
1438 theError = "Operations only between sub-shapes of the same shape not allowed.";
1444 if (anObjectsToolsNb[0] < 1) // check number of objects
1446 theError = "Objects not selected.";
1449 if (anObjectsToolsNb[1] < 1) // check number of tools
1451 theError = "Tools not selected.";
1454 if (isAllInSameCompSolid)
1456 theError = "Operations only between sub-shapes of the same shape not allowed.";
1464 //=================================================================================================
1466 bool FeaturesPlugin_ValidatorBooleanArguments::isNotObligatory(std::string theFeature,
1467 std::string theAttribute)
1469 if (theAttribute == "main_objects" || theAttribute == "tool_objects")
1478 //==================================================================================================
1479 bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
1480 const AttributePtr& theAttribute,
1481 const std::list<std::string>& theArguments,
1482 Events_InfoMessage& theError) const
1484 std::shared_ptr<FeaturesPlugin_BooleanSmash> aFeature =
1485 std::dynamic_pointer_cast<FeaturesPlugin_BooleanSmash>(theAttribute->owner());
1487 AttributeSelectionListPtr anAttrSelectionList =
1488 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1489 if (!aFeature.get() || !anAttrSelectionList.get()) {
1492 "Error: Validator used in wrong feature or attribute";
1497 AttributeSelectionListPtr anOtherAttrSelectionList;
1498 if (theAttribute->id() == FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()) {
1499 anOtherAttrSelectionList =
1500 aFeature->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID());
1502 anOtherAttrSelectionList =
1503 aFeature->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID());
1506 GeomAPI_Shape::ShapeType aSelectedShapesType = GeomAPI_Shape::SHAPE;
1507 GeomAPI_DataMapOfShapeShape aSelectedCompSolidsInOtherList;
1508 GeomPlanePtr aFacesPln;
1510 for (int anIndex = 0; anIndex < anOtherAttrSelectionList->size(); ++anIndex) {
1511 AttributeSelectionPtr anAttrSelection = anOtherAttrSelectionList->value(anIndex);
1513 if (anAttrSelection->contextFeature().get()) {
1514 theError = "Error: Features not allowed for selection.";
1518 ResultPtr aContext = anAttrSelection->context();
1519 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1520 if (!aShape.get()) {
1521 if (!aContext.get()) {
1522 theError = "Error: Empty selection.";
1525 aShape = aContext->shape();
1528 if (aShape->isSolid() || aShape->isCompSolid()) {
1529 aSelectedShapesType = GeomAPI_Shape::SOLID;
1530 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1531 if (aResCompSolidPtr.get()) {
1532 GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
1533 aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape);
1536 aSelectedShapesType = GeomAPI_Shape::FACE;
1537 GeomAPI_Face aFace(aShape);
1538 aFacesPln = aFace.getPlane();
1543 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1544 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1545 if (!anAttrSelection.get()) {
1546 theError = "Error: Empty attribute selection.";
1550 if (anAttrSelection->contextFeature().get()) {
1551 theError = "Error: Features not allowed for selection.";
1555 ResultPtr aContext = anAttrSelection->context();
1556 if(!aContext.get()) {
1557 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1558 if (!aContFeat.get() || !aContFeat->results().size() ||
1559 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1560 theError = "Error: Empty selection context.";
1564 ResultConstructionPtr aResultConstruction =
1565 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1566 if (aResultConstruction.get()) {
1567 theError = "Error: Result construction not allowed for selection.";
1570 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1571 GeomShapePtr aContextShape = aContext->shape();
1572 if (!aShape.get()) {
1573 aShape = aContextShape;
1575 if (!aShape.get()) {
1576 theError = "Error: Empty shape.";
1579 if (!aShape->isEqual(aContextShape)) {
1580 theError = "Error: Local selection not allowed.";
1584 if (aSelectedShapesType == GeomAPI_Shape::SHAPE) {
1585 // Other list is empty.
1586 if (aShape->isSolid() || aShape->isCompSolid()) {
1587 aSelectedShapesType = GeomAPI_Shape::SOLID;
1589 aSelectedShapesType = GeomAPI_Shape::FACE;
1590 GeomAPI_Face aFace(aShape);
1591 aFacesPln = aFace.getPlane();
1593 if (!aFacesPln.get()) {
1594 theError = "Error: Only planar faces allowed.";
1600 } else if (aSelectedShapesType == GeomAPI_Shape::SOLID) {
1601 if (!aShape->isSolid() && !aShape->isCompSolid()) {
1602 theError = "Error: Selected shapes should have the same type.";
1606 GeomAPI_Face aFace(aShape);
1607 GeomPlanePtr aPln = aFace.getPlane();
1610 theError = "Error: Only planar faces allowed.";
1614 if (!aFacesPln->isCoincident(aPln)) {
1615 theError = "Error: Only coincident faces allowed.";
1624 //==================================================================================================
1626 bool FeaturesPlugin_IntersectionSelection::isValid(const AttributePtr& theAttribute,
1627 const std::list<std::string>& theArguments,
1628 Events_InfoMessage& theError) const
1630 if (!theAttribute.get()) {
1631 theError = "Error: empty selection.";
1634 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1635 AttributeSelectionListPtr anAttrSelectionList =
1636 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1637 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1638 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1639 if (!anAttrSelection.get()) {
1640 theError = "Error: empty attribute selection.";
1643 ResultPtr aContext = anAttrSelection->context();
1644 if (aContext.get()) {
1645 aFeature = ModelAPI_Feature::feature(aContext);
1647 aFeature = anAttrSelection->contextFeature();
1648 if (!aFeature.get() || !aFeature->results().size() ||
1649 aFeature->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1650 theError = "Error: Empty selection context.";
1654 if (!aFeature.get()) {
1655 theError = "Error: empty feature.";
1658 std::string aFeatureKind = aFeature->getKind();
1659 if (aFeatureKind == "Sketch" ||
1660 aFeatureKind == "Plane" ||
1661 aFeatureKind == "Axis") {
1662 theError = "Error: %1 shape is not allowed for selection.";
1663 theError.arg(aFeatureKind);
1666 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1667 if (!aShape.get()) {
1668 GeomShapePtr aContextShape = aContext->shape();
1669 aShape = aContextShape;
1671 if (!aShape.get()) {
1672 theError = "Error: empty shape.";
1675 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1676 theError = "Error: Local selection not allowed.";
1680 int aShapeType = aShape->shapeType();
1681 // Allow to select edges, faces and solids.
1682 if (aShapeType != GeomAPI_Shape::EDGE &&
1683 aShapeType != GeomAPI_Shape::FACE &&
1684 aShapeType != GeomAPI_Shape::SOLID &&
1685 aShapeType != GeomAPI_Shape::COMPSOLID &&
1686 aShapeType != GeomAPI_Shape::COMPOUND) {
1687 theError = "Error: selected shape has the wrong type.";
1696 //==================================================================================================
1698 bool FeaturesPlugin_ValidatorBooleanFuseSelection::isValid(
1699 const AttributePtr& theAttribute,
1700 const std::list<std::string>& theArguments,
1701 Events_InfoMessage& theError) const
1703 AttributeSelectionListPtr anAttrSelectionList =
1704 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1705 if (!anAttrSelectionList.get()) {
1707 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1711 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1712 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1713 if (!anAttrSelection.get()) {
1714 theError = "Error: Empty attribute selection.";
1717 ResultPtr aContext = anAttrSelection->context();
1718 if(!aContext.get()) {
1719 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1720 if (!aContFeat.get() || !aContFeat->results().size() ||
1721 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1722 theError = "Error: Empty selection context.";
1726 ResultConstructionPtr aResultConstruction =
1727 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1728 if (aResultConstruction.get()) {
1729 theError = "Error: Result construction not allowed for selection.";
1732 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1733 if (!aShape.get()) {
1734 GeomShapePtr aContextShape = aContext->shape();
1735 aShape = aContextShape;
1737 if (!aShape.get()) {
1738 theError = "Error: Empty shape.";
1741 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1742 theError = "Error: Local selection not allowed.";
1751 //=================================================================================================
1752 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
1753 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1754 const std::list<std::string>& theArguments,
1755 Events_InfoMessage& theError) const
1758 if (theArguments.size() != 2) {
1759 theError = "Wrong number of arguments (expected 2).";
1764 std::shared_ptr<FeaturesPlugin_BooleanFuse> aFeature =
1765 std::dynamic_pointer_cast<FeaturesPlugin_BooleanFuse>(theFeature);
1767 int anObjectsNb = 0, aToolsNb = 0;
1769 std::list<std::string>::const_iterator anIt = theArguments.begin();
1771 bool isAllInSameCompSolid = true;
1772 ResultBodyPtr aCompSolid;
1774 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1775 if (anAttrSelList) {
1776 anObjectsNb = anAttrSelList->size();
1777 for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex) {
1778 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1779 ResultPtr aContext = anAttr->context();
1780 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1781 if (aResCompSolidPtr.get()) {
1782 if (aCompSolid.get()) {
1783 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1785 aCompSolid = aResCompSolidPtr;
1788 isAllInSameCompSolid = false;
1795 if (aFeature->string(FeaturesPlugin_BooleanFuse::CREATION_METHOD())->value()
1796 == FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED()) {
1797 anAttrSelList = theFeature->selectionList(*anIt);
1798 if (anAttrSelList) {
1799 aToolsNb = anAttrSelList->size();
1800 if (isAllInSameCompSolid) {
1801 for (int anIndex = 0; anIndex < aToolsNb; ++anIndex) {
1802 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1803 ResultPtr aContext = anAttr->context();
1804 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1805 if (aResCompSolidPtr.get()) {
1806 if (aCompSolid.get()) {
1807 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1809 aCompSolid = aResCompSolidPtr;
1812 isAllInSameCompSolid = false;
1820 if (anObjectsNb + aToolsNb < 2) {
1821 theError = "Not enough arguments for Fuse operation.";
1828 //=================================================================================================
1830 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isNotObligatory(
1831 std::string theFeature,
1832 std::string theAttribute)
1834 if (theAttribute == "main_objects" || theAttribute == "tool_objects") {
1842 //==================================================================================================
1844 bool FeaturesPlugin_ValidatorBooleanCommonSelection::isValid(
1845 const AttributePtr& theAttribute,
1846 const std::list<std::string>& theArguments,
1847 Events_InfoMessage& theError) const
1849 AttributeSelectionListPtr anAttrSelectionList =
1850 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1851 if (!anAttrSelectionList.get()) {
1853 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1857 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1858 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1859 if (!anAttrSelection.get()) {
1860 theError = "Error: Empty attribute selection.";
1863 ResultPtr aContext = anAttrSelection->context();
1864 if (!aContext.get() && !anAttrSelection->contextFeature().get()) {
1865 theError = "Error: Empty selection context.";
1868 ResultConstructionPtr aResultConstruction =
1869 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1870 if (aResultConstruction.get()) {
1871 if (theAttribute->id() != FeaturesPlugin_BooleanCommon::TOOL_LIST_ID()) {
1872 theError = "Error: Result construction not allowed for selection.";
1876 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1877 GeomShapePtr aContextShape;
1878 if (aContext.get()) {
1879 aContextShape = aContext->shape();
1881 if (!aShape.get()) {
1882 aShape = aContextShape;
1884 if (!aShape.get()) {
1885 theError = "Error: Empty shape.";
1888 if (aContextShape.get() && !aShape->isEqual(aContextShape)) {
1889 theError = "Error: Local selection not allowed.";
1893 if (aResultConstruction.get() && aShape->shapeType() != GeomAPI_Shape::FACE) {
1894 theError = "Error: Result construction should be plane.";
1903 //=================================================================================================
1904 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isValid(
1905 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1906 const std::list<std::string>& theArguments,
1907 Events_InfoMessage& theError) const
1909 if (theArguments.size() != 2) {
1911 theError = "Wrong number of arguments (expected 2).";
1916 std::shared_ptr<FeaturesPlugin_BooleanCommon> aFeature =
1917 std::dynamic_pointer_cast<FeaturesPlugin_BooleanCommon>(theFeature);
1919 int anObjectsNb = 0, aToolsNb = 0;
1921 std::list<std::string>::const_iterator anIt = theArguments.begin();
1923 ResultBodyPtr aCompSolid;
1925 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1926 if (anAttrSelList) {
1927 anObjectsNb = anAttrSelList->size();
1930 bool isSimpleMode = aFeature->string(FeaturesPlugin_BooleanCommon::CREATION_METHOD())->value()
1931 == FeaturesPlugin_BooleanCommon::CREATION_METHOD_SIMPLE();
1933 if (!isSimpleMode) {
1934 anAttrSelList = theFeature->selectionList(*anIt);
1935 if (anAttrSelList) {
1936 aToolsNb = anAttrSelList->size();
1940 if ((isSimpleMode && anObjectsNb < 2)
1941 || (!isSimpleMode && (anObjectsNb == 0 || aToolsNb == 0))) {
1942 theError = "Not enough arguments for Fuse operation.";
1948 //=================================================================================================
1950 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isNotObligatory(
1951 std::string theFeature,
1952 std::string theAttribute)
1958 //==================================================================================================
1959 bool FeaturesPlugin_ValidatorDefeaturingSelection::isValid(
1960 const AttributePtr& theAttribute,
1961 const std::list<std::string>& theArguments,
1962 Events_InfoMessage& theError) const
1964 AttributeSelectionListPtr anAttrSelectionList =
1965 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1966 if (!anAttrSelectionList.get()) {
1968 theError = "Error: This validator can only work with selection list attributes.";
1973 // Check selected entities are sub-shapes of solid or compsolid
1974 GeomShapePtr aBaseSolid;
1975 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1976 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1977 if (!anAttrSelection.get()) {
1978 theError = "Error: Empty attribute selection.";
1981 ResultPtr aContext = anAttrSelection->context();
1982 if (!aContext.get()) {
1983 theError = "Error: Empty selection context.";
1987 GeomShapePtr aContextShape = aContext->shape();
1988 if (aContextShape->shapeType() != GeomAPI_Shape::SOLID) {
1989 theError = "Error: Not all selected shapes are sub-shapes of solids.";