Salome HOME
Copyright update 2020
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Validators.cpp
index ee82a62f5c8c415cd3a897a4818c44d102358822..37d1385dd3d9d520aed07d0ad5baa42cd1f698db 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2020  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
 #include "FeaturesPlugin_BooleanFuse.h"
 #include "FeaturesPlugin_BooleanCommon.h"
 #include "FeaturesPlugin_BooleanSmash.h"
+#include "FeaturesPlugin_Extrusion.h"
 #include "FeaturesPlugin_Pipe.h"
 #include "FeaturesPlugin_Union.h"
 
 #include <Events_InfoMessage.h>
 
 #include <ModelAPI_Attribute.h>
+#include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
@@ -52,6 +54,7 @@
 #include <GeomAPI_ShapeIterator.h>
 
 #include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_Prism.h>
 #include <GeomAlgoAPI_ShapeBuilder.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAlgoAPI_WireBuilder.h>
@@ -268,9 +271,8 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theA
         if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
           for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
             GeomShapePtr aSubShape = anIt.current();
-            if(aSubShape->shapeType() != GeomAPI_Shape::VERTEX
-                && aSubShape->shapeType() != GeomAPI_Shape::EDGE
-                && aSubShape->shapeType() != GeomAPI_Shape::FACE) {
+            if (aSubShape->shapeType() > GeomAPI_Shape::VERTEX ||
+                aSubShape->shapeType() < GeomAPI_Shape::FACE) {
               theError = "Error: Compound should contain only faces, edges or vertices.";
               return false;
             }
@@ -296,7 +298,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theA
 
           if(aSelectedWiresFromObjects.isBound(aWire)) {
             theError =
-              "Error: Objects with such wire already selected. Don't allow to select this object.";
+              "Error: Objects with this wire already selected. Don't allow to select this object.";
             return false;
           }
 
@@ -458,7 +460,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
     GeomValidators_ShapeType aShapeTypeValidator;
     if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
       theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or "
-                 "wires on sketch, whole sketch(if it has at least one face), "
+                 "wires on sketch, whole sketch (if it has at least one face), "
                  "and whole objects with shape types: %1";
       std::string anArgumentString;
       for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {
@@ -686,6 +688,99 @@ bool FeaturesPlugin_ValidatorExtrusionDir::isShapesCanBeEmpty(const AttributePtr
   return true;
 }
 
+//==================================================================================================
+bool FeaturesPlugin_ValidatorExtrusionBoundaryFace::isValid(
+    const AttributePtr& theAttribute,
+    const std::list<std::string>& theArguments,
+    Events_InfoMessage& theError) const
+{
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
+
+  // Collect all necessary attributes and try to build prism
+
+  // base face
+  AttributeSelectionListPtr aBaseShapeAttr =
+      aFeature->selectionList(FeaturesPlugin_Extrusion::BASE_OBJECTS_ID());
+  ListOfShape aBaseShapeList;
+  std::string anError;
+  if (!FeaturesPlugin_Tools::getShape(aBaseShapeAttr, true, aBaseShapeList, anError)) {
+    theError = anError;
+    return false;
+  }
+
+  // direction
+  AttributeSelectionPtr aSelection =
+      aFeature->selection(FeaturesPlugin_Extrusion::DIRECTION_OBJECT_ID());
+  GeomShapePtr aShape = aSelection->value();
+  if (!aShape.get() && aSelection->context().get())
+    aShape = aSelection->context()->shape();
+
+  GeomEdgePtr anEdge;
+  if (aShape.get()) {
+    if (aShape->isEdge())
+      anEdge = aShape->edge();
+    else if (aShape->isCompound()) {
+      GeomAPI_ShapeIterator anIt(aShape);
+      anEdge = anIt.current()->edge();
+    }
+  }
+
+  std::shared_ptr<GeomAPI_Dir> aDir;
+  if (anEdge.get() && anEdge->isLine())
+    aDir = anEdge->line()->direction();
+
+  // from/to shapes
+  GeomShapePtr aFromShape, aToShape;
+  aSelection = aFeature->selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
+  if (aSelection.get()) {
+    aToShape = aSelection->value();
+    if (!aToShape.get() && aSelection->context().get())
+      aToShape = aSelection->context()->shape();
+    if (aToShape.get() && aToShape->isCompound()) {
+      GeomAPI_ShapeIterator anIt(aToShape);
+      aToShape = anIt.current();
+    }
+    if (aToShape.get() && !aToShape->isFace()) {
+      theError = "\"To\" shape is not a face";
+      return false;
+    }
+  }
+  aSelection = aFeature->selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
+  if (aSelection.get()) {
+    aFromShape = aSelection->value();
+    if (!aFromShape.get() && aSelection->context().get())
+      aFromShape = aSelection->context()->shape();
+    if (aFromShape.get() && aFromShape->isCompound()) {
+      GeomAPI_ShapeIterator anIt(aFromShape);
+      aFromShape = anIt.current();
+    }
+    if (aFromShape.get() && !aFromShape->isFace()) {
+      theError = "\"From\" shape is not a face";
+      return false;
+    }
+  }
+
+  double aToSize = aFeature->real(FeaturesPlugin_Extrusion::TO_OFFSET_ID())->value();
+  double aFromSize = aFeature->real(FeaturesPlugin_Extrusion::FROM_OFFSET_ID())->value();
+
+  // check extrusion
+  for (ListOfShape::iterator anIt = aBaseShapeList.begin(); anIt != aBaseShapeList.end(); anIt++) {
+    std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIt;
+
+    std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo(
+        new GeomAlgoAPI_Prism(aBaseShape, aDir, aToShape, aToSize, aFromShape, aFromSize));
+    bool isFailed = GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPrismAlgo,
+                                                                    FeaturesPlugin_Extrusion::ID(),
+                                                                    anError);
+    if (isFailed) {
+      theError = anError;
+      return false;
+    }
+  }
+
+  return true;
+}
+
 //==================================================================================================
 bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
                                                        const std::list<std::string>& theArguments,
@@ -817,8 +912,9 @@ bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAtt
       }
     }
 
