]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
CEA : Lot2 - Bounding box
authorcg246364 <clarisse.genrault@cea.fr>
Tue, 19 Jan 2021 14:46:17 +0000 (15:46 +0100)
committercg246364 <clarisse.genrault@cea.fr>
Wed, 20 Jan 2021 14:22:42 +0000 (15:22 +0100)
30 files changed:
src/FeaturesAPI/CMakeLists.txt
src/FeaturesAPI/FeaturesAPI.i
src/FeaturesAPI/FeaturesAPI_BoundingBox.cpp [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_BoundingBox.h [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_swig.h
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_BoundingBox.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_BoundingBox.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_CommonBoundingBox.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_CommonBoundingBox.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp
src/FeaturesPlugin/FeaturesPlugin_msg_fr.ts
src/FeaturesPlugin/Test/TestBoundingBox.py [new file with mode: 0644]
src/FeaturesPlugin/bounding_box_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/create_bounding_box_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/doc/FeaturesPlugin.rst
src/FeaturesPlugin/doc/TUI_boundingBoxFeature.rst [new file with mode: 0644]
src/FeaturesPlugin/doc/boundingBoxFeature.rst [new file with mode: 0644]
src/FeaturesPlugin/doc/examples/create_bounding_box.py [new file with mode: 0644]
src/FeaturesPlugin/doc/images/BoundingBoxResult.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/bounding.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/boundingBoxPropertyPanel.png [new file with mode: 0644]
src/FeaturesPlugin/icons/bounding.png [new file with mode: 0644]
src/FeaturesPlugin/plugin-Features.xml
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.h [new file with mode: 0644]
src/PythonAPI/model/features/__init__.py

index 844baeb00a8ebe37a3c5d22a0fa70197384e8243..1ebde42d05d6db8df4dee34a40621aadb476402f 100644 (file)
@@ -53,6 +53,7 @@ SET(PROJECT_HEADERS
   FeaturesAPI_Defeaturing.h
   FeaturesAPI_PointCoordinates.h
   FeaturesAPI_GeometryCalculation.h
+  FeaturesAPI_BoundingBox.h
 )
 
 SET(PROJECT_SOURCES
@@ -88,6 +89,7 @@ SET(PROJECT_SOURCES
   FeaturesAPI_Defeaturing.cpp
   FeaturesAPI_PointCoordinates.cpp
   FeaturesAPI_GeometryCalculation.cpp
+  FeaturesAPI_BoundingBox.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 4a63d049b89615ef434b00e13a1fc46c555a0bbf..6f89d07cfc24be61610c7a8b460c0adcb228e380 100644 (file)
@@ -92,6 +92,7 @@
 %shared_ptr(FeaturesAPI_Copy)
 %shared_ptr(FeaturesAPI_ImportResult)
 %shared_ptr(FeaturesAPI_Defeaturing)
+%shared_ptr(FeaturesAPI_BoundingBox)
 
 
 %typecheck(SWIG_TYPECHECK_POINTER) std::pair<std::list<ModelHighAPI_Selection>, bool>, const std::pair<std::list<ModelHighAPI_Selection>, bool> & {
 %include "FeaturesAPI_ImportResult.h"
 %include "FeaturesAPI_PointCoordinates.h"
 %include "FeaturesAPI_GeometryCalculation.h"
+%include "FeaturesAPI_BoundingBox.h"
diff --git a/src/FeaturesAPI/FeaturesAPI_BoundingBox.cpp b/src/FeaturesAPI/FeaturesAPI_BoundingBox.cpp
new file mode 100644 (file)
index 0000000..d72009d
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright (C) 2018-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
+// 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 "FeaturesAPI_BoundingBox.h"
+
+#include <FeaturesPlugin_CreateBoundingBox.h>
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelHighAPI_Services.h>
+#include <ModelHighAPI_Tools.h>
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Selection.h>
+#include <ModelHighAPI_Tools.h>
+
+//=================================================================================================
+FeaturesAPI_BoundingBox::FeaturesAPI_BoundingBox(
+                                    const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//=================================================================================================
+FeaturesAPI_BoundingBox::FeaturesAPI_BoundingBox(
+                                    const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                    const ModelHighAPI_Selection& theObject)
+:ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(theObject, myobjectSelected);
+    execute();
+  }
+}
+
+//=================================================================================================
+FeaturesAPI_BoundingBox::~FeaturesAPI_BoundingBox()
+{
+}
+
+//=================================================================================================
+void FeaturesAPI_BoundingBox::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionPtr anAttrObject;
+    anAttrObject = aBase->selection(FeaturesPlugin_CreateBoundingBox::OBJECT_ID());
+
+  theDumper << aBase << " = model.getBoundingBox(" << aDocName << ", " << anAttrObject;
+
+  theDumper << ")" << std::endl;
+}
+
+//=================================================================================================
+BoundingBoxPtr getBoundingBox(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const ModelHighAPI_Selection& theObject)
+{
+
+  FeaturePtr aFeature =
+      thePart->addFeature(FeaturesPlugin_CreateBoundingBox::ID());
+
+  BoundingBoxPtr aBoundingBox;
+
+  aBoundingBox.reset(new FeaturesAPI_BoundingBox(aFeature, theObject));
+
+  return aBoundingBox;
+}
+
diff --git a/src/FeaturesAPI/FeaturesAPI_BoundingBox.h b/src/FeaturesAPI/FeaturesAPI_BoundingBox.h
new file mode 100644 (file)
index 0000000..cc45aa4
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2018-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
+// 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
+//
+
+#ifndef FeaturesAPI_BoundingBox_H_
+#define FeaturesAPI_BoundingBox_H_
+
+#include "FeaturesAPI.h"
+
+#include "FeaturesPlugin_CreateBoundingBox.h"
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+#include <memory>
+
+class ModelAPI_Document;
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_NormalToFace
+/// \ingroup CPPHighAPI
+/// \brief Interface for NormalToface feature.
+class FeaturesAPI_BoundingBox: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_BoundingBox(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_BoundingBox(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                   const ModelHighAPI_Selection& theObject);
+
+  /// Destructor.
+  FEATURESAPI_EXPORT
+  virtual ~FeaturesAPI_BoundingBox();
+
+  INTERFACE_1(FeaturesPlugin_CreateBoundingBox::ID(),
+              objectSelected, FeaturesPlugin_CreateBoundingBox::OBJECT_ID(),
+              ModelAPI_AttributeSelection, /** object selected*/)
+
+  /// Dump wrapped feature
+  FEATURESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+};
+
+/// Pointer on the NormalToface object.
+typedef std::shared_ptr<FeaturesAPI_BoundingBox> BoundingBoxPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief get the bounding Box
+/// \param thePart the part
+/// \param theobject the object selected
+FEATURESAPI_EXPORT
+BoundingBoxPtr getBoundingBox(const std::shared_ptr<ModelAPI_Document>& thePart,
+                              const ModelHighAPI_Selection& theObject);
+
+#endif // FeaturesAPI_BoundingBox_H_
index 1ad19edc162025c00261c70ff8fc02af74a0c9f7..6bd15c3c02a3aa89cca7e66f1265dd0e2ba25c1c 100644 (file)
@@ -55,5 +55,6 @@
   #include "FeaturesAPI_ImportResult.h"
   #include "FeaturesAPI_PointCoordinates.h"
   #include "FeaturesAPI_GeometryCalculation.h"
+  #include "FeaturesAPI_BoundingBox.h"
 
 #endif // FeaturesAPI_swig_H_
index 1e14a62895a6e28f66b10f4155ebb52b4caf123d..7a793e03b8e2f29646f82d2cc291c66fe0958337 100644 (file)
@@ -69,6 +69,9 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_VersionedChFi.h
     FeaturesPlugin_PointCoordinates.h
     FeaturesPlugin_GeometryCalculation.h
+    FeaturesPlugin_BoundingBox.h
+    FeaturesPlugin_CommonBoundingBox.h
+    FeaturesPlugin_CreateBoundingBox.h
 )
 
 SET(PROJECT_SOURCES
@@ -118,6 +121,9 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_VersionedChFi.cpp
     FeaturesPlugin_PointCoordinates.cpp
     FeaturesPlugin_GeometryCalculation.cpp
+    FeaturesPlugin_BoundingBox.cpp
+    FeaturesPlugin_CommonBoundingBox.cpp
+    FeaturesPlugin_CreateBoundingBox.cpp
 )
 
 SET(XML_RESOURCES
@@ -156,6 +162,8 @@ SET(XML_RESOURCES
   defeaturing_widget.xml
   point_coordinates_widget.xml
   geometry_calculation_widget.xml
+  bounding_box_widget.xml
+  create_bounding_box_widget.xml
 )
 
 SET(TEXT_RESOURCES
@@ -698,4 +706,5 @@ ADD_UNIT_TESTS(TestExtrusion.py
                Test20247.py
                TestPointCoordinates.py
                TestGeometryCalculation.py
+               TestBoundingBox.py
 )
diff --git a/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.cpp b/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.cpp
new file mode 100644 (file)
index 0000000..6e30b6f
--- /dev/null
@@ -0,0 +1,195 @@
+// Copyright (C) 2018-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
+// 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 "FeaturesPlugin_BoundingBox.h"
+
+#include <Config_PropManager.h>
+
+#include <FeaturesPlugin_CreateBoundingBox.h>
+
+#include <GeomAlgoAPI_BoundingBox.h>
+
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <iomanip>
+#include <sstream>
+
+//=================================================================================================
+FeaturesPlugin_BoundingBox::FeaturesPlugin_BoundingBox()
+{
+}
+
+//=================================================================================================
+void FeaturesPlugin_BoundingBox::initAttributes()
+{
+  // attribute for object selected
+  data()->addAttribute(OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+
+  // attributes for result message and values
+  data()->addAttribute(X_MIN_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(Y_MIN_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(Z_MIN_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(X_MAX_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(Y_MAX_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(Z_MAX_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(CREATEBOX_ID(), ModelAPI_AttributeBoolean::typeId());
+
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), X_MIN_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), Y_MIN_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), Z_MIN_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), X_MAX_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), Y_MAX_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), Z_MAX_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATEBOX_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), RESULT_VALUES_ID());
+
+  data()->addAttribute(RESULT_VALUES_ID(), ModelAPI_AttributeDoubleArray::typeId());
+
+  data()->realArray(RESULT_VALUES_ID())->setSize(6);
+
+}
+
+//=================================================================================================
+void FeaturesPlugin_BoundingBox::execute()
+{
+  updateValues();
+  createBoxByTwoPoints();
+
+  if (boolean(CREATEBOX_ID())->value()) {
+    if (!myCreateFeature.get())
+      createBox();
+    updateBox();
+  } else {
+    if (myCreateFeature.get()) {
+      myCreateFeature->eraseResults();
+      SessionPtr aSession = ModelAPI_Session::get();
+      DocumentPtr aDoc =  aSession->activeDocument();
+      aDoc->removeFeature(myCreateFeature);
+      myCreateFeature.reset();
+    }
+  }
+}
+
+//=================================================================================================
+void FeaturesPlugin_BoundingBox::attributeChanged(const std::string& theID)
+{
+  if (theID == OBJECT_ID()) {
+    if (myCreateFeature.get())
+      updateBox();
+  }
+}
+
+//=================================================================================================
+AttributePtr FeaturesPlugin_BoundingBox::attributResultValues()
+{
+   return attribute(RESULT_VALUES_ID());
+}
+
+//=================================================================================================
+void FeaturesPlugin_BoundingBox::updateValues()
+{
+  AttributeSelectionPtr aSelection = selection(OBJECT_ID());
+  if (aSelection->isInitialized()) {
+    AttributeDoubleArrayPtr aValues =
+      std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+    std::stringstream streamxmin;
+    std::stringstream streamymin;
+    std::stringstream streamzmin;
+    std::stringstream streamxmax;
+    std::stringstream streamymax;
+    std::stringstream streamzmax;
+
+    GeomShapePtr aShape;
+    if (aSelection && aSelection->isInitialized()) {
+      aShape = aSelection->value();
+      if (!aShape && aSelection->context())
+        aShape = aSelection->context()->shape();
+    }
+
+    if (aShape && !aShape->isEqual(myShape)) {
+      double aXmin, aXmax, aYmin,aYmax,aZmin,aZmax;
+      std::string aError;
+      if (!GetBoundingBox(aShape,
+                          true,
+                          aXmin, aXmax,
+                          aYmin,aYmax,
+                          aZmin,aZmax,
+                          aError))
+          setError("Error in bounding box calculation :" +  aError);
+
+      myShape = aShape;
+      streamxmin << std::setprecision(14) << aXmin;
+      aValues->setValue(0, aXmin);
+      streamxmax << std::setprecision(14) << aXmax;
+      aValues->setValue(1, aXmax);
+      streamymin << std::setprecision(14) << aYmin;
+      aValues->setValue(2, aYmin);
+      streamymax << std::setprecision(14) << aYmax;
+      aValues->setValue(3, aYmax);
+      streamzmin << std::setprecision(14) << aZmin;
+      aValues->setValue(4, aZmin);
+      streamzmax << std::setprecision(14) << aZmax;
+      aValues->setValue(5, aZmax);
+      string(X_MIN_COORD_ID() )->setValue( "X = " +  streamxmin.str() );
+      string(Y_MIN_COORD_ID() )->setValue( "Y = " +  streamymin.str() );
+      string(Z_MIN_COORD_ID() )->setValue( "Z = " +  streamzmin.str() );
+      string(X_MAX_COORD_ID() )->setValue( "X = " +  streamxmax.str() );
+      string(Y_MAX_COORD_ID() )->setValue( "Y = " +  streamymax.str() );
+      string(Z_MAX_COORD_ID() )->setValue( "Z = " +  streamzmax.str() );
+    }
+  }
+}
+
+//=================================================================================================
+void FeaturesPlugin_BoundingBox::createBox()
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+
+  DocumentPtr aDoc =  aSession->activeDocument();
+
+  if (aDoc.get()) {
+    myCreateFeature = aDoc->addFeature(FeaturesPlugin_CreateBoundingBox::ID());
+  }
+}
+
+//=================================================================================================
+void FeaturesPlugin_BoundingBox::updateBox()
+{
+  myCreateFeature->boolean(FeaturesPlugin_CreateBoundingBox::COMPUTE_ID())->setValue(false);
+  myCreateFeature->selection(FeaturesPlugin_CreateBoundingBox::OBJECT_ID())
+                        ->setValue(selection(OBJECT_ID())->context(),
+                                   selection(OBJECT_ID())->value());
+
+  AttributeDoubleArrayPtr aValuesFeatures =
+    std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>
+                              (myCreateFeature->attribute(RESULT_VALUES_ID()));
+  AttributeDoubleArrayPtr aValues =
+    std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+  for (int anI=0; anI < 6; anI++)
+    aValuesFeatures->setValue(anI,aValues->value(anI));
+
+  myCreateFeature->execute();
+  myCreateFeature->boolean(FeaturesPlugin_CreateBoundingBox::COMPUTE_ID())->setValue(true);
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.h b/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.h
new file mode 100644 (file)
index 0000000..ef12a57
--- /dev/null
@@ -0,0 +1,140 @@
+// Copyright (C) 2018-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
+// 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
+//
+
+#ifndef FeaturesPlugin_BoundingBox_H_
+#define FeaturesPlugin_BoundingBox_H_
+
+#include <FeaturesPlugin_CommonBoundingBox.h>
+
+/// \class FeaturesPlugin_BoundingBox
+/// \ingroup Plugins
+/// \brief Feature to view the Bounding Box.
+
+class FeaturesPlugin_BoundingBox : public FeaturesPlugin_CommonBoundingBox
+{
+public:
+  /// Bounding box macro kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("BoundingBoxMacro");
+    return MY_ID;
+  }
+
+  /// Attribute name for object selected.
+  inline static const std::string& OBJECT_ID()
+  {
+    static const std::string MY_OBJECT_ID("main_object");
+    return MY_OBJECT_ID;
+  }
+
+  /// Attribute name for x coodinate.
+  inline static const std::string& X_MIN_COORD_ID()
+  {
+    static const std::string MY_X_MIN_COORD_ID("xmincoordinate");
+    return MY_X_MIN_COORD_ID;
+  }
+
+  /// Attribute name for y coodinate.
+  inline static const std::string& Y_MIN_COORD_ID()
+  {
+    static const std::string MY_Y_MIN_COORD_ID("ymincoordinate");
+    return MY_Y_MIN_COORD_ID;
+  }
+
+  /// Attribute name for z coodinate.
+  inline static const std::string& Z_MIN_COORD_ID()
+  {
+    static const std::string MY_Z_MIN_COORD_ID("zmincoordinate");
+    return MY_Z_MIN_COORD_ID;
+  }
+
+  /// Attribute name for x max coodinate.
+  inline static const std::string& X_MAX_COORD_ID()
+  {
+    static const std::string MY_X_MAX_COORD_ID("xmaxcoordinate");
+    return MY_X_MAX_COORD_ID;
+  }
+
+  /// Attribute name for y max coodinate.
+  inline static const std::string& Y_MAX_COORD_ID()
+  {
+    static const std::string MY_Y_MAX_COORD_ID("ymaxcoordinate");
+    return MY_Y_MAX_COORD_ID;
+  }
+
+  /// Attribute name for z max coodinate.
+  inline static const std::string& Z_MAX_COORD_ID()
+  {
+    static const std::string MY_Z_MAX_COORD_ID("zmaxcoordinate");
+    return MY_Z_MAX_COORD_ID;
+  }
+
+  /// Attribute name for checkbox create box.
+  inline static const std::string& CREATEBOX_ID()
+  {
+    static const std::string MY_CREATEBOX_ID("createbox");
+    return MY_CREATEBOX_ID;
+  }
+
+  /// Attribute name for values of result.
+  inline static const std::string& RESULT_VALUES_ID()
+  {
+    static const std::string MY_RESULT_VALUES_ID("result_values");
+    return MY_RESULT_VALUES_ID;
+  }
+
+  /// \return the kind of a feature.
+  virtual const std::string& getKind()
+  {
+    return ID();
+  }
+
+  /// Performs the algorithm and stores results it in the data structure.
+  FEATURESPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Called on change of any argument-attribute of this object
+  /// \param theID identifier of changed attribute
+  FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+  /// Reimplemented from ModelAPI_Feature::isMacro(). Returns true.
+  FEATURESPLUGIN_EXPORT virtual bool isMacro() const { return true; }
+
+  /// Use plugin manager for features creation
+  FeaturesPlugin_BoundingBox();
+
+private:
+  /// Return Attribut values of result.
+  virtual AttributePtr attributResultValues();
+
+  /// Update values displayed.
+  void updateValues();
+  /// Create Box
+  void createBox();
+  /// Update Box
+  void updateBox();
+
+  /// Feature to create box
+  FeaturePtr myCreateFeature;
+
+};
+
+#endif
diff --git a/src/FeaturesPlugin/FeaturesPlugin_CommonBoundingBox.cpp b/src/FeaturesPlugin/FeaturesPlugin_CommonBoundingBox.cpp
new file mode 100644 (file)
index 0000000..9a3784a
--- /dev/null
@@ -0,0 +1,115 @@
+// Copyright (C) 2018-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
+// 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 "FeaturesPlugin_CommonBoundingBox.h"
+
+#include <ModelAPI_AttributeDoubleArray.h>
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+#include <GeomAPI_Vertex.h>
+
+#include <GeomAlgoAPI_BoundingBox.h>
+#include <GeomAlgoAPI_PointBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <Config_PropManager.h>
+
+#include <iomanip>
+#include <sstream>
+
+
+
+//=================================================================================================
+void FeaturesPlugin_CommonBoundingBox::createBoxByTwoPoints()
+{
+  AttributeDoubleArrayPtr aValues =
+      std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attributResultValues());
+
+  SessionPtr aSession = ModelAPI_Session::get();
+
+  DocumentPtr aDoc =  aSession->activeDocument();
+
+  GeomVertexPtr vertexFirst =
+          GeomAlgoAPI_PointBuilder::vertex(aValues->value(0),
+                                           aValues->value(2),
+                                           aValues->value(4));
+
+  GeomVertexPtr  vertexSecond =
+          GeomAlgoAPI_PointBuilder::vertex(aValues->value(1),
+                                           aValues->value(3),
+                                           aValues->value(5));
+
+
+  std::shared_ptr<GeomAlgoAPI_Box> aBoxAlgo;
+
+
+  aBoxAlgo = std::shared_ptr<GeomAlgoAPI_Box>(
+                          new GeomAlgoAPI_Box(vertexFirst->point(),vertexSecond->point()));
+
+
+  // These checks should be made to the GUI for the feature but
+  // the corresponding validator does not exist yet.
+  if (!aBoxAlgo->check()) {
+    setError(aBoxAlgo->getError());
+    return;
+  }
+
+  // Build the box
+  aBoxAlgo->build();
+
+  // Check if the creation of the box
+  if (!aBoxAlgo->isDone()) {
+    // The error is not displayed in a popup window. It must be in the message console.
+    setError(aBoxAlgo->getError());
+    return;
+  }
+  if (!aBoxAlgo->checkValid("Box builder with two points")) {
+    // The error is not displayed in a popup window. It must be in the message console.
+    setError(aBoxAlgo->getError());
+    return;
+  }
+
+  int aResultIndex = 0;
+  ResultBodyPtr aResultBox = document()->createBody(data(), aResultIndex);
+  loadNamingDS(aBoxAlgo, aResultBox);
+  setResult(aResultBox, aResultIndex);
+}
+
+//=================================================================================================
+void FeaturesPlugin_CommonBoundingBox::loadNamingDS(std::shared_ptr<GeomAlgoAPI_Box> theBoxAlgo,
+                                        std::shared_ptr<ModelAPI_ResultBody> theResultBox)
+{
+  // Load the result
+  theResultBox->store(theBoxAlgo->shape());
+
+  // Prepare the naming
+  theBoxAlgo->prepareNamingFaces();
+
+  // Insert to faces
+  std::map< std::string, std::shared_ptr<GeomAPI_Shape> > listOfFaces =
+    theBoxAlgo->getCreatedFaces();
+  for (std::map< std::string, std::shared_ptr<GeomAPI_Shape> >::iterator it = listOfFaces.begin();
+       it != listOfFaces.end();
+       ++it) {
+    theResultBox->generated((*it).second, (*it).first);
+  }
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_CommonBoundingBox.h b/src/FeaturesPlugin/FeaturesPlugin_CommonBoundingBox.h
new file mode 100644 (file)
index 0000000..c28392d
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2018-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
+// 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
+//
+
+#ifndef FeaturesPlugin_CommonBoundingBox_H_
+#define FeaturesPlugin_CommonBoundingBox_H_
+
+#include "FeaturesPlugin.h"
+#include <ModelAPI_Feature.h>
+
+#include <GeomAlgoAPI_Box.h>
+
+#include <GeomAPI_IPresentable.h>
+#include <GeomAPI_IScreenParams.h>
+
+#include <ModelAPI_Attribute.h>
+
+/// \class FeaturesPlugin_CommonBoundingBox
+/// \ingroup Plugins
+/// \brief Feature to view the Bounding Box.
+
+class FeaturesPlugin_CommonBoundingBox : public ModelAPI_Feature
+{
+public:
+  /// Performs the algorithm and stores results it in the data structure.
+  FEATURESPLUGIN_EXPORT virtual void execute(){};
+
+  /// Return Attribut values of result.
+  virtual AttributePtr attributResultValues() = 0;
+
+protected:
+  FeaturesPlugin_CommonBoundingBox() {}
+
+  /// Create box with two points
+  void createBoxByTwoPoints();
+
+  /// Create namming
+  void loadNamingDS(std::shared_ptr<GeomAlgoAPI_Box> theBoxAlgo,
+                    std::shared_ptr<ModelAPI_ResultBody> theResultBox);
+
+  GeomShapePtr myShape;
+};
+
+#endif
diff --git a/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.cpp b/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.cpp
new file mode 100644 (file)
index 0000000..f59d98b
--- /dev/null
@@ -0,0 +1,158 @@
+// Copyright (C) 2018-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
+// 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 "FeaturesPlugin_CreateBoundingBox.h"
+
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeBoolean.h>
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAlgoAPI_BoundingBox.h>
+
+#include <Config_PropManager.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <iomanip>
+#include <sstream>
+
+//=================================================================================================
+FeaturesPlugin_CreateBoundingBox::FeaturesPlugin_CreateBoundingBox()
+{
+}
+
+//=================================================================================================
+void FeaturesPlugin_CreateBoundingBox::initAttributes()
+{
+  // attribute for object selected
+  data()->addAttribute(OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+
+  // attributes for result message and values
+  data()->addAttribute(X_MIN_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(Y_MIN_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(Z_MIN_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(X_MAX_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(Y_MAX_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(Z_MAX_COORD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(COMPUTE_ID(), ModelAPI_AttributeBoolean::typeId());
+
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), X_MIN_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), Y_MIN_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), Z_MIN_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), X_MAX_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), Y_MAX_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), Z_MAX_COORD_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), COMPUTE_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_ID());
+  data()->addAttribute(RESULT_VALUES_ID(), ModelAPI_AttributeDoubleArray::typeId());
+
+  data()->realArray(RESULT_VALUES_ID())->setSize(6);
+  data()->boolean(COMPUTE_ID())->setValue(true);
+}
+
+//=================================================================================================
+void FeaturesPlugin_CreateBoundingBox::execute()
+{
+  updateValues();
+  createBoxByTwoPoints();
+}
+
+//=================================================================================================
+void FeaturesPlugin_CreateBoundingBox::attributeChanged(const std::string& theID)
+{
+}
+
+//=================================================================================================
+void FeaturesPlugin_CreateBoundingBox::updateValues()
+{
+  AttributeSelectionPtr aSelection = selection(OBJECT_ID());
+  AttributeDoubleArrayPtr aValues =
+      std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+
+  if (aSelection->isInitialized()) {
+    std::stringstream streamxmin;
+    std::stringstream streamymin;
+    std::stringstream streamzmin;
+    std::stringstream streamxmax;
+    std::stringstream streamymax;
+    std::stringstream streamzmax;
+
+    GeomShapePtr aShape;
+    if (aSelection && aSelection->isInitialized()) {
+      aShape = aSelection->value();
+      if (!aShape && aSelection->context())
+        aShape = aSelection->context()->shape();
+    }
+
+    AttributeBooleanPtr anIsCompute = boolean(COMPUTE_ID());
+    if (!anIsCompute->value()) {
+      myShape = aShape;
+      anIsCompute->setValue(true);
+    }
+
+    if (aShape && !aShape->isEqual(myShape)) {
+      double aXmin, aXmax, aYmin,aYmax,aZmin,aZmax;
+      std::string aError;
+      if (!GetBoundingBox(aShape,
+                          true,
+                          aXmin, aXmax,
+                          aYmin,aYmax,
+                          aZmin,aZmax,
+                          aError))
+          setError("Error in bounding box calculation :" +  aError);
+      myShape = aShape;
+      streamxmin << std::setprecision(14) << aXmin;
+      aValues->setValue(0, aXmin);
+      streamxmax << std::setprecision(14) << aXmax;
+      aValues->setValue(1, aXmax);
+      streamymin << std::setprecision(14) << aYmin;
+      aValues->setValue(2, aYmin);
+      streamymax << std::setprecision(14) << aYmax;
+      aValues->setValue(3, aYmax);
+      streamzmin << std::setprecision(14) << aZmin;
+      aValues->setValue(4, aZmin);
+      streamzmax << std::setprecision(14) << aZmax;
+      aValues->setValue(5, aZmax);
+    } else {
+      streamxmin << std::setprecision(14) << aValues->value(0);
+      streamxmax << std::setprecision(14) << aValues->value(1);
+      streamymin << std::setprecision(14) << aValues->value(2);
+      streamymax << std::setprecision(14) << aValues->value(3);
+      streamzmin << std::setprecision(14) << aValues->value(4);
+      streamzmax << std::setprecision(14) << aValues->value(5);
+    }
+
+    string(X_MIN_COORD_ID() )->setValue( "X = " +  streamxmin.str() );
+    string(Y_MIN_COORD_ID() )->setValue( "Y = " +  streamymin.str() );
+    string(Z_MIN_COORD_ID() )->setValue( "Z = " +  streamzmin.str() );
+    string(X_MAX_COORD_ID() )->setValue( "X = " +  streamxmax.str() );
+    string(Y_MAX_COORD_ID() )->setValue( "Y = " +  streamymax.str() );
+    string(Z_MAX_COORD_ID() )->setValue( "Z = " +  streamzmax.str() );
+  }
+}
+
+//=================================================================================================
+AttributePtr FeaturesPlugin_CreateBoundingBox::attributResultValues()
+{
+   return attribute(RESULT_VALUES_ID());
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.h b/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.h
new file mode 100644 (file)
index 0000000..6884ac0
--- /dev/null
@@ -0,0 +1,130 @@
+// Copyright (C) 2018-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
+// 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
+//
+
+#ifndef FeaturesPlugin_CreateBoundingBox_H_
+#define FeaturesPlugin_CreateBoundingBox_H_
+
+#include <FeaturesPlugin_CommonBoundingBox.h>
+
+/// \class FeaturesPlugin_BoundingBox
+/// \ingroup Plugins
+/// \brief Feature to view the Bounding Box.
+
+class FeaturesPlugin_CreateBoundingBox : public FeaturesPlugin_CommonBoundingBox
+{
+public:
+  /// Bounding box kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("BoundingBox");
+    return MY_ID;
+  }
+
+  /// Attribute name for object selected.
+  inline static const std::string& OBJECT_ID()
+  {
+    static const std::string MY_OBJECT_ID("main_object");
+    return MY_OBJECT_ID;
+  }
+
+  /// Attribute name for x coodinate.
+  inline static const std::string& X_MIN_COORD_ID()
+  {
+    static const std::string MY_X_MIN_COORD_ID("xmincoordinate");
+    return MY_X_MIN_COORD_ID;
+  }
+
+  /// Attribute name for y coodinate.
+  inline static const std::string& Y_MIN_COORD_ID()
+  {
+    static const std::string MY_Y_MIN_COORD_ID("ymincoordinate");
+    return MY_Y_MIN_COORD_ID;
+  }
+
+  /// Attribute name for z coodinate.
+  inline static const std::string& Z_MIN_COORD_ID()
+  {
+    static const std::string MY_Z_MIN_COORD_ID("zmincoordinate");
+    return MY_Z_MIN_COORD_ID;
+  }
+
+  /// Attribute name for x max coodinate.
+  inline static const std::string& X_MAX_COORD_ID()
+  {
+    static const std::string MY_X_MAX_COORD_ID("xmaxcoordinate");
+    return MY_X_MAX_COORD_ID;
+  }
+
+  /// Attribute name for y max coodinate.
+  inline static const std::string& Y_MAX_COORD_ID()
+  {
+    static const std::string MY_Y_MAX_COORD_ID("ymaxcoordinate");
+    return MY_Y_MAX_COORD_ID;
+  }
+
+  /// Attribute name for z max coodinate.
+  inline static const std::string& Z_MAX_COORD_ID()
+  {
+    static const std::string MY_Z_MAX_COORD_ID("zmaxcoordinate");
+    return MY_Z_MAX_COORD_ID;
+  }
+
+  /// Attribute name for values of result.
+  inline static const std::string& RESULT_VALUES_ID()
+  {
+    static const std::string MY_RESULT_VALUES_ID("result_values");
+    return MY_RESULT_VALUES_ID;
+  }
+
+  /// Attribute name for indicate to compute the bounding box.
+  inline static const std::string& COMPUTE_ID()
+  {
+    static const std::string MY_COMPUTE_ID("compute");
+    return MY_COMPUTE_ID;
+  }
+
+  /// \return the kind of a feature.
+  virtual const std::string& getKind()
+  {
+    return ID();
+  }
+
+  /// Performs the algorithm and stores results it in the data structure.
+  FEATURESPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Called on change of any argument-attribute of this object
+  /// \param theID identifier of changed attribute
+  FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+  /// Return Attribut values of result.
+  FEATURESPLUGIN_EXPORT virtual AttributePtr attributResultValues();
+
+  /// Use plugin manager for features creation
+  FeaturesPlugin_CreateBoundingBox();
+
+private:
+  /// Update values displayed.
+  void updateValues();
+
+};
+
+#endif
index 8419057e24c8e54d51522416643debcf3b3fa572..d3332d14ffd1d2fc26fce64a9ae47fdd58a56307 100644 (file)
@@ -24,7 +24,9 @@
 #include <FeaturesPlugin_BooleanCommon.h>
 #include <FeaturesPlugin_BooleanSmash.h>
 #include <FeaturesPlugin_BooleanFill.h>
+#include <FeaturesPlugin_BoundingBox.h>
 #include <FeaturesPlugin_Chamfer.h>
+#include <FeaturesPlugin_CreateBoundingBox.h>
 #include <FeaturesPlugin_Defeaturing.h>
 #include <FeaturesPlugin_Extrusion.h>
 #include <FeaturesPlugin_ExtrusionCut.h>
@@ -203,6 +205,10 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new FeaturesPlugin_PointCoordinates);
   } else if (theFeatureID == FeaturesPlugin_GeometryCalculation::ID()) {
     return FeaturePtr(new FeaturesPlugin_GeometryCalculation);
+  } else if (theFeatureID == FeaturesPlugin_BoundingBox::ID()) {
+    return FeaturePtr(new FeaturesPlugin_BoundingBox);
+  } else if (theFeatureID == FeaturesPlugin_CreateBoundingBox::ID()) {
+    return FeaturePtr(new FeaturesPlugin_CreateBoundingBox);
   }
 
 
