}
#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 :
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
*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;
+ }
+ }
+
}
}
}