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.
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
#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
//! 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.
#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
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;
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);
//=======================================================================
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;
}
//=======================================================================
//=======================================================================
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;
}
//=======================================================================
//=======================================================================
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);
+ }
}
#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:
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).
}
//! 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.
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.
//! 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
#include <BRep_Tool.hxx>
#include <BVH_LinearBuilder.hxx>
#include <Poly_Triangulation.hxx>
+#include <TopoDS.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepExtrema_TriangleSet, BVH_PrimitiveSet3d)
{
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
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
//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
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());
+}
#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
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,
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.
//! 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)
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
{
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;
}
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)
{
if (aFlag == "-tol")
{
+ isTolerance = Standard_True;
if (++anArgIdx >= theNbArgs)
{
Message::SendFail() << "Error: wrong syntax at argument '" << aFlag;
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;
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;
}
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,
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
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;
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
009 bvh
010 progress
011 2ddeviation
+012 proximity
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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