Salome HOME
bos #29469: Advanced geometry features: Detect type of shape
authorvsv <vsv@opencascade.com>
Wed, 15 Jun 2022 14:48:49 +0000 (17:48 +0300)
committerjfa <jfa@opencascade.com>
Thu, 8 Sep 2022 15:29:01 +0000 (18:29 +0300)
20 files changed:
CMakeLists.txt
CTestTestfileInstall.cmake [deleted file]
CTestTestfileInstall.cmake.in [new file with mode: 0644]
idl/GEOM_Gen.idl
src/GEOMImpl/CMakeLists.txt
src/GEOMImpl/GEOMImpl_Gen.cxx
src/GEOMImpl/GEOMImpl_Gen.hxx
src/GEOMImpl/GEOMImpl_ICanonicalRecognition.cxx [new file with mode: 0644]
src/GEOMImpl/GEOMImpl_ICanonicalRecognition.hxx [new file with mode: 0644]
src/GEOM_I/CMakeLists.txt
src/GEOM_I/GEOM_Gen_i.cc
src/GEOM_I/GEOM_Gen_i.hh
src/GEOM_I/GEOM_ICanonicalRecognition_i.cc [new file with mode: 0644]
src/GEOM_I/GEOM_ICanonicalRecognition_i.hh [new file with mode: 0644]
src/GEOM_SWIG/CMakeLists.txt
src/GEOM_SWIG/GEOM_example8.py [new file with mode: 0644]
src/GEOM_SWIG/canonicalrecognition.py [new file with mode: 0644]
src/GEOM_SWIG/geomBuilder.py
test/test_CR.py [new file with mode: 0644]
test/tests.set

index 9fd2336443dc094baa3a917e8c4859052e58dbb1..21b0c03ec6da3f7ca6ebcb163dc710ca9096da8d 100644 (file)
@@ -204,7 +204,8 @@ SALOME_ACCUMULATE_ENVIRONMENT(LD_LIBRARY_PATH NOCHECK ${CMAKE_INSTALL_PREFIX}/${
 # ===============
 SET(GEOM_TEST_DIR ${SALOME_INSTALL_SCRIPT_SCRIPTS}/test)
 IF(SALOME_BUILD_TESTS)
-  INSTALL(FILES CTestTestfileInstall.cmake
+  CONFIGURE_FILE(CTestTestfileInstall.cmake.in CTestTestfileInstall.cmake @ONLY)
+  INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/CTestTestfileInstall.cmake
           DESTINATION ${GEOM_TEST_DIR}
           RENAME CTestTestfile.cmake)
 ENDIF()
diff --git a/CTestTestfileInstall.cmake b/CTestTestfileInstall.cmake
deleted file mode 100644 (file)
index cba60b0..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (C) 2017-2022  CEA/DEN, EDF R&D, OPEN CASCADE
-#
-# 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
-#
-
-SET(PYTHON_TEST_DRIVER "$ENV{KERNEL_ROOT_DIR}/bin/salome/appliskel/python_test_driver.py")
-SET(COMPONENT_NAME GEOM)
-SET(TIMEOUT        300)
-
-SUBDIRS(examples xao other)
diff --git a/CTestTestfileInstall.cmake.in b/CTestTestfileInstall.cmake.in
new file mode 100644 (file)
index 0000000..c47c8b1
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright (C) 2017-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# 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
+#
+
+SET(OpenCASCADE_VERSION @OpenCASCADE_VERSION@)
+SET(OpenCASCADE_SP_VERSION @OpenCASCADE_SP_VERSION@)
+
+SET(PYTHON_TEST_DRIVER "$ENV{KERNEL_ROOT_DIR}/bin/salome/appliskel/python_test_driver.py")
+SET(COMPONENT_NAME GEOM)
+SET(TIMEOUT        300)
+
+SUBDIRS(examples xao other)
index 98b0086b9b60f12c7a2d3e96d04d82f1a05db7c7..7423266a40e83d282b5ecf86ecad0da9e07e14da 100644 (file)
@@ -4937,6 +4937,48 @@ module GEOM
                       in boolean isRelative, in double angularDeflection);
   };
 
