Salome HOME
[bos #29473] [EDF] (2022-T1) Advanced geometry features: conformity of non holed...
authorAlexey SOZINOV <alexey.sozinov@opencascade.com>
Fri, 22 Apr 2022 10:12:04 +0000 (13:12 +0300)
committerjfa <jfa@opencascade.com>
Mon, 26 Sep 2022 14:43:15 +0000 (17:43 +0300)
24 files changed:
doc/salome/examples/check_conformity.py [new file with mode: 0644]
doc/salome/gui/GEOM/CMakeLists.txt
doc/salome/gui/GEOM/input/check_conformity.doc [new file with mode: 0644]
doc/salome/gui/GEOM/input/tui_check_conformity.doc [new file with mode: 0644]
doc/salome/gui/GEOM/input/tui_measurement_tools.doc
doc/salome/gui/GEOM/input/using_measurement_tools.doc
idl/GEOM_Gen.idl
src/GEOMImpl/CMakeLists.txt
src/GEOMImpl/GEOMImpl_ConformityDriver.cxx [new file with mode: 0644]
src/GEOMImpl/GEOMImpl_ConformityDriver.hxx [new file with mode: 0644]
src/GEOMImpl/GEOMImpl_Gen.cxx
src/GEOMImpl/GEOMImpl_IConformity.cxx [new file with mode: 0644]
src/GEOMImpl/GEOMImpl_IConformity.hxx [new file with mode: 0644]
src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx
src/GEOMImpl/GEOMImpl_Types.hxx
src/GEOM_I/GEOM_IMeasureOperations_i.cc
src/GEOM_I/GEOM_IMeasureOperations_i.hh
src/GEOM_SWIG/CMakeLists.txt
src/GEOM_SWIG/conformity.py [new file with mode: 0644]
src/GEOM_SWIG/geomBuilder.py
test/data/test_twisted_face.brep [new file with mode: 0644]
test/test_conformity.py [new file with mode: 0644]
test/tests.set

diff --git a/doc/salome/examples/check_conformity.py b/doc/salome/examples/check_conformity.py
new file mode 100644 (file)
index 0000000..f2b8ab9
--- /dev/null
@@ -0,0 +1,45 @@
+# Check Conformity
+
+import salome
+salome.salome_init_without_session()
+import GEOM
+from salome.geom import geomBuilder
+geompy = geomBuilder.New()
+
+O = geompy.MakeVertex(0, 0, 0)
+OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+Vertex_1 = geompy.MakeVertex(-30, -70, 0)
+Vertex_2 = geompy.MakeVertex(-30, 50, 0)
+Line_1 = geompy.MakeLineTwoPnt(Vertex_2, Vertex_1)
+Vertex_3 = geompy.MakeVertex(0, -50, 0)
+Vertex_4 = geompy.MakeVertex(-40, -10, 0)
+Vertex_5 = geompy.MakeVertex(0, 40, 0)
+Arc_1 = geompy.MakeArc(Vertex_5, Vertex_4, Vertex_3)
+Vertex_6 = geompy.MakeVertex(10, -50, 4)
+Vertex_7 = geompy.MakeVertex(10, -50, 10)
+Vertex_8 = geompy.MakeVertex(10, 40, 10)
+Arc_1_vertex_3 = geompy.GetSubShape(Arc_1, [3])
+Line_2 = geompy.MakeLineTwoPnt(Arc_1_vertex_3, Vertex_6)
+Line_3 = geompy.MakeLineTwoPnt(Vertex_6, Vertex_7)
+Line_4 = geompy.MakeLineTwoPnt(Vertex_7, Vertex_8)
+Vertex_9 = geompy.MakeVertex(15, 40, 10)
+Vertex_10 = geompy.MakeVertex(17, 0, 6)
+Vertex_11 = geompy.MakeVertex(17, 0, 3)
+Line_5 = geompy.MakeLineTwoPnt(Vertex_8, Vertex_9)
+Line_6 = geompy.MakeLineTwoPnt(Vertex_9, Vertex_10)
+Line_7 = geompy.MakeLineTwoPnt(Vertex_10, Vertex_11)
+Arc_1_vertex_2 = geompy.GetSubShape(Arc_1, [2])
+Line_8 = geompy.MakeLineTwoPnt(Vertex_11, Arc_1_vertex_2)
+Wire_1 = geompy.MakeWire([Arc_1, Line_2, Line_3, Line_4, Line_5, Line_6, Line_7, Line_8], 1e-07)
+Wire_2 = geompy.MakeWire([Line_1], 1e-07)
+Compound_1 = geompy.MakeCompound([Wire_1, Wire_2])
+
+# Get CheckConformity tool
+cc = geompy.CheckConformity(Compound_1)
+valid = cc.isValid()
+dist = cc.distantShapes()
+small = cc.smallEdges()
+interfer = cc.interferingSubshapes()
+intersect = cc.selfIntersected2D()
index 7343b1cb6c30bc23fd614b7484d558190ec72301..3fe599dc5ba9146b0222689984ed005b011236ab 100644 (file)
@@ -59,13 +59,14 @@ ENDIF(WIN32)
 
 ADD_CUSTOM_TARGET(usr_docs ${CMAKE_COMMAND} -E make_directory tmp
   COMMAND ${CMAKE_COMMAND} -E make_directory tmp1
-  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/geomBuilder.py ${CMAKE_SOURCE_DIR}/src/GEOM_SWIG/geomBuilder.py
-  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/gsketcher.py   ${CMAKE_SOURCE_DIR}/src/GEOM_SWIG/gsketcher.py
-  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/geomtools.py   ${CMAKE_SOURCE_DIR}/src/GEOM_PY/geomtools.py
-  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/sketcher.py    ${CMAKE_SOURCE_DIR}/src/GEOM_PY/sketcher.py
-  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/structelem.py  ${CMAKE_SOURCE_DIR}/src/GEOM_PY/structelem/__init__.py
-  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/parts.py       ${CMAKE_SOURCE_DIR}/src/GEOM_PY/structelem/parts.py
-  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/orientation.py ${CMAKE_SOURCE_DIR}/src/GEOM_PY/structelem/orientation.py
+  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/geomBuilder.py     ${CMAKE_SOURCE_DIR}/src/GEOM_SWIG/geomBuilder.py
+  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/gsketcher.py       ${CMAKE_SOURCE_DIR}/src/GEOM_SWIG/gsketcher.py
+  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/conformity.py ${CMAKE_SOURCE_DIR}/src/GEOM_SWIG/conformity.py
+  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/geomtools.py       ${CMAKE_SOURCE_DIR}/src/GEOM_PY/geomtools.py
+  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/sketcher.py        ${CMAKE_SOURCE_DIR}/src/GEOM_PY/sketcher.py
+  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/structelem.py      ${CMAKE_SOURCE_DIR}/src/GEOM_PY/structelem/__init__.py
+  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/parts.py           ${CMAKE_SOURCE_DIR}/src/GEOM_PY/structelem/parts.py
+  COMMAND ${PYTHON_EXECUTABLE} ${f} -o tmp/orientation.py     ${CMAKE_SOURCE_DIR}/src/GEOM_PY/structelem/orientation.py
   COMMAND ${plugins_cmd}
   COMMAND ${DOXYGEN_EXECUTABLE} doxyfile_tui 
   COMMAND ${DOXYGEN_EXECUTABLE} doxyfile_py
diff --git a/doc/salome/gui/GEOM/input/check_conformity.doc b/doc/salome/gui/GEOM/input/check_conformity.doc
new file mode 100644 (file)
index 0000000..5722539
--- /dev/null
@@ -0,0 +1,55 @@
+/*! 
+
+\page check_conformity_page Check Conformity
+
+The Check Conformity tool provides the user with a simple python API to analyze, available shape for Boolean Operations or not. \n
+Also tool provide advanced output to indicate imperfections in the input shape.
+
+This is just a TUI functionality.
+
+<b>TUI Commands:</b>
+
+<UL>
+
+<LI> 
+<em>geompy.CheckConformity(shape),</em> \n
+where \n
+\em shape is the shape checked for validity. \n
+</LI>
+
+The following functionality is available from the tool:
+<LI>
+<em>geompy.isValid()</em> 
+
+</LI>
+
+<LI>
+<em>geompy.selfIntersected2D()</em> 
+</LI>
+
+<LI>
+<em>geompy.interferingSubshapes(shapeType1, shapeType2),</em> 
+where \n
+\em shapeType1 is the first type of subshape. \n
+\em shapeType2 is the second type of subshape. \n 
+</LI>
+
+<LI>
+<em>geompy.smallEdges()</em> 
+</LI>
+
+<LI>
+<em>geompy.distantShapes(shapeType, subShapeType, tolerance),</em> 
+where \n
+\em shapeType is the type of shape. \n
+\em subShapeType is the type of subshape. \n
+\em tolerance is available tolerance, by default used tolerance of sub-shape.
+</LI>
+
+<LI>
+<em>geompy.updateTolerance()</em> 
+</LI>
+</UL>
+See also a \ref tui_check_conformity_page "TUI example".
+
+*/
diff --git a/doc/salome/gui/GEOM/input/tui_check_conformity.doc b/doc/salome/gui/GEOM/input/tui_check_conformity.doc
new file mode 100644 (file)
index 0000000..70513e8
--- /dev/null
@@ -0,0 +1,6 @@
+/*!
+
+\page tui_check_conformity_page Check Conformity
+\tui_script{check_conformity.py}
+
+*/
index be111dbb16e2372e877388ae8a4dfcca6feaa3a1..3966c9c0feb209d4941ee806860a4576566515f1 100644 (file)
@@ -21,6 +21,7 @@
 <li>\subpage tui_check_self_intersections_page</li>
 <li>\subpage tui_check_self_intersections_fast_page</li>
 <li>\subpage tui_fast_intersection_page</li>
+<li>\subpage tui_check_conformity_page</li>
 </ul>
 
 */
index feca9e24f5282ecc5e9f03de9051eb1eef8fe379..11803eec225f0245527a067d7ab4f6a70f53d4a9 100644 (file)
@@ -29,6 +29,7 @@
 <li>\subpage boundaries_page "Check Free Boundaries"</li>
 <li>\subpage free_faces_page "Check Free Faces"</li>
 <li>\subpage check_shape_page "Check Shape"</li>
+<li>\subpage check_conformity_page "Check Conformity"</li>
 <li>\subpage check_compound_of_blocks_page "Check compound of blocks"</li>
 <li>\subpage get_non_blocks_page "Get non blocks"</li>
 <li>\subpage check_self_intersections_page "Detect Self-intersections"</li>
index 7423266a40e83d282b5ecf86ecad0da9e07e14da..89a1e777950838776ea50635979880ba45957b67 100644 (file)
@@ -4745,6 +4745,94 @@ module GEOM
                                                      in GEOM_Object thePoint,
                                                      in GEOM_Object theDirection);
 
+    //! Methods and structure for implement CheckConformity tool
+
+    /*!
+    *  \brief Structure for store shapes from failed checks.
+    *         If failed check on small edges, then second shape is null
+    */
+    struct PairOfShape
+    {
+      GEOM_Object first;
+      GEOM_Object second;
+    };
+
+    /*!
+    *  \brief Structure for store result of check
+    *  store type of check as number and failed shapes
+    */
+    struct CheckResult
+    {
+      long  type;
+      PairOfShape failedShapes;
+    };
+
+    typedef sequence<PairOfShape> SequenceOfPairOfShape;
+    typedef sequence<CheckResult> CheckResults;
+
+    /*!
+    *  \brief Perform analyse of shape and return all failed checks.
+    *
+    *  \param theShape Shape for check.
+    */
+    CheckResults CheckConformityShape(in GEOM_Object theShape);
+
+    /*!
+    *  \brief Find all self-intersected 2D curves.
+    *
+    *  \param theResults result of check - list of failed checks and sub-shapes.
+    */
+    SequenceOfPairOfShape SelfIntersected2D(in CheckResults theResults);
+
+    /*!
+    *  \brief Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned.
+    *         Avaliable types:
+    *         - vertices touched by tolerance;
+    *         - vertex touching an edge in the inner point;
+    *         - vertex lying on the inner point of a face;
+    *         - edges intersecting by inner points;
+    *         - edge touching/intersecting face in the inner point;
+    *         - faces intersection by inner point
+    * 
+    *  \param theResults result of check - list of failed checks and sub-shapes.
+    *  \param theShapeType1 Type of shape.
+    *  \param theShapeType2 Type of shape.
+    */
+    SequenceOfPairOfShape InterferingSubshapes(in CheckResults theResults,
+                                               in long theShapeType1,
+                                               in long theShapeType2);
+
+    /*!
+    *  \brief Find edges, which are fully covered by tolerances of vertices.
+    *
+    *  \param theResults result of check - list of failed checks and sub-shapes.
+    */
+    ListOfGO SmallEdges(in CheckResults theResults);
+
+    /*!
+    *  \brief find remote objects (sub-shape on a shape).
+    *         Avaliable types:
+    *         - vertex far from edge;
+    *         - vertex far from face;
+    *         - edge far from face
+    *
+    *  \param theResults result of check - list of failed checks and sub-shapes.
+    *  \param theShapeType Type of shape.
+    *  \param theSubShapeType Type of sub-shape.
+    *  \param theTolerance tolerance, by default used tolerance of sub-shape.
+    */
+    SequenceOfPairOfShape DistantShapes(in CheckResults theResults,
+                                        in long theShapeType,
+                                        in long theSubShapeType,
+                                        in double theTolerance);
+
+    /*!
+    *  \brief Compute possible tolerance for the shape, minimize tolerance of shape as well
+    *         as tolerance of sub-shapes as much as possible
+    *
+    *  \param theShape Shape for update.
+    */
+    double UpdateTolerance(in GEOM_Object theShape);
   };
 
  // # GEOM_IGroupOperations:
index 98e47cea33c888d99aaad2d04d266a482214a526..6dbbae81ed19136ec63e2e9be83fafebe878ad65 100644 (file)
@@ -120,6 +120,7 @@ SET(GEOMImpl_HEADERS
   GEOMImpl_IPipePath.hxx
   GEOMImpl_IRevolution.hxx
   GEOMImpl_IMeasure.hxx
+  GEOMImpl_IConformity.hxx
   GEOMImpl_IShapes.hxx
   GEOMImpl_IShapeExtend.hxx
   GEOMImpl_IFilling.hxx
@@ -156,6 +157,7 @@ SET(GEOMImpl_HEADERS
   GEOMImpl_BlockDriver.hxx
   GEOMImpl_Block6Explorer.hxx
   GEOMImpl_MeasureDriver.hxx
+  GEOMImpl_ConformityDriver.hxx
   GEOMImpl_PolylineDriver.hxx
   GEOMImpl_PolylineDumper.hxx
   GEOMImpl_CircleDriver.hxx
@@ -205,6 +207,7 @@ SET(GEOMImpl_SOURCES
   GEOMImpl_ITestOperations.cxx
   GEOMImpl_IPolyline2D.cxx
   GEOMImpl_ITransferData.cxx
+  GEOMImpl_IConformity.cxx
   GEOMImpl_Gen.cxx
   GEOMImpl_PointDriver.cxx
   GEOMImpl_VectorDriver.cxx
@@ -233,6 +236,7 @@ SET(GEOMImpl_SOURCES
   GEOMImpl_BlockDriver.cxx
   GEOMImpl_Block6Explorer.cxx
   GEOMImpl_MeasureDriver.cxx
+  GEOMImpl_ConformityDriver.cxx
   GEOMImpl_PolylineDriver.cxx
   GEOMImpl_PolylineDumper.cxx
   GEOMImpl_CircleDriver.cxx
diff --git a/src/GEOMImpl/GEOMImpl_ConformityDriver.cxx b/src/GEOMImpl/GEOMImpl_ConformityDriver.cxx
new file mode 100644 (file)
index 0000000..003e204
--- /dev/null
@@ -0,0 +1,253 @@
+// Copyright (C) 2013-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
+//
+
+#include "GEOMImpl_ConformityDriver.hxx"
+
+// internal includes
+#include "GEOMImpl_IConformity.hxx"
+
+// KERNEL includes
+#include <utilities.h>
+#include <Basics_Utils.hxx>
+
+// GEOM includes
+#include "GEOM_Function.hxx"
+#include "GEOMImpl_Types.hxx"
+
+#include <BOPAlgo_ArgumentAnalyzer.hxx>
+#include <BRepTools.hxx>
+#include <BRepTools_ReShape.hxx>
+#include <BRepLib.hxx>
+#include <BRep_Tool.hxx>
+
+#include <TopExp_Explorer.hxx>
+#include <GEOMUtils.hxx>
+#include <TColStd_HArray2OfInteger.hxx>
+
+namespace
+{
+  //=======================================================================
+  //function : ConvertShapesToIndices
+  //purpose  : Convert sub-shapes of shapes to sequence of indices
+  //=======================================================================
+  Handle(TColStd_HArray1OfInteger) ConvertShapesToIndices(const TopoDS_Shape& theShape,
+                                                          const TopTools_ListOfShape& theShapes)
+  {
+    Handle(TColStd_HArray1OfInteger) aSeqOfIDs = new TColStd_HArray1OfInteger(1, theShapes.Size());
+
+    TopTools_IndexedMapOfShape anIndices;
+    TopExp::MapShapes(theShape, anIndices);
+
+    TopTools_ListIteratorOfListOfShape itSub(theShapes);
+    for (int index = 1; itSub.More(); itSub.Next(), ++index)
+    {
+      int id = anIndices.FindIndex(itSub.Value());
+      aSeqOfIDs->SetValue(index, id);
+    }
+
+    return aSeqOfIDs;
+  }
+
+  //=======================================================================
+  //function : ConvertShapesToIndices
+  //purpose  : Convert list of pair shapes to sequence of indices
+  //=======================================================================
+  Handle(TColStd_HArray2OfInteger) ConvertShapesToIndices(
+    const TopoDS_Shape& theShape,
+    const NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>>& theShapes)
+  {
+    Handle(TColStd_HArray2OfInteger) aSeqOfIDs = new TColStd_HArray2OfInteger(1, theShapes.Size(), 1, 2);
+
+    TopTools_IndexedMapOfShape anIndices;
+    TopExp::MapShapes(theShape, anIndices);
+
+    NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>>::Iterator itSub(theShapes);
+    for (int index = 1; itSub.More(); itSub.Next(), ++index)
+    {
+      int anID1 = anIndices.FindIndex(itSub.Value().first);
+      aSeqOfIDs->SetValue(index, 1, anID1);
+
+      int anID2 = anIndices.FindIndex(itSub.Value().second);
+      aSeqOfIDs->SetValue(index, 2, anID2);
+    }
+
+    return aSeqOfIDs;
+  }
+}
+
+//=======================================================================
+//function : GetID
+//purpose  :
+//=======================================================================
+const Standard_GUID& GEOMImpl_ConformityDriver::GetID()
+{
+  static Standard_GUID aGUID("B77BABDA-C0A1-4E65-9B1E-7EFC4448077E");
+  return aGUID;
+}
+
+//=======================================================================
+//function : GEOMImpl_ConformityDriver
+//purpose  :
+//=======================================================================
+GEOMImpl_ConformityDriver::GEOMImpl_ConformityDriver()
+{
+}
+
+//=======================================================================
+//function : Execute
+//purpose  :
+//=======================================================================
+Standard_Integer GEOMImpl_ConformityDriver::Execute(Handle(TFunction_Logbook)& log) const
+{
+  if (Label().IsNull()) return 0;
+  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
+  GEOMImpl_IConformity aCI(aFunction);
+
+  Standard_Integer aType = aFunction->GetType();
+
+  Handle(GEOM_Function) aRefShape = aCI.GetShape();
+  if (aRefShape.IsNull()) return 0;
+
+  TopoDS_Shape aShape = aRefShape->GetValue();
+
+  switch (aType)
+  {
+  case CONFORMITY_UPDATE_TOL:
+  {
+    Standard_Real aTolerance = updateTolerance(aShape);
+    aFunction->SetReal(CHECKCONFORMITY_RET_TOLERANCE, aTolerance);
+  }
+  break;
+  case CONFORMITY_CHECK_SHAPE:
+  {
+    NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>> aFailedShape;
+    Handle(TColStd_HArray1OfInteger) aTypesOfCheck;
+    checkShape(aShape, aFailedShape, aTypesOfCheck);
+
+    Handle(TColStd_HArray2OfInteger) anArray = ConvertShapesToIndices(aShape, aFailedShape);
+    aFunction->SetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS, aTypesOfCheck);
+    aCI.SetListOfShapesIndices(anArray);
+  }
+  }
+
+  return 1;
+}
+
+//=======================================================================
+//function : checkShape
+//purpose  :
+//=======================================================================
+void GEOMImpl_ConformityDriver::checkShape(const TopoDS_Shape & theShape,
+                                           NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>>& theFailedShape,
+                                           Handle(TColStd_HArray1OfInteger)& theTypesOfCheck) const
+{
+  BOPAlgo_ArgumentAnalyzer anAnalyzer;
+  performAnalyze(theShape, anAnalyzer);
+
+  const BOPAlgo_ListOfCheckResult& aResult = anAnalyzer.GetCheckResult();
+  theTypesOfCheck = new TColStd_HArray1OfInteger(1, aResult.Size());
+
+  BOPAlgo_ListOfCheckResult::Iterator anIter(aResult);
+  for (int index = 1; anIter.More(); anIter.Next(), ++index)
+  {
+    theTypesOfCheck->SetValue(index, anIter.Value().GetCheckStatus());
+    std::pair<TopoDS_Shape, TopoDS_Shape> aPair;
+    aPair.first = anIter.Value().GetFaultyShapes1().First();
+    if (anIter.Value().GetFaultyShapes1().Size() != 1)
+      aPair.second = anIter.Value().GetFaultyShapes1().Last();
+    theFailedShape.Append(aPair);
+  }
+}
+
+//=======================================================================
+//function : updateTolerance
+//purpose  :
+//=======================================================================
+Standard_Real GEOMImpl_ConformityDriver::updateTolerance(const TopoDS_Shape& theShape) const
+{
+  Standard_Real aTolerance = INFINITY;
+
+  TopoDS_Shape aResShape = theShape;
+
+  BRepLib::UpdateTolerances(aResShape, Standard_False);
+
+  for (const auto& aType : { TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE })
+  {
+    for (TopExp_Explorer anExp(aResShape, aType); anExp.More(); anExp.Next())
+    {
+      Standard_Real aCurTolerance = INFINITY;
+      switch (aType)
+      {
+      case TopAbs_VERTEX:
+        aCurTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(anExp.Value()));
+        break;
+      case TopAbs_EDGE:
+        aCurTolerance = BRep_Tool::Tolerance(TopoDS::Edge(anExp.Value()));
+        break;
+      case TopAbs_FACE:
+        aCurTolerance = BRep_Tool::Tolerance(TopoDS::Face(anExp.Value()));
+        break;
+      }
+      aTolerance = Min(aTolerance, aCurTolerance);
+    }
+  }
+
+  TopoDS_Shape aShape = theShape;
+  GEOMUtils::FixShapeTolerance(aShape, aTolerance, Standard_True);
+
+  Standard_Real aResTol = 0.;
+  for (const auto& aType : { TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE })
+  {
+    for (TopExp_Explorer anExp(aShape, aType); anExp.More(); anExp.Next())
+    {
+      Standard_Real aCurTolerance = INFINITY;
+      switch (aType)
+      {
+      case TopAbs_VERTEX:
+        aCurTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(anExp.Value()));
+        break;
+      case TopAbs_EDGE:
+        aCurTolerance = BRep_Tool::Tolerance(TopoDS::Edge(anExp.Value()));
+        break;
+      case TopAbs_FACE:
+        aCurTolerance = BRep_Tool::Tolerance(TopoDS::Face(anExp.Value()));
+        break;
+      }
+      aResTol = Max(aResTol, aCurTolerance);
+    }
+  }
+
+  return aResTol;
+}
+
+//=======================================================================
+//function : performAnalyze
+//purpose  : 
+//=======================================================================
+void GEOMImpl_ConformityDriver::performAnalyze(const TopoDS_Shape& theShape,
+                                               BOPAlgo_ArgumentAnalyzer& theAnalyzer) const
+{
+  theAnalyzer.SetShape1(theShape);
+
+  theAnalyzer.CurveOnSurfaceMode() = Standard_True;
+  theAnalyzer.SelfInterMode() = Standard_True;
+  theAnalyzer.SmallEdgeMode() = Standard_True;
+
+  theAnalyzer.Perform();
+}
diff --git a/src/GEOMImpl/GEOMImpl_ConformityDriver.hxx b/src/GEOMImpl/GEOMImpl_ConformityDriver.hxx
new file mode 100644 (file)
index 0000000..40734c3
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright (C) 2013-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
+//
+
+#ifndef _GEOMImpl_ConformityDriver_HXX_
+#define _GEOMImpl_ConformityDriver_HXX_
+
+#include "GEOM_BaseDriver.hxx"
+
+#include <Standard_Transient.hxx>
+#include <TopoDS_Shape.hxx>
+
+#include <BOPAlgo_ArgumentAnalyzer.hxx>
+
+DEFINE_STANDARD_HANDLE(GEOMImpl_ConformityDriver, GEOM_BaseDriver)
+
+class GEOMImpl_ConformityDriver : public GEOM_BaseDriver
+{
+
+public:
+  Standard_EXPORT GEOMImpl_ConformityDriver();
+  Standard_EXPORT ~GEOMImpl_ConformityDriver() {};
+
+  Standard_EXPORT static const Standard_GUID& GetID();
+  Standard_EXPORT virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
+  Standard_EXPORT Standard_Boolean         MustExecute(const Handle(TFunction_Logbook)&) const { return Standard_True; }
+  Standard_EXPORT virtual void             Validate(Handle(TFunction_Logbook)&) const {}
+
+private:
+  Standard_EXPORT void checkShape(const TopoDS_Shape& theShape,
+                                  NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>>& theFailedShape,
+                                  Handle(TColStd_HArray1OfInteger)& theTypesOfCheck) const;
+
+  Standard_EXPORT Standard_Real updateTolerance(const TopoDS_Shape& theShape) const;
+
+  Standard_EXPORT  virtual bool GetCreationInformation(std::string& /*theOperationName*/,
+                                                       std::vector<GEOM_Param>& /*params*/)
+  {
+    return Standard_False;
+  }
+
+private:
+  void performAnalyze(const TopoDS_Shape& theShape, BOPAlgo_ArgumentAnalyzer& theAnalyzer) const;
+
+};
+
+#endif // _GEOMImpl_ConformityDriver_HXX_
index 74aceaf120e9a8e3fb4310a0ce82db0c9857202a..7df117c33a0cf95055e099ae18427c9cd69df65b 100644 (file)
@@ -83,6 +83,7 @@
 #include <GEOMImpl_GlueDriver.hxx>
 #include <GEOMImpl_MeasureDriver.hxx>
 #include <GEOMImpl_FieldDriver.hxx>
+#include <GEOMImpl_ConformityDriver.hxx>
 
 //=============================================================================
 /*!
@@ -163,6 +164,7 @@ GEOMImpl_Gen::GEOMImpl_Gen()
    // Measurements
    TFunction_DriverTable::Get()->AddDriver(GEOMImpl_MeasureDriver::GetID(), new GEOMImpl_MeasureDriver());
    TFunction_DriverTable::Get()->AddDriver(GEOMImpl_PatchFaceDriver::GetID(), new GEOMImpl_PatchFaceDriver());
+   TFunction_DriverTable::Get()->AddDriver(GEOMImpl_ConformityDriver::GetID(), new GEOMImpl_ConformityDriver());
 
    // Field
    TFunction_DriverTable::Get()->AddDriver(GEOMImpl_FieldDriver::GetID(), new GEOMImpl_FieldDriver());
diff --git a/src/GEOMImpl/GEOMImpl_IConformity.cxx b/src/GEOMImpl/GEOMImpl_IConformity.cxx
new file mode 100644 (file)
index 0000000..4a80e95
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (C) 2013-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
+//
+#include "GEOMImpl_IConformity.hxx"
+
+//=============================================================================
+/*!
+ *  SetListOfShapesIndices
+ *  Input 2D array of indexes converted into 1D array
+ */
+ //=============================================================================
+void GEOMImpl_IConformity::SetListOfShapesIndices(const Handle(TColStd_HArray2OfInteger)& theArrayOfIndexes)
+{
+  Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1, theArrayOfIndexes->Size());
+
+  for (Standard_Integer aRow = 1; aRow <= theArrayOfIndexes->NbRows(); ++aRow)
+  {
+    anArray->SetValue(2 * aRow - 1, theArrayOfIndexes->Value(aRow, 1));
+    anArray->SetValue(2 * aRow, theArrayOfIndexes->Value(aRow, 2));
+  }
+
+  _func->SetIntegerArray(CHECKCONFORMITY_RET_LIST_OF_INDEXES, anArray);
+}
+
+//=============================================================================
+/*!
+ *  GetListOfShapesIndices
+ *  Get cached 1D array of indexes and converted into 2D array of indexes
+ */
+ //=============================================================================
+Handle(TColStd_HArray2OfInteger) GEOMImpl_IConformity::GetListOfShapesIndices()
+{
+  Handle(TColStd_HArray1OfInteger) anArray = _func->GetIntegerArray(CHECKCONFORMITY_RET_LIST_OF_INDEXES);
+
+  Standard_Integer aLength = anArray->Size() / 2;
+  Handle(TColStd_HArray2OfInteger) aResArray = new TColStd_HArray2OfInteger(1, aLength, 1, 2);
+
+  for (Standard_Integer anIndex = 1; anIndex <= aLength; ++anIndex)
+  {
+    aResArray->SetValue(anIndex, 1, anArray->Value(2 * anIndex - 1));
+    aResArray->SetValue(anIndex, 2, anArray->Value(2 * anIndex));
+  }
+
+  return aResArray;
+}
\ No newline at end of file
diff --git a/src/GEOMImpl/GEOMImpl_IConformity.hxx b/src/GEOMImpl/GEOMImpl_IConformity.hxx
new file mode 100644 (file)
index 0000000..f9f3435
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright (C) 2013-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
+//
+
+#ifndef _GEOMImpl_IConformity_HXX_
+#define _GEOMImpl_IConformity_HXX_
+
+#include "GEOM_Function.hxx"
+#include <TColStd_HArray2OfInteger.hxx>
+#include <TColStd_HArray2OfTransient.hxx>
+
+#define CHECKCONFORMITY_ARG_SHAPE 1
+#define CHECKCONFORMITY_ARG_SHAPETYPE_1 2
+#define CHECKCONFORMITY_ARG_SHAPETYPE_2 3
+#define CHECKCONFORMITY_ARG_TOLERANCE 4
+
+#define CHECKCONFORMITY_RET_TOLERANCE 5
+#define CHECKCONFORMITY_RET_ISVALID 6
+#define CHECKCONFORMITY_RET_SHAPES_IDS 7
+#define CHECKCONFORMITY_RET_TYPES_CHECKS 8
+#define CHECKCONFORMITY_RET_LIST_OF_INDEXES 9
+#define CHECKCONFORMITY_RET_LIST_SHAPES 10
+
+class GEOMImpl_IConformity
+{
+public:
+  GEOMImpl_IConformity(Handle(GEOM_Function) theFunction)
+    : _func(theFunction)
+  {
+  }
+
+  void SetShape(Handle(GEOM_Function) theRef)
+  {
+    _func->SetReference(CHECKCONFORMITY_ARG_SHAPE, theRef);
+  }
+  Handle(GEOM_Function) GetShape()
+  {
+    return _func->GetReference(CHECKCONFORMITY_ARG_SHAPE);
+  }
+
+  void SetShapeType1(int theShapeType) { _func->SetInteger(CHECKCONFORMITY_ARG_SHAPETYPE_1, theShapeType); }
+  Standard_Integer GetShapeType1() { return _func->GetInteger(CHECKCONFORMITY_ARG_SHAPETYPE_1); }
+  void SetShapeType2(int theShapeType) { _func->SetInteger(CHECKCONFORMITY_ARG_SHAPETYPE_2, theShapeType); }
+  Standard_Integer GetShapeType2() { return _func->GetInteger(CHECKCONFORMITY_ARG_SHAPETYPE_2); }
+  void SetTolerance(double theTolerance) { _func->SetReal(CHECKCONFORMITY_ARG_TOLERANCE, theTolerance); }
+  Standard_Real GetTolerance() { return _func->GetReal(CHECKCONFORMITY_ARG_TOLERANCE); }
+
+  void SetListOfShapesIndices(const Handle(TColStd_HArray2OfInteger)& theArrayOfIndexes);
+  Handle(TColStd_HArray2OfInteger) GetListOfShapesIndices();
+
+private:
+  Handle(GEOM_Function) _func;
+};
+
+#endif // _GEOMImpl_IConformity_HXX_
index aa141c2888c9a1ba326fda763f96b421452dbc61..1c8c7add37667c3ecbc3179336a1e8b890cb29c8 100644 (file)
@@ -29,6 +29,9 @@
 
 #include <GEOMImpl_Types.hxx>
 