index ff2645663d07385590a993e1f792780c4f31052c..878c1f4d5b97b1bad9fdab6ec1d76f3155b3364f 100644 (file)
       <source>Geometry calculation</source>
       <translation>Calcul de la géométrie</translation>
     </message>
+    <message>
+      <source>Bounding box</source>
+      <translation>Boîte englobante</translation>
+    </message>
     <message>
       <source>Placement</source>
       <translation>Placement</translation>
     </message>
   </context>
 
+  <!-- Bounding Box -->
+  <context>
+    <name>BoundingBox</name>
+    <message>
+      <source>BoundingBox</source>
+      <translation>Boîte englobante</translation>
+    </message>
+    <message>
+      <source>Create box</source>
+      <translation>Créer la boîte</translation>
+    </message>
+  </context>
+  <context>
+    <name>BoundingBoxMacro</name>
+    <message>
+      <source>BoundingBox</source>
+      <translation>Boîte englobante</translation>
+    </message>
+    <message>
+      <source>Create box</source>
+      <translation>Créer la boîte</translation>
+    </message>
+  </context>
+
   <!-- Chamfer -->
   <context>
     <name>Chamfer</name>
       <translation>Deuxième direction</translation>
     </message>
   </context>
-  <!-- PointCoordinates -->
+
+  <!--Bounding box-->
   <context>