-    ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext);
-    GeomShapePtr anOwner = aContextOwner.get() ? aContextOwner->shape() : aContext->shape();
+    ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext, true);
+    GeomShapePtr anOwner = aContext->shape();
+    GeomShapePtr aTopLevelOwner = aContextOwner.get() ? aContextOwner->shape() : anOwner;
 
     if (!anOwner) {
       theError = "Error: wrong feature is selected.";
@@ -832,8 +928,8 @@ bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAtt
     }
 
     if (!aBaseSolid)
-      aBaseSolid = anOwner;
-    else if (!aBaseSolid->isEqual(anOwner)) {
+      aBaseSolid = aTopLevelOwner;
+    else if (!aBaseSolid->isEqual(aTopLevelOwner)) {
       theError = "Error: Sub-shapes of different solids have been selected.";
       return false;
     }
@@ -1646,9 +1742,6 @@ bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
   if (anObjectsNb + aToolsNb < 2) {
     theError = "Not enough arguments for Fuse operation.";
     return false;
-  } else if (isAllInSameCompSolid) {
-    theError = "Operations only between sub-shapes of the same shape not allowed.";
-    return false;
   }
 
   return true;
@@ -1784,3 +1877,42 @@ bool FeaturesPlugin_ValidatorBooleanCommonArguments::isNotObligatory(
   return false;
 }
 // LCOV_EXCL_STOP
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorDefeaturingSelection::isValid(
+    const AttributePtr& theAttribute,
+    const std::list<std::string>& theArguments,
+    Events_InfoMessage& theError) const
+{
+  AttributeSelectionListPtr anAttrSelectionList =
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if (!anAttrSelectionList.get()) {
+    // LCOV_EXCL_START
+    theError = "Error: This validator can only work with selection list attributes.";
+    return false;
+    // LCOV_EXCL_STOP
+  }
+
+  // Check selected entities are sub-shapes of solid or compsolid
+  GeomShapePtr aBaseSolid;
+  for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+    if (!anAttrSelection.get()) {
+      theError = "Error: Empty attribute selection.";
+      return false;
+    }
+    ResultPtr aContext = anAttrSelection->context();
+    if (!aContext.get()) {
+      theError = "Error: Empty selection context.";
+      return false;
+    }
+
+    GeomShapePtr aContextShape = aContext->shape();
+    if (aContextShape->shapeType() != GeomAPI_Shape::SOLID) {
+      theError = "Error: Not all selected shapes are sub-shapes of solids.";
+      return false;
+    }
+  }
+
+  return true;
+}