+#include <GEOMImpl_IConformity.hxx>
+#include <GEOMImpl_ConformityDriver.hxx>
+
 #include <GEOMUtils.hxx>
 
 #include <GEOMAlgo_AlgoTools.hxx>
@@ -46,6 +49,7 @@
 #include <BOPDS_DS.hxx>
 #include <BOPDS_MapOfPair.hxx>
 #include <BOPDS_Pair.hxx>
+#include <BOPTools_AlgoTools.hxx>
 #include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_Copy.hxx>
 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
@@ -2787,6 +2791,339 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::SurfaceCurvatureByPointAndDirec
   return aCV;
 }
 
+//=============================================================================
+/*!
+ *  SelfIntersected2D
+ *  Find all self-intersected 2D curves.
+ *  \param theChecks list of failed checks, contains type of check and failed shapes
+ */
+ //=============================================================================
+std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
+  GEOMImpl_IMeasureOperations::SelfIntersected2D(const std::list<FailedChecks>& theChecks)
+{
+  SetErrorCode(KO);
+  MESSAGE("GEOMImpl_IMeasureOperations::selfIntersected2D");
+
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aSelfInters2D;
+  try
+  {
+    OCC_CATCH_SIGNALS;
+    for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
+         anIter != theChecks.end(); ++anIter)
+    {
+      if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
+        aSelfInters2D.push_back(anIter->FailedShapes);
+    }
+  }
+  catch (Standard_Failure& aFail)
+  {
+    SetErrorCode(aFail.GetMessageString());
+    return aSelfInters2D;
+  }
+
+  SetErrorCode(OK);
+  return aSelfInters2D;
+}
+
+namespace
+{
+  static bool checkTypes(const GEOMImpl_IMeasureOperations::CoupleOfObjects& theShapes,
+                         const int theShapeType1,
+                         const int theShapeType2)
+  {
+    if (theShapeType1 == -1 && theShapeType2 == -1)
+      return true;
+
+    TopAbs_ShapeEnum aShapeType1 = theShapes.first.IsNull()
+      ? TopAbs_SHAPE
+      : theShapes.first->GetValue().ShapeType();
+    TopAbs_ShapeEnum aShapeType2 = theShapes.second.IsNull()
+      ? TopAbs_SHAPE
+      : theShapes.second->GetValue().ShapeType();
+
+    if (theShapeType1 == -1)
+      return aShapeType1 == theShapeType2 || aShapeType2 == theShapeType2;
+    else if (theShapeType2 == -1)
+      return aShapeType1 == theShapeType1 || aShapeType2 == theShapeType1;
+    return (aShapeType1 == theShapeType1 && aShapeType2 == theShapeType2) ||
+      (aShapeType1 == theShapeType2 && aShapeType2 == theShapeType1);
+  }
+} // namespace
+
+//=============================================================================
+/*!
+ *  InterferingSubshapes
+ *  Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned.
+ *  \param theChecks list of failed checks, contains type of check and failed shapes
+ *  \param theShapeType1 Type of shape.
+ *  \param theShapeType2 Type of shape.
+ */
+ //=============================================================================
+std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
+  GEOMImpl_IMeasureOperations::InterferingSubshapes
+    (const std::list<FailedChecks>& theChecks,
+     const int                      theShapeType1,
+     const int                      theShapeType2)
+{
+  SetErrorCode(KO);
+  MESSAGE("GEOMImpl_IMeasureOperations::interferingSubshapes");
+
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> anInterfer;
+  try
+  {
+    OCC_CATCH_SIGNALS;
+    for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
+         anIter != theChecks.end(); ++anIter)
+    {
+      if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_SelfIntersect &&
+          checkTypes(anIter->FailedShapes, theShapeType1, theShapeType2))
+        anInterfer.push_back(anIter->FailedShapes);
+    }
+  }
+  catch (Standard_Failure& aFail)
+  {
+    SetErrorCode(aFail.GetMessageString());
+    return anInterfer;
+  }
+
+  SetErrorCode(OK);
+  return anInterfer;
+}
+
+//=============================================================================
+/*!
+ *  SmallEdges
+ *  Find edges, which are fully covered by tolerances of vertices.
+ *  \param theChecks list of failed checks, contains type of check and failed shapes
+ */
+ //=============================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::SmallEdges(
+    const std::list<FailedChecks>& theChecks)
+{
+  SetErrorCode(KO);
+  MESSAGE("GEOMImpl_IMeasureOperations::smallEdges");
+
+  Handle(TColStd_HSequenceOfTransient) aSmallEdges = new TColStd_HSequenceOfTransient;
+  try
+  {
+    OCC_CATCH_SIGNALS;
+    for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
+         anIter != theChecks.end(); ++anIter)
+    {
+      if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_TooSmallEdge)
+        aSmallEdges->Append(anIter->FailedShapes.first);
+    }
+  }
+  catch (Standard_Failure& aFail)
+  {
+    SetErrorCode(aFail.GetMessageString());
+    return NULL;
+  }
+
+  SetErrorCode(OK);
+  return aSmallEdges;
+}
+
+//=============================================================================
+/*!
+ *  DistantShapes
+ *  find remote objects (sub-shape on a shape).
+ *  \param theShape Shape for check.
+ *  \param theShapeType Type of shape.
+ *  \param theSubShapeType Type of sub-shape.
+ *  \param theTolerance tolerance.
+ */
+ //=============================================================================
+std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
+  GEOMImpl_IMeasureOperations::DistantShapes
+    (const std::list<FailedChecks>& theChecks,
+     const int                      theShapeType,
+     const int                      theSubShapeType,
+     double                         theTolerance)
+{
+  SetErrorCode(KO);
+  MESSAGE("GEOMImpl_IMeasureOperations::distantShapes");
+
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aDistShapes;
+  try
+  {
+    OCC_CATCH_SIGNALS;
+    for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
+         anIter != theChecks.end(); ++anIter)
+    {
+      Handle(GEOM_Object) aSubShape = anIter->FailedShapes.first;
+      Handle(GEOM_Object) aShape = anIter->FailedShapes.second;
+      if ((anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface ||
+           anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfVertex ||
+           anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfEdge ||
+           anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfFace) &&
+          aShape && (theShapeType == -1 || aShape->GetValue().ShapeType() == theShapeType) &&
+          aSubShape && (theSubShapeType == -1 || aSubShape->GetValue().ShapeType() == theSubShapeType))
+      {
+        gp_XYZ aP1, aP2;
+        Standard_Real aDist = Precision::Infinite();
+        if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
+          aDist = ComputeTolerance(aSubShape, aShape);
+        if (aDist > theTolerance)
+          aDistShapes.push_back(anIter->FailedShapes);
+      }
+    }
+  }
+  catch (Standard_Failure& aFail)
+  {
+    SetErrorCode(aFail.GetMessageString());
+    return aDistShapes;
+  }
+
+  SetErrorCode(OK);
+  return aDistShapes;
+}
+
+//=============================================================================
+/*!
+ *  CheckConformityShape
+ *  Perform analyse of shape and find imperfections in the shape.
+ *  \param theShape Shape for analyse.
+ */
+ //=============================================================================
+void GEOMImpl_IMeasureOperations::CheckConformityShape(Handle(GEOM_Object) theShape, std::list<FailedChecks>& theChecks)
+{
+  SetErrorCode(KO);
+  MESSAGE("GEOMImpl_IMeasureOperations::checkShape");
+
+  Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
+  Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_CHECK_SHAPE);
+  if (aFunction.IsNull()) return;
+
+  //Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return;
+
+  GEOMImpl_IConformity aCI(aFunction);
+
+  Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+  if (aRefShape.IsNull()) return;
+
+  aCI.SetShape(aRefShape);
+
+  try
+  {
+    OCC_CATCH_SIGNALS;
+    if (!GetSolver()->ComputeFunction(aFunction))
+    {
+      SetErrorCode("Failed: checkShape");
+      return;
+    }
+    Handle(TColStd_HArray1OfInteger) aTypesChecks = aFunction->GetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS);
+    Handle(TColStd_HArray2OfInteger) aRes = aCI.GetListOfShapesIndices();
+    if (aRes.IsNull())
+      return;
+
+    for (Standard_Integer anIndex = 1; anIndex <= aRes->NbRows(); ++anIndex)
+    {
+      std::pair<Handle(GEOM_Object), Handle(GEOM_Object)> aPair;
+      Handle(TColStd_HArray1OfInteger) anArray;
+      anArray = new TColStd_HArray1OfInteger(1, 1);
+      anArray->SetValue(1, aRes->Value(anIndex, 1));
+
+      Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
+      if (!anObj.IsNull())
+        aPair.first = anObj;
+
+      anArray = new TColStd_HArray1OfInteger(1, 1);
+      anArray->SetValue(1, aRes->Value(anIndex, 2));
+
+      anObj = GetEngine()->AddSubShape(theShape, anArray);
+      if (!anObj.IsNull())
+        aPair.second = anObj;
+      theChecks.push_back({ aTypesChecks->Value(anIndex), aPair });
+    }
+  }
+  catch (Standard_Failure& aFail)
+  {
+    SetErrorCode(aFail.GetMessageString());
+    return;
+  }
+
+  SetErrorCode(OK);
+  return;
+}
+
+//=============================================================================
+/*!
+ *  UpdateTolerance
+ *  Compute possible tolerance for the shape, minimize tolerance of shape as well
+ *  as tolerance of sub-shapes as much as possible
+ *  \param theShape Shape for compute tolerance.
+ */
+ //=============================================================================
+double GEOMImpl_IMeasureOperations::UpdateTolerance(Handle(GEOM_Object) theShape)
+{
+  SetErrorCode(KO);
+  MESSAGE("GEOMImpl_IMeasureOperations::updateTolerance");
+
+  double aResTol = -1;
+  Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
+  Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_UPDATE_TOL);
+  if (aFunction.IsNull()) return aResTol;
+
+  //Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return aResTol;
+
+  GEOMImpl_IConformity aCI(aFunction);
+
+  Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+  if (aRefShape.IsNull()) return aResTol;
+
+  aCI.SetShape(aRefShape);
+
+  try
+  {
+    OCC_CATCH_SIGNALS;
+    if (!GetSolver()->ComputeFunction(aFunction))
+    {
+      SetErrorCode("Failed: updateTolerance");
+      return aResTol;
+    }
+    aResTol = aFunction->GetReal(CHECKCONFORMITY_RET_TOLERANCE);
+  }
+  catch (Standard_Failure& aFail)
+  {
+    SetErrorCode(aFail.GetMessageString());
+    return aResTol;
+  }
+
+  SetErrorCode(OK);
+  return aResTol;
+}
+
+//=============================================================================
+/*!
+ *  ComputeTolerance
+ *  Compute distance from the edge to the face.
+ */
+ //=============================================================================
+double GEOMImpl_IMeasureOperations::ComputeTolerance(Handle(GEOM_Object) theEdge,
+                                                     Handle(GEOM_Object) theFace)
+{
+  double aMaxDist = Precision::Infinite();
+  if (theEdge.IsNull() || theFace.IsNull())
+    return aMaxDist;
+
+  Handle(GEOM_Function) aRefEdge = theEdge->GetLastFunction();
+  Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
+  if (aRefEdge.IsNull() || aRefFace.IsNull())
+    return aMaxDist;
+
+  TopoDS_Edge aEdge = TopoDS::Edge(aRefEdge->GetValue());
+  TopoDS_Face aFace = TopoDS::Face(aRefFace->GetValue());
+  if (aEdge.IsNull() || aFace.IsNull())
+    return aMaxDist;
+
+  double aParam = 0.0;
+  BOPTools_AlgoTools::ComputeTolerance(aFace, aEdge, aMaxDist, aParam);
+  return aMaxDist;
+}
+
 //=======================================================================
 //function : FillErrorsSub
 //purpose  : Fill the errors list of subshapes on shape.