-    <name>PointCoordinates</name>
+    <name>BoundingBoxMacro</name>
     <message>
-      <source>Point coordinates</source>
-      <translation>Coordonnées d'un point</translation>
+      <source>Bounding box</source>
+      <translation>Boîte englobante</translation>
+    </message>
+  </context>
+  <context>
+    <name>BoundingBoxMacro:main_object</name>
+    <message>
+      <source>Object</source>
+      <translation>Objet</translation>
     </message>
   </context>
+  <context>
+  <name>BoundingBoxMacro:createbox</name>
+    <message>
+      <source>Create box</source>
+      <translation>Créer la boîte</translation>
+    </message>
+  </context>
+  <context>
+    <name>BoundingBox</name>
+    <message>
+      <source>Bounding box</source>
+      <translation>Boîte englobante</translation>
+    </message>
+  </context>
+  <context>
+    <name>BoundingBox:main_object</name>
+    <message>
+      <source>Object</source>
+      <translation>Objet</translation>
+    </message>
+  </context>
+
   <!--Geometry calculation-->
   <context>
     <name>GeometryCalculation</name>
       <translation>Volume = </translation>
     </message>
   </context>
+
   <!-- Measurement -->
   <context>
     <name>Measurement</name>
     </message>
   </context>
 
+  <!-- PointCoordinates -->
+  <context>
+    <name>PointCoordinates</name>
+    <message>
+      <source>Point coordinates</source>
+      <translation>Coordonnées d'un point</translation>
+    </message>
+  </context>
+
   <!-- Rotation -->
   <context>
     <name>Rotation</name>
