1 // Copyright (C) 2014-2020 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "FeaturesPlugin_Validators.h"
22 #include "FeaturesPlugin_Boolean.h"
23 #include "FeaturesPlugin_BooleanFuse.h"
24 #include "FeaturesPlugin_BooleanCommon.h"
25 #include "FeaturesPlugin_BooleanSmash.h"
26 #include "FeaturesPlugin_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
67 #pragma warning(disable: 4100)
70 //==================================================================================================
71 bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
72 const std::list<std::string>& theArguments,
73 Events_InfoMessage& theError) const
75 AttributeSelectionPtr aPathAttrSelection =
76 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
77 if(!aPathAttrSelection.get()) {
79 theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
84 GeomShapePtr aPathShape = aPathAttrSelection->value();
85 ResultPtr aContext = aPathAttrSelection->context();
87 theError = "Error: Empty context.";
90 GeomShapePtr aContextShape = aContext->shape();
91 if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE &&
92 !aPathShape->isEqual(aContextShape)) {
93 theError = "Error: Local selection of wires not allowed.";
100 //==================================================================================================
101 bool FeaturesPlugin_ValidatorPipeLocations::isValid(const AttributePtr& theAttribute,
102 const std::list<std::string>& theArguments,
103 Events_InfoMessage& theError) const
105 AttributeSelectionListPtr anAttrSelectionList =
106 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
107 if(!anAttrSelectionList.get()) {
110 "Error: This validator can only work with selection list attributes in \"Pipe\" feature.";
114 std::shared_ptr<FeaturesPlugin_Pipe> aFeature =
115 std::dynamic_pointer_cast<FeaturesPlugin_Pipe>(theAttribute->owner());
117 AttributeSelectionPtr aPathSelection = aFeature->selection(FeaturesPlugin_Pipe::PATH_OBJECT_ID());
118 if (!aPathSelection.get()) {
120 theError = "Error: Path not selected.";
125 GeomShapePtr aPathShape = aPathSelection->value();
126 if (!aPathShape.get()) {
127 ResultPtr aContext = aPathSelection->context();
128 if (!aContext.get()) {
129 FeaturePtr aContFeat = aPathSelection->contextFeature();
130 if (!aContFeat.get() || !aContFeat->results().size()) {
131 theError = "Error: Empty selection context.";
135 aPathShape = aContext->shape();
138 if (!aPathShape.get()) {
139 theError = "Error: Empty path shape.";
143 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
144 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
145 if (!anAttrSelection.get()) {
146 theError = "Error: Empty attribute selection.";
149 ResultPtr aContext = anAttrSelection->context();
150 if (!aContext.get()) {
151 FeaturePtr aContFeat = anAttrSelection->contextFeature();
152 if (!aContFeat.get() || !aContFeat->results().size()) {
153 theError = "Error: Empty selection context.";
157 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
158 if (!aShape.get() && aContext.get()) {
159 GeomShapePtr aContextShape = aContext->shape();
160 aShape = aContextShape;
163 theError = "Error: Empty shape.";
167 if (!aPathShape->isSubShape(aShape)) {
168 theError = "Error: Location should be a vertex subshape from path shape.";
176 //==================================================================================================
178 bool FeaturesPlugin_ValidatorPipeLocationsNumber::isValid(
179 const std::shared_ptr<ModelAPI_Feature>& theFeature,
180 const std::list<std::string>& theArguments,
181 Events_InfoMessage& theError) const
183 static const std::string aCreationMethodID = "creation_method";
184 static const std::string aBaseObjectsID = "base_objects";
185 static const std::string aLocationsID = "locations_objects";
187 if(theFeature->getKind() != "Pipe") {
188 theError = "Error: Feature \"%1\" does not supported by this validator.";
189 theError.arg(theFeature->getKind());
193 AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
194 if(!aCreationMethodAttr.get()) {
195 theError = "Error: Could not get \"%1\" attribute.";
196 theError.arg(aCreationMethodID);
200 if(aCreationMethodAttr->value() != "locations") {
204 AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
205 if(!aBaseObjectsSelectionList.get()) {
206 theError = "Error: Could not get \"%1\" attribute.";
207 theError.arg(aBaseObjectsID);
211 AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
212 if(!aLocationsSelectionList.get()) {
213 theError = "Error: Could not get \"%1\" attribute.";
214 theError.arg(aBaseObjectsID);
218 if(aLocationsSelectionList->size() > 0 &&
219 aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
220 theError = "Error: Number of locations should be the same as base objects.";
228 //==================================================================================================
229 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
230 const std::list<std::string>& theArguments,
231 Events_InfoMessage& theError) const
234 if(theArguments.empty()) {
235 theError = "Error: Validator parameters is empty.";
240 // Checking attribute.
241 if(!isValidAttribute(theAttribute, theArguments, theError)) {
242 if(theError.empty()) {
243 theError = "Error: Attribute contains unacceptable shape.";
248 GeomAPI_DataMapOfShapeShape aSelectedWiresFromObjects;
249 std::string anAttributeType = theAttribute->attributeType();
250 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
251 AttributeSelectionListPtr aListAttr =
252 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
253 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
254 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
255 ResultPtr aContext = aSelectionAttr->context();
256 if(!aContext.get() && !aSelectionAttr->contextFeature().get()) {
257 theError = "Error: Empty context.";
261 ResultConstructionPtr aResultConstruction =
262 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
263 if(!aResultConstruction.get()) {
264 // It is not a result construction.
265 // If shape is compound check that it contains only faces, edges or vertices.
266 GeomShapePtr aShape = aSelectionAttr->value();
268 if (aContext.get()) {
269 aShape = aContext->shape();
271 theError = "Error: Empty context.";
276 if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
277 for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
278 GeomShapePtr aSubShape = anIt.current();
279 if (aSubShape->shapeType() > GeomAPI_Shape::VERTEX ||
280 aSubShape->shapeType() < GeomAPI_Shape::FACE) {
281 theError = "Error: Compound should contain only faces, edges or vertices.";
290 GeomShapePtr aShape = aSelectionAttr->value();
291 GeomShapePtr aContextShape = aResultConstruction->shape();
293 // Whole sketch selected.
296 // Object from sketch selected.
297 for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
298 GeomShapePtr aWire = anExp.current();
299 if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
300 theError = "Error: Wire with wrong orientation selected.";
304 if(aSelectedWiresFromObjects.isBound(aWire)) {
306 "Error: Objects with this wire already selected. Don't allow to select this object.";
310 aSelectedWiresFromObjects.bind(aWire, aWire);
319 //==================================================================================================
320 bool FeaturesPlugin_ValidatorBaseForGenerationSketchOrSketchObjects::isValid(
321 const std::shared_ptr<ModelAPI_Feature>& theFeature,
322 const std::list<std::string>& theArguments,
323 Events_InfoMessage& theError) const
325 const std::string aBaseObjectsID = theArguments.front();
327 AttributeSelectionListPtr aListAttr = theFeature->selectionList(aBaseObjectsID);
328 if(!aListAttr.get()) {
330 theError = "Error: Could not get \"%1\" attribute.";
331 theError.arg(aBaseObjectsID);
336 std::set<ResultConstructionPtr> aSelectedSketches;
337 std::set<ResultConstructionPtr> aSelectedSketchesFromObjects;
339 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
340 AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
341 ResultPtr aContext = aSelectionAttr->context();
342 if(!aContext.get()) {
343 FeaturePtr aFeature = aSelectionAttr->contextFeature();
344 if (!aFeature.get() || aFeature->results().empty()) {
345 theError = "Error: Empty context.";
348 aContext = aFeature->firstResult();
352 ResultConstructionPtr aResultConstruction =
353 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
354 if(!aResultConstruction.get()) {
355 // It is not a result construction.
359 GeomShapePtr aShape = aSelectionAttr->value();
360 GeomShapePtr aContextShape = aResultConstruction->shape();
362 // Whole sketch selected.
363 aSelectedSketches.insert(aResultConstruction);
365 // Object from sketch selected.
366 aSelectedSketchesFromObjects.insert(aResultConstruction);
371 for(std::set<ResultConstructionPtr>::const_iterator anIt = aSelectedSketches.cbegin();
372 anIt != aSelectedSketches.cend();
374 ResultConstructionPtr aResultConstruction = *anIt;
375 if(aSelectedSketchesFromObjects.find(aResultConstruction) !=
376 aSelectedSketchesFromObjects.cend()) {
377 theError = "Sketch and objects from it can not be selected at the same time.";
385 //==================================================================================================
386 bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute,
387 const std::list<std::string>& theArguments,
388 Events_InfoMessage& theError) const
390 if(!theAttribute.get()) {
392 theError = "Error: Empty attribute.";
397 std::string anAttributeType = theAttribute->attributeType();
398 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
399 AttributeSelectionListPtr aListAttr =
400 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
401 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
402 // If at least one attribute is invalid, the result is false.
403 if(!isValidAttribute(aListAttr->value(anIndex), theArguments, theError)) {
407 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
409 AttributeSelectionPtr anAttr =
410 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
411 ResultPtr aContext = anAttr->context();
412 if(!aContext.get() && !anAttr->contextFeature().get()) {
413 theError = "Error: Attribute have empty context.";
417 GeomShapePtr aShape = anAttr->value();
418 GeomShapePtr aContextShape;
419 if(!aShape.get() && aContext.get()) {
420 aContextShape = aContext->shape();
421 aShape = aContextShape;
424 theError = "Error: Empty shape selected";
428 ResultConstructionPtr aConstruction;
429 if (!aContext.get() && anAttr->contextFeature()->results().size() == 1) {
430 aContext = anAttr->contextFeature()->firstResult();
433 aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
434 if(aConstruction.get()) {
435 // Construction selected. Check that it is not infinite.
436 if(aConstruction->isInfinite()) {
437 theError = "Error: Infinite constructions is not allowed as base.";
441 aContextShape = aContext->shape();
442 if(aShape->isEqual(aContextShape)) {
443 // Whole construction selected. Check that it have faces.
444 if(aConstruction->facesNum() > 0) {
448 // Shape on construction selected. Check that it is a face or wire.
449 if(aShape->shapeType() == GeomAPI_Shape::WIRE ||
450 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 anArgsIt = theArguments.begin();
556 AttributePtr aCheckAttribute = theFeature->attribute(*anArgsIt);
559 GeomShapePtr aDirShape;
560 AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
562 aDirShape = aSelAttr->value();
563 if(!aDirShape.get()) {
564 ResultPtr aContext = aSelAttr->context();
565 if(!aContext.get()) {
566 FeaturePtr aFeature = aSelAttr->contextFeature();
567 if (aFeature.get() && !aFeature->results().empty()) {
568 aContext = aFeature->firstResult();
573 aDirShape = aContext->shape();
576 if (aDirShape.get() && aDirShape->isCompound()) {
577 GeomAPI_ShapeIterator anIt(aDirShape);
578 aDirShape = anIt.current();
583 if(!aDirShape.get() || aDirShape->isNull() ||
584 aDirShape->shapeType() != GeomAPI_Shape::EDGE) {
585 // Check that dir can be empty.
586 if(!isShapesCanBeEmpty(aCheckAttribute, theError)) {
587 theError = "Error: Base objects list contains vertex or edge, so attribute \"%1\" "
588 "can not be used with default value. Select direction for extrusion.";
589 theError.arg(*anArgsIt);
596 std::shared_ptr<GeomAPI_Edge> aDirEdge(new GeomAPI_Edge(aDirShape));
598 // If faces selected check that direction not parallel with them.
599 AttributeSelectionListPtr aListAttr =
600 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aCheckAttribute);
601 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
602 AttributeSelectionPtr anAttr = aListAttr->value(anIndex);
603 GeomShapePtr aShapeInList = anAttr->value();
604 if(!aShapeInList.get()) {
605 aShapeInList = anAttr->context()->shape();
607 bool isParallel = true;
608 if(aShapeInList->shapeType() == GeomAPI_Shape::FACE ||
609 aShapeInList->shapeType() == GeomAPI_Shape::SHELL) {
610 for(GeomAPI_ShapeExplorer
611 anExp(aShapeInList, GeomAPI_Shape::FACE); anExp.more(); anExp.next()) {
612 std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(anExp.current()));
613 isParallel = GeomAlgoAPI_ShapeTools::isParallel(aDirEdge, aFace);
618 } else if(aShapeInList->shapeType() == GeomAPI_Shape::COMPOUND) {
619 std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges =
620 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShapeInList);
621 if(aPlanarEdges.get()) {
622 std::shared_ptr<GeomAPI_Dir> aSketchDir = aPlanarEdges->norm();
623 if(aDirEdge->isLine()) {
624 std::shared_ptr<GeomAPI_Dir> aDir = aDirEdge->line()->direction();
625 isParallel = fabs(aSketchDir->angle(aDir) - M_PI / 2.0) < 10e-7;
637 "Error: Direction is parallel to one of the selected face or face on selected shell.";
645 //==================================================================================================
646 bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr& theAttribute,
647 Events_InfoMessage& theError) const
650 if(!theAttribute.get()) {
655 std::string anAttributeType = theAttribute->attributeType();
656 if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
657 AttributeSelectionListPtr aListAttr =
658 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
659 for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
660 // If at least one attribute is invalid, the result is false.
661 if(!isShapesCanBeEmpty(aListAttr->value(anIndex), theError)) {
665 } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
667 AttributeSelectionPtr anAttr =
668 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
669 ResultPtr aContext = anAttr->context();
670 if(!aContext.get() && !anAttr->contextFeature().get()) {
674 GeomShapePtr aShape = anAttr->value();
675 if(!aShape.get() && aContext.get()) {
676 GeomShapePtr aContextShape = aContext->shape();
677 aShape = aContextShape;
683 if(aShape->shapeType() == GeomAPI_Shape::VERTEX ||
684 aShape->shapeType() == GeomAPI_Shape::EDGE ||
685 !aShape->isPlanar()) {
695 //==================================================================================================
696 bool FeaturesPlugin_ValidatorExtrusionBoundaryFace::isValid(
697 const AttributePtr& theAttribute,
698 const std::list<std::string>& theArguments,
699 Events_InfoMessage& theError) const
701 FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
703 // Collect all necessary attributes and try to build prism
706 AttributeSelectionListPtr aBaseShapeAttr =
707 aFeature->selectionList(FeaturesPlugin_Extrusion::BASE_OBJECTS_ID());
708 ListOfShape aBaseShapeList;
710 if (!FeaturesPlugin_Tools::getShape(aBaseShapeAttr, true, aBaseShapeList, anError)) {
716 AttributeSelectionPtr aSelection =
717 aFeature->selection(FeaturesPlugin_Extrusion::DIRECTION_OBJECT_ID());
718 GeomShapePtr aShape = aSelection->value();
719 if (!aShape.get() && aSelection->context().get())
720 aShape = aSelection->context()->shape();
724 if (aShape->isEdge())
725 anEdge = aShape->edge();
726 else if (aShape->isCompound()) {
727 GeomAPI_ShapeIterator anIt(aShape);
728 anEdge = anIt.current()->edge();
732 std::shared_ptr<GeomAPI_Dir> aDir;
733 if (anEdge.get() && anEdge->isLine())
734 aDir = anEdge->line()->direction();
737 GeomShapePtr aFromShape, aToShape;
738 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
739 if (aSelection.get()) {
740 aToShape = aSelection->value();
741 if (!aToShape.get() && aSelection->context().get())
742 aToShape = aSelection->context()->shape();
743 if (aToShape.get() && aToShape->isCompound()) {
744 GeomAPI_ShapeIterator anIt(aToShape);
745 aToShape = anIt.current();
747 if (aToShape.get() && !aToShape->isFace()) {
748 theError = "\"To\" shape is not a face";
752 aSelection = aFeature->selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
753 if (aSelection.get()) {
754 aFromShape = aSelection->value();
755 if (!aFromShape.get() && aSelection->context().get())
756 aFromShape = aSelection->context()->shape();
757 if (aFromShape.get() && aFromShape->isCompound()) {
758 GeomAPI_ShapeIterator anIt(aFromShape);
759 aFromShape = anIt.current();
761 if (aFromShape.get() && !aFromShape->isFace()) {
762 theError = "\"From\" shape is not a face";
767 double aToSize = aFeature->real(FeaturesPlugin_Extrusion::TO_OFFSET_ID())->value();
768 double aFromSize = aFeature->real(FeaturesPlugin_Extrusion::FROM_OFFSET_ID())->value();
771 for (ListOfShape::iterator anIt = aBaseShapeList.begin(); anIt != aBaseShapeList.end(); anIt++) {
772 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIt;
774 std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo(
775 new GeomAlgoAPI_Prism(aBaseShape, aDir, aToShape, aToSize, aFromShape, aFromSize));
776 bool isFailed = GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPrismAlgo,
777 FeaturesPlugin_Extrusion::ID(),
788 //==================================================================================================
789 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
790 const std::list<std::string>& theArguments,
791 Events_InfoMessage& theError) const
793 AttributeSelectionListPtr anAttrSelectionList =
794 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
795 if(!anAttrSelectionList.get()) {
798 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
802 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
803 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theAttribute->owner());
804 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
806 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
807 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
808 if(!anAttrSelection.get()) {
809 theError = "Error: Empty attribute selection.";
812 ResultPtr aContext = anAttrSelection->context();
813 if(!aContext.get()) {
814 FeaturePtr aContFeat = anAttrSelection->contextFeature();
815 if (!aContFeat.get() || !aContFeat->results().size()) {
816 theError = "Error: Empty selection context.";
820 ResultConstructionPtr aResultConstruction =
821 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
822 if(aResultConstruction.get()) {
823 if (anOperationType != FeaturesPlugin_Boolean::BOOL_FILL
824 || theAttribute->id() != FeaturesPlugin_Boolean::TOOL_LIST_ID()) {
825 theError = "Error: Result construction not allowed for selection.";
829 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
830 if(!aShape.get() && aContext.get()) {
831 GeomShapePtr aContextShape = aContext->shape();
832 aShape = aContextShape;
835 theError = "Error: Empty shape.";
838 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
839 theError = "Error: Local selection not allowed.";
843 GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType();
844 std::set<GeomAPI_Shape::ShapeType> anAllowedTypes;
845 if(anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE) {
846 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
847 anAllowedTypes.insert(GeomAPI_Shape::FACE);
848 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
849 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
850 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
851 } else if (anOperationType == FeaturesPlugin_Boolean::BOOL_FILL
852 || anOperationType == FeaturesPlugin_Boolean::BOOL_CUT)
854 anAllowedTypes.insert(GeomAPI_Shape::VERTEX);
855 anAllowedTypes.insert(GeomAPI_Shape::EDGE);
856 anAllowedTypes.insert(GeomAPI_Shape::WIRE);
857 anAllowedTypes.insert(GeomAPI_Shape::FACE);
858 anAllowedTypes.insert(GeomAPI_Shape::SHELL);
859 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
860 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
861 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
863 anAllowedTypes.insert(GeomAPI_Shape::SOLID);
864 anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
865 anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
868 if(anAllowedTypes.find(aShapeType) == anAllowedTypes.end()
869 || (aResultConstruction.get() && aShapeType != GeomAPI_Shape::FACE)) {
870 theError = "Error: Selected shape has the wrong type.";
879 //==================================================================================================
880 bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute,
881 const std::list<std::string>& theArguments,
882 Events_InfoMessage& theError) const
884 AttributeSelectionListPtr anAttrSelectionList =
885 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
886 if(!anAttrSelectionList.get()) {
889 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
894 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
895 // Check all selected entities are sub-shapes of single solid
896 GeomShapePtr aBaseSolid;
897 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
898 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
899 if(!anAttrSelection.get()) {
900 theError = "Error: Empty attribute selection.";
903 ResultPtr aContext = anAttrSelection->context();
904 if(!aContext.get()) {
905 FeaturePtr aContFeat = anAttrSelection->contextFeature();
906 if (!aContFeat.get() || !aContFeat->results().size() ||
907 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
908 theError = "Error: Empty selection context.";
911 if (aContFeat->results().size() == 1)
912 aContext = aContFeat->firstResult();
914 theError = "Error: Too many shapes selected.";
919 ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext, true);
920 GeomShapePtr anOwner = aContext->shape();
921 GeomShapePtr aTopLevelOwner = aContextOwner.get() ? aContextOwner->shape() : anOwner;
924 theError = "Error: wrong feature is selected.";
928 if (anOwner->shapeType() != GeomAPI_Shape::SOLID &&
929 anOwner->shapeType() != GeomAPI_Shape::COMPSOLID) {
930 theError = "Error: Not all selected shapes are sub-shapes of solids.";
935 aBaseSolid = aTopLevelOwner;
936 else if (!aBaseSolid->isEqual(aTopLevelOwner)) {
937 theError = "Error: Sub-shapes of different solids have been selected.";
946 //==================================================================================================
947 bool FeaturesPlugin_ValidatorFillet1DSelection::isValid(const AttributePtr& theAttribute,
948 const std::list<std::string>& theArguments,
949 Events_InfoMessage& theError) const
951 AttributeSelectionListPtr anAttrSelectionList =
952 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
953 if (!anAttrSelectionList.get()) {
956 "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
961 // check each selected vertex is a sharp corner between adjacent edges,
962 // and these edges are in the same plane
963 std::map<GeomShapePtr, MapShapeToShapes> aWireSubshapes;
964 int aNbSel = anAttrSelectionList->size();
965 for (int ind = 0; ind < aNbSel; ++ind) {
966 AttributeSelectionPtr aCurSel = anAttrSelectionList->value(ind);
967 GeomShapePtr aContext = aCurSel->context()->shape();
968 GeomShapePtr aVertex = aCurSel->value();
969 // check wire already processed, if not, store all vertices and edges, sharing them
970 std::map<GeomShapePtr, MapShapeToShapes>::iterator aProcessed = aWireSubshapes.find(aContext);
971 if (aProcessed == aWireSubshapes.end()) {
972 if (aContext->shapeType() != GeomAPI_Shape::WIRE) {
973 theError = "Selected vertex is not a wire corner";
976 if (aVertex->shapeType() != GeomAPI_Shape::VERTEX) {
977 theError = "Selected shape is not a vertex";
981 GeomAlgoAPI_MapShapesAndAncestors aMapVE(aContext, GeomAPI_Shape::VERTEX,
982 GeomAPI_Shape::EDGE);
983 aWireSubshapes[aContext] = aMapVE.map();
984 aProcessed = aWireSubshapes.find(aContext);
988 MapShapeToShapes::iterator aFound = aProcessed->second.find(aVertex);
989 if (aFound == aProcessed->second.end()) {
990 theError = "Selected vertex does not exist in the wire";
993 else if (aFound->second.size() != 2) {
994 theError = "Vertex should be shared between 2 edges exactly";
999 anEdges.insert(anEdges.end(), aFound->second.begin(), aFound->second.end());
1000 GeomPlanePtr aPlane = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
1002 theError = "Error: Edges are not planar";
1006 GeomEdgePtr anEdge1(new GeomAPI_Edge(anEdges.front()));
1007 GeomEdgePtr anEdge2(new GeomAPI_Edge(anEdges.back()));
1008 GeomVertexPtr aSharedVertex(new GeomAPI_Vertex(aVertex));
1009 if (GeomAlgoAPI_ShapeTools::isTangent(anEdge1, anEdge2, aSharedVertex)) {
1010 theError = "Error: Edges are tangent";
1018 //==================================================================================================
1019 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
1020 const std::list<std::string>& theArguments,
1021 Events_InfoMessage& theError) const
1023 AttributeSelectionListPtr anAttrSelectionList =
1024 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1025 if(!anAttrSelectionList.get()) {
1027 theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
1032 for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1033 AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
1035 //GeomValidators_BodyShapes aBodyValidator;
1036 //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
1040 GeomValidators_FeatureKind aFeatureKindValidator;
1041 if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
1045 ResultPtr aContext = aSelectAttr->context();
1046 ResultConstructionPtr aResultConstruction =
1047 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1048 if(aResultConstruction.get()) {
1049 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1053 ResultBodyPtr aResultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1054 if(aResultBody.get()) {
1057 FeaturePtr aResultFeature = aSelectAttr->contextFeature();
1058 if(aResultFeature.get()) {
1059 bool aOkRes = false;
1060 std::list<ResultPtr>::const_iterator aFRes = aResultFeature->results().cbegin();
1061 for(; aFRes != aResultFeature->results().cend() && !aOkRes; aFRes++) {
1062 ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aFRes);
1063 if (aBody.get() && !aBody->isDisabled())
1070 theError = "Error: Only body shapes and construction planes are allowed for selection.";
1078 //==================================================================================================
1079 bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
1080 const std::list<std::string>& theArguments,
1081 Events_InfoMessage& theError) const
1083 AttributeSelectionListPtr aSubShapesAttrList =
1084 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1085 if(!aSubShapesAttrList.get()) {
1088 "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
1093 static const std::string aBaseShapeID = "base_shape";
1094 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1095 AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
1097 if(!aShapeAttrSelection.get()) {
1099 theError = "Error: Could not get \"%1\" attribute.";
1100 theError.arg(aBaseShapeID);
1105 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1106 ResultPtr aContext = aShapeAttrSelection->context();
1107 if(!aContext.get()) {
1108 theError = "Error: Empty context.";
1111 if(!aBaseShape.get()) {
1112 aBaseShape = aContext->shape();
1114 if(!aBaseShape.get()) {
1115 theError = "Error: Empty base shape.";
1119 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
1120 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1121 bool isSameFound = false;
1122 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1123 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1124 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
1126 if ((*anIt)->isEqual(aShapeToAdd)) {
1132 theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
1140 //==================================================================================================
1141 bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(
1142 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1143 const std::list<std::string>& theArguments,
1144 Events_InfoMessage& theError) const
1146 static const std::string aBaseShapeID = "base_shape";
1147 static const std::string aSubShapesID = "subshapes_to_keep";
1150 if(theFeature->getKind() != "Remove_SubShapes") {
1151 theError = "Error: Feature \"%1\" does not supported by this validator.";
1152 theError.arg(theFeature->getKind());
1156 AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
1157 if(!aShapeAttrSelection.get()) {
1158 theError = "Error: Could not get \"%1\" attribute.";
1159 theError.arg(aBaseShapeID);
1163 AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
1164 if(!aSubShapesAttrList.get()) {
1165 theError = "Error: Could not get \"%1\" attribute.";
1166 theError.arg(aSubShapesID);
1172 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
1173 if(!aBaseShape.get()) {
1174 theError = "Error: Base shape is empty.";
1177 GeomShapePtr aResultShape = aBaseShape->emptyCopied();
1179 if (aSubShapesAttrList->size() == 0) {
1180 theError = "Error: Resulting shape is not valid.";
1184 // Copy sub-shapes from list to new shape.
1185 for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
1186 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
1187 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
1188 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
1192 if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
1193 theError = "Error: Resulting shape is not valid.";
1200 //==================================================================================================
1202 bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttribute,
1203 const std::list<std::string>& theArguments,
1204 Events_InfoMessage& theError) const
1206 AttributeSelectionListPtr aBaseObjectsAttrList =
1207 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1208 if(!aBaseObjectsAttrList.get()) {
1209 theError = "Error: This validator can only work with selection list in \"%1\" feature.";
1210 theError.arg(FeaturesPlugin_Union::ID());
1214 for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) {
1215 AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
1216 ResultPtr aContext = anAttrSelectionInList->context();
1217 if (!aContext.get()) {
1218 theError = "Error: selection is invalid.";
1222 ResultConstructionPtr aConstruction =
1223 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1224 if(aConstruction.get()) {
1225 theError = "Error: Result construction not allowed for selection.";
1229 GeomShapePtr aShape = anAttrSelectionInList->value();
1230 GeomShapePtr aContextShape = aContext->shape();
1231 if (aShape.get() && aContextShape.get() && !aContextShape->isEqual(aShape)) {
1232 theError = "Error: Local selection not allowed.";
1236 ResultBodyPtr aResult =
1237 std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
1238 if(!aResult.get()) {
1242 if(aResult->numberOfSubs() > 0) {
1243 theError = "Error: Whole compsolids not allowed for selection.";
1252 //==================================================================================================
1253 bool FeaturesPlugin_ValidatorUnionArguments::isValid(
1254 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1255 const std::list<std::string>& theArguments,
1256 Events_InfoMessage& theError) const
1259 // Check feature kind.
1260 if(theFeature->getKind() != FeaturesPlugin_Union::ID()) {
1261 theError = "Error: This validator supports only \"%1\" feature.";
1262 theError.arg(FeaturesPlugin_Union::ID());
1266 // Get base objects attribute list.
1267 AttributeSelectionListPtr aBaseObejctsAttrList =
1268 theFeature->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1269 if(!aBaseObejctsAttrList.get()) {
1270 theError = "Error: Could not get \"%1\" attribute.";
1271 theError.arg(FeaturesPlugin_Union::BASE_OBJECTS_ID());
1277 GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::COMPSOLID;
1278 ListOfShape aBaseShapesList;
1279 for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) {
1280 AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex);
1281 GeomShapePtr aShape = anAttrSelectionInList->value();
1282 if (!aShape.get()) {
1285 aBaseShapesList.push_back(aShape);
1286 aType = aShape->shapeType() == GeomAPI_Shape::FACE ? GeomAPI_Shape::SHELL :
1287 GeomAPI_Shape::COMPSOLID;
1290 // Make compound and find connected.
1291 GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList);
1292 ListOfShape aResults;
1293 GeomAlgoAPI_ShapeTools::combineShapes(aCompound, aType, aResults);
1295 if(aResults.size() > 1 || (aResults.size() == 1 && aResults.front()->shapeType() > aType)) {
1296 theError = "Error: Not all shapes have shared topology.";
1303 bool FeaturesPlugin_ValidatorConcealedResult::isValid(const AttributePtr& theAttribute,
1304 const std::list<std::string>& theArguments,
1305 Events_InfoMessage& theError) const
1307 if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
1309 theError = "Error: The attribute with the %1 type is not processed";
1310 theError.arg(theAttribute->attributeType());
1315 AttributeReferencePtr aRefAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeReference>
1317 ObjectPtr aRefObject = aRefAttribute->value();
1318 if (!aRefObject.get()) {
1319 theError = "Error: Empty feature.";
1323 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aRefObject);
1324 if (!aRefFeature.get()) {
1325 theError = "Error: Empty feature.";
1328 std::list<std::shared_ptr<ModelAPI_Result> > aResults;
1329 ModelAPI_Tools::getConcealedResults(aRefFeature, aResults);
1331 size_t aConcealedResults = aResults.size();
1332 if (!aConcealedResults && !theArguments.empty()) {
1333 // find if these results are touched by the feature in another attribute
1334 std::list<std::string>::const_iterator anIt = theArguments.begin();
1335 std::string aRecoveredList = *anIt;
1336 if (!aRecoveredList.empty()) {
1337 std::shared_ptr<ModelAPI_AttributeRefList> aParameterList =
1338 theAttribute->owner()->data()->reflist(aRecoveredList);
1339 if (aParameterList.get())
1340 aConcealedResults = aParameterList->size();
1344 if (aConcealedResults == 0)
1345 theError = "Error: No concealed results.";
1347 return theError.empty();
1350 bool FeaturesPlugin_ValidatorCircular::isValid(const AttributePtr& theAttribute,
1351 const std::list<std::string>& theArguments,
1352 Events_InfoMessage& theError) const
1354 static std::list<std::string> aEdgeArg(1, "circle");
1355 static std::list<std::string> aFaceArg(1, "cylinder");
1357 Events_InfoMessage aError;
1358 bool isValid = GeomValidators_ShapeType().isValid(theAttribute, aEdgeArg, aError);
1360 isValid = GeomValidators_Face().isValid(theAttribute, aFaceArg, aError);
1362 theError = "The shape neither circle nor cylinder";
1367 //=================================================================================================
1368 bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
1369 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1370 const std::list<std::string>& theArguments,
1371 Events_InfoMessage& theError) const
1374 if (theArguments.size() != 2)
1376 theError = "Wrong number of arguments (expected 2).";
1381 int anObjectsToolsNb[2] = { 0, 0 };
1383 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
1385 bool isAllInSameCompSolid = true;
1386 ResultBodyPtr aCompSolid;
1388 for (int* anArgNbIt = anObjectsToolsNb; anIt != aLast; ++anIt, ++anArgNbIt) {
1389 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1392 *anArgNbIt = anAttrSelList->size();
1393 if (isAllInSameCompSolid) {
1394 for (int anIndex = 0; anIndex < *anArgNbIt; ++anIndex)
1396 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1397 ResultPtr aContext = anAttr->context();
1398 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1399 if (aResCompSolidPtr.get())
1401 if (aCompSolid.get())
1403 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1407 aCompSolid = aResCompSolidPtr;
1412 isAllInSameCompSolid = false;
1420 std::shared_ptr<FeaturesPlugin_Boolean> aFeature =
1421 std::dynamic_pointer_cast<FeaturesPlugin_Boolean>(theFeature);
1422 FeaturesPlugin_Boolean::OperationType anOperationType = aFeature->operationType();
1424 if (anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE)
1427 if (anObjectsToolsNb[0] + anObjectsToolsNb[1] < 2)
1429 theError = "Not enough arguments for Fuse operation.";
1432 else if (isAllInSameCompSolid)
1434 theError = "Operations only between sub-shapes of the same shape not allowed.";
1440 if (anObjectsToolsNb[0] < 1) // check number of objects
1442 theError = "Objects not selected.";
1445 if (anObjectsToolsNb[1] < 1) // check number of tools
1447 theError = "Tools not selected.";
1450 if (isAllInSameCompSolid)
1452 theError = "Operations only between sub-shapes of the same shape not allowed.";
1460 //=================================================================================================
1462 bool FeaturesPlugin_ValidatorBooleanArguments::isNotObligatory(std::string theFeature,
1463 std::string theAttribute)
1465 if (theAttribute == "main_objects" || theAttribute == "tool_objects")
1474 //==================================================================================================
1475 bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
1476 const AttributePtr& theAttribute,
1477 const std::list<std::string>& theArguments,
1478 Events_InfoMessage& theError) const
1480 std::shared_ptr<FeaturesPlugin_BooleanSmash> aFeature =
1481 std::dynamic_pointer_cast<FeaturesPlugin_BooleanSmash>(theAttribute->owner());
1483 AttributeSelectionListPtr anAttrSelectionList =
1484 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1485 if (!aFeature.get() || !anAttrSelectionList.get()) {
1488 "Error: Validator used in wrong feature or attribute";
1493 AttributeSelectionListPtr anOtherAttrSelectionList;
1494 if (theAttribute->id() == FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()) {
1495 anOtherAttrSelectionList =
1496 aFeature->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID());
1498 anOtherAttrSelectionList =
1499 aFeature->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID());
1502 GeomAPI_Shape::ShapeType aSelectedShapesType = GeomAPI_Shape::SHAPE;
1503 GeomAPI_DataMapOfShapeShape aSelectedCompSolidsInOtherList;
1504 GeomPlanePtr aFacesPln;
1506 for (int anIndex = 0; anIndex < anOtherAttrSelectionList->size(); ++anIndex) {
1507 AttributeSelectionPtr anAttrSelection = anOtherAttrSelectionList->value(anIndex);
1509 if (anAttrSelection->contextFeature().get()) {
1510 theError = "Error: Features not allowed for selection.";
1514 ResultPtr aContext = anAttrSelection->context();
1515 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1516 if (!aShape.get()) {
1517 if (!aContext.get()) {
1518 theError = "Error: Empty selection.";
1521 aShape = aContext->shape();
1524 if (aShape->isSolid() || aShape->isCompSolid()) {
1525 aSelectedShapesType = GeomAPI_Shape::SOLID;
1526 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1527 if (aResCompSolidPtr.get()) {
1528 GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
1529 aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape);
1532 aSelectedShapesType = GeomAPI_Shape::FACE;
1533 GeomAPI_Face aFace(aShape);
1534 aFacesPln = aFace.getPlane();
1539 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1540 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1541 if (!anAttrSelection.get()) {
1542 theError = "Error: Empty attribute selection.";
1546 if (anAttrSelection->contextFeature().get()) {
1547 theError = "Error: Features not allowed for selection.";
1551 ResultPtr aContext = anAttrSelection->context();
1552 if(!aContext.get()) {
1553 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1554 if (!aContFeat.get() || !aContFeat->results().size() ||
1555 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1556 theError = "Error: Empty selection context.";
1560 ResultConstructionPtr aResultConstruction =
1561 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1562 if (aResultConstruction.get()) {
1563 theError = "Error: Result construction not allowed for selection.";
1566 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1567 GeomShapePtr aContextShape = aContext->shape();
1568 if (!aShape.get()) {
1569 aShape = aContextShape;
1571 if (!aShape.get()) {
1572 theError = "Error: Empty shape.";
1575 if (!aShape->isEqual(aContextShape)) {
1576 theError = "Error: Local selection not allowed.";
1580 if (aSelectedShapesType == GeomAPI_Shape::SHAPE) {
1581 // Other list is empty.
1582 if (aShape->isSolid() || aShape->isCompSolid()) {
1583 aSelectedShapesType = GeomAPI_Shape::SOLID;
1585 aSelectedShapesType = GeomAPI_Shape::FACE;
1586 GeomAPI_Face aFace(aShape);
1587 aFacesPln = aFace.getPlane();
1589 if (!aFacesPln.get()) {
1590 theError = "Error: Only planar faces allowed.";
1596 } else if (aSelectedShapesType == GeomAPI_Shape::SOLID) {
1597 if (!aShape->isSolid() && !aShape->isCompSolid()) {
1598 theError = "Error: Selected shapes should have the same type.";
1602 GeomAPI_Face aFace(aShape);
1603 GeomPlanePtr aPln = aFace.getPlane();
1606 theError = "Error: Only planar faces allowed.";
1610 if (!aFacesPln->isCoincident(aPln)) {
1611 theError = "Error: Only coincident faces allowed.";
1620 //==================================================================================================
1622 bool FeaturesPlugin_IntersectionSelection::isValid(const AttributePtr& theAttribute,
1623 const std::list<std::string>& theArguments,
1624 Events_InfoMessage& theError) const
1626 if (!theAttribute.get()) {
1627 theError = "Error: empty selection.";
1630 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
1631 AttributeSelectionListPtr anAttrSelectionList =
1632 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1633 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1634 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1635 if (!anAttrSelection.get()) {
1636 theError = "Error: empty attribute selection.";
1639 ResultPtr aContext = anAttrSelection->context();
1640 if (aContext.get()) {
1641 aFeature = ModelAPI_Feature::feature(aContext);
1643 aFeature = anAttrSelection->contextFeature();
1644 if (!aFeature.get() || !aFeature->results().size() ||
1645 aFeature->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1646 theError = "Error: Empty selection context.";
1650 if (!aFeature.get()) {
1651 theError = "Error: empty feature.";
1654 std::string aFeatureKind = aFeature->getKind();
1655 if (aFeatureKind == "Sketch" ||
1656 aFeatureKind == "Plane" ||
1657 aFeatureKind == "Axis") {
1658 theError = "Error: %1 shape is not allowed for selection.";
1659 theError.arg(aFeatureKind);
1662 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1663 if (!aShape.get()) {
1664 GeomShapePtr aContextShape = aContext->shape();
1665 aShape = aContextShape;
1667 if (!aShape.get()) {
1668 theError = "Error: empty shape.";
1671 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1672 theError = "Error: Local selection not allowed.";
1676 int aShapeType = aShape->shapeType();
1677 // Allow to select edges, faces and solids.
1678 if (aShapeType != GeomAPI_Shape::EDGE &&
1679 aShapeType != GeomAPI_Shape::FACE &&
1680 aShapeType != GeomAPI_Shape::SOLID &&
1681 aShapeType != GeomAPI_Shape::COMPSOLID &&
1682 aShapeType != GeomAPI_Shape::COMPOUND) {
1683 theError = "Error: selected shape has the wrong type.";
1692 //==================================================================================================
1694 bool FeaturesPlugin_ValidatorBooleanFuseSelection::isValid(
1695 const AttributePtr& theAttribute,
1696 const std::list<std::string>& theArguments,
1697 Events_InfoMessage& theError) const
1699 AttributeSelectionListPtr anAttrSelectionList =
1700 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1701 if (!anAttrSelectionList.get()) {
1703 "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
1707 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1708 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1709 if (!anAttrSelection.get()) {
1710 theError = "Error: Empty attribute selection.";
1713 ResultPtr aContext = anAttrSelection->context();
1714 if(!aContext.get()) {
1715 FeaturePtr aContFeat = anAttrSelection->contextFeature();
1716 if (!aContFeat.get() || !aContFeat->results().size() ||
1717 aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) {
1718 theError = "Error: Empty selection context.";
1722 ResultConstructionPtr aResultConstruction =
1723 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
1724 if (aResultConstruction.get()) {
1725 theError = "Error: Result construction not allowed for selection.";
1728 std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
1729 if (!aShape.get()) {
1730 GeomShapePtr aContextShape = aContext->shape();
1731 aShape = aContextShape;
1733 if (!aShape.get()) {
1734 theError = "Error: Empty shape.";
1737 if (aContext.get() && !aShape->isEqual(aContext->shape())) {
1738 theError = "Error: Local selection not allowed.";
1747 //=================================================================================================
1748 bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
1749 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1750 const std::list<std::string>& theArguments,
1751 Events_InfoMessage& theError) const
1754 if (theArguments.size() != 2) {
1755 theError = "Wrong number of arguments (expected 2).";
1760 std::shared_ptr<FeaturesPlugin_BooleanFuse> aFeature =
1761 std::dynamic_pointer_cast<FeaturesPlugin_BooleanFuse>(theFeature);
1763 int anObjectsNb = 0, aToolsNb = 0;
1765 std::list<std::string>::const_iterator anIt = theArguments.begin();
1767 bool isAllInSameCompSolid = true;
1768 ResultBodyPtr aCompSolid;
1770 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1771 if (anAttrSelList) {
1772 anObjectsNb = anAttrSelList->size();
1773 for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex) {
1774 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1775 ResultPtr aContext = anAttr->context();
1776 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1777 if (aResCompSolidPtr.get()) {
1778 if (aCompSolid.get()) {
1779 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1781 aCompSolid = aResCompSolidPtr;
1784 isAllInSameCompSolid = false;
1791 if (aFeature->string(FeaturesPlugin_BooleanFuse::CREATION_METHOD())->value()
1792 == FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED()) {
1793 anAttrSelList = theFeature->selectionList(*anIt);
1794 if (anAttrSelList) {
1795 aToolsNb = anAttrSelList->size();
1796 if (isAllInSameCompSolid) {
1797 for (int anIndex = 0; anIndex < aToolsNb; ++anIndex) {
1798 AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
1799 ResultPtr aContext = anAttr->context();
1800 ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
1801 if (aResCompSolidPtr.get()) {
1802 if (aCompSolid.get()) {
1803 isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
1805 aCompSolid = aResCompSolidPtr;
1808 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();
1919 ResultBodyPtr aCompSolid;
1921 AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
1922 if (anAttrSelList) {
1923 anObjectsNb = anAttrSelList->size();
1926 bool isSimpleMode = aFeature->string(FeaturesPlugin_BooleanCommon::CREATION_METHOD())->value()
1927 == FeaturesPlugin_BooleanCommon::CREATION_METHOD_SIMPLE();
1929 if (!isSimpleMode) {
1930 anAttrSelList = theFeature->selectionList(*anIt);
1931 if (anAttrSelList) {
1932 aToolsNb = anAttrSelList->size();
1936 if ((isSimpleMode && anObjectsNb < 2)
1937 || (!isSimpleMode && (anObjectsNb == 0 || aToolsNb == 0))) {
1938 theError = "Not enough arguments for Fuse operation.";
1944 //=================================================================================================
1946 bool FeaturesPlugin_ValidatorBooleanCommonArguments::isNotObligatory(
1947 std::string theFeature,
1948 std::string theAttribute)
1954 //==================================================================================================
1955 bool FeaturesPlugin_ValidatorDefeaturingSelection::isValid(
1956 const AttributePtr& theAttribute,
1957 const std::list<std::string>& theArguments,
1958 Events_InfoMessage& theError) const
1960 AttributeSelectionListPtr anAttrSelectionList =
1961 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
1962 if (!anAttrSelectionList.get()) {
1964 theError = "Error: This validator can only work with selection list attributes.";
1969 // Check selected entities are sub-shapes of solid or compsolid
1970 GeomShapePtr aBaseSolid;
1971 for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
1972 AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
1973 if (!anAttrSelection.get()) {
1974 theError = "Error: Empty attribute selection.";
1977 ResultPtr aContext = anAttrSelection->context();
1978 if (!aContext.get()) {
1979 theError = "Error: Empty selection context.";
1983 GeomShapePtr aContextShape = aContext->shape();
1984 if (aContextShape->shapeType() != GeomAPI_Shape::SOLID) {
1985 theError = "Error: Not all selected shapes are sub-shapes of solids.";