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_CompositeBoolean.h"
27 #include "FeaturesPlugin_Extrusion.h"
28 #include "FeaturesPlugin_Pipe.h"
29 #include "FeaturesPlugin_Union.h"
31 #include <Events_InfoMessage.h>
33 #include <ModelAPI_Attribute.h>
34 #include <ModelAPI_AttributeDouble.h>
35 #include <ModelAPI_AttributeInteger.h>
36 #include <ModelAPI_AttributeSelectionList.h>
37 #include <ModelAPI_AttributeString.h>
38 #include <ModelAPI_AttributeReference.h>
39 #include <ModelAPI_AttributeRefList.h>
40 #include <ModelAPI_Feature.h>
41 #include <ModelAPI_ResultBody.h>
42 #include <ModelAPI_ResultConstruction.h>
43 #include <ModelAPI_Tools.h>
45 #include <GeomValidators_BodyShapes.h>
46 #include <GeomValidators_Face.h>
47 #include <GeomValidators_FeatureKind.h>
48 #include <GeomValidators_ShapeType.h>
50 #include <GeomAPI_DataMapOfShapeShape.h>
51 #include <GeomAPI_Lin.h>
52 #include <GeomAPI_PlanarEdges.h>
53 #include <GeomAPI_Pln.h>
54 #include <GeomAPI_ShapeExplorer.h>
55 #include <GeomAPI_ShapeIterator.h>
57 #include <GeomAlgoAPI_CompoundBuilder.h>
58 #include <GeomAlgoAPI_MapShapesAndAncestors.h>
59 #include <GeomAlgoAPI_Prism.h>
60 #include <GeomAlgoAPI_ShapeBuilder.h>
61 #include <GeomAlgoAPI_ShapeTools.h>
62 #include <GeomAlgoAPI_WireBuilder.h>
64 #define _USE_MATH_DEFINES
67 //==================================================================================================
68 bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
69 const std::list<std::string>& theArguments,
70 Events_InfoMessage& theError) const
72 AttributeSelectionPtr aPathAttrSelection =
73 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
74 if(!aPathAttrSelection.get()) {
76 theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
81 GeomShapePtr aPathShape = aPathAttrSelection->value();
82 ResultPtr aContext = aPathAttrSelection->context();
84 theError = "Error: Empty context.";
87 GeomShapePtr aContextShape = aContext->shape();
88 if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE &&
89 !aPathShape->isEqual(aContextShape)) {
90 theError = "Error: Local selection of wires not allowed.";
97 //==================================================================================================
98 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const AttributePtr& theAttribute,
99 const std::list<std::string>& theArguments,
100 Events_InfoMessage& theError) const
102 AttributeSelectionListPtr anAttrSelectionList =
103 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
104 if(!anAttrSelectionList.get()) {
107 "Error: This validator can only work with selection list attributes in \"Pipe\" feature.";
111 std::shared_ptr<FeaturesPlugin_Pipe> aFeature =
112 std::dynamic_pointer_cast<FeaturesPlugin_Pipe>(theAttribute->owner());
114 AttributeSelectionPtr aPathSelection = aFeature->selection(FeaturesPlugin_Pipe::PATH_OBJECT_ID());
115 if (!aPathSelection.get()) {
117 theError = "Error: Path not selected.";
122 GeomShapePtr aPathShape = aPathSelection->value();
123 if (!aPathShape.get()) {
124 ResultPtr aContext = aPathSelection->context();
125 if (!aContext.get()) {
126 FeaturePtr aContFeat = aPathSelection->contextFeature();
127 if (!aContFeat.get() || !aContFeat->results().size()) {
128 theError = "Error: Empty selection context.";
132 aPathShape = aContext->shape();
135 if (!aPathShape.get()) {
136 theError = "Error: Empty path shape.";
140 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
141 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
142 if (!anAttrSelection.get()) {
143 theError = "Error: Empty attribute selection.";
146 ResultPtr aContext = anAttrSelection->context();
147 if (!aContext.get()) {
148 FeaturePtr aContFeat = anAttrSelection->contextFeature();
149 if (!aContFeat.get() || !aContFeat->results().size()) {
150 theError = "Error: Empty selection context.";
154 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
155 if (!aShape.get() && aContext.get()) {
156 GeomShapePtr aContextShape = aContext->shape();
157 aShape = aContextShape;
160 theError = "Error: Empty shape.";
164 if (!aPathShape->isSubShape(aShape)) {
165 theError = "Error: Location should be a vertex subshape from path shape.";
173 //==================================================================================================
175 bool FeaturesPlugin_ValidatorPipeLocationsNumber::isValid(
176 const std::shared_ptr<ModelAPI_Feature>& theFeature,
177 const std::list<std::string>& theArguments,
178 Events_InfoMessage& theError) const
180 static const std::string aCreationMethodID = "creation_method";
181 static const std::string aBaseObjectsID = "base_objects";
182 static const std::string aLocationsID = "locations_objects";
184 if(theFeature->getKind() != "Pipe") {
185 theError = "Error: Feature \"%1\" does not supported by this validator.";
186 theError.arg(theFeature->getKind());
190 AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
191 if(!aCreationMethodAttr.get()) {
192 theError = "Error: Could not get \"%1\" attribute.";
193 theError.arg(aCreationMethodID);
197 if(aCreationMethodAttr->value() != "locations") {
201 AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
202 if(!aBaseObjectsSelectionList.get()) {
203 theError = "Error: Could not get \"%1\" attribute.";
204 theError.arg(aBaseObjectsID);
208 AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
209 if(!aLocationsSelectionList.get()) {
210 theError = "Error: Could not get \"%1\" attribute.";
211 theError.arg(aBaseObjectsID);
215 if(aLocationsSelectionList->size() > 0 &&
216 aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
217 theError = "Error: Number of locations should be the same as base objects.";
225 //==================================================================================================
226 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
227 const std::list<std::string>& theArguments,
228 Events_InfoMessage& theError) const
231 if(theArguments.empty()) {
232 theError = "Error: Validator parameters is empty.";
237 // Checking attribute.
238 if(!isValidAttribute(theAttribute, theArguments, theError)) {
239 if(theError.empty()) {
240 theError = "Error: Attribute contains unacceptable shape.";
245 GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;
246 std::string anAttributeType = theAttribute->attributeType();
247 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
248 AttributeSelectionListPtr aListAttr =
249 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
250 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
251 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
252 ResultPtr aContext = aSelectionAttr->context();
253 if(!aContext.get() && !aSelectionAttr->contextFeature().get()) {
254 theError = "Error: Empty context.";
258 ResultConstructionPtr aResultConstruction =
259 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
260 if(!aResultConstruction.get()) {
261 // It is not a result construction.
262 // If shape is compound check that it contains only faces, edges or vertices.
263 GeomShapePtr aShape = aSelectionAttr->value();
265 if (aContext.get()) {
266 aShape = aContext->shape();
268 theError = "Error: Empty context.";
273 if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
274 for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
275 GeomShapePtr aSubShape = anIt.current();
276 if (aSubShape->shapeType() > GeomAPI_Shape::VERTEX ||
277 aSubShape->shapeType() < GeomAPI_Shape::FACE) {
278 theError = "Error: Compound should contain only faces, edges or vertices.";
287 GeomShapePtr aShape = aSelectionAttr->value();
288 GeomShapePtr aContextShape = aResultConstruction->shape();
290 // Whole sketch selected.
293 // Object from sketch selected.
294 for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
295 GeomShapePtr aWire = anExp.current();
296 if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
297 theError = "Error: Wire with wrong orientation selected.";
301 if(aSelectedWiresFromObjects.isBound(aWire)) {
303 "Error: Objects with this wire already selected. Don't allow to select this object.";
307 aSelectedWiresFromObjects.bind(aWire, aWire);
316 //==================================================================================================
317 bool FeaturesPlugin_ValidatorBaseForGenerationSketchOrSketchObjects::isValid(
318 const std::shared_ptr<ModelAPI_Feature>& theFeature,
319 const std::list<std::string>& theArguments,
320 Events_InfoMessage& theError) const
322 const std::string aBaseObjectsID = theArguments.front();
324 AttributeSelectionListPtr aListAttr = theFeature->selectionList(aBaseObjectsID);
325 if(!aListAttr.get()) {
327 theError = "Error: Could not get \"%1\" attribute.";
328 theError.arg(aBaseObjectsID);
333 std::set<ResultConstructionPtr> aSelectedSketches;
334 std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;
336 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
337 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
338 ResultPtr aContext = aSelectionAttr->context();
339 if(!aContext.get()) {
340 FeaturePtr aFeature = aSelectionAttr->contextFeature();
341 if (!aFeature.get() || aFeature->results().empty()) {
342 theError = "Error: Empty context.";
345 aContext = aFeature->firstResult();
349 ResultConstructionPtr aResultConstruction =
350 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
351 if(!aResultConstruction.get()) {
352 // It is not a result construction.
356 GeomShapePtr aShape = aSelectionAttr->value();
357 GeomShapePtr aContextShape = aResultConstruction->shape();
359 // Whole sketch selected.
360 aSelectedSketches.insert(aResultConstruction);
362 // Object from sketch selected.
363 aSelectedSketchesFromObjects.insert(aResultConstruction);
368 for(std::set<ResultConstructionPtr>::const_iterator anIt = aSelectedSketches.cbegin();
369 anIt != aSelectedSketches.cend();
371 ResultConstructionPtr aResultConstruction = *anIt;
372 if(aSelectedSketchesFromObjects.find(aResultConstruction) !=
373 aSelectedSketchesFromObjects.cend()) {
374 theError = "Sketch and objects from it can not be selected at the same time.";
382 //==================================================================================================
383 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
384 const std::list<std::string>& theArguments,
385 Events_InfoMessage& theError) const
387 if(!theAttribute.get()) {
389 theError = "Error: Empty attribute.";
394 std::string anAttributeType = theAttribute->attributeType();
395 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
396 AttributeSelectionListPtr aListAttr =
397 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
398 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
399 // If at least one attribute is invalid, the result is false.
400 if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {
404 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
406 AttributeSelectionPtr anAttr =
407 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
408 ResultPtr aContext = anAttr->context();
409 if(!aContext.get() && !anAttr->contextFeature().get()) {
410 theError = "Error: Attribute have empty context.";
414 GeomShapePtr aShape = anAttr->value();
415 GeomShapePtr aContextShape;
416 if(!aShape.get() && aContext.get()) {
417 aContextShape = aContext->shape();
418 aShape = aContextShape;
421 theError = "Error: Empty shape selected";
425 ResultConstructionPtr aConstruction;
426 if (!aContext.get() && anAttr->contextFeature()->results().size() == 1) {
427 aContext = anAttr->contextFeature()->firstResult();
430 aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
431 if(aConstruction.get()) {
432 // Construction selected. Check that it is not infinite.
433 if(aConstruction->isInfinite()) {
434 theError = "Error: Infinite constructions is not allowed as base.";
438 GeomShapePtr aContextShape = aContext->shape();
439 if(aShape->isEqual(aContextShape)) {
440 // Whole construction selected. Check that it have faces.
441 if(aConstruction->facesNum() > 0) {
445 // CUT operation supports only FACE or WIRE as a tool base
446 std::shared_ptr<FeaturesPlugin_CompositeBoolean> aComposite =
447 std::dynamic_pointer_cast<FeaturesPlugin_CompositeBoolean>(
448 ModelAPI_Feature::feature(theAttribute->owner()));
450 aComposite->operationType() == FeaturesPlugin_CompositeBoolean::BOOL_CUT) {
451 return aShape->shapeType() == GeomAPI_Shape::WIRE ||
452 aShape->shapeType() == GeomAPI_Shape::FACE;
457 if(aContextShape.get() && !aShape->isEqual(aContextShape)) {
458 // Local selection on body does not allowed.
460 "Error: Selected shape is in the local selection. Only global selection is allowed.";
464 // Check that object is a shape with allowed type.
465 GeomValidators_ShapeType aShapeTypeValidator;
466 if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
467 theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or "
468 "wires on sketch, whole sketch (if it has at least one face), "
469 "and whole objects with shape types: %1";
470 std::string anArgumentString;
471 for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {
472 if (!anArgumentString.empty())
473 anArgumentString += ", ";
474 anArgumentString += *anIt;
476 theError.arg(anArgumentString);
482 theError = "Error: Attribute \"%1\" does not supported by this validator.";
483 theError.arg(anAttributeType);
491 //==================================================================================================
493 bool FeaturesPlugin_ValidatorCompositeLauncher::isValid(const AttributePtr& theAttribute,
494 const std::list<std::string>& theArguments,
495 Events_InfoMessage& theError) const
497 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
498 theError = "Error: The attribute with the %1 type is not processed";
499 theError.arg(theAttribute->attributeType());
502 if (theArguments.size() != 2) {
503 theError = "Error: Wrong parameters in XML definition for %1 type";
504 theError.arg(theAttribute->attributeType());
507 // first argument is for the base attribute, second - for skipping feature kind
508 std::list<std::string>::const_iterator anIt = theArguments.begin();
509 std::string aBaseAttributeId = *anIt;
510 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
511 AttributePtr aBaseAttribute = aFeature->attribute(aBaseAttributeId);
512 if (!aBaseAttribute.get()) {
513 theError = "Wrong parameters in XML definition for %1 type";
514 theError.arg(theAttribute->attributeType());
517 if (aBaseAttribute->isInitialized()) // when base list of composite feature is already filled,
518 // this validator is not necessary anymore
522 std::string aFeatureAttributeKind = *anIt;
523 GeomValidators_FeatureKind* aValidator = new GeomValidators_FeatureKind();
524 // check whether the selection is on the sketch
525 std::list<std::string> anArguments;
526 anArguments.push_back(aFeatureAttributeKind);
528 bool aFeatureKind = aValidator->isValid(theAttribute, theArguments, theError);
529 bool aPlanarFace = false;
530 // check if selection has Face selected
531 GeomValidators_ShapeType* aShapeType = new GeomValidators_ShapeType();
533 anArguments.push_back("face");
534 aPlanarFace = aShapeType->isValid(theAttribute, anArguments, theError);
536 bool aValid = !aFeatureKind && aPlanarFace;
541 //==================================================================================================
542 bool FeaturesPlugin_ValidatorExtrusionDir::isValid(
543 const std::shared_ptr<ModelAPI_Feature>& theFeature,
544 const std::list<std::string>& theArguments,
545 Events_InfoMessage& theError) const
547 if(theArguments.size() != 2) {
549 theError = "Error: Validator should be used with 2 parameters for extrusion.";
554 std::list<std::string>::const_iterator
555 anArgsIt = theArguments.begin(), aLast = theArguments.end();
557 AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
560 GeomShapePtr aDirShape;
561 AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
563 aDirShape = aSelAttr->value();
564 if(!aDirShape.get()) {
565 ResultPtr aContext = aSelAttr->context();
566 if(!aContext.get()) {
567 FeaturePtr aFeature = aSelAttr->contextFeature();
568 if (aFeature.get() && !aFeature->results().empty()) {
569 aContext = aFeature->firstResult();
574 aDirShape = aContext->shape();
577 if (aDirShape.get() && aDirShape->isCompound()) {
578 GeomAPI_ShapeIterator anIt(aDirShape);
579 aDirShape = anIt.current();
584 if(!aDirShape.get() || aDirShape->isNull() ||
585 aDirShape->shapeType() != GeomAPI_Shape::EDGE) {
586 // Check that dir can be empty.
587 if(!isShapesCanBeEmpty(aCheckAttribute, theError)) {
588 theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" "
589 "can not be used with default value. Select direction for extrusion.";
590 theError.arg(*anArgsIt);
597 std::shared_ptr<GeomAPI_Edge> aDirEdge(new GeomAPI_Edge(aDirShape));
599 // If faces selected check that direction not parallel with them.
600 AttributeSelectionListPtr aListAttr =
601 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aCheckAttribute);
602 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
603 AttributeSelectionPtr anAttr = aListAttr->value(anIndex);
604 GeomShapePtr aShapeInList = anAttr->value();
605 if(!aShapeInList.get()) {
606 aShapeInList = anAttr->context()->shape();
608 bool isParallel = true;
609 if(aShapeInList->shapeType() == GeomAPI_Shape::FACE ||
610 aShapeInList->shapeType() == GeomAPI_Shape::SHELL) {
611 for(GeomAPI_ShapeExplorer
612 anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
613 std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(anExp.current()));
614 isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace);
619 } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) {
620 std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges =
621 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShapeInList);
622 if(aPlanarEdges.get()) {
623 std::shared_ptr<GeomAPI_Dir> aSketchDir = aPlanarEdges->norm();
624 if(aDirEdge->isLine()) {
625 std::shared_ptr<GeomAPI_Dir> aDir = aDirEdge->line()->direction();
626 isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7;
638 "Error: Direction is parallel to one of the selected face or face on selected shell.";
646 //==================================================================================================
647 bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute,
648 Events_InfoMessage& theError) const
651 if(!theAttribute.get()) {
656 std::string anAttributeType = theAttribute->attributeType();
657 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
658 AttributeSelectionListPtr aListAttr =
659 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
660 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
661 // If at least one attribute is invalid, the result is false.
662 if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
666 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
668 AttributeSelectionPtr anAttr =
669 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
670 ResultPtr aContext = anAttr->context();
671 if(!aContext.get() && !anAttr->contextFeature().get()) {
675 GeomShapePtr aShape = anAttr->value();
676 if(!aShape.get() && aContext.get()) {
677 GeomShapePtr aContextShape = aContext->shape();
678 aShape = aContextShape;
684 if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
685 aShape->shapeType() == GeomAPI_Shape::EDGE ||
686 !aShape->isPlanar()) {
696 //==================================================================================================
697 bool FeaturesPlugin_ValidatorExtrusionBoundaryFace::isValid(
698 const AttributePtr& theAttribute,
699 const std::list<std::string>& theArguments,
700 Events_InfoMessage& theError) const
702 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
704 // Collect all necessary attributes and try to build prism
707 AttributeSelectionListPtr aBaseShapeAttr =
708 aFeature->selectionList(FeaturesPlugin_Extrusion::BASE_OBJECTS_ID());
709 ListOfShape aBaseShapeList;
711 if (!FeaturesPlugin_Tools::getShape(aBaseShapeAttr, true, aBaseShapeList, anError)) {
717 AttributeSelectionPtr aSelection =
718 aFeature->selection(FeaturesPlugin_Extrusion::DIRECTION_OBJECT_ID());
719 GeomShapePtr aShape = aSelection->value();
720 if (!aShape.get() && aSelection->context().get())
721 aShape = aSelection->context()->shape();
725 if (aShape->isEdge())
726 anEdge = aShape->edge();
727 else if (aShape->isCompound()) {
728 GeomAPI_ShapeIterator anIt(aShape);
729 anEdge = anIt.current()->edge();
733 std::shared_ptr<GeomAPI_Dir> aDir;
734 if (anEdge.get() && anEdge->isLine())
735 aDir = anEdge->line()->direction();
738 GeomShapePtr aFromShape, aToShape;
739 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
740 if (aSelection.get()) {
741 aToShape = aSelection->value();
742 if (!aToShape.get() && aSelection->context().get())
743 aToShape = aSelection->context()->shape();
744 if (aToShape.get() && aToShape->isCompound()) {
745 GeomAPI_ShapeIterator anIt(aToShape);
746 aToShape = anIt.current();
748 if (aToShape.get() && !aToShape->isFace()) {
749 theError = "\"To\" shape is not a face";
753 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
754 if (aSelection.get()) {
755 aFromShape = aSelection->value();
756 if (!aFromShape.get() && aSelection->context().get())
757 aFromShape = aSelection->context()->shape();
758 if (aFromShape.get() && aFromShape->isCompound()) {
759 GeomAPI_ShapeIterator anIt(aFromShape);
760 aFromShape = anIt.current();
762 if (aFromShape.get() && !aFromShape->isFace()) {
763 theError = "\"From\" shape is not a face";
768 double aToSize = aFeature->real(FeaturesPlugin_Extrusion::TO_OFFSET_ID())->value();
769 double aFromSize = aFeature->real(FeaturesPlugin_Extrusion::FROM_OFFSET_ID())->value();
772 for (ListOfShape::iterator anIt = aBaseShapeList.begin(); anIt != aBaseShapeList.end(); anIt++) {
773 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIt;
775 std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo(
776 new GeomAlgoAPI_Prism(aBaseShape, aDir, aToShape, aToSize, aFromShape, aFromSize));
777 bool isFailed = GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPrismAlgo,
778 FeaturesPlugin_Extrusion::ID(),
789 //==================================================================================================
790 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
791 const std::list<std::string>& theArguments,
792 Events_InfoMessage& theError) const
794 AttributeSelectionListPtr anAttrSelectionList =
795 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
796 if(!anAttrSelectionList.get()) {
799 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
803 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
804 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theAttribute->owner());
805 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
807 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
808 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
809 if(!anAttrSelection.get()) {
810 theError = "Error: Empty attribute selection.";
813 ResultPtr aContext = anAttrSelection->context();
814 if(!aContext.get()) {
815 FeaturePtr aContFeat = anAttrSelection->contextFeature();
816 if (!aContFeat.get() || !aContFeat->results().size()) {
817 theError = "Error: Empty selection context.";
821 ResultConstructionPtr aResultConstruction =
822 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
823 if(aResultConstruction.get()) {
824 if (anOperationType != FeaturesPlugin_Boolean::BOOL_FILL
825 || theAttribute->id() != FeaturesPlugin_Boolean::TOOL_LIST_ID()) {
826 theError = "Error: Result construction not allowed for selection.";
830 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
831 if(!aShape.get() && aContext.get()) {
832 GeomShapePtr aContextShape = aContext->shape();
833 aShape = aContextShape;
836 theError = "Error: Empty shape.";
839 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
840 theError = "Error: Local selection not allowed.";
844 GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType();
845 std::set<GeomAPI_Shape::ShapeType> anAllowedTypes;
846 if(anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE) {
847 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
848 anAllowedTypes.insert(GeomAPI_Shape::FACE);
849 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
850 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
851 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
852 } else if (anOperationType == FeaturesPlugin_Boolean::BOOL_FILL
853 || anOperationType == FeaturesPlugin_Boolean::BOOL_CUT)
855 anAllowedTypes.insert(GeomAPI_Shape::VERTEX);
856 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
857 anAllowedTypes.insert(GeomAPI_Shape::WIRE);
858 anAllowedTypes.insert(GeomAPI_Shape::FACE);
859 anAllowedTypes.insert(GeomAPI_Shape::SHELL);
860 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
861 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
862 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
864 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
865 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
866 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
869 if(anAllowedTypes.find(aShapeType) == anAllowedTypes.end()
870 || (aResultConstruction.get() && aShapeType != GeomAPI_Shape::FACE)) {
871 theError = "Error: Selected shape has the wrong type.";
880 //==================================================================================================
881 bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute,
882 const std::list<std::string>& theArguments,
883 Events_InfoMessage& theError) const
885 AttributeSelectionListPtr anAttrSelectionList =
886 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
887 if(!anAttrSelectionList.get()) {
890 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
895 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
896 // Check all selected entities are sub-shapes of single solid
897 GeomShapePtr aBaseSolid;
898 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
899 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
900 if(!anAttrSelection.get()) {
901 theError = "Error: Empty attribute selection.";
904 ResultPtr aContext = anAttrSelection->context();
905 if(!aContext.get()) {
906 FeaturePtr aContFeat = anAttrSelection->contextFeature();
907 if (!aContFeat.get() || !aContFeat->results().size() ||
908 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
909 theError = "Error: Empty selection context.";
912 if (aContFeat->results().size() == 1)
913 aContext = aContFeat->firstResult();
915 theError = "Error: Too many shapes selected.";
920 ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext, true);
921 GeomShapePtr anOwner = aContext->shape();
922 GeomShapePtr aTopLevelOwner = aContextOwner.get() ? aContextOwner->shape() : anOwner;
925 theError = "Error: wrong feature is selected.";
929 if (anOwner->shapeType() != GeomAPI_Shape::SOLID &&
930 anOwner->shapeType() != GeomAPI_Shape::COMPSOLID) {
931 theError = "Error: Not all selected shapes are sub-shapes of solids.";
936 aBaseSolid = aTopLevelOwner;
937 else if (!aBaseSolid->isEqual(aTopLevelOwner)) {
938 theError = "Error: Sub-shapes of different solids have been selected.";
947 //==================================================================================================
948 bool FeaturesPlugin_ValidatorFillet1DSelection::isValid(const AttributePtr& theAttribute,
949 const std::list<std::string>& theArguments,
950 Events_InfoMessage& theError) const
952 AttributeSelectionListPtr anAttrSelectionList =
953 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
954 if (!anAttrSelectionList.get()) {
957 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
962 // check each selected vertex is a sharp corner between adjacent edges,
963 // and these edges are in the same plane
964 std::map<GeomShapePtr, MapShapeToShapes> aWireSubshapes;
965 int aNbSel = anAttrSelectionList->size();
966 for (int ind = 0; ind < aNbSel; ++ind) {
967 AttributeSelectionPtr aCurSel = anAttrSelectionList->value(ind);
968 GeomShapePtr aContext = aCurSel->context()->shape();
969 GeomShapePtr aVertex = aCurSel->value();
970 // check wire already processed, if not, store all vertices and edges, sharing them
971 std::map<GeomShapePtr, MapShapeToShapes>::iterator aProcessed = aWireSubshapes.find(aContext);
972 if (aProcessed == aWireSubshapes.end()) {
973 if (aContext->shapeType() != GeomAPI_Shape::WIRE) {
974 theError = "Selected vertex is not a wire corner";
977 if (aVertex->shapeType() != GeomAPI_Shape::VERTEX) {
978 theError = "Selected shape is not a vertex";
982 GeomAlgoAPI_MapShapesAndAncestors aMapVE(aContext, GeomAPI_Shape::VERTEX,
983 GeomAPI_Shape::EDGE);
984 aWireSubshapes[aContext] = aMapVE.map();
985 aProcessed = aWireSubshapes.find(aContext);
989 MapShapeToShapes::iterator aFound = aProcessed->second.find(aVertex);
990 if (aFound == aProcessed->second.end()) {
991 theError = "Selected vertex does not exist in the wire";
994 else if (aFound->second.size() != 2) {
995 theError = "Vertex should be shared between 2 edges exactly";
1000 anEdges.insert(anEdges.end(), aFound->second.begin(), aFound->second.end());
1001 GeomPlanePtr aPlane = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
1003 theError = "Error: Edges are not planar";
1007 GeomEdgePtr anEdge1(new GeomAPI_Edge(anEdges.front()));
1008 GeomEdgePtr anEdge2(new GeomAPI_Edge(anEdges.back()));
1009 GeomVertexPtr aSharedVertex(new GeomAPI_Vertex(aVertex));
1010 if (GeomAlgoAPI_ShapeTools::isTangent(anEdge1, anEdge2, aSharedVertex)) {
1011 theError = "Error: Edges are tangent";
1019 //==================================================================================================
1020 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
1021 const std::list<std::string>& theArguments,
1022 Events_InfoMessage& theError) const
1024 AttributeSelectionListPtr anAttrSelectionList =
1025 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1026 if(!anAttrSelectionList.get()) {
1028 theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
1033 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1034 AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
1036 //GeomValidators_BodyShapes aBodyValidator;
1037 //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
1041 GeomValidators_FeatureKind aFeatureKindValidator;
1042 if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
1046 ResultPtr aContext = aSelectAttr->context();
1047 ResultConstructionPtr aResultConstruction =
1048 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1049 if(aResultConstruction.get()) {
1050 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1054 ResultBodyPtr aResultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1055 if(aResultBody.get()) {
1058 FeaturePtr aResultFeature = aSelectAttr->contextFeature();
1059 if(aResultFeature.get()) {
1060 bool aOkRes = false;
1061 std::list<ResultPtr>::const_iterator aFRes = aResultFeature->results().cbegin();
1062 for(; aFRes != aResultFeature->results().cend() && !aOkRes; aFRes++) {
1063 ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aFRes);
1064 if (aBody.get() && !aBody->isDisabled())
1071 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1079 //==================================================================================================
1080 bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
1081 const std::list<std::string>& theArguments,
1082 Events_InfoMessage& theError) const
1084 AttributeSelectionListPtr aSubShapesAttrList =
1085 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1086 if(!aSubShapesAttrList.get()) {
1089 "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
1094 static const std::string aBaseShapeID = "base_shape";
1095 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1096 AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
1098 if(!aShapeAttrSelection.get()) {
1100 theError = "Error: Could not get \"%1\" attribute.";
1101 theError.arg(aBaseShapeID);
1106 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1107 ResultPtr aContext = aShapeAttrSelection->context();
1108 if(!aContext.get()) {
1109 theError = "Error: Empty context.";
1112 if(!aBaseShape.get()) {
1113 aBaseShape = aContext->shape();
1115 if(!aBaseShape.get()) {
1116 theError = "Error: Empty base shape.";
1120 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
1121 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1122 bool isSameFound = false;
1123 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1124 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1125 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
1127 if ((*anIt)->isEqual(aShapeToAdd)) {
1133 theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
1141 //==================================================================================================
1142 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(
1143 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1144 const std::list<std::string>& theArguments,
1145 Events_InfoMessage& theError) const
1147 static const std::string aBaseShapeID = "base_shape";
1148 static const std::string aSubShapesID = "subshapes_to_keep";
1151 if(theFeature->getKind() != "Remove_SubShapes") {
1152 theError = "Error: Feature \"%1\" does not supported by this validator.";
1153 theError.arg(theFeature->getKind());
1157 AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
1158 if(!aShapeAttrSelection.get()) {
1159 theError = "Error: Could not get \"%1\" attribute.";
1160 theError.arg(aBaseShapeID);
1164 AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
1165 if(!aSubShapesAttrList.get()) {
1166 theError = "Error: Could not get \"%1\" attribute.";
1167 theError.arg(aSubShapesID);
1173 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1174 if(!aBaseShape.get()) {
1175 theError = "Error: Base shape is empty.";
1178 GeomShapePtr aResultShape = aBaseShape->emptyCopied();
1180 if (aSubShapesAttrList->size() == 0) {
1181 theError = "Error: Resulting shape is not valid.";
1185 // Copy sub-shapes from list to new shape.
1186 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1187 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1188 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1189 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
1193 if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
1194 theError = "Error: Resulting shape is not valid.";
1201 //==================================================================================================
1203 bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute,
1204 const std::list<std::string>& theArguments,
1205 Events_InfoMessage& theError) const
1207 AttributeSelectionListPtr aBaseObjectsAttrList =
1208 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1209 if(!aBaseObjectsAttrList.get()) {
1210 theError = "Error: This validator can only work with selection list in \"%1\" feature.";
1211 theError.arg(FeaturesPlugin_Union::ID());
1215 for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {
1216 bool isSameFound = false;
1217 AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
1218 ResultPtr aContext = anAttrSelectionInList->context();
1219 if (!aContext.get()) {
1220 theError = "Error: selection is invalid.";
1224 ResultConstructionPtr aConstruction =
1225 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1226 if(aConstruction.get()) {
1227 theError = "Error: Result construction not allowed for selection.";
1231 GeomShapePtr aShape = anAttrSelectionInList->value();
1232 GeomShapePtr aContextShape = aContext->shape();
1233 if (aShape.get() && aContextShape.get() && !aContextShape->isEqual(aShape)) {
1234 theError = "Error: Local selection not allowed.";
1238 ResultBodyPtr aResult =
1239 std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1240 if(!aResult.get()) {
1244 if(aResult->numberOfSubs() > 0) {
1245 theError = "Error: Whole compsolids not allowed for selection.";
1254 //==================================================================================================
1255 bool FeaturesPlugin_ValidatorUnionArguments::isValid(
1256 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1257 const std::list<std::string>& theArguments,
1258 Events_InfoMessage& theError) const
1261 // Check feature kind.
1262 if(theFeature->getKind() != FeaturesPlugin_Union::ID()) {
1263 theError = "Error: This validator supports only \"%1\" feature.";
1264 theError.arg(FeaturesPlugin_Union::ID());
1268 // Get base objects attribute list.
1269 AttributeSelectionListPtr aBaseObejctsAttrList =
1270 theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1271 if(!aBaseObejctsAttrList.get()) {
1272 theError = "Error: Could not get \"%1\" attribute.";
1273 theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1279 GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::COMPSOLID;
1280 ListOfShape aBaseShapesList;
1281 for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {
1282 AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);
1283 GeomShapePtr aShape = anAttrSelectionInList->value();
1284 if (!aShape.get()) {
1287 aBaseShapesList.push_back(aShape);
1288 aType = aShape->shapeType() == GeomAPI_Shape::FACE ? GeomAPI_Shape::SHELL :
1289 GeomAPI_Shape::COMPSOLID;
1292 // Make compound and find connected.
1293 GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);
1294 ListOfShape aResults;
1295 GeomAlgoAPI_ShapeTools::combineShapes(aCompound, aType, aResults);
1297 if(aResults.size() > 1 || (aResults.size() == 1 && aResults.front()->shapeType() > aType)) {
1298 theError = "Error: Not all shapes have shared topology.";
1305 bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute,
1306 const std::list<std::string>& theArguments,
1307 Events_InfoMessage& theError) const
1309 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
1311 theError = "Error: The attribute with the %1 type is not processed";
1312 theError.arg(theAttribute->attributeType());
1317 AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeReference>
1319 ObjectPtr aRefObject = aRefAttribute->value();
1320 if (!aRefObject.get()) {
1321 theError = "Error: Empty feature.";
1325 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aRefObject);
1326 if (!aRefFeature.get()) {
1327 theError = "Error: Empty feature.";
1330 std::list<std::shared_ptr<ModelAPI_Result> > aResults;
1331 ModelAPI_Tools::getConcealedResults(aRefFeature, aResults);
1333 size_t aConcealedResults = aResults.size();
1334 if (!aConcealedResults && !theArguments.empty()) {
1335 // find if these results are touched by the feature in another attribute
1336 std::list<std::string>::const_iterator anIt = theArguments.begin();
1337 std::string aRecoveredList = *anIt;
1338 if (!aRecoveredList.empty()) {
1339 std::shared_ptr<ModelAPI_AttributeRefList> aParameterList =
1340 theAttribute->owner()->data()->reflist(aRecoveredList);
1341 if (aParameterList.get())
1342 aConcealedResults = aParameterList->size();
1346 if (aConcealedResults == 0)
1347 theError = "Error: No concealed results.";
1349 return theError.empty();
1352 bool FeaturesPlugin_ValidatorCircular::isValid(const AttributePtr& theAttribute,
1353 const std::list<std::string>& theArguments,
1354 Events_InfoMessage& theError) const
1356 static std::list<std::string> aEdgeArg(1, "circle");
1357 static std::list<std::string> aFaceArg(1, "cylinder");
1359 Events_InfoMessage aError;
1360 bool isValid = GeomValidators_ShapeType().isValid(theAttribute, aEdgeArg, aError);
1362 isValid = GeomValidators_Face().isValid(theAttribute, aFaceArg, aError);
1364 theError = "The shape neither circle nor cylinder";
1369 //=================================================================================================
1370 bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
1371 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1372 const std::list<std::string>& theArguments,
1373 Events_InfoMessage& theError) const
1376 if (theArguments.size() != 2)
1378 theError = "Wrong number of arguments (expected 2).";
1383 int anObjectsToolsNb[2] = { 0, 0 };
1385 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1387 bool isAllInSameCompSolid = true;
1388 ResultBodyPtr aCompSolid;
1390 for (int* anArgNbIt = anObjectsToolsNb; anIt != aLast; ++anIt, ++anArgNbIt) {
1391 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1394 *anArgNbIt = anAttrSelList->size();
1395 if (isAllInSameCompSolid) {
1396 for (int anIndex = 0; anIndex < *anArgNbIt; ++anIndex)
1398 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1399 ResultPtr aContext = anAttr->context();
1400 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1401 if (aResCompSolidPtr.get())
1403 if (aCompSolid.get())
1405 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1409 aCompSolid = aResCompSolidPtr;
1414 isAllInSameCompSolid = false;
1422 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
1423 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theFeature);
1424 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
1426 if (anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE)
1429 if (anObjectsToolsNb[0] + anObjectsToolsNb[1] < 2)
1431 theError = "Not enough arguments for Fuse operation.";
1434 else if (isAllInSameCompSolid)
1436 theError = "Operations only between sub-shapes of the same shape not allowed.";
1442 if (anObjectsToolsNb[0] < 1) // check number of objects
1444 theError = "Objects not selected.";
1447 if (anObjectsToolsNb[1] < 1) // check number of tools
1449 theError = "Tools not selected.";
1452 if (isAllInSameCompSolid)
1454 theError = "Operations only between sub-shapes of the same shape not allowed.";
1462 //=================================================================================================
1464 bool FeaturesPlugin_ValidatorBooleanArguments::isNotObligatory(std::string theFeature,
1465 std::string theAttribute)
1467 if (theAttribute == "main_objects" || theAttribute == "tool_objects")
1476 //==================================================================================================
1477 bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
1478 const AttributePtr& theAttribute,
1479 const std::list<std::string>& theArguments,
1480 Events_InfoMessage& theError) const
1482 std::shared_ptr<FeaturesPlugin_BooleanSmash> aFeature =
1483 std::dynamic_pointer_cast<FeaturesPlugin_BooleanSmash>(theAttribute->owner());
1485 AttributeSelectionListPtr anAttrSelectionList =
1486 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1487 if (!aFeature.get() || !anAttrSelectionList.get()) {
1490 "Error: Validator used in wrong feature or attribute";
1495 AttributeSelectionListPtr anOtherAttrSelectionList;
1496 if (theAttribute->id() == FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()) {
1497 anOtherAttrSelectionList =
1498 aFeature->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID());
1500 anOtherAttrSelectionList =
1501 aFeature->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID());
1504 GeomAPI_Shape::ShapeType aSelectedShapesType = GeomAPI_Shape::SHAPE;
1505 GeomAPI_DataMapOfShapeShape aSelectedCompSolidsInOtherList;
1506 GeomPlanePtr aFacesPln;
1508 for (int anIndex = 0; anIndex < anOtherAttrSelectionList->size(); ++anIndex) {
1509 AttributeSelectionPtr anAttrSelection = anOtherAttrSelectionList->value(anIndex);
1511 if (anAttrSelection->contextFeature().get()) {
1512 theError = "Error: Features not allowed for selection.";
1516 ResultPtr aContext = anAttrSelection->context();
1517 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1518 if (!aShape.get()) {
1519 if (!aContext.get()) {
1520 theError = "Error: Empty selection.";
1523 aShape = aContext->shape();
1526 if (aShape->isSolid() || aShape->isCompSolid()) {
1527 aSelectedShapesType = GeomAPI_Shape::SOLID;
1528 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1529 if (aResCompSolidPtr.get()) {
1530 GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
1531 aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape);
1534 aSelectedShapesType = GeomAPI_Shape::FACE;
1535 GeomAPI_Face aFace(aShape);
1536 aFacesPln = aFace.getPlane();
1541 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1542 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1543 if (!anAttrSelection.get()) {
1544 theError = "Error: Empty attribute selection.";
1548 if (anAttrSelection->contextFeature().get()) {
1549 theError = "Error: Features not allowed for selection.";
1553 ResultPtr aContext = anAttrSelection->context();
1554 if(!aContext.get()) {
1555 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1556 if (!aContFeat.get() || !aContFeat->results().size() ||
1557 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1558 theError = "Error: Empty selection context.";
1562 ResultConstructionPtr aResultConstruction =
1563 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1564 if (aResultConstruction.get()) {
1565 theError = "Error: Result construction not allowed for selection.";
1568 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1569 GeomShapePtr aContextShape = aContext->shape();
1570 if (!aShape.get()) {
1571 aShape = aContextShape;
1573 if (!aShape.get()) {
1574 theError = "Error: Empty shape.";
1577 if (!aShape->isEqual(aContextShape)) {
1578 theError = "Error: Local selection not allowed.";
1582 if (aSelectedShapesType == GeomAPI_Shape::SHAPE) {
1583 // Other list is empty.
1584 if (aShape->isSolid() || aShape->isCompSolid()) {
1585 aSelectedShapesType = GeomAPI_Shape::SOLID;
1587 aSelectedShapesType = GeomAPI_Shape::FACE;
1588 GeomAPI_Face aFace(aShape);
1589 aFacesPln = aFace.getPlane();
1591 if (!aFacesPln.get()) {
1592 theError = "Error: Only planar faces allowed.";
1598 } else if (aSelectedShapesType == GeomAPI_Shape::SOLID) {
1599 if (!aShape->isSolid() && !aShape->isCompSolid()) {
1600 theError = "Error: Selected shapes should have the same type.";
1604 GeomAPI_Face aFace(aShape);
1605 GeomPlanePtr aPln = aFace.getPlane();
1608 theError = "Error: Only planar faces allowed.";
1612 if (!aFacesPln->isCoincident(aPln)) {
1613 theError = "Error: Only coincident faces allowed.";
1622 //==================================================================================================
1624 bool FeaturesPlugin_IntersectionSelection::isValid(const AttributePtr& theAttribute,
1625 const std::list<std::string>& theArguments,
1626 Events_InfoMessage& theError) const
1628 if (!theAttribute.get()) {
1629 theError = "Error: empty selection.";
1632 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1633 AttributeSelectionListPtr anAttrSelectionList =
1634 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1635 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1636 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1637 if (!anAttrSelection.get()) {
1638 theError = "Error: empty attribute selection.";
1641 ResultPtr aContext = anAttrSelection->context();
1642 if(!aContext.get()) {
1643 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1644 if (!aContFeat.get() || !aContFeat->results().size() ||
1645 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1646 theError = "Error: Empty selection context.";
1650 FeaturePtr aFeature = anAttrSelection->contextFeature().get() ?
1651 anAttrSelection->contextFeature() : ModelAPI_Feature::feature(aContext);
1652 if (!aFeature.get()) {
1653 theError = "Error: empty feature.";
1656 std::string aFeatureKind = aFeature->getKind();
1657 if (aFeatureKind == "Sketch" ||
1658 aFeatureKind == "Plane" ||
1659 aFeatureKind == "Axis") {
1660 theError = "Error: %1 shape is not allowed for selection.";
1661 theError.arg(aFeatureKind);
1664 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1665 if (!aShape.get()) {
1666 GeomShapePtr aContextShape = aContext->shape();
1667 aShape = aContextShape;
1669 if (!aShape.get()) {
1670 theError = "Error: empty shape.";
1673 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1674 theError = "Error: Local selection not allowed.";
1678 int aShapeType = aShape->shapeType();
1679 // Allow to select edges, faces and solids.
1680 if (aShapeType != GeomAPI_Shape::EDGE &&
1681 aShapeType != GeomAPI_Shape::FACE &&
1682 aShapeType != GeomAPI_Shape::SOLID &&
1683 aShapeType != GeomAPI_Shape::COMPSOLID &&
1684 aShapeType != GeomAPI_Shape::COMPOUND) {
1685 theError = "Error: selected shape has the wrong type.";
1694 //==================================================================================================
1696 bool FeaturesPlugin_ValidatorBooleanFuseSelection::isValid(
1697 const AttributePtr& theAttribute,
1698 const std::list<std::string>& theArguments,
1699 Events_InfoMessage& theError) const
1701 AttributeSelectionListPtr anAttrSelectionList =
1702 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1703 if (!anAttrSelectionList.get()) {
1705 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1709 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1710 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1711 if (!anAttrSelection.get()) {
1712 theError = "Error: Empty attribute selection.";
1715 ResultPtr aContext = anAttrSelection->context();
1716 if(!aContext.get()) {
1717 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1718 if (!aContFeat.get() || !aContFeat->results().size() ||
1719 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1720 theError = "Error: Empty selection context.";
1724 ResultConstructionPtr aResultConstruction =
1725 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1726 if (aResultConstruction.get()) {
1727 theError = "Error: Result construction not allowed for selection.";
1730 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1731 if (!aShape.get()) {
1732 GeomShapePtr aContextShape = aContext->shape();
1733 aShape = aContextShape;
1735 if (!aShape.get()) {
1736 theError = "Error: Empty shape.";
1739 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1740 theError = "Error: Local selection not allowed.";
1749 //=================================================================================================
1750 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
1751 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1752 const std::list<std::string>& theArguments,
1753 Events_InfoMessage& theError) const
1756 if (theArguments.size() != 2) {
1757 theError = "Wrong number of arguments (expected 2).";
1762 std::shared_ptr<FeaturesPlugin_BooleanFuse> aFeature =
1763 std::dynamic_pointer_cast<FeaturesPlugin_BooleanFuse>(theFeature);
1765 int anObjectsNb = 0, aToolsNb = 0;
1767 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1769 bool isAllInSameCompSolid = true;
1770 ResultBodyPtr aCompSolid;
1772 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1773 if (anAttrSelList) {
1774 anObjectsNb = anAttrSelList->size();
1775 for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex) {
1776 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1777 ResultPtr aContext = anAttr->context();
1778 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1779 if (aResCompSolidPtr.get()) {
1780 if (aCompSolid.get()) {
1781 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1783 aCompSolid = aResCompSolidPtr;
1786 isAllInSameCompSolid = false;
1793 if (aFeature->string(FeaturesPlugin_BooleanFuse::CREATION_METHOD())->value()
1794 == FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED()) {
1795 anAttrSelList = theFeature->selectionList(*anIt);
1796 if (anAttrSelList) {
1797 aToolsNb = anAttrSelList->size();
1798 if (isAllInSameCompSolid) {
1799 for (int anIndex = 0; anIndex < aToolsNb; ++anIndex) {
1800 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1801 ResultPtr aContext = anAttr->context();
1802 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1803 if (aResCompSolidPtr.get()) {
1804 if (aCompSolid.get()) {
1805 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1807 aCompSolid = aResCompSolidPtr;
1810 isAllInSameCompSolid = false;
1820 if (anObjectsNb + aToolsNb < 2) {
1821 theError = "Not enough arguments for Fuse operation.";
1828 //=================================================================================================
1830 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isNotObligatory(
1831 std::string theFeature,
1832 std::string theAttribute)
1834 if (theAttribute == "main_objects" || theAttribute == "tool_objects") {
1842 //==================================================================================================
1844 bool FeaturesPlugin_ValidatorBooleanCommonSelection::isValid(
1845 const AttributePtr& theAttribute,
1846 const std::list<std::string>& theArguments,
1847 Events_InfoMessage& theError) const
1849 AttributeSelectionListPtr anAttrSelectionList =
1850 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1851 if (!anAttrSelectionList.get()) {
1853 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1857 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1858 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1859 if (!anAttrSelection.get()) {
1860 theError = "Error: Empty attribute selection.";
1863 ResultPtr aContext = anAttrSelection->context();
1864 if (!aContext.get() && !anAttrSelection->contextFeature().get()) {
1865 theError = "Error: Empty selection context.";
1868 ResultConstructionPtr aResultConstruction =
1869 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1870 if (aResultConstruction.get()) {
1871 if (theAttribute->id() != FeaturesPlugin_BooleanCommon::TOOL_LIST_ID()) {
1872 theError = "Error: Result construction not allowed for selection.";
1876 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1877 GeomShapePtr aContextShape;
1878 if (aContext.get()) {
1879 aContextShape = aContext->shape();
1881 if (!aShape.get()) {
1882 aShape = aContextShape;
1884 if (!aShape.get()) {
1885 theError = "Error: Empty shape.";
1888 if (aContextShape.get() && !aShape->isEqual(aContextShape)) {
1889 theError = "Error: Local selection not allowed.";
1893 if (aResultConstruction.get() && aShape->shapeType() != GeomAPI_Shape::FACE) {
1894 theError = "Error: Result construction should be plane.";
1903 //=================================================================================================
1904 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isValid(
1905 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1906 const std::list<std::string>& theArguments,
1907 Events_InfoMessage& theError) const
1909 if (theArguments.size() != 2) {
1911 theError = "Wrong number of arguments (expected 2).";
1916 std::shared_ptr<FeaturesPlugin_BooleanCommon> aFeature =
1917 std::dynamic_pointer_cast<FeaturesPlugin_BooleanCommon>(theFeature);
1919 int anObjectsNb = 0, aToolsNb = 0;
1921 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1923 bool isAllInSameCompSolid = true;
1924 ResultBodyPtr aCompSolid;
1926 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1927 if (anAttrSelList) {
1928 anObjectsNb = anAttrSelList->size();
1931 bool isSimpleMode = aFeature->string(FeaturesPlugin_BooleanCommon::CREATION_METHOD())->value()
1932 == FeaturesPlugin_BooleanCommon::CREATION_METHOD_SIMPLE();
1934 if (!isSimpleMode) {
1935 anAttrSelList = theFeature->selectionList(*anIt);
1936 if (anAttrSelList) {
1937 aToolsNb = anAttrSelList->size();
1941 if ((isSimpleMode && anObjectsNb < 2)
1942 || (!isSimpleMode && (anObjectsNb == 0 || aToolsNb == 0))) {
1943 theError = "Not enough arguments for Fuse operation.";
1949 //=================================================================================================
1951 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isNotObligatory(
1952 std::string theFeature,
1953 std::string theAttribute)
1959 //==================================================================================================
1960 bool FeaturesPlugin_ValidatorDefeaturingSelection::isValid(
1961 const AttributePtr& theAttribute,
1962 const std::list<std::string>& theArguments,
1963 Events_InfoMessage& theError) const
1965 AttributeSelectionListPtr anAttrSelectionList =
1966 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1967 if (!anAttrSelectionList.get()) {
1969 theError = "Error: This validator can only work with selection list attributes.";
1974 // Check selected entities are sub-shapes of solid or compsolid
1975 GeomShapePtr aBaseSolid;
1976 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1977 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1978 if (!anAttrSelection.get()) {
1979 theError = "Error: Empty attribute selection.";
1982 ResultPtr aContext = anAttrSelection->context();
1983 if (!aContext.get()) {
1984 theError = "Error: Empty selection context.";
1988 GeomShapePtr aContextShape = aContext->shape();
1989 if (aContextShape->shapeType() != GeomAPI_Shape::SOLID) {
1990 theError = "Error: Not all selected shapes are sub-shapes of solids.";