]> OCCT Git - occt.git/commitdiff
0033017: Implement an algorithm to find a proximity between a pair of shapes
authorknosulko <knosulko@opencascade.com>
Fri, 5 Aug 2022 09:44:29 +0000 (12:44 +0300)
committersmoskvin <smoskvin@opencascade.com>
Tue, 13 Sep 2022 20:29:39 +0000 (23:29 +0300)
Extend "proximity" command to be able to compute the proximity value;
Implement classes for calculate proximity value between two shapes;
Add possibility to set up the number of sample points for the input shapes;
Add tests lowalgos/proximity.

35 files changed:
dox/upgrade/upgrade.md
src/BRepExtrema/BRepExtrema_ProximityDistTool.cxx [new file with mode: 0644]
src/BRepExtrema/BRepExtrema_ProximityDistTool.hxx [new file with mode: 0644]
src/BRepExtrema/BRepExtrema_ProximityValueTool.cxx [new file with mode: 0644]
src/BRepExtrema/BRepExtrema_ProximityValueTool.hxx [new file with mode: 0644]
src/BRepExtrema/BRepExtrema_SelfIntersection.hxx
src/BRepExtrema/BRepExtrema_ShapeProximity.cxx
src/BRepExtrema/BRepExtrema_ShapeProximity.hxx
src/BRepExtrema/BRepExtrema_TriangleSet.cxx
src/BRepExtrema/BRepExtrema_TriangleSet.hxx
src/BRepExtrema/FILES
src/BRepTest/BRepTest_ExtremaCommands.cxx
src/BVH/BVH_Tools.hxx
tests/lowalgos/grids.list
tests/lowalgos/proximity/A1 [new file with mode: 0644]
tests/lowalgos/proximity/A2 [new file with mode: 0644]
tests/lowalgos/proximity/A3 [new file with mode: 0644]
tests/lowalgos/proximity/A4 [new file with mode: 0644]
tests/lowalgos/proximity/A5 [new file with mode: 0644]
tests/lowalgos/proximity/B1 [new file with mode: 0644]
tests/lowalgos/proximity/B2 [new file with mode: 0644]
tests/lowalgos/proximity/B3 [new file with mode: 0644]
tests/lowalgos/proximity/B4 [new file with mode: 0644]
tests/lowalgos/proximity/B5 [new file with mode: 0644]
tests/lowalgos/proximity/B6 [new file with mode: 0644]
tests/lowalgos/proximity/C1 [new file with mode: 0644]
tests/lowalgos/proximity/C2 [new file with mode: 0644]
tests/lowalgos/proximity/C3 [new file with mode: 0644]
tests/lowalgos/proximity/C4 [new file with mode: 0644]
tests/lowalgos/proximity/D1 [new file with mode: 0644]
tests/lowalgos/proximity/D2 [new file with mode: 0644]
tests/lowalgos/proximity/D3 [new file with mode: 0644]
tests/lowalgos/proximity/E1 [new file with mode: 0644]
tests/lowalgos/proximity/E2 [new file with mode: 0644]
tests/lowalgos/proximity/end [new file with mode: 0644]