diff --git a/src/FeaturesPlugin/Test/TestBoundingBox.py b/src/FeaturesPlugin/Test/TestBoundingBox.py
new file mode 100644 (file)
index 0000000..673445e
--- /dev/null
@@ -0,0 +1,81 @@
+# 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
+# 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
+#
+
+"""
+      Unit test of ...
+"""
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+
+
+import os
+import math
+
+from ModelAPI import *
+from salome.shaper import model
+
+
+__updated__ = "2020-11-12"
+
+
+#=========================================================================
+# test Bounding Box  
+#=========================================================================
+def test_Bounding_Box():
+
+    model.begin()
+    file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Step","screw.step")
+    partSet = model.moduleDocument()
+    Part_1 = model.addPart(partSet)
+    Part_1_doc = Part_1.document()
+    Import_1 = model.addImport(Part_1_doc,file_path)
+    model.do()
+    ### Create BoundingBox
+    BoundingBox_1 = model.getBoundingBox(Part_1_doc, model.selection("SOLID", "screw_1"))
+    model.end()
+
+    myDelta = 1e-6
+    Props = model.getGeometryCalculation(Part_1_doc,model.selection("SOLID", "BoundingBox_1_1"))
+
+    print(" Basic Properties:")
+    print(" Wires length: ", Props[0])
+    print(" Surface area: ", Props[1])
+    print(" Volume      : ", Props[2]) 
+    
+    aReflength = 0.32855301948678
+    aReslength = Props[0]
+    assert (math.fabs(aReslength - aReflength) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aReflength, aReslength)
+
+    aRefSurface = 0.0041640657342782
+    aResSurface = Props[1]
+    assert (math.fabs(aResSurface - aRefSurface) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aRefSurface, aResSurface)
+
+    aRefVolume = 1.6785355394103e-05
+    aResVolume = Props[2]
+    assert (math.fabs(aResVolume - aRefVolume) < myDelta), "The volume is wrong: expected = {0}, real = {1}".format(aRefVolume, aResVolume)
+
+    
+if __name__ == '__main__':
+
+    test_Bounding_Box()
+        
+    #=========================================================================
+    # End of test
+    #=========================================================================
diff --git a/src/FeaturesPlugin/bounding_box_widget.xml b/src/FeaturesPlugin/bounding_box_widget.xml
new file mode 100644 (file)
index 0000000..199c2a1
--- /dev/null
@@ -0,0 +1,22 @@
+<source>
+  <shape_selector id="main_object"
+                  label="Object"
+                  tooltip="Select a object"
+                  shape_types="vertex edge face solid compsolid compound object"
+                  default=""
+                  geometrical_selection="true">
+    <validator id="GeomValidators_ConstructionComposite"/>
+    <validator id="GeomValidators_ShapeType" parameters="vertex,line,edge,wire,face,shell,solid,compsolid,compound"/>
+  </shape_selector>
+  <groupbox title="Min">
+    <label id="xmincoordinate" isSelectable = "true"/>
+    <label id="ymincoordinate" isSelectable = "true"/>
+    <label id="zmincoordinate" isSelectable = "true"/>
+  </groupbox>
+  <groupbox title="Max">
+    <label id="xmaxcoordinate" isSelectable = "true"/>
+    <label id="ymaxcoordinate" isSelectable = "true"/>
+    <label id="zmaxcoordinate" isSelectable = "true"/>
+  </groupbox>
+  <boolvalue id="createbox" label="Create box" default="false"/>
+</source>
diff --git a/src/FeaturesPlugin/create_bounding_box_widget.xml b/src/FeaturesPlugin/create_bounding_box_widget.xml
new file mode 100644 (file)
index 0000000..39e494f
--- /dev/null
@@ -0,0 +1,21 @@
+<source>
+  <shape_selector id="main_object"
+                  label="Object"
+                  tooltip="Select a object"
+                  shape_types="vertex edge face solid compsolid compound object"
+                  default=""
+                  geometrical_selection="true">
+    <validator id="GeomValidators_ConstructionComposite"/>
+    <validator id="GeomValidators_ShapeType" parameters="vertex,line,edge,wire,face,shell,solid,compsolid,compound"/>
+  </shape_selector>
+  <groupbox title="Min">
+    <label id="xmincoordinate" isSelectable = "true"/>
+    <label id="ymincoordinate" isSelectable = "true"/>
+    <label id="zmincoordinate" isSelectable = "true"/>
+  </groupbox>
+  <groupbox title="Max">
+    <label id="xmaxcoordinate" isSelectable = "true"/>
+    <label id="ymaxcoordinate" isSelectable = "true"/>
+    <label id="zmaxcoordinate" isSelectable = "true"/>
+  </groupbox>
+</source>
index 23cfb1f5c4bedca923e999f59506428a972142b8..34e8fea427339345fec31c0820001e11f9c71f34 100644 (file)
@@ -12,6 +12,7 @@ Features plug-in provides a set of common topological operations. It implements
 
    booleanOperations.rst
    angularCopyFeature.rst