index 827f695fff310e441679ea5952ac548558e1b196..d896b5da1adcd036b8d520c268e6dc8f379c58eb 100644 (file)
@@ -217,6 +217,28 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations {
   Standard_EXPORT Standard_Real MinSurfaceCurvatureByPoint (Handle(GEOM_Object) theSurf,
                                                             Handle(GEOM_Object) thePoint);
 
+  // Methods checking the shapes which are not applicable to modelling operations
+  typedef std::pair< Handle(GEOM_Object), Handle(GEOM_Object)> CoupleOfObjects;
+  struct FailedChecks
+  {
+    Standard_Integer TypeOfCheck;
+    CoupleOfObjects FailedShapes;
+  };
+
+  Standard_EXPORT std::list<CoupleOfObjects> SelfIntersected2D(const std::list<FailedChecks>& theChecks);
+  Standard_EXPORT std::list<CoupleOfObjects> InterferingSubshapes(const std::list<FailedChecks>& theChecks,
+                                                                  const int theShapeType1,
+                                                                  const int theShapeType2);
+  Standard_EXPORT Handle(TColStd_HSequenceOfTransient) SmallEdges(const std::list<FailedChecks>& theChecks);
+  Standard_EXPORT std::list<CoupleOfObjects> DistantShapes(const std::list<FailedChecks>& theChecks,
+                                                           const int theShapeType,
+                                                           const int theSubShapeType,
+                                                           double theTolerance);
+  Standard_EXPORT void CheckConformityShape(Handle(GEOM_Object) theShape, std::list<FailedChecks>& theChecks);
+
+  Standard_EXPORT double ComputeTolerance(Handle(GEOM_Object) theEdge, Handle(GEOM_Object) theFace);
+  Standard_EXPORT double UpdateTolerance(Handle(GEOM_Object) theShape);
+
   Standard_EXPORT Handle(GEOM_Object) SurfaceCurvatureByPointAndDirection
                                       (Handle(GEOM_Object) theSurf,
                                        Handle(GEOM_Object) thePoint,
index af37b6dcf59a8452aace7026cac3ea2ef1c8097c..fec26368a732588a3dff19d0357b939420ab84a9 100644 (file)
 
 #define GEOM_PATCH_FACE 60
 
+#define GEOM_CHECKCONFORMITY 62
+
 //GEOM_Function types
 
 #define COPY_WITH_REF    1
 #define TD_GET_IN_PLACE_OLD        2
 #define TD_GET_IN_PLACE_BY_HISTORY 3
 
+// Conformity operations
+#define CONFORMITY_UPDATE_TOL       2
+#define CONFORMITY_CHECK_SHAPE      3
+
 // Plugins specified constants
 #define PLUGIN_NAME "Plugin Name"
 
index 0c09e09c4b1ebaccdf503e5e29c0762917fdee19..c2bffa8e9a4a12abe774b1140662db441c0f3b64 100644 (file)
@@ -1243,3 +1243,203 @@ GEOM::GEOM_Object_ptr GEOM_IMeasureOperations_i::SurfaceCurvatureByPointAndDirec
 
   return GetObject(anObject);
 }
+
+//=============================================================================
+/*!
+ *  SelfIntersected2D
+ *  Find all self-intersected 2D curves.
+ *  \param theShape Shape for check.
+ */
+ //=============================================================================
+GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape* GEOM_IMeasureOperations_i::SelfIntersected2D(
+                                          const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts)
+{
+  GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape_var aSeq =
+    new GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape;
+
+  // Perform patch face operation
+  std::list<GEOMImpl_IMeasureOperations::FailedChecks> aResults;
+  ConvertToList(theResuts, aResults);
+
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aSelfInters = GetOperations()->SelfIntersected2D(aResults);
+  if (!GetOperations()->IsDone() || aSelfInters.empty())
+    return aSeq._retn();
+
+  Standard_Integer aLength = aSelfInters.size();
+  aSeq->length(aLength);
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>::iterator anIter(aSelfInters.begin());
+  for (Standard_Integer i = 0; i < aLength; i++, ++anIter)
+  {
+    aSeq[i].first = GetObject(Handle(::GEOM_Object)::DownCast((*anIter).first));
+    aSeq[i].second = GetObject(Handle(::GEOM_Object)::DownCast((*anIter).second));
+  }
+
+  return aSeq._retn();
+}
+
+//=============================================================================
+/*!
+ *  InterferingSubshapes
+ *  Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned.
+ *  \param theShape Shape for check.
+ *  \param theShapeType1 Type of shape.
+ *  \param theShapeType2 Type of shape.
+ */
+ //=============================================================================
+GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape* GEOM_IMeasureOperations_i::InterferingSubshapes(
+    const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts,
+    const CORBA::Long theShapeType1,
+    const CORBA::Long theShapeType2)
+{
+  GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape_var aSeq =
+    new GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape;
+
+  // Perform patch face operation
+  std::list<GEOMImpl_IMeasureOperations::FailedChecks> aResults;
+  ConvertToList(theResuts, aResults);
+
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aSelfInterf =
+    GetOperations()->InterferingSubshapes(aResults, theShapeType1, theShapeType2);
+  if (!GetOperations()->IsDone() || aSelfInterf.empty())
+    return aSeq._retn();
+
+  Standard_Integer aLength = aSelfInterf.size();
+  aSeq->length(aLength);
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>::iterator anIter(aSelfInterf.begin());
+  for (Standard_Integer i = 0; i < aLength; i++, ++anIter)
+  {
+    aSeq[i].first = GetObject(Handle(::GEOM_Object)::DownCast((*anIter).first));
+    aSeq[i].second = GetObject(Handle(::GEOM_Object)::DownCast((*anIter).second));
+  }
+
+  return aSeq._retn();
+}
+
+//=============================================================================
+/*!
+ *  SmallEdges
+ *  Find edges, which are fully covered by tolerances of vertices.
+ *  \param theShape Shape for check.
+ */
+ //=============================================================================
+GEOM::ListOfGO* GEOM_IMeasureOperations_i::SmallEdges(const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts)
+{
+  GEOM::ListOfGO_var aSeq = new GEOM::ListOfGO;
+
+  std::list<GEOMImpl_IMeasureOperations::FailedChecks> aResults;
+  ConvertToList(theResuts, aResults);
+
+  //Get the reference shape
+  Handle(TColStd_HSequenceOfTransient) aSmallEdges = GetOperations()->SmallEdges(aResults);
+  if (!GetOperations()->IsDone() || aSmallEdges.IsNull())
+    return aSeq._retn();
+
+  Standard_Integer aLength = aSmallEdges->Length();
+  aSeq->length(aLength);
+  for (Standard_Integer i = 1; i <= aLength; i++)
+    aSeq[i - 1] = GetObject(Handle(::GEOM_Object)::DownCast(aSmallEdges->Value(i)));
+
+  return aSeq._retn();
+}
+
+//=============================================================================
+/*!
+ *  DistantShapes
+ *  find remote objects (sub-shape on a shape).
+ *  \param theShape Shape for check.
+ *  \param theShapeType Type of shape.
+ *  \param theSubShapeType Type of sub-shape.
+ *  \param theTolerance tolerance.
+ */
+ //=============================================================================
+GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape* GEOM_IMeasureOperations_i::DistantShapes(
+    const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts,
+    const CORBA::Long theShapeType,
+    const CORBA::Long theSubShapeType,
+    const CORBA::Double theTolerance)
+{
+  GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape_var aSeq =
+    new GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape;
+
+  std::list<GEOMImpl_IMeasureOperations::FailedChecks> aResults;
+  ConvertToList(theResuts, aResults);
+
+  // Perform patch face operation
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aDistantS =
+      GetOperations()->DistantShapes(aResults, theShapeType, theSubShapeType, theTolerance);
+  if (!GetOperations()->IsDone() || aDistantS.empty())
+    return aSeq._retn();
+
+  Standard_Integer aLength = aDistantS.size();
+  aSeq->length(aLength);
+  std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>::iterator anIter(aDistantS.begin());
+  for (Standard_Integer i = 0; i < aLength; i++, ++anIter)
+  {
+    aSeq[i].first = GetObject(Handle(::GEOM_Object)::DownCast((*anIter).first));
+    aSeq[i].second = GetObject(Handle(::GEOM_Object)::DownCast((*anIter).second));
+  }
+
+  return aSeq._retn();
+}
+
+//=============================================================================
+/*!
+ *  CheckConformityShape
+ *  Perform all required checks
+ */
+ //=============================================================================
+GEOM::GEOM_IMeasureOperations::CheckResults* GEOM_IMeasureOperations_i::CheckConformityShape(
+    GEOM::GEOM_Object_ptr theShape)
+{
+  GEOM::GEOM_IMeasureOperations::CheckResults_var aRes = new GEOM::GEOM_IMeasureOperations::CheckResults;
+
+  //Get the reference shape
+  Handle(::GEOM_Object) aShapeRef = GetObjectImpl(theShape);
+  if (aShapeRef.IsNull()) return nullptr;
+
+  std::list<GEOMImpl_IMeasureOperations::FailedChecks> aChecks;
+  GetOperations()->CheckConformityShape(aShapeRef, aChecks);
+
+  Standard_Integer aLength = aChecks.size();
+  aRes->length(aLength);
+  std::list<GEOMImpl_IMeasureOperations::FailedChecks>::const_iterator anIntIt = aChecks.cbegin();
+  for (Standard_Integer i = 0; i < aLength; i++, ++anIntIt)
+  {
+    aRes[i].type = (*anIntIt).TypeOfCheck;
+    aRes[i].failedShapes.first  = GetObject(Handle(::GEOM_Object)::DownCast((*anIntIt).FailedShapes.first));
+    aRes[i].failedShapes.second = GetObject(Handle(::GEOM_Object)::DownCast((*anIntIt).FailedShapes.second));
+  }
+
+  return aRes._retn();
+}
+
+//=============================================================================
+/*!
+ *  UpdateTolerance
+ *  Compute possible tolerance for the shape, minimize tolerance of shape as well
+ *  as tolerance of sub-shapes as much as possible
+ *  \param theShape Shape for check.
+ */
+ //=============================================================================
+CORBA::Double GEOM_IMeasureOperations_i::UpdateTolerance(GEOM::GEOM_Object_ptr theShape)
+{
+  //Get the reference shape
+  Handle(::GEOM_Object) aShapeRef = GetObjectImpl(theShape);
+  if (aShapeRef.IsNull())
+    return false;
+
+  return GetOperations()->UpdateTolerance(aShapeRef);
+}
+
+void GEOM_IMeasureOperations_i::ConvertToList(const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts,
+                                              std::list<GEOMImpl_IMeasureOperations::FailedChecks>& theListOfResults)
+{
+  for (Standard_Integer i = 0; i < theResuts.length(); ++i)
+  {
+    GEOMImpl_IMeasureOperations::FailedChecks aCheck;
+    aCheck.TypeOfCheck = theResuts[i].type;
+    aCheck.FailedShapes.first = GetObjectImpl(theResuts[i].failedShapes.first);
+    aCheck.FailedShapes.second = GetObjectImpl(theResuts[i].failedShapes.second);
+    theListOfResults.push_back(aCheck);
+  }
+}
index 6a5aa39ee22c4119d21ba710fde7aa9cddc61595..630218c04624399bbf9bc2bb90d71b4af0d49e4b 100644 (file)
@@ -170,8 +170,33 @@ class GEOM_I_EXPORT GEOM_IMeasureOperations_i :
                                                              GEOM::GEOM_Object_ptr thePoint,
                                                              GEOM::GEOM_Object_ptr theDirection);
 
+  // Methods for class CheckConformity
+  GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape* SelfIntersected2D(
+                               const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts);
+
+  GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape* InterferingSubshapes(
+                                                  const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts,
+                                                  const CORBA::Long theShapeType1,
+                                                  const CORBA::Long theShapeType2);
+
+  GEOM::ListOfGO* SmallEdges(const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts);
+
+  GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape* DistantShapes(
+      const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts,
+      const CORBA::Long theShapeType,
+      const CORBA::Long theSubShapeType,
+      const CORBA::Double theTolerance);
+
+  GEOM::GEOM_IMeasureOperations::CheckResults* CheckConformityShape(GEOM::GEOM_Object_ptr theShape);
+
+  CORBA::Double UpdateTolerance(GEOM::GEOM_Object_ptr theShape);
+
   ::GEOMImpl_IMeasureOperations* GetOperations()
   { return (::GEOMImpl_IMeasureOperations*)GetImpl(); }
+
+private:
+  void ConvertToList(const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts,
+                     std::list <GEOMImpl_IMeasureOperations::FailedChecks>& theListOfResults);
 };
 
 #endif