index 329bbacb9f9b295d59761b70018bafb904e20df2..7bf9c8d2dd3fad3258483d58a3d9508acdce9d9f 100644 (file)
@@ -2338,3 +2338,8 @@ or to include system OpenGL headers in advance (with help of `OpenGl_GlNative.hx
 
 Method `StdPrs_ToolTriangulatedShape::Normal()` has been removed.
 Please use `BRepLib_ToolTriangulatedShape::ComputeNormals()` to fill in normal attributes in triangulation and fetch them directly using `Poly_Triangulation::Normal()`.
+
+@subsection upgrade_occt770_shapeproximity BRepExtrema_ShapeProximity
+
+A new way of using the `BRepExtrema_ShapeProximity` class was provided for computing a proximity value between two shapes.
+If at initialization of the `BRepExtrema_ShapeProximity` class the *theTolerance* parameter is not defined (Precision::Infinite() by default), the proximity value will be computed.
diff --git a/src/BRepExtrema/BRepExtrema_ProximityDistTool.cxx b/src/BRepExtrema/BRepExtrema_ProximityDistTool.cxx
new file mode 100644 (file)
index 0000000..cd51510
--- /dev/null
@@ -0,0 +1,460 @@
+// Created on: 2022-08-08
+// Created by: Kseniya NOSULKO
+// Copyright (c) 2022 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepExtrema_ProximityDistTool.hxx>
+
+#include <BRepAdaptor_Surface.hxx>
+#include <BRep_Tool.hxx>
+#include <gp_Pln.hxx>
+#include <Precision.hxx>
+#include <Poly_Connect.hxx>
+#include <Standard_NullValue.hxx>
+#include <TopoDS.hxx>
+
+//=======================================================================
+//function : BRepExtrema_ProximityDistTool
+//purpose  : Creates new unitialized tool
+//=======================================================================
+BRepExtrema_ProximityDistTool::BRepExtrema_ProximityDistTool()
+: myMinDistance (std::numeric_limits<Standard_Real>::max()),
+  myProxDist (-1.),
+  myPntStatus1 (ProxPnt_Status_UNKNOWN),
+  myPntStatus2 (ProxPnt_Status_UNKNOWN),
+  myNbSamples1 (0),
+  myProxVtxIdx1 (-1)
+{
+}
+
+//=======================================================================
+//function : BRepExtrema_ProximityDistTool
+//purpose  : Creates new tool for the given element sets
+//=======================================================================
+BRepExtrema_ProximityDistTool::BRepExtrema_ProximityDistTool (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                                              const Standard_Integer theNbSamples1,
+                                                              const Handle(BRepExtrema_TriangleSet)& theSet2,
+                                                              const BRepExtrema_ShapeList& theShapeList1,
+                                                              const BRepExtrema_ShapeList& theShapeList2)
+: myMinDistance (std::numeric_limits<Standard_Real>::max()),
+  myProxDist (-1.),
+  myPntStatus1 (ProxPnt_Status_UNKNOWN),
+  myPntStatus2 (ProxPnt_Status_UNKNOWN),
+  myNbSamples1 (theNbSamples1),
+  myProxVtxIdx1 (-1)
+{
+  LoadTriangleSets (theSet1, theSet2);
+  LoadShapeLists (theShapeList1, theShapeList2);
+}
+
+//=======================================================================
+//function : LoadTriangleSets
+//purpose  : Loads the given element sets into the tool
+//=======================================================================
+void BRepExtrema_ProximityDistTool::LoadTriangleSets (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                                      const Handle(BRepExtrema_TriangleSet)& theSet2)
+{
+  mySet1 = theSet1;
+  mySet2 = theSet2;
+}
+
+//=======================================================================
+//function : LoadTriangleSets
+//purpose  : Loads the given list of subshapes into the proximity tool
+//=======================================================================
+void BRepExtrema_ProximityDistTool::LoadShapeLists (const BRepExtrema_ShapeList& theShapeList1,
+                                                    const BRepExtrema_ShapeList& theShapeList2)
+{
+  myShapeList1 = theShapeList1;
+  myShapeList2 = theShapeList2;
+}
+//=======================================================================
+//function : Perform
+//purpose  : Performs searching of the proximity distance
+//=======================================================================
+void BRepExtrema_ProximityDistTool::Perform()
+{
+  SetBVHSet (mySet2.get());
+
+  const BVH_Array3d& aVertices1 = mySet1->GetVertices();
+  Standard_Integer aVtxSize = (Standard_Integer)aVertices1.size();
+  Standard_Integer aVtxStep = Max (myNbSamples1 <= 0 ? 1 : aVtxSize / myNbSamples1, 1);
+  for (Standard_Integer aVtxIdx = 0; aVtxIdx < aVtxSize; aVtxIdx += aVtxStep)
+  {
+    myDistance = std::numeric_limits<Standard_Real>::max();
+    myMinDistance = std::numeric_limits<Standard_Real>::max();
+    myIsDone = Standard_False;
+    SetObject (aVertices1[aVtxIdx]);
+
+    ComputeDistance();
+
+    if (!IsDone() && myProxDist < 0.) return;
+
+    if (IsDone() && myDistance > myProxDist)
+    {
+      myPnt1 = aVertices1[aVtxIdx];
+      myPnt2 = myExtremaPoint;
+      myProxDist = myDistance;
+      myProxVtxIdx1 = aVtxIdx;
+      myProxPrjState = myExtPrjState;
+    }
+  }
+
+   myIsDone = myProxDist > -1.;
+
+   if (myIsDone)
+   {
+     DefineStatusProxPnt();
+   }
+}
+
+static Standard_Real pointBoxSquareMaxDistance (const BVH_Vec3d& thePoint,
+                                                const BVH_Vec3d& theCMin,
+                                                const BVH_Vec3d& theCMax)
+{
+  Standard_Real aDist = 0;
+  for (int i = 0; i < 3; ++i)
+  {
+    if (thePoint[i] <= 0.5 * (theCMax[i] + theCMin[i])) { Standard_Real d = theCMax[i] - thePoint[i]; d *= d; aDist += d; }
+    else { Standard_Real d = thePoint[i] - theCMin[i]; d *= d; aDist += d; }
+  }
+  return aDist;
+}
+
+//=======================================================================
+//function : Branch rejection
+//purpose  : Defines the rules for node rejection by bounding box
+//=======================================================================
+Standard_Boolean BRepExtrema_ProximityDistTool::RejectNode (const BVH_Vec3d& theCornerMin,
+                                                            const BVH_Vec3d& theCornerMax,
+                                                            Standard_Real& theMetric) const
+{
+  theMetric = sqrt (BVH_Tools<Standard_Real, 3>::PointBoxSquareDistance (myObject,
+                                                                         theCornerMin,
+                                                                         theCornerMax));
+
+  Standard_Real aMaxMetric = sqrt (pointBoxSquareMaxDistance (myObject,
+                                                              theCornerMin,
+                                                              theCornerMax));
+
+  return theMetric > myDistance || aMaxMetric < myProxDist;
+}
+
+//=======================================================================
+//function : Leaf acceptance
+//purpose  : Defines the rules for leaf acceptance
+//=======================================================================
+Standard_Boolean BRepExtrema_ProximityDistTool::Accept (const Standard_Integer theTrgIdx,
+                                                        const Standard_Real&)
+{
+  BVH_Vec3d aTrgVert1;
+  BVH_Vec3d aTrgVert2;
+  BVH_Vec3d aTrgVert3;
+
+  BVH_PrjState aBVH_PrjState;
+  Standard_Integer aNumberOfFirstNode = -1;
+  Standard_Integer aNumberOfLastNode = -1;
+
+  mySet2->GetVertices (theTrgIdx, aTrgVert1, aTrgVert2, aTrgVert3);
+
+  BVH_Vec3d aNearestPnt = BVH_Tools<Standard_Real, 3>::PointTriangleProjection (myObject,
+                                                                                aTrgVert1, aTrgVert2, aTrgVert3,
+                                                                                &aBVH_PrjState,
+                                                                                &aNumberOfFirstNode, &aNumberOfLastNode);
+
+  PrjState aPrjState (theTrgIdx, aBVH_PrjState, aNumberOfFirstNode, aNumberOfLastNode);
+  BVH_Vec3d aDirect = myObject - aNearestPnt;
+  Standard_Real aSqDistance = aDirect.Dot(aDirect);
+
+  if (aSqDistance > Precision::SquareConfusion()) // point belongs to triangle
+  {
+    const BVH_Vec3d aAB = aTrgVert2 - aTrgVert1;
+
+    BVH_Vec3d aNorm;
+    if (aTrgVert2.IsEqual (aTrgVert3)) // is this degenerate triangle (= segment)
+    {
+      const BVH_Vec3d aAP = myObject - aTrgVert1;
+      aNorm = BVH_Vec3d::Cross (BVH_Vec3d::Cross (aAP, aAB), aAB);
+    }
+    else
+    {
+      const BVH_Vec3d aAC = aTrgVert3 - aTrgVert1;
+      aNorm = BVH_Vec3d::Cross (aAB, aAC);
+    }
+
+    Standard_Real aNormSqLen = aNorm.Dot (aNorm);
+
+    // check if the distance is under perpendicular
+    const BVH_Vec3d aCrossCross = BVH_Vec3d::Cross (aDirect, aNorm);
+    Standard_Real aCrossCrossSqLen = aCrossCross.Dot (aCrossCross);
+    if (aCrossCrossSqLen > Precision::SquareConfusion() * aSqDistance * aNormSqLen)
+    {
+      // the distance is not under perpendicular
+      if (myMinDistance - sqrt (aSqDistance) > Precision::Confusion())
+      {
+        myMinDistance = sqrt (aSqDistance);
+        myMinDistPoint = aNearestPnt;
+        myMinPrjState = aPrjState;
+      }
+
+      return Standard_False;
+    }
+  }
+
+  // the distance is under perpendicular
+  if (myDistance - sqrt (aSqDistance) > Precision::Confusion())
+  {
+    myDistance = sqrt (aSqDistance);
+    myExtremaPoint = aNearestPnt;
+    myExtPrjState = aPrjState;
+
+    return Standard_True;
+  }
+
+  return Standard_False;
+}
+
+//=======================================================================
+//function : ComputeDistance
+//purpose  : Computes the distance between object and BVH tree
+//=======================================================================
+Standard_Real BRepExtrema_ProximityDistTool::ComputeDistance()
+{
+  myIsDone = this->Select() > 0;
+
+  if (!myIsDone)
+  {
+    if (myMinDistance < std::numeric_limits<Standard_Real>::max())
+    {
+      myExtremaPoint = myMinDistPoint;
+      myExtPrjState = myMinPrjState;
+      myIsDone = true;
+    }
+
+    myDistance = myMinDistance;
+  }
+
+  return myDistance;
+}
+
+static Standard_Boolean isNodeOnBorder (const Standard_Integer theNodeIdx, const Handle (Poly_Triangulation)& theTr)
+{
+  Poly_Connect aPolyConnect (theTr);
+
+  Standard_Integer aContTrg; //index of triangle containing exploring node
+  for (aPolyConnect.Initialize (theNodeIdx); aPolyConnect.More(); aPolyConnect.Next())
+  {
+    aContTrg = aPolyConnect.Value();
+
+    Standard_Integer aContTrgNodes[3];
+    theTr->Triangle (aContTrg).Get (aContTrgNodes[0], aContTrgNodes[1], aContTrgNodes[2]); //indices of nodes of the triangle
+
+    Standard_Integer aAdjTrg[3];
+    aPolyConnect.Triangles (aContTrg, aAdjTrg[0], aAdjTrg[1], aAdjTrg[2]); //indices of adjacent triangles
+  
+    for (Standard_Integer j = 0; j < 3; j++)
+    {
+      Standard_Integer k = (j + 1) % 3;
+      if (aAdjTrg[j] == 0) //free segment of triangle
+      {
+        //aContTrgNodes[j], aContTrgNodes[k] are ends of free segment and it is a part of border
+        if (aContTrgNodes[j] == theNodeIdx || aContTrgNodes[k] == theNodeIdx)
+        {
+          return Standard_True;
+        }
+      }
+    }
+  }
+
+  return Standard_False;
+}
+
+//=======================================================================
+//function : defineStatusProxPnt1
+//purpose  : Defines the status of proximity point from 1st BVH
+//=======================================================================
+void BRepExtrema_ProximityDistTool::defineStatusProxPnt1()
+{
+  Standard_Integer aFaceID1 = mySet1->GetShapeIDOfVtx (myProxVtxIdx1);
+
+  if (myShapeList1 (aFaceID1).ShapeType() == TopAbs_EDGE)
+  {
+    const BVH_Array3d& aVertices1 = mySet1->GetVertices();
+    Standard_Integer aVtxSize = (Standard_Integer)aVertices1.size();
+    Standard_Integer aLastIdx = aVtxSize - 1;
+
+    if ((aVertices1[0] - aVertices1[aLastIdx]).Modulus() < Precision::Confusion()) // if closed
+    {
+      myPntStatus1 = ProxPnt_Status_MIDDLE;
+      return;
+    }
+
+    if (myProxVtxIdx1 == 0 || myProxVtxIdx1 == aLastIdx)
+    {
+      myPntStatus1 = ProxPnt_Status_BORDER;
+    }
+    else
+    {
+      myPntStatus1 = ProxPnt_Status_MIDDLE;
+    }
+  }
+  else if (myShapeList1 (aFaceID1).ShapeType() == TopAbs_FACE)
+  {
+    Standard_Integer aNodeIdx = mySet1->GetVtxIdxInShape (myProxVtxIdx1) + 1;
+
+    TopLoc_Location aLocation;
+    const TopoDS_Face& aF = TopoDS::Face (myShapeList1 (aFaceID1));
+    Handle (Poly_Triangulation) aTr = BRep_Tool::Triangulation (aF, aLocation);
+
+    if (isNodeOnBorder (aNodeIdx, aTr))
+    {
+      myPntStatus1 = ProxPnt_Status_BORDER;
+    }
+    else
+    {
+      myPntStatus1 = ProxPnt_Status_MIDDLE;
+    }
+  }
+}
+
+//=======================================================================
+//function : defineStatusProxPnt2
+//purpose  : Defines the status of proximity point from 2nd BVH
+//=======================================================================
+void BRepExtrema_ProximityDistTool::defineStatusProxPnt2()
+{
+  Standard_Integer aTrgIdx = myProxPrjState.GetTrgIdx();
+  Standard_Integer aFaceID2 = mySet2->GetFaceID (aTrgIdx);
+
+  if (myShapeList2 (aFaceID2).ShapeType() == TopAbs_EDGE)
+  {
+    if (myProxPrjState.GetPrjState() == BVH_PrjState::BVH_PrjStateInTriangle_INNER)
+    {
+      return;
+    }
+    else
+    {
+      const BVH_Array3d& aVertices2 = mySet2->GetVertices();
+      Standard_Integer aVtxSize = (Standard_Integer)aVertices2.size();
+      Standard_Integer aLastIdx = aVtxSize - 1;
+
+      if ((aVertices2[0] - aVertices2[aLastIdx]).Modulus() < Precision::Confusion()) // if closed
+      {
+        myPntStatus2 = ProxPnt_Status_MIDDLE;
+        return;
+      }
+
+      NCollection_Array1<Standard_Integer> aVtxIndicesOfTrg;
+      mySet2->GetVtxIndices (aTrgIdx, aVtxIndicesOfTrg);
+
+      Standard_Integer aFirstNodeNum = myProxPrjState.GetNumberOfFirstNode();
+      Standard_Integer aFirstVtxIdx = aVtxIndicesOfTrg[aFirstNodeNum];
+
+      if (myProxPrjState.GetPrjState() == BVH_PrjState::BVH_PrjStateInTriangle_VERTEX)
+      {
+        if (aFirstVtxIdx == 0 || aFirstVtxIdx == aLastIdx)
+        {
+          myPntStatus2 = ProxPnt_Status_BORDER;
+        }
+        else
+        {
+          myPntStatus2 = ProxPnt_Status_MIDDLE;
+        }
+      }
+      else if (myProxPrjState.GetPrjState() == BVH_PrjState::BVH_PrjStateInTriangle_EDGE)
+      {
+        Standard_Integer aLastNodeNum = myProxPrjState.GetNumberOfLastNode();
+        Standard_Integer aLastVtxIdx = aVtxIndicesOfTrg[aLastNodeNum];
+
+        // it could be border only in case projection is on a degenerated edge
+        if (aFirstVtxIdx == aLastVtxIdx && (aFirstVtxIdx == 0 || aFirstVtxIdx == aLastIdx))
+        {
+          myPntStatus2 = ProxPnt_Status_BORDER;
+        }
+        else
+        {
+          myPntStatus2 = ProxPnt_Status_MIDDLE;
+        }
+      }
+    }
+  }
+  else if (myShapeList2 (aFaceID2).ShapeType() == TopAbs_FACE)
+  {
+    if (myProxPrjState.GetPrjState() == BVH_PrjState::BVH_PrjStateInTriangle_INNER)
+    {
+      myPntStatus2 = ProxPnt_Status_MIDDLE;
+    }
+    else
+    {
+      TopLoc_Location aLocation;
+      const TopoDS_Face& aF = TopoDS::Face (myShapeList2 (aFaceID2));
+      Handle (Poly_Triangulation) aTr = BRep_Tool::Triangulation (aF, aLocation);
+
+      NCollection_Array1<Standard_Integer> aVtxIndicesOfTrg;
+      mySet2->GetVtxIndices (aTrgIdx, aVtxIndicesOfTrg);
+
+      if (myProxPrjState.GetPrjState() == BVH_PrjState::BVH_PrjStateInTriangle_VERTEX)
+      {
+        Standard_Integer aNodeNum = myProxPrjState.GetNumberOfFirstNode();
+        Standard_Integer aNodeIdx = mySet2->GetVtxIdxInShape (aVtxIndicesOfTrg[aNodeNum]) + 1;
+
+        if (isNodeOnBorder (aNodeIdx, aTr))
+        {
+          myPntStatus2 = ProxPnt_Status_BORDER;
+        }
+        else
+        {
+          myPntStatus2 = ProxPnt_Status_MIDDLE;
+        }
+      }
+      else if (myProxPrjState.GetPrjState() == BVH_PrjState::BVH_PrjStateInTriangle_EDGE)
+      {
+        myPntStatus2 = ProxPnt_Status_MIDDLE;
+
+        Poly_Connect aPolyConnect (aTr);
+        Standard_Integer aTrgIdxInShape = mySet2->GetTrgIdxInShape (aTrgIdx) + 1;
+
+        Standard_Integer aAdjTrg[3];
+        aPolyConnect.Triangles (aTrgIdxInShape, aAdjTrg[0], aAdjTrg[1], aAdjTrg[2]); //indices of adjacent triangles
+
+        for (Standard_Integer j = 0; j < 3; j++)
+        {
+          Standard_Integer k = (j + 1) % 3;
+          if (aAdjTrg[j] == 0) //free segment of triangle
+          {
+            //aVtxIndicesOfTrg[j] and aVtxIndicesOfTrg[k] are ends of free segment and it is a part of border
+            if (j == myProxPrjState.GetNumberOfFirstNode() &&
+                k == myProxPrjState.GetNumberOfLastNode())
+            {
+              myPntStatus2 = ProxPnt_Status_BORDER;
+              break;
+            }
+          }
+        }
+      } //else if (myProxPrjState.GetPrjState() == BVH_PrjState::BVH_PrjStateInTriangle_EDGE)
+    }
+  } //else if (myShapeList1 (aFaceID1).ShapeType() == TopAbs_FACE)
+}
+
+//=======================================================================
+//function : DefineStatusProxPnt
+//purpose  : Defines the status of proximity points
+//=======================================================================
+void BRepExtrema_ProximityDistTool::DefineStatusProxPnt()
+{
+  // define the status of proximity point from 1st BVH
+  defineStatusProxPnt1();
+
+  // define the status of proximity point from 2nd BVH
+  defineStatusProxPnt2();
+}
diff --git a/src/BRepExtrema/BRepExtrema_ProximityDistTool.hxx b/src/BRepExtrema/BRepExtrema_ProximityDistTool.hxx
new file mode 100644 (file)
index 0000000..3739fff
--- /dev/null
@@ -0,0 +1,200 @@
+// Created on: 2022-08-08
+// Created by: Kseniya NOSULKO
+// Copyright (c) 2022 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepExtrema_ProximityDistTool_HeaderFile
+#define _BRepExtrema_ProximityDistTool_HeaderFile
+
+#include <BRepExtrema_ElementFilter.hxx>
+#include <BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx>
+#include <BRepExtrema_TriangleSet.hxx>
+#include <BVH_Distance.hxx>
+#include <BVH_Tools.hxx>
+
+//! Tool class for computation the proximity distance from first 
+//! primitive set to second one that is the maximal from minimum 
+//! perpendicular distances. If no perpendicular distance is found, the 
+//! minimum distance will be returned.
+//! This tool is not intended to be used independently, and is integrated
+//! in other classes, implementing algorithms based on shape tessellation
+//! (BRepExtrema_ProximityValueTool).
+//! 
+//! Please note that algorithm results are approximate and depend greatly
+//! on the quality of input tessellation(s).
+class BRepExtrema_ProximityDistTool : public BVH_Distance <Standard_Real, 3, BVH_Vec3d, 
+                                                           BRepExtrema_TriangleSet>
+{
+public:
+
+  typedef typename BVH_Tools<Standard_Real, 3>::BVH_PrjStateInTriangle BVH_PrjState;
+
+  enum ProxPnt_Status
+  {
+    ProxPnt_Status_BORDER,
+    ProxPnt_Status_MIDDLE,
+    ProxPnt_Status_UNKNOWN
+  };
+
+public:
+
+  //! Struct with information about projection point state from 2nd BVH,
+  //! providing proximity point of 2nd shape
+  struct PrjState
+  {
+    PrjState()
+    : myTrgIdx (0),
+      myPrjState (BVH_PrjState::BVH_PrjStateInTriangle_INNER),
+      myNumberOfFirstNode (0),
+      myNumberOfLastNode (0)
+    {}
+
+    PrjState (const Standard_Integer theTrgIdx,
+              const BVH_PrjState     thePrjState,
+              const Standard_Integer theNumberOfFirstNode,
+              const Standard_Integer theNumberOfLastNode)
+    : myTrgIdx (theTrgIdx),
+      myPrjState (thePrjState),
+      myNumberOfFirstNode (theNumberOfFirstNode),
+      myNumberOfLastNode (theNumberOfLastNode)
+    {}
+
+    Standard_Integer GetTrgIdx() const { return myTrgIdx; }
+
+    BVH_PrjState GetPrjState() const { return myPrjState; }
+
+    Standard_Integer GetNumberOfFirstNode() const { return myNumberOfFirstNode; }
+
+    Standard_Integer GetNumberOfLastNode() const { return myNumberOfLastNode; }
+
+  private:
+
+    Standard_Integer myTrgIdx; //!< Index of triangle on which the projection is located
+    BVH_PrjState myPrjState; //!< Position of a projection on the triangle (vertex, edge, inner)
+    Standard_Integer myNumberOfFirstNode; //!< The 1st vtx of the triangle edge on which the projection is located
+    Standard_Integer myNumberOfLastNode; //!< The 2nd vtx of the triangle edge on which the projection is located
+  };
+
+public:
+
+  //! Creates new unitialized tool.
+  Standard_EXPORT BRepExtrema_ProximityDistTool();
+
+  //! Creates new tool for the given element sets.
+  Standard_EXPORT BRepExtrema_ProximityDistTool (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                                 const Standard_Integer theNbSamples1,
+                                                 const Handle(BRepExtrema_TriangleSet)& theSet2,
+                                                 const BRepExtrema_ShapeList& theShapeList1,
+                                                 const BRepExtrema_ShapeList& theShapeList2);
+
+public:
+
+  //! Loads the given element sets into the tool.
+  Standard_EXPORT void LoadTriangleSets (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                         const Handle(BRepExtrema_TriangleSet)& theSet2);
+
+  //! Loads the given list of subshapes into the tool.
+  Standard_EXPORT void LoadShapeLists (const BRepExtrema_ShapeList& theShapeList1,
+                                       const BRepExtrema_ShapeList& theShapeList2);
+
+  //! Performs searching of the proximity distance.
+  Standard_EXPORT void Perform();
+
+public: //! @name Reject/Accept implementations
+
+  //! Defines the rules for node rejection by bounding box.
+  Standard_EXPORT virtual Standard_Boolean RejectNode (const BVH_Vec3d& theCornerMin,
+                                                       const BVH_Vec3d& theCornerMax,
+                                                       Standard_Real& theMetric) const Standard_OVERRIDE;
+
+  //! Defines the rules for leaf acceptance.
+  Standard_EXPORT virtual Standard_Boolean Accept (const Standard_Integer theSgmIdx,
+                                                   const Standard_Real&) Standard_OVERRIDE;
+
+  //! Returns points on triangles sets, which provide the proximity distance.
+  void ProximityPoints (BVH_Vec3d& thePoint1, BVH_Vec3d& thePoint2) const
+  {
+    thePoint1 = myPnt1;
+    thePoint2 = myPnt2;
+  }
+
+  //! Returns status of points on triangles sets, which provide the proximity distance.
+  void ProximityPointsStatus (ProxPnt_Status& thePointStatus1, ProxPnt_Status& thePointStatus2) const
+  {
+    thePointStatus1 = myPntStatus1;
+    thePointStatus2 = myPntStatus2;
+  }
+
+  //! Returns the computed distance
+  Standard_Real ProximityDistance() const { return myProxDist; }
+
+protected:
+
+  //! Computes the distance between object and BVH tree.
+  Standard_EXPORT Standard_Real ComputeDistance();
+
+  //! Defines the status of proximity points.
+  Standard_EXPORT void DefineStatusProxPnt();
+
+private:
+
+  //! Defines the status of proximity point from 1st BVH.
+  void defineStatusProxPnt1();
+
+  //! Defines the status of proximity point from 2nd BVH.
+  void defineStatusProxPnt2();
+
+protected:
+
+  Standard_Real myMinDistance; //!< Minimal distance from point to BVH, could be not equal to myDistance
+  BVH_Vec3d myMinDistPoint; //!< Point on BVH providing the minimal distance
+
+  BVH_Vec3d myExtremaPoint; //!< Point on BVH providing the extrema
+
+  Standard_Real myProxDist; //!< Proximity distance
+
+  //! Proximity points
+  BVH_Vec3d myPnt1, myPnt2;
+
+  //! Proximity points' status
+  ProxPnt_Status myPntStatus1, myPntStatus2;
+
+private:
+
+  //! Set of all mesh elements (triangles) of the 1st shape.
+  Handle(BRepExtrema_TriangleSet) mySet1;
+  //! Set of all mesh elements (triangles) of the 2nd shape.
+  Handle(BRepExtrema_TriangleSet) mySet2;
+
+  //! List of subshapes of the 1st shape.
+  BRepExtrema_ShapeList myShapeList1;
+  //! List of subshapes of the 2nd shape.
+  BRepExtrema_ShapeList myShapeList2;
+
+  Standard_Integer myNbSamples1; //!< Number of samples points on the first shape
+
+  //! Vertex index from 1st BVH corresponding to proximity point of 1st shape
+  Standard_Integer myProxVtxIdx1;
+
+  //! Information of projection point state from 2nd BVH providing proximity point of 2nd shape
+  PrjState myProxPrjState;
+
+  //! Information of projection point state from 2nd BVH providing the extrema
+  PrjState myExtPrjState;
+
+  //! Information of projection point state from 2nd BVH providing the minimal distance
+  PrjState myMinPrjState;
+
+};
+
+#endif // _BRepExtrema_ProximityDistTool_HeaderFile
diff --git a/src/BRepExtrema/BRepExtrema_ProximityValueTool.cxx b/src/BRepExtrema/BRepExtrema_ProximityValueTool.cxx
new file mode 100644 (file)
index 0000000..a816be8
--- /dev/null
@@ -0,0 +1,161 @@
+// Created on: 2022-08-08
+// Created by: Kseniya NOSULKO
+// Copyright (c) 2022 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepExtrema_ProximityValueTool.hxx>
+
+//=======================================================================
+//function : BRepExtrema_ProximityValueTool
+//purpose  : Creates new unitialized proximity tool
+//=======================================================================
+BRepExtrema_ProximityValueTool::BRepExtrema_ProximityValueTool()
+: myDistance (std::numeric_limits<Standard_Real>::max()),
+  myIsDone (Standard_False),
+  myNbSamples1(0),
+  myNbSamples2(0)
+{}
+
+//=======================================================================
+//function : BRepExtrema_ProximityValueTool
+//purpose  : Creates new proximity tool for the given element sets
+//=======================================================================
+BRepExtrema_ProximityValueTool::BRepExtrema_ProximityValueTool (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                                                const Handle(BRepExtrema_TriangleSet)& theSet2,
+                                                                const BRepExtrema_ShapeList& theShapeList1,
+                                                                const BRepExtrema_ShapeList& theShapeList2)
+: myDistance (std::numeric_limits<Standard_Real>::max()),
+  myIsDone (Standard_False),
+  myNbSamples1(0),
+  myNbSamples2(0)
+{
+  LoadTriangleSets (theSet1, theSet2);
+  LoadShapeLists (theShapeList1, theShapeList2);
+}
+
+//=======================================================================
+//function : LoadTriangleSets
+//purpose  : Loads the given element sets into the proximity tool
+//=======================================================================
+void BRepExtrema_ProximityValueTool::LoadTriangleSets (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                                       const Handle(BRepExtrema_TriangleSet)& theSet2)
+{
+  mySet1 = theSet1;
+  mySet2 = theSet2;
+
+  myIsDone = Standard_False;
+}
+
+//=======================================================================
+//function : LoadTriangleSets
+//purpose  : Loads the given list of subshapes into the proximity tool
+//=======================================================================
+void BRepExtrema_ProximityValueTool::LoadShapeLists (const BRepExtrema_ShapeList& theShapeList1,
+                                                     const BRepExtrema_ShapeList& theShapeList2)
+{
+  myShapeList1 = theShapeList1;
+  myShapeList2 = theShapeList2;
+
+  myIsDone = Standard_False;
+}
+
+//=======================================================================
+//function : SetNbSamplePoints
+//purpose  : Sets number of sample points used for proximity calculation for each shape
+//=======================================================================
+void BRepExtrema_ProximityValueTool::SetNbSamplePoints(const Standard_Integer theSamples1,
+                                                       const Standard_Integer theSamples2)
+{
+  myNbSamples1 = theSamples1;
+  myNbSamples2 = theSamples2;
+
+  myIsDone = Standard_False;
+}
+
+//=======================================================================
+//function : computeProximityValue
+//purpose  : Returns the computed proximity value from first BVH to another one
+//=======================================================================
+Standard_Real BRepExtrema_ProximityValueTool::computeProximityDist (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                                                    const Standard_Integer theNbSamples1,
+                                                                    const Handle(BRepExtrema_TriangleSet)& theSet2,
+                                                                    const BRepExtrema_ShapeList& theShapeList1,
+                                                                    const BRepExtrema_ShapeList& theShapeList2,
+                                                                    BVH_Vec3d& thePoint1,
+                                                                    BVH_Vec3d& thePoint2,
+                                                                    ProxPnt_Status& thePointStatus1,
+                                                                    ProxPnt_Status& thePointStatus2) const
+{
+  BRepExtrema_ProximityDistTool aProxDistTool (theSet1, theNbSamples1, theSet2, theShapeList1, theShapeList2);
+  aProxDistTool.Perform();
+
+  if (!aProxDistTool.IsDone())
+    return -1.;
+
+  aProxDistTool.ProximityPoints (thePoint1, thePoint2);
+  aProxDistTool.ProximityPointsStatus (thePointStatus1, thePointStatus2);
+
+  return aProxDistTool.ProximityDistance();
+}
+
+//=======================================================================
+//function : Perform
+//purpose  : Performs the computation of the proximity value
+//=======================================================================
+void BRepExtrema_ProximityValueTool::Perform (Standard_Real& theTolerance)
+{
+  myIsDone = Standard_False;
+
+  // max(min) dist from the 1st shape to the 2nd one
+  BVH_Vec3d aP1_1, aP1_2;
+  ProxPnt_Status aPointStatus1_1 = ProxPnt_Status::ProxPnt_Status_UNKNOWN;
+  ProxPnt_Status aPointStatus1_2 = ProxPnt_Status::ProxPnt_Status_UNKNOWN;
+
+  Standard_Real aProximityDist1 = computeProximityDist (mySet1, myNbSamples1, mySet2, myShapeList1, myShapeList2,
+                                                        aP1_1, aP1_2, aPointStatus1_1, aPointStatus1_2);
+
+  if (aProximityDist1 < 0.)
+    return;
+
+  // max(min) dist from the 2nd shape to t he 1st one
+  BVH_Vec3d aP2_1, aP2_2;
+  ProxPnt_Status aPointStatus2_1 = ProxPnt_Status::ProxPnt_Status_UNKNOWN;
+  ProxPnt_Status aPointStatus2_2 = ProxPnt_Status::ProxPnt_Status_UNKNOWN;
+
+  Standard_Real aProximityDist2 = computeProximityDist (mySet2, myNbSamples2, mySet1, myShapeList2, myShapeList1,
+                                                        aP2_2, aP2_1, aPointStatus2_2, aPointStatus2_1);
+
+  if (aProximityDist2 < 0.)
+    return;
+
+  // min dist of the two max(min) dists
+  if (aProximityDist1 < aProximityDist2)
+  {
+    myDistance = aProximityDist1;
+    myPnt1.SetCoord(aP1_1.x(), aP1_1.y(), aP1_1.z());
+    myPnt2.SetCoord(aP1_2.x(), aP1_2.y(), aP1_2.z());
+    myPntStatus1 = aPointStatus1_1;
+    myPntStatus2 = aPointStatus1_2;
+  }
+  else
+  {
+    myDistance = aProximityDist2;
+    myPnt1.SetCoord(aP2_1.x(), aP2_1.y(), aP2_1.z());
+    myPnt2.SetCoord(aP2_2.x(), aP2_2.y(), aP2_2.z());
+    myPntStatus1 = aPointStatus2_1;
+    myPntStatus2 = aPointStatus2_2;
+  }
+
+  myIsDone = Standard_True;
+  theTolerance = myDistance;
+}
diff --git a/src/BRepExtrema/BRepExtrema_ProximityValueTool.hxx b/src/BRepExtrema/BRepExtrema_ProximityValueTool.hxx
new file mode 100644 (file)
index 0000000..09610c8
--- /dev/null
@@ -0,0 +1,126 @@
+// Created on: 2022-08-08
+// Created by: Kseniya NOSULKO
+// Copyright (c) 2022 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepExtrema_ProximityValueTool_HeaderFile
+#define _BRepExtrema_ProximityValueTool_HeaderFile
+
+#include <BRepExtrema_ProximityDistTool.hxx>
+#include <BRepExtrema_TriangleSet.hxx>
+
+//! Tool class for computation of the proximity value from one BVH
+//! primitive set to another, solving max(min) problem.
+//! This tool is not intended to be used independently, and is integrated
+//! in other classes, implementing algorithms based on shape tessellation
+//! (BRepExtrema_ShapeProximity and BRepExtrema_SelfIntersection).
+//! 
+//! Please note that algorithm results are approximate and depend greatly
+//! on the quality of input tessellation(s).
+class BRepExtrema_ProximityValueTool
+{
+public:
+  typedef typename BRepExtrema_ProximityDistTool::ProxPnt_Status ProxPnt_Status;
+
+public:
+
+  //! Creates new unitialized proximity tool.
+  Standard_EXPORT BRepExtrema_ProximityValueTool();
+
+  //! Creates new proximity tool for the given element sets.
+  Standard_EXPORT BRepExtrema_ProximityValueTool (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                                  const Handle(BRepExtrema_TriangleSet)& theSet2,
+                                                  const BRepExtrema_ShapeList& theShapeList1,
+                                                  const BRepExtrema_ShapeList& theShapeList2);
+
+public:
+
+  //! Loads the given element sets into the proximity tool.
+  Standard_EXPORT void LoadTriangleSets (const Handle (BRepExtrema_TriangleSet)& theSet1,
+                                         const Handle (BRepExtrema_TriangleSet)& theSet2);
+
+  //! Loads the given list of subshapes into the proximity tool.
+  Standard_EXPORT void LoadShapeLists (const BRepExtrema_ShapeList& theShapeList1,
+                                       const BRepExtrema_ShapeList& theShapeList2);
+
+  //! Sets number of sample points used for proximity calculation for each shape.
+  //! If number is less or equal zero, all triangulation nodes are used.
+  Standard_EXPORT void SetNbSamplePoints (const Standard_Integer theSamples1 = 0,
+                                          const Standard_Integer theSamples2 = 0);
+
+  //! Performs the computation of the proximity value.
+  Standard_EXPORT void Perform (Standard_Real& theTolerance);
+
+  //! Is proximity test completed?
+  Standard_Boolean IsDone() const { return myIsDone; }
+
+  //! Marks test results as outdated.
+  void MarkDirty() { myIsDone = Standard_False; }
+
+  //! Returns the computed distance.
+  Standard_Real Distance() const { return myDistance; }
+
+  //! Returns points on triangles sets, which provide the proximity distance.
+  void ProximityPoints(gp_Pnt& thePoint1, gp_Pnt& thePoint2) const
+  {
+    thePoint1 = myPnt1;
+    thePoint2 = myPnt2;
+  }
+
+  //! Returns status of points on triangles sets, which provide the proximity distance.
+  void ProximityPointsStatus (ProxPnt_Status& thePointStatus1, ProxPnt_Status& thePointStatus2) const
+  {
+    thePointStatus1 = myPntStatus1;
+    thePointStatus2 = myPntStatus2;
+  }
+
+private:
+
+  //! Returns the computed proximity value from first BVH to another one.
+  Standard_Real computeProximityDist (const Handle(BRepExtrema_TriangleSet)& theSet1,
+                                      const Standard_Integer theNbSamples1,
+                                      const Handle(BRepExtrema_TriangleSet)& theSet2,
+                                      const BRepExtrema_ShapeList& theShapeList1,
+                                      const BRepExtrema_ShapeList& theShapeList2,
+                                      BVH_Vec3d& thePoint1,
+                                      BVH_Vec3d& thePoint2,
+                                      ProxPnt_Status& thePointStatus1,
+                                      ProxPnt_Status& thePointStatus2) const;
+
+private:
+
+  //! Set of all mesh primitives of the 1st shape.
+  Handle(BRepExtrema_TriangleSet) mySet1;
+  //! Set of all mesh primitives of the 2nd shape.
+  Handle(BRepExtrema_TriangleSet) mySet2;
+
+  //! List of subshapes of the 1st shape.
+  BRepExtrema_ShapeList myShapeList1;
+  //! List of subshapes of the 2nd shape.
+  BRepExtrema_ShapeList myShapeList2;
+
+  Standard_Real myDistance;  //!< Distance
+  Standard_Boolean myIsDone; //!< State of the algorithm
+
+  Standard_Integer myNbSamples1; //!< Number of samples points on the first shape
+  Standard_Integer myNbSamples2; //!< Number of samples points on the second shape
+
+  //! Proximity points
+  gp_Pnt myPnt1, myPnt2;
+
+  //! Proximity points' status
+  ProxPnt_Status myPntStatus1, myPntStatus2;
+
+};
+
+#endif // _BRepExtrema_ProximityValueTool_HeaderFile
index dbad24376623eab87d3b6cbcaa7b5f774b8aff03..efb1b39fd02248a1d2e024eab7ba49afc2c95604 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <BRepExtrema_OverlapTool.hxx>
 
+#include <TopoDS.hxx>
+
 //! Tool class for detection of self-sections in the given shape.
 //! This class is based on BRepExtrema_OverlapTool and thus uses
 //! shape tessellation to detect incorrect mesh fragments (pairs
@@ -76,7 +78,7 @@ public:
   //! Returns sub-shape from the shape for the given index (started from 0).
   const TopoDS_Face& GetSubShape (const Standard_Integer theID) const
   {
-    return myFaceList.Value (theID);
+    return TopoDS::Face(myFaceList.Value(theID));
   }
 
   //! Returns set of all the face triangles of the shape.
index 65b2e69589e1ce24f755a6635e659359aa908442..09efa4e58597006479279c0c1e54328dafde3b44 100644 (file)
 #include <Precision.hxx>
 #include <TopExp_Explorer.hxx>
 
+// Assign a map of sub-shapes (edges/faces) of a given shape
+static Standard_Boolean initSubShapes(const TopoDS_Shape&              theShape,
+                                      BRepExtrema_ShapeList&           theSubshapesList,
+                                      Handle(BRepExtrema_TriangleSet)& theTriangleSet)
+{
+  theSubshapesList.Clear();
+
+  for (TopExp_Explorer anIter(theShape, TopAbs_FACE); anIter.More(); anIter.Next())
+  {
+    theSubshapesList.Append(anIter.Current());
+  }
+
+  for (TopExp_Explorer anIter(theShape, TopAbs_EDGE); anIter.More(); anIter.Next())
+  {
+    theSubshapesList.Append(anIter.Current());
+  }
+
+  if (theTriangleSet.IsNull())
+    theTriangleSet = new BRepExtrema_TriangleSet;
+  return theTriangleSet->Init(theSubshapesList);
+}
+
 //=======================================================================
 //function : BRepExtrema_ShapeProximity
 //purpose  : Creates uninitialized proximity tool
@@ -25,7 +47,9 @@
 BRepExtrema_ShapeProximity::BRepExtrema_ShapeProximity (const Standard_Real theTolerance)
 : myTolerance   (theTolerance),
   myElementSet1 (new BRepExtrema_TriangleSet),
-  myElementSet2 (new BRepExtrema_TriangleSet)
+  myElementSet2 (new BRepExtrema_TriangleSet),
+  myNbSamples1  (0),
+  myNbSamples2  (0)
 {
   // Should be initialized later
   myIsInitS1 = myIsInitS2 = Standard_False;
@@ -40,7 +64,9 @@ BRepExtrema_ShapeProximity::BRepExtrema_ShapeProximity (const TopoDS_Shape& theS
                                                         const Standard_Real theTolerance)
 : myTolerance   (theTolerance),
   myElementSet1 (new BRepExtrema_TriangleSet),
-  myElementSet2 (new BRepExtrema_TriangleSet)
+  myElementSet2 (new BRepExtrema_TriangleSet),
+  myNbSamples1  (0),
+  myNbSamples2  (0)
 {
   LoadShape1 (theShape1);
   LoadShape2 (theShape2);
@@ -52,16 +78,18 @@ BRepExtrema_ShapeProximity::BRepExtrema_ShapeProximity (const TopoDS_Shape& theS
 //=======================================================================
 Standard_Boolean BRepExtrema_ShapeProximity::LoadShape1 (const TopoDS_Shape& theShape1)
 {
-  myFaceList1.Clear();
+  myIsInitS1 = initSubShapes(theShape1, myShapeList1, myElementSet1);
 
-  for (TopExp_Explorer anIter (theShape1, TopAbs_FACE); anIter.More(); anIter.Next())
+  if (myTolerance == Precision::Infinite())
   {
-    myFaceList1.Append (static_cast<const TopoDS_Face&> (anIter.Current()));
+    myProxValTool.MarkDirty();
+  }
+  else
+  {
+    myOverlapTool.MarkDirty();
   }
 
-  myOverlapTool.MarkDirty();
-
-  return myIsInitS1 = myElementSet1->Init (myFaceList1);
+  return myIsInitS1;
 }
 
 //=======================================================================
@@ -70,16 +98,18 @@ Standard_Boolean BRepExtrema_ShapeProximity::LoadShape1 (const TopoDS_Shape& the
 //=======================================================================
 Standard_Boolean BRepExtrema_ShapeProximity::LoadShape2 (const TopoDS_Shape& theShape2)
 {
-  myFaceList2.Clear();
+  myIsInitS2 = initSubShapes(theShape2, myShapeList2, myElementSet2);
 
-  for (TopExp_Explorer anIter (theShape2, TopAbs_FACE); anIter.More(); anIter.Next())
+  if (myTolerance == Precision::Infinite())
   {
-    myFaceList2.Append (static_cast<const TopoDS_Face&> (anIter.Current()));
+    myProxValTool.MarkDirty();
+  }
+  else
+  {
+    myOverlapTool.MarkDirty();
   }
 
-  myOverlapTool.MarkDirty();
-
-  return myIsInitS2 = myElementSet2->Init (myFaceList2);
+  return myIsInitS2;
 }
 
 //=======================================================================
@@ -88,13 +118,32 @@ Standard_Boolean BRepExtrema_ShapeProximity::LoadShape2 (const TopoDS_Shape& the
 //=======================================================================
 void BRepExtrema_ShapeProximity::Perform()
 {
-  if (!myIsInitS1 || !myIsInitS2 || myOverlapTool.IsDone())
+  if (myTolerance == Precision::Infinite())
   {
-    return;
+    if (!myIsInitS1 || !myIsInitS2 || myProxValTool.IsDone())
+    {
+      return;
+    }
+
+    myProxValTool.LoadTriangleSets (myElementSet1,
+                                    myElementSet2);
+    myProxValTool.LoadShapeLists (myShapeList1,
+                                  myShapeList2);
+
+    myProxValTool.Perform (myTolerance);
+    myProxValTool.ProximityPoints(myProxPoint1, myProxPoint2);
+    myProxValTool.ProximityPointsStatus (myProxPntStatus1, myProxPntStatus2);
   }
+  else
+  {
+    if (!myIsInitS1 || !myIsInitS2 || myOverlapTool.IsDone())
+    {
+      return;
+    }
 
-  myOverlapTool.LoadTriangleSets (myElementSet1,
-                                  myElementSet2);
+    myOverlapTool.LoadTriangleSets (myElementSet1,
+                                    myElementSet2);
 
-  myOverlapTool.Perform (myTolerance);
+    myOverlapTool.Perform (myTolerance);
+  }
 }
index d863742136b8091ce9b4893d31390d9263a19b30..c6f6d77721ea30ab9c6f998f897130239ac560bf 100644 (file)
 #ifndef _BRepExtrema_ShapeProximity_HeaderFile
 #define _BRepExtrema_ShapeProximity_HeaderFile
 
+#include <NCollection_DataMap.hxx>
+#include <Precision.hxx>
+#include <TColStd_PackedMapOfInteger.hxx>
+
+#include <BRepExtrema_ProximityValueTool.hxx>
+#include <BRepExtrema_TriangleSet.hxx>
 #include <BRepExtrema_OverlapTool.hxx>
 
-//! Tool class for shape proximity detection.
+//! @brief Tool class for shape proximity detection.
+//!
+//! First approach:
 //! For two given shapes and given tolerance (offset from the mesh) the algorithm allows
 //! to determine whether or not they are overlapped. The algorithm input consists of any
 //! shapes which can be decomposed into individual faces (used as basic shape elements).
-//! High performance is achieved through the use of existing triangulation of faces. So
-//! poly triangulation (with the desired deflection) should already be built. Note that
-//! solution is approximate (and corresponds to the deflection used for triangulation).
 //!
 //! The algorithm can be run in two modes. If tolerance is set to zero, the algorithm
 //! will detect only intersecting faces (containing triangles with common points). If
 //! tolerance is set to positive value, the algorithm will also detect faces located
 //! on distance less than the given tolerance from each other.
+//!
+//! Second approach:
+//! Compute the proximity value between two shapes if the tolerance is not defined (Precision::Infinite()).
+//! In this case the proximity value is a minimal thickness of a layer containing both shapes.
+//!
+//! For the both approaches the high performance is achieved through the use of existing
+//! triangulation of faces. So, poly triangulation (with the desired deflection) should already
+//! be built. Note that solution is approximate (and corresponds to the deflection used for
+//! triangulation).
 class BRepExtrema_ShapeProximity
 {
+public:
+  typedef typename BRepExtrema_ProximityValueTool::ProxPnt_Status ProxPnt_Status;
+
 public:
 
   //! Creates empty proximity tool.
-  Standard_EXPORT BRepExtrema_ShapeProximity (const Standard_Real theTolerance = 0.0);
+  Standard_EXPORT BRepExtrema_ShapeProximity (const Standard_Real theTolerance = Precision::Infinite());
 
   //! Creates proximity tool for the given two shapes.
   Standard_EXPORT BRepExtrema_ShapeProximity (const TopoDS_Shape& theShape1,
                                               const TopoDS_Shape& theShape2,
-                                              const Standard_Real theTolerance = 0.0);
+                                              const Standard_Real theTolerance = Precision::Infinite());
 
 public:
 
@@ -56,19 +73,33 @@ public:
     myTolerance = theTolerance;
   }
 
+  //! Returns proximity value calculated for the whole input shapes.
+  Standard_Real Proximity() const
+  {
+    return Tolerance();
+  }
+
   //! Loads 1st shape into proximity tool.
   Standard_EXPORT Standard_Boolean LoadShape1 (const TopoDS_Shape& theShape1);
 
   //! Loads 2nd shape into proximity tool.
   Standard_EXPORT Standard_Boolean LoadShape2 (const TopoDS_Shape& theShape2);
 
+  //! Set number of sample points on the 1st shape used to compute the proximity value.
+  //! In case of 0, all triangulation nodes will be used.
+  void SetNbSamples1(const Standard_Integer theNbSamples) { myNbSamples1 = theNbSamples; }
+
+  //! Set number of sample points on the 2nd shape used to compute the proximity value.
+  //! In case of 0, all triangulation nodes will be used.
+  void SetNbSamples2(const Standard_Integer theNbSamples) { myNbSamples2 = theNbSamples; }
+
   //! Performs search of overlapped faces.
   Standard_EXPORT void Perform();
 
   //! True if the search is completed.
   Standard_Boolean IsDone() const
   { 
-    return myOverlapTool.IsDone();
+    return myOverlapTool.IsDone() || myProxValTool.IsDone();
   }
 
   //! Returns set of IDs of overlapped faces of 1st shape (started from 0).
@@ -84,15 +115,15 @@ public:
   }
 
   //! Returns sub-shape from 1st shape with the given index (started from 0).
-  const TopoDS_Face& GetSubShape1 (const Standard_Integer theID) const
+  const TopoDS_Shape& GetSubShape1 (const Standard_Integer theID) const
   {
-    return myFaceList1.Value (theID);
+    return myShapeList1.Value (theID);
   }
 
   //! Returns sub-shape from 1st shape with the given index (started from 0).
-  const TopoDS_Face& GetSubShape2 (const Standard_Integer theID) const
+  const TopoDS_Shape& GetSubShape2 (const Standard_Integer theID) const
   {
-    return myFaceList2.Value (theID);
+    return myShapeList2.Value (theID);
   }
 
   //! Returns set of all the face triangles of the 1st shape.
@@ -107,6 +138,34 @@ public:
     return myElementSet2;
   }
 
+  //! Returns the point on the 1st shape, which could be used as a reference point
+  //! for the value of the proximity.
+  const gp_Pnt& ProximityPoint1() const
+  {
+    return myProxPoint1;
+  }
+
+  //! Returns the point on the 2nd shape, which could be used as a reference point
+  //! for the value of the proximity.
+  const gp_Pnt& ProximityPoint2() const
+  {
+    return myProxPoint2;
+  }
+
+  //! Returns the status of point on the 1st shape, which could be used as a reference point
+  //! for the value of the proximity.
+  const ProxPnt_Status& ProxPntStatus1() const
+  {
+    return myProxPntStatus1;
+  }
+
+  //! Returns the status of point on the 2nd shape, which could be used as a reference point
+  //! for the value of the proximity.
+  const ProxPnt_Status& ProxPntStatus2() const
+  {
+    return myProxPntStatus2;
+  }
+
 private:
 
   //! Maximum overlapping distance.
@@ -117,19 +176,39 @@ private:
   //! Is the 2nd shape initialized?
   Standard_Boolean myIsInitS2;
 
-  //! List of faces of the 1st shape.
-  BRepExtrema_ShapeList myFaceList1;
-  //! List of faces of the 2nd shape.
-  BRepExtrema_ShapeList myFaceList2;
+  //! List of subshapes of the 1st shape.
+  BRepExtrema_ShapeList myShapeList1;
+  //! List of subshapes of the 2nd shape.
+  BRepExtrema_ShapeList myShapeList2;
 
   //! Set of all the face triangles of the 1st shape.
   Handle(BRepExtrema_TriangleSet) myElementSet1;
   //! Set of all the face triangles of the 2nd shape.
   Handle(BRepExtrema_TriangleSet) myElementSet2;
 
+  //! Number of sample points on the 1st shape used to compute the proximity value
+  //! (if zero (default), all triangulation nodes will be used).
+  Standard_Integer myNbSamples1;
+  //! Number of sample points on the 2nd shape used to compute the proximity value
+  //! (if zero (default), all triangulation nodes will be used).
+  Standard_Integer myNbSamples2;
+
+  //! Reference point of the proximity value on the 1st shape.
+  gp_Pnt myProxPoint1;
+  //! Reference point of the proximity value on the 2st shape.
+  gp_Pnt myProxPoint2;
+
+  //! Status of reference points of the proximity value.
+  ProxPnt_Status myProxPntStatus1, myProxPntStatus2;
+
   //! Overlap tool used for intersection/overlap test.
   BRepExtrema_OverlapTool myOverlapTool;
 
+  //! Shape-shape proximity tool used for computation of
+  //! the minimal diameter of a tube containing both edges or
+  //! the minimal thickness of a shell containing both faces.
+  BRepExtrema_ProximityValueTool myProxValTool;
+
 };
 
 #endif // _BRepExtrema_ShapeProximity_HeaderFile
index 48189a4addf78de8801629ab4c0bc4b73f5d74c6..e1f843d8095d23e1f3de1d3ddce0d4ac98033fb3 100644 (file)
@@ -18,6 +18,7 @@
 #include <BRep_Tool.hxx>
 #include <BVH_LinearBuilder.hxx>
 #include <Poly_Triangulation.hxx>
+#include <TopoDS.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(BRepExtrema_TriangleSet, BVH_PrimitiveSet3d)
 
@@ -114,17 +115,65 @@ void BRepExtrema_TriangleSet::Swap (const Standard_Integer theIndex1, const Stan
 {
   std::swap (myTriangles[theIndex1],
              myTriangles[theIndex2]);
+
+  std::swap (myTrgIdxMap (theIndex1),
+             myTrgIdxMap (theIndex2));
 }
 
 //=======================================================================
 //function : GetFaceID
-//purpose  : Returns face ID of the given triangle
+//purpose  : Returns face ID of the given vertex
 //=======================================================================
 Standard_Integer BRepExtrema_TriangleSet::GetFaceID (const Standard_Integer theIndex) const
 {
   return myTriangles[theIndex].w();
 }
 
+//=======================================================================
+//function : GetShapeIDOfVtx
+//purpose  : Returns shape ID of the given vertex index
+//=======================================================================
+Standard_Integer BRepExtrema_TriangleSet::GetShapeIDOfVtx (const Standard_Integer theIndex) const
+{
+  return myShapeIdxOfVtxVec.Value (theIndex);
+}
+
+//=======================================================================
+//function : GetVtxIdxInShape
+//purpose  : Returns vertex index in tringulation of the shape, which vertex belongs,
+//           with the given vtx ID in whole set
+//=======================================================================
+Standard_Integer BRepExtrema_TriangleSet::GetVtxIdxInShape (const Standard_Integer theIndex) const
+{
+  Standard_Integer aShID = myShapeIdxOfVtxVec.Value (theIndex);
+  Standard_Integer aNumVertices = 0;
+
+  for (Standard_Integer aSIdx = 0; aSIdx < aShID; aSIdx++)
+  {
+    aNumVertices += myNumVtxInShapeVec.Value (aSIdx);
+  }
+
+  return theIndex - aNumVertices;
+}
+
+//=======================================================================
+//function : GetTrgIdxInShape
+//purpose  :  Returns triangle index (before swapping) in tringulation of the shape, which triangle belongs,
+//            with the given trg ID in whole set (after swapping)
+//=======================================================================
+Standard_Integer BRepExtrema_TriangleSet::GetTrgIdxInShape (const Standard_Integer theIndex) const
+{
+  Standard_Integer aShID = GetFaceID (theIndex);
+  Standard_Integer aNumTriangles = 0;
+
+  for (Standard_Integer aSIdx = 0; aSIdx < aShID; aSIdx++)
+  {
+    aNumTriangles += myNumTrgInShapeVec.Value (aSIdx);
+  }
+
+  return myTrgIdxMap (theIndex) - aNumTriangles;
+}
+
 //=======================================================================
 //function : GetVertices
 //purpose  : Returns vertices of the given triangle
@@ -141,6 +190,21 @@ void BRepExtrema_TriangleSet::GetVertices (const Standard_Integer theIndex,
   theVertex3 = myVertexArray[aTriangle.z()];
 }
 
+//=======================================================================
+//function : GetVertices
+//purpose  : Returns vertices of the given triangle
+//=======================================================================
+void BRepExtrema_TriangleSet::GetVtxIndices (const Standard_Integer theIndex,
+                                             NCollection_Array1<Standard_Integer>& theVtxIndices) const
+{
+  BVH_Vec4i aTriangle = myTriangles[theIndex];
+
+  theVtxIndices = NCollection_Array1<Standard_Integer> (0, 2);
+  theVtxIndices.SetValue (0, aTriangle.x());
+  theVtxIndices.SetValue (1, aTriangle.y());
+  theVtxIndices.SetValue (2, aTriangle.z());
+}
+
 //=======================================================================
 //function : Clear
 //purpose  : Clears triangle set data
@@ -158,41 +222,26 @@ void BRepExtrema_TriangleSet::Clear()
 //function : Init
 //purpose  : Initializes triangle set
 //=======================================================================
-Standard_Boolean BRepExtrema_TriangleSet::Init (const BRepExtrema_ShapeList& theFaces)
+Standard_Boolean BRepExtrema_TriangleSet::Init (const BRepExtrema_ShapeList& theShapes)
 {
   Clear();
 
-  for (Standard_Integer aFaceIdx = 0; aFaceIdx < theFaces.Size(); ++aFaceIdx)
+  Standard_Boolean isOK = Standard_True;
+  for (Standard_Integer aShapeIdx = 0; aShapeIdx < theShapes.Size() && isOK; ++aShapeIdx)
+  {
+    if (theShapes (aShapeIdx).ShapeType() == TopAbs_FACE)
+      isOK = initFace (TopoDS::Face (theShapes(aShapeIdx)), aShapeIdx);
+    else if (theShapes (aShapeIdx).ShapeType() == TopAbs_EDGE)
+      isOK = initEdge (TopoDS::Edge (theShapes(aShapeIdx)), aShapeIdx);
+  }
+
+  Standard_Integer aNumTrg = static_cast<Standard_Integer> (myTriangles.size());
+  myTrgIdxMap.Clear();
+  myTrgIdxMap.ReSize (aNumTrg);
+
+  for (Standard_Integer aTrgIdx = 0; aTrgIdx < aNumTrg; ++aTrgIdx)
   {
-    TopLoc_Location aLocation;
-
-    Handle(Poly_Triangulation) aTriangulation =
-      BRep_Tool::Triangulation (theFaces (aFaceIdx), aLocation);
-
-    if (aTriangulation.IsNull())
-    {
-      return Standard_False;
-    }
-
-    const Standard_Integer aVertOffset =
-      static_cast<Standard_Integer> (myVertexArray.size()) - 1;
-
-    for (Standard_Integer aVertIdx = 1; aVertIdx <= aTriangulation->NbNodes(); ++aVertIdx)
-    {
-      gp_Pnt aVertex = aTriangulation->Node (aVertIdx);
-      aVertex.Transform (aLocation.Transformation());
-      myVertexArray.push_back (BVH_Vec3d (aVertex.X(), aVertex.Y(), aVertex.Z()));
-    }
-
-    for (Standard_Integer aTriIdx = 1; aTriIdx <= aTriangulation->NbTriangles(); ++aTriIdx)
-    {
-      Standard_Integer aVertex1, aVertex2, aVertex3;
-      aTriangulation->Triangle (aTriIdx).Get (aVertex1, aVertex2, aVertex3);
-      myTriangles.push_back (BVH_Vec4i (aVertex1 + aVertOffset,
-                                        aVertex2 + aVertOffset,
-                                        aVertex3 + aVertOffset,
-                                        aFaceIdx));
-    }
+    myTrgIdxMap.Bind (aTrgIdx, aTrgIdx);
   }
 
   MarkDirty(); // needs BVH rebuilding
@@ -203,3 +252,95 @@ Standard_Boolean BRepExtrema_TriangleSet::Init (const BRepExtrema_ShapeList& the
   return Standard_True;
 }
 
+//=======================================================================
+//function : initFace
+//purpose  : Initializes triangle set
+//=======================================================================
+Standard_Boolean BRepExtrema_TriangleSet::initFace (const TopoDS_Face& theFace, const Standard_Integer theIndex)
+{
+  TopLoc_Location aLocation;
+
+  Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (theFace, aLocation);
+  if (aTriangulation.IsNull())
+  {
+    return Standard_False;
+  }
+
+  const Standard_Integer aVertOffset =
+    static_cast<Standard_Integer> (myVertexArray.size()) - 1;
+
+  initNodes (aTriangulation->MapNodeArray()->ChangeArray1(), aLocation.Transformation(), theIndex);
+
+  for (Standard_Integer aTriIdx = 1; aTriIdx <= aTriangulation->NbTriangles(); ++aTriIdx)
+  {
+    Standard_Integer aVertex1;
+    Standard_Integer aVertex2;
+    Standard_Integer aVertex3;
+
+    aTriangulation->Triangle (aTriIdx).Get (aVertex1,
+                                            aVertex2,
+                                            aVertex3);
+
+    myTriangles.push_back (BVH_Vec4i (aVertex1 + aVertOffset,
+                                      aVertex2 + aVertOffset,
+                                      aVertex3 + aVertOffset,
+                                      theIndex));
+  }
+
+  myNumTrgInShapeVec.SetValue (theIndex, aTriangulation->NbTriangles());
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : initEdge
+//purpose  : Initializes triangle set
+//=======================================================================
+Standard_Boolean BRepExtrema_TriangleSet::initEdge (const TopoDS_Edge& theEdge, const Standard_Integer theIndex)
+{
+  TopLoc_Location aLocation;
+
+  Handle(Poly_Polygon3D) aPolygon = BRep_Tool::Polygon3D (theEdge, aLocation);
+  if (aPolygon.IsNull())
+  {
+    return Standard_False;
+  }
+
+  const Standard_Integer aVertOffset =
+    static_cast<Standard_Integer> (myVertexArray.size()) - 1;
+
+  initNodes (aPolygon->Nodes(), aLocation.Transformation(), theIndex);
+
+  for (Standard_Integer aVertIdx = 1; aVertIdx < aPolygon->NbNodes(); ++aVertIdx)
+  {
+    // segment as degenerate triangle
+    myTriangles.push_back (BVH_Vec4i (aVertIdx + aVertOffset,
+                                      aVertIdx + aVertOffset + 1,
+                                      aVertIdx + aVertOffset + 1,
+                                      theIndex));
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : initNodes
+//purpose  : Initializes nodes
+//=======================================================================
+void BRepExtrema_TriangleSet::initNodes (const TColgp_Array1OfPnt& theNodes,
+                                         const gp_Trsf& theTrsf,
+                                         const Standard_Integer theIndex)
+{
+  for (Standard_Integer aVertIdx = 1; aVertIdx <= theNodes.Size(); ++aVertIdx)
+  {
+    gp_Pnt aVertex = theNodes.Value (aVertIdx);
+
+    aVertex.Transform (theTrsf);
+
+    myVertexArray.push_back (BVH_Vec3d (aVertex.X(),
+                                        aVertex.Y(),
+                                        aVertex.Z()));
+    myShapeIdxOfVtxVec.Append (theIndex);
+  }
+
+  myNumVtxInShapeVec.SetValue (theIndex, theNodes.Size());
+}
index 3b0414c75b06cc8c0db6ad6baeaab064dcf20939..eb87430cb1e349b849e319035867be891b1add74 100644 (file)
 #ifndef _BRepExtrema_TriangleSet_HeaderFile
 #define _BRepExtrema_TriangleSet_HeaderFile
 
-#include <TopoDS_Face.hxx>
 #include <BVH_PrimitiveSet3d.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_DataMapOfIntegerInteger.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
 
 //! List of shapes and their IDs for collision detection.
-typedef NCollection_Vector<TopoDS_Face> BRepExtrema_ShapeList;
+typedef NCollection_Vector<TopoDS_Shape> BRepExtrema_ShapeList;
 
 //! Triangle set corresponding to specific face.
 class BRepExtrema_TriangleSet : public BVH_PrimitiveSet3d
@@ -59,7 +62,10 @@ public:
   Standard_EXPORT void Clear();
 
   //! Initializes triangle set.
-  Standard_EXPORT Standard_Boolean Init (const BRepExtrema_ShapeList& theFaces);
+  Standard_EXPORT Standard_Boolean Init (const BRepExtrema_ShapeList& theShapes);
+
+  //! Returns all vertices.
+  Standard_EXPORT const BVH_Array3d& GetVertices() const { return myVertexArray; }
 
   //! Returns vertices of the given triangle.
   Standard_EXPORT void GetVertices (const Standard_Integer theIndex,
@@ -67,9 +73,37 @@ public:
                                     BVH_Vec3d&             theVertex2,
                                     BVH_Vec3d&             theVertex3) const;
 
+  //! Returns vertex indices of the given triangle.
+  Standard_EXPORT void GetVtxIndices (const Standard_Integer theIndex,
+                                      NCollection_Array1<Standard_Integer>& theVtxIndices) const;
+
   //! Returns face ID of the given triangle.
   Standard_EXPORT Standard_Integer GetFaceID (const Standard_Integer theIndex) const;
 
+  //! Returns shape ID of the given vertex index.
+  Standard_EXPORT Standard_Integer GetShapeIDOfVtx (const Standard_Integer theIndex) const;
+
+  //! Returns vertex index in tringulation of the shape, which vertex belongs,
+  //! with the given vtx ID in whole set.
+  Standard_EXPORT Standard_Integer GetVtxIdxInShape (const Standard_Integer theIndex) const;
+
+  //! Returns triangle index (before swapping) in tringulation of the shape, which triangle belongs,
+  //! with the given trg ID in whole set (after swapping).
+  Standard_EXPORT Standard_Integer GetTrgIdxInShape (const Standard_Integer theIndex) const;
+
+private:
+
+  //! Initializes triangle set from the face
+  Standard_Boolean initFace (const TopoDS_Face& theFace, const Standard_Integer theIndex);
+
+  //! Initializes polygon from the edge
+  Standard_Boolean initEdge (const TopoDS_Edge& theEdge, const Standard_Integer theIndex);
+
+  //! Initializes nodes
+  void initNodes (const TColgp_Array1OfPnt& theNodes,
+                  const gp_Trsf& theTrsf,
+                  const Standard_Integer theIndex);
+
 protected:
 
   //! Array of vertex indices.
@@ -78,6 +112,19 @@ protected:
   //! Array of vertex coordinates.
   BVH_Array3d myVertexArray;
 
+  //! Vector of shapes' indices where index of item corresponds to index of vertex,
+  //! belonging to this shape.
+  NCollection_Vector<Standard_Integer> myShapeIdxOfVtxVec;
+
+  //! Vector of vertexes' number belonging to shape which index corresponds item's index.
+  NCollection_Vector<Standard_Integer> myNumVtxInShapeVec;
+
+  //! Vector of triangles' number belonging to shape which index corresponds item's index.
+  NCollection_Vector<Standard_Integer> myNumTrgInShapeVec;
+
+  //! Map of triangles' indices after (key) and before (value) swapping.
+  TColStd_DataMapOfIntegerInteger myTrgIdxMap;
+
 public:
 
   DEFINE_STANDARD_RTTIEXT(BRepExtrema_TriangleSet, BVH_PrimitiveSet3d)
index e9fc5d2f3006131c195292af8972fd33bb40388c..b7405afc30892119c83fe6fa56678540eadc2065 100644 (file)
@@ -18,6 +18,10 @@ BRepExtrema_OverlapTool.cxx
 BRepExtrema_OverlapTool.hxx
 BRepExtrema_Poly.cxx
 BRepExtrema_Poly.hxx
+BRepExtrema_ProximityValueTool.cxx
+BRepExtrema_ProximityValueTool.hxx
+BRepExtrema_ProximityDistTool.cxx
+BRepExtrema_ProximityDistTool.hxx
 BRepExtrema_SelfIntersection.cxx
 BRepExtrema_SelfIntersection.hxx
 BRepExtrema_SeqOfSolution.hxx
index ee9d0f4f7d94776e5600dc8d4127c83cbf90caa3..0976a5349b57dea44b6066cdc9184b6f56365b67 100644 (file)
@@ -173,7 +173,7 @@ static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs,
 {
   if (theNbArgs < 3 || theNbArgs > 6)
   {
-    Message::SendFail() << "Usage: " << theArgs[0] << " Shape1 Shape2 [-tol <value>] [-profile]";
+    Message::SendFail() << "Usage: " << theArgs[0] << " Shape1 Shape2 [-tol <value> | -value] [-profile]";
     return 1;
   }
 
@@ -186,9 +186,11 @@ static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs,
     return 1;
   }
 
-  BRepExtrema_ShapeProximity aTool;
+  BRepExtrema_ShapeProximity aTool(0.0);
 
   Standard_Boolean aProfile = Standard_False;
+  Standard_Boolean isTolerance = Standard_False;
+  Standard_Boolean isValue = Standard_False;
 
   for (Standard_Integer anArgIdx = 3; anArgIdx < theNbArgs; ++anArgIdx)
   {
@@ -197,6 +199,7 @@ static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs,
 
     if (aFlag == "-tol")
     {
+      isTolerance = Standard_True;
       if (++anArgIdx >= theNbArgs)
       {
         Message::SendFail() << "Error: wrong syntax at argument '" << aFlag;
@@ -214,13 +217,23 @@ static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs,
         aTool.SetTolerance (aTolerance);
       }
     }
-
-    if (aFlag == "-profile")
+    else if (aFlag == "-value")
+    {
+      isValue = Standard_True;
+      aTool.SetTolerance(Precision::Infinite());
+    }
+    else if (aFlag == "-profile")
     {
       aProfile = Standard_True;
     }
   }
 
+  if (isTolerance && isValue)
+  {
+    Message::SendFail() << "Error: Proximity value could not be computed if the tolerance is set";
+    return 1;
+  }
+
   Standard_Real aInitTime = 0.0;
   Standard_Real aWorkTime = 0.0;
 
@@ -264,38 +277,73 @@ static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs,
     theDI << "Executing proximity test: " << aWorkTime << "\n";
   }
 
-  TopoDS_Builder aCompBuilder;
+  if (isValue)
+  {
+    theDI << "Proximity value: " << aTool.Proximity() << "\n";
 
-  TopoDS_Compound aFaceCompound1;
-  aCompBuilder.MakeCompound (aFaceCompound1);
+    // proximity points
+    TopoDS_Vertex aProxVtx1 = BRepLib_MakeVertex (aTool.ProximityPoint1());
+    TopoDS_Vertex aProxVtx2 = BRepLib_MakeVertex (aTool.ProximityPoint2());
 
-  for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aTool.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
-  {
-    TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[1]) + "_" + (anIt1.Key() + 1);
+    DBRep::Set ("ProxPnt1", aProxVtx1);
+    DBRep::Set ("ProxPnt2", aProxVtx2);
 
-    const TopoDS_Face& aFace = aTool.GetSubShape1 (anIt1.Key());
-    aCompBuilder.Add (aFaceCompound1, aFace);
-    DBRep::Set (aStr.ToCString(), aFace);
+    // proximity points' status
+    TCollection_AsciiString ProxPntStatus1;
+    TCollection_AsciiString ProxPntStatus2;
 
-    theDI << aStr << " \n";
-  }
+    switch (aTool.ProxPntStatus1()) 
+    {
+      case 0: ProxPntStatus1 = "Border"; break;
+      case 1: ProxPntStatus1 = "Middle"; break;
+      default: ProxPntStatus1 = "Unknown";
+    }
 
-  TopoDS_Compound aFaceCompound2;
-  aCompBuilder.MakeCompound (aFaceCompound2);
+    switch (aTool.ProxPntStatus2())
+    {
+    case 0: ProxPntStatus2 = "Border"; break;
+    case 1: ProxPntStatus2 = "Middle"; break;
+    default: ProxPntStatus2 = "Unknown";
+    }
 
-  for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aTool.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
+    theDI << " Status of ProxPnt1 on " << theArgs[1] << " : " << ProxPntStatus1 << "\n";
+    theDI << " Status of ProxPnt2 on " << theArgs[2] << " : " << ProxPntStatus2 << "\n";
+  }
+  else
   {
-    TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[2]) + "_" + (anIt2.Key() + 1);
+    TopoDS_Builder aCompBuilder;
 
-    const TopoDS_Face& aFace = aTool.GetSubShape2 (anIt2.Key());
-    aCompBuilder.Add (aFaceCompound2, aFace);
-    DBRep::Set (aStr.ToCString(), aFace);
+    TopoDS_Compound aFaceCompound1;
+    aCompBuilder.MakeCompound(aFaceCompound1);
 
-    theDI << aStr << " \n";
-  }
+    for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1(aTool.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
+    {
+      TCollection_AsciiString aStr = TCollection_AsciiString(theArgs[1]) + "_" + (anIt1.Key() + 1);
+
+      const TopoDS_Shape& aShape = aTool.GetSubShape1(anIt1.Key());
+      aCompBuilder.Add(aFaceCompound1, aShape);
+      DBRep::Set(aStr.ToCString(), aShape);
+
+      theDI << aStr << " \n";
+    }
+
+    TopoDS_Compound aFaceCompound2;
+    aCompBuilder.MakeCompound(aFaceCompound2);
+
+    for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2(aTool.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
+    {
+      TCollection_AsciiString aStr = TCollection_AsciiString(theArgs[2]) + "_" + (anIt2.Key() + 1);
 
-  DBRep::Set ((TCollection_AsciiString (theArgs[1]) + "_" + "overlapped").ToCString(), aFaceCompound1);
-  DBRep::Set ((TCollection_AsciiString (theArgs[2]) + "_" + "overlapped").ToCString(), aFaceCompound2);
+      const TopoDS_Shape& aShape = aTool.GetSubShape2(anIt2.Key());
+      aCompBuilder.Add(aFaceCompound2, aShape);
+      DBRep::Set(aStr.ToCString(), aShape);
+
+      theDI << aStr << " \n";
+    }
+
+    DBRep::Set((TCollection_AsciiString(theArgs[1]) + "_" + "overlapped").ToCString(), aFaceCompound1);
+    DBRep::Set((TCollection_AsciiString(theArgs[2]) + "_" + "overlapped").ToCString(), aFaceCompound2);
+  }
 
   return 0;
 }
@@ -445,12 +493,14 @@ void BRepTest::ExtremaCommands (Draw_Interpretor& theCommands)
                    aGroup);
 
   theCommands.Add ("proximity",
-                   "proximity Shape1 Shape2 [-tol <value>] [-profile]"
+                   "proximity Shape1 Shape2 [-tol <value> | -value] [-profile]"
                    "\n\t\t: Searches for pairs of overlapping faces of the given shapes."
                    "\n\t\t: The options are:"
                    "\n\t\t:   -tol     : non-negative tolerance value used for overlapping"
                    "\n\t\t:              test (for zero tolerance, the strict intersection"
                    "\n\t\t:              test will be performed)"
+                   "\n\t\t:   -value   : compute the proximity value (minimal value which"
+                   "\n\t\t:              shows both shapes fully overlapped)"
                    "\n\t\t:   -profile : outputs execution time for main algorithm stages",
                    __FILE__,
                    ShapeProximity,
index b90034778b7b52726ac5a7b2f52692d64d6bb9d9..1aee086ffb4006b896faebe092730c606efca0e9 100644 (file)
@@ -30,6 +30,15 @@ public: //! @name public types
 
   typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
 
+public:
+
+  enum BVH_PrjStateInTriangle
+  {
+    BVH_PrjStateInTriangle_VERTEX,
+    BVH_PrjStateInTriangle_EDGE,
+    BVH_PrjStateInTriangle_INNER
+  };
+
 public: //! @name Box-Box Square distance
 
   //! Computes Square distance between Axis aligned bounding boxes
@@ -113,11 +122,14 @@ public: //! @name Point-Box projection
 
 public: //! @name Point-Triangle Square distance
 
-  //! Computes square distance between point and triangle
-  static T PointTriangleSquareDistance (const BVH_VecNt& thePoint,
-                                        const BVH_VecNt& theNode0,
-                                        const BVH_VecNt& theNode1,
-                                        const BVH_VecNt& theNode2)
+  //! Find nearest point on a triangle for the given point
+  static BVH_VecNt PointTriangleProjection (const BVH_VecNt& thePoint,
+                                            const BVH_VecNt& theNode0,
+                                            const BVH_VecNt& theNode1,
+                                            const BVH_VecNt& theNode2,
+                                            BVH_PrjStateInTriangle* thePrjState = nullptr,
+                                            Standard_Integer* theNumberOfFirstNode = nullptr,
+                                            Standard_Integer* theNumberOfLastNode = nullptr)
   {
     const BVH_VecNt aAB = theNode1 - theNode0;
     const BVH_VecNt aAC = theNode2 - theNode0;
@@ -128,68 +140,110 @@ public: //! @name Point-Triangle Square distance
   
     if (aABdotAP <= 0. && aACdotAP <= 0.)
     {
-      return aAP.Dot(aAP);
+      if (thePrjState != nullptr)
+      {
+        *thePrjState = BVH_PrjStateInTriangle_VERTEX;
+        *theNumberOfFirstNode = 0;
+        *theNumberOfLastNode = 0;
+      }
+      return theNode0;
     }
-  
+
     const BVH_VecNt aBC = theNode2 - theNode1;
     const BVH_VecNt aBP = thePoint - theNode1;
-  
-    T aBAdotBP = -(aAB.Dot(aBP));
-    T aBCdotBP =  (aBC.Dot(aBP));
-  
+
+    T aBAdotBP = -(aAB.Dot (aBP));
+    T aBCdotBP = (aBC.Dot (aBP));
+
     if (aBAdotBP <= 0. && aBCdotBP <= 0.)
     {
-      return (aBP.Dot(aBP));
+      if (thePrjState != nullptr)
+      {
+        *thePrjState = BVH_PrjStateInTriangle_VERTEX;
+        *theNumberOfFirstNode = 1;
+        *theNumberOfLastNode = 1;
+      }
+      return theNode1;
     }
-  
+
     const BVH_VecNt aCP = thePoint - theNode2;
-  
-    T aCBdotCP = -(aBC.Dot(aCP));
-    T aCAdotCP = -(aAC.Dot(aCP));
-  
+
+    T aCBdotCP = -(aBC.Dot (aCP));
+    T aCAdotCP = -(aAC.Dot (aCP));
+
     if (aCAdotCP <= 0. && aCBdotCP <= 0.)
     {
-      return (aCP.Dot(aCP));
+      if (thePrjState != nullptr)
+      {
+        *thePrjState = BVH_PrjStateInTriangle_VERTEX;
+        *theNumberOfFirstNode = 2;
+        *theNumberOfLastNode = 2;
+      }
+      return theNode2;
     }
-  
-    T aACdotBP = (aAC.Dot(aBP));
-  
+
+    T aACdotBP = (aAC.Dot (aBP));
+
     T aVC = aABdotAP * aACdotBP + aBAdotBP * aACdotAP;
-  
+
     if (aVC <= 0. && aABdotAP > 0. && aBAdotBP > 0.)
     {
-      const BVH_VecNt aDirect = aAP - aAB * (aABdotAP / (aABdotAP + aBAdotBP));
-  
-      return (aDirect.Dot(aDirect));
+      if (thePrjState != nullptr)
+      {
+        *thePrjState = BVH_PrjStateInTriangle_EDGE;
+        *theNumberOfFirstNode = 0;
+        *theNumberOfLastNode = 1;
+      }
+      return theNode0 + aAB * (aABdotAP / (aABdotAP + aBAdotBP));
     }
-  
-    T aABdotCP = (aAB.Dot(aCP));
-  
+
+    T aABdotCP = (aAB.Dot (aCP));
+
     T aVA = aBAdotBP * aCAdotCP - aABdotCP * aACdotBP;
-  
+
     if (aVA <= 0. && aBCdotBP > 0. && aCBdotCP > 0.)
     {
-      const BVH_VecNt aDirect = aBP - aBC * (aBCdotBP / (aBCdotBP + aCBdotCP));
-  
-      return (aDirect.Dot(aDirect));
+      if (thePrjState != nullptr)
+      {
+        *thePrjState = BVH_PrjStateInTriangle_EDGE;
+        *theNumberOfFirstNode = 1;
+        *theNumberOfLastNode = 2;
+      }
+      return theNode1 + aBC * (aBCdotBP / (aBCdotBP + aCBdotCP));
     }
-  
+
     T aVB = aABdotCP * aACdotAP + aABdotAP * aCAdotCP;
-  
+
     if (aVB <= 0. && aACdotAP > 0. && aCAdotCP > 0.)
     {
-      const BVH_VecNt aDirect = aAP - aAC * (aACdotAP / (aACdotAP + aCAdotCP));
-  
-      return (aDirect.Dot(aDirect));
+      if (thePrjState != nullptr)
+      {
+        *thePrjState = BVH_PrjStateInTriangle_EDGE;
+        *theNumberOfFirstNode = 2;
+        *theNumberOfLastNode = 0;
+      }
+      return theNode0 + aAC * (aACdotAP / (aACdotAP + aCAdotCP));
     }
-  
+
     T aNorm = aVA + aVB + aVC;
-  
-    const BVH_VecNt& aDirect = thePoint - (theNode0 * aVA +
-                                           theNode1 * aVB +
-                                           theNode2 * aVC) / aNorm;
-  
-    return (aDirect.Dot(aDirect));
+
+    if (thePrjState != nullptr)
+    {
+      *thePrjState = BVH_PrjStateInTriangle_INNER;
+    }
+
+    return (theNode0 * aVA + theNode1 * aVB + theNode2 * aVC) / aNorm;
+  }
+
+  //! Computes square distance between point and triangle
+  static T PointTriangleSquareDistance (const BVH_VecNt& thePoint,
+                                        const BVH_VecNt& theNode0,
+                                        const BVH_VecNt& theNode1,
+                                        const BVH_VecNt& theNode2)
+  {
+    const BVH_VecNt aProj = PointTriangleProjection(thePoint, theNode0, theNode1, theNode2);
+    const BVH_VecNt aPP = aProj - thePoint;
+    return aPP.Dot(aPP);
   }
 
 public: //! @name Ray-Box Intersection
index cb983a97811748b6cdd21dc9a0a7f298f4d3f151..6b1835d322873cd50d0159ad04d0d729eeb9b36f 100644 (file)
@@ -9,3 +9,4 @@
 009 bvh
 010 progress
 011 2ddeviation
+012 proximity
diff --git a/tests/lowalgos/proximity/A1 b/tests/lowalgos/proximity/A1
new file mode 100644 (file)
index 0000000..2a7025c
--- /dev/null
@@ -0,0 +1,24 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts ""
+
+circle c 0 0 0 1 0 0 5
+mkedge e1 c pi/2 pi
+mkedge e2 c -pi/2 0
+incmesh e1 1.e-3
+incmesh e2 1.e-3
+
+set log [proximity e1 e2 -value -profile]
+
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val
+set tol 1.e-3
+set expected 10.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Middle
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/A2 b/tests/lowalgos/proximity/A2
new file mode 100644 (file)
index 0000000..61a92c1
--- /dev/null
@@ -0,0 +1,26 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts ""
+
+circle c1 0 0 0 1 0 0 1
+mkedge e1 c1
+incmesh e1 1.e-3
+
+circle c2 0 0 0 0 1 0 1
+mkedge e2 c2
+incmesh e2 1.e-3
+set log [proximity e1 e2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 2.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Middle
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/A3 b/tests/lowalgos/proximity/A3
new file mode 100644 (file)
index 0000000..f878329
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts ""
+
+circle c1 0 -1 0 1 0 0 1
+trim c1 c1 -pi 0
+mkedge e1 c1
+incmesh e1 1.e-3
+
+circle c2 0 1 0 1 0 0 1
+trim c2 c2 0 pi
+mkedge e2 c2
+incmesh e2 1.e-3
+
+set log [proximity e1 e2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected [expr {sqrt(5.0) - 1.}]
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/A4 b/tests/lowalgos/proximity/A4
new file mode 100644 (file)
index 0000000..29c72fd
--- /dev/null
@@ -0,0 +1,26 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts ""
+
+circle c1 0 0 0 1 0 0 1
+mkedge e1 c1
+incmesh e1 1.e-3
+
+circle c2 0 0 0 -1 0.5 0 1
+mkedge e2 c2
+incmesh e2 1.e-3
+
+set log [proximity e1 e2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 2.0 
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Middle 
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/A5 b/tests/lowalgos/proximity/A5
new file mode 100644 (file)
index 0000000..19a1dae
--- /dev/null
@@ -0,0 +1,31 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts ""
+
+circle c1 0 0 0 1 0 0 1
+trim c1 c1 -pi/2. pi/2.
+mkedge e1 c1
+incmesh e1 1.e-3
+
+circle c2 0 0 0 1 0.5 0 1
+trim c2 c2 0 pi
+mkedge e2 c2
+incmesh e2 1.e-3
+
+set log [proximity e1 e2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+explode e1 v
+explode e2 v
+distmini d e1_1 e2_1
+regexp {([-0-9.+eE]+)$} [dump d_val] full expected
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/B1 b/tests/lowalgos/proximity/B1
new file mode 100644 (file)
index 0000000..68d4348
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts ""
+
+plane p1 0 0 0 0 0 1
+trim p1 p1 -1 1 -1 1
+mkface f1 p1
+incmesh f1 1.e-1
+
+plane p2 0 0 1 0 0 1
+trim p2 p2 -1 1 -1 1
+mkface f2 p2
+incmesh f2 1.e-1
+
+set log [proximity f1 f2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 1.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/B2 b/tests/lowalgos/proximity/B2
new file mode 100644 (file)
index 0000000..aff0e9a
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts ""
+
+plane p1 0 0 0 0 0 1
+trim p1 p1 -1 1 -1 1
+mkface f1 p1
+incmesh f1 1.e-1
+
+plane p2 0 0 1 -1 0 0
+trim p2 p2 -1 1 -1 1
+mkface f2 p2
+incmesh f2 1.e-1
+
+set log [proximity f1 f2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 1.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/B3 b/tests/lowalgos/proximity/B3
new file mode 100644 (file)
index 0000000..67f0c62
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts ""
+
+plane p1 0 0 0 0 0 1
+trim p1 p1 -1 1 -1 1
+mkface f1 p1
+incmesh f1 1.e-1
+
+plane p2 0 0 0 -1 0 0
+trim p2 p2 -1 1 -1 1
+mkface f2 p2
+incmesh f2 1.e-1
+
+set log [proximity f1 f2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 1.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/B4 b/tests/lowalgos/proximity/B4
new file mode 100644 (file)
index 0000000..1250bbf
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+plane p1 0 0 0 0 0 1
+trim p1 p1 -1 1 -1 1
+mkface f1 p1
+incmesh f1 1.e-1
+
+plane p2 0 0 0.5 -1 0 0
+trim p2 p2 -1 1 -1 1
+mkface f2 p2
+incmesh f2 1.e-1
+
+set log [proximity f1 f2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 1.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/B5 b/tests/lowalgos/proximity/B5
new file mode 100644 (file)
index 0000000..048d183
--- /dev/null
@@ -0,0 +1,27 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+plane p1 0 0 0 0 0 1
+trim p1 p1 -1 1 -1 1
+mkface f1 p1
+incmesh f1 1.e-3
+
+polyline f2 -1 -1 1  -1 1 1  1 1 2  1 -1 2  -1 -1 1
+mkplane f2 f2
+incmesh f2 1.e-3
+
+set log [proximity f1 f2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected [expr {0.8 * sqrt(5.0)}]
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/B6 b/tests/lowalgos/proximity/B6
new file mode 100644 (file)
index 0000000..860919a
--- /dev/null
@@ -0,0 +1,27 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+plane p1 0 0 0 0 0 1
+trim p1 p1 -1 1 -1 1
+mkface f1 p1
+incmesh f1 1.e-3
+
+circle c 0 0 1 1
+mkedge e1 c
+incmesh e1 1.e-3
+
+set log [proximity f1 e1 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 1.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Middle
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/C1 b/tests/lowalgos/proximity/C1
new file mode 100644 (file)
index 0000000..4575124
--- /dev/null
@@ -0,0 +1,29 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+plane p1 0 0 0 0 0 1
+trim p1 p1 -1 1 -1 1
+mkface f1 p1
+incmesh f1 1.e-3
+
+dset lo pi/2. la 0.
+cylinder cy1 0 0 0 cos(la)*cos(lo) cos(la)*sin(lo) sin(la) 0.1
+trimv cy1 cy1 0 1
+mkface fcy1 cy1
+incmesh fcy1 1.e-3
+
+set log [proximity f1 fcy1 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 0.1
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/C2 b/tests/lowalgos/proximity/C2
new file mode 100644 (file)
index 0000000..2920e41
--- /dev/null
@@ -0,0 +1,29 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+plane p1 0 0 0 0 0 1
+trim p1 p1 -2 2 -2 2
+mkface f1 p1
+incmesh f1 1.e-3
+
+dset lo pi/2. la pi/4.
+cylinder cy1 0 0 1 cos(la)*cos(lo) cos(la)*sin(lo) sin(la) 0.1
+trimv cy1 cy1 0 1
+mkface fcy1 cy1
+incmesh fcy1 1.e-3
+
+set log [proximity f1 fcy1 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected [expr {1. + 1.1 * sqrt(2.)/2.}]
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/C3 b/tests/lowalgos/proximity/C3
new file mode 100644 (file)
index 0000000..9323eb8
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+cylinder cy1 0 0 1 1 0 0 0.1
+trimv cy1 cy1 0 1
+mkface fcy1 cy1
+incmesh fcy1 1.e-3
+
+cylinder cy2 0 0 0 1 0 0 0.1
+trimv cy2 cy2 0 1
+mkface fcy2 cy2
+incmesh fcy2 1.e-3
+
+set log [proximity fcy1 fcy2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 1.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/C4 b/tests/lowalgos/proximity/C4
new file mode 100644 (file)
index 0000000..acbaf9f
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+cylinder cy1 0 0 1 1 0 0 0.1
+trim cy1 cy1 -pi/2. pi/2. 0 1
+mkface fcy1 cy1
+incmesh fcy1 1.e-5
+
+cylinder cy2 0 0 0 1 0 0 0.1
+trim cy2 cy2 pi/2. -pi/2. 0 1
+mkface fcy2 cy2
+incmesh fcy2 1.e-5 
+
+set log [proximity fcy1 fcy2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 1.2
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/D1 b/tests/lowalgos/proximity/D1
new file mode 100644 (file)
index 0000000..2e8dccc
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+sphere s1 0 1 0 0 0 1 1
+trimu s1 s1 0 pi
+mkface fs1 s1
+incmesh fs1 1e-3
+
+sphere s2 0 -1 0 0 0 1 1
+trimu s2 s2 -pi 0
+mkface fs2 s2
+incmesh fs2 1e-3
+
+set log [proximity fs1 fs2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-2
+set expected 4.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Middle
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/D2 b/tests/lowalgos/proximity/D2
new file mode 100644 (file)
index 0000000..0c19db3
--- /dev/null
@@ -0,0 +1,26 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+sphere s1 0 1 0 0 0 1 1
+mkface fs1 s1
+incmesh fs1 1e-3
+
+sphere s2 0 -1 0 0 0 1 1
+mkface fs2 s2
+incmesh fs2 1e-3
+
+set log [proximity fs1 fs2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-2
+set expected 4.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Middle 
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/D3 b/tests/lowalgos/proximity/D3
new file mode 100644 (file)
index 0000000..8a3704c
--- /dev/null
@@ -0,0 +1,33 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+sphere s1 0 1 0 0 0 1 1
+trimu s1_1 s1 0 0.5*pi
+trimu s1_2 s1 0.5*pi pi
+
+mkface fs1_1 s1_1
+mkface fs1_2 s1_2
+compound fs1_1 fs1_2 fs1
+incmesh fs1 1e-3
+
+plane p1 0 0 0 0 1 0
+trim p1 p1 -2 2 -2 2 
+mkface f2 p1
+incmesh f2 0.001
+
+set log [proximity fs1 f2 -value -profile]
+
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-2
+set expected 2.0
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Middle
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/E1 b/tests/lowalgos/proximity/E1
new file mode 100644 (file)
index 0000000..0997c11
--- /dev/null
@@ -0,0 +1,30 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+beziercurve bc1 7 10 84 0 54 96 0 145 146 0 167 167 0 185 212 0 187 234 0 176 302 0
+beziercurve bc2 8 120 72 0 170 87 0 227 118 0 238 126 0 243 157 0 203 216 0 134 281 0 94 324 0
+
+mkedge e1 bc1
+mkedge e2 bc2
+
+incmesh e1 1.e-3
+incmesh e2 1.e-3
+
+set log [proximity e1 e2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+explode e1 v
+explode e2 v
+distmini d e1_2 e2_2
+regexp {([-0-9.+eE]+)$} [dump d_val] full expected
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Border
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Border
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/E2 b/tests/lowalgos/proximity/E2
new file mode 100644 (file)
index 0000000..ffdd658
--- /dev/null
@@ -0,0 +1,27 @@
+puts "============"
+puts "0033017: Implement an algorithm to find a proximity between a pair of shapes"
+puts "==========="
+puts "" 
+
+beziercurve bc1 6 54 96 0 145 146 0 167 167 0 185 212 0 187 234 0 176 302 0
+beziercurve bc2 7 120 72 0 170 87 0 227 118 0 238 126 0 243 157 0 203 216 0 134 281 0
+
+mkedge e1 bc1
+mkedge e2 bc2
+
+incmesh e1 1.e-3
+incmesh e2 1.e-3
+
+set log [proximity e1 e2 -value -profile]
+regexp {Proximity value: ([0-9+-.eE]*)} $log full val;
+
+set tol 1.e-3
+set expected 76.34
+
+regexp {Status of ProxPnt1 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status1 ${val2}
+set expected_status1 Middle
+
+regexp {Status of ProxPnt2 on ([A-Za-z0-9._-]*) : ([A-Za-z]*)} $log full val1 val2
+set status2 ${val2}
+set expected_status2 Middle
\ No newline at end of file
diff --git a/tests/lowalgos/proximity/end b/tests/lowalgos/proximity/end
new file mode 100644 (file)
index 0000000..43cebce
--- /dev/null
@@ -0,0 +1,19 @@
+set er [expr abs(${expected} - ${val})]
+
+if {${er} > ${tol}} {
+   puts "Error: bad proximity value"
+} else {
+   puts "OK"
+}
+
+if {${status1} != ${expected_status1}} {
+   puts "Error: bad 1st proximity point status"
+} else {
+   puts "OK"
+}
+
+if {${status2} != ${expected_status2}} {
+   puts "Error: bad 2nd proximity point status"
+} else {
+   puts "OK"
+}
\ No newline at end of file