From: vsv Date: Mon, 20 Jun 2022 09:31:26 +0000 (+0300) Subject: bos #29469: [EDF] (2022-T1) Advanced geometry features: Detect type of shape X-Git-Tag: OPERA_v0.5-s990~2^2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=0781abb644b6bcb3716924df3325e7d10ba85587;p=modules%2Fshaper.git bos #29469: [EDF] (2022-T1) Advanced geometry features: Detect type of shape --- diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index fef2d06fc..eec42e1bd 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -96,6 +96,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_NormalToFace.h GeomAlgoAPI_Tube.h GeomAlgoAPI_ShapeInfo.h + GeomAlgoAPI_CanonicalRecognition.h ) SET(PROJECT_SOURCES @@ -171,6 +172,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_NormalToFace.cpp GeomAlgoAPI_Tube.cpp GeomAlgoAPI_ShapeInfo.cpp + GeomAlgoAPI_CanonicalRecognition.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI.i b/src/GeomAlgoAPI/GeomAlgoAPI.i index 153bf5b89..2524c6ce8 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI.i +++ b/src/GeomAlgoAPI/GeomAlgoAPI.i @@ -34,6 +34,7 @@ %include "std_string.i" %include "std_list.i" %include "std_shared_ptr.i" +%include "std_vector.i" %exceptionclass GeomAlgoAPI_Exception; @@ -48,6 +49,107 @@ } } +%typemap(out) std::list< std::shared_ptr< GeomAPI_Shape > >::value_type & { + $result = SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr(*$1)), $descriptor(std::shared_ptr *), SWIG_POINTER_OWN | 0 ); +} + +%template(ShapeList) std::list >; +%template(ValuesList) std::list; +%template(VectorOfDouble) std::vector; + +%typemap(in) std::vector& (std::vector temp) { + if (PyList_Check($input)) { + for (Py_ssize_t i = 0; i < PyList_Size($input); ++i) { + PyObject * item = PySequence_GetItem($input, i); + if (PyNumber_Check(item)) { + temp.push_back(PyFloat_AsDouble(item)); + } else { + PyErr_SetString(PyExc_TypeError, "argument must be double value."); + return NULL; + } + Py_DECREF(item); + } + $1 = &temp; + } else { + PyErr_SetString(PyExc_ValueError, "argument must be a list of double values."); + return NULL; + } +} + +%typemap(argout) std::vector& { + PyObject* outList = PyList_New(0); + int error; + std::vector::iterator it; + for ( it=$1->begin() ; it != $1->end(); it++ ) + { + error = PyList_Append(outList, PyFloat_FromDouble(*it)); + if (error) + SWIG_fail; + } + if ((!$result) || ($result == Py_None)) { + $result = outList; + } else { + PyObject *aObj1, *aObj2; + if (!PyTuple_Check($result)) { + PyObject* aObj = $result; + $result = PyTuple_New(1); + PyTuple_SetItem($result,0,aObj); + } + aObj2 = PyTuple_New(1); + PyTuple_SetItem(aObj2,0,outList); + aObj1 = $result; + $result = PySequence_Concat(aObj1,aObj2); + Py_DECREF(aObj1); + Py_DECREF(aObj2); + } +} + +%typecheck(SWIG_TYPECHECK_POINTER) std::vector, const std::vector& { + if (PyTuple_Check($input)) { + for (Py_ssize_t i = 0; i < PyTuple_Size($input); ++i) { + PyObject * item = PySequence_GetItem($input, i); + if (PyNumber_Check(item)) { + $1 = 1; + } else { + $1 = 0; + break; + } + Py_DECREF(item); + } + } else { + $1 = 0; + } +} + +%typemap(in) double& (double temp) { + if (PyFloat_Check($input)) { + temp = PyFloat_AsDouble($input); + $1 = &temp; + } else { + PyErr_SetString(PyExc_ValueError, "argument must be a double value."); + return NULL; + } +} + +%typemap(argout) double& { + if ((!$result) || ($result == Py_None)) { + $result = PyFloat_FromDouble(*$1); + } else { + PyObject *aObj1, *aObj2; + if (!PyTuple_Check($result)) { + PyObject* aObj = $result; + $result = PyTuple_New(1); + PyTuple_SetItem($result,0,aObj); + } + aObj2 = PyTuple_New(1); + PyTuple_SetItem(aObj2,0,PyFloat_FromDouble(*$1)); + aObj1 = $result; + $result = PySequence_Concat(aObj1,aObj2); + Py_DECREF(aObj1); + Py_DECREF(aObj2); + } +} + // shared pointers %shared_ptr(GeomAlgoAPI_Boolean) %shared_ptr(GeomAlgoAPI_Intersection) @@ -114,9 +216,4 @@ %include "GeomAlgoAPI_Box.h" %include "GeomAlgoAPI_MapShapesAndAncestors.h" %include "GeomAlgoAPI_ShapeInfo.h" - -%typemap(out) std::list< std::shared_ptr< GeomAPI_Shape > >::value_type & { - $result = SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr(*$1)), $descriptor(std::shared_ptr *), SWIG_POINTER_OWN | 0 ); -} -%template(ShapeList) std::list >; -%template(ValuesList) std::list; +%include "GeomAlgoAPI_CanonicalRecognition.h" diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_CanonicalRecognition.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_CanonicalRecognition.cpp new file mode 100644 index 000000000..dc935586d --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_CanonicalRecognition.cpp @@ -0,0 +1,441 @@ +// Copyright (C) 2014-2022 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_CanonicalRecognition.h" + +#include +// code from KERNEL_SRC/src/Basics/Basics_OCCTVersion.hxx +#ifdef OCC_VERSION_SERVICEPACK +# define OCC_VERSION_LARGE (OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8 | OCC_VERSION_SERVICEPACK) +#else +# ifdef OCC_VERSION_DEVELOPMENT +# define OCC_VERSION_LARGE ((OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8)-1) +# else +# define OCC_VERSION_LARGE (OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8) +# endif +#endif + +#if OCC_VERSION_LARGE > 0x07050303 +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include + +static bool isValidDirection(const std::vector& theDir) +{ + return (theDir.size() == 3) && (gp_Vec(theDir[0], theDir[1], theDir[2]).Magnitude() > 0.); +} + +bool GeomAlgoAPI_CanonicalRecognition::isPlane(const GeomShapePtr& theShape, double theTolerance, + std::vector& theNormal, std::vector& theOrigin) +{ + if (!theShape.get()) + return false; + + const TopoDS_Shape& aShape = theShape->impl(); + if (aShape.IsNull()) + return false; + + bool aIsValidNormal = isValidDirection(theNormal); + bool aIsValidOrigin = theOrigin.size() == 3; + gp_Pln aPln; + if (aIsValidNormal && aIsValidOrigin) { + aPln = gp_Pln(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2]), + gp_Dir(theNormal[0], theNormal[1], theNormal[2])); + } + + bool aResult = false; + +#if OCC_VERSION_LARGE > 0x07050303 + ShapeAnalysis_CanonicalRecognition aRecognition(aShape); + try { + if (aRecognition.GetStatus() == 0) + aResult = aRecognition.IsPlane(theTolerance, aPln); + } + catch (...) { + return false; + } +#endif + + gp_Pnt aOrig = aPln.Location(); + if (theOrigin.size() != 3) + theOrigin.resize(3); + theOrigin[0] = aOrig.X(); + theOrigin[1] = aOrig.Y(); + theOrigin[2] = aOrig.Z(); + + gp_Dir aNorm = aPln.Axis().Direction(); + if (theNormal.size() != 3) + theNormal.resize(3); + theNormal[0] = aNorm.X(); + theNormal[1] = aNorm.Y(); + theNormal[2] = aNorm.Z(); + + return aResult; +} + +bool GeomAlgoAPI_CanonicalRecognition::isSphere(const GeomShapePtr& theShape, double theTolerance, + std::vector& theOrigin, double& theRadius) +{ + if (!theShape.get()) + return false; + + const TopoDS_Shape& aShape = theShape->impl(); + if (aShape.IsNull()) + return false; + + bool aIsValidOrigin = theOrigin.size() == 3; + bool aIsValidRadius = theRadius > 0; + gp_Sphere aSphere; + if (aIsValidOrigin && aIsValidRadius) + { + aSphere.SetLocation(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2])); + aSphere.SetRadius(theRadius); + } + else + aSphere.SetRadius(1.0); + + bool aResult = false; + +#if OCC_VERSION_LARGE > 0x07050303 + ShapeAnalysis_CanonicalRecognition aRecognition(aShape); + try { + if (aRecognition.GetStatus() == 0) + aResult = aRecognition.IsSphere(theTolerance, aSphere); + } + catch (...) { + return false; + } +#endif + + gp_Pnt aLoc = aSphere.Location(); + if (theOrigin.size() != 3) + theOrigin.resize(3); + theOrigin[0] = aLoc.X(); + theOrigin[1] = aLoc.Y(); + theOrigin[2] = aLoc.Z(); + theRadius = aSphere.Radius(); + + return aResult; +} + +bool GeomAlgoAPI_CanonicalRecognition::isCone(const GeomShapePtr& theShape, double theTolerance, + std::vector& theAxis, std::vector& theApex, + double& theHalfAngle) +{ + if (!theShape.get()) + return false; + + const TopoDS_Shape& aShape = theShape->impl(); + if (aShape.IsNull()) + return false; + + bool aIsValidAxis = isValidDirection(theAxis); + bool aIsValidApex = theApex.size() == 3; + bool aIsValidAngle = theHalfAngle > 0; + gp_Cone aCone; + if (aIsValidAxis && aIsValidApex && aIsValidAngle) + { + gp_Pnt aLoc(theApex[0], theApex[1], theApex[2]); + gp_Ax3 aAx3(aLoc, gp_Dir(theAxis[0], theAxis[1], theAxis[2])); + aCone.SetPosition(aAx3); + } + else + aCone.SetRadius(1.0); + + bool aResult = false; + +#if OCC_VERSION_LARGE > 0x07050303 + ShapeAnalysis_CanonicalRecognition aRecognition(aShape); + try { + if (aRecognition.GetStatus() == 0) + aResult = aRecognition.IsCone(theTolerance, aCone); + } + catch (...) { + return false; + } +#endif + + gp_Dir aDir = aCone.Axis().Direction(); + if (theAxis.size() != 3) + theAxis.resize(3); + theAxis[0] = aDir.X(); + theAxis[1] = aDir.Y(); + theAxis[2] = aDir.Z(); + + gp_Pnt aApex = aCone.Apex(); + if (theApex.size() != 3) + theApex.resize(3); + theApex[0] = aApex.X(); + theApex[1] = aApex.Y(); + theApex[2] = aApex.Z(); + + theHalfAngle = aCone.SemiAngle(); + + return aResult; +} + +bool GeomAlgoAPI_CanonicalRecognition::isCylinder(const GeomShapePtr& theShape, double theTolerance, + std::vector& theAxis, std::vector& theOrigin, + double& theRadius) +{ + if (!theShape.get()) + return false; + + const TopoDS_Shape& aShape = theShape->impl(); + if (aShape.IsNull()) + return false; + + bool aIsValidAxis = isValidDirection(theAxis); + bool aIsValidOrigin = theOrigin.size() == 3; + bool aIsValidRadius = theRadius > 0; + gp_Cylinder aCylinder; + if (aIsValidAxis && aIsValidOrigin && aIsValidRadius) + { + gp_Pnt aLoc(theOrigin[0], theOrigin[0], theOrigin[0]); + gp_Ax3 aAx3(aLoc, gp_Dir(theAxis[0], theAxis[1], theAxis[2])); + aCylinder.SetPosition(aAx3); + aCylinder.SetRadius(theRadius); + } + else + aCylinder.SetRadius(1.0); + + bool aResult = false; + +#if OCC_VERSION_LARGE > 0x07050303 + ShapeAnalysis_CanonicalRecognition aRecognition(aShape); + try { + if (aRecognition.GetStatus() == 0) + aResult = aRecognition.IsCylinder(theTolerance, aCylinder); + } + catch (...) { + return false; + } +#endif + + gp_Dir aDir = aCylinder.Axis().Direction(); + if (theAxis.size() != 3) + theAxis.resize(3); + theAxis[0] = aDir.X(); + theAxis[1] = aDir.Y(); + theAxis[2] = aDir.Z(); + + gp_Pnt aLoc = aCylinder.Location(); + if (theOrigin.size() != 3) + theOrigin.resize(3); + theOrigin[0] = aLoc.X(); + theOrigin[1] = aLoc.Y(); + theOrigin[2] = aLoc.Z(); + + theRadius = aCylinder.Radius(); + + return aResult; +} + +bool GeomAlgoAPI_CanonicalRecognition::isLine(const GeomShapePtr& theEdge, double theTolerance, + std::vector& theDir, std::vector& theOrigin) +{ + if (!theEdge.get()) + return false; + + const TopoDS_Shape& aShape = theEdge->impl(); + if (aShape.IsNull()) + return false; + + bool aIsValidDir = isValidDirection(theDir); + bool aIsValidOrigin = theOrigin.size() == 3; + gp_Lin aLine; + if (aIsValidDir && aIsValidOrigin) + { + aLine.SetLocation(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2])); + aLine.SetDirection(gp_Dir(theDir[0], theDir[1], theDir[2])); + } + + bool aResult = false; + +#if OCC_VERSION_LARGE > 0x07050303 + ShapeAnalysis_CanonicalRecognition aRecognition(aShape); + try { + if (aRecognition.GetStatus() == 0) + aResult = aRecognition.IsLine(theTolerance, aLine); + } + catch (...) { + return false; + } +#endif + + gp_Pnt aLoc = aLine.Location(); + if (theOrigin.size() != 3) + theOrigin.resize(3); + theOrigin[0] = aLoc.X(); + theOrigin[1] = aLoc.Y(); + theOrigin[2] = aLoc.Z(); + + gp_Dir aDir = aLine.Direction(); + if (theDir.size() != 3) + theDir.resize(3); + theDir[0] = aDir.X(); + theDir[1] = aDir.Y(); + theDir[2] = aDir.Z(); + + return aResult; +} + +bool GeomAlgoAPI_CanonicalRecognition::isCircle(const GeomShapePtr& theEdge, double theTolerance, + std::vector& theNormal, std::vector& theOrigin, + double& theRadius) +{ + if (!theEdge.get()) + return false; + + const TopoDS_Shape& aShape = theEdge->impl(); + if (aShape.IsNull()) + return false; + + bool aIsValidNormal = isValidDirection(theNormal); + bool aIsValidOrigin = theOrigin.size() == 3; + bool aIsValidRadius = theRadius > 0; + gp_Circ aCircle; + if (aIsValidNormal && aIsValidOrigin && aIsValidRadius) + { + gp_Ax2 aAx2(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2]), + gp_Dir(theNormal[0], theNormal[1], theNormal[2])); + aCircle.SetPosition(aAx2); + aCircle.SetRadius(theRadius); + } + else + aCircle.SetRadius(1.0); + + bool aResult = false; + +#if OCC_VERSION_LARGE > 0x07050303 + ShapeAnalysis_CanonicalRecognition aRecognition(aShape); + try { + if (aRecognition.GetStatus() == 0) + aResult = aRecognition.IsCircle(theTolerance, aCircle); + } + catch (...) { + return false; + } +#endif + + gp_Pnt aLoc = aCircle.Location(); + if (theOrigin.size() != 3) + theOrigin.resize(3); + theOrigin[0] = aLoc.X(); + theOrigin[1] = aLoc.Y(); + theOrigin[2] = aLoc.Z(); + + gp_Dir aDir = aCircle.Axis().Direction(); + if (theNormal.size() != 3) + theNormal.resize(3); + theNormal[0] = aDir.X(); + theNormal[1] = aDir.Y(); + theNormal[2] = aDir.Z(); + theRadius = aCircle.Radius(); + return aResult; +} + +bool GeomAlgoAPI_CanonicalRecognition::isEllipse(const GeomShapePtr& theEdge, double theTolerance, + std::vector& theNormal, std::vector& theDirX, + std::vector& theOrigin, + double& theMajorRadius, double& theMinorRadius) +{ + if (!theEdge.get()) + return false; + + const TopoDS_Shape& aShape = theEdge->impl(); + if (aShape.IsNull()) + return false; + + bool aIsValidNormal = isValidDirection(theNormal); + bool aIsValidOrigin = theOrigin.size() == 3; + bool aIsValidDirX = isValidDirection(theDirX); + bool aIsValidRad1 = (theMajorRadius > 0) && (theMajorRadius > theMinorRadius); + bool aIsValidRad2 = (theMinorRadius > 0) && (theMajorRadius > theMinorRadius); + + gp_Elips aElips; + if (aIsValidNormal && aIsValidOrigin && aIsValidDirX && aIsValidRad1 && aIsValidRad2) + { + gp_Pnt anOrigin(theOrigin[0], theOrigin[1], theOrigin[2]); + gp_XYZ aNormal(theNormal[0], theNormal[1], theNormal[2]); + gp_XYZ aDirX(theDirX[0], theDirX[1], theDirX[2]); + Standard_Boolean isCollinear = + aNormal.CrossSquareMagnitude(aDirX) < Precision::SquareConfusion(); + gp_Ax2 aAx2 = isCollinear ? gp_Ax2(anOrigin, aNormal) : gp_Ax2(anOrigin, aNormal, aDirX); + aElips = gp_Elips(aAx2, theMajorRadius, theMinorRadius); + } + else + aElips.SetMajorRadius(1.0); + + bool aResult = false; + +#if OCC_VERSION_LARGE > 0x07050303 + ShapeAnalysis_CanonicalRecognition aRecognition(aShape); + try { + if (aRecognition.GetStatus() == 0) + aResult = aRecognition.IsEllipse(theTolerance, aElips); + } + catch (...) { + return false; + } +#endif + + gp_Pnt aLoc = aElips.Position().Location(); + if (theOrigin.size() != 3) + theOrigin.resize(3); + theOrigin[0] = aLoc.X(); + theOrigin[1] = aLoc.Y(); + theOrigin[2] = aLoc.Z(); + + gp_Dir aNorm = aElips.Position().Direction(); + if (theNormal.size() != 3) + theNormal.resize(3); + theNormal[0] = aNorm.X(); + theNormal[1] = aNorm.Y(); + theNormal[2] = aNorm.Z(); + + gp_Dir aDirX = aElips.Position().XDirection(); + if (theDirX.size() != 3) + theDirX.resize(3); + theDirX[0] = aDirX.X(); + theDirX[1] = aDirX.Y(); + theDirX[2] = aDirX.Z(); + + theMajorRadius = aElips.MajorRadius(); + theMinorRadius = aElips.MinorRadius(); + + return aResult; +} + +bool GeomAlgoAPI_CanonicalRecognition::isImplemented() +{ +#if OCC_VERSION_LARGE > 0x07050303 + return true; +#else + return false; +#endif +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_CanonicalRecognition.h b/src/GeomAlgoAPI/GeomAlgoAPI_CanonicalRecognition.h new file mode 100644 index 000000000..6efddfac9 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_CanonicalRecognition.h @@ -0,0 +1,85 @@ +// Copyright (C) 2014-2022 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_CanonicalRecognition_H_ +#define GeomAlgoAPI_CanonicalRecognition_H_ + +#include "GeomAlgoAPI.h" +#include + +#include + +class GeomAlgoAPI_CanonicalRecognition +{ +public: + /*! + * \brief Check if the shape is planar + */ + GEOMALGOAPI_EXPORT static bool isPlane(const GeomShapePtr& theShape, double theTolerance, + std::vector& theNormal, std::vector& theOrigin); + + /*! + * \brief Check if shape is spherical + */ + GEOMALGOAPI_EXPORT static bool isSphere(const GeomShapePtr& theShape, double theTolerance, + std::vector& theOrigin, double& theRadius); + + /*! + * \brief Check if shape is conical + */ + GEOMALGOAPI_EXPORT static bool isCone(const GeomShapePtr& theShape, double theTolerance, + std::vector& theAxis, std::vector& theApex, + double& theHalfAngle); + + /*! + * \brief Check if shape is cylinder + */ + GEOMALGOAPI_EXPORT static bool isCylinder(const GeomShapePtr& theShape, double theTolerance, + std::vector& theAxis, std::vector& theOrigin, + double& theRadius); + + /*! + * \brief Check if edge / wire is line + */ + GEOMALGOAPI_EXPORT static bool isLine(const GeomShapePtr& theEdge, double theTolerance, + std::vector& theDir, std::vector& theOrigin); + + /*! + * \brief Check if edge / wire is circle + */ + GEOMALGOAPI_EXPORT static bool isCircle(const GeomShapePtr& theEdge, double theTolerance, + std::vector& theNormal, std::vector& theOrigin, + double& theRadius); + + /*! + * \brief Check if edge / wire is ellipse + */ + GEOMALGOAPI_EXPORT static bool isEllipse(const GeomShapePtr& theEdge, double theTolerance, + std::vector& theNormal, std::vector& theDirX, + std::vector& theOrigin, + double& theMajorRadius, double& theMinorRadius); + + /*! + * \brief Check if the algorithm is implemented (Shaper is built with appropriate OCCT version) + */ + GEOMALGOAPI_EXPORT static bool isImplemented(); + +}; + +#endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h index a3be80588..d628b267a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h @@ -64,6 +64,7 @@ #include "GeomAlgoAPI_Symmetry.h" #include "GeomAlgoAPI_MapShapesAndAncestors.h" #include "GeomAlgoAPI_ShapeInfo.h" + #include "GeomAlgoAPI_CanonicalRecognition.h" #include #include diff --git a/src/PythonAPI/Test/TestCR.py b/src/PythonAPI/Test/TestCR.py new file mode 100644 index 000000000..634275b10 --- /dev/null +++ b/src/PythonAPI/Test/TestCR.py @@ -0,0 +1,118 @@ +# Copyright (C) 2014-2022 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 +# + +from salome.shaper import model, geom + +def isCRImplemented(): + CR = geom.CanonicalRecognition() + return CR.isImplemented() + +def GetShapeType(theShape): + CR = geom.CanonicalRecognition() + if CR.isLine(theShape, 0.1)[0]: + return "Line" + if CR.isPlane(theShape, 0.1)[0]: + if CR.isCircle(theShape, 0.1)[0]: + return ("Plane","Circle") + if CR.isEllipse(theShape, 0.1)[0]: + return ("Plane","Ellipse") + return "Plane" + if CR.isSphere(theShape, 0.1)[0]: + return "Sphere" + if CR.isCone(theShape, 0.1)[0]: + return "Cone" + if CR.isCylinder(theShape, 0.1)[0]: + return "Cylinder" + return "Not defined" + + +model.begin() +partSet = model.moduleDocument() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +### Create Cylinder +Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10) + +### Create Shell +Plane_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Cylinder_1_1/Face_2")]) + +### Create Recover +Recover_1 = model.addRecover(Part_1_doc, Plane_1, [Cylinder_1.result()]) + +### Create Shell +Shell_2 = model.addShell(Part_1_doc, [model.selection("FACE", "Recover_1_1/Modified_Face&Cylinder_1_1/Face_1")]) + +### Create Wire +Circle_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "[Recover_1_1/Modified_Face&Cylinder_1_1/Face_1][new_weak_name_2]")], False) + +### Create Recover +Recover_2 = model.addRecover(Part_1_doc, Circle_1, [Shell_2.result()]) + +### Create Edge +Line_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "(Recover_2_1/Modified_Edge&Wire_1_1/Edge)")], False) + +### Create Recover +Cylinder_3 = model.addRecover(Part_1_doc, Line_1, [Recover_2.result()]) + +### Create Sphere +Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), 10) +SphereShell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Sphere_1_1/Face_1")]) + +### Create Cone +Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 0, 10) +ConeShell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Cone_1_1/Face_1")]) + +### Create Sketch +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) + +### Create SketchProjection +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() + +### Create SketchEllipse +SketchEllipse_1 = Sketch_1.addEllipse(-37.39690313669599, -52.92905511857006, 61.08141071866921, -16.40734649833807, 41.5747486523393) +[SketchPoint_2, SketchPoint_3, SketchPoint_4, SketchPoint_5, SketchPoint_6, SketchPoint_7, SketchPoint_8, SketchLine_1, SketchLine_2] = SketchEllipse_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux") +model.do() + +### Create Wire +EllipseWire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/SketchEllipse_1")], False) + +model.end() + +### Get shapes for tests +aPlaneShape = Plane_1.defaultResult().shape() +aCircleShape = Circle_1.defaultResult().shape() +aLineShape = Line_1.defaultResult().shape() +aCylinderShape = Cylinder_3.defaultResult().shape() +aSphereShape = SphereShell_1.defaultResult().shape() +aConeShape = ConeShell_1.defaultResult().shape() +aEllipseShape = EllipseWire_1.defaultResult().shape() + +### Check shapes types +if isCRImplemented(): + assert (GetShapeType(aPlaneShape) == "Plane") + assert (GetShapeType(aCircleShape)[1] == "Circle") + assert (GetShapeType(aLineShape) == "Line") + assert (GetShapeType(aCylinderShape) == "Cylinder") + assert (GetShapeType(aSphereShape) == "Sphere") + assert (GetShapeType(aConeShape) == "Cone") + assert (GetShapeType(aEllipseShape)[1] == "Ellipse") diff --git a/src/PythonAPI/geom/CanonicalRecognition.py b/src/PythonAPI/geom/CanonicalRecognition.py new file mode 100644 index 000000000..44b025582 --- /dev/null +++ b/src/PythonAPI/geom/CanonicalRecognition.py @@ -0,0 +1,85 @@ +# 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 +# + +from GeomAlgoAPI import GeomAlgoAPI_CanonicalRecognition + +class CanonicalRecognition: + "The class provides recognition of canonical shapes" + + def isPlane(self, shape, tolerance, normal = [], origin = []): + """ + Check if shape is planar + Usage: + > CR.isPlane(shape, tolerance, normal, origin) + """ + return GeomAlgoAPI_CanonicalRecognition.isPlane(shape, tolerance, normal, origin) + + def isSphere(self, shape, tolerance, origin = [], radius = 0.0): + """ + Check if shape is spherical + Usage: + > CR.isSphere(shape, tolerance, origin, radius) + """ + return GeomAlgoAPI_CanonicalRecognition.isSphere(shape, tolerance, origin, radius) + + def isCone(self, shape, tolerance, axis = [], apex = [], halfAngle = 0.0): + """ + Check if shape is conical + Usage: + > CR.isCone(shape, tolerance, axis, apex, halfAngle) + """ + return GeomAlgoAPI_CanonicalRecognition.isCone(shape, tolerance, axis, apex, halfAngle) + + def isCylinder(self, shape, tolerance, axis = [], origin = [], radius = 0.0): + """ + Check if shape is cylinder + Usage: + > CR.isCylinder(shape, tolerance, axis, origin, radius) + """ + return GeomAlgoAPI_CanonicalRecognition.isCylinder(shape, tolerance, axis, origin, radius) + + def isLine(self, edge, tolerance, direction = [], origin = []): + """ + Check if edge/wire is line + Usage: + > CR.isLine(edge, tolerance, direction, origin) + """ + return GeomAlgoAPI_CanonicalRecognition.isLine(edge, tolerance, direction, origin) + + def isCircle(self, edge, tolerance, normal = [], origin = [], radius = 0.0): + """ + Check if edge/wire is circle + Usage: + > CR.isCircle(edge, tolerance, normal, origin, radius) + """ + return GeomAlgoAPI_CanonicalRecognition.isCircle(edge, tolerance, normal, origin, radius) + + def isEllipse(self, edge, tolerance, normal = [], dirX = [], origin = [], majorRadius = 0.0, minorRadius = 0.0): + """ + Check if edge/wire is ellipse + Usage: + > CR.isEllipse(edge, tolerance, normal, dirX, origin, majorRadius, minorRadius) + """ + return GeomAlgoAPI_CanonicalRecognition.isEllipse(edge, tolerance, normal, dirX, origin, majorRadius, minorRadius) + + def isImplemented(self): + """ + Check if the CanonicalRecognition is implemented (built with appropriate OCCT version) + Usage: + > CR.isImplemented() + """ + return GeomAlgoAPI_CanonicalRecognition.isImplemented() diff --git a/src/PythonAPI/geom/__init__.py b/src/PythonAPI/geom/__init__.py index 00475f940..ef2c426fa 100644 --- a/src/PythonAPI/geom/__init__.py +++ b/src/PythonAPI/geom/__init__.py @@ -39,3 +39,4 @@ from GeomAPI import GeomAPI_Shape as Shape from GeomAlgoAPI import GeomAlgoAPI_Boolean as Boolean from .ShapeInfo import * +from .CanonicalRecognition import * diff --git a/src/PythonAPI/tests.set b/src/PythonAPI/tests.set index 510f66d07..d877f34f2 100644 --- a/src/PythonAPI/tests.set +++ b/src/PythonAPI/tests.set @@ -52,4 +52,6 @@ SET(TEST_NAMES TestShapeInfo.py Test2044.py + + TestCR.py )