0025262: Foundation Classes - Poly package improvements
authorpdn <pdn@opencascade.com>
Tue, 23 Sep 2014 08:04:57 +0000 (12:04 +0400)
committerbugmaster <bugmaster@opencascade.com>
Sun, 21 Mar 2021 16:15:07 +0000 (19:15 +0300)
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
src/Poly/Poly.hxx
src/Poly/Poly_CoherentTriangulation.cxx

index 18d7afa..b6bd5b2 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <Poly.hxx>
 
+#include <gp_Ax1.hxx>
 #include <gp_Pnt.hxx>
 #include <gp_Pnt2d.hxx>
 #include <gp_XY.hxx>
-#include <Poly.hxx>
 #include <Poly_Array1OfTriangle.hxx>
 #include <Poly_ListOfTriangulation.hxx>
 #include <Poly_Polygon2D.hxx>
@@ -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;
+}
index 203de14..e9d4a6a 100644 (file)
@@ -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
index 91d0a33..a30a68d 100644 (file)
@@ -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<Poly_CoherentTriangle *>(aTri.GetConnectedTri(ind[i-1])),
-          const_cast<Poly_CoherentTriangle *>(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<Poly_CoherentLink *>(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;
             }
           }
         }