Salome HOME
Merge remote-tracking branch 'remotes/origin/CEA_2020_Lot2_1'
authorArtem Zhidkov <Artem.Zhidkov@opencascade.com>
Wed, 10 Feb 2021 08:19:45 +0000 (11:19 +0300)
committerArtem Zhidkov <Artem.Zhidkov@opencascade.com>
Wed, 10 Feb 2021 08:19:45 +0000 (11:19 +0300)
13 files changed:
1  2 
src/FeaturesAPI/FeaturesAPI_BoundingBox.cpp
src/FeaturesAPI/FeaturesAPI_GeometryCalculation.cpp
src/FeaturesAPI/FeaturesAPI_PointCoordinates.cpp
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_GeometryCalculation.cpp
src/FeaturesPlugin/FeaturesPlugin_PointCoordinates.cpp
src/FeaturesPlugin/Test/TestBoundingBox.py
src/FeaturesPlugin/Test/TestGeometryCalculation.py
src/FeaturesPlugin/Test/TestPointCoordinates.py
src/FeaturesPlugin/doc/examples/geometry_calculation.py
src/FeaturesPlugin/doc/examples/point_coordinates.py
src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp

index 0000000000000000000000000000000000000000,d72009d399bc6e3f0ca27dc986ce4bbc4bf7171f..ccd1e34539d3b0fe86923316a0553c4512702dcc
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,84 +1,83 @@@
 -
+ // 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;
+ }
index 0000000000000000000000000000000000000000,666489e0ad0276bf63c146b61c8a2bea7692f01a..3cce850fd086dbfc67f987cd698ba0705ed10c1a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,46 +1,45 @@@
 -
+ // 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_GeometryCalculation.h"
+ #include <FeaturesPlugin_GeometryCalculation.h>
+ #include <ModelAPI_AttributeDoubleArray.h>
+ #include <ModelHighAPI_Services.h>
+ #include <ModelHighAPI_Tools.h>
+ //=================================================================================================
+ std::list<double> getGeometryCalculation(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                          const ModelHighAPI_Selection& theObject)
+ {
+   FeaturePtr aPointCoodFeat = thePart->addFeature(FeaturesPlugin_GeometryCalculation::ID());
+   fillAttribute(theObject, aPointCoodFeat
+                       ->selection(FeaturesPlugin_GeometryCalculation::OBJECT_SELECTED_ID()));
+   std::list<double> res;
+   // obtain result
+   AttributeDoubleArrayPtr aResult = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
+       aPointCoodFeat->attribute(FeaturesPlugin_GeometryCalculation::RESULT_VALUES_ID()));
+   for (int i : {0, 1, 2})
+     res.push_back(aResult->value(i));
+   return res;
+ }
index 0000000000000000000000000000000000000000,8898319f7110645facee0ca30066070884537df4..8982268cb919dcbb0fddae9494a2c5ca70837d46
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,45 +1,44 @@@
 -
+ // 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_PointCoordinates.h"
+ #include <FeaturesPlugin_PointCoordinates.h>
+ #include <ModelAPI_AttributeDoubleArray.h>
+ #include <ModelHighAPI_Services.h>
+ #include <ModelHighAPI_Tools.h>
+ std::list<double> getPointCoordinates(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                       const ModelHighAPI_Selection& thePoint)
+ {
+   FeaturePtr aPointCoordFeat = thePart->addFeature(FeaturesPlugin_PointCoordinates::ID());
+   fillAttribute(thePoint, aPointCoordFeat
+                       ->selection(FeaturesPlugin_PointCoordinates::POINT_SELECTED_ID()));
+   std::list<double> res;
+   // obtain result
+   AttributeDoubleArrayPtr aResult = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
+       aPointCoordFeat->attribute(FeaturesPlugin_PointCoordinates::RESULT_VALUES_ID()));
+   for ( int i : {0, 1, 2})
+     res.push_back( aResult->value(i));
+   return res;
+ }
index ae6ccc7ceb29442c65895d7992c7afbe69a4b1ef,7a793e03b8e2f29646f82d2cc291c66fe0958337..e45e5136b8cbff76cb52f6e15bd2eb87dccbfb12
@@@ -688,5 -704,7 +704,8 @@@ ADD_UNIT_TESTS(TestExtrusion.p
                 Test20245_2.py
                 Test20245_3.py
                 Test20247.py
 +               Test22847.py
+                TestPointCoordinates.py
+                TestGeometryCalculation.py
+                TestBoundingBox.py
  )