index 39f3ac6af4a860b5bd8b43301e67ffed091a4398..e9b78cadcecd64a14ae20b6fe1180e7e9d4cc1b0 100644 (file)
@@ -72,6 +72,7 @@ SET(_python_SCRIPTS
   geomBuilder.py
   gsketcher.py
   canonicalrecognition.py
+  conformity.py
   )
 
 # Advanced scripts
diff --git a/src/GEOM_SWIG/conformity.py b/src/GEOM_SWIG/conformity.py
new file mode 100644 (file)
index 0000000..009ecca
--- /dev/null
@@ -0,0 +1,322 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2014-2022  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
+#
+# Author : Alexey SOZINOV, Open CASCADE S.A.S.
+
+
+## @defgroup check_conformity CheckConformity - Wrapper to find imperfections in the shape
+#  @{ 
+#  @details
+#  This tool provides the user with a simple python API 
+#  to analyze, available shape for Boolean Operations or not.
+#  Also tool provide advanced output to indicate imperfections in the input shape.
+#  @n Example:
+#  @code
+#  import GEOM
+#  from salome.geom import geomBuilder
+#  from salome.geom.CheckConformity import CheckConformity
+#
+#  geompy = geomBuilder.New()
+#
+#  O = geompy.MakeVertex(0, 0, 0)
+#  OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+#  OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+#  OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+#  Vertex_1 = geompy.MakeVertex(-30, -70, 0)
+#  Vertex_2 = geompy.MakeVertex(-30, 50, 0)
+#  Line_1 = geompy.MakeLineTwoPnt(Vertex_2, Vertex_1)
+#  Vertex_3 = geompy.MakeVertex(0, -50, 0)
+#  Vertex_4 = geompy.MakeVertex(-40, -10, 0)
+#  Vertex_5 = geompy.MakeVertex(0, 40, 0)
+#  Arc_1 = geompy.MakeArc(Vertex_5, Vertex_4, Vertex_3)
+#  Vertex_6 = geompy.MakeVertex(10, -50, 4)
+#  Vertex_7 = geompy.MakeVertex(10, -50, 10)
+#  Vertex_8 = geompy.MakeVertex(10, 40, 10)
+#  Arc_1_vertex_3 = geompy.GetSubShape(Arc_1, [3])
+#  Line_2 = geompy.MakeLineTwoPnt(Arc_1_vertex_3, Vertex_6)
+#  Line_3 = geompy.MakeLineTwoPnt(Vertex_6, Vertex_7)
+#  Line_4 = geompy.MakeLineTwoPnt(Vertex_7, Vertex_8)
+#  Vertex_9 = geompy.MakeVertex(15, 40, 10)
+#  Vertex_10 = geompy.MakeVertex(17, 0, 6)
+#  Vertex_11 = geompy.MakeVertex(17, 0, 3)
+#  Line_5 = geompy.MakeLineTwoPnt(Vertex_8, Vertex_9)
+#  Line_6 = geompy.MakeLineTwoPnt(Vertex_9, Vertex_10)
+#  Line_7 = geompy.MakeLineTwoPnt(Vertex_10, Vertex_11)
+#  Arc_1_vertex_2 = geompy.GetSubShape(Arc_1, [2])
+#  Line_8 = geompy.MakeLineTwoPnt(Vertex_11, Arc_1_vertex_2)
+#  Wire_1 = geompy.MakeWire([Arc_1, Line_2, Line_3, Line_4, Line_5, Line_6, Line_7, Line_8], 1e-07)
+#  Wire_2 = geompy.MakeWire([Line_1], 1e-07)
+#  Compound_1 = geompy.MakeCompound([Wire_1, Wire_2])
+#
+#  # Create class CheckConformity for check shape
+#  cc = CheckConformity(Compound_1, geompy)
+#  valid = cc.isValid()
+#  dist = cc.distantShapes()
+#  small = cc.smallEdges()
+#  interfer = cc.interferingSubshapes()
+#  intersect = cc.selfIntersected2D()
+#
+#  geompy.addToStudy( O, 'O' )
+#  geompy.addToStudy( OX, 'OX' )
+#  geompy.addToStudy( OY, 'OY' )
+#  geompy.addToStudy( OZ, 'OZ' )
+#  geompy.addToStudy( Vertex_1, 'Vertex_1' )
+#  geompy.addToStudy( Vertex_2, 'Vertex_2' )
+#  geompy.addToStudy( Line_1, 'Line_1' )
+#  geompy.addToStudy( Vertex_3, 'Vertex_3' )
+#  geompy.addToStudy( Vertex_4, 'Vertex_4' )
+#  geompy.addToStudy( Vertex_5, 'Vertex_5' )
+#  geompy.addToStudy( Arc_1, 'Arc_1' )
+#  geompy.addToStudy( Vertex_6, 'Vertex_6' )
+#  geompy.addToStudy( Vertex_7, 'Vertex_7' )
+#  geompy.addToStudy( Vertex_8, 'Vertex_8' )
+#  geompy.addToStudyInFather( Arc_1, Arc_1_vertex_3, 'Arc_1:vertex_3' )
+#  geompy.addToStudy( Line_2, 'Line_2' )
+#  geompy.addToStudy( Line_3, 'Line_3' )
+#  geompy.addToStudy( Line_4, 'Line_4' )
+#  geompy.addToStudy( Vertex_9, 'Vertex_9' )
+#  geompy.addToStudy( Vertex_10, 'Vertex_10' )
+#  geompy.addToStudy( Vertex_11, 'Vertex_11' )
+#  geompy.addToStudy( Line_5, 'Line_5' )
+#  geompy.addToStudy( Line_6, 'Line_6' )
+#  geompy.addToStudy( Line_7, 'Line_7' )
+#  geompy.addToStudyInFather( Arc_1, Arc_1_vertex_2, 'Arc_1:vertex_2' )
+#  geompy.addToStudy( Line_8, 'Line_8' )
+#  geompy.addToStudy( Wire_1, 'Wire_1' )
+#  geompy.addToStudy( Wire_2, 'Wire_2' )
+#  geompy.addToStudy( Compound_1, 'Compound_1' )
+#  
+#  salome.sg.updateObjBrowser()
+#
+#  @endcode
+#  @n Additional examples can be found as unit tests in the source code.
+#  @}
+
+
+## An interface to find imperfections in the shape.
+#  Use geompy.CheckConformity(shape) method to obtain an instance of this class
+#
+#  @ref tui_check_conformity_page "Example"
+#  @ingroup check_conformity
+class CheckConformity:
+    AUTO = -1
+
+    """
+    Check Conformity interface
+
+    Example of usage:
+        cc = CheckConformity(Lot4_twistedFace_brep_1, geompy)
+        valid = cc.isValid()
+        dist = cc.distantShapes(geompy.ShapeType["EDGE"], geompy.ShapeType["VERTEX"])
+        small = cc.smallEdges()
+        interfer = cc.interferingSubshapes()
+        interferEV = cc.interferingSubshapes(geompy.ShapeType["EDGE"], geompy.ShapeType["VERTEX"])
+        interferVV = cc.interferingSubshapes(geompy.ShapeType["VERTEX], geompy.ShapeType["VERTEX"])
+        intersect = cc.selfIntersected2D()
+    """
+
+    def __init__(self, shape, geompyD):
+        self.geompyD = geompyD
+        self.myShape = shape
+        self.myIsChecked = False;
+        self.myResults = []
+      
+    ##  Perform analyse of shape.
+    #
+    #  @return New List, which contains pair: type of check and single of pair failed sub-shapes.
+    def __checkShape(self): 
+        """
+        Perform analyse of shape.
+
+        Returns:
+            New List, which contains pair: type of check and single of pair failed sub-shapes.
+        """
+        anOp = self.geompyD.GetIMeasureOperations()
+        self.myResults = anOp.CheckConformityShape(self.myShape)
+        self.myIsChecked = True
+
+    ## Check whether the shape is applicable for Boolean Operations.
+    #
+    #  @return Boolean value True if shape is applicable for Boolean Operations, otherwise - False
+    def isValid(self):
+        """
+        check whether the shape is applicable for Boolean Operations.
+
+        Returns:
+            Boolean value True if shape is applicable for Boolean Operations, otherwise - False.
+
+        Example of usage:
+            Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
+            cc = CheckConformity(Box_1, geompy)
+            isValid = cc.isValid()
+        """
+        if not self.myIsChecked:
+            self.__checkShape()
+        return len(self.myResults) == 0
+       
+    ## Find all self-intersected 2D curves.
+    #
+    #  @return New List, of pair sub-shape, which has self-intersected in 2D
+    def selfIntersected2D(self):
+        """
+        Find all self-intersected 2D curves.
+
+        Returns:
+            New List, of pair sub-shape, which has self-intersected in 2D/
+
+        Example of usage:
+            Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
+            cc = CheckConformity(Box_1, geompy)
+            selfIntersected2D = cc.selfIntersected2D()
+        """
+        if not self.myIsChecked:
+            self.__checkShape()
+
+        anOp = self.geompyD.GetIMeasureOperations()
+        return anOp.SelfIntersected2D(self.myResults)
+
+    ## Find pairs of interfering sub-shapes:
+    #  - vertices touched by tolerance;
+    #  - vertex touching an edge in the inner point;
+    #  - vertex lying on the inner point of a face;
+    #  - edges intersecting by inner points;
+    #  - edge touching/intersecting face in the inner point;
+    #  - faces intersection by inner point
+    #
+    # Types of interfering shapes could be specified,
+    # by default all pairs of interfering shapes are returned.
+    #
+    #  @param shapeType1 first type of shape
+    #  @param shapeType2 second type of shape
+    #
+    #  @return New List, of pairs of interfering shapes with given types (if they was specified)
+    def interferingSubshapes(self, shapeType1 = AUTO, shapeType2 = AUTO):
+        """
+        Find pairs of interfering sub-shapes:
+         - vertices touched by tolerance
+         - vertex touching an edge in the inner point
+         - vertex lying on the inner point of a face
+         - edges intersecting by inner points
+         - edge touching/intersecting face in the inner point
+         - faces intersection by inner point
+        
+         Types of interfering shapes could be specified, by default all pairs of 
+         interfering shapes are returned.
+
+        Parameters:
+            shapeType1 first type of shape
+            shapeType2 second type of shape
+
+        Returns:
+            New List, of pairs of interfering shapes with given types (if they was specified)
+
+        Example of usage:
+            Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
+            cc = CheckConformity(Box_1, geompy)
+            interferingSubshapes = cc.interferingSubshapes()
+            interferingSubshapesVV = cc.interferingSubshapes(geompy.ShapeType["VERTEX"], geompy.ShapeType["VERTEX"])
+        """
+        if not self.myIsChecked:
+            self.__checkShape()
+
+        anOp = self.geompyD.GetIMeasureOperations()
+        return anOp.InterferingSubshapes(self.myResults, shapeType1, shapeType2)
+       
+    ## Find edges, which are fully covered by tolerances of vertices.
+    #
+    #  @return New List of edges, which are fully covered by tolerances of vertices
+    def smallEdges(self):
+        """
+        Find edges, which are fully covered by tolerances of vertices.
+
+        Returns:
+            New List of edges, which are fully covered by tolerances of vertices.
+
+        Example of usage:
+            Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
+            cc = CheckConformity(Box_1, geompy)
+            smallEdges = cc.smallEdges()
+        """
+        if not self.myIsChecked:
+            self.__checkShape()
+
+        anOp = self.geompyD.GetIMeasureOperations()
+        return anOp.SmallEdges(self.myResults)
+       
+    ## Find remote objects (sub-shape on a shape):
+    #  - vertex far from edge;
+    #  - vertex far from face;
+    #  - edge far from face
+    #
+    #  Sub-shape which are lying far from its parent shape more than the given tolerance.
+    #
+    #  @param shapeType type of shape
+    #  @param subShapeType type of sub-shape
+    #  @param tolerance available tolerance, by default used tolerance of sub-shape.
+    #
+    #  @return New List, of pair of sub-shape with given types,
+    #          that lying far from its parent shape more than the given tolerance.
+    def distantShapes(self, shapeType = AUTO, subShapeType = AUTO, tolerance = -1.0):
+        """
+        Find remote objects (sub-shape on a shape):
+         - vertex far from edge;
+         - vertex far from face;
+         - edge far from face
+
+        Sub-shape which are lying far from its parent shape more than the given tolerance.
+
+        Parameters:
+            shapeType type of shape
+            subShapeType type of sub-shape
+            tolerance available tolerance, by default used tolerance of sub-shape.
+
+        Returns:
+            New List, of pair of sub-shape with given types,
+                that lying far from its parent shape more than the given tolerance
+
+        Example of usage:
+            Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
+            cc = CheckConformity(Box_1, geompy)
+            distantShapes = cc.distantShapes(geompy.ShapeType["EDGE"], geompy.ShapeType["VERTEX"])
+        """
+        if not self.myIsChecked:
+            self.__checkShape()
+
+        anOp = self.geompyD.GetIMeasureOperations()
+        return anOp.DistantShapes(self.myResults, shapeType, subShapeType, tolerance)
+        
+    ## Compute possible tolerance for the shape,
+    #   minimize tolerance of shape as well as tolerance of sub-shapes as much as possible  .
+    #
+    #  @return New value of tolerance.
+    def updateTolerance(self):
+        """
+        Compute possible tolerance for the shape,
+        minimize tolerance of shape as well as tolerance of sub-shapes as much as possible.
+
+        Returns:
+            New value of tolerance.
+
+        Example of usage:
+            Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
+            cc = CheckConformity(Box_1, geompy)
+            toler = cc.updateTolerance()
+        """
+        anOp = self.geompyD.GetIMeasureOperations()
+        return anOp.UpdateTolerance(self.myShape)
index 49115d58acebcea80805e6999fee71176ef15050..cf5a9dba0bcd519c8477c7212a46ac2387486ec8 100644 (file)
@@ -261,6 +261,7 @@ import functools
 
 from salome.geom.gsketcher import Sketcher3D, Sketcher2D, Polyline2D
 from salome.geom.canonicalrecognition import CanonicalRecognition
+from salome.geom.conformity import CheckConformity
 
 # 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
@@ -14036,6 +14037,25 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
             RaiseIfFailed("Tesselate", self.TestOp)
             return r
 
