From: razmyslovich Date: Wed, 10 Dec 2014 13:43:53 +0000 (+0100) Subject: 0025589: modify the wire interference checker to detect all types of intersections X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=30d665dfb036fce22aae37386e711ac13cde7391;p=occt-copy.git 0025589: modify the wire interference checker to detect all types of intersections --- diff --git a/src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx b/src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx index a8273b3f08..4e1d586ee3 100644 --- a/src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx +++ b/src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx @@ -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; + } + } + } } }