index 0000000000000000000000000000000000000000,648e88bcde1c76ce40039353f0e3f00108f56d1e..106c01949e2e6f0bac8140848768aa296ee9c90b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,106 +1,105 @@@
 -
+ // 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_GeometryCalculation.h"
+ #include <ModelAPI_AttributeSelection.h>
+ #include <ModelAPI_AttributeDoubleArray.h>
+ #include <ModelAPI_AttributeString.h>
+ #include <ModelAPI_Data.h>
+ #include <ModelAPI_Session.h>
+ #include <Config_PropManager.h>
+ #include <GeomAPI_Shape.h>
+ #include <GeomAlgoAPI_ShapeTools.h>
+ #include <iomanip>
+ #include <sstream>
+ //=================================================================================================
+ FeaturesPlugin_GeometryCalculation::FeaturesPlugin_GeometryCalculation()
+ {
+ }
+ //=================================================================================================
+ void FeaturesPlugin_GeometryCalculation::initAttributes()
+ {
+   // attribute for point selected
+   data()->addAttribute(OBJECT_SELECTED_ID(), ModelAPI_AttributeSelection::typeId());
+   // attributes for result message and values
+   data()->addAttribute(LENGTH_ID(), ModelAPI_AttributeString::typeId());
+   data()->addAttribute(AREA_ID(), ModelAPI_AttributeString::typeId());
+   data()->addAttribute(VOLUME_ID(), ModelAPI_AttributeString::typeId());
+   data()->addAttribute(RESULT_VALUES_ID(), ModelAPI_AttributeDoubleArray::typeId());
+   data()->realArray(RESULT_VALUES_ID())->setSize(3);
+ }
+ //=================================================================================================
+ void FeaturesPlugin_GeometryCalculation::execute()
+ {
+ }
+ //=================================================================================================
+ void FeaturesPlugin_GeometryCalculation::attributeChanged(const std::string& theID)
+ {
+   if (theID == OBJECT_SELECTED_ID()) {
+     AttributeSelectionPtr aSelection = selection(OBJECT_SELECTED_ID());
+     AttributeDoubleArrayPtr aValues =
+       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+     std::stringstream streamL;
+     std::stringstream streamA;
+     std::stringstream streamV;
+     GeomShapePtr aShape;
+     if (aSelection && aSelection->isInitialized()) {
+       aShape = aSelection->value();
+       if (!aShape && aSelection->context())
+         aShape = aSelection->context()->shape();
+     }
+     if (aShape) {
+       double aTolerance = 0.0001;
+       double aLength;
+       double aSurfArea;
+       double aVolume;
+       aLength = GeomAlgoAPI_ShapeTools::length(aShape);
+       aSurfArea = GeomAlgoAPI_ShapeTools::area(aShape);
+       aVolume = GeomAlgoAPI_ShapeTools::volume(aShape);
+       streamL << std::setprecision(14) << aLength;
+       aValues->setValue(0, aLength);
+       streamA << std::setprecision(14) << aSurfArea;
+       aValues->setValue(1, aSurfArea);
+       streamV << std::setprecision(14) << aVolume;
+       aValues->setValue(2, aVolume);
+     }
+     string(LENGTH_ID())->setValue(streamL.str());
+     string(AREA_ID())->setValue(streamA.str());
+     string(VOLUME_ID())->setValue(streamV.str());
+   }
+ }
index 0000000000000000000000000000000000000000,a3aed9848145bd8588480dfe887e64180099efac..e01dd5faaa452ce2291ccc7c3203e5512d7c2b33
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,96 +1,95 @@@
 -