+        ## Obtain a shape checker
+        #  @return An instance of @ref conformity.CheckConformity "CheckConformity" interface
+        #
+        #  @ref tui_conformity_page "Example"
+        def CheckConformity (self, shape):
+            """
+            Obtain a shape checker.
+
+            Example of usage:
+                conf = geompy.CheckConformity(shape)
+                valid = conf.isValid()
+                si2d = conf.selfIntersected2D()
+                dist = conf.distantShapes()
+                small = conf.smallEdges()
+                interfer = cc.interferingSubshapes()
+            """
+            conf = CheckConformity (shape, self)
+            return conf
+
         # end of l2_testing
         ## @}
 
diff --git a/test/data/test_twisted_face.brep b/test/data/test_twisted_face.brep
new file mode 100644 (file)
index 0000000..676989c
--- /dev/null
@@ -0,0 +1,136 @@
+DBRep_DrawableShape
+
+CASCADE Topology V1, (c) Matra-Datavision
+Locations 1
+1
+              1               0               0 4.9737991503207e-14 
+              0               1               0 3.01980662698043e-14 
+              0               0               1            0.32 
+Curve2ds 8
+7 0 0  3 31 25  0.62097105974585987 0.15948827432010637  1.0178384577946662 0.15904747894940738  1.7919772886097678 0.16023544703874379  2.8296462714764243 0.1646936597454636  3.6343610308315899 0.14495897382667697  4.2530291807844067 0.15584083155973055  4.2561593560079443 0.17243028775592023  4.2737975042802532 0.17718432089155983  4.2758972298938769 0.17768014496855566  4.2745790439640698 0.17761511454292708  4.2732608580342637 0.17755008411729845  4.2719426721044567 0.17748505369166984  4.2685737431310367 0.17705122614450211  4.2216670901036162 0.17117537647031988  3.9576620993263232 0.14271883246905073  3.2500874413330538 0.16344974989888242  2.312036977642228 0.16533544597384642  1.1999709601549366 0.16115329090091313  0.00022624251974185183 0.16189798040525596  -1.1998248025434153 0.16208187349580844  -2.311258030335043 0.16043260825740957  -3.2514593267329666 0.16133561787898357  -3.9513964340409169 0.16177800498883513  -4.3599719186139723 0.15862634177392065  -4.4459314998039563 0.15711547491183947  -4.2024214434830869 0.15999005244503542  -3.6485515116162728 0.16128595108290927  -2.8257647574668181 0.15951696874898502  -1.7930836444807681 0.15985961908083829  -1.0179150779613311 0.16014164694355873  -0.62096545850060725 0.16030074567237121 
+ 2.7541326116201541e-08 4 0.27272615781512782 1 0.54545228808892954 1 0.8181784183627312 1 1.090904548636533 1 1.3636306789103347 1 1.4003088700995505 3 1.6113309571563268 3 1.6363568091841363 1 1.9090829394579381 1 2.1818090697317398 1 2.4545352000055414 1 2.7272613302793434 1 2.9999874605531449 1 3.2727135908269465 1 3.5454397211007485 1 3.81816585137455 1 4.090891981648352 1 4.363618111922154 1 4.636344242195956 1 4.9090703724697571 1 5.1817965027435591 1 5.4545226330173611 1 5.7272487632911622 1 5.9999748935649642 4
+1 -3.4248030194958998 0 0 -1 
+1 2.8583822876836802 0 0 -1 
+7 0 0  3 25 23  -0.6209620987776987 -0.16035721318542759  -0.62096069724977554 -0.16035721251953333  -0.62095789413719815 -0.16036055379429462  -0.62095368917383242 -0.16034551006685868  -0.62094948429349828 -0.16040066107752729  -0.62094527811728994 -0.16019508877479838  -0.62094107578103619 -0.16096221498699803  -0.62093685812010402 -0.15809927045232355  -0.6209326966571187 -0.16878391038965959  -0.6209283244661995 -0.12890828318527064  -0.62092473772895762 -0.27772614007521373  -0.62091821864307994 0.27766967227100359  -0.62092472877529792 0.12885181481429389  -0.6209277475409225 0.1687274414802038  -0.62093170161728761 0.15804280145819435  -0.62093540487979548 0.16090574406487421  -0.62093917514963304 0.16013862284434646  -0.62094292726679878 0.16034417430359288  -0.62094668404991493 0.16028909887058088  -0.62095043938475591 0.16030385832646019  -0.62095419490960202 0.16029990511866365  -0.62095795018549138 0.16030096767631077  -0.62096170533020278 0.16030067983549126  -0.62096420865114232 0.1603007451603144  -0.62096546028617927 0.16030074567037278 
+ 0 4 0.014545454545454545 1 0.029090909090909091 1 0.04363636363636364 1 0.058181818181818182 1 0.072727272727272724 1 0.08727272727272728 1 0.10181818181818182 1 0.11636363636363636 1 0.13090909090909092 1 0.14545454545454545 1 0.16 1 0.17454545454545456 1 0.18909090909090909 1 0.20363636363636364 1 0.21818181818181817 1 0.23272727272727273 1 0.24727272727272728 1 0.26181818181818184 1 0.27636363636363637 1 0.29090909090909089 1 0.30545454545454548 1 0.32000000000000001 4
+7 0 0  3 25 23  0.6209636437661743 -0.15936091417489001  2.8184585451988475 -0.15962923605265164  4.863846894809253 -0.15988740199557316  4.033478155810525 -0.15997041413064539  4.2422461610528446 -0.15986030561968187  4.1724167286244374 -0.16113847443422949  4.1600237866777077 -0.15746513833300432  4.1825400739429934 -0.17226855681516937  3.9993960594473905 -0.11847341774690462  3.2389189425778135 -0.16972203585787271  2.3151759956328601 -0.16679448873668454  1.1991715484596084 -0.16156207767724787  0.00047142312684085678 -0.16228234707147723  -1.1998630401968884 -0.16240511721764153  -2.3112385812378755 -0.16048009570996505  -3.2514502587465168 -0.16150868866128715  -3.9513835019866392 -0.16197902677309359  -4.3599820969175109 -0.15846602674918697  -4.4459460149769034 -0.15679013613557097  -4.202424471792817 -0.15998087327767832  -3.6485404351878947 -0.16144219257916345  -2.8257687756075289 -0.15945826383556991  -1.793085623573907 -0.15983016733365712  -1.0179140721649196 -0.16016073237670145  -0.62096209699262495 -0.16035721318781571 
+ 2.7541319253003154e-08 4 0.27272615781512088 1 0.54545228808892243 1 0.81817841836272409 1 1.0909045486365256 1 1.3636306789103272 1 1.636356809184129 1 1.9090829394579305 1 2.1818090697317323 1 2.4545352000055338 1 2.7272613302793354 1 2.9999874605531369 1 3.2727135908269389 1 3.5454397211007405 1 3.818165851374542 1 4.0908919816483431 1 4.3636181119221451 1 4.6363442421959471 1 4.9090703724697482 1 5.1817965027435502 1 5.4545226330173513 1 5.7272487632911533 1 5.9999748935649544 4
+1 -3.14159265358979 0 0 -1 
+1 -3.14159265358979 0 0 -1 
+7 0 0  3 25 23  0.62096364376617197 -0.15936091417489004  0.62096600342515695 -0.15936091258261845  0.62097072259168928 -0.15936091062828914  0.620977800972911 -0.15936090031642275  0.62098487872827279 -0.15936091583722597  0.62099195680105379 -0.15936083540954299  0.62099903167631065 -0.15936111294495542  0.62100611647004245 -0.15936005457829247  0.62101316223368075 -0.15936398185865458  0.62102035164550939 -0.15934930245481194  0.62102700294132829 -0.1594040641425821  0.62103566049969239 -0.15919966814992498  0.62103682857088205 -0.15996246178918291  0.62104933493493297 -0.15711566266509028  0.62105719674297022 -0.16774002880017616  0.62105568508920372 -0.12808933474578055  0.62109630928636139 -0.27606771619194986  0.62097776098957436 0.2761951441728413  0.62100304478927904 0.12821668987985085  0.62098978849897268 0.16786766260858166  0.62098685892210059 0.15724224190900948  0.62098116103304402 0.160092967901729  0.62097620813079191 0.15931550055438551  0.62097276407328406 0.15948827343533056  0.62097105974585987 0.15948827432010637 
+ 0 4 0.014545454545454545 1 0.029090909090909091 1 0.04363636363636364 1 0.058181818181818182 1 0.072727272727272724 1 0.08727272727272728 1 0.10181818181818182 1 0.11636363636363636 1 0.13090909090909092 1 0.14545454545454545 1 0.16 1 0.17454545454545456 1 0.18909090909090909 1 0.20363636363636364 1 0.21818181818181817 1 0.23272727272727273 1 0.24727272727272728 1 0.26181818181818184 1 0.27636363636363637 1 0.29090909090909089 1 0.30545454545454548 1 0.32000000000000001 4
+Curves 4
+2 0 0 2.9976021664879227e-15 -0 -0 1 1 0 0 -0 1 0 4.3999988324068218
+1 4.2247172844370402 -1.2295339373438301 -0.31999999999999701 1.5543122344752204e-13 9.4368957093138382e-14 1 
+2 0 0 -0.31999999999999701 -0 -0 1 1 0 0 -0 1 0 4.399998832406772
+1 4.3999988324067703 1.2118177255615601e-07 -0.31999999999999701 1.5543122344752204e-13 9.4368957093138382e-14 1 
+Polygon3D 0
+PolygonOnTriangulations 4
+4 1 2 3 4 
+p 10.5555271570971 1 2.85840975720812 2.95281296336246 3.04721616951681 3.14161937567116 
+2 5 4 
+p 10.5555271570971 1 0.130768656348819 0.145573538739984 
+15 6 7 8 9 10 11 12 13 14 15 16 17 18 19 5 
+p 10.5555271570971 1 4.41837812472862e-06 0.224406885029112 0.448809351680099 0.673211818331085 0.897614284982072 1.12201675163306 1.34641921828405 1.57082168493503 1.79522415158602 2.01962661823701 2.24402908488799 2.46843155153898 2.69283401818997 2.91723648484095 3.14163895149194 
+3 6 20 1 
+p 10.5555271570971 1 0.21818181209589 0.244036851709834 0.269891891323777 
+Surfaces 3
+9 0 0 0 0 8 8 9 9 2 2 -174.88262536028634 20.115756517047814 -0.3360037374077432  155.28184381865157 -26.949740273051514 -0.29199681629118862  342.25201270130145 -53.600605786911629 -0.24799288924755652  380.21525191976525 -59.008630769498389 -0.20399207777438805  607.45386704617511 -91.406722806183566 -0.15998730860769791  409.37590667531362 -63.165796541109138 -0.11599143246439086  385.00040719109734 -59.694876548117968 -0.071991924228347937  179.85807572447689 -30.453321097052338 -0.027996195602999974  -187.22237544497972 21.874913984124859 0.01599614705040675  
+45.595805439384741 -10.108529975318158 -0.33599913086958388  393.09319161231565 -59.645301152812316 -0.29199184733164268  392.95398471337256 -59.617619322834926 -0.24799183265921931  679.32484598549058 -100.4450914321129 -0.20398582703906376  674.70797696539512 -99.783330472893738 -0.15998590596113832  709.8586561563751 -104.79797738251789 -0.11598515301873674  441.1177439127631 -66.483901617561642 -0.071990754414883049  419.55871122934235 -63.418203865420054 -0.027991187141944728  32.873078622123323 -8.2947900184392029 0.016000745581129634  
+-265.5267065782528 35.466878047215758 -0.33600563990895316  -152.42240733047166 19.353031963949501 -0.29200325753394196  606.61651424406261 -88.878628198092912 -0.24798736823219084  866.75763580769967 -125.95182176056026 -0.20398191184313225  279.52842258142277 -42.227049159628372 -0.15999417223355378  895.20026155262929 -130.00659648069754 -0.11598128154503856  659.77347191738284 -96.456630000408779 -0.071986185589234725  -127.19981789000208 15.757366743172026 -0.028002623331403981  -280.73347230497853 37.634733595426738 0.015994184605220372  
+-18.384521194240119 1.4330261647594302 -0.33600047560861585  246.85017045359717 -36.385419678274026 -0.29199491173985415  411.02053012269545 -59.733699351165114 -0.24799146332450744  209.5230404117749 -31.046895486067982 -0.2039956567581111  816.73506961060468 -117.61333059354504 -0.15998294354114698  268.57770258752282 -39.465525874784753 -0.11599438641956296  430.38612987936915 -62.494347651814955 -0.07199098719486953  277.28660798171717 -40.724303962901999 -0.027994168524625575  -27.014613182592282 2.6632833503885243 0.015999486411110084  
+158.34370391746307 -22.531767381083686 -0.33599678439540631  627.41167081652043 -89.383505599478667 -0.29198695953552517  -640.97155221844434 91.371821572558261 -0.24801345970432431  428.61160000545902 -61.048724006982724 -0.20399108075684549  848.10972849864663 -120.85590513685582 -0.15998229083690799  428.59745550562371 -61.046721625662627 -0.11599104543677718  -560.46411853857239 79.895192314923833 -0.072011705210113922  649.51820901421399 -92.534883862514903 -0.027986390483598543  138.31644714585269 -19.676809736957985 0.016002939330571193  
+-519.28662329316705 75.264243713691073 -0.33601095587850188  -899.75777282852448 129.49548135850873 -0.29201889287687949  1549.6228838804584 -219.62518224878863 -0.2479676636756519  608.87018031464834 -85.549217903028449 -0.2039873142418758  -1070.7322830872597 153.87894333230977 -0.16002241474246248  676.82618885455156 -95.236423247639976 -0.11598585778941062  1568.1495059870201 -222.2662408107918 -0.071967205087704017  -865.56118569163561 124.62069328518106 -0.02801807104289401  -527.77702479684638 76.474585366632681 0.015989009061928624  
+492.6255316214573 -67.762507275271034 -0.335989802157725  1023.9703838694743 -143.49958752974814 -0.29197867491063612  -770.94549001177757 112.35184470921905 -0.24801618543274223  -626.08690058156378 91.710460823259069 -0.20401313914140118  1019.5592687785827 -142.87126234454581 -0.15997871359543026  -588.68014630249627 86.378146705491531 -0.11601232141758575  -702.81134503243766 102.63934808387245 -0.072014689639558982  1052.9242288265141 -147.62698890673698 -0.027977962693006606  473.22453716553389 -64.996898563789543 0.016009934661604608  
+-358.96894641857233 54.839443251496121 -0.33600761101063475  -466.33039789982951 70.145465225179834 -0.29200983794709007  52.138863045446421 -3.7579904377173245 -0.24799897986301572  -267.78268791193477 41.845674630022465 -0.20400565106214139  -46.305790616710397 10.27620269827398 -0.16000100255563338  -227.80925582181993 36.147486334027555 -0.11600477967398286  118.91357102680659 -13.276626566685531 -0.071997512492502608  -431.88009873773217 65.234589865797034 -0.028009010808113584  -374.94873851867101 57.117359259399663 0.015992197339829154  
+160.96730402211875 -18.062141537146204 -0.33599674359720932  89.518766251097134 -7.8753952668369767 -0.29199821965549416  181.92453444883697 -21.045728326557732 -0.24799626981188339  460.77512250420557 -60.793526963469375 -0.20399042173810653  103.08554192144311 -9.8063886386183299 -0.15999788258907288  500.58321210622182 -66.46811931999973 -0.11598955380674428  241.85608700923589 -29.588875956014551 -0.071994945519574055  121.8377569863633 -12.482445174360755 -0.027997437078280944  144.24253216347762 -15.678042228903394 0.016003049177001155  
+
+-4.7677092944316106 9
+4.8347594340046625 9
+
+-0.17600005192468385 9
+0.17600009053478316 9
+
+6 -1.5543122344752204e-13 -9.4368957093138382e-14 -1 
+7 1 0  2 3 2  4.2247172844370899 -1.2295339373438601 -0.31999999999999701  1 4.3999988324067703 -0.62726091784256299 -0.31999999999999701  0.98999072837878299 4.3999988324067703 1.2118177255615601e-07 -0.31999999999999701  1
+ -3.4248030194958998 3 -3.14159265358979 3
+6 -1.5543122344752204e-13 -9.4368957093138382e-14 -1 
+7 1 0  2 9 5  4.3999988324067703 1.2118177255615601e-07 -0.31999999999999701  1 4.3999988324067703 4.0989988014398007 -0.31999999999999701  0.73169100399514997 0.311270015288028 4.3889761123108606 -0.31999999999999701  1 -3.77745880183071 4.6789534231819303 -0.31999999999999701  0.73169100399514597 -4.3559603724603706 0.62098273408916393 -0.31999999999999701  1 -4.9344619430900201 -3.4369879550036 -0.31999999999999701  0.73169100399515696 -0.92758352060249294 -4.3011149642798703 -0.31999999999999701  1 3.0792949018850901 -5.1652419735561397 -0.31999999999999701  0.73169100399515496 4.2247172844370899 -1.2295339373438601 -0.31999999999999701  1
+ -3.14159265358979 3 -1.6415989182714199 2 -0.14160518295305599 2 1.3583885523653101 2 2.8583822876836802 3
+Triangulations 1
+169 309 1 0.217176532318544
+4.39999883238536 9.78102022170809e-06 0.109090906047948 -4.32182832219151 0.825705564159932 2.99760216648792e-15 -4.38041815207094 0.414640251529911 2.99760216648792e-15 -0.0876407731994031 -0.614825757235303 -0.087213230630005 -0.0876407716270111 -0.614868824029569 -0.254615671825588 4.39999883238531 9.78102019151002e-06 -0.210909093952052 4.28967442031498 0.979123635133129 -0.319999999999997 3.964242109848 1.9091291783661 -0.319999999999997 3.44002086914622 2.74340047113422 -0.319999999999997 2.7432980380738 3.4401025565354 -0.319999999999997 1.90901113619218 3.96429895531041 -0.319999999999997 0.978995903130371 4.28970357330607 -0.319999999999997 -0.000111575786980819 4.39999883099209 -0.319999999999997 -0.979213459679932 4.28965391675862 -0.319999999999997 -1.90921218823388 3.96420213226825 -0.319999999999997 -2.74347250375108 3.43996342223907 -0.319999999999997 -3.44015999978924 2.74322600254354 -0.319999999999997 -3.96433892868015 1.908928124297 -0.319999999999997 -4.28972407230683 0.978906077543822 -0.319999999999997 4.39999883240681 1.21181795585659e-07 -0.0759631482901633 292.256227945119 -42.1818638343837 -0.0791267342992782 279.281199080839 -40.1233784077806 -0.0791594568061422 272.691891691997 -39.0791721958618 -0.0791983095918541 205.803238920401 -28.7075477420649 -0.0721561923887264 252.391498270548 -35.8711347306924 -0.0793023320224702 229.931335158156 -32.3557001830613 -0.0785712251324319 215.446152410669 -30.0820147072656 -0.0786238639025644 266.020223073081 -38.0236950994589 -0.0792246170403919 249.265275029543 -34.9023850066943 -0.115511320797899 276.627064568781 -39.0640826441895 -0.119084305565619 261.079766945603 -36.6909321412353 -0.118718842387043 345.027589880093 -49.4159758368101 -0.139996650113427 331.178921878442 -47.4158330266109 -0.119736774520679 335.898957812085 -48.1411346140541 -0.11971731832498 339.883370831653 -48.6303215090956 -0.140012978413422 326.438549342137 -46.6878668516607 -0.119749957611981 334.709494226454 -47.8405573079115 -0.140026170568687 316.851717200005 -45.2168150683032 -0.119776326012588 324.244585314259 -46.2443318852616 -0.140052557328637 307.091253847031 -43.7205499854623 -0.119815245102533 318.932968612492 -45.4347030968148 -0.140072025893274 293.230564593037 -41.5220322110854 -0.140015219145977 255.461146252969 -35.7854425124404 -0.137189209816799 269.622773979522 -37.934827753135 -0.138975692149302 255.59363862441 -35.8043221373143 -0.138806175329406 338.138231680866 -48.800467880462 -0.0993778273193145 255.066920816529 -35.7292615776236 -0.133955281493809 230.158110059735 -32.1789810637551 -0.090599765167557 333.271138627376 -48.1195459985563 -0.21082911940967 236.210410973903 -33.0412707273328 -0.19575579488462 345.504754124672 -49.8242270908203 -0.200702837450784 373.606618361327 -53.8170413782076 -0.170307945756896 342.766590954203 -49.0672791305785 -0.160276220042185 363.655874036362 -52.2549081710366 -0.160198353250674 321.300390972456 -45.7983625759116 -0.160329004777196 252.263397759022 -35.3295279317365 -0.164855399675873 253.893622142167 -35.5619230086358 -0.158867261156308 267.938365777704 -37.6940371214381 -0.160215432204394 262.762081509729 -36.8914728047111 -0.14730448738032 281.727229342871 -39.770924210064 -0.150115301781785 254.566460845979 -35.6578384567754 -0.155633310522618 274.814003950932 -38.720426732288 -0.147824245692988 255.741234539102 -35.8253375500411 -0.143177308394584 370.369590007148 -53.3947869070428 -0.180434039610032 367.690303880805 -52.8626724604916 -0.155127143006063 373.776830258147 -53.802130603594 -0.160181916026526 372.734167549006 -53.6339154675387 -0.155118924741369 362.594201269868 -52.0839266864839 -0.155138173538465 357.434708711342 -51.2959742449113 -0.155157638922746 346.981591392214 -49.7009522341197 -0.155196572495682 341.698985963535 -48.8955409953978 -0.155213687880352 373.402707772916 -53.7422969653733 -0.144984771786904 378.319676340443 -54.4954520326631 -0.14497655617536 380.880571605869 -54.8800870405289 -0.150039515716429 375.005402349536 -54.0034256531539 -0.139913612386338 370.951985456885 -53.360284465174 -0.150055948918494 365.205925394021 -52.5020303960753 -0.139930042888822 336.389733178734 -48.0864781652064 -0.155226882866155 368.439541334908 -52.9825574245553 -0.144992988364337 363.426039090929 -52.2155863937971 -0.145004017169686 360.239780117642 -51.741868063435 -0.139938259528469 325.650061792752 -46.4510839103547 -0.155253275371023 358.362805707079 -51.4414700966242 -0.145017858190307 355.211920544897 -50.9726807214181 -0.139957722160473 353.245314949436 -50.6595061653208 -0.145037322696349 315.076894429196 -44.842449459008 -0.155250541768985 348.084375716271 -49.8713497920336 -0.145056788110791 250.675735290311 -35.1032083201236 -0.169466453371358 342.889228580388 -49.0784057262526 -0.145073901666838 337.661042367445 -48.2808405950209 -0.145088663340052 332.398150201103 -47.4783876326078 -0.145101857356481 327.095903847998 -46.6703259206072 -0.145115052195702 288.588533246804 -40.8177427149621 -0.155193751454757 308.281545067856 -43.8050247735432 -0.150172090717294 324.418729306905 -46.2624652511273 -0.145124786924774 313.973398778748 -44.6720550247332 -0.145122050649821 369.836354190326 -53.3123452853836 -0.124708455596791 345.22787869248 -49.5758964412254 -0.119678408257466 354.387879483504 -50.9861254215305 -0.11966199112575 300.978765484904 -42.6952724179809 -0.145093650275133 287.800636969563 -40.6923395026094 -0.145065253736802 284.28569829973 -40.1587763013408 -0.143919726911949 272.368518934994 -38.3490262660703 -0.143399965782159 262.772012924728 -36.8929121386531 -0.14107649839003 347.789893787988 -50.1958603599269 -0.104440638603177 249.921742818746 -34.9959481741353 -0.116888391006371 250.747701834013 -35.1136762579215 -0.118745226368321 329.718477196364 -47.6229216816775 -0.213360700233596 369.073318044905 -53.2198008089297 -0.182965573256106 378.883041363971 -54.6116428302041 -0.167768216086764 378.766105497109 -54.565593415896 -0.160173698903136 383.28987233617 -55.2529066075766 -0.157633984969964 377.730764708091 -54.3984216780706 -0.155110707464905 382.679186541725 -55.1560615094325 -0.155102491195676 379.408502622067 -54.6539130950289 -0.152575109440547 374.43799809412 -53.8931261012506 -0.152583326171463 369.420149120441 -53.1255911910627 -0.15259154389224 364.350205362617 -52.3505740531829 -0.15260257387771 359.226010225385 -51.5677387057546 -0.15261782176072 354.048173097622 -50.7771720466758 -0.152637287528527 348.826079122927 -49.9802977194549 -0.152656754221635 362.226373871239 -52.0282145731367 -0.147541010785952 360.826635613813 -51.8123230777371 -0.150078008585453 343.569595926301 -49.1786098591897 -0.15267386906014 379.837156122428 -54.7444335934541 -0.139905398556495 338.278427746162 -48.3720517360694 -0.152689024145822 339.99384389993 -48.6329254070199 -0.150151169048485 351.96308329487 -50.4603077594083 -0.147577129214449 350.488297572281 -50.2336615867769 -0.150116939758571 332.95375958951 -47.5607922830394 -0.152702219453906 329.363836161127 -47.0131623419482 -0.1501775592605 349.368499184398 -50.0642175248518 -0.147586862216783 346.76740958396 -49.667243965979 -0.147595419068334 377.875293723446 -54.4549824885421 -0.137373933033357 327.589154395377 -46.7438410053658 -0.152715415596968 341.533543432017 -48.8687807473498 -0.147612533433927 322.343473510177 -45.9453535462601 -0.152714047940767 338.905318909053 -48.4679837258047 -0.147619914566002 336.269782604893 -48.0661738667275 -0.147626511659748 330.968651997097 -47.2582702718518 -0.147639706475675 328.303301834888 -46.8522113413295 -0.147646304192751 326.961089791743 -46.6477641743056 -0.147651171633079 321.747039478112 -45.8537859292953 -0.14764980331552 375.526079986894 -54.1429844754241 -0.129771349718599 311.214704752315 -44.2509743087047 -0.147647068859654 304.689637813947 -43.2586269896669 -0.147632869252533 291.499888206427 -41.2540353533509 -0.147604472957256 254.435349234103 -35.6391459387743 -0.156321855231056 284.839834254462 -40.2424508562232 -0.14759027617232 279.6114401717 -39.4483803076794 -0.145871985014749 267.623323598241 -37.6285200278463 -0.145352225368073 254.351247688848 -35.6272664283862 -0.130032817924701 383.522581384771 -55.2909754133174 -0.158899733375778 377.698490439069 -54.3921950588664 -0.151311420124222 367.689200406403 -52.860860835067 -0.15132926060139 357.474600878019 -51.3000496121888 -0.151357647279274 347.064737430139 -49.7112373523994 -0.151395403661034 376.830402964961 -54.3338084711905 -0.13103707571852 315.072580353742 -44.8377133041855 -0.148910945797723 350.08703401267 -50.5282056170309 -0.105706343844815 328.799315581267 -47.4943472446794 -0.213993596087664 383.620718367656 -55.3074129576439 -0.159532607959587 378.087210013865 -54.5178592828284 -0.132302802711928 383.665225144101 -55.3149814702205 -0.159849045346871 378.393971337674 -54.5628113835814 -0.132619234615848 350.654047443167 -50.6102554153596 -0.106022770307262 328.567586747806 -47.4619273223718 -0.214151820091711 383.686337191133 -55.3186030315307 -0.160007264064377 378.697752191033 -54.6073386310196 -0.132935666582086 0.620988235079467 0.161615877403512 0.207646234488105 0.16172054799534 -0.207541943699009 0.161875406818212 -0.62092039057729 0.161940308030103 -0.620924297653306 -0.162287236800933 0.621069780553672 -0.15936092713457 3.95176990092944 -0.159789770144912 4.34542689909 -0.159930079119764 4.15251318103879 -0.159937785644465 4.20561365532281 -0.16029457207876 4.17766773501422 -0.160150182733031 4.16559301556595 -0.160229206124795 4.16218116437178 -0.163741093719529 4.0543421332554 -0.14356063314107 3.66910580921202 -0.142326378239446 3.01528189630961 -0.164897451154454 2.23091911074297 -0.166199645573306 1.33079053987402 -0.162883643600812 0.363705756412436 -0.162057857300563 0.620994664540127 0.174551623667082 -0.517576755626724 0.0808671965193711 -0.310887532187583 0.0808347459134257 -0.207090487640805 0.0807960312077076 0.621011836178349 0.0878395494007764 0.103839101600593 0.0806924341483145 0.414337621152337 0.0814240115649055 0.621008621448018 0.0813716762689919 -0.103754987492964 0.0807698635597507 0.621020421997459 0.0444835122676239 0.362434054708581 0.0409099546413929 0.517683314484453 0.0412757433496884 -0.232701156733846 0.0199961781762587 -0.206864759611702 0.0402563434024553 -0.258763281885092 0.0402757007553144 -0.180918020560191 0.01997995758784 -0.155197009537782 0.0402432595784769 -0.129250270486271 0.0199668737638616 -0.0518615093899417 0.0402170919305201 -0.0259147703384306 0.0199407061159048 0.0519355351568367 0.040178377224802 0.0259837519349586 0.0199213487630457 0.272141265451394 0.0199786936381382 0.621024714907014 0.0228054937010476 0.491731531262575 0.0210187148879322 0.621023911224432 0.0211885254181015 -0.595085458608652 0.0606151439446608 0.621026322272179 0.02603943026694 0.621017736453069 0.0693954674000925 -0.608004878130979 -0.0508360464281363 0.621040808366011 -0.0357606888668965 -0.569250526640015 -0.0407100201407812 -0.556332083886692 -0.0103157159757431 -0.2066390315826 -0.000283344402796898 -0.414233120676157 -0.000205914991360689 3.19687130805324e-05 -0.000335679698710567 0.621033565319095 -0.00486062929997827 0.62102900781657 0.00112747513447137 0.492346995745951 -0.000220989948525513 0.556381073222155 0.0126900632941479 0.382244130598673 0.00987885184480636 0.621030615181735 0.00436141170036369 0.446585940316564 0.012170052669251 0.62102927240954 0.016817389266598 -0.595086435377656 -0.0204417422630983 -0.44652825079046 0.00486521080380323 -0.517577732395728 -0.000189689688388006 -0.498200556650245 0.00487332345528957 -0.394799390827274 0.00485428697697371 -0.342900868553885 0.00483492962411464 -0.239103824007106 0.00479621491839655 -0.187291841308518 0.00477921013886773 -0.511118511019066 0.015007462394131 -0.562790816878851 0.0150155750456174 -0.582167992624333 0.00995256190193983 -0.543413641133369 0.0200785881892949 -0.478823380904763 0.00993633659896714 -0.440069029413799 0.0200623628863223 -0.135624091234598 0.00476612631488932 -0.459446205159281 0.0149993497426447 -0.407717345196095 0.0149884259158152 -0.388396723554014 0.0200542502348359 -0.0322885910867574 0.00473995866693247 -0.355931931129508 0.0149746909136425 -0.336498201280624 0.0200348928819769 -0.304033408856118 0.0149553335607834 0.0680592928976589 0.00474291363550164 -0.252134886582729 0.0149359762079244 0.621035040387775 -0.00947164980014928 -0.200322903884141 0.0149189714283955 -0.148597460760353 0.014904319222197 -0.0969297106864331 0.0148912353982185 -0.0452619606125129 0.0148781515742402 0.314216806414094 0.00480025851059418 0.136086617082237 0.00982150696971384 -0.0193126994758184 0.0148684728978107 0.0810351845085979 0.0148714278663798 -0.588626725616493 0.0352838529233004 -0.36256032643187 0.0403144154610325 -0.46590493815144 0.0403306407640052 0.204113941266815 0.014900100303926 0.327192698025033 0.0149287727414723 0.359363602883979 0.0160743731536946 0.46915873578957 0.0165943837785916 0.556380401836058 0.018918052077265 -0.614462634354134 0.0555521308009833 0.621023504431305 0.0431064283333452 0.621018814632294 0.0412495757017316 -0.61769346600372 -0.0533675529999751 -0.604775023250397 -0.022973248834937 -0.598315801873736 -0.007776096752418 -0.569250038255513 -0.000181577036901637 -0.611233756242557 0.00235804218642349 -0.549872862510031 0.00488143610677591 -0.601545168369816 0.00488954875826225 -0.566020427567182 0.00741699900435788 -0.514348121707397 0.00740888635287151 -0.462675815847612 0.0074007737013852 -0.410946955884426 0.00738984987455565 -0.359133264766138 0.00737470928471134 -0.307234742492749 0.0073553519318523 -0.255336220219359 0.00733599457899325 -0.391541503087243 0.0124514574305616 -0.375365660978391 0.00991448894530808 -0.203524237520771 0.00731898979946444 -0.595085946993154 0.0200867008407813 -0.151784371134517 0.00730394549771082 -0.167944651034436 0.00984176468053233 -0.287801012643865 0.0124155539001867 -0.271568616431612 0.00987577423958996 -0.100116621060597 0.00729086167373241 -0.0646091508865952 0.00981559703257551 -0.261851751507171 0.0124058752237572 -0.235945760157877 0.0123973728339928 -0.585397359120413 0.0226182074126201 -0.0484488709866764 0.00727777784975397 -0.184133777459288 0.0123803680544639 0.00172507100553188 0.00727925533403856 -0.158271055897394 0.0123730419513646 -0.132437180860434 0.0123665000393754 -0.0807694307865141 0.012353416215397 -0.0549355557495541 0.0123468743034078 -0.0419609251812068 0.0123420349651931 0.00821301681100128 0.0123435124494777 -0.608003901361975 0.0302208397796228 0.108560900795418 0.0123464674180468 0.170100279174526 0.0123608036368199 0.293179035932744 0.0123894760743662 0.621032156398657 0.00367286973322434 0.354718414311853 0.0124038122931393 0.402974771600272 0.0141222129114728 0.512769904505862 0.0146422235363697 0.621026388420422 0.0299619087999716 -0.616078050178927 0.00109228890050411 -0.548258057165865 0.00868072412740567 -0.444885168394594 0.0086630932367614 -0.34130020173557 0.00863492043858019 -0.237546426976192 0.0085973820195272 -0.612848195298346 0.0289550864937034 0.0721498169466193 0.0110825097095957 -0.619306928290505 0.0542863775150639 -0.620115612971905 -0.0540004296429348 -0.618500197147113 0.000459412257544395 -0.617692489234716 0.027689333207784 -0.619711270631205 0.00014297393606455 -0.618903562718809 0.0273728948863041 -0.620518001774598 0.053969939193584 -0.620721149713952 -0.0541586488036747 -0.620316807373252 -1.52452246753865e-05 -0.620114636202902 0.0270564565648243 18 6 19 12 9 13 11 9 12 10 9 11 6 18 17 21 3 4 22 3 21 23 3 22 24 1 2 24 2 3 24 25 26 24 20 1 24 26 27 24 28 25 24 3 23 24 23 28 29 30 31 32 33 34 35 36 33 35 33 32 37 36 35 37 38 36 39 38 37 39 40 38 41 40 39 42 40 41 42 30 40 43 44 45 46 22 21 46 21 4 46 25 28 46 23 22 46 28 23 46 38 40 47 44 43 48 30 29 48 26 25 48 6 20 48 27 26 48 24 27 48 46 40 48 20 24 48 25 46 48 40 30 49 50 51 52 53 54 52 55 53 56 57 58 59 60 61 59 62 60 63 43 45 63 47 43 63 59 61 64 55 52 65 66 54 65 67 66 68 65 54 69 54 53 69 68 54 70 69 53 71 70 53 72 73 74 72 75 73 72 74 76 72 77 75 78 71 53 78 53 55 79 77 72 79 72 76 80 81 77 80 77 79 82 78 55 83 84 81 83 81 80 85 32 84 85 84 83 86 82 55 87 32 85 88 50 6 88 64 50 88 58 55 88 56 58 88 55 64 89 32 87 89 35 32 90 37 35 90 35 89 91 39 37 91 37 90 92 39 91 93 61 60 93 58 61 93 86 55 93 94 86 93 55 58 93 60 94 95 41 39 95 39 92 96 41 95 97 98 99 100 41 96 100 42 41 101 42 100 102 44 42 102 42 101 103 44 102 104 63 45 104 45 44 104 103 63 104 44 103 105 38 46 105 46 4 105 36 38 106 29 31 106 48 29 106 31 107 106 6 48 108 50 49 109 108 49 109 51 50 109 50 64 109 49 51 110 66 111 110 54 66 110 109 64 110 52 54 110 64 52 112 111 66 112 113 114 112 66 67 112 67 113 115 114 113 115 74 114 116 115 113 116 113 67 117 67 65 117 116 67 118 65 68 118 117 65 119 68 69 119 118 68 120 69 70 120 119 69 121 120 70 122 76 123 122 79 76 122 80 79 122 83 80 124 70 71 124 121 70 125 114 74 125 74 73 125 73 75 125 112 114 126 71 78 126 124 71 126 127 124 128 85 83 128 83 122 128 122 123 128 87 85 128 123 129 130 126 78 130 78 82 130 127 126 130 131 127 132 128 129 132 87 128 133 132 129 133 87 132 133 89 87 133 129 127 134 125 75 134 75 77 135 130 82 135 131 130 136 89 133 136 133 127 136 90 89 137 135 82 137 86 94 137 131 135 137 82 86 138 90 136 138 136 127 139 91 90 139 90 138 139 138 127 139 127 131 140 92 91 140 91 139 140 139 131 141 92 140 141 140 131 142 95 92 142 141 131 142 92 141 143 142 131 143 95 142 143 96 95 144 84 32 144 98 97 144 34 98 144 32 34 145 96 143 146 145 94 146 100 96 146 96 145 147 100 146 147 101 100 147 94 60 147 146 94 148 61 58 148 58 57 148 57 56 148 56 88 148 88 6 148 63 61 148 6 63 149 147 60 149 101 147 149 60 62 150 101 149 150 149 62 150 102 101 150 103 102 151 150 62 151 103 150 151 63 103 151 62 59 151 59 63 152 106 107 152 6 106 152 44 47 152 47 63 152 30 42 152 42 44 152 63 6 152 31 30 152 107 31 153 111 112 154 74 115 154 115 116 154 116 76 154 76 74 155 123 76 155 117 118 155 118 123 155 116 117 155 76 116 156 123 118 156 118 119 156 119 120 156 120 129 156 129 123 157 121 124 157 129 120 157 124 127 157 127 129 157 120 121 158 84 144 159 143 131 159 137 94 159 131 137 159 94 145 159 145 143 160 36 105 160 105 4 160 33 36 161 50 108 161 108 109 162 111 153 163 81 84 163 84 158 164 111 162 165 81 163 166 97 99 166 99 98 166 158 144 166 33 160 166 163 158 166 165 163 166 144 97 166 98 34 166 160 4 166 34 33 167 4 5 167 5 19 167 50 161 167 19 6 167 6 50 167 166 4 167 161 109 168 109 110 168 111 164 168 166 167 168 110 111 168 167 109 169 162 153 169 153 112 169 77 81 169 164 162 169 168 164 169 81 165 169 165 166 169 125 134 169 166 168 169 112 125 169 134 77 
+
+TShapes 9
+Ve
+384.257962534587
+-0.0876407731994031 -0.614825757235303 -0.087213230630005
+0 0
+
+0101101
+*
+Ve
+253.88119506966
+4.39999883238531 9.78102019151002e-06 -0.210909093952052
+0 0
+
+0101101
+*
+Ed
+ 0.855163473894945 1 1 0
+1  1 0 2.85840975720812 3.14161937567116
+2  1 1 0 2.85840975720812 3.14161937567116
+6  1 1 0
+0
+
+0101000
+-9 0 +8 1 *
+Ve
+384.257962534587
+-0.0876407716270111 -0.614868824029569 -0.254615671825588
+0 0
+
+0101101
+*
+Ed
+ 384.257962534587 1 1 0
+1  2 0 0.130768656348819 0.145573538739984
+2  2 2 0 0.130768656348819 0.145573538739984
+2  3 3 0 0.130768656348819 0.145573538739984
+2  4 1 0 0.130768656348819 0.145573538739984
+6  2 1 0
+0
+
+0101000
++6 0 -9 0 *
+Ed
+ 22.232555512994 1 1 0
+1  3 0 4.41837812472862e-06 3.14163895149194
+2  5 1 0 4.41837812472862e-06 3.14163895149194
+6  3 1 0
+0
+
+0101000
++8 0 -6 0 *
+Ed
+ 253.88119506966 1 1 0
+1  4 0 0.21818181209589 0.269891891323777
+2  6 2 0 0.21818181209589 0.269891891323777
+2  7 3 0 0.21818181209589 0.269891891323777
+2  8 1 0 0.21818181209589 0.269891891323777
+6  4 1 0
+0
+
+0101000
++8 0 -8 1 *
+Wi
+
+0101100
++7 0 -5 0 -4 0 +3 0 *
+Fa
+0  1e-07 1 0
+2  1
+0101000
++2 0 *
+
++1 0 
\ No newline at end of file
diff --git a/test/test_conformity.py b/test/test_conformity.py
new file mode 100644 (file)
index 0000000..6c5e7b0
--- /dev/null
@@ -0,0 +1,34 @@
+# Check shape applicability for Boolean Operations
+
+import salome
+salome.salome_init_without_session()
+import GEOM
+from salome.geom import geomBuilder
+geompy = geomBuilder.New()
+
+from inspect import getfile
+from os.path import abspath, dirname, join
+
+data_dir = abspath(join(dirname(getfile(lambda: None)), 'data'))
+shape = geompy.ImportBREP(join(data_dir, 'test_twisted_face.brep'))
+
+tol = geompy.Tolerance(shape)
+
+# perform all checks
+check = geompy.CheckConformity(shape)
+assert(not check.isValid())
+assert(len(check.smallEdges()) == 4)
+assert(len(check.selfIntersected2D()) == 2)
+assert(len(check.interferingSubshapes()) == 6)
+for p in check.interferingSubshapes():
+    assert(geomBuilder.EnumToLong(p.first.GetShapeType()) == geompy.ShapeType["VERTEX"] and
+           geomBuilder.EnumToLong(p.second.GetShapeType()) == geompy.ShapeType["VERTEX"])
+assert(len(check.distantShapes()) == 2)
+for p in check.distantShapes():
+    assert(geomBuilder.EnumToLong(p.first.GetShapeType()) == geompy.ShapeType["EDGE"] and
+           geomBuilder.EnumToLong(p.second.GetShapeType()) == geompy.ShapeType["FACE"])
+assert(len(check.distantShapes(tolerance = 300.0)) == 1)
+assert(len(check.distantShapes(tolerance = 400.0)) == 0)
+
+newTol = check.updateTolerance()
+assert(newTol < max(tol))
index b87d630e212477d48c2617d4f07265860e218903..1688ac2c72e03b0c54cc82a93ad0c87459689de2 100644 (file)
 
 SET(ALL_TESTS
   test_perf_01.py
+  test_patch_face_01.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
+      test_conformity.py
     )
 ENDIF()