+   boundingBoxFeature.rst
    chamferFeature.rst
    copyFeature.rst
    defeaturingFeature.rst
diff --git a/src/FeaturesPlugin/doc/TUI_boundingBoxFeature.rst b/src/FeaturesPlugin/doc/TUI_boundingBoxFeature.rst
new file mode 100644 (file)
index 0000000..bb73b22
--- /dev/null
@@ -0,0 +1,11 @@
+
+  .. _tui_create_Bounding_Box:
+
+Create bounding box
+===================
+
+.. literalinclude:: examples/create_bounding_box.py 
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/create_bounding_box.py>`
diff --git a/src/FeaturesPlugin/doc/boundingBoxFeature.rst b/src/FeaturesPlugin/doc/boundingBoxFeature.rst
new file mode 100644 (file)
index 0000000..9a1222d
--- /dev/null
@@ -0,0 +1,51 @@
+.. |boundingBox.icon|    image:: images/bounding.png
+
+Bounding box
+============
+
+The **Bounding box** feature displays the bounding box of sub-elements of a geometrical object (shape).
+
+The property panel displays the coordinates of inferior (**Min**) and superior (**Max**) points.
+the resulting bounding box can be created via a dedicated check-box **Create Box**. If this last is checked corresponding result and feature would be created. 
+
+If the check-box **Create Box** isn't checked, **Apply** button does not generate any result and has the same effect as **Cancel** for this feature.  
+
+To display the bounding box in the active part:
+
+#. select in the Main Menu *Inspection - > Bounding box* item  or
+#. click |boundingBox.icon| **Bounding box** button in the toolbar
+
+Coordinates of the two points (inferior and superior) of the bounding box can be displayed for a selected object in the property panel : 
+
+.. figure:: images/boundingBoxPropertyPanel.png
+   :align: center
+
+   Bounding Box
+
+
+Input fields:
+
+- **Object** contains object selected in 3D OCC viewer or object browser. 
+- **Create box** check-box allow the creation of the bounding box (result and feature). 
+
+Note, the coordinates of two points displayed can be selected.
+
+**TUI Command**:
+
+.. py:function:: model.getBoundingBox(Part_doc, shape)
+    :param part: The current part object.
+    :param object: A shape in format *model.selection("Type", shape)*.
+    :return: Created bounding box.
+
+Result
+""""""
+
+Result of **Bounding box** where **Create box** is checked.
+
+.. figure:: images/BoundingBoxResult.png
+   :align: center
+
+   Object selected
+
+**See Also** a sample TUI Script of :ref:`tui_create_Bounding_Box` operation.
diff --git a/src/FeaturesPlugin/doc/examples/create_bounding_box.py b/src/FeaturesPlugin/doc/examples/create_bounding_box.py
new file mode 100644 (file)
index 0000000..d904006
--- /dev/null
@@ -0,0 +1,13 @@
+from salome.shaper import model
+import os
+
+model.begin()
+file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Step","screw.step")
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Import_1 = model.addImport(Part_1_doc,file_path)
+model.do()
+### Create BoundingBox
+BoundingBox_1 = model.getBoundingBox(Part_1_doc, model.selection("SOLID", "screw_1"))
+model.end()
diff --git a/src/FeaturesPlugin/doc/images/BoundingBoxResult.png b/src/FeaturesPlugin/doc/images/BoundingBoxResult.png
new file mode 100644 (file)
index 0000000..89eb127
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/BoundingBoxResult.png differ
diff --git a/src/FeaturesPlugin/doc/images/bounding.png b/src/FeaturesPlugin/doc/images/bounding.png
new file mode 100644 (file)
index 0000000..5a77a45
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/bounding.png differ
diff --git a/src/FeaturesPlugin/doc/images/boundingBoxPropertyPanel.png b/src/FeaturesPlugin/doc/images/boundingBoxPropertyPanel.png
new file mode 100644 (file)
index 0000000..0da9dda
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/boundingBoxPropertyPanel.png differ
diff --git a/src/FeaturesPlugin/icons/bounding.png b/src/FeaturesPlugin/icons/bounding.png
new file mode 100644 (file)
index 0000000..5a77a45
Binary files /dev/null and b/src/FeaturesPlugin/icons/bounding.png differ
index 2ee03397712e6b750fbd9f76916fd9fffefe6196..7fb18f31f027a7f84b76cc35129868e5f90fbf23 100644 (file)
                icon="icons/Features/geometryCalculation.png" helpfile="geometryCalculationFeature.html" abort_confirmation="false">
         <source path="geometry_calculation_widget.xml"/>
       </feature>
+      <feature id="BoundingBoxMacro" title="Bounding box" tooltip="Calculate the bounding box" auto_preview="true"
+               icon="icons/Features/bounding.png" helpfile="boundingBoxFeature.html">
+        <source path="bounding_box_widget.xml"/>
+      </feature>
+      <feature id="BoundingBox" title="Bounding box" tooltip="Calculate the bounding box" auto_preview="true"
+               icon="icons/Features/bounding.png" helpfile="boundingBoxFeature.html" internal="1">
+        <source path="create_bounding_box_widget.xml"/>
+      </feature>
       <feature id="Measurement" title="Measurement" tooltip="Calculate properties of objects"
                icon="icons/Features/measurement.png" helpfile="measurementFeature.html" abort_confirmation="false">
         <source path="measurement_widget.xml"/>
index 0aaebb2197613b74b6d33b7b3bb86519c4513013..e3ea735fbb2e6b9cb0ef3a654de23d3958c19c30 100644 (file)
@@ -89,6 +89,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_Chamfer.h
     GeomAlgoAPI_Defeaturing.h
     GeomAlgoAPI_GeometryCalculation.h
+    GeomAlgoAPI_BoundingBox.h
 )
 
 SET(PROJECT_SOURCES
@@ -157,6 +158,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_Chamfer.cpp
     GeomAlgoAPI_Defeaturing.cpp
     GeomAlgoAPI_GeometryCalculation.cpp
+    GeomAlgoAPI_BoundingBox.cpp
 )
 
 SET(PROJECT_LIBRARIES
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp
new file mode 100644 (file)
index 0000000..856b2eb
--- /dev/null
@@ -0,0 +1,395 @@
+// 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
+// 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 "GeomAlgoAPI_BoundingBox.h"
+
+#include <BRepBuilderAPI_Copy.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepTools.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepBndLib.hxx>
+#include <BRep_Builder.hxx>
+#include <Geom_Circle.hxx>
+#include <ShapeAnalysis.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS.hxx>
+#include <gp_Pln.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+#include <BRepExtrema_DistShapeShape.hxx>
+#include <ShapeFix_Shape.hxx>
+#include <BRepBuilderAPI_Sewing.hxx>
+#include <Standard_ErrorHandler.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRepClass3d_SolidClassifier.hxx>
+#include <Geom_SphericalSurface.hxx>
+#include <Geom_ToroidalSurface.hxx>
+
+/**
+* This function constructs and returns modified shape from the original one
+* for singular cases. It is used for the method GetMinDistanceSingular.
+*
+* \param theShape the original shape
+* \param theModifiedShape output parameter. The modified shape.
+* \param theAddDist output parameter. The added distance for modified shape.
+* \retval true if the shape is modified; false otherwise.
+*
+* \internal
+*/
+Standard_Boolean ModifyShape(const TopoDS_Shape  &theShape,
+                             TopoDS_Shape  &theModifiedShape,
+                             Standard_Real &theAddDist)
+{
+  TopExp_Explorer anExp;
+  int nbf = 0;
+
+  theAddDist = 0.;
+  theModifiedShape.Nullify();
+
+  for ( anExp.Init( theShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+    nbf++;
+    theModifiedShape = anExp.Current();
+  }
+  if(nbf==1) {
+    TopoDS_Shape sh = theShape;
+    while(sh.ShapeType()==TopAbs_COMPOUND) {
+      TopoDS_Iterator it(sh);
+      sh = it.Value();
+    }
+    Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(theModifiedShape));
+    if(S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
+       S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ||
+       S->IsUPeriodic()) {
+      const Standard_Boolean isShell =
+        (sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE);
+
+      if (!isShell && S->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
+        Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
+        gp_Pnt PC = SS->Location();
+          BRep_Builder B;
+          TopoDS_Vertex V;
+          B.MakeVertex(V,PC,1.e-7);
+          theModifiedShape = V;
+          theAddDist = SS->Radius();
+          return Standard_True;
+        }
+        if (!isShell && S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
+          Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
+          gp_Ax3 ax3 = TS->Position();
+          Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
+          BRep_Builder B;
+          TopoDS_Edge E;
+          B.MakeEdge(E,C,1.e-7);
+          theModifiedShape = E;
+          theAddDist = TS->MinorRadius();
+          return Standard_True;
+        }
+
+        // non solid case or any periodic surface (Mantis 22454).
+        double U1,U2,V1,V2;
+        // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88
+        //S->Bounds(U1,U2,V1,V2); changed by
+        ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(theModifiedShape),U1,U2,V1,V2);
+        // end of changes for 020677 (dmv)
+        Handle(Geom_RectangularTrimmedSurface) TrS1 =
+          new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
+        Handle(Geom_RectangularTrimmedSurface) TrS2 =
+          new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
+        TopoDS_Shape aMShape;
+
+        TopoDS_Face F1 = BRepBuilderAPI_MakeFace(TrS1, Precision::Confusion());
+        TopoDS_Face F2 = BRepBuilderAPI_MakeFace(TrS2, Precision::Confusion());
+
+        if (isShell) {
+          BRep_Builder B;
+          B.MakeCompound(TopoDS::Compound(aMShape));
+          B.Add(aMShape, F1);
+          B.Add(aMShape, F2);
+        } else {
+          // The original shape is a solid.
+          BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0);
+          aSewing.Add(F1);
+          aSewing.Add(F2);
+          aSewing.Perform();
+          aMShape = aSewing.SewedShape();
+          BRep_Builder B;
+          TopoDS_Solid aSolid;
+          B.MakeSolid(aSolid);
+          B.Add(aSolid, aMShape);
+          aMShape = aSolid;
+        }
+
+        Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
+        sfs->Init(aMShape);
+        sfs->SetPrecision(1.e-6);
+        sfs->SetMaxTolerance(1.0);
+        sfs->Perform();
+        theModifiedShape = sfs->Shape();
+        return Standard_True;
+      }
+    }
+
+    theModifiedShape = theShape;
+    return Standard_False;
+  }
+
+//=======================================================================
+// function : GetMinDistanceSingular
+//=======================================================================
+double GetMinDistanceSingular(const TopoDS_Shape& aSh1,
+                              const TopoDS_Shape& aSh2,
+                              gp_Pnt& Ptmp1, gp_Pnt& Ptmp2)
+{
+  TopoDS_Shape     tmpSh1;
+  TopoDS_Shape     tmpSh2;
+  Standard_Real    AddDist1 = 0.;
+  Standard_Real    AddDist2 = 0.;
+  Standard_Boolean IsChange1 = ModifyShape(aSh1, tmpSh1, AddDist1);
+  Standard_Boolean IsChange2 = ModifyShape(aSh2, tmpSh2, AddDist2);
+
+  if( !IsChange1 && !IsChange2 )
+    return -2.0;
+
+  BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2);
+  if (dst.IsDone()) {
+    double MinDist = 1.e9;
+    gp_Pnt PMin1, PMin2, P1, P2;
+    for (int i = 1; i <= dst.NbSolution(); i++) {
+      P1 = dst.PointOnShape1(i);
+      P2 = dst.PointOnShape2(i);
+      Standard_Real Dist = P1.Distance(P2);
+      if (MinDist > Dist) {
+        MinDist = Dist;
+        PMin1 = P1;
+        PMin2 = P2;
+      }
+    }
+    if(MinDist<1.e-7) {
+      Ptmp1 = PMin1;
+      Ptmp2 = PMin2;
+    }
+    else {
+      gp_Dir aDir(gp_Vec(PMin1,PMin2));
+      if( MinDist > (AddDist1+AddDist2) ) {
+        Ptmp1 = gp_Pnt(PMin1.X() + aDir.X()*AddDist1,
+                       PMin1.Y() + aDir.Y()*AddDist1,
+                       PMin1.Z() + aDir.Z()*AddDist1);
+        Ptmp2 = gp_Pnt(PMin2.X() - aDir.X()*AddDist2,
+                       PMin2.Y() - aDir.Y()*AddDist2,
+                       PMin2.Z() - aDir.Z()*AddDist2);
+        return (MinDist - AddDist1 - AddDist2);
+      }
+      else {
+        if( AddDist1 > 0 ) {
+          Ptmp1 = gp_Pnt(PMin1.X() + aDir.X()*AddDist1,
+                         PMin1.Y() + aDir.Y()*AddDist1,
+                         PMin1.Z() + aDir.Z()*AddDist1);
+          Ptmp2 = Ptmp1;
+        }
+        else {
+          Ptmp2 = gp_Pnt(PMin2.X() - aDir.X()*AddDist2,
+                         PMin2.Y() - aDir.Y()*AddDist2,
+                         PMin2.Z() - aDir.Z()*AddDist2);
+          Ptmp1 = Ptmp2;
+        }
+      }
+    }
+    double res = MinDist - AddDist1 - AddDist2;
+    if(res<0.) res = 0.0;
+    return res;
+  }
+  return -2.0;
+}
+
+//=======================================================================
+// function : GetMinDistance
+//=======================================================================
+Standard_Real GetMinDistance(const TopoDS_Shape& theShape1,
+                             const TopoDS_Shape& theShape2,
+                             gp_Pnt& thePnt1, gp_Pnt& thePnt2)
+{
+  Standard_Real aResult = 1.e9;
+
+  // Issue 0020231: A min distance bug with torus and vertex.
+  // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs
+
+  // which of shapes consists of only one vertex?
+  TopExp_Explorer exp1(theShape1,TopAbs_VERTEX), exp2(theShape2,TopAbs_VERTEX);
+  TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape();
+  TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape();
+  exp1.Next(); exp2.Next();
+  if ( exp1.More() ) V1.Nullify();
+  if ( exp2.More() ) V2.Nullify();
+  // vertex and container of solids
+  TopoDS_Shape V = V1.IsNull() ? V2 : V1;
+  TopoDS_Shape S = V1.IsNull() ? theShape1 : theShape2;
+  if ( !V.IsNull() ) {
+    // classify vertex against solids
+    gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) );
+    for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) {
+      BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6);
+      if ( classifier.State() == TopAbs_IN ) {
+        thePnt1 = p;
+        thePnt2 = p;
+        return 0.0;
+      }
+    }
+  }
+
+  aResult = GetMinDistanceSingular(theShape1, theShape2, thePnt1, thePnt2);
+
+
+  BRepExtrema_DistShapeShape dst (theShape1, theShape2);
+  if (dst.IsDone()) {
+    gp_Pnt P1, P2;
+
+    for (int i = 1; i <= dst.NbSolution(); i++) {
+      P1 = dst.PointOnShape1(i);
+      P2 = dst.PointOnShape2(i);
+
+      Standard_Real Dist = P1.Distance(P2);
+      if (aResult < 0 || aResult > Dist) {
+        aResult = Dist;
+        thePnt1 = P1;
+        thePnt2 = P2;
+      }
+    }
+  }
+
+  return aResult;
+}
+
+//=======================================================================
+// function : PreciseBoundingBox
+//=======================================================================
+Standard_Boolean PreciseBoundingBox
+                          (const TopoDS_Shape &theShape, Bnd_Box &theBox)
+{
+  if (theBox.IsVoid()) BRepBndLib::Add( theShape, theBox );
+  if (theBox.IsVoid()) return Standard_False;
+
+  Standard_Real aBound[6];
+  theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);
+
+  Standard_Integer i;
+  const gp_Pnt aMid(0.5*(aBound[1] + aBound[0]),  // XMid
+                    0.5*(aBound[3] + aBound[2]),  // YMid
+                    0.5*(aBound[5] + aBound[4])); // ZMid
+  const gp_XYZ aSize(aBound[1] - aBound[0],       // DX
+                     aBound[3] - aBound[2],       // DY
+                     aBound[5] - aBound[4]);      // DZ
+  const gp_Pnt aPnt[6] =
+    {
+      gp_Pnt(aBound[0] - (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMin
+      gp_Pnt(aBound[1] + (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMax
+      gp_Pnt(aMid.X(), aBound[2] - (aBound[3] - aBound[2]), aMid.Z()), // YMin
+      gp_Pnt(aMid.X(), aBound[3] + (aBound[3] - aBound[2]), aMid.Z()), // YMax
+      gp_Pnt(aMid.X(), aMid.Y(), aBound[4] - (aBound[5] - aBound[4])), // ZMin
+      gp_Pnt(aMid.X(), aMid.Y(), aBound[5] + (aBound[5] - aBound[4]))  // ZMax
+    };
+  const gp_Dir aDir[3] = { gp::DX(), gp::DY(), gp::DZ() };
+  const Standard_Real aPlnSize[3] =
+    {
+      0.5*Max(aSize.Y(), aSize.Z()), // XMin, XMax planes
+      0.5*Max(aSize.X(), aSize.Z()), // YMin, YMax planes
+      0.5*Max(aSize.X(), aSize.Y())  // ZMin, ZMax planes
+    };
+  gp_Pnt aPMin[2];
+
+  for (i = 0; i < 6; i++) {
+    const Standard_Integer iHalf = i/2;
+    const gp_Pln aPln(aPnt[i], aDir[iHalf]);
+    BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf],
+                                    -aPlnSize[iHalf], aPlnSize[iHalf]);
+
+    if (!aMkFace.IsDone()) {
+      return Standard_False;
+    }
+
+    TopoDS_Shape aFace = aMkFace.Shape();
+
+    // Get minimal distance between planar face and shape.
+    Standard_Real aMinDist = GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]);
+
+    if (aMinDist < 0.) {
+      return Standard_False;
+    }
+
+    aBound[i] = aPMin[1].Coord(iHalf + 1);
+  }
+
+  // Update Bounding box with the new values.
+  theBox.SetVoid();
+  theBox.Update(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);
+
+  return Standard_True;
+}
+
+//=================================================================================================
+bool GetBoundingBox(const std::shared_ptr<GeomAPI_Shape>& theShape,
+                    const bool thePrecise,
+                    Standard_Real& theXmin,Standard_Real& theXmax,
+                    Standard_Real& theYmin,Standard_Real& theYmax,
+                    Standard_Real& theZmin,Standard_Real& theZmax,
+                    std::string& theError)
+{
+  #ifdef _DEBUG
+  std::cout << "GetBoundingBox " << std::endl;
+  #endif
+
+  if (!theShape.get()) {
+    theError = "GetBoundingBox : An invalid argument";
+    return false;
+  }
+
+  TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
+
+  //Compute the parameters
+  Bnd_Box B;
+  try {
+    OCC_CATCH_SIGNALS;
+    BRepBuilderAPI_Copy aCopyTool (aShape);
+    if (!aCopyTool.IsDone()) {
+      theError = "GetBoundingBox Error: Bad shape detected";
+      return false;
+    }
+
+    aShape = aCopyTool.Shape();
+
+    // remove triangulation to obtain more exact boundaries
+    BRepTools::Clean(aShape);
+
+    BRepBndLib::Add(aShape, B);
+
+    if (thePrecise) {
+      if (!PreciseBoundingBox(aShape, B)) {
+        theError = "GetBoundingBox Error: Bounding box cannot be precised";
+        return false;
+      }
+    }
+
+    B.Get(theXmin, theYmin, theZmin, theXmax, theYmax, theZmax);
+  }
+  catch (Standard_Failure& aFail) {
+    theError = aFail.GetMessageString();
+    return false;
+  }
+  return true;
+}
+
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.h b/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.h
new file mode 100644 (file)
index 0000000..010c3a3
--- /dev/null
@@ -0,0 +1,45 @@
+// 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
+// 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
+//
+
+#ifndef GeomAlgoAPI_BoundingBox_H_
+#define GeomAlgoAPI_BoundingBox_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAPI_Shape.h>
+#include <Standard_TypeDef.hxx>
+
+/// get the boundin box of theshape.
+  /// \param theShape   the shape
+  /// \param thePrecise precise TRUE for precise computation; FALSE for fast one.
+  /// \param theXmin    X min of the box
+  /// \param theXmax    X max of the box
+  /// \param theYmin    Y min of the box
+  /// \param theYmax    Y max of the box
+  /// \param theZmin    Z min of the box
+  /// \param theZmax    Z max of the box
+  /// \param theError  error
+GEOMALGOAPI_EXPORT
+bool GetBoundingBox(const std::shared_ptr<GeomAPI_Shape>& theShape,
+                    const bool thePrecise,
+                    Standard_Real& theXmin,Standard_Real& theXmax,
+                    Standard_Real& theYmin,Standard_Real& theYmax,
+                    Standard_Real& theZmin,Standard_Real& theZmax,
+                    std::string& theError);
+
+#endif
index 84b7b656213016e7ec9e71aae5a3415bd90f2888..81ba70cc0aac225d059c6193ac70abb3c9c1a12a 100644 (file)
@@ -30,7 +30,7 @@ from FeaturesAPI import addRecover
 from FeaturesAPI import addFillet, addChamfer
 from FeaturesAPI import addFusionFaces
 from FeaturesAPI import measureLength, measureDistance, measureRadius, measureAngle
-from FeaturesAPI import getPointCoordinates, getGeometryCalculation
+from FeaturesAPI import getPointCoordinates, getGeometryCalculation, getBoundingBox
 from FeaturesAPI import addRemoveResults
 from FeaturesAPI import addCopy, addImportResult
 from FeaturesAPI import addDefeaturing