+  // # GEOM_ICanonicalRecognition:
+  /*!
+   *  \brief Interface for canonical recognition operations.
+   */
+  interface GEOM_ICanonicalRecognition : GEOM_IOperations
+  {
+    /*!
+     * check if the shape is planar
+     */
+    boolean isPlane(in GEOM_Object shape, in double tolerance, inout ListOfDouble normal, inout ListOfDouble origin);
+
+    /*!
+     * check if shape is spherical
+     */
+    boolean isSphere(in GEOM_Object shape, in double tolerance, inout ListOfDouble origin, inout double radius);
+
+    /*!
+     * check if shape is conical
+     */
+    boolean isCone(in GEOM_Object shape, in double tolerance, inout ListOfDouble axis, inout ListOfDouble apex, inout double halfAngle);
+
+    /*!
+     * check if shape is cylinder
+     */
+    boolean isCylinder(in GEOM_Object shape, in double tolerance, inout ListOfDouble axis, inout ListOfDouble origin, inout double radius);
+
+    /*!
+     * check if edge / wire is line
+     */
+    boolean isLine(in GEOM_Object edge, in double tolerance, inout ListOfDouble direction, inout ListOfDouble origin);
+
+    /*!
+     * check if edge / wire is circle
+     */
+    boolean isCircle(in GEOM_Object edge, in double tolerance, inout ListOfDouble normal, inout ListOfDouble origin, inout double radius);
+
+    /*!
+     * check if edge / wire is ellipse
+     */
+    boolean isEllipse(in GEOM_Object edge, in double tolerance, inout ListOfDouble normal, inout ListOfDouble dirX, inout ListOfDouble origin, inout double majorRadius, inout double minorRadius);
+  };
+
   // # GEOM_Gen:
   /*!
    *  \brief Interface to access other GEOM interfaces.
@@ -5050,20 +5092,21 @@ module GEOM
 
     // #  Methods to access interfaces for objects creation and transformation
 
-    GEOM_IBasicOperations     GetIBasicOperations    () raises (SALOME::SALOME_Exception);
-    GEOM_ITransformOperations GetITransformOperations() raises (SALOME::SALOME_Exception);
-    GEOM_I3DPrimOperations    GetI3DPrimOperations   () raises (SALOME::SALOME_Exception);
-    GEOM_IShapesOperations    GetIShapesOperations   () raises (SALOME::SALOME_Exception);
-    GEOM_IBooleanOperations   GetIBooleanOperations  () raises (SALOME::SALOME_Exception);
-    GEOM_ICurvesOperations    GetICurvesOperations   () raises (SALOME::SALOME_Exception);
-    GEOM_ILocalOperations     GetILocalOperations    () raises (SALOME::SALOME_Exception);
-    GEOM_IHealingOperations   GetIHealingOperations  () raises (SALOME::SALOME_Exception);
-    GEOM_IInsertOperations    GetIInsertOperations   () raises (SALOME::SALOME_Exception);
-    GEOM_IMeasureOperations   GetIMeasureOperations  () raises (SALOME::SALOME_Exception);
-    GEOM_IBlocksOperations    GetIBlocksOperations   () raises (SALOME::SALOME_Exception);
-    GEOM_IGroupOperations     GetIGroupOperations    () raises (SALOME::SALOME_Exception);
-    GEOM_IFieldOperations     GetIFieldOperations    () raises (SALOME::SALOME_Exception);
-    GEOM_ITestOperations      GetITestOperations     () raises (SALOME::SALOME_Exception);
+    GEOM_IBasicOperations      GetIBasicOperations     () raises (SALOME::SALOME_Exception);
+    GEOM_ITransformOperations  GetITransformOperations () raises (SALOME::SALOME_Exception);
+    GEOM_I3DPrimOperations     GetI3DPrimOperations    () raises (SALOME::SALOME_Exception);
+    GEOM_IShapesOperations     GetIShapesOperations    () raises (SALOME::SALOME_Exception);
+    GEOM_IBooleanOperations    GetIBooleanOperations   () raises (SALOME::SALOME_Exception);
+    GEOM_ICurvesOperations     GetICurvesOperations    () raises (SALOME::SALOME_Exception);
+    GEOM_ILocalOperations      GetILocalOperations     () raises (SALOME::SALOME_Exception);
+    GEOM_IHealingOperations    GetIHealingOperations   () raises (SALOME::SALOME_Exception);
+    GEOM_IInsertOperations     GetIInsertOperations    () raises (SALOME::SALOME_Exception);
+    GEOM_IMeasureOperations    GetIMeasureOperations   () raises (SALOME::SALOME_Exception);
+    GEOM_IBlocksOperations     GetIBlocksOperations    () raises (SALOME::SALOME_Exception);
+    GEOM_IGroupOperations      GetIGroupOperations     () raises (SALOME::SALOME_Exception);
+    GEOM_IFieldOperations      GetIFieldOperations     () raises (SALOME::SALOME_Exception);
+    GEOM_ITestOperations       GetITestOperations      () raises (SALOME::SALOME_Exception);
+    GEOM_ICanonicalRecognition GetICanonicalRecognition() raises (SALOME::SALOME_Exception);
 
     GEOM_IOperations GetPluginOperations (in string theLibName) raises (SALOME::SALOME_Exception);
 
index 43faf7ab824395a301409d4eeddb0c390fcd8c54..98e47cea33c888d99aaad2d04d266a482214a526 100644 (file)
@@ -182,6 +182,7 @@ SET(GEOMImpl_HEADERS
   GEOMImpl_PatchFaceDriver.hxx
   GEOMImpl_Types.hxx
   GEOM_GEOMImpl.hxx
+  GEOMImpl_ICanonicalRecognition.hxx
   )
 # --- sources ---
 
@@ -257,6 +258,7 @@ SET(GEOMImpl_SOURCES
   GEOMImpl_GlueDriver.cxx
   GEOMImpl_PatchFaceDriver.cxx
   GEOMImpl_FieldDriver.cxx
+  GEOMImpl_ICanonicalRecognition.cxx
   )
 
 # --- rules ---
index 867f7b9eb2535c0b1799f076ccfe6ff9ec02d137..74aceaf120e9a8e3fb4310a0ce82db0c9857202a 100644 (file)
@@ -185,6 +185,7 @@ GEOMImpl_Gen::GEOMImpl_Gen()
    _GroupOperations = new GEOMImpl_IGroupOperations( this );
    _FieldOperations = new GEOMImpl_IFieldOperations( this );
    _TestOperations = new GEOMImpl_ITestOperations( this );
+   _CanonicalRecognition = new GEOMImpl_ICanonicalRecognition( this );
 }
 
 //=============================================================================
@@ -210,6 +211,7 @@ GEOMImpl_Gen::~GEOMImpl_Gen()
   delete _MeasureOperations;
   delete _GroupOperations;
   delete _FieldOperations;
+  delete _CanonicalRecognition;
 }
 
 //=============================================================================
@@ -351,3 +353,13 @@ GEOMImpl_ITestOperations* GEOMImpl_Gen::GetITestOperations()
 {
   return _TestOperations;
 }
+
+//=============================================================================
+/*!
+ * GetICanonicalRecognition
+ */
+//=============================================================================
+GEOMImpl_ICanonicalRecognition* GEOMImpl_Gen::GetICanonicalRecognition()
+{
+  return _CanonicalRecognition;
+}
index dcd430f1950bfcdb58c16f176411186ebf0add69..86237a72e8d1566ba0fe9b14bfddf898f0e2f1e8 100644 (file)
@@ -41,6 +41,7 @@
 #include "GEOMImpl_IGroupOperations.hxx"
 #include "GEOMImpl_IFieldOperations.hxx"
 #include "GEOMImpl_ITestOperations.hxx"
+#include "GEOMImpl_ICanonicalRecognition.hxx"
 #include "GEOM_Engine.hxx"
 
 class GEOMIMPL_EXPORT GEOMImpl_Gen : public GEOM_Engine
@@ -77,22 +78,25 @@ class GEOMIMPL_EXPORT GEOMImpl_Gen : public GEOM_Engine
 
   GEOMImpl_ITestOperations* GetITestOperations();
 
+  GEOMImpl_ICanonicalRecognition* GetICanonicalRecognition();
+
  private:
 
-  GEOMImpl_IBasicOperations*     _BasicOperations;
-  GEOMImpl_ITransformOperations* _TransformOperations;
-  GEOMImpl_I3DPrimOperations*    _3DPrimOperations;
-  GEOMImpl_IShapesOperations*    _ShapesOperations;
-  GEOMImpl_IBlocksOperations*    _BlocksOperations;
-  GEOMImpl_IBooleanOperations*   _BooleanOperations;
-  GEOMImpl_IHealingOperations*   _HealingOperations;
-  GEOMImpl_ICurvesOperations*    _CurvesOperations;
-  GEOMImpl_ILocalOperations*     _LocalOperations;
-  GEOMImpl_IInsertOperations*    _InsertOperations;
-  GEOMImpl_IMeasureOperations*   _MeasureOperations;
-  GEOMImpl_IGroupOperations*     _GroupOperations;
-  GEOMImpl_IFieldOperations*     _FieldOperations;
-  GEOMImpl_ITestOperations*      _TestOperations;
+  GEOMImpl_IBasicOperations*      _BasicOperations;
+  GEOMImpl_ITransformOperations*  _TransformOperations;
+  GEOMImpl_I3DPrimOperations*     _3DPrimOperations;
+  GEOMImpl_IShapesOperations*     _ShapesOperations;
+  GEOMImpl_IBlocksOperations*     _BlocksOperations;
+  GEOMImpl_IBooleanOperations*    _BooleanOperations;
+  GEOMImpl_IHealingOperations*    _HealingOperations;
+  GEOMImpl_ICurvesOperations*     _CurvesOperations;
+  GEOMImpl_ILocalOperations*      _LocalOperations;
+  GEOMImpl_IInsertOperations*     _InsertOperations;
+  GEOMImpl_IMeasureOperations*    _MeasureOperations;
+  GEOMImpl_IGroupOperations*      _GroupOperations;
+  GEOMImpl_IFieldOperations*      _FieldOperations;
+  GEOMImpl_ITestOperations*       _TestOperations;
+  GEOMImpl_ICanonicalRecognition* _CanonicalRecognition;
 };
 
 #endif
