1 // Copyright (C) 2014-2022 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>
66 #define _USE_MATH_DEFINES
70 #pragma warning(disable: 4100)
73 //==================================================================================================
74 bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
75 const std::list<std::string>& theArguments,
76 Events_InfoMessage& theError) const
78 AttributeSelectionPtr aPathAttrSelection =
79 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
80 if(!aPathAttrSelection.get()) {
82 theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
87 GeomShapePtr aPathShape = aPathAttrSelection->value();
88 ResultPtr aContext = aPathAttrSelection->context();
90 theError = "Error: Empty context.";
93 GeomShapePtr aContextShape = aContext->shape();
94 if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE &&
95 !aPathShape->isEqual(aContextShape)) {
96 theError = "Error: Local selection of wires not allowed.";
103 //==================================================================================================
104 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const AttributePtr& theAttribute,
105 const std::list<std::string>& theArguments,
106 Events_InfoMessage& theError) const
108 AttributeSelectionListPtr anAttrSelectionList =
109 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
110 if(!anAttrSelectionList.get()) {
113 "Error: This validator can only work with selection list attributes in \"Pipe\" feature.";
117 std::shared_ptr<FeaturesPlugin_Pipe> aFeature =
118 std::dynamic_pointer_cast<FeaturesPlugin_Pipe>(theAttribute->owner());
120 AttributeSelectionPtr aPathSelection = aFeature->selection(FeaturesPlugin_Pipe::PATH_OBJECT_ID());
121 if (!aPathSelection.get()) {
123 theError = "Error: Path not selected.";
128 GeomShapePtr aPathShape = aPathSelection->value();
129 if (!aPathShape.get()) {
130 ResultPtr aContext = aPathSelection->context();
131 if (!aContext.get()) {
132 FeaturePtr aContFeat = aPathSelection->contextFeature();
133 if (!aContFeat.get() || !aContFeat->results().size()) {
134 theError = "Error: Empty selection context.";
138 aPathShape = aContext->shape();
141 if (!aPathShape.get()) {
142 theError = "Error: Empty path shape.";
146 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
147 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
148 if (!anAttrSelection.get()) {
149 theError = "Error: Empty attribute selection.";
152 ResultPtr aContext = anAttrSelection->context();
153 if (!aContext.get()) {
154 FeaturePtr aContFeat = anAttrSelection->contextFeature();
155 if (!aContFeat.get() || !aContFeat->results().size()) {
156 theError = "Error: Empty selection context.";
160 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
161 if (!aShape.get() && aContext.get()) {
162 GeomShapePtr aContextShape = aContext->shape();
163 aShape = aContextShape;
166 theError = "Error: Empty shape.";
170 if (!aPathShape->isSubShape(aShape)) {
171 theError = "Error: Location should be a vertex subshape from path shape.";
179 //==================================================================================================
181 bool FeaturesPlugin_ValidatorPipeLocationsNumber::isValid(
182 const std::shared_ptr<ModelAPI_Feature>& theFeature,
183 const std::list<std::string>& theArguments,
184 Events_InfoMessage& theError) const
186 static const std::string aCreationMethodID = "creation_method";
187 static const std::string aBaseObjectsID = "base_objects";
188 static const std::string aLocationsID = "locations_objects";
190 if(theFeature->getKind() != "Pipe") {
191 theError = "Error: Feature \"%1\" does not supported by this validator.";
192 theError.arg(theFeature->getKind());
196 AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
197 if(!aCreationMethodAttr.get()) {
198 theError = "Error: Could not get \"%1\" attribute.";
199 theError.arg(aCreationMethodID);
203 if(aCreationMethodAttr->value() != "locations") {
207 AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
208 if(!aBaseObjectsSelectionList.get()) {
209 theError = "Error: Could not get \"%1\" attribute.";
210 theError.arg(aBaseObjectsID);
214 AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
215 if(!aLocationsSelectionList.get()) {
216 theError = "Error: Could not get \"%1\" attribute.";
217 theError.arg(aBaseObjectsID);
221 if(aLocationsSelectionList->size() > 0 &&
222 aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
223 theError = "Error: Number of locations should be the same as base objects.";
231 //==================================================================================================
232 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
233 const std::list<std::string>& theArguments,
234 Events_InfoMessage& theError) const
237 if(theArguments.empty()) {
238 theError = "Error: Validator parameters is empty.";
243 // Checking attribute.
244 if(!isValidAttribute(theAttribute, theArguments, theError)) {
245 if(theError.empty()) {
246 theError = "Error: Attribute contains unacceptable shape.";
251 GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;
252 std::string anAttributeType = theAttribute->attributeType();
253 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
254 AttributeSelectionListPtr aListAttr =
255 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
256 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
257 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
258 ResultPtr aContext = aSelectionAttr->context();
259 if(!aContext.get() && !aSelectionAttr->contextFeature().get()) {
260 theError = "Error: Empty context.";
264 ResultConstructionPtr aResultConstruction =
265 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
266 if(!aResultConstruction.get()) {
267 // It is not a result construction.
268 // If shape is compound check that it contains only faces, edges or vertices.
269 GeomShapePtr aShape = aSelectionAttr->value();
271 if (aContext.get()) {
272 aShape = aContext->shape();
274 theError = "Error: Empty context.";
279 if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
280 for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
281 GeomShapePtr aSubShape = anIt.current();
282 if (aSubShape->shapeType() > GeomAPI_Shape::VERTEX ||
283 aSubShape->shapeType() < GeomAPI_Shape::FACE) {
284 theError = "Error: Compound should contain only faces, edges or vertices.";
293 GeomShapePtr aShape = aSelectionAttr->value();
294 GeomShapePtr aContextShape = aResultConstruction->shape();
296 // Whole sketch selected.
299 // Object from sketch selected.
300 for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
301 GeomShapePtr aWire = anExp.current();
302 if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
303 theError = "Error: Wire with wrong orientation selected.";
307 if(aSelectedWiresFromObjects.isBound(aWire)) {
309 "Error: Objects with this wire already selected. Don't allow to select this object.";
313 aSelectedWiresFromObjects.bind(aWire, aWire);
322 //==================================================================================================
323 bool FeaturesPlugin_ValidatorBaseForGenerationSketchOrSketchObjects::isValid(
324 const std::shared_ptr<ModelAPI_Feature>& theFeature,
325 const std::list<std::string>& theArguments,
326 Events_InfoMessage& theError) const
328 const std::string aBaseObjectsID = theArguments.front();
330 AttributeSelectionListPtr aListAttr = theFeature->selectionList(aBaseObjectsID);
331 if(!aListAttr.get()) {
333 theError = "Error: Could not get \"%1\" attribute.";
334 theError.arg(aBaseObjectsID);
339 std::set<ResultConstructionPtr> aSelectedSketches;
340 std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;
342 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
343 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
344 ResultPtr aContext = aSelectionAttr->context();
345 if(!aContext.get()) {
346 FeaturePtr aFeature = aSelectionAttr->contextFeature();
347 if (!aFeature.get() || aFeature->results().empty()) {
348 theError = "Error: Empty context.";
351 aContext = aFeature->firstResult();
355 ResultConstructionPtr aResultConstruction =
356 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
357 if(!aResultConstruction.get()) {
358 // It is not a result construction.
362 GeomShapePtr aShape = aSelectionAttr->value();
363 GeomShapePtr aContextShape = aResultConstruction->shape();
365 // Whole sketch selected.
366 aSelectedSketches.insert(aResultConstruction);
368 // Object from sketch selected.
369 aSelectedSketchesFromObjects.insert(aResultConstruction);
374 for(std::set<ResultConstructionPtr>::const_iterator anIt = aSelectedSketches.cbegin();
375 anIt != aSelectedSketches.cend();
377 ResultConstructionPtr aResultConstruction = *anIt;
378 if(aSelectedSketchesFromObjects.find(aResultConstruction) !=
379 aSelectedSketchesFromObjects.cend()) {
380 theError = "Sketch and objects from it can not be selected at the same time.";
388 //==================================================================================================
389 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
390 const std::list<std::string>& theArguments,
391 Events_InfoMessage& theError) const
393 if(!theAttribute.get()) {
395 theError = "Error: Empty attribute.";
400 std::string anAttributeType = theAttribute->attributeType();
401 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
402 AttributeSelectionListPtr aListAttr =
403 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
405 const std::string& aVersion = theAttribute->owner()->data()->version();
406 std::string aSelType;
407 if (!aVersion.empty())
408 aSelType = aListAttr->selectionType();
410 std::list<std::string> anApplicableTypes;
411 switch (GeomValidators_ShapeType::shapeType(aSelType)) {
412 case GeomValidators_ShapeType::Vertex:
413 anApplicableTypes.push_back("vertex");
415 case GeomValidators_ShapeType::Edge:
416 anApplicableTypes.push_back("edge");
417 anApplicableTypes.push_back("wire");
419 case GeomValidators_ShapeType::Face:
420 anApplicableTypes.push_back("face");
421 anApplicableTypes.push_back("shell");
422 // wire should not be the first in this list to be able to check
423 // the type of selection when evaluating shape by shape
424 anApplicableTypes.push_back("wire");
427 anApplicableTypes = theArguments;
431 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
432 // If at least one attribute is invalid, the result is false.
433 if(!isValidAttribute(aListAttr->value(anIndex), anApplicableTypes, theError)) {
437 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
439 AttributeSelectionPtr anAttr =
440 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
441 ResultPtr aContext = anAttr->context();
442 if(!aContext.get() && !anAttr->contextFeature().get()) {
443 theError = "Error: Attribute have empty context.";
447 GeomShapePtr aShape = anAttr->value();
448 GeomShapePtr aContextShape;
449 if(!aShape.get() && aContext.get()) {
450 aContextShape = aContext->shape();
451 aShape = aContextShape;
454 theError = "Error: Empty shape selected";
458 ResultConstructionPtr aConstruction;
459 if (!aContext.get() && anAttr->contextFeature()->results().size() == 1) {
460 aContext = anAttr->contextFeature()->firstResult();
463 aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
464 if(aConstruction.get()) {
465 // Construction selected. Check that it is not infinite.
466 if(aConstruction->isInfinite() && !aConstruction->shape()->isVertex()) {
467 theError = "Error: Infinite constructions is not allowed as base.";
471 aContextShape = aContext->shape();
472 if(aShape->isEqual(aContextShape)) {
473 // Whole construction selected. Check that it has faces.
474 if((theArguments.front() == "face" && aConstruction->facesNum() > 0) ||
475 theArguments.front() == "edge") {
479 // CUT operation supports only FACE or WIRE as a tool base
480 std::shared_ptr<FeaturesPlugin_CompositeBoolean> aComposite =
481 std::dynamic_pointer_cast<FeaturesPlugin_CompositeBoolean>(
482 ModelAPI_Feature::feature(theAttribute->owner()));
484 aComposite->operationType() == FeaturesPlugin_CompositeBoolean::BOOL_CUT) {
485 return aShape->shapeType() == GeomAPI_Shape::WIRE ||
486 aShape->shapeType() == GeomAPI_Shape::FACE;
491 if(!aConstruction && aContextShape.get() && !aShape->isEqual(aContextShape)) {
492 // Local selection on body does not allowed.
494 "Error: Selected shape is in the local selection. Only global selection is allowed.";
498 // Check that object is a shape with allowed type.
499 GeomValidators_ShapeType aShapeTypeValidator;
500 if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
501 theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or "
502 "wires on sketch, whole sketch (if it has at least one face), "
503 "and whole objects with shape types: %1";
504 std::string anArgumentString;
505 for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {
506 if (!anArgumentString.empty())
507 anArgumentString += ", ";
508 anArgumentString += *anIt;
510 theError.arg(anArgumentString);
516 theError = "Error: Attribute \"%1\" does not supported by this validator.";
517 theError.arg(anAttributeType);
525 //==================================================================================================
527 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
528 const std::list<std::string>& theArguments,
529 Events_InfoMessage& theError) const
531 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
532 theError = "Error: The attribute with the %1 type is not processed";
533 theError.arg(theAttribute->attributeType());
536 if (theArguments.size() != 2) {
537 theError = "Error: Wrong parameters in XML definition for %1 type";
538 theError.arg(theAttribute->attributeType());
541 // first argument is for the base attribute, second - for skipping feature kind
542 std::list<std::string>::const_iterator anIt = theArguments.begin();
543 std::string aBaseAttributeId = *anIt;
544 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
545 AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);
546 if (!aBaseAttribute.get()) {
547 theError = "Wrong parameters in XML definition for %1 type";
548 theError.arg(theAttribute->attributeType());
551 if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
552 // this validator is not necessary anymore
556 std::string aFeatureAttributeKind = *anIt;
557 GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
558 // check whether the selection is on the sketch
559 std::list<std::string> anArguments;
560 anArguments.push_back(aFeatureAttributeKind);
562 bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);
563 bool aPlanarFace = false;
564 // check if selection has Face selected
565 GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
567 anArguments.push_back("face");
568 aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
570 bool aValid = !aFeatureKind && aPlanarFace;
575 //==================================================================================================
576 bool FeaturesPlugin_ValidatorExtrusionDir::isValid(
577 const std::shared_ptr<ModelAPI_Feature>& theFeature,
578 const std::list<std::string>& theArguments,
579 Events_InfoMessage& theError) const
581 if(theArguments.size() != 2) {
583 theError = "Error: Validator should be used with 2 parameters for extrusion.";
588 std::list<std::string>::const_iterator anArgsIt = theArguments.begin();
590 AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
593 GeomShapePtr aDirShape;
594 AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
596 aDirShape = aSelAttr->value();
597 if(!aDirShape.get()) {
598 ResultPtr aContext = aSelAttr->context();
599 if(!aContext.get()) {
600 FeaturePtr aFeature = aSelAttr->contextFeature();
601 if (aFeature.get() && !aFeature->results().empty()) {
602 aContext = aFeature->firstResult();
607 aDirShape = aContext->shape();
610 if (aDirShape.get() && aDirShape->isCompound()) {
611 GeomAPI_ShapeIterator anIt(aDirShape);
612 aDirShape = anIt.current();
617 if(!aDirShape.get() || aDirShape->isNull() ||
618 aDirShape->shapeType() != GeomAPI_Shape::EDGE) {
619 // Check that dir can be empty.
620 if(!isShapesCanBeEmpty(aCheckAttribute, theError)) {
621 theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" "
622 "can not be used with default value. Select direction for extrusion.";
623 theError.arg(*anArgsIt);
630 std::shared_ptr<GeomAPI_Edge> aDirEdge(new GeomAPI_Edge(aDirShape));
632 // If faces selected check that direction not parallel with them.
633 AttributeSelectionListPtr aListAttr =
634 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aCheckAttribute);
635 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
636 AttributeSelectionPtr anAttr = aListAttr->value(anIndex);
637 GeomShapePtr aShapeInList = anAttr->value();
638 if(!aShapeInList.get()) {
639 aShapeInList = anAttr->context()->shape();
641 bool isParallel = true;
642 if(aShapeInList->shapeType() == GeomAPI_Shape::FACE ||
643 aShapeInList->shapeType() == GeomAPI_Shape::SHELL) {
644 for(GeomAPI_ShapeExplorer
645 anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
646 std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(anExp.current()));
647 isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace);
652 } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) {
653 std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges =
654 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShapeInList);
655 if(aPlanarEdges.get()) {
656 std::shared_ptr<GeomAPI_Dir> aSketchDir = aPlanarEdges->norm();
657 if(aDirEdge->isLine()) {
658 std::shared_ptr<GeomAPI_Dir> aDir = aDirEdge->line()->direction();
659 isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7;
671 "Error: Direction is parallel to one of the selected face or face on selected shell.";
679 //==================================================================================================
680 bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute,
681 Events_InfoMessage& theError) const
684 if(!theAttribute.get()) {
689 std::string anAttributeType = theAttribute->attributeType();
690 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
691 AttributeSelectionListPtr aListAttr =
692 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
693 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
694 // If at least one attribute is invalid, the result is false.
695 if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
699 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
701 AttributeSelectionPtr anAttr =
702 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
703 ResultPtr aContext = anAttr->context();
704 if(!aContext.get() && !anAttr->contextFeature().get()) {
708 GeomShapePtr aShape = anAttr->value();
709 if(!aShape.get() && aContext.get()) {
710 GeomShapePtr aContextShape = aContext->shape();
711 aShape = aContextShape;
717 if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
718 aShape->shapeType() == GeomAPI_Shape::EDGE ||
719 !aShape->isPlanar()) {
729 //==================================================================================================
730 bool FeaturesPlugin_ValidatorExtrusionBoundaryFace::isValid(
731 const AttributePtr& theAttribute,
732 const std::list<std::string>& theArguments,
733 Events_InfoMessage& theError) const
735 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
737 // Collect all necessary attributes and try to build prism
740 AttributeSelectionListPtr aBaseShapeAttr =
741 aFeature->selectionList(FeaturesPlugin_Extrusion::BASE_OBJECTS_ID());
742 ListOfShape aBaseShapeList;
744 if (!FeaturesPlugin_Tools::getShape(aBaseShapeAttr, true, aBaseShapeList, anError)) {
750 AttributeSelectionPtr aSelection =
751 aFeature->selection(FeaturesPlugin_Extrusion::DIRECTION_OBJECT_ID());
752 GeomShapePtr aShape = aSelection->value();
753 if (!aShape.get() && aSelection->context().get())
754 aShape = aSelection->context()->shape();
758 if (aShape->isEdge())
759 anEdge = aShape->edge();
760 else if (aShape->isCompound()) {
761 GeomAPI_ShapeIterator anIt(aShape);
762 anEdge = anIt.current()->edge();
766 std::shared_ptr<GeomAPI_Dir> aDir;
767 if (anEdge.get() && anEdge->isLine())
768 aDir = anEdge->line()->direction();
771 GeomShapePtr aFromShape, aToShape;
772 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
773 if (aSelection.get()) {
774 aToShape = aSelection->value();
775 if (!aToShape.get() && aSelection->context().get())
776 aToShape = aSelection->context()->shape();
777 if (aToShape.get() && aToShape->isCompound()) {
778 GeomAPI_ShapeIterator anIt(aToShape);
779 aToShape = anIt.current();
781 if (aToShape.get() && !aToShape->isFace()) {
782 theError = "\"To\" shape is not a face";
786 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
787 if (aSelection.get()) {
788 aFromShape = aSelection->value();
789 if (!aFromShape.get() && aSelection->context().get())
790 aFromShape = aSelection->context()->shape();
791 if (aFromShape.get() && aFromShape->isCompound()) {
792 GeomAPI_ShapeIterator anIt(aFromShape);
793 aFromShape = anIt.current();
795 if (aFromShape.get() && !aFromShape->isFace()) {
796 theError = "\"From\" shape is not a face";
801 double aToSize = aFeature->real(FeaturesPlugin_Extrusion::TO_OFFSET_ID())->value();
802 double aFromSize = aFeature->real(FeaturesPlugin_Extrusion::FROM_OFFSET_ID())->value();
805 for (ListOfShape::iterator anIt = aBaseShapeList.begin(); anIt != aBaseShapeList.end(); anIt++) {
806 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIt;
808 std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo(
809 new GeomAlgoAPI_Prism(aBaseShape, aDir, aToShape, aToSize, aFromShape, aFromSize));
810 bool isFailed = GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPrismAlgo,
811 FeaturesPlugin_Extrusion::ID(),
822 //==================================================================================================
823 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
824 const std::list<std::string>& theArguments,
825 Events_InfoMessage& theError) const
827 AttributeSelectionListPtr anAttrSelectionList =
828 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
829 if(!anAttrSelectionList.get()) {
832 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
836 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
837 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theAttribute->owner());
838 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
840 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
841 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
842 if(!anAttrSelection.get()) {
843 theError = "Error: Empty attribute selection.";
846 ResultPtr aContext = anAttrSelection->context();
847 if(!aContext.get()) {
848 FeaturePtr aContFeat = anAttrSelection->contextFeature();
849 if (!aContFeat.get() || !aContFeat->results().size()) {
850 theError = "Error: Empty selection context.";
854 ResultConstructionPtr aResultConstruction =
855 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
856 if(aResultConstruction.get()) {
857 if (anOperationType != FeaturesPlugin_Boolean::BOOL_FILL
858 || theAttribute->id() != FeaturesPlugin_Boolean::TOOL_LIST_ID()) {
859 theError = "Error: Result construction not allowed for selection.";
863 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
864 if(!aShape.get() && aContext.get()) {
865 GeomShapePtr aContextShape = aContext->shape();
866 aShape = aContextShape;
869 theError = "Error: Empty shape.";
872 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
873 theError = "Error: Local selection not allowed.";
877 GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType();
878 std::set<GeomAPI_Shape::ShapeType> anAllowedTypes;
879 if(anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE) {
880 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
881 anAllowedTypes.insert(GeomAPI_Shape::FACE);
882 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
883 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
884 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
885 } else if (anOperationType == FeaturesPlugin_Boolean::BOOL_FILL
886 || anOperationType == FeaturesPlugin_Boolean::BOOL_CUT)
888 anAllowedTypes.insert(GeomAPI_Shape::VERTEX);
889 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
890 anAllowedTypes.insert(GeomAPI_Shape::WIRE);
891 anAllowedTypes.insert(GeomAPI_Shape::FACE);
892 anAllowedTypes.insert(GeomAPI_Shape::SHELL);
893 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
894 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
895 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
897 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
898 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
899 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
902 if(anAllowedTypes.find(aShapeType) == anAllowedTypes.end()
903 || (aResultConstruction.get() && aShapeType != GeomAPI_Shape::FACE)) {
904 theError = "Error: Selected shape has the wrong type.";
913 //==================================================================================================
914 bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute,
915 const std::list<std::string>& theArguments,
916 Events_InfoMessage& theError) const
918 AttributeSelectionListPtr anAttrSelectionList =
919 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
920 if(!anAttrSelectionList.get()) {
923 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
928 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
929 // Check all selected entities are sub-shapes of single solid
930 GeomShapePtr aBaseSolid;
931 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
932 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
933 if(!anAttrSelection.get()) {
934 theError = "Error: Empty attribute selection.";
937 ResultPtr aContext = anAttrSelection->context();
938 if(!aContext.get()) {
939 FeaturePtr aContFeat = anAttrSelection->contextFeature();
940 if (!aContFeat.get() || !aContFeat->results().size() ||
941 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
942 theError = "Error: Empty selection context.";
945 if (aContFeat->results().size() == 1)
946 aContext = aContFeat->firstResult();
948 theError = "Error: Too many shapes selected.";
953 ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext, true);
954 GeomShapePtr anOwner = aContext->shape();
955 GeomShapePtr aTopLevelOwner = aContextOwner.get() ? aContextOwner->shape() : anOwner;
958 theError = "Error: wrong feature is selected.";
962 if (anOwner->shapeType() != GeomAPI_Shape::SOLID &&
963 anOwner->shapeType() != GeomAPI_Shape::COMPSOLID) {
964 theError = "Error: Not all selected shapes are sub-shapes of solids.";
969 aBaseSolid = aTopLevelOwner;
970 else if (!aBaseSolid->isEqual(aTopLevelOwner)) {
971 theError = "Error: Sub-shapes of different solids have been selected.";
980 //==================================================================================================
981 bool FeaturesPlugin_ValidatorFillet1DSelection::isValid(const AttributePtr& theAttribute,
982 const std::list<std::string>& theArguments,
983 Events_InfoMessage& theError) const
985 AttributeSelectionListPtr anAttrSelectionList =
986 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
987 if (!anAttrSelectionList.get()) {
990 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
995 // Validate wires selection
996 if (!theArguments.empty() &&
997 theArguments.front() == "wire") {
998 for (int ind = 0; ind < anAttrSelectionList->size(); ++ind) {
999 AttributeSelectionPtr aCurSel = anAttrSelectionList->value(ind);
1000 //GeomShapePtr aContext = aCurSel->context()->shape();
1001 GeomShapePtr aWire = aCurSel->value();
1002 if (aWire->shapeType() != GeomAPI_Shape::WIRE) {
1003 theError = "Selected shape is not a wire";
1010 // check each selected vertex is a sharp corner between adjacent edges,
1011 // and these edges are in the same plane
1012 std::map<GeomShapePtr, MapShapeToShapes> aWireSubshapes;
1013 int aNbSel = anAttrSelectionList->size();
1014 for (int ind = 0; ind < aNbSel; ++ind) {
1015 AttributeSelectionPtr aCurSel = anAttrSelectionList->value(ind);
1016 GeomShapePtr aContext = aCurSel->context()->shape();
1017 GeomShapePtr aVertex = aCurSel->value();
1018 // check wire already processed, if not, store all vertices and edges, sharing them
1019 std::map<GeomShapePtr, MapShapeToShapes>::iterator aProcessed = aWireSubshapes.find(aContext);
1020 if (aProcessed == aWireSubshapes.end()) {
1021 if (aContext->shapeType() != GeomAPI_Shape::WIRE) {
1022 theError = "Selected vertex is not a wire corner";
1025 if (aVertex->shapeType() != GeomAPI_Shape::VERTEX) {
1026 theError = "Selected shape is not a vertex";
1030 GeomAlgoAPI_MapShapesAndAncestors aMapVE(aContext, GeomAPI_Shape::VERTEX,
1031 GeomAPI_Shape::EDGE);
1032 aWireSubshapes[aContext] = aMapVE.map();
1033 aProcessed = aWireSubshapes.find(aContext);
1037 MapShapeToShapes::iterator aFound = aProcessed->second.find(aVertex);
1038 if (aFound == aProcessed->second.end()) {
1039 theError = "Selected vertex does not exist in the wire";
1042 else if (aFound->second.size() != 2) {
1043 theError = "Vertex should be shared between 2 edges exactly";
1047 ListOfShape anEdges;
1048 anEdges.insert(anEdges.end(), aFound->second.begin(), aFound->second.end());
1049 GeomPlanePtr aPlane = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
1051 theError = "Error: Edges are not planar";
1055 GeomEdgePtr anEdge1(new GeomAPI_Edge(anEdges.front()));
1056 GeomEdgePtr anEdge2(new GeomAPI_Edge(anEdges.back()));
1057 GeomVertexPtr aSharedVertex(new GeomAPI_Vertex(aVertex));
1058 if (GeomAlgoAPI_ShapeTools::isTangent(anEdge1, anEdge2, aSharedVertex)) {
1059 theError = "Error: Edges are tangent";
1067 //==================================================================================================
1068 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
1069 const std::list<std::string>& theArguments,
1070 Events_InfoMessage& theError) const
1072 AttributeSelectionListPtr anAttrSelectionList =
1073 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1074 if(!anAttrSelectionList.get()) {
1076 theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
1081 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1082 AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
1084 //GeomValidators_BodyShapes aBodyValidator;
1085 //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
1089 GeomValidators_FeatureKind aFeatureKindValidator;
1090 if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
1094 ResultPtr aContext = aSelectAttr->context();
1095 ResultConstructionPtr aResultConstruction =
1096 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1097 if(aResultConstruction.get()) {
1098 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1102 ResultBodyPtr aResultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1103 if(aResultBody.get()) {
1106 FeaturePtr aResultFeature = aSelectAttr->contextFeature();
1107 if(aResultFeature.get()) {
1108 bool aOkRes = false;
1109 std::list<ResultPtr>::const_iterator aFRes = aResultFeature->results().cbegin();
1110 for(; aFRes != aResultFeature->results().cend() && !aOkRes; aFRes++) {
1111 ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aFRes);
1112 if (aBody.get() && !aBody->isDisabled())
1119 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1127 //==================================================================================================
1128 bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
1129 const std::list<std::string>& theArguments,
1130 Events_InfoMessage& theError) const
1132 AttributeSelectionListPtr aSubShapesAttrList =
1133 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1134 if(!aSubShapesAttrList.get()) {
1137 "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
1142 static const std::string aBaseShapeID = "base_shape";
1143 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1144 AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
1146 if(!aShapeAttrSelection.get()) {
1148 theError = "Error: Could not get \"%1\" attribute.";
1149 theError.arg(aBaseShapeID);
1154 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1155 ResultPtr aContext = aShapeAttrSelection->context();
1156 if(!aContext.get()) {
1157 theError = "Error: Empty context.";
1160 if(!aBaseShape.get()) {
1161 aBaseShape = aContext->shape();
1163 if(!aBaseShape.get()) {
1164 theError = "Error: Empty base shape.";
1168 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
1169 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1170 bool isSameFound = false;
1171 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1172 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1173 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
1175 if ((*anIt)->isEqual(aShapeToAdd)) {
1181 theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
1189 //==================================================================================================
1190 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(
1191 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1192 const std::list<std::string>& theArguments,
1193 Events_InfoMessage& theError) const
1195 static const std::string aBaseShapeID = "base_shape";
1196 static const std::string aSubShapesID = "subshapes_to_keep";
1199 if(theFeature->getKind() != "Remove_SubShapes") {
1200 theError = "Error: Feature \"%1\" does not supported by this validator.";
1201 theError.arg(theFeature->getKind());
1205 AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
1206 if(!aShapeAttrSelection.get()) {
1207 theError = "Error: Could not get \"%1\" attribute.";
1208 theError.arg(aBaseShapeID);
1212 AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
1213 if(!aSubShapesAttrList.get()) {
1214 theError = "Error: Could not get \"%1\" attribute.";
1215 theError.arg(aSubShapesID);
1221 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1222 if(!aBaseShape.get()) {
1223 theError = "Error: Base shape is empty.";
1226 GeomShapePtr aResultShape = aBaseShape->emptyCopied();
1228 if (aSubShapesAttrList->size() == 0) {
1229 theError = "Error: Resulting shape is not valid.";
1233 // Copy sub-shapes from list to new shape.
1234 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1235 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1236 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1237 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
1241 if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
1242 theError = "Error: Resulting shape is not valid.";
1249 //==================================================================================================
1251 bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute,
1252 const std::list<std::string>& theArguments,
1253 Events_InfoMessage& theError) const
1255 AttributeSelectionListPtr aBaseObjectsAttrList =
1256 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1257 if(!aBaseObjectsAttrList.get()) {
1258 theError = "Error: This validator can only work with selection list in \"%1\" feature.";
1259 theError.arg(FeaturesPlugin_Union::ID());
1263 for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {
1264 AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
1265 ResultPtr aContext = anAttrSelectionInList->context();
1266 if (!aContext.get()) {
1267 theError = "Error: selection is invalid.";
1271 ResultConstructionPtr aConstruction =
1272 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1273 if(aConstruction.get()) {
1274 theError = "Error: Result construction not allowed for selection.";
1278 GeomShapePtr aShape = anAttrSelectionInList->value();
1279 GeomShapePtr aContextShape = aContext->shape();
1280 if (aShape.get() && aContextShape.get() && !aContextShape->isEqual(aShape)) {
1281 theError = "Error: Local selection not allowed.";
1285 ResultBodyPtr aResult =
1286 std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1287 if(!aResult.get()) {
1291 if(aResult->numberOfSubs() > 0) {
1292 theError = "Error: Whole compsolids not allowed for selection.";
1301 //==================================================================================================
1302 bool FeaturesPlugin_ValidatorUnionArguments::isValid(
1303 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1304 const std::list<std::string>& theArguments,
1305 Events_InfoMessage& theError) const
1308 // Check feature kind.
1309 if(theFeature->getKind() != FeaturesPlugin_Union::ID()) {
1310 theError = "Error: This validator supports only \"%1\" feature.";
1311 theError.arg(FeaturesPlugin_Union::ID());
1315 // Get base objects attribute list.
1316 AttributeSelectionListPtr aBaseObejctsAttrList =
1317 theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1318 if(!aBaseObejctsAttrList.get()) {
1319 theError = "Error: Could not get \"%1\" attribute.";
1320 theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1326 GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::COMPSOLID;
1327 ListOfShape aBaseShapesList;
1328 for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {
1329 AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);
1330 GeomShapePtr aShape = anAttrSelectionInList->value();
1331 if (!aShape.get()) {
1334 aBaseShapesList.push_back(aShape);
1335 aType = aShape->shapeType() == GeomAPI_Shape::FACE ? GeomAPI_Shape::SHELL :
1336 GeomAPI_Shape::COMPSOLID;
1339 // Make compound and find connected.
1340 GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);
1341 ListOfShape aResults;
1342 GeomAlgoAPI_ShapeTools::combineShapes(aCompound, aType, aResults);
1344 if(aResults.size() > 1 || (aResults.size() == 1 && aResults.front()->shapeType() > aType)) {
1345 theError = "Error: Not all shapes have shared topology.";
1352 bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute,
1353 const std::list<std::string>& theArguments,
1354 Events_InfoMessage& theError) const
1356 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
1358 theError = "Error: The attribute with the %1 type is not processed";
1359 theError.arg(theAttribute->attributeType());
1364 AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeReference>
1366 ObjectPtr aRefObject = aRefAttribute->value();
1367 if (!aRefObject.get()) {
1368 theError = "Error: Empty feature.";
1372 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aRefObject);
1373 if (!aRefFeature.get()) {
1374 theError = "Error: Empty feature.";
1377 std::list<std::shared_ptr<ModelAPI_Result> > aResults;
1378 ModelAPI_Tools::getConcealedResults(aRefFeature, aResults);
1380 size_t aConcealedResults = aResults.size();
1381 if (!aConcealedResults && !theArguments.empty()) {
1382 // find if these results are touched by the feature in another attribute
1383 std::list<std::string>::const_iterator anIt = theArguments.begin();
1384 std::string aRecoveredList = *anIt;
1385 if (!aRecoveredList.empty()) {
1386 std::shared_ptr<ModelAPI_AttributeRefList> aParameterList =
1387 theAttribute->owner()->data()->reflist(aRecoveredList);
1388 if (aParameterList.get())
1389 aConcealedResults = aParameterList->size();
1393 if (aConcealedResults == 0)
1394 theError = "Error: No concealed results.";
1396 return theError.empty();
1399 bool FeaturesPlugin_ValidatorCircular::isValid(const AttributePtr& theAttribute,
1400 const std::list<std::string>& theArguments,
1401 Events_InfoMessage& theError) const
1403 static std::list<std::string> aEdgeArg(1, "circle");
1404 static std::list<std::string> aFaceArg(1, "cylinder");
1406 Events_InfoMessage aError;
1407 bool isValid = GeomValidators_ShapeType().isValid(theAttribute, aEdgeArg, aError);
1409 isValid = GeomValidators_Face().isValid(theAttribute, aFaceArg, aError);
1411 theError = "The shape neither circle nor cylinder";
1416 //=================================================================================================
1417 bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
1418 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1419 const std::list<std::string>& theArguments,
1420 Events_InfoMessage& theError) const
1423 if (theArguments.size() != 2)
1425 theError = "Wrong number of arguments (expected 2).";
1430 int anObjectsToolsNb[2] = { 0, 0 };
1432 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1434 bool isAllInSameCompSolid = true;
1435 ResultBodyPtr aCompSolid;
1437 for (int* anArgNbIt = anObjectsToolsNb; anIt != aLast; ++anIt, ++anArgNbIt) {
1438 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1441 *anArgNbIt = anAttrSelList->size();
1442 if (isAllInSameCompSolid) {
1443 for (int anIndex = 0; anIndex < *anArgNbIt; ++anIndex)
1445 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1446 ResultPtr aContext = anAttr->context();
1447 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1448 if (aResCompSolidPtr.get())
1450 if (aCompSolid.get())
1452 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1456 aCompSolid = aResCompSolidPtr;
1461 isAllInSameCompSolid = false;
1469 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
1470 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theFeature);
1471 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
1473 if (anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE)
1476 if (anObjectsToolsNb[0] + anObjectsToolsNb[1] < 2)
1478 theError = "Not enough arguments for Fuse operation.";
1481 else if (isAllInSameCompSolid)
1483 theError = "Operations only between sub-shapes of the same shape not allowed.";
1489 if (anObjectsToolsNb[0] < 1) // check number of objects
1491 theError = "Objects not selected.";
1494 if (anObjectsToolsNb[1] < 1) // check number of tools
1496 theError = "Tools not selected.";
1499 if (isAllInSameCompSolid)
1501 theError = "Operations only between sub-shapes of the same shape not allowed.";
1509 //=================================================================================================
1511 bool FeaturesPlugin_ValidatorBooleanArguments::isNotObligatory(std::string theFeature,
1512 std::string theAttribute)
1514 if (theAttribute == "main_objects" || theAttribute == "tool_objects")
1523 //==================================================================================================
1524 bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
1525 const AttributePtr& theAttribute,
1526 const std::list<std::string>& theArguments,
1527 Events_InfoMessage& theError) const
1529 std::shared_ptr<FeaturesPlugin_BooleanSmash> aFeature =
1530 std::dynamic_pointer_cast<FeaturesPlugin_BooleanSmash>(theAttribute->owner());
1532 AttributeSelectionListPtr anAttrSelectionList =
1533 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1534 if (!aFeature.get() || !anAttrSelectionList.get()) {
1537 "Error: Validator used in wrong feature or attribute";
1542 AttributeSelectionListPtr anOtherAttrSelectionList;
1543 if (theAttribute->id() == FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()) {
1544 anOtherAttrSelectionList =
1545 aFeature->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID());
1547 anOtherAttrSelectionList =
1548 aFeature->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID());
1551 GeomAPI_Shape::ShapeType aSelectedShapesType = GeomAPI_Shape::SHAPE;
1552 GeomAPI_DataMapOfShapeShape aSelectedCompSolidsInOtherList;
1553 GeomPlanePtr aFacesPln;
1555 for (int anIndex = 0; anIndex < anOtherAttrSelectionList->size(); ++anIndex) {
1556 AttributeSelectionPtr anAttrSelection = anOtherAttrSelectionList->value(anIndex);
1558 if (anAttrSelection->contextFeature().get()) {
1559 theError = "Error: Features not allowed for selection.";
1563 ResultPtr aContext = anAttrSelection->context();
1564 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1565 if (!aShape.get()) {
1566 if (!aContext.get()) {
1567 theError = "Error: Empty selection.";
1570 aShape = aContext->shape();
1573 if (aShape->isSolid() || aShape->isCompSolid()) {
1574 aSelectedShapesType = GeomAPI_Shape::SOLID;
1575 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1576 if (aResCompSolidPtr.get()) {
1577 GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
1578 aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape);
1581 aSelectedShapesType = GeomAPI_Shape::FACE;
1582 GeomAPI_Face aFace(aShape);
1583 aFacesPln = aFace.getPlane();
1588 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1589 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1590 if (!anAttrSelection.get()) {
1591 theError = "Error: Empty attribute selection.";
1595 if (anAttrSelection->contextFeature().get()) {
1596 theError = "Error: Features not allowed for selection.";
1600 ResultPtr aContext = anAttrSelection->context();
1601 if(!aContext.get()) {
1602 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1603 if (!aContFeat.get() || !aContFeat->results().size() ||
1604 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1605 theError = "Error: Empty selection context.";
1609 ResultConstructionPtr aResultConstruction =
1610 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1611 if (aResultConstruction.get()) {
1612 theError = "Error: Result construction not allowed for selection.";
1615 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1616 GeomShapePtr aContextShape = aContext->shape();
1617 if (!aShape.get()) {
1618 aShape = aContextShape;
1620 if (!aShape.get()) {
1621 theError = "Error: Empty shape.";
1624 if (!aShape->isEqual(aContextShape)) {
1625 theError = "Error: Local selection not allowed.";
1629 if (aSelectedShapesType == GeomAPI_Shape::SHAPE) {
1630 // Other list is empty.
1631 if (aShape->isSolid() || aShape->isCompSolid()) {
1632 aSelectedShapesType = GeomAPI_Shape::SOLID;
1634 aSelectedShapesType = GeomAPI_Shape::FACE;
1635 GeomAPI_Face aFace(aShape);
1636 aFacesPln = aFace.getPlane();
1638 if (!aFacesPln.get()) {
1639 theError = "Error: Only planar faces allowed.";
1645 } else if (aSelectedShapesType == GeomAPI_Shape::SOLID) {
1646 if (!aShape->isSolid() && !aShape->isCompSolid()) {
1647 theError = "Error: Selected shapes should have the same type.";
1651 GeomAPI_Face aFace(aShape);
1652 GeomPlanePtr aPln = aFace.getPlane();
1655 theError = "Error: Only planar faces allowed.";
1659 if (!aFacesPln->isCoincident(aPln)) {
1660 theError = "Error: Only coincident faces allowed.";
1669 //==================================================================================================
1671 bool FeaturesPlugin_IntersectionSelection::isValid(const AttributePtr& theAttribute,
1672 const std::list<std::string>& theArguments,
1673 Events_InfoMessage& theError) const
1675 if (!theAttribute.get()) {
1676 theError = "Error: empty selection.";
1679 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1680 AttributeSelectionListPtr anAttrSelectionList =
1681 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1682 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1683 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1684 if (!anAttrSelection.get()) {
1685 theError = "Error: empty attribute selection.";
1688 ResultPtr aContext = anAttrSelection->context();
1689 if (aContext.get()) {
1690 aFeature = ModelAPI_Feature::feature(aContext);
1692 aFeature = anAttrSelection->contextFeature();
1693 if (!aFeature.get() || !aFeature->results().size() ||
1694 aFeature->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1695 theError = "Error: Empty selection context.";
1699 if (!aFeature.get()) {
1700 theError = "Error: empty feature.";
1703 std::string aFeatureKind = aFeature->getKind();
1704 if (aFeatureKind == "Sketch" ||
1705 aFeatureKind == "Plane" ||
1706 aFeatureKind == "Axis") {
1707 theError = "Error: %1 shape is not allowed for selection.";
1708 theError.arg(aFeatureKind);
1711 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1712 if (!aShape.get()) {
1713 GeomShapePtr aContextShape = aContext->shape();
1714 aShape = aContextShape;
1716 if (!aShape.get()) {
1717 theError = "Error: empty shape.";
1720 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1721 theError = "Error: Local selection not allowed.";
1725 int aShapeType = aShape->shapeType();
1726 // Allow to select edges, faces and solids.
1727 if (aShapeType != GeomAPI_Shape::EDGE &&
1728 aShapeType != GeomAPI_Shape::FACE &&
1729 aShapeType != GeomAPI_Shape::SOLID &&
1730 aShapeType != GeomAPI_Shape::COMPSOLID &&
1731 aShapeType != GeomAPI_Shape::COMPOUND) {
1732 theError = "Error: selected shape has the wrong type.";
1741 //==================================================================================================
1743 bool FeaturesPlugin_ValidatorBooleanFuseSelection::isValid(
1744 const AttributePtr& theAttribute,
1745 const std::list<std::string>& theArguments,
1746 Events_InfoMessage& theError) const
1748 AttributeSelectionListPtr anAttrSelectionList =
1749 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1750 if (!anAttrSelectionList.get()) {
1752 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1756 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1757 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1758 if (!anAttrSelection.get()) {
1759 theError = "Error: Empty attribute selection.";
1762 ResultPtr aContext = anAttrSelection->context();
1763 if(!aContext.get()) {
1764 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1765 if (!aContFeat.get() || !aContFeat->results().size() ||
1766 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1767 theError = "Error: Empty selection context.";
1771 ResultConstructionPtr aResultConstruction =
1772 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1773 if (aResultConstruction.get()) {
1774 theError = "Error: Result construction not allowed for selection.";
1777 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1778 if (!aShape.get()) {
1779 GeomShapePtr aContextShape = aContext->shape();
1780 aShape = aContextShape;
1782 if (!aShape.get()) {
1783 theError = "Error: Empty shape.";
1786 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1787 theError = "Error: Local selection not allowed.";
1796 //=================================================================================================
1797 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
1798 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1799 const std::list<std::string>& theArguments,
1800 Events_InfoMessage& theError) const
1803 if (theArguments.size() != 2) {
1804 theError = "Wrong number of arguments (expected 2).";
1809 std::shared_ptr<FeaturesPlugin_BooleanFuse> aFeature =
1810 std::dynamic_pointer_cast<FeaturesPlugin_BooleanFuse>(theFeature);
1812 int anObjectsNb = 0, aToolsNb = 0;
1814 std::list<std::string>::const_iterator anIt = theArguments.begin();
1816 bool isAllInSameCompSolid = true;
1817 ResultBodyPtr aCompSolid;
1819 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1820 if (anAttrSelList) {
1821 anObjectsNb = anAttrSelList->size();
1822 for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex) {
1823 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1824 ResultPtr aContext = anAttr->context();
1825 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1826 if (aResCompSolidPtr.get()) {
1827 if (aCompSolid.get()) {
1828 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1830 aCompSolid = aResCompSolidPtr;
1833 isAllInSameCompSolid = false;
1840 if (aFeature->string(FeaturesPlugin_BooleanFuse::CREATION_METHOD())->value()
1841 == FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED()) {
1842 anAttrSelList = theFeature->selectionList(*anIt);
1843 if (anAttrSelList) {
1844 aToolsNb = anAttrSelList->size();
1845 if (isAllInSameCompSolid) {
1846 for (int anIndex = 0; anIndex < aToolsNb; ++anIndex) {
1847 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1848 ResultPtr aContext = anAttr->context();
1849 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1850 if (aResCompSolidPtr.get()) {
1851 if (aCompSolid.get()) {
1852 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1854 aCompSolid = aResCompSolidPtr;
1857 isAllInSameCompSolid = false;
1865 if (anObjectsNb + aToolsNb < 2) {
1866 theError = "Not enough arguments for Fuse operation.";
1873 //=================================================================================================
1875 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isNotObligatory(
1876 std::string theFeature,
1877 std::string theAttribute)
1879 if (theAttribute == "main_objects" || theAttribute == "tool_objects") {
1887 //==================================================================================================
1889 bool FeaturesPlugin_ValidatorBooleanCommonSelection::isValid(
1890 const AttributePtr& theAttribute,
1891 const std::list<std::string>& theArguments,
1892 Events_InfoMessage& theError) const
1894 AttributeSelectionListPtr anAttrSelectionList =
1895 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1896 if (!anAttrSelectionList.get()) {
1898 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1902 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1903 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1904 if (!anAttrSelection.get()) {
1905 theError = "Error: Empty attribute selection.";
1908 ResultPtr aContext = anAttrSelection->context();
1909 if (!aContext.get() && !anAttrSelection->contextFeature().get()) {
1910 theError = "Error: Empty selection context.";
1913 ResultConstructionPtr aResultConstruction =
1914 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1915 if (aResultConstruction.get()) {
1916 if (theAttribute->id() != FeaturesPlugin_BooleanCommon::TOOL_LIST_ID()) {
1917 theError = "Error: Result construction not allowed for selection.";
1921 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1922 GeomShapePtr aContextShape;
1923 if (aContext.get()) {
1924 aContextShape = aContext->shape();
1926 if (!aShape.get()) {
1927 aShape = aContextShape;
1929 if (!aShape.get()) {
1930 theError = "Error: Empty shape.";
1933 if (aContextShape.get() && !aShape->isEqual(aContextShape)) {
1934 theError = "Error: Local selection not allowed.";
1938 if (aResultConstruction.get() && aShape->shapeType() != GeomAPI_Shape::FACE) {
1939 theError = "Error: Result construction should be plane.";
1948 //=================================================================================================
1949 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isValid(
1950 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1951 const std::list<std::string>& theArguments,
1952 Events_InfoMessage& theError) const
1954 if (theArguments.size() != 2) {
1956 theError = "Wrong number of arguments (expected 2).";
1961 std::shared_ptr<FeaturesPlugin_BooleanCommon> aFeature =
1962 std::dynamic_pointer_cast<FeaturesPlugin_BooleanCommon>(theFeature);
1964 int anObjectsNb = 0, aToolsNb = 0;
1966 std::list<std::string>::const_iterator anIt = theArguments.begin();
1968 ResultBodyPtr aCompSolid;
1970 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1971 if (anAttrSelList) {
1972 anObjectsNb = anAttrSelList->size();
1975 bool isSimpleMode = aFeature->string(FeaturesPlugin_BooleanCommon::CREATION_METHOD())->value()
1976 == FeaturesPlugin_BooleanCommon::CREATION_METHOD_SIMPLE();
1978 if (!isSimpleMode) {
1979 anAttrSelList = theFeature->selectionList(*anIt);
1980 if (anAttrSelList) {
1981 aToolsNb = anAttrSelList->size();
1985 if ((isSimpleMode && anObjectsNb < 2)
1986 || (!isSimpleMode && (anObjectsNb == 0 || aToolsNb == 0))) {
1987 theError = "Not enough arguments for Fuse operation.";
1993 //=================================================================================================
1995 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isNotObligatory(
1996 std::string theFeature,
1997 std::string theAttribute)
2003 //==================================================================================================
2004 bool FeaturesPlugin_ValidatorDefeaturingSelection::isValid(
2005 const AttributePtr& theAttribute,
2006 const std::list<std::string>& theArguments,
2007 Events_InfoMessage& theError) const
2009 AttributeSelectionListPtr anAttrSelectionList =
2010 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
2011 if (!anAttrSelectionList.get()) {
2013 theError = "Error: This validator can only work with selection list attributes.";
2018 // Check selected entities are sub-shapes of solid or compsolid
2019 GeomShapePtr aBaseSolid;
2020 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
2021 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
2022 if (!anAttrSelection.get()) {
2023 theError = "Error: Empty attribute selection.";
2026 ResultPtr aContext = anAttrSelection->context();
2027 if (!aContext.get()) {
2028 theError = "Error: Empty selection context.";
2032 GeomShapePtr aContextShape = aContext->shape();
2033 if (aContextShape->shapeType() != GeomAPI_Shape::SOLID) {
2034 theError = "Error: Not all selected shapes are sub-shapes of solids.";
2038 ResultBodyPtr aResRootPtr = ModelAPI_Tools::bodyOwner(aContext, true);
2039 if (aResRootPtr.get() && aResRootPtr->shape().get()) {
2040 if (!aResRootPtr->shape()->isCollectionOfSolids()) {
2041 theError = "Error: The main shape should be a collection of solids";