+ // 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_PointCoordinates.h"
+ #include <ModelAPI_AttributeSelection.h>
+ #include <ModelAPI_AttributeDoubleArray.h>
+ #include <ModelAPI_AttributeString.h>
+ #include <ModelAPI_Data.h>
+ #include <ModelAPI_Session.h>
+ #include <Config_PropManager.h>
+ #include <GeomAPI_Pnt.h>
+ #include <GeomAPI_Shape.h>
+ #include <GeomAPI_Vertex.h>
+ #include <GeomAlgoAPI_PointBuilder.h>
+ #include <iomanip>
+ #include <sstream>
+ FeaturesPlugin_PointCoordinates::FeaturesPlugin_PointCoordinates()
+ {
+ }
+ void FeaturesPlugin_PointCoordinates::initAttributes()
+ {
+   // attribute for point selected
+   data()->addAttribute(POINT_SELECTED_ID(), ModelAPI_AttributeSelection::typeId());
+   // attribute for x, y and z coordinates
+   data()->addAttribute(X_COORD_ID(), ModelAPI_AttributeString::typeId());
+   data()->addAttribute(Y_COORD_ID(), ModelAPI_AttributeString::typeId());
+   data()->addAttribute(Z_COORD_ID(), ModelAPI_AttributeString::typeId());
+   // attributes for result message and values
+   data()->addAttribute(RESULT_VALUES_ID(), ModelAPI_AttributeDoubleArray::typeId());
+   data()->realArray(RESULT_VALUES_ID())->setSize(3);
+ }
+ void FeaturesPlugin_PointCoordinates::execute()
+ {
+ }
+ void FeaturesPlugin_PointCoordinates::attributeChanged(const std::string& theID)
+ {
+   if (theID == POINT_SELECTED_ID()) {
+     AttributeSelectionPtr aSelection = selection(POINT_SELECTED_ID());
+     GeomShapePtr aShape;
+     GeomPointPtr aPoint;
+     if (aSelection && aSelection->isInitialized()) {
+       aShape = aSelection->value();
+       if (!aShape && aSelection->context())
+         aShape = aSelection->context()->shape();
+     }
+     AttributeDoubleArrayPtr aValues =
+       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+     std::stringstream streamx;
+     std::stringstream streamy;
+     std::stringstream streamz;
+     if (aShape) {
+       aPoint = GeomAlgoAPI_PointBuilder::point(aShape);
+       streamx << std::setprecision(14) << aPoint->x();
+       aValues->setValue(0, aPoint->x());
+       streamy << std::setprecision(14) << aPoint->y();
+       aValues->setValue(1, aPoint->y());
+       streamz << std::setprecision(14) << aPoint->z();
+       aValues->setValue(2, aPoint->z());
+     }
+     string(X_COORD_ID() )->setValue( "X = " +  streamx.str() );
+     string(Y_COORD_ID() )->setValue( "Y = " +  streamy.str() );
+     string(Z_COORD_ID() )->setValue( "Z = " +  streamz.str() );
+   }
+ }
index 0000000000000000000000000000000000000000,49f90f8e06854893c03dd687b7ccbddf5eaf13ff..dba0e1b2f019ff6b8ec9427ddcdfc5a5501ed0cb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,82 +1,82 @@@
 -# test Bounding Box  
+ # 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"
+ #=========================================================================
 -    print(" Volume      : ", Props[2]) 
 -    