diff --git a/src/GEOMImpl/GEOMImpl_ICanonicalRecognition.cxx b/src/GEOMImpl/GEOMImpl_ICanonicalRecognition.cxx
new file mode 100644 (file)
index 0000000..73cead1
--- /dev/null
@@ -0,0 +1,262 @@
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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 "GEOMImpl_ICanonicalRecognition.hxx"
+
+#include <Basics_OCCTVersion.hxx>
+
+#include "GEOM_Function.hxx"
+#include "GEOM_Object.hxx"
+#include "GEOM_PythonDump.hxx"
+
+#if OCC_VERSION_LARGE > 0x07050303
+#include <ShapeAnalysis_CanonicalRecognition.hxx>
+#endif
+
+#include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
+#include <gp_Pln.hxx>
+
+#include <utilities.h>
+
+
+//=============================================================================
+/*!
+ *   constructor:
+ */
+//=============================================================================
+GEOMImpl_ICanonicalRecognition::GEOMImpl_ICanonicalRecognition (GEOM_Engine* theEngine)
+: GEOM_IOperations(theEngine)
+{
+  MESSAGE("GEOMImpl_ICanonicalRecognition::GEOMImpl_ICanonicalRecognition");
+}
+
+//=============================================================================
+/*!
+ *  destructor
+ */
+//=============================================================================
+GEOMImpl_ICanonicalRecognition::~GEOMImpl_ICanonicalRecognition()
+{
+  MESSAGE("GEOMImpl_ICanonicalRecognition::~GEOMImpl_ICanonicalRecognition");
+}
+
+//=============================================================================
+/*!
+ * \brief Check if the shape is planar
+ */
+ //=============================================================================
+bool GEOMImpl_ICanonicalRecognition::isPlane(const Handle(GEOM_Object)& theShape, double theTolerance, gp_Pln& thePln)
+{
+  SetErrorCode(KO);
+  if (theShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+  TopoDS_Shape aShape = theShape->GetValue();
+  if (aShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+
+#if OCC_VERSION_LARGE < 0x07050304
+  SetErrorCode("Shape type detection aborted. Improper OCCT version: please, use OCCT 7.5.3p5 or newer.");
+  return false;
+#else
+  ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
+  SetErrorCode(OK);
+  return aRecognition.GetStatus() == 0 && aRecognition.IsPlane(theTolerance, thePln);
+#endif
+}
+
+//=============================================================================
+/*!
+ * \brief Check if shape is spherical
+ */
+ //=============================================================================
+bool GEOMImpl_ICanonicalRecognition::isSphere(const Handle(GEOM_Object)& theShape, double theTolerance,
+  gp_Sphere& theSphere)
+{
+  SetErrorCode(KO);
+  if (theShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+  TopoDS_Shape aShape = theShape->GetValue();
+  if (aShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+
+#if OCC_VERSION_LARGE < 0x07050304
+  SetErrorCode("Shape type detection aborted. Improper OCCT version: please, use OCCT 7.5.3p5 or newer.");
+  return false;
+#else
+  ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
+  SetErrorCode(OK);
+  return aRecognition.GetStatus() == 0 && aRecognition.IsSphere(theTolerance, theSphere);
+#endif
+}
+
+//=============================================================================
+/*!
+ * \brief Check if shape is conical
+ */
+ //=============================================================================
+bool GEOMImpl_ICanonicalRecognition::isCone(const Handle(GEOM_Object)& theShape, double theTolerance,
+  gp_Cone& theCone)
+{
+  SetErrorCode(KO);
+  if (theShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+  TopoDS_Shape aShape = theShape->GetValue();
+  if (aShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+
+#if OCC_VERSION_LARGE < 0x07050304
+  SetErrorCode("Shape type detection aborted. Improper OCCT version: please, use OCCT 7.5.3p5 or newer.");
+  return false;
+#else
+  ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
+  SetErrorCode(OK);
+  return aRecognition.GetStatus() == 0 && aRecognition.IsCone(theTolerance, theCone);
+#endif
+}
+
+//=============================================================================
+/*!
+ * \brief Check if shape is cylinder
+ */
+ //=============================================================================
+bool GEOMImpl_ICanonicalRecognition::isCylinder(const Handle(GEOM_Object)& theShape, double theTolerance,
+  gp_Cylinder& theCylinder)
+{
+  SetErrorCode(KO);
+  if (theShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+  TopoDS_Shape aShape = theShape->GetValue();
+  if (aShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+
+#if OCC_VERSION_LARGE < 0x07050304
+  SetErrorCode("Shape type detection aborted. Improper OCCT version: please, use OCCT 7.5.3p5 or newer.");
+  return false;
+#else
+  ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
+  SetErrorCode(OK);
+  return aRecognition.GetStatus() == 0 && aRecognition.IsCylinder(theTolerance, theCylinder);
+#endif
+}
+
+//=============================================================================
+/*!
+ * \brief Check if edge / wire is line
+ */
+ //=============================================================================
+bool GEOMImpl_ICanonicalRecognition::isLine(const Handle(GEOM_Object)& theEdge, double theTolerance,
+  gp_Lin& theLine)
+{
+  SetErrorCode(KO);
+  if (theEdge.IsNull()) {
+    SetErrorCode("Error: NULL edge");
+    return false;
+  }
+  TopoDS_Shape aShape = theEdge->GetValue();
+  if (aShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+
+#if OCC_VERSION_LARGE < 0x07050304
+  SetErrorCode("Shape type detection aborted. Improper OCCT version: please, use OCCT 7.5.3p5 or newer.");
+  return false;
+#else
+  ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
+  SetErrorCode(OK);
+  return aRecognition.GetStatus() == 0 && aRecognition.IsLine(theTolerance, theLine);
+#endif
+}
+
+//=============================================================================
+/*!
+ * \brief Check if edge / wire is circle
+ */
+ //=============================================================================
+bool GEOMImpl_ICanonicalRecognition::isCircle(const Handle(GEOM_Object)& theEdge, double theTolerance,
+  gp_Circ& theCircle)
+{
+  SetErrorCode(KO);
+  if (theEdge.IsNull()) {
+    SetErrorCode("Error: NULL edge");
+    return false;
+  }
+  TopoDS_Shape aShape = theEdge->GetValue();
+  if (aShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+
+#if OCC_VERSION_LARGE < 0x07050304
+  SetErrorCode("Shape type detection aborted. Improper OCCT version: please, use OCCT 7.5.3p5 or newer.");
+  return false;
+#else
+  ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
+  SetErrorCode(OK);
+  return aRecognition.GetStatus() == 0 && aRecognition.IsCircle(theTolerance, theCircle);
+#endif
+}
+
+//=============================================================================
+/*!
+ * \brief Check if edge / wire is ellipse
+ */
+ //=============================================================================
+bool GEOMImpl_ICanonicalRecognition::isEllipse(const Handle(GEOM_Object)& theEdge, double theTolerance,
+  gp_Elips& theElips)
+{
+  SetErrorCode(KO);
+  if (theEdge.IsNull()) {
+    SetErrorCode("Error: NULL edge");
+    return false;
+  }
+  TopoDS_Shape aShape = theEdge->GetValue();
+  if (aShape.IsNull()) {
+    SetErrorCode("Error: NULL shape");
+    return false;
+  }
+
+#if OCC_VERSION_LARGE < 0x07050304
+  SetErrorCode("Shape type detection aborted. Improper OCCT version: please, use OCCT 7.5.3p5 or newer.");
+  return false;
+#else
+  ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
+  SetErrorCode(OK);
+  return aRecognition.GetStatus() == 0 && aRecognition.IsEllipse(theTolerance, theElips);
+#endif
+}
diff --git a/src/GEOMImpl/GEOMImpl_ICanonicalRecognition.hxx b/src/GEOMImpl/GEOMImpl_ICanonicalRecognition.hxx
new file mode 100644 (file)
index 0000000..b4d482d
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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 _GEOMImpl_ICanonicalRecognition_HXX_
+#define _GEOMImpl_ICanonicalRecognition_HXX_
+
+#include "GEOM_IOperations.hxx"
+
+#include <GEOM_Field.hxx>
+
+#include <TColStd_HSequenceOfTransient.hxx>
+#include <TColStd_HArray1OfExtendedString.hxx>
+
+#include <vector>
+
+class GEOM_Object;
+
+class GEOMImpl_ICanonicalRecognition : public GEOM_IOperations {
+ public:
+  Standard_EXPORT GEOMImpl_ICanonicalRecognition(GEOM_Engine* theEngine);
+  Standard_EXPORT ~GEOMImpl_ICanonicalRecognition();
+
+  /*!
+   * \brief Check if the shape is planar
+   */
+  Standard_EXPORT bool isPlane(const Handle(GEOM_Object)& theShape, double theTolerance,
+    gp_Pln& thePln);
+
+  /*!
+   * \brief Check if shape is spherical
+   */
+  Standard_EXPORT bool isSphere(const Handle(GEOM_Object)& theShape, double theTolerance,
+    gp_Sphere& theSphere);
+
+  /*!
+   * \brief Check if shape is conical
+   */
+  Standard_EXPORT bool isCone(const Handle(GEOM_Object)& theShape, double theTolerance,
+    gp_Cone& theCone);
+
+  /*!
+   * \brief Check if shape is cylinder
+   */
+  Standard_EXPORT bool isCylinder(const Handle(GEOM_Object)& theShape, double theTolerance,
+    gp_Cylinder& theCylinder);
+
+  /*!
+   * \brief Check if edge / wire is line
+   */
+  Standard_EXPORT bool isLine(const Handle(GEOM_Object)& theEdge, double theTolerance,
+    gp_Lin& theLine);
+
+  /*!
+   * \brief Check if edge / wire is circle
+   */
+  Standard_EXPORT bool isCircle(const Handle(GEOM_Object)& theEdge, double theTolerance,
+    gp_Circ& theCircle);
+
+  /*!
+   * \brief Check if edge / wire is ellipse
+   */
+  Standard_EXPORT bool isEllipse(const Handle(GEOM_Object)& theEdge, double theTolerance,
+    gp_Elips& theElips);
+
+};
+
+#endif
index 32ca2847982cd89a9efd71f3f2fc4cea70c71a17..7aec8371baa30950512f2bac53df41b9998e69b7 100644 (file)
@@ -78,6 +78,7 @@ SET(GEOMEngine_HEADERS
   GEOM_IMeasureOperations_i.hh
   GEOM_IGroupOperations_i.hh
   GEOM_ITestOperations_i.hh
+  GEOM_ICanonicalRecognition_i.hh
   GEOM_Gen_i.hh
   GEOM_Gen_Session_i.hh
   GEOM_Gen_No_Session_i.hh
@@ -105,6 +106,7 @@ SET(GEOMEngine_SOURCES
   GEOM_IGroupOperations_i.cc
   GEOM_IFieldOperations_i.cc
   GEOM_ITestOperations_i.cc
+  GEOM_ICanonicalRecognition_i.cc
   GEOM_Gen_i.cc
   GEOM_Gen_Session_i.cc
   GEOM_Gen_No_Session_i.cc
index c4a5599bb445b724a83a9214ebdb278ccbbf3d88..00e58ed8af2e1fde929ea9b27e1c8f4ad561c5a2 100644 (file)
@@ -2485,6 +2485,25 @@ GEOM::GEOM_ITestOperations_ptr GEOM_Gen_i::GetITestOperations()
   return operations._retn();
 }
 
+//============================================================================
+// function : GetICanonicalRecognition
+// purpose  :
+//============================================================================
+GEOM::GEOM_ICanonicalRecognition_ptr GEOM_Gen_i::GetICanonicalRecognition()
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  MESSAGE("GEOM_Gen_i::GetICanonicalRecognition");
+
+  GEOM::GEOM_Gen_ptr engine = _this();
+
+  GEOM_ICanonicalRecognition_i* aServant =
+    new GEOM_ICanonicalRecognition_i(_poa, engine, _impl->GetICanonicalRecognition());
+
+  // activate the CORBA servant
+  GEOM::GEOM_ICanonicalRecognition_var operations = aServant->_this();
+  return operations._retn();
+}
+
 //============================================================================
 // function : GetPluginOperations
 // purpose  :
index cfe4b62aba32d211cca612cdcea1e60e46c1c66a..a956ed9110ba8bec8699feb329f14103371b63e6 100644 (file)
@@ -52,6 +52,7 @@
 #include "GEOM_IGroupOperations_i.hh"
 #include "GEOM_IFieldOperations_i.hh"
 #include "GEOM_ITestOperations_i.hh"
+#include "GEOM_ICanonicalRecognition_i.hh"
 #include "GEOMUtils.hxx"
 
 #include <TopTools_IndexedMapOfShape.hxx>
@@ -259,6 +260,8 @@ class GEOM_I_EXPORT GEOM_Gen_i : public POA_GEOM::GEOM_Gen, public Engines_Compo
   virtual GEOM::GEOM_ITestOperations_ptr GetITestOperations()
     ;
 
+  virtual GEOM::GEOM_ICanonicalRecognition_ptr GetICanonicalRecognition();
+
   //Returns a pointer to corresponding plugin operations interface
   virtual GEOM::GEOM_IOperations_ptr GetPluginOperations (const char* theLibName)
     ;
diff --git a/src/GEOM_I/GEOM_ICanonicalRecognition_i.cc b/src/GEOM_I/GEOM_ICanonicalRecognition_i.cc
new file mode 100644 (file)
index 0000000..d8ab9b2
--- /dev/null
@@ -0,0 +1,325 @@
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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 "GEOM_ICanonicalRecognition_i.hh"
+
+#include "utilities.h"
+#include "OpUtil.hxx"
+#include "Utils_ExceptHandlers.hxx"
+
+#include "GEOM_Engine.hxx"
+#include "GEOM_Object.hxx"
+#include "GEOM_Field.hxx"
+
+#include "gp_Pln.hxx"
+#include "gp_Sphere.hxx"
+#include "gp_Cone.hxx"
+#include "gp_Cylinder.hxx"
+#include "gp_Circ.hxx"
+#include "gp_Elips.hxx"
+
+//=============================================================================
+/*
+ *   constructor:
+ */
+//=============================================================================
+GEOM_ICanonicalRecognition_i::GEOM_ICanonicalRecognition_i (PortableServer::POA_ptr thePOA,
+                                                  GEOM::GEOM_Gen_ptr theEngine,
+                                                  ::GEOMImpl_ICanonicalRecognition* theImpl)
+  :GEOM_IOperations_i(thePOA, theEngine, theImpl)
+{
+  MESSAGE("GEOM_ICanonicalRecognition_i::GEOM_ICanonicalRecognition_i");
+}
+
+//=============================================================================
+/*
+ *  destructor
+ */
+//=============================================================================
+GEOM_ICanonicalRecognition_i::~GEOM_ICanonicalRecognition_i()
+{
+  MESSAGE("GEOM_ICanonicalRecognition_i::~GEOM_ICanonicalRecognition_i");
+}
+
+static bool isValidDirection(const GEOM::ListOfDouble& theDir)
+{
+  return (theDir.length() == 3) && (gp_Vec(theDir[0], theDir[1], theDir[2]).Magnitude() > 0.);
+}
+
+//=============================================================================
+/*
+ *  \brief Check if the shape is planar
+ */
+ //=============================================================================
+CORBA::Boolean GEOM_ICanonicalRecognition_i::isPlane(GEOM::GEOM_Object_ptr theShape, CORBA::Double theTolerance,
+  GEOM::ListOfDouble& theNormal, GEOM::ListOfDouble& theOrigin)
+{
+  Handle(::GEOM_Object) go = GetObjectImpl(theShape);
+
+  bool aIsValidNormal = isValidDirection(theNormal);
+  bool aIsValidOrigin = theOrigin.length() == 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 = GetOperation()->isPlane(go, theTolerance, aPln);
+  gp_Pnt aOrig = aPln.Location();
+  theOrigin[0] = aOrig.X();
+  theOrigin[1] = aOrig.Y();
+  theOrigin[2] = aOrig.Z();
+
+  gp_Dir aNorm = aPln.Axis().Direction();
+  theNormal[0] = aNorm.X();
+  theNormal[1] = aNorm.Y();
+  theNormal[2] = aNorm.Z();
+
+  return aResult;
+}
+
+//=============================================================================
+/*
+ * \brief Check if shape is spherical
+ */
+ //=============================================================================
+CORBA::Boolean GEOM_ICanonicalRecognition_i::isSphere(GEOM::GEOM_Object_ptr theShape, CORBA::Double theTolerance,
+  GEOM::ListOfDouble& theOrigin, CORBA::Double& theRadius)
+{
+  Handle(::GEOM_Object) go = GetObjectImpl(theShape);
+
+  bool aIsValidOrigin = theOrigin.length() == 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 = GetOperation()->isSphere(go, theTolerance, aSphere);
+  gp_Pnt aLoc = aSphere.Location();
+  theOrigin[0] = aLoc.X();
+  theOrigin[1] = aLoc.Y();
+  theOrigin[2] = aLoc.Z();
+  theRadius = aSphere.Radius();
+
+  return aResult;
+}
+
+//=============================================================================
+/*
+ * \brief Check if shape is conical
+ */
+ //=============================================================================
+CORBA::Boolean GEOM_ICanonicalRecognition_i::isCone(GEOM::GEOM_Object_ptr theShape, CORBA::Double theTolerance,
+  GEOM::ListOfDouble& theAxis, GEOM::ListOfDouble& theApex, CORBA::Double& theHalfAngle)
+{
+  Handle(::GEOM_Object) go = GetObjectImpl(theShape);
+
+  bool aIsValidAxis = isValidDirection(theAxis);
+  bool aIsValidApex = theApex.length() == 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 = GetOperation()->isCone(go, theTolerance, aCone);
+  gp_Dir aDir = aCone.Axis().Direction();
+  theAxis[0] = aDir.X();
+  theAxis[1] = aDir.Y();
+  theAxis[2] = aDir.Z();
+
+  gp_Pnt aApex = aCone.Apex();
+  theApex[0] = aApex.X();
+  theApex[1] = aApex.Y();
+  theApex[2] = aApex.Z();
+
+  theHalfAngle = aCone.SemiAngle();
+  return aResult;
+}
+
+//=============================================================================
+/*!
+ * \brief Check if shape is cylinder
+ */
+ //=============================================================================
+CORBA::Boolean GEOM_ICanonicalRecognition_i::isCylinder(GEOM::GEOM_Object_ptr theShape, CORBA::Double theTolerance,
+  GEOM::ListOfDouble& theAxis, GEOM::ListOfDouble& theOrigin, CORBA::Double& theRadius)
+{
+  Handle(::GEOM_Object) go = GetObjectImpl(theShape);
+
+  bool aIsValidAxis = isValidDirection(theAxis);
+  bool aIsValidOrigin = theOrigin.length() == 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 = GetOperation()->isCylinder(go, theTolerance, aCylinder);
+  gp_Dir aDir = aCylinder.Axis().Direction();
+  theAxis[0] = aDir.X();
+  theAxis[1] = aDir.Y();
+  theAxis[2] = aDir.Z();
+
+  gp_Pnt aLoc = aCylinder.Location();
+  theOrigin[0] = aLoc.X();
+  theOrigin[1] = aLoc.Y();
+  theOrigin[2] = aLoc.Z();
+
+  theRadius = aCylinder.Radius();
+
+  return aResult;
+}
+
+//=============================================================================
+/*!
+ * \brief Check if edge / wire is line
+ */
+ //=============================================================================
+CORBA::Boolean GEOM_ICanonicalRecognition_i::isLine(GEOM::GEOM_Object_ptr theEdge, CORBA::Double theTolerance,
+  GEOM::ListOfDouble& theDir, GEOM::ListOfDouble& theOrigin)
+{
+  Handle(::GEOM_Object) go = GetObjectImpl(theEdge);
+
+  bool aIsValidDir = isValidDirection(theDir);
+  bool aIsValidOrigin = theOrigin.length() == 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 = GetOperation()->isLine(go, theTolerance, aLine);
+  gp_Pnt aLoc = aLine.Location();
+  theOrigin[0] = aLoc.X();
+  theOrigin[1] = aLoc.Y();
+  theOrigin[2] = aLoc.Z();
+
+  gp_Dir aDir = aLine.Direction();
+  theDir[0] = aDir.X();
+  theDir[1] = aDir.Y();
+  theDir[2] = aDir.Z();
+
+  return aResult;
+}
+
+//=============================================================================
+/*!
+ * \brief Check if edge / wire is circle
+ */
+ //=============================================================================
+CORBA::Boolean GEOM_ICanonicalRecognition_i::isCircle(GEOM::GEOM_Object_ptr theEdge, CORBA::Double theTolerance,
+  GEOM::ListOfDouble& theNormal, GEOM::ListOfDouble& theOrigin, CORBA::Double& theRadius)
+{
+  Handle(::GEOM_Object) go = GetObjectImpl(theEdge);
+  bool aIsValidNormal = isValidDirection(theNormal);
+  bool aIsValidOrigin = theOrigin.length() == 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 = GetOperation()->isCircle(go, theTolerance, aCircle);
+  gp_Pnt aLoc = aCircle.Location();
+  theOrigin[0] = aLoc.X();
+  theOrigin[1] = aLoc.Y();
+  theOrigin[2] = aLoc.Z();
+
+  gp_Dir aDir = aCircle.Axis().Direction();
+  theNormal[0] = aDir.X();
+  theNormal[1] = aDir.Y();
+  theNormal[2] = aDir.Z();
+  theRadius = aCircle.Radius();
+
+  return aResult;
+}
+
+//=============================================================================
+/*!
+ * \brief Check if edge / wire is ellipse
+ */
+ //=============================================================================
+CORBA::Boolean GEOM_ICanonicalRecognition_i::isEllipse(GEOM::GEOM_Object_ptr theEdge, CORBA::Double theTolerance,
+  GEOM::ListOfDouble& theNormal, GEOM::ListOfDouble& theDirX, GEOM::ListOfDouble& theOrigin,
+  CORBA::Double& theMajorRadius, CORBA::Double& theMinorRadius)
+{
+  Handle(::GEOM_Object) go = GetObjectImpl(theEdge);
+  bool aIsValidNormal = isValidDirection(theNormal);
+  bool aIsValidOrigin = theOrigin.length() == 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 = GetOperation()->isEllipse(go, theTolerance, aElips);
+  gp_Pnt aLoc = aElips.Position().Location();
+  if (theOrigin.length() != 3)
+    theOrigin.allocbuf(3);
+  theOrigin[0] = aLoc.X();
+  theOrigin[1] = aLoc.Y();
+  theOrigin[2] = aLoc.Z();
+
+  gp_Dir aNorm = aElips.Position().Direction();
+  theNormal[0] = aNorm.X();
+  theNormal[1] = aNorm.Y();
+  theNormal[2] = aNorm.Z();
+
+  gp_Dir aDirX = aElips.Position().XDirection();
+  theDirX[0] = aDirX.X();
+  theDirX[1] = aDirX.Y();
+  theDirX[2] = aDirX.Z();
+
+  theMajorRadius = aElips.MajorRadius();
+  theMinorRadius = aElips.MinorRadius();
+
+  return aResult;
+}
diff --git a/src/GEOM_I/GEOM_ICanonicalRecognition_i.hh b/src/GEOM_I/GEOM_ICanonicalRecognition_i.hh
new file mode 100644 (file)
index 0000000..a237f7d
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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 _GEOM_ICanonicalRecognition_i_HeaderFile
+#define _GEOM_ICanonicalRecognition_i_HeaderFile
+
+#include "GEOMImpl_Gen.hxx"
+
+#include <SALOMEconfig.h>
+
+#include CORBA_SERVER_HEADER(GEOM_Gen)
+#include "GEOM_IOperations_i.hh"
+#include "GEOM_Object_i.hh"
+
+#include "GEOMImpl_ICanonicalRecognition.hxx"
+
+class GEOM_I_EXPORT GEOM_ICanonicalRecognition_i :
+  public virtual POA_GEOM::GEOM_ICanonicalRecognition,
+  public virtual GEOM_IOperations_i
+{
+ public:
+  GEOM_ICanonicalRecognition_i (PortableServer::POA_ptr thePOA, GEOM::GEOM_Gen_ptr theEngine,
+                           ::GEOMImpl_ICanonicalRecognition* theImpl);
+  ~GEOM_ICanonicalRecognition_i();
+
+  /*!
+   *  \brief Check if the shape is planar
+   */
+  CORBA::Boolean isPlane(GEOM::GEOM_Object_ptr theShape, CORBA::Double theTolerance,
+    GEOM::ListOfDouble& theNormal, GEOM::ListOfDouble& theOrigin);
+
+  /*!
+   * \brief Check if shape is spherical
+   */
+  CORBA::Boolean isSphere(GEOM::GEOM_Object_ptr theShape, CORBA::Double theTolerance,
+    GEOM::ListOfDouble& theOrigin, CORBA::Double& theRadius);
+
+  /*!
+   * \brief Check if shape is conical
+   */
+  CORBA::Boolean isCone(GEOM::GEOM_Object_ptr theShape, CORBA::Double theTolerance,
+    GEOM::ListOfDouble& theAxis, GEOM::ListOfDouble& theApex,
+    CORBA::Double& theHalfAngle);
+
+  /*!
+   * \brief Check if shape is cylinder
+   */
+  CORBA::Boolean isCylinder(GEOM::GEOM_Object_ptr theShape, CORBA::Double theTolerance,
+    GEOM::ListOfDouble& theAxis, GEOM::ListOfDouble& theOrigin,
+    CORBA::Double& theRadius);
+
+  /*!
+   * \brief Check if edge / wire is line
+   */
+  CORBA::Boolean isLine(GEOM::GEOM_Object_ptr theEdge, CORBA::Double theTolerance,
+    GEOM::ListOfDouble& theDir, GEOM::ListOfDouble& theOrigin);
+
+  /*!
+   * \brief Check if edge / wire is circle
+   */
+  CORBA::Boolean isCircle(GEOM::GEOM_Object_ptr theEdge, CORBA::Double theTolerance,
+    GEOM::ListOfDouble& theNormal, GEOM::ListOfDouble& theOrigin,
+    CORBA::Double& theRadius);
+
+  /*!
+   * \brief Check if edge / wire is ellipse
+   */
+  CORBA::Boolean isEllipse(GEOM::GEOM_Object_ptr theEdge, CORBA::Double theTolerance,
+    GEOM::ListOfDouble& theNormal, GEOM::ListOfDouble& theDirX,
+    GEOM::ListOfDouble& theOrigin,
+    CORBA::Double& theMajorRadius, CORBA::Double& theMinorRadius);
+
+  ::GEOMImpl_ICanonicalRecognition* GetOperation()
+  { return (::GEOMImpl_ICanonicalRecognition*)GetImpl(); }
+};
+
+#endif
index 963540446f2c338f7ecb92d1f162e29fbe246cf6..39f3ac6af4a860b5bd8b43301e67ffed091a4398 100644 (file)
@@ -71,6 +71,7 @@ SET(_other_SCRIPTS
 SET(_python_SCRIPTS
   geomBuilder.py
   gsketcher.py
+  canonicalrecognition.py
   )
 
 # Advanced scripts
diff --git a/src/GEOM_SWIG/GEOM_example8.py b/src/GEOM_SWIG/GEOM_example8.py
new file mode 100644 (file)
index 0000000..925f070
--- /dev/null
@@ -0,0 +1,11 @@
+import salome
+salome.salome_init()
+import GEOM
+from salome.geom import geomBuilder
+
+geompy = geomBuilder.New()
+aCircle = geompy.MakeCircleR(150.)
+aCylinder = geompy.MakeCylinderRH(100.,200.)
+
+aCR = geompy.CanonicalRecognition()
+aCR.isCylinder(aCylinder, 0.1)
diff --git a/src/GEOM_SWIG/canonicalrecognition.py b/src/GEOM_SWIG/canonicalrecognition.py
new file mode 100644 (file)
index 0000000..69aaa18
--- /dev/null
@@ -0,0 +1,90 @@
+#  -*- coding: iso-8859-1 -*-
+# Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# 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
+#
+#  File   : GEOM_CanonicalRecognition.py
+#  Author : Vitaly SMETANNIKOV, Open CASCADE S.A.S.
+#  Module : GEOM_SWIG
+
+def setVectorSize(theVec):
+    "We have to set the vector size because we need to have output values in this vector"
+    if len(theVec) != 3:
+        theVec = [0,0,0]
+    return theVec
+
+class CanonicalRecognition:
+    "The class provides recognition of canonical shapes"
+
+    def __init__(self, geompyD):
+        self.CR = geompyD.GetICanonicalRecognition()
+        
+    def isPlane(self, shape, tolerance, normal = [], origin = []):
+        """
+        Check if shape is planar
+        Usage:
+        > CR.isPlane(shape, tolerance, normal, origin)
+        """
+        return self.CR.isPlane(shape, tolerance, setVectorSize(normal), setVectorSize(origin))
+
+    def isSphere(self, shape, tolerance, origin = [], radius = 0.0):
+        """
+        Check if shape is spherical
+        Usage:
+        > CR.isSphere(shape, tolerance, origin, radius)
+        """
+        return self.CR.isSphere(shape, tolerance, setVectorSize(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 self.CR.isCone(shape, tolerance, setVectorSize(axis), setVectorSize(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 self.CR.isCylinder(shape, tolerance, setVectorSize(axis), setVectorSize(origin), radius)
+
+    def isLine(self, edge, tolerance, direction = [], origin = []):
+        """
+        Check if edge/wire is line
+        Usage:
+        > CR.isLine(edge, tolerance, direction, origin)
+        """
+        return self.CR.isLine(edge, tolerance, setVectorSize(direction), setVectorSize(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 self.CR.isCircle(edge, tolerance, setVectorSize(normal), setVectorSize(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 self.CR.isEllipse(edge, tolerance, setVectorSize(normal), setVectorSize(dirX), setVectorSize(origin), majorRadius, minorRadius)
index e80d9f60ac9c4f6121570b9c8e8174b7436b05f4..49115d58acebcea80805e6999fee71176ef15050 100644 (file)
@@ -260,6 +260,7 @@ import os
 import functools
 
 from salome.geom.gsketcher import Sketcher3D, Sketcher2D, Polyline2D
+from salome.geom.canonicalrecognition import CanonicalRecognition
 
 # In case the omniORBpy EnumItem class does not fully support Python 3
 # (for instance in version 4.2.1-2), the comparison ordering methods must be
@@ -11839,6 +11840,22 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
             aDescr = self.MeasuOp.IsGoodForSolid(theShell)
             return aDescr
 
+        ## Obtain a canonical recognition interface.
+        #  @return An instance of
+        #          @ref canonicalrecognition.CanonicalRecognition "CanonicalRecognition" interface
+        #
+        #  @ref tui_3dsketcher_page "Example"
+        def CanonicalRecognition (self):
+            """
+            Obtain a canonical recognition interface.
+
+            Example of usage:
+                cr = geompy.CanonicalRecognition()
+                cr.isLine(aLine, tolerance)
+            """
+            cr = CanonicalRecognition (self)
+            return cr
+
         # end of l2_measure
         ## @}
 
diff --git a/test/test_CR.py b/test/test_CR.py
new file mode 100644 (file)
index 0000000..cf58efe
--- /dev/null
@@ -0,0 +1,104 @@
+#  -*- coding: iso-8859-1 -*-
+# Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# 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
+#
+
+import salome
+###
+salome.salome_init()
+
+import GEOM
+from salome.geom import geomBuilder
+import math
+import SALOMEDS
+
+geompy = geomBuilder.New()
+
+import unittest
+
+def GetShapeType(theShape):
+    CR = geompy.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"
+
+class GEOMTestCR(unittest.TestCase):
+    def testBasic(self):
+        """
+        Acceptance test for tuleap29469
+        """
+        O = geompy.MakeVertex(0, 0, 0)
+        OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+        OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+        OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+        Cylinder_1 = geompy.MakeCylinderRH(100, 300)
+        [Face_1,Face_2,Face_3] = geompy.ExtractShapes(Cylinder_1, geompy.ShapeType["FACE"], True)
+        [Edge_1,Edge_2,Edge_3] = geompy.ExtractShapes(Cylinder_1, geompy.ShapeType["EDGE"], True)
+        Sphere_1 = geompy.MakeSphereR(100)
+        [Shell_1] = geompy.ExtractShapes(Sphere_1, geompy.ShapeType["SHELL"], True)
+        Cone_1 = geompy.MakeConeR1R2H(100, 0, 300)
+        [Shell_2] = geompy.ExtractShapes(Cone_1, geompy.ShapeType["SHELL"], True)
+        [Face_4,Face_5] = geompy.ExtractShapes(Shell_2, geompy.ShapeType["FACE"], True)
+
+        ## Create ellips
+        Cylinder_2 = geompy.MakeCylinderRH(100, 300)
+        Plane_1 = geompy.MakePlaneLCS(None, 350, 1)
+        Translation_1 = geompy.MakeTranslation(Plane_1, 0, 0, 150)
+        Rotation_1 = geompy.MakeRotation(Translation_1, OX, 20*math.pi/180.0)
+        Partition_1 = geompy.MakePartition([Cylinder_2], [Rotation_1], [], [], geompy.ShapeType["SOLID"], 0, [], 0)
+        [Edge_4,Edge_5,Edge_6,Edge_7,Edge_8] = geompy.ExtractShapes(Partition_1, geompy.ShapeType["EDGE"], True)
+
+        assert GetShapeType(Face_1) == "Plane"
+        assert GetShapeType(Face_2) == "Cylinder"
+        assert GetShapeType(Edge_3) == "Line"
+        assert GetShapeType(Edge_2)[1] == "Circle"
+        assert GetShapeType(Shell_1) == "Sphere"
+        assert GetShapeType(Shell_2) == "Cone"
+        assert GetShapeType(Edge_5)[1] == "Ellipse"
+        
+    def testOnSetOfPtsOnCyl(self):
+        import numpy as np
+        tab = [[49.9999999999997, 86.6025403784442, 0.0], [1.43524931876432e-12, 100.0, 0.0], [6.12323399573677e-15, 100.0, 300.0], [50.0, 86.6025403784439, 300.0], [34.20201433256674, 93.96926207859089, 300.0], [17.364817766692976, 98.48077530122082, 300.0], [0.0, 100.0, 19.999999999999854], [0.0, 100.0, 39.99999999999963], [0.0, 100.0, 59.99999999999965], [0.0, 100.0, 79.99999999999966], [0.0, 100.0, 99.9999999999997], [0.0, 100.0, 119.99999999999973], [0.0, 100.0, 139.99999999999974], [0.0, 100.0, 159.99999999999977], [0.0, 100.0, 179.9999999999998], [0.0, 100.0, 199.99999999999983], [0.0, 100.0, 219.9999999999999], [0.0, 100.0, 239.99999999999994], [0.0, 100.0, 259.9999999999999], [0.0, 100.0, 279.99999999999994], [34.20201433256736, 93.96926207859066, 0.0], [17.364817766694355, 98.48077530122058, 0.0], [50.0, 86.60254037844386, 19.999999999999854], [50.0, 86.60254037844386, 39.99999999999963], [50.0, 86.60254037844386, 59.99999999999965], [50.0, 86.60254037844386, 79.99999999999966], [50.0, 86.60254037844386, 99.9999999999997], [50.0, 86.60254037844386, 119.99999999999973], [50.0, 86.60254037844386, 139.99999999999974], [50.0, 86.60254037844386, 159.99999999999977], [50.0, 86.60254037844386, 179.9999999999998], [50.0, 86.60254037844386, 199.99999999999983], [50.0, 86.60254037844386, 219.9999999999999], [50.0, 86.60254037844386, 239.99999999999994], [50.0, 86.60254037844386, 259.9999999999999], [50.0, 86.60254037844386, 279.99999999999994], [29.61877316560949, 95.5129743865417, 277.8870679979398], [17.205660214608802, 98.50870650140234, 30.630206624576903], [16.710324551353793, 98.59394024679419, 72.64745394595525], [17.100883188710984, 98.52694958317781, 107.80372339391727], [17.635764230289126, 98.4326156312716, 152.57612984579256], [13.644784679867689, 99.06472556384563, 189.91477232835643], [17.211909165765633, 98.50761484712454, 226.50789445170153], [16.947190833941324, 98.55350182940215, 264.31714685564623], [33.70205726794775, 94.14972828377132, 23.514274138894333], [33.9866992950552, 94.04735121749837, 45.6467424308921], [33.80199583830124, 94.11389417799832, 66.95510896864648], [31.934324162661458, 94.76391159230425, 89.88408369489096], [34.465261348238855, 93.8730299936973, 112.129816095113], [37.584878577685345, 92.66810078069287, 129.81302524607864], [34.76442821196357, 93.76264997905739, 147.223574108196], [33.921830158958535, 94.07076824745704, 167.36545102566686], [31.81206857237576, 94.80502251013108, 189.95083125203968], [33.807919537982364, 94.11176640842159, 212.57124554127284], [34.08001408422917, 94.01357689195078, 233.1435048617797], [33.7912654017101, 94.11774743666143, 253.72564508639465], [17.227853600937443, 98.50482759897946, 52.4555873421884], [13.783376774516714, 99.04553763139313, 90.1191962222661], [19.72881682971234, 98.03455404345786, 129.98468730013374], [16.735452147700688, 98.58967816872119, 172.6689841537882], [16.664342186017773, 98.60172259908703, 207.05379129229303], [17.201463406704146, 98.50943942926392, 246.03943188659505]]
+
+        vtx = [ geompy.MakeVertex(x,y,z) for x,y,z in tab]
+
+        theShape = geompy.MakeSmoothingSurface( vtx, 2, 8, 0)
+        CR = geompy.CanonicalRecognition()
+        recog,axis,pt,radius = CR.isCylinder(theShape, 0.1)
+        self.assertTrue( recog )
+        self.assertTrue( np.isclose(100,radius,rtol=1e-2, atol = 0) )
+        axisA = np.array(axis).reshape(1,3)
+        self.assertTrue( np.isclose( np.linalg.norm( axisA ) , 1.0 , rtol=1e-10, atol = 0 ) )
+        self.assertTrue( np.isclose( np.abs( np.dot( axisA.reshape(3), np.array([0,0,1]) ) ), 1.0 , rtol=1e-7, atol = 0 ) )
+        relDistOfPtToIdealAxis = np.linalg.norm( np.cross( axisA.reshape(3), np.array(pt) )/np.linalg.norm( np.array(pt) ) )
+        self.assertTrue( np.isclose( relDistOfPtToIdealAxis, 0.0, rtol = 0, atol = 1e-3 ) )
+
+if __name__ == '__main__':
+    unittest.main()
index 761c3421368e6261d1babc180fafe527f70bb876..b87d630e212477d48c2617d4f07265860e218903 100644 (file)
 
 SET(ALL_TESTS
   test_perf_01.py
-  test_point_cloud_on_face.py
   )
+
+IF(${OpenCASCADE_VERSION}.${OpenCASCADE_SP_VERSION} VERSION_GREATER "7.5.3.3")
+    LIST(APPEND ALL_TESTS
+      test_point_cloud_on_face.py
+      test_CR.py
+    )
+ENDIF()