From f7ad1e7e3729c128014a23f18c028c55f50db301 Mon Sep 17 00:00:00 2001 From: pdn Date: Tue, 23 Sep 2014 12:04:57 +0400 Subject: [PATCH] 0025262: Foundation Classes - Poly package improvements Improvements of functionality of Poly package: * Add function to intersect a triangulation by an axis. * Add function to intersect a triangle by an axis. * Correct the bugs in the methods RemoveDegenerated, RemoveTriangle and ReplaceNodes of the class Poly_CoherentTriangulation. --- src/Poly/Poly.cxx | 122 +++++++++++++++++++++++- src/Poly/Poly.hxx | 43 +++++---- src/Poly/Poly_CoherentTriangulation.cxx | 66 +++++++------ 3 files changed, 185 insertions(+), 46 deletions(-) diff --git a/src/Poly/Poly.cxx b/src/Poly/Poly.cxx index 18d7afac9c..b6bd5b2d53 100644 --- a/src/Poly/Poly.cxx +++ b/src/Poly/Poly.cxx @@ -14,11 +14,12 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include +#include #include #include #include -#include #include #include #include @@ -562,3 +563,122 @@ Standard_Real Poly::PointOnTriangle (const gp_XY& theP1, const gp_XY& theP2, con } } +//======================================================================= +//function : Intersect +//purpose : +//======================================================================= +Standard_Boolean Poly::Intersect (const Handle(Poly_Triangulation)& theTri, + const gp_Ax1& theAxis, + const Standard_Boolean theIsClosest, + Poly_Triangle& theTriangle, + Standard_Real& theDistance) +{ + const Standard_Real aConf = 1E-15; + const gp_XYZ& aLoc = theAxis.Location().XYZ(); + const gp_Dir& aDir = theAxis.Direction(); + + Standard_Real aResult = theIsClosest ? RealLast() : 0.0; + Standard_Real aParam = 0.0; + Standard_Integer aTriNodes[3] = {}; + for (Standard_Integer aTriIter = 1; aTriIter <= theTri->NbTriangles(); ++aTriIter) + { + const Poly_Triangle& aTri = theTri->Triangle (aTriIter); + aTri.Get (aTriNodes[0], aTriNodes[1], aTriNodes[2]); + if (IntersectTriLine (aLoc, aDir, + theTri->Node (aTriNodes[0]).XYZ(), + theTri->Node (aTriNodes[1]).XYZ(), + theTri->Node (aTriNodes[2]).XYZ(), + aParam)) + { + if (aParam > aConf) + { + if (theIsClosest) + { + if (aParam < aResult) + { + aResult = aParam; + theTriangle = aTri; + } + } + else if (aParam > aResult) + { + aResult = aParam; + theTriangle = aTri; + } + } + } + } + + if (aConf < aResult && aResult < RealLast()) + { + theDistance = aResult; + return Standard_True; + } + return Standard_False; +} + +//! Calculate the minor of the given matrix, defined by the columns specified by values c1, c2, c3. +static double Determinant (const double a[3][4], + const int c1, + const int c2, + const int c3) +{ + return a[0][c1]*a[1][c2]*a[2][c3] + + a[0][c2]*a[1][c3]*a[2][c1] + + a[0][c3]*a[1][c1]*a[2][c2] - + a[0][c3]*a[1][c2]*a[2][c1] - + a[0][c2]*a[1][c1]*a[2][c3] - + a[0][c1]*a[1][c3]*a[2][c2]; +} + +//======================================================================= +//function : IntersectTriLine +//purpose : Intersect a triangle with a line +//======================================================================= +Standard_Integer Poly::IntersectTriLine (const gp_XYZ& theStart, + const gp_Dir& theDir, + const gp_XYZ& theV0, + const gp_XYZ& theV1, + const gp_XYZ& theV2, + Standard_Real& theParam) +{ + int aRes = 0; + const double aConf = 1E-15; + + const double aMat34[3][4] = + { + { -theDir.X(), + theV1.X() - theV0.X(), theV2.X() - theV0.X(), theStart.X() - theV0.X() }, + { -theDir.Y(), + theV1.Y() - theV0.Y(), theV2.Y() - theV0.Y(), theStart.Y() - theV0.Y() }, + { -theDir.Z(), + theV1.Z() - theV0.Z(), theV2.Z() - theV0.Z(), theStart.Z() - theV0.Z() } + }; + + const double aD = Determinant (aMat34, 0, 1, 2); + const double aDt = Determinant (aMat34, 3, 1, 2); + if (aD > aConf) + { + const double aDa = Determinant (aMat34, 0, 3, 2); + if (aDa > -aConf) + { + const double aDb = Determinant (aMat34, 0, 1, 3); + aRes = ((aDb > -aConf) && (aDa + aDb <= aD + aConf)); + } + } + else if (aD < -aConf) + { + const double aDa = Determinant (aMat34, 0, 3, 2); + if (aDa < aConf) + { + const double aDb = Determinant (aMat34, 0, 1, 3); + aRes = ((aDb < aConf) && (aDa + aDb >= aD - aConf)); + } + } + if (aRes != 0) + { + theParam = aDt / aD; + } + + return aRes; +} diff --git a/src/Poly/Poly.hxx b/src/Poly/Poly.hxx index 203de140ef..e9d4a6a00f 100644 --- a/src/Poly/Poly.hxx +++ b/src/Poly/Poly.hxx @@ -125,6 +125,33 @@ public: //! point is inside). Standard_EXPORT static Standard_Real PointOnTriangle (const gp_XY& P1, const gp_XY& P2, const gp_XY& P3, const gp_XY& P, gp_XY& UV); + //! Computes the intersection between axis and triangulation. + //! @param theTri [in] input triangulation + //! @param theAxis [in] intersecting ray + //! @param theIsClosest [in] finds the closest intersection when TRUE, finds the farthest otherwise + //! @param theTriangle [out] intersected triangle + //! @param theDistance [out] distance along ray to intersection point + //! @return TRUE if intersection takes place, FALSE otherwise. + Standard_EXPORT static Standard_Boolean Intersect (const Handle(Poly_Triangulation)& theTri, + const gp_Ax1& theAxis, + const Standard_Boolean theIsClosest, + Poly_Triangle& theTriangle, + Standard_Real& theDistance); + + //! Computes the intersection between a triangle defined by three vertexes and a line. + //! @param theStart [in] picking ray origin + //! @param theDir [in] picking ray direction + //! @param theV0 [in] first triangle node + //! @param theV1 [in] second triangle node + //! @param theV2 [in] third triangle node + //! @param theParam [out] param on line of the intersection point + //! @return 1 if intersection was found, 0 otherwise. + Standard_EXPORT static Standard_Integer IntersectTriLine (const gp_XYZ& theStart, + const gp_Dir& theDir, + const gp_XYZ& theV0, + const gp_XYZ& theV1, + const gp_XYZ& theV2, + Standard_Real& theParam); //! Returns area and perimeter of 2D-polygon given by its vertices. //! theArea will be negative if the polygon is bypassed clockwise @@ -169,18 +196,8 @@ public: return Standard_True; } - -protected: - - - - - private: - - - friend class Poly_Triangle; friend class Poly_Triangulation; friend class Poly_Polygon3D; @@ -190,10 +207,4 @@ friend class Poly_Connect; }; - - - - - - #endif // _Poly_HeaderFile diff --git a/src/Poly/Poly_CoherentTriangulation.cxx b/src/Poly/Poly_CoherentTriangulation.cxx index 91d0a33b6e..a30a68d225 100644 --- a/src/Poly/Poly_CoherentTriangulation.cxx +++ b/src/Poly/Poly_CoherentTriangulation.cxx @@ -222,34 +222,42 @@ Standard_Boolean Poly_CoherentTriangulation::RemoveDegenerated const Standard_Integer ip1(aTri.Node(ind[i+1])); // Disconnect from both neighbours - Poly_CoherentTriangle * pTriConn[2] = { - const_cast(aTri.GetConnectedTri(ind[i-1])), - const_cast(aTri.GetConnectedTri(ind[i+1])) - }; RemoveTriangle(aTri); // Reconnect all triangles from Node(ind[i+1]) to Node(ind[i-1]) - Poly_CoherentTriPtr::Iterator anIterConn = - pNode[ind[i+1]]->TriangleIterator(); - for (; anIterConn.More(); anIterConn.Next()) { + for (;;) + { + Poly_CoherentTriPtr::Iterator anIterConn = pNode[ind[i+1]]->TriangleIterator(); + if (!anIterConn.More()) + { + break; + } + Poly_CoherentTriangle& aTriConn = anIterConn.ChangeValue(); - if (&aTriConn != &aTri) { - if (aTriConn.Node(0) == ip1) - aTriConn.myNodes[0] = im1; - else if (aTriConn.Node(1) == ip1) - aTriConn.myNodes[1] = im1; - else if (aTriConn.Node(2) == ip1) - aTriConn.myNodes[2] = im1; - pNode[ind[i+1]]->RemoveTriangle(aTriConn, myAlloc); - pNode[ind[i-1]]->AddTriangle(aTriConn, myAlloc); + Standard_Integer aNewTriConn[] = {aTriConn.Node(0), aTriConn.Node(1), aTriConn.Node(2)}; + if (&aTriConn != &aTri) + { + if (aNewTriConn[0] == ip1) + aNewTriConn[0] = im1; + else if (aNewTriConn[1] == ip1) + aNewTriConn[1] = im1; + else if (aNewTriConn[2] == ip1) + aNewTriConn[2] = im1; + + RemoveTriangle (aTriConn); + AddTriangle (aNewTriConn[0], aNewTriConn[1], aNewTriConn[2]); + } + else + { + anIterConn.Next(); + if (!anIterConn.More()) + { + break; + } } } - // Set the new mutual connection between the neighbours of the - // removed degenerated triangle. - if (pTriConn[0] && pTriConn[1]) { - pTriConn[0]->SetConnection(* pTriConn[1]); - } - if (pLstRemovedNode) { + if (pLstRemovedNode) + { pLstRemovedNode->Append(TwoIntegers(ip1, im1)); } aResult = Standard_True; @@ -440,10 +448,6 @@ Standard_Boolean Poly_CoherentTriangulation::RemoveTriangle for (Standard_Integer i = 0; i < 3; i++) { if (theTriangle.Node(i) >= 0) { Poly_CoherentNode& aNode = myNodes(theTriangle.Node(i)); - if (aNode.RemoveTriangle(theTriangle, myAlloc)) { - theTriangle.myNodes[i] = -1; - aResult = Standard_True; - } // If Links exist in this Triangulation, remove or update a Link Poly_CoherentLink * aLink = const_cast(theTriangle.mypLink[i]); @@ -456,10 +460,10 @@ Standard_Boolean Poly_CoherentTriangulation::RemoveTriangle for (Standard_Integer j = 0; j < 3; j++) { if (aLink == pTriOpp->GetLink(j)) { if (aLink->OppositeNode(0) == theTriangle.Node(i)) { - aLink->myOppositeNode[0] = 0L; + aLink->myOppositeNode[0] = -1; toRemoveLink = Standard_False; } else if (aLink->OppositeNode(1) == theTriangle.Node(i)) { - aLink->myOppositeNode[1] = 0L; + aLink->myOppositeNode[1] = -1; toRemoveLink = Standard_False; } break; @@ -469,6 +473,11 @@ Standard_Boolean Poly_CoherentTriangulation::RemoveTriangle if (toRemoveLink) RemoveLink(* aLink); } + if (aNode.RemoveTriangle(theTriangle, myAlloc)) + { + theTriangle.myNodes[i] = -1; + aResult = Standard_True; + } } theTriangle.RemoveConnection(i); } @@ -540,7 +549,6 @@ Standard_Boolean Poly_CoherentTriangulation::ReplaceNodes toAddLink = Standard_False; } } - break; } } }