]> OCCT Git - occt-copy.git/commitdiff
0025589: modify the wire interference checker to detect all types of intersections CR25589
authorrazmyslovich <razmyslovich@volumegraphics.com>
Wed, 10 Dec 2014 13:43:53 +0000 (14:43 +0100)
committerrazmyslovich <razmyslovich@volumegraphics.com>
Wed, 10 Dec 2014 13:43:53 +0000 (14:43 +0100)
src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx

index a8273b3f08b0d78c3b8502232f21ddf4ee02b19d..4e1d586ee3bc718ded75c6ee284e119f76cdf900 100644 (file)
@@ -59,6 +59,47 @@ BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
 }
 #endif
 
+bool ArePointsOnDifferentSides(const gp_Pnt2d & point1, const gp_Pnt2d & point2, const BRepMesh::Segment & segment1, const BRepMesh::Segment & segment2)
+{
+  return 0 > (((segment1.EndPnt.X()-segment1.StartPnt.X())*(point1.Y()-segment1.StartPnt.Y())-(point1.X()-segment1.StartPnt.X())*(segment1.EndPnt.Y()-segment1.StartPnt.Y())) * 
+              ((segment2.EndPnt.X()-segment2.StartPnt.X())*(point2.Y()-segment2.StartPnt.Y())-(point2.X()-segment2.StartPnt.X())*(segment2.EndPnt.Y()-segment2.StartPnt.Y())));
+}
+
+const BRepMesh::Segment& GetSegmentFromArray(Standard_Integer idx, const BRepMesh::HArray1OfSegments& segsarray)
+{
+  if (idx < segsarray->Lower())
+  {
+    idx = segsarray->Upper();
+  }
+  if (idx > segsarray->Upper())
+  {
+    idx = segsarray->Lower();
+  }
+  return segsarray->Value(idx);
+}
+
+bool CheckSelftIntersectArea(Standard_Integer idx1, Standard_Integer idx2, const BRepMesh::HArray1OfSegments& segsarray, const gp_Pnt2d & intPnt)
+{
+  gp_XY aPrevVec;
+  Standard_Real aSumS = 0.;
+  const gp_XY& aRefPnt  = intPnt.Coord();
+  for (Standard_Integer i = idx1; i < idx2; ++i)
+  {
+    const BRepMesh::Segment& aSeg = segsarray->Value(i);
+    gp_XY aCurVec = aSeg.EndPnt - aRefPnt;
+
+    if (aCurVec.SquareModulus() < gp::Resolution())
+      continue;
+
+    if (aPrevVec.SquareModulus() > gp::Resolution())
+      aSumS += aPrevVec ^ aCurVec;
+
+    aPrevVec = aCurVec;
+  }
+
+  return (Abs(aSumS / 2.) < MIN_LOOP_S);
+}
+
 //=======================================================================
 //function : Checker's body
 //purpose  : 
@@ -125,33 +166,15 @@ void BRepMesh_WireInterferenceChecker::operator ()(
         BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
           aSegment1.StartPnt, aSegment1.EndPnt, 
           aSegment2.StartPnt, aSegment2.EndPnt,
-          Standard_False, Standard_False,
+          Standard_True, Standard_True,
           aIntPnt);
 
-        if (aIntStatus == BRepMesh_GeomTool::Cross)
+        if (aIntStatus == BRepMesh_GeomTool::Cross || aIntStatus == BRepMesh_GeomTool::Glued || aIntStatus == BRepMesh_GeomTool::PointOnSegment)
         {
           // TODO: remove this block after implementation of LoopChecker2d.
-          if (isSelfIntCheck)
+          if (isSelfIntCheck && CheckSelftIntersectArea(aSegmentId1, aSegmentId2, aWireSegments1, aIntPnt))
           {
-            gp_XY aPrevVec;
-            Standard_Real aSumS = 0.;
-            const gp_XY& aRefPnt  = aIntPnt.Coord();
-            for (Standard_Integer i = aSegmentId1; i < aSegmentId2; ++i)
-            {
-              const BRepMesh::Segment& aSeg = aWireSegments1->Value(i);
-              gp_XY aCurVec = aSeg.EndPnt - aRefPnt;
-
-              if (aCurVec.SquareModulus() < gp::Resolution())
-                continue;
-
-              if (aPrevVec.SquareModulus() > gp::Resolution())
-                aSumS += aPrevVec ^ aCurVec;
-
-              aPrevVec = aCurVec;
-            }
-
-            if (Abs(aSumS / 2.) < MIN_LOOP_S)
-              continue;
+            continue;
           }
 
 #ifdef HAVE_TBB
@@ -160,6 +183,45 @@ void BRepMesh_WireInterferenceChecker::operator ()(
           *myStatus = BRepMesh_SelfIntersectingWire;
           return;
         }
+
+        if (aIntStatus == BRepMesh_GeomTool::EndPointTouch && (!isSelfIntCheck || abs(aSegmentId1 - aSegmentId2) > 2))
+        {
+          bool segmentsAreEqual = false;
+          gp_Pnt2d otherPnt1;
+          gp_Pnt2d otherPnt2;
+          const BRepMesh::Segment * refSegment1 = &aSegment2;
+          const BRepMesh::Segment * refSegment2 = NULL;
+          Standard_Boolean s1s2 = aSegment1.StartPnt.IsEqual(aSegment2.StartPnt, Precision::PConfusion());
+          Standard_Boolean s1e2 = aSegment1.StartPnt.IsEqual(aSegment2.EndPnt, Precision::PConfusion());
+          Standard_Boolean e1e2 = aSegment1.EndPnt.IsEqual(aSegment2.EndPnt, Precision::PConfusion());
+          Standard_Boolean e1s2 = aSegment1.EndPnt.IsEqual(aSegment2.StartPnt, Precision::PConfusion());
+
+          if ((s1s2 && e1e2) || (s1e2 && e1s2))
+          {
+            segmentsAreEqual = true;
+          }
+          else
+          {
+            otherPnt1 = (s1s2 || s1e2)? aSegment1.EndPnt : aSegment1.StartPnt;
+            otherPnt2 = GetSegmentFromArray(aSegmentId1 + ((s1s2 || s1e2)? -1 : 1), aWireSegments1).StartPnt;
+            refSegment2 = &(GetSegmentFromArray(aSegmentId2 + ((s1s2 || e1s2)? -1 : 1), aWireSegments2));
+          }
+
+          if (!segmentsAreEqual && NULL != refSegment1 && NULL != refSegment2 && ArePointsOnDifferentSides(otherPnt1, otherPnt2, *refSegment1, *refSegment2))
+          {
+            if (isSelfIntCheck && CheckSelftIntersectArea(aSegmentId1, aSegmentId2, aWireSegments1, aIntPnt))
+            {
+              continue;
+            }
+
+#ifdef HAVE_TBB
+            Standard_Mutex::Sentry aSentry(myMutex);
+#endif
+            *myStatus = BRepMesh_SelfIntersectingWire;
+            return;
+          }
+        }
+
       }
     }
   }