++# test Bounding Box
+ #=========================================================================
+ def test_Bounding_Box():
+     model.begin()
+     partSet = model.moduleDocument()
+     Part_1 = model.addPart(partSet)
+     Part_1_doc = Part_1.document()
+     ### Create Cone
+     Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 5, 10)
+     model.do()
+     ### Create BoundingBox
+     BoundingBox_1 = model.getBoundingBox(Part_1_doc, model.selection("SOLID", "Cone_1_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 = 200
+     aReslength = Props[0]
+     assert (math.fabs(aReslength - aReflength) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aReflength, aReslength)
+     aRefSurface = 1600
+     aResSurface = Props[1]
+     assert (math.fabs(aResSurface - aRefSurface) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aRefSurface, aResSurface)
+     aRefVolume = 4000
+     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
+     #=========================================================================
index 0000000000000000000000000000000000000000,a3e1f1ec24e3683ae8b67edd872458743b59d4d9..11e6bdba54897a4544597c307575fa561ec764ec
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,80 +1,80 @@@
 -    
+ # 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 salome
+ import os
+ import math
+ from ModelAPI import *
+ from salome.shaper import model
+ __updated__ = "2020-11-12"
+ #=========================================================================
+ # test Geometry calculation
+ #=========================================================================
+ def test_Geometry_Calculation():
+     model.begin()
+     file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Brep","box1.brep")
+     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()
 -    print(" Volume      : ", Props[2]) 
 -    
++
+     myDelta = 1e-6
+     Props = model.getGeometryCalculation(Part_1_doc,model.selection("SOLID", "box1_1"))
+     print(" Geometry calculation:")
+     print(" Wires length: ", Props[0])
+     print(" Surface area: ", Props[1])
 -    
++    print(" Volume      : ", Props[2])
++
+     aReflength = 2400
+     aReslength = Props[0]
+     assert (math.fabs(aReslength - aReflength) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aReflength, aReslength)
+     aRefSurface = 240000
+     aResSurface = Props[1]
+     assert (math.fabs(aResSurface - aRefSurface) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aRefSurface, aResSurface)
+     aRefVolume = 8000000
+     aResVolume = Props[2]
+     assert (math.fabs(aResVolume - aRefVolume) < myDelta), "The volume is wrong: expected = {0}, real = {1}".format(aRefVolume, aResVolume)
 -        
++
+ if __name__ == '__main__':
+     test_Geometry_Calculation()
++
+     #=========================================================================
+     # End of test
+     #=========================================================================
index 0000000000000000000000000000000000000000,8b5c5b95492d547730b876b2dac9c6f500c758d9..f2b03fe92b7202f9b4211d483f7d09e819829fde
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,73 +1,73 @@@
 -    
+ # 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 salome.shaper import model
+ __updated__ = "2020-11-12"
+ #=========================================================================
+ # test get point coordinates
+ #=========================================================================
+ def test_point_coordinates():
+     model.begin()
+     file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Brep","box1.brep")
+     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()
 -    print(" z: ", coordinates[2]) 
++
+     myDelta = 1e-6
+     coordinates = model.getPointCoordinates(Part_1_doc,model.selection("VERTEX", "[box1_1/Shape_2][box1_1/Shape_3][box1_1/Shape_6]"))
+     print(" x: ", coordinates[0])
+     print(" y: ", coordinates[1])
 -    
++    print(" z: ", coordinates[2])
+     aRef = 200
+     aRes = coordinates[0]
+     assert (math.fabs(aRes - aRef) < myDelta), "The coordinate X is wrong: expected = {0}, real = {1}".format(aRef, aRes)
+     aRef = 0
+     aRes= coordinates[1]
+     assert (math.fabs(aRes - aRef) < myDelta), "The coordinate Y is wrong: expected = {0}, real = {1}".format(aRef, aRes)
+     aRef = 200
+     aRes = coordinates[2]
+     assert (math.fabs(aRes - aRef) < myDelta), "The coordinate Z is wrong: expected = {0}, real = {1}".format(aRef, aRes)
 -        
++
+ if __name__ == '__main__':
+     test_point_coordinates()
++
+     #=========================================================================
+     # End of test
+     #=========================================================================
index 0000000000000000000000000000000000000000,e1e340a3b3aa3c61512b618905bab29f89d5d029..2562da94d8c1fcc7fd8bf5c89667ee97b71f4f48
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,13 +1,13 @@@
 -print(" volume: ", properties[2]) 
+ import os
+ from salome.shaper import model
+ model.begin()
+ partSet = model.moduleDocument()
+ Part_1 = model.addPart(partSet)
+ Part_1_doc = Part_1.document()
+ Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+ properties = model.getGeometryCalculation(Part_1_doc,model.selection("SOLID", "Box_1_1"))
+ print(" length: ", properties[0])
+ print(" area: ", properties[1])
++print(" volume: ", properties[2])
+ model.end()
index 0000000000000000000000000000000000000000,d7e0e0eee689f5aa3b766704b91953e62127d37f..e8d902de6f19c4cc981afb911577d50b21a6bf53
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,13 +1,13 @@@
 -print(" z: ", coordinates[2]) 
+ import os
+ from salome.shaper import model
+ model.begin()
+ partSet = model.moduleDocument()
+ Part_1 = model.addPart(partSet)
+ Part_1_doc = Part_1.document()
+ Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+ coordinates = model.getPointCoordinates(Part_1_doc,model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Left][Box_1_1/Top]"))
+ print(" x: ", coordinates[0])
+ print(" y: ", coordinates[1])
++print(" z: ", coordinates[2])
+ model.end()
index 0000000000000000000000000000000000000000,157823bb9e788e2ba55989a72e1596c80e4c73e6..0589a8c105311b1ec3aded3692de82a33d2343b3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,391 +1,390 @@@
 -
+ // 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,
+                     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 (!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;
+ }