X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FBuildPlugin%2FBuildPlugin_Validators.cpp;h=4c7c8a4fc8afbbceb1fb1f1b6a1820c95730cc1f;hb=d9d68ad55d070600eac1027ac23575616edbe69c;hp=7204aebce1f05fd0f784cde8ee740f70e75a3960;hpb=e8109d1f288ff9d45c2e9622116c903a562fda14;p=modules%2Fshaper.git diff --git a/src/BuildPlugin/BuildPlugin_Validators.cpp b/src/BuildPlugin/BuildPlugin_Validators.cpp index 7204aebce..4c7c8a4fc 100644 --- a/src/BuildPlugin/BuildPlugin_Validators.cpp +++ b/src/BuildPlugin/BuildPlugin_Validators.cpp @@ -1,8 +1,21 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: BuildPlugin_Validators.cpp -// Created: 22 March 2016 -// Author: Dmitry Bobylev +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "BuildPlugin_Validators.h" @@ -10,26 +23,39 @@ #include #include +#include +#include +#include #include +#include +#include +#include +#include #include +#include +#include +#include #include -#include +#include //================================================================================================= bool BuildPlugin_ValidatorBaseForBuild::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { // Get base objects list. if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) { - Events_Error::send("Error: BuildPlugin_ValidatorBaseForBuild does not support attribute type \"" + theAttribute->attributeType() - + "\"\n Only \"" + ModelAPI_AttributeSelectionList::typeId() + "\" supported."); + std::string aMsg = "Error: BuildPlugin_ValidatorBaseForBuild does " + "not support attribute type '%1'\nOnly '%2' is supported."; + Events_InfoMessage("BuildPlugin_Validators", aMsg). + arg(theAttribute->attributeType()).arg(ModelAPI_AttributeSelectionList::typeId()).send(); return false; } - AttributeSelectionListPtr aSelectionList = std::dynamic_pointer_cast(theAttribute); + AttributeSelectionListPtr aSelectionList = + std::dynamic_pointer_cast(theAttribute); if(!aSelectionList.get()) { theError = "Could not get selection list."; return false; @@ -69,23 +95,23 @@ bool BuildPlugin_ValidatorBaseForBuild::isValid(const AttributePtr& theAttribute } // Check that it is shape on sketch. - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); + ResultConstructionPtr aConstruction = + std::dynamic_pointer_cast(aContext); if(aConstruction.get()) { if(aConstruction->isInfinite()) { theError = "Inifinte objects not acceptable."; return false; } - std::shared_ptr anEdges = std::dynamic_pointer_cast(aContextShape); + std::shared_ptr anEdges = + std::dynamic_pointer_cast(aContextShape); if(anEdges.get()) { if(aShape->isEqual(aContextShape)) { // It is whole sketch. return false; } - } else if(!aShape->isEqual(aContextShape)) { - // Local selection on body does not allowed. - theError = "Selected shape is in the local selection. Only global selection is allowed."; - return false; + + continue; } } } @@ -96,35 +122,34 @@ bool BuildPlugin_ValidatorBaseForBuild::isValid(const AttributePtr& theAttribute //================================================================================================= bool BuildPlugin_ValidatorBaseForWire::isValid(const std::shared_ptr& theFeature, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { // Get attribute. if(theArguments.size() != 1) { - Events_Error::send("Error: BuildPlugin_ValidatorBaseForWire should be used only with 1 parameter (ID of base objects list)"); + std::string aMsg = "Error: BuildPlugin_ValidatorBaseForWire should be used only " + "with 1 parameter (ID of base objects list)."; + Events_InfoMessage("BuildPlugin_Validators", aMsg).send(); return false; } - AttributePtr anAttribute = theFeature->attribute(theArguments.front()); - - // Check base objects list. - BuildPlugin_ValidatorBaseForBuild aValidatorBaseForBuild; - std::list anArguments; - anArguments.push_back("edge"); - anArguments.push_back("wire"); - if(!aValidatorBaseForBuild.isValid(anAttribute, anArguments, theError)) { + AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front()); + if(!aSelectionList.get()) { + theError = "Empty attribute \"%1\"."; + theError.arg(theArguments.front()); return false; } + // Collect base shapes. - AttributeSelectionListPtr aSelectionList = - std::dynamic_pointer_cast(anAttribute); ListOfShape aListOfShapes; for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); GeomShapePtr aShape = aSelection->value(); if(!aShape.get()) { - aShape = aSelection->context()->shape(); + if (aSelection->context().get()) + aShape = aSelection->context()->shape(); } - aListOfShapes.push_back(aShape); + if (aShape.get()) + aListOfShapes.push_back(aShape); } // Create wire. @@ -138,40 +163,325 @@ bool BuildPlugin_ValidatorBaseForWire::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const { - return false; + // Get attribute. + if(theArguments.size() != 1) { + std::string aMsg = "Error: BuildPlugin_ValidatorBaseForFace should be used only with " + "1 parameter (ID of base objects list)."; + Events_InfoMessage("BuildPlugin_Validators", aMsg).send(); + return false; + } + AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front()); + if(!aSelectionList.get()) { + theError = "Empty attribute \"%1\"."; + theError.arg(theArguments.front()); + return false; + } + + bool hasEdgesOrWires = false; + bool hasFaces = false; + + // Collect base shapes. + ListOfShape anEdges; + for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { + AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); + GeomShapePtr aShape = aSelection->value(); + if(!aShape.get()) { + if (!aSelection->context()) { + theError = "Objects are not selected."; + return false; + } + aShape = aSelection->context()->shape(); + } + if (aShape->shapeType() == GeomAPI_Shape::FACE) { + // skip faces exploding + hasFaces = true; + continue; + } + + for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { + hasEdgesOrWires = true; + GeomShapePtr anEdge = anExp.current(); + anEdges.push_back(anEdge); + } + } + + if (hasFaces && hasEdgesOrWires) { + theError = "Faces and edges/wires should be selected together."; + return false; + } else if (hasEdgesOrWires && anEdges.empty()) { + theError = "Objects are not selected."; + return false; + } + + // Check that edges does not have intersections. + if(anEdges.size() > 1) { + GeomAlgoAPI_PaveFiller aPaveFiller(anEdges, false); + if(!aPaveFiller.isDone()) { + theError = "Error while checking if edges intersects."; + return false; + } + GeomShapePtr aSectedEdges = aPaveFiller.shape(); + + int anEdgesNum = 0; + for(GeomAPI_ShapeExplorer + anExp(aSectedEdges, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { + anEdgesNum++; + } + if(anEdgesNum != anEdges.size()) { + theError = "Selected objects have intersections."; + return false; + } + } + + if (!anEdges.empty()) { + // Check that they are planar. + std::shared_ptr aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges); + if(!aPln.get()) { + theError = "Selected object(s) should belong to only one plane."; + return false; + } + + // Check that selected objects have closed contours. + GeomAlgoAPI_SketchBuilder aBuilder(aPln, anEdges); + const ListOfShape& aFaces = aBuilder.faces(); + if(aFaces.empty()) { + theError = "Selected objects do not generate closed contour."; + return false; + } + } + + return true; } //================================================================================================= -bool BuildPlugin_ValidatorBaseForFace::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - std::string& theError) const +bool BuildPlugin_ValidatorBaseForSolids::isValid( + const std::shared_ptr& theFeature, const std::list& theArguments, + Events_InfoMessage& theError) const { // Get base objects list. - BuildPlugin_ValidatorBaseForBuild aValidatorBaseForBuild; - std::list anArguments; - anArguments.push_back("edge"); - anArguments.push_back("wire"); - if(!aValidatorBaseForBuild.isValid(theAttribute, anArguments, theError)) { + AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front()); + if (!aSelectionList.get()) { + theError = "Could not get selection list."; + return false; + } + if (aSelectionList->size() == 0) { + theError = "Empty selection list."; return false; } // Collect base shapes. - AttributeSelectionListPtr aSelectionList = - std::dynamic_pointer_cast(theAttribute); - ListOfShape aListOfShapes; - for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { + ListOfShape anOriginalShapes; + for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); + if (!aSelection->context().get()) { + theError = "Invalid selection."; + return false; + } GeomShapePtr aShape = aSelection->value(); - if(!aShape.get()) { + if (!aShape.get()) aShape = aSelection->context()->shape(); + anOriginalShapes.push_back(aShape); + } + + std::shared_ptr anAlgorithm( + new GeomAlgoAPI_MakeVolume(anOriginalShapes, false)); + + std::string anErr; + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(anAlgorithm, "MakeVolume", anErr)) { + theError = anErr; + return false; + } + + // set of allowed types of results + std::set aResultType; + std::string aType = theArguments.back(); + if (aType == "solid") + aResultType.insert(GeomAPI_Shape::SOLID); + else if (aType == "compsolid") { + aResultType.insert(GeomAPI_Shape::COMPSOLID); + aResultType.insert(GeomAPI_Shape::SOLID); + } + + GeomShapePtr aCompound = anAlgorithm->shape(); + if (aCompound->shapeType() == GeomAPI_Shape::COMPOUND) { + GeomAPI_ShapeIterator anIt(aCompound); + GeomShapePtr aFoundSub; + for (; anIt.more() && !aFoundSub; anIt.next()) { + aFoundSub = anIt.current(); + if (aResultType.count(aFoundSub->shapeType()) == 0) { + theError = "Unable to build a solid"; + return false; + } + } + if (anIt.more() || !aFoundSub.get()) { + theError = "Unable to build a solid"; + return false; } - aListOfShapes.push_back(aShape); + } else if (aResultType.count(aCompound->shapeType()) == 0) { + theError = "Unable to build a solid"; + return false; + } + // check the internal faces presence + for(GeomAPI_ShapeExplorer aFaces(aCompound, GeomAPI_Shape::FACE); aFaces.more(); aFaces.next()) { + if (aFaces.current()->orientation() == GeomAPI_Shape::INTERNAL) { + theError = "Internal faces are not allowed in the resulting solid"; + return false; + } + } + + return true; +} + + +//================================================================================================= +bool BuildPlugin_ValidatorSubShapesSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if(theArguments.size() != 1) { + std::string aMsg = "Error: BuildPlugin_ValidatorSubShapesSelection should be used only with " + "1 parameter(Sketch feature id)."; + Events_InfoMessage("BuildPlugin_Validators", aMsg).send(); + return false; + } + + // Get base objects list. + if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) { + std::string aMsg = + "Error: BuildPlugin_ValidatorSubShapesSelection does not support attribute type \"" + "%1\"\n Only \"%2\" supported."; + Events_InfoMessage("BuildPlugin_Validators", aMsg). + arg(theAttribute->attributeType()).arg(ModelAPI_AttributeSelectionList::typeId()).send(); + return false; + } + AttributeSelectionListPtr aSelectionList = + std::dynamic_pointer_cast(theAttribute); + if(!aSelectionList.get()) { + theError = "Could not get selection list."; + return false; + } + + // Get base shape. + const std::string aBaseShapeId = "base_shape"; + FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); + AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeId); + + if(!aShapeAttrSelection.get()) { + theError = "Base shape is empty."; + return false; + } + + ResultPtr aBaseContext = aShapeAttrSelection->context(); + + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + if(!aBaseShape.get()) { + theError = "Base shape is empty."; + return false; + } + + GeomAlgoAPI_ShapeBuilder aBuilder; + aBuilder.removeInternal(aBaseShape); + aBaseShape = aBuilder.shape(); + + // If selected shape is wire allow to select only vertices. If face - allow vertices and edges. + std::set anAllowedTypes; + switch(aBaseShape->shapeType()) { + case GeomAPI_Shape::FACE: anAllowedTypes.insert(GeomAPI_Shape::EDGE); + case GeomAPI_Shape::WIRE: anAllowedTypes.insert(GeomAPI_Shape::VERTEX); + default: break; + } + + // Check selected shapes. + GeomValidators_FeatureKind aFeatureKindValidator; + std::list anArguments; + anArguments.push_back(theArguments.front()); + for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { + AttributeSelectionPtr aSelectionAttrInList = aSelectionList->value(anIndex); + if(!aSelectionAttrInList.get()) { + theError = "Empty attribute in list."; + return false; + } + + // If context of selection same skip. + if(aBaseContext == aSelectionAttrInList->context()) { + continue; + } + + // Check that it is a selection on Sketch. + if(!aFeatureKindValidator.isValid(aSelectionAttrInList, anArguments, theError)) { + return false; + } + + // Check shape type. + GeomShapePtr aShapeInList = aSelectionAttrInList->value(); + if(!aShapeInList.get()) { + aShapeInList = aSelectionAttrInList->context()->shape(); + } + if(anAllowedTypes.find(aShapeInList->shapeType()) == anAllowedTypes.cend()) { + theError = "Selected shape has unacceptable type."; + return false; + } + + // Check that shape inside wire or face. + if(!GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aShapeInList, aBaseShape)) { + theError = "Selected shape is not inside base face."; + return false; + } + } + + return true; +} + + +//================================================================================================= +bool BuildPlugin_ValidatorFillingSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + // Get base objects list. + if (theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) { + std::string aMsg = + "Error: BuildPlugin_ValidatorFillingSelection does not support attribute type \"" + "%1\"\n Only \"%2\" supported."; + Events_InfoMessage("BuildPlugin_Validators", aMsg). + arg(theAttribute->attributeType()).arg(ModelAPI_AttributeSelectionList::typeId()).send(); + return false; + } + AttributeSelectionListPtr aSelectionList = + std::dynamic_pointer_cast(theAttribute); + if (!aSelectionList.get()) { + theError = "Could not get selection list."; + return false; } - // Check that they are planar. - GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aListOfShapes); + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); + + // Check selected shapes. + for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { + AttributeSelectionPtr aSelectionAttrInList = aSelectionList->value(anIndex); + if (!aSelectionAttrInList.get()) { + theError = "Empty attribute in list."; + return false; + } + + // Check shape exists. + GeomShapePtr aShapeInList = aSelectionAttrInList->value(); + if (!aShapeInList.get()) { + theError = "Object has no shape"; + return false; + } - return aCompound->isPlanar(); + // Check shape type. + GeomAPI_Shape::ShapeType aType = aShapeInList->shapeType(); + if (aType != GeomAPI_Shape::EDGE && aType != GeomAPI_Shape::WIRE) { + theError = "Incorrect objects selected"; + return false; + } + } + + return true; }