a8273b3f08b0d78c3b8502232f21ddf4ee02b19d
[occt.git] / src / BRepMesh / BRepMesh_WireInterferenceChecker.cxx
1 // Created on: 2014-06-18
2 // Created by: Oleg AGASHIN
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepMesh_WireInterferenceChecker.hxx>
17 #include <BRepMesh_GeomTool.hxx>
18 #include <Precision.hxx>
19
20 // TODO: remove this variable after implementation of LoopChecker2d.
21 static const Standard_Real MIN_LOOP_S = 2 * M_PI * 2.E-5;
22
23 #ifdef HAVE_TBB
24 //=======================================================================
25 //function : Constructor
26 //purpose  :
27 //=======================================================================
28 BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
29   const BRepMesh::Array1OfSegmentsTree& theWires,
30   BRepMesh_Status*                      theStatus,
31   Standard_Mutex*                       theMutex)
32 : myWires (theWires),
33   myStatus(theStatus),
34   myMutex (theMutex)
35 {
36 }
37
38 //=======================================================================
39 //function : Checker's body
40 //purpose  : 
41 //=======================================================================
42 void BRepMesh_WireInterferenceChecker::operator ()(
43   const tbb::blocked_range<Standard_Integer>& theWireRange) const
44 {
45   for (Standard_Integer i = theWireRange.begin(); i != theWireRange.end(); ++i)
46     this->operator ()(i);
47 }
48 #else
49 //=======================================================================
50 //function : Constructor
51 //purpose  : 
52 //=======================================================================
53 BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
54   const BRepMesh::Array1OfSegmentsTree& theWires,
55   BRepMesh_Status*                      theStatus)
56 : myWires (theWires),
57   myStatus(theStatus)
58 {
59 }
60 #endif
61
62 //=======================================================================
63 //function : Checker's body
64 //purpose  : 
65 //=======================================================================
66 void BRepMesh_WireInterferenceChecker::operator ()(
67   const Standard_Integer& theWireId) const
68 {
69   if (*myStatus == BRepMesh_SelfIntersectingWire)
70     return;
71
72   const BRepMesh::SegmentsTree&      aWireSegTree1  = myWires(theWireId);
73   const BRepMesh::HArray1OfSegments& aWireSegments1 = aWireSegTree1.first;
74   const BRepMesh::HBndBox2dTree&     aWireBoxTree1  = aWireSegTree1.second;
75
76   for (Standard_Integer aWireIt = theWireId; aWireIt <= myWires.Upper(); ++aWireIt)
77   {
78 #ifdef HAVE_TBB
79     // Break execution in case if flag was raised by another thread
80     if (*myStatus == BRepMesh_SelfIntersectingWire)
81       return;
82 #endif
83
84     const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId);
85     const BRepMesh::SegmentsTree& aWireSegTree2 = 
86       isSelfIntCheck ? aWireSegTree1 : myWires(aWireIt);
87
88     const BRepMesh::HArray1OfSegments& aWireSegments2 = aWireSegTree2.first;
89     const BRepMesh::HBndBox2dTree&     aWireBoxTree2  = aWireSegTree2.second;
90
91     BRepMesh_WireChecker::BndBox2dTreeSelector aSelector (aWireSegments2->Size());
92
93     Standard_Integer aSegmentId1 = aWireSegments1->Lower();
94     for (; aSegmentId1 <= aWireSegments1->Upper(); ++aSegmentId1)
95     {
96 #ifdef HAVE_TBB
97       // Break execution in case if flag was raised by another thread
98       if (*myStatus == BRepMesh_SelfIntersectingWire)
99         return;
100 #endif
101
102       aSelector.Clear();
103       aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd());
104       if (isSelfIntCheck)
105         aSelector.SetSkippedIndex(aSegmentId1);
106
107       if (aWireBoxTree2->Select(aSelector) == 0)
108         continue;
109
110       const BRepMesh::Segment& aSegment1 = aWireSegments1->Value(aSegmentId1);
111       const BRepMesh::Array1OfInteger& aSelected = aSelector.Indices();
112       const Standard_Integer aSelectedNb = aSelector.IndicesNb();
113       for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt)
114       {
115 #ifdef HAVE_TBB
116         // Break execution in case if flag was raised by another thread
117         if (*myStatus == BRepMesh_SelfIntersectingWire)
118           return;
119 #endif
120
121         const Standard_Integer aSegmentId2 = aSelected(aBndIt);
122         const BRepMesh::Segment& aSegment2 = aWireSegments2->Value(aSegmentId2);
123
124         gp_Pnt2d aIntPnt;
125         BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
126           aSegment1.StartPnt, aSegment1.EndPnt, 
127           aSegment2.StartPnt, aSegment2.EndPnt,
128           Standard_False, Standard_False,
129           aIntPnt);
130
131         if (aIntStatus == BRepMesh_GeomTool::Cross)
132         {
133           // TODO: remove this block after implementation of LoopChecker2d.
134           if (isSelfIntCheck)
135           {
136             gp_XY aPrevVec;
137             Standard_Real aSumS = 0.;
138             const gp_XY& aRefPnt  = aIntPnt.Coord();
139             for (Standard_Integer i = aSegmentId1; i < aSegmentId2; ++i)
140             {
141               const BRepMesh::Segment& aSeg = aWireSegments1->Value(i);
142               gp_XY aCurVec = aSeg.EndPnt - aRefPnt;
143
144               if (aCurVec.SquareModulus() < gp::Resolution())
145                 continue;
146
147               if (aPrevVec.SquareModulus() > gp::Resolution())
148                 aSumS += aPrevVec ^ aCurVec;
149
150               aPrevVec = aCurVec;
151             }
152
153             if (Abs(aSumS / 2.) < MIN_LOOP_S)
154               continue;
155           }
156
157 #ifdef HAVE_TBB
158           Standard_Mutex::Sentry aSentry(myMutex);
159 #endif
160           *myStatus = BRepMesh_SelfIntersectingWire;
161           return;
162         }
163       }
164     }
165   }
166 }