1 // Copyright (C) 2014-2019 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_Extrusion.h"
27 #include "FeaturesPlugin_Pipe.h"
28 #include "FeaturesPlugin_Union.h"
30 #include <Events_InfoMessage.h>
32 #include <ModelAPI_Attribute.h>
33 #include <ModelAPI_AttributeDouble.h>
34 #include <ModelAPI_AttributeInteger.h>
35 #include <ModelAPI_AttributeSelectionList.h>
36 #include <ModelAPI_AttributeString.h>
37 #include <ModelAPI_AttributeReference.h>
38 #include <ModelAPI_AttributeRefList.h>
39 #include <ModelAPI_Feature.h>
40 #include <ModelAPI_ResultBody.h>
41 #include <ModelAPI_ResultConstruction.h>
42 #include <ModelAPI_Tools.h>
44 #include <GeomValidators_BodyShapes.h>
45 #include <GeomValidators_Face.h>
46 #include <GeomValidators_FeatureKind.h>
47 #include <GeomValidators_ShapeType.h>
49 #include <GeomAPI_DataMapOfShapeShape.h>
50 #include <GeomAPI_Lin.h>
51 #include <GeomAPI_PlanarEdges.h>
52 #include <GeomAPI_Pln.h>
53 #include <GeomAPI_ShapeExplorer.h>
54 #include <GeomAPI_ShapeIterator.h>
56 #include <GeomAlgoAPI_CompoundBuilder.h>
57 #include <GeomAlgoAPI_MapShapesAndAncestors.h>
58 #include <GeomAlgoAPI_Prism.h>
59 #include <GeomAlgoAPI_ShapeBuilder.h>
60 #include <GeomAlgoAPI_ShapeTools.h>
61 #include <GeomAlgoAPI_WireBuilder.h>
63 #define _USE_MATH_DEFINES
66 //==================================================================================================
67 bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
68 const std::list<std::string>& theArguments,
69 Events_InfoMessage& theError) const
71 AttributeSelectionPtr aPathAttrSelection =
72 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
73 if(!aPathAttrSelection.get()) {
75 theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
80 GeomShapePtr aPathShape = aPathAttrSelection->value();
81 ResultPtr aContext = aPathAttrSelection->context();
83 theError = "Error: Empty context.";
86 GeomShapePtr aContextShape = aContext->shape();
87 if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE &&
88 !aPathShape->isEqual(aContextShape)) {
89 theError = "Error: Local selection of wires not allowed.";
96 //==================================================================================================
97 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const AttributePtr& theAttribute,
98 const std::list<std::string>& theArguments,
99 Events_InfoMessage& theError) const
101 AttributeSelectionListPtr anAttrSelectionList =
102 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
103 if(!anAttrSelectionList.get()) {
106 "Error: This validator can only work with selection list attributes in \"Pipe\" feature.";
110 std::shared_ptr<FeaturesPlugin_Pipe> aFeature =
111 std::dynamic_pointer_cast<FeaturesPlugin_Pipe>(theAttribute->owner());
113 AttributeSelectionPtr aPathSelection = aFeature->selection(FeaturesPlugin_Pipe::PATH_OBJECT_ID());
114 if (!aPathSelection.get()) {
116 theError = "Error: Path not selected.";
121 GeomShapePtr aPathShape = aPathSelection->value();
122 if (!aPathShape.get()) {
123 ResultPtr aContext = aPathSelection->context();
124 if (!aContext.get()) {
125 FeaturePtr aContFeat = aPathSelection->contextFeature();
126 if (!aContFeat.get() || !aContFeat->results().size()) {
127 theError = "Error: Empty selection context.";
131 aPathShape = aContext->shape();
134 if (!aPathShape.get()) {
135 theError = "Error: Empty path shape.";
139 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
140 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
141 if (!anAttrSelection.get()) {
142 theError = "Error: Empty attribute selection.";
145 ResultPtr aContext = anAttrSelection->context();
146 if (!aContext.get()) {
147 FeaturePtr aContFeat = anAttrSelection->contextFeature();
148 if (!aContFeat.get() || !aContFeat->results().size()) {
149 theError = "Error: Empty selection context.";
153 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
154 if (!aShape.get() && aContext.get()) {
155 GeomShapePtr aContextShape = aContext->shape();
156 aShape = aContextShape;
159 theError = "Error: Empty shape.";
163 if (!aPathShape->isSubShape(aShape)) {
164 theError = "Error: Location should be a vertex subshape from path shape.";
172 //==================================================================================================
174 bool FeaturesPlugin_ValidatorPipeLocationsNumber::isValid(
175 const std::shared_ptr<ModelAPI_Feature>& theFeature,
176 const std::list<std::string>& theArguments,
177 Events_InfoMessage& theError) const
179 static const std::string aCreationMethodID = "creation_method";
180 static const std::string aBaseObjectsID = "base_objects";
181 static const std::string aLocationsID = "locations_objects";
183 if(theFeature->getKind() != "Pipe") {
184 theError = "Error: Feature \"%1\" does not supported by this validator.";
185 theError.arg(theFeature->getKind());
189 AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
190 if(!aCreationMethodAttr.get()) {
191 theError = "Error: Could not get \"%1\" attribute.";
192 theError.arg(aCreationMethodID);
196 if(aCreationMethodAttr->value() != "locations") {
200 AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
201 if(!aBaseObjectsSelectionList.get()) {
202 theError = "Error: Could not get \"%1\" attribute.";
203 theError.arg(aBaseObjectsID);
207 AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
208 if(!aLocationsSelectionList.get()) {
209 theError = "Error: Could not get \"%1\" attribute.";
210 theError.arg(aBaseObjectsID);
214 if(aLocationsSelectionList->size() > 0 &&
215 aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
216 theError = "Error: Number of locations should be the same as base objects.";
224 //==================================================================================================
225 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
226 const std::list<std::string>& theArguments,
227 Events_InfoMessage& theError) const
230 if(theArguments.empty()) {
231 theError = "Error: Validator parameters is empty.";
236 // Checking attribute.
237 if(!isValidAttribute(theAttribute, theArguments, theError)) {
238 if(theError.empty()) {
239 theError = "Error: Attribute contains unacceptable shape.";
244 GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;
245 std::string anAttributeType = theAttribute->attributeType();
246 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
247 AttributeSelectionListPtr aListAttr =
248 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
249 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
250 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
251 ResultPtr aContext = aSelectionAttr->context();
252 if(!aContext.get() && !aSelectionAttr->contextFeature().get()) {
253 theError = "Error: Empty context.";
257 ResultConstructionPtr aResultConstruction =
258 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
259 if(!aResultConstruction.get()) {
260 // It is not a result construction.
261 // If shape is compound check that it contains only faces, edges or vertices.
262 GeomShapePtr aShape = aSelectionAttr->value();
264 if (aContext.get()) {
265 aShape = aContext->shape();
267 theError = "Error: Empty context.";
272 if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
273 for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
274 GeomShapePtr aSubShape = anIt.current();
275 if (aSubShape->shapeType() > GeomAPI_Shape::VERTEX ||
276 aSubShape->shapeType() < GeomAPI_Shape::FACE) {
277 theError = "Error: Compound should contain only faces, edges or vertices.";
286 GeomShapePtr aShape = aSelectionAttr->value();
287 GeomShapePtr aContextShape = aResultConstruction->shape();
289 // Whole sketch selected.
292 // Object from sketch selected.
293 for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
294 GeomShapePtr aWire = anExp.current();
295 if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
296 theError = "Error: Wire with wrong orientation selected.";
300 if(aSelectedWiresFromObjects.isBound(aWire)) {
302 "Error: Objects with this wire already selected. Don't allow to select this object.";
306 aSelectedWiresFromObjects.bind(aWire, aWire);
315 //==================================================================================================
316 bool FeaturesPlugin_ValidatorBaseForGenerationSketchOrSketchObjects::isValid(
317 const std::shared_ptr<ModelAPI_Feature>& theFeature,
318 const std::list<std::string>& theArguments,
319 Events_InfoMessage& theError) const
321 const std::string aBaseObjectsID = theArguments.front();
323 AttributeSelectionListPtr aListAttr = theFeature->selectionList(aBaseObjectsID);
324 if(!aListAttr.get()) {
326 theError = "Error: Could not get \"%1\" attribute.";
327 theError.arg(aBaseObjectsID);
332 std::set<ResultConstructionPtr> aSelectedSketches;
333 std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;
335 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
336 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
337 ResultPtr aContext = aSelectionAttr->context();
338 if(!aContext.get()) {
339 FeaturePtr aFeature = aSelectionAttr->contextFeature();
340 if (!aFeature.get() || aFeature->results().empty()) {
341 theError = "Error: Empty context.";
344 aContext = aFeature->firstResult();
348 ResultConstructionPtr aResultConstruction =
349 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
350 if(!aResultConstruction.get()) {
351 // It is not a result construction.
355 GeomShapePtr aShape = aSelectionAttr->value();
356 GeomShapePtr aContextShape = aResultConstruction->shape();
358 // Whole sketch selected.
359 aSelectedSketches.insert(aResultConstruction);
361 // Object from sketch selected.
362 aSelectedSketchesFromObjects.insert(aResultConstruction);
367 for(std::set<ResultConstructionPtr>::const_iterator anIt = aSelectedSketches.cbegin();
368 anIt != aSelectedSketches.cend();
370 ResultConstructionPtr aResultConstruction = *anIt;
371 if(aSelectedSketchesFromObjects.find(aResultConstruction) !=
372 aSelectedSketchesFromObjects.cend()) {
373 theError = "Sketch and objects from it can not be selected at the same time.";
381 //==================================================================================================
382 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
383 const std::list<std::string>& theArguments,
384 Events_InfoMessage& theError) const
386 if(!theAttribute.get()) {
388 theError = "Error: Empty attribute.";
393 std::string anAttributeType = theAttribute->attributeType();
394 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
395 AttributeSelectionListPtr aListAttr =
396 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
397 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
398 // If at least one attribute is invalid, the result is false.
399 if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {
403 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
405 AttributeSelectionPtr anAttr =
406 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
407 ResultPtr aContext = anAttr->context();
408 if(!aContext.get() && !anAttr->contextFeature().get()) {
409 theError = "Error: Attribute have empty context.";
413 GeomShapePtr aShape = anAttr->value();
414 GeomShapePtr aContextShape;
415 if(!aShape.get() && aContext.get()) {
416 aContextShape = aContext->shape();
417 aShape = aContextShape;
420 theError = "Error: Empty shape selected";
424 ResultConstructionPtr aConstruction;
425 if (!aContext.get() && anAttr->contextFeature()->results().size() == 1) {
426 aContext = anAttr->contextFeature()->firstResult();
429 aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
430 if(aConstruction.get()) {
431 // Construction selected. Check that it is not infinite.
432 if(aConstruction->isInfinite()) {
433 theError = "Error: Infinite constructions is not allowed as base.";
437 GeomShapePtr aContextShape = aContext->shape();
438 if(aShape->isEqual(aContextShape)) {
439 // Whole construction selected. Check that it have faces.
440 if(aConstruction->facesNum() > 0) {
444 // Shape on construction selected. Check that it is a face or wire.
445 if(aShape->shapeType() == GeomAPI_Shape::WIRE ||
446 aShape->shapeType() == GeomAPI_Shape::FACE) {
453 if(aContextShape.get() && !aShape->isEqual(aContextShape)) {
454 // Local selection on body does not allowed.
456 "Error: Selected shape is in the local selection. Only global selection is allowed.";
460 // Check that object is a shape with allowed type.
461 GeomValidators_ShapeType aShapeTypeValidator;
462 if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
463 theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or "
464 "wires on sketch, whole sketch (if it has at least one face), "
465 "and whole objects with shape types: %1";
466 std::string anArgumentString;
467 for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {
468 if (!anArgumentString.empty())
469 anArgumentString += ", ";
470 anArgumentString += *anIt;
472 theError.arg(anArgumentString);
478 theError = "Error: Attribute \"%1\" does not supported by this validator.";
479 theError.arg(anAttributeType);
487 //==================================================================================================
489 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
490 const std::list<std::string>& theArguments,
491 Events_InfoMessage& theError) const
493 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
494 theError = "Error: The attribute with the %1 type is not processed";
495 theError.arg(theAttribute->attributeType());
498 if (theArguments.size() != 2) {
499 theError = "Error: Wrong parameters in XML definition for %1 type";
500 theError.arg(theAttribute->attributeType());
503 // first argument is for the base attribute, second - for skipping feature kind
504 std::list<std::string>::const_iterator anIt = theArguments.begin();
505 std::string aBaseAttributeId = *anIt;
506 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
507 AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);
508 if (!aBaseAttribute.get()) {
509 theError = "Wrong parameters in XML definition for %1 type";
510 theError.arg(theAttribute->attributeType());
513 if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
514 // this validator is not necessary anymore
518 std::string aFeatureAttributeKind = *anIt;
519 GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
520 // check whether the selection is on the sketch
521 std::list<std::string> anArguments;
522 anArguments.push_back(aFeatureAttributeKind);
524 bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);
525 bool aPlanarFace = false;
526 // check if selection has Face selected
527 GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
529 anArguments.push_back("face");
530 aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
532 bool aValid = !aFeatureKind && aPlanarFace;
537 //==================================================================================================
538 bool FeaturesPlugin_ValidatorExtrusionDir::isValid(
539 const std::shared_ptr<ModelAPI_Feature>& theFeature,
540 const std::list<std::string>& theArguments,
541 Events_InfoMessage& theError) const
543 if(theArguments.size() != 2) {
545 theError = "Error: Validator should be used with 2 parameters for extrusion.";
550 std::list<std::string>::const_iterator
551 anArgsIt = theArguments.begin(), aLast = theArguments.end();
553 AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
556 GeomShapePtr aDirShape;
557 AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
559 aDirShape = aSelAttr->value();
560 if(!aDirShape.get()) {
561 ResultPtr aContext = aSelAttr->context();
562 if(!aContext.get()) {
563 FeaturePtr aFeature = aSelAttr->contextFeature();
564 if (aFeature.get() && !aFeature->results().empty()) {
565 aContext = aFeature->firstResult();
570 aDirShape = aContext->shape();
573 if (aDirShape.get() && aDirShape->isCompound()) {
574 GeomAPI_ShapeIterator anIt(aDirShape);
575 aDirShape = anIt.current();
580 if(!aDirShape.get() || aDirShape->isNull() ||
581 aDirShape->shapeType() != GeomAPI_Shape::EDGE) {
582 // Check that dir can be empty.
583 if(!isShapesCanBeEmpty(aCheckAttribute, theError)) {
584 theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" "
585 "can not be used with default value. Select direction for extrusion.";
586 theError.arg(*anArgsIt);
593 std::shared_ptr<GeomAPI_Edge> aDirEdge(new GeomAPI_Edge(aDirShape));
595 // If faces selected check that direction not parallel with them.
596 AttributeSelectionListPtr aListAttr =
597 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aCheckAttribute);
598 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
599 AttributeSelectionPtr anAttr = aListAttr->value(anIndex);
600 GeomShapePtr aShapeInList = anAttr->value();
601 if(!aShapeInList.get()) {
602 aShapeInList = anAttr->context()->shape();
604 bool isParallel = true;
605 if(aShapeInList->shapeType() == GeomAPI_Shape::FACE ||
606 aShapeInList->shapeType() == GeomAPI_Shape::SHELL) {
607 for(GeomAPI_ShapeExplorer
608 anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
609 std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(anExp.current()));
610 isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace);
615 } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) {
616 std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges =
617 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShapeInList);
618 if(aPlanarEdges.get()) {
619 std::shared_ptr<GeomAPI_Dir> aSketchDir = aPlanarEdges->norm();
620 if(aDirEdge->isLine()) {
621 std::shared_ptr<GeomAPI_Dir> aDir = aDirEdge->line()->direction();
622 isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7;
634 "Error: Direction is parallel to one of the selected face or face on selected shell.";
642 //==================================================================================================
643 bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute,
644 Events_InfoMessage& theError) const
647 if(!theAttribute.get()) {
652 std::string anAttributeType = theAttribute->attributeType();
653 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
654 AttributeSelectionListPtr aListAttr =
655 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
656 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
657 // If at least one attribute is invalid, the result is false.
658 if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
662 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
664 AttributeSelectionPtr anAttr =
665 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
666 ResultPtr aContext = anAttr->context();
667 if(!aContext.get() && !anAttr->contextFeature().get()) {
671 GeomShapePtr aShape = anAttr->value();
672 if(!aShape.get() && aContext.get()) {
673 GeomShapePtr aContextShape = aContext->shape();
674 aShape = aContextShape;
680 if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
681 aShape->shapeType() == GeomAPI_Shape::EDGE ||
682 !aShape->isPlanar()) {
692 //==================================================================================================
693 bool FeaturesPlugin_ValidatorExtrusionBoundaryFace::isValid(
694 const AttributePtr& theAttribute,
695 const std::list<std::string>& theArguments,
696 Events_InfoMessage& theError) const
698 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
700 // Collect all necessary attributes and try to build prism
703 AttributeSelectionListPtr aBaseShapeAttr =
704 aFeature->selectionList(FeaturesPlugin_Extrusion::BASE_OBJECTS_ID());
705 ListOfShape aBaseShapeList;
707 if (!FeaturesPlugin_Tools::getShape(aBaseShapeAttr, true, aBaseShapeList, anError)) {
713 AttributeSelectionPtr aSelection =
714 aFeature->selection(FeaturesPlugin_Extrusion::DIRECTION_OBJECT_ID());
715 GeomShapePtr aShape = aSelection->value();
716 if (!aShape.get() && aSelection->context().get())
717 aShape = aSelection->context()->shape();
721 if (aShape->isEdge())
722 anEdge = aShape->edge();
723 else if (aShape->isCompound()) {
724 GeomAPI_ShapeIterator anIt(aShape);
725 anEdge = anIt.current()->edge();
729 std::shared_ptr<GeomAPI_Dir> aDir;
730 if (anEdge.get() && anEdge->isLine())
731 aDir = anEdge->line()->direction();
734 GeomShapePtr aFromShape, aToShape;
735 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
736 if (aSelection.get()) {
737 aToShape = aSelection->value();
738 if (!aToShape.get() && aSelection->context().get())
739 aToShape = aSelection->context()->shape();
740 if (aToShape.get() && aToShape->isCompound()) {
741 GeomAPI_ShapeIterator anIt(aToShape);
742 aToShape = anIt.current();
744 if (aToShape.get() && !aToShape->isFace()) {
745 theError = "\"To\" shape is not a face";
749 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
750 if (aSelection.get()) {
751 aFromShape = aSelection->value();
752 if (!aFromShape.get() && aSelection->context().get())
753 aFromShape = aSelection->context()->shape();
754 if (aFromShape.get() && aFromShape->isCompound()) {
755 GeomAPI_ShapeIterator anIt(aFromShape);
756 aFromShape = anIt.current();
758 if (aFromShape.get() && !aFromShape->isFace()) {
759 theError = "\"From\" shape is not a face";
764 double aToSize = aFeature->real(FeaturesPlugin_Extrusion::TO_OFFSET_ID())->value();
765 double aFromSize = aFeature->real(FeaturesPlugin_Extrusion::FROM_OFFSET_ID())->value();
768 for (ListOfShape::iterator anIt = aBaseShapeList.begin(); anIt != aBaseShapeList.end(); anIt++) {
769 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIt;
771 std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo(
772 new GeomAlgoAPI_Prism(aBaseShape, aDir, aToShape, aToSize, aFromShape, aFromSize));
773 bool isFailed = GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPrismAlgo,
774 FeaturesPlugin_Extrusion::ID(),
785 //==================================================================================================
786 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
787 const std::list<std::string>& theArguments,
788 Events_InfoMessage& theError) const
790 AttributeSelectionListPtr anAttrSelectionList =
791 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
792 if(!anAttrSelectionList.get()) {
795 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
799 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
800 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theAttribute->owner());
801 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
803 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
804 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
805 if(!anAttrSelection.get()) {
806 theError = "Error: Empty attribute selection.";
809 ResultPtr aContext = anAttrSelection->context();
810 if(!aContext.get()) {
811 FeaturePtr aContFeat = anAttrSelection->contextFeature();
812 if (!aContFeat.get() || !aContFeat->results().size()) {
813 theError = "Error: Empty selection context.";
817 ResultConstructionPtr aResultConstruction =
818 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
819 if(aResultConstruction.get()) {
820 if (anOperationType != FeaturesPlugin_Boolean::BOOL_FILL
821 || theAttribute->id() != FeaturesPlugin_Boolean::TOOL_LIST_ID()) {
822 theError = "Error: Result construction not allowed for selection.";
826 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
827 if(!aShape.get() && aContext.get()) {
828 GeomShapePtr aContextShape = aContext->shape();
829 aShape = aContextShape;
832 theError = "Error: Empty shape.";
835 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
836 theError = "Error: Local selection not allowed.";
840 GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType();
841 std::set<GeomAPI_Shape::ShapeType> anAllowedTypes;
842 if(anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE) {
843 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
844 anAllowedTypes.insert(GeomAPI_Shape::FACE);
845 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
846 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
847 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
848 } else if (anOperationType == FeaturesPlugin_Boolean::BOOL_FILL
849 || anOperationType == FeaturesPlugin_Boolean::BOOL_CUT)
851 anAllowedTypes.insert(GeomAPI_Shape::VERTEX);
852 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
853 anAllowedTypes.insert(GeomAPI_Shape::WIRE);
854 anAllowedTypes.insert(GeomAPI_Shape::FACE);
855 anAllowedTypes.insert(GeomAPI_Shape::SHELL);
856 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
857 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
858 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
860 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
861 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
862 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
865 if(anAllowedTypes.find(aShapeType) == anAllowedTypes.end()
866 || (aResultConstruction.get() && aShapeType != GeomAPI_Shape::FACE)) {
867 theError = "Error: Selected shape has the wrong type.";
876 //==================================================================================================
877 bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute,
878 const std::list<std::string>& theArguments,
879 Events_InfoMessage& theError) const
881 AttributeSelectionListPtr anAttrSelectionList =
882 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
883 if(!anAttrSelectionList.get()) {
886 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
891 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
892 // Check all selected entities are sub-shapes of single solid
893 GeomShapePtr aBaseSolid;
894 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
895 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
896 if(!anAttrSelection.get()) {
897 theError = "Error: Empty attribute selection.";
900 ResultPtr aContext = anAttrSelection->context();
901 if(!aContext.get()) {
902 FeaturePtr aContFeat = anAttrSelection->contextFeature();
903 if (!aContFeat.get() || !aContFeat->results().size() ||
904 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
905 theError = "Error: Empty selection context.";
908 if (aContFeat->results().size() == 1)
909 aContext = aContFeat->firstResult();
911 theError = "Error: Too many shapes selected.";
916 ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext, true);
917 GeomShapePtr anOwner = aContext->shape();
918 GeomShapePtr aTopLevelOwner = aContextOwner.get() ? aContextOwner->shape() : anOwner;
921 theError = "Error: wrong feature is selected.";
925 if (anOwner->shapeType() != GeomAPI_Shape::SOLID &&
926 anOwner->shapeType() != GeomAPI_Shape::COMPSOLID) {
927 theError = "Error: Not all selected shapes are sub-shapes of solids.";
932 aBaseSolid = aTopLevelOwner;
933 else if (!aBaseSolid->isEqual(aTopLevelOwner)) {
934 theError = "Error: Sub-shapes of different solids have been selected.";
943 //==================================================================================================
944 bool FeaturesPlugin_ValidatorFillet1DSelection::isValid(const AttributePtr& theAttribute,
945 const std::list<std::string>& theArguments,
946 Events_InfoMessage& theError) const
948 AttributeSelectionListPtr anAttrSelectionList =
949 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
950 if (!anAttrSelectionList.get()) {
953 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
958 // check each selected vertex is a sharp corner between adjacent edges,
959 // and these edges are in the same plane
960 std::map<GeomShapePtr, MapShapeToShapes> aWireSubshapes;
961 int aNbSel = anAttrSelectionList->size();
962 for (int ind = 0; ind < aNbSel; ++ind) {
963 AttributeSelectionPtr aCurSel = anAttrSelectionList->value(ind);
964 GeomShapePtr aContext = aCurSel->context()->shape();
965 GeomShapePtr aVertex = aCurSel->value();
966 // check wire already processed, if not, store all vertices and edges, sharing them
967 std::map<GeomShapePtr, MapShapeToShapes>::iterator aProcessed = aWireSubshapes.find(aContext);
968 if (aProcessed == aWireSubshapes.end()) {
969 if (aContext->shapeType() != GeomAPI_Shape::WIRE) {
970 theError = "Selected vertex is not a wire corner";
973 if (aVertex->shapeType() != GeomAPI_Shape::VERTEX) {
974 theError = "Selected shape is not a vertex";
978 GeomAlgoAPI_MapShapesAndAncestors aMapVE(aContext, GeomAPI_Shape::VERTEX,
979 GeomAPI_Shape::EDGE);
980 aWireSubshapes[aContext] = aMapVE.map();
981 aProcessed = aWireSubshapes.find(aContext);
985 MapShapeToShapes::iterator aFound = aProcessed->second.find(aVertex);
986 if (aFound == aProcessed->second.end()) {
987 theError = "Selected vertex does not exist in the wire";
990 else if (aFound->second.size() != 2) {
991 theError = "Vertex should be shared between 2 edges exactly";
996 anEdges.insert(anEdges.end(), aFound->second.begin(), aFound->second.end());
997 GeomPlanePtr aPlane = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
999 theError = "Error: Edges are not planar";
1003 GeomEdgePtr anEdge1(new GeomAPI_Edge(anEdges.front()));
1004 GeomEdgePtr anEdge2(new GeomAPI_Edge(anEdges.back()));
1005 GeomVertexPtr aSharedVertex(new GeomAPI_Vertex(aVertex));
1006 if (GeomAlgoAPI_ShapeTools::isTangent(anEdge1, anEdge2, aSharedVertex)) {
1007 theError = "Error: Edges are tangent";
1015 //==================================================================================================
1016 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
1017 const std::list<std::string>& theArguments,
1018 Events_InfoMessage& theError) const
1020 AttributeSelectionListPtr anAttrSelectionList =
1021 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1022 if(!anAttrSelectionList.get()) {
1024 theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
1029 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1030 AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
1032 //GeomValidators_BodyShapes aBodyValidator;
1033 //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
1037 GeomValidators_FeatureKind aFeatureKindValidator;
1038 if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
1042 ResultPtr aContext = aSelectAttr->context();
1043 ResultConstructionPtr aResultConstruction =
1044 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1045 if(aResultConstruction.get()) {
1046 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1050 ResultBodyPtr aResultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1051 if(aResultBody.get()) {
1054 FeaturePtr aResultFeature = aSelectAttr->contextFeature();
1055 if(aResultFeature.get()) {
1056 bool aOkRes = false;
1057 std::list<ResultPtr>::const_iterator aFRes = aResultFeature->results().cbegin();
1058 for(; aFRes != aResultFeature->results().cend() && !aOkRes; aFRes++) {
1059 ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aFRes);
1060 if (aBody.get() && !aBody->isDisabled())
1067 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1075 //==================================================================================================
1076 bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
1077 const std::list<std::string>& theArguments,
1078 Events_InfoMessage& theError) const
1080 AttributeSelectionListPtr aSubShapesAttrList =
1081 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1082 if(!aSubShapesAttrList.get()) {
1085 "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
1090 static const std::string aBaseShapeID = "base_shape";
1091 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1092 AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
1094 if(!aShapeAttrSelection.get()) {
1096 theError = "Error: Could not get \"%1\" attribute.";
1097 theError.arg(aBaseShapeID);
1102 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1103 ResultPtr aContext = aShapeAttrSelection->context();
1104 if(!aContext.get()) {
1105 theError = "Error: Empty context.";
1108 if(!aBaseShape.get()) {
1109 aBaseShape = aContext->shape();
1111 if(!aBaseShape.get()) {
1112 theError = "Error: Empty base shape.";
1116 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
1117 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1118 bool isSameFound = false;
1119 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1120 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1121 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
1123 if ((*anIt)->isEqual(aShapeToAdd)) {
1129 theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
1137 //==================================================================================================
1138 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(
1139 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1140 const std::list<std::string>& theArguments,
1141 Events_InfoMessage& theError) const
1143 static const std::string aBaseShapeID = "base_shape";
1144 static const std::string aSubShapesID = "subshapes_to_keep";
1147 if(theFeature->getKind() != "Remove_SubShapes") {
1148 theError = "Error: Feature \"%1\" does not supported by this validator.";
1149 theError.arg(theFeature->getKind());
1153 AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
1154 if(!aShapeAttrSelection.get()) {
1155 theError = "Error: Could not get \"%1\" attribute.";
1156 theError.arg(aBaseShapeID);
1160 AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
1161 if(!aSubShapesAttrList.get()) {
1162 theError = "Error: Could not get \"%1\" attribute.";
1163 theError.arg(aSubShapesID);
1169 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1170 if(!aBaseShape.get()) {
1171 theError = "Error: Base shape is empty.";
1174 GeomShapePtr aResultShape = aBaseShape->emptyCopied();
1176 if (aSubShapesAttrList->size() == 0) {
1177 theError = "Error: Resulting shape is not valid.";
1181 // Copy sub-shapes from list to new shape.
1182 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1183 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1184 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1185 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
1189 if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
1190 theError = "Error: Resulting shape is not valid.";
1197 //==================================================================================================
1199 bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute,
1200 const std::list<std::string>& theArguments,
1201 Events_InfoMessage& theError) const
1203 AttributeSelectionListPtr aBaseObjectsAttrList =
1204 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1205 if(!aBaseObjectsAttrList.get()) {
1206 theError = "Error: This validator can only work with selection list in \"%1\" feature.";
1207 theError.arg(FeaturesPlugin_Union::ID());
1211 for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {
1212 bool isSameFound = false;
1213 AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
1214 ResultPtr aContext = anAttrSelectionInList->context();
1215 if (!aContext.get()) {
1216 theError = "Error: selection is invalid.";
1220 ResultConstructionPtr aConstruction =
1221 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1222 if(aConstruction.get()) {
1223 theError = "Error: Result construction not allowed for selection.";
1227 GeomShapePtr aShape = anAttrSelectionInList->value();
1228 GeomShapePtr aContextShape = aContext->shape();
1229 if (aShape.get() && aContextShape.get() && !aContextShape->isEqual(aShape)) {
1230 theError = "Error: Local selection not allowed.";
1234 ResultBodyPtr aResult =
1235 std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1236 if(!aResult.get()) {
1240 if(aResult->numberOfSubs() > 0) {
1241 theError = "Error: Whole compsolids not allowed for selection.";
1250 //==================================================================================================
1251 bool FeaturesPlugin_ValidatorUnionArguments::isValid(
1252 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1253 const std::list<std::string>& theArguments,
1254 Events_InfoMessage& theError) const
1257 // Check feature kind.
1258 if(theFeature->getKind() != FeaturesPlugin_Union::ID()) {
1259 theError = "Error: This validator supports only \"%1\" feature.";
1260 theError.arg(FeaturesPlugin_Union::ID());
1264 // Get base objects attribute list.
1265 AttributeSelectionListPtr aBaseObejctsAttrList =
1266 theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1267 if(!aBaseObejctsAttrList.get()) {
1268 theError = "Error: Could not get \"%1\" attribute.";
1269 theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1275 GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::COMPSOLID;
1276 ListOfShape aBaseShapesList;
1277 for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {
1278 AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);
1279 GeomShapePtr aShape = anAttrSelectionInList->value();
1280 if (!aShape.get()) {
1283 aBaseShapesList.push_back(aShape);
1284 aType = aShape->shapeType() == GeomAPI_Shape::FACE ? GeomAPI_Shape::SHELL :
1285 GeomAPI_Shape::COMPSOLID;
1288 // Make compound and find connected.
1289 GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);
1290 ListOfShape aResults;
1291 GeomAlgoAPI_ShapeTools::combineShapes(aCompound, aType, aResults);
1293 if(aResults.size() > 1 || (aResults.size() == 1 && aResults.front()->shapeType() > aType)) {
1294 theError = "Error: Not all shapes have shared topology.";
1301 bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute,
1302 const std::list<std::string>& theArguments,
1303 Events_InfoMessage& theError) const
1305 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
1307 theError = "Error: The attribute with the %1 type is not processed";
1308 theError.arg(theAttribute->attributeType());
1313 AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeReference>
1315 ObjectPtr aRefObject = aRefAttribute->value();
1316 if (!aRefObject.get()) {
1317 theError = "Error: Empty feature.";
1321 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aRefObject);
1322 if (!aRefFeature.get()) {
1323 theError = "Error: Empty feature.";
1326 std::list<std::shared_ptr<ModelAPI_Result> > aResults;
1327 ModelAPI_Tools::getConcealedResults(aRefFeature, aResults);
1329 size_t aConcealedResults = aResults.size();
1330 if (!aConcealedResults && !theArguments.empty()) {
1331 // find if these results are touched by the feature in another attribute
1332 std::list<std::string>::const_iterator anIt = theArguments.begin();
1333 std::string aRecoveredList = *anIt;
1334 if (!aRecoveredList.empty()) {
1335 std::shared_ptr<ModelAPI_AttributeRefList> aParameterList =
1336 theAttribute->owner()->data()->reflist(aRecoveredList);
1337 if (aParameterList.get())
1338 aConcealedResults = aParameterList->size();
1342 if (aConcealedResults == 0)
1343 theError = "Error: No concealed results.";
1345 return theError.empty();
1348 bool FeaturesPlugin_ValidatorCircular::isValid(const AttributePtr& theAttribute,
1349 const std::list<std::string>& theArguments,
1350 Events_InfoMessage& theError) const
1352 static std::list<std::string> aEdgeArg(1, "circle");
1353 static std::list<std::string> aFaceArg(1, "cylinder");
1355 Events_InfoMessage aError;
1356 bool isValid = GeomValidators_ShapeType().isValid(theAttribute, aEdgeArg, aError);
1358 isValid = GeomValidators_Face().isValid(theAttribute, aFaceArg, aError);
1360 theError = "The shape neither circle nor cylinder";
1365 //=================================================================================================
1366 bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
1367 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1368 const std::list<std::string>& theArguments,
1369 Events_InfoMessage& theError) const
1372 if (theArguments.size() != 2)
1374 theError = "Wrong number of arguments (expected 2).";
1379 int anObjectsToolsNb[2] = { 0, 0 };
1381 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1383 bool isAllInSameCompSolid = true;
1384 ResultBodyPtr aCompSolid;
1386 for (int* anArgNbIt = anObjectsToolsNb; anIt != aLast; ++anIt, ++anArgNbIt) {
1387 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1390 *anArgNbIt = anAttrSelList->size();
1391 if (isAllInSameCompSolid) {
1392 for (int anIndex = 0; anIndex < *anArgNbIt; ++anIndex)
1394 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1395 ResultPtr aContext = anAttr->context();
1396 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1397 if (aResCompSolidPtr.get())
1399 if (aCompSolid.get())
1401 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1405 aCompSolid = aResCompSolidPtr;
1410 isAllInSameCompSolid = false;
1418 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
1419 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theFeature);
1420 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
1422 if (anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE)
1425 if (anObjectsToolsNb[0] + anObjectsToolsNb[1] < 2)
1427 theError = "Not enough arguments for Fuse operation.";
1430 else if (isAllInSameCompSolid)
1432 theError = "Operations only between sub-shapes of the same shape not allowed.";
1438 if (anObjectsToolsNb[0] < 1) // check number of objects
1440 theError = "Objects not selected.";
1443 if (anObjectsToolsNb[1] < 1) // check number of tools
1445 theError = "Tools not selected.";
1448 if (isAllInSameCompSolid)
1450 theError = "Operations only between sub-shapes of the same shape not allowed.";
1458 //=================================================================================================
1460 bool FeaturesPlugin_ValidatorBooleanArguments::isNotObligatory(std::string theFeature,
1461 std::string theAttribute)
1463 if (theAttribute == "main_objects" || theAttribute == "tool_objects")
1472 //==================================================================================================
1473 bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
1474 const AttributePtr& theAttribute,
1475 const std::list<std::string>& theArguments,
1476 Events_InfoMessage& theError) const
1478 std::shared_ptr<FeaturesPlugin_BooleanSmash> aFeature =
1479 std::dynamic_pointer_cast<FeaturesPlugin_BooleanSmash>(theAttribute->owner());
1481 AttributeSelectionListPtr anAttrSelectionList =
1482 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1483 if (!aFeature.get() || !anAttrSelectionList.get()) {
1486 "Error: Validator used in wrong feature or attribute";
1491 AttributeSelectionListPtr anOtherAttrSelectionList;
1492 if (theAttribute->id() == FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()) {
1493 anOtherAttrSelectionList =
1494 aFeature->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID());
1496 anOtherAttrSelectionList =
1497 aFeature->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID());
1500 GeomAPI_Shape::ShapeType aSelectedShapesType = GeomAPI_Shape::SHAPE;
1501 GeomAPI_DataMapOfShapeShape aSelectedCompSolidsInOtherList;
1502 GeomPlanePtr aFacesPln;
1504 for (int anIndex = 0; anIndex < anOtherAttrSelectionList->size(); ++anIndex) {
1505 AttributeSelectionPtr anAttrSelection = anOtherAttrSelectionList->value(anIndex);
1507 if (anAttrSelection->contextFeature().get()) {
1508 theError = "Error: Features not allowed for selection.";
1512 ResultPtr aContext = anAttrSelection->context();
1513 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1514 if (!aShape.get()) {
1515 if (!aContext.get()) {
1516 theError = "Error: Empty selection.";
1519 aShape = aContext->shape();
1522 if (aShape->isSolid() || aShape->isCompSolid()) {
1523 aSelectedShapesType = GeomAPI_Shape::SOLID;
1524 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1525 if (aResCompSolidPtr.get()) {
1526 GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
1527 aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape);
1530 aSelectedShapesType = GeomAPI_Shape::FACE;
1531 GeomAPI_Face aFace(aShape);
1532 aFacesPln = aFace.getPlane();
1537 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1538 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1539 if (!anAttrSelection.get()) {
1540 theError = "Error: Empty attribute selection.";
1544 if (anAttrSelection->contextFeature().get()) {
1545 theError = "Error: Features not allowed for selection.";
1549 ResultPtr aContext = anAttrSelection->context();
1550 if(!aContext.get()) {
1551 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1552 if (!aContFeat.get() || !aContFeat->results().size() ||
1553 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1554 theError = "Error: Empty selection context.";
1558 ResultConstructionPtr aResultConstruction =
1559 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1560 if (aResultConstruction.get()) {
1561 theError = "Error: Result construction not allowed for selection.";
1564 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1565 GeomShapePtr aContextShape = aContext->shape();
1566 if (!aShape.get()) {
1567 aShape = aContextShape;
1569 if (!aShape.get()) {
1570 theError = "Error: Empty shape.";
1573 if (!aShape->isEqual(aContextShape)) {
1574 theError = "Error: Local selection not allowed.";
1578 if (aSelectedShapesType == GeomAPI_Shape::SHAPE) {
1579 // Other list is empty.
1580 if (aShape->isSolid() || aShape->isCompSolid()) {
1581 aSelectedShapesType = GeomAPI_Shape::SOLID;
1583 aSelectedShapesType = GeomAPI_Shape::FACE;
1584 GeomAPI_Face aFace(aShape);
1585 aFacesPln = aFace.getPlane();
1587 if (!aFacesPln.get()) {
1588 theError = "Error: Only planar faces allowed.";
1594 } else if (aSelectedShapesType == GeomAPI_Shape::SOLID) {
1595 if (!aShape->isSolid() && !aShape->isCompSolid()) {
1596 theError = "Error: Selected shapes should have the same type.";
1600 GeomAPI_Face aFace(aShape);
1601 GeomPlanePtr aPln = aFace.getPlane();
1604 theError = "Error: Only planar faces allowed.";
1608 if (!aFacesPln->isCoincident(aPln)) {
1609 theError = "Error: Only coincident faces allowed.";
1618 //==================================================================================================
1620 bool FeaturesPlugin_IntersectionSelection::isValid(const AttributePtr& theAttribute,
1621 const std::list<std::string>& theArguments,
1622 Events_InfoMessage& theError) const
1624 if (!theAttribute.get()) {
1625 theError = "Error: empty selection.";
1628 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1629 AttributeSelectionListPtr anAttrSelectionList =
1630 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1631 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1632 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1633 if (!anAttrSelection.get()) {
1634 theError = "Error: empty attribute selection.";
1637 ResultPtr aContext = anAttrSelection->context();
1638 if(!aContext.get()) {
1639 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1640 if (!aContFeat.get() || !aContFeat->results().size() ||
1641 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1642 theError = "Error: Empty selection context.";
1646 FeaturePtr aFeature = anAttrSelection->contextFeature().get() ?
1647 anAttrSelection->contextFeature() : ModelAPI_Feature::feature(aContext);
1648 if (!aFeature.get()) {
1649 theError = "Error: empty feature.";
1652 std::string aFeatureKind = aFeature->getKind();
1653 if (aFeatureKind == "Sketch" ||
1654 aFeatureKind == "Plane" ||
1655 aFeatureKind == "Axis") {
1656 theError = "Error: %1 shape is not allowed for selection.";
1657 theError.arg(aFeatureKind);
1660 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1661 if (!aShape.get()) {
1662 GeomShapePtr aContextShape = aContext->shape();
1663 aShape = aContextShape;
1665 if (!aShape.get()) {
1666 theError = "Error: empty shape.";
1669 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1670 theError = "Error: Local selection not allowed.";
1674 int aShapeType = aShape->shapeType();
1675 // Allow to select edges, faces and solids.
1676 if (aShapeType != GeomAPI_Shape::EDGE &&
1677 aShapeType != GeomAPI_Shape::FACE &&
1678 aShapeType != GeomAPI_Shape::SOLID &&
1679 aShapeType != GeomAPI_Shape::COMPSOLID &&
1680 aShapeType != GeomAPI_Shape::COMPOUND) {
1681 theError = "Error: selected shape has the wrong type.";
1690 //==================================================================================================
1692 bool FeaturesPlugin_ValidatorBooleanFuseSelection::isValid(
1693 const AttributePtr& theAttribute,
1694 const std::list<std::string>& theArguments,
1695 Events_InfoMessage& theError) const
1697 AttributeSelectionListPtr anAttrSelectionList =
1698 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1699 if (!anAttrSelectionList.get()) {
1701 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1705 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1706 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1707 if (!anAttrSelection.get()) {
1708 theError = "Error: Empty attribute selection.";
1711 ResultPtr aContext = anAttrSelection->context();
1712 if(!aContext.get()) {
1713 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1714 if (!aContFeat.get() || !aContFeat->results().size() ||
1715 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1716 theError = "Error: Empty selection context.";
1720 ResultConstructionPtr aResultConstruction =
1721 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1722 if (aResultConstruction.get()) {
1723 theError = "Error: Result construction not allowed for selection.";
1726 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1727 if (!aShape.get()) {
1728 GeomShapePtr aContextShape = aContext->shape();
1729 aShape = aContextShape;
1731 if (!aShape.get()) {
1732 theError = "Error: Empty shape.";
1735 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1736 theError = "Error: Local selection not allowed.";
1745 //=================================================================================================
1746 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
1747 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1748 const std::list<std::string>& theArguments,
1749 Events_InfoMessage& theError) const
1752 if (theArguments.size() != 2) {
1753 theError = "Wrong number of arguments (expected 2).";
1758 std::shared_ptr<FeaturesPlugin_BooleanFuse> aFeature =
1759 std::dynamic_pointer_cast<FeaturesPlugin_BooleanFuse>(theFeature);
1761 int anObjectsNb = 0, aToolsNb = 0;
1763 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1765 bool isAllInSameCompSolid = true;
1766 ResultBodyPtr aCompSolid;
1768 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1769 if (anAttrSelList) {
1770 anObjectsNb = anAttrSelList->size();
1771 for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex) {
1772 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1773 ResultPtr aContext = anAttr->context();
1774 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1775 if (aResCompSolidPtr.get()) {
1776 if (aCompSolid.get()) {
1777 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1779 aCompSolid = aResCompSolidPtr;
1782 isAllInSameCompSolid = false;
1789 if (aFeature->string(FeaturesPlugin_BooleanFuse::CREATION_METHOD())->value()
1790 == FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED()) {
1791 anAttrSelList = theFeature->selectionList(*anIt);
1792 if (anAttrSelList) {
1793 aToolsNb = anAttrSelList->size();
1794 if (isAllInSameCompSolid) {
1795 for (int anIndex = 0; anIndex < aToolsNb; ++anIndex) {
1796 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1797 ResultPtr aContext = anAttr->context();
1798 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1799 if (aResCompSolidPtr.get()) {
1800 if (aCompSolid.get()) {
1801 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1803 aCompSolid = aResCompSolidPtr;
1806 isAllInSameCompSolid = false;
1816 if (anObjectsNb + aToolsNb < 2) {
1817 theError = "Not enough arguments for Fuse operation.";
1824 //=================================================================================================
1826 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isNotObligatory(
1827 std::string theFeature,
1828 std::string theAttribute)
1830 if (theAttribute == "main_objects" || theAttribute == "tool_objects") {
1838 //==================================================================================================
1840 bool FeaturesPlugin_ValidatorBooleanCommonSelection::isValid(
1841 const AttributePtr& theAttribute,
1842 const std::list<std::string>& theArguments,
1843 Events_InfoMessage& theError) const
1845 AttributeSelectionListPtr anAttrSelectionList =
1846 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1847 if (!anAttrSelectionList.get()) {
1849 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1853 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1854 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1855 if (!anAttrSelection.get()) {
1856 theError = "Error: Empty attribute selection.";
1859 ResultPtr aContext = anAttrSelection->context();
1860 if (!aContext.get() && !anAttrSelection->contextFeature().get()) {
1861 theError = "Error: Empty selection context.";
1864 ResultConstructionPtr aResultConstruction =
1865 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1866 if (aResultConstruction.get()) {
1867 if (theAttribute->id() != FeaturesPlugin_BooleanCommon::TOOL_LIST_ID()) {
1868 theError = "Error: Result construction not allowed for selection.";
1872 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1873 GeomShapePtr aContextShape;
1874 if (aContext.get()) {
1875 aContextShape = aContext->shape();
1877 if (!aShape.get()) {
1878 aShape = aContextShape;
1880 if (!aShape.get()) {
1881 theError = "Error: Empty shape.";
1884 if (aContextShape.get() && !aShape->isEqual(aContextShape)) {
1885 theError = "Error: Local selection not allowed.";
1889 if (aResultConstruction.get() && aShape->shapeType() != GeomAPI_Shape::FACE) {
1890 theError = "Error: Result construction should be plane.";
1899 //=================================================================================================
1900 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isValid(
1901 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1902 const std::list<std::string>& theArguments,
1903 Events_InfoMessage& theError) const
1905 if (theArguments.size() != 2) {
1907 theError = "Wrong number of arguments (expected 2).";
1912 std::shared_ptr<FeaturesPlugin_BooleanCommon> aFeature =
1913 std::dynamic_pointer_cast<FeaturesPlugin_BooleanCommon>(theFeature);
1915 int anObjectsNb = 0, aToolsNb = 0;
1917 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1919 bool isAllInSameCompSolid = true;
1920 ResultBodyPtr aCompSolid;
1922 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1923 if (anAttrSelList) {
1924 anObjectsNb = anAttrSelList->size();
1927 bool isSimpleMode = aFeature->string(FeaturesPlugin_BooleanCommon::CREATION_METHOD())->value()
1928 == FeaturesPlugin_BooleanCommon::CREATION_METHOD_SIMPLE();
1930 if (!isSimpleMode) {
1931 anAttrSelList = theFeature->selectionList(*anIt);
1932 if (anAttrSelList) {
1933 aToolsNb = anAttrSelList->size();
1937 if ((isSimpleMode && anObjectsNb < 2)
1938 || (!isSimpleMode && (anObjectsNb == 0 || aToolsNb == 0))) {
1939 theError = "Not enough arguments for Fuse operation.";
1945 //=================================================================================================
1947 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isNotObligatory(
1948 std::string theFeature,
1949 std::string theAttribute)
1955 //==================================================================================================
1956 bool FeaturesPlugin_ValidatorDefeaturingSelection::isValid(
1957 const AttributePtr& theAttribute,
1958 const std::list<std::string>& theArguments,
1959 Events_InfoMessage& theError) const
1961 AttributeSelectionListPtr anAttrSelectionList =
1962 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1963 if (!anAttrSelectionList.get()) {
1965 theError = "Error: This validator can only work with selection list attributes.";
1970 // Check selected entities are sub-shapes of solid or compsolid
1971 GeomShapePtr aBaseSolid;
1972 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1973 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1974 if (!anAttrSelection.get()) {
1975 theError = "Error: Empty attribute selection.";
1978 ResultPtr aContext = anAttrSelection->context();
1979 if (!aContext.get()) {
1980 theError = "Error: Empty selection context.";
1984 GeomShapePtr aContextShape = aContext->shape();
1985 if (aContextShape->shapeType() != GeomAPI_Shape::SOLID) {
1986 theError = "Error: Not all selected shapes are sub-shapes of solids.";