3accbd570c76338575991dbd7a91849c49c36d59
[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 std::vector<BRepMeshCol::SegmentsTree>& theWires,
30   BRepMesh_Status*                              theStatus,
31   Standard_Mutex*                               theMutex)
32   : myWires(&theWires.front()),
33     myWiresNb(theWires.size()),
34     myStatus(theStatus),
35     myMutex(theMutex)
36 {
37 }
38
39 //=======================================================================
40 //function : Checker's body
41 //purpose  : 
42 //=======================================================================
43 void BRepMesh_WireInterferenceChecker::operator ()(
44   const tbb::blocked_range<Standard_Integer>& theWireRange) const
45 {
46   for (Standard_Integer i = theWireRange.begin(); i != theWireRange.end(); ++i)
47     this->operator ()(i);
48 }
49 #else
50 //=======================================================================
51 //function : Constructor
52 //purpose  : 
53 //=======================================================================
54 BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
55   const std::vector<BRepMesh_WireChecker::SegmentsTree>& theWires,
56   BRepMesh_Status*                                       theStatus)
57   : myWires(&theWires.front()),
58     myWiresNb(theWires.size()),
59     myStatus(theStatus)
60 {
61 }
62 #endif
63
64 //=======================================================================
65 //function : Checker's body
66 //purpose  : 
67 //=======================================================================
68 void BRepMesh_WireInterferenceChecker::operator ()(
69   const Standard_Integer& theWireId) const
70 {
71   if (*myStatus == BRepMesh_SelfIntersectingWire)
72     return;
73
74   const BRepMeshCol::SegmentsTree&  aWireSegTree1  = myWires[theWireId];
75   const BRepMeshCol::Segment*       aWireSegments1 = &aWireSegTree1.first->front();
76   const BRepMeshCol::HBndBox2dTree& aWireBoxTree1  = aWireSegTree1.second;
77   const Standard_Integer aWireLen1 = aWireSegTree1.first->size();
78
79   for (Standard_Integer aWireIt = theWireId; aWireIt < myWiresNb; ++aWireIt)
80   {
81 #ifdef HAVE_TBB
82     // Break execution in case if flag was raised by another thread
83     if (*myStatus == BRepMesh_SelfIntersectingWire)
84       return;
85 #endif
86
87     const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId);
88     const BRepMeshCol::SegmentsTree& aWireSegTree2 = 
89       isSelfIntCheck ? aWireSegTree1 : myWires[aWireIt];
90
91     const BRepMeshCol::Segment*       aWireSegments2 = &aWireSegTree2.first->front();
92     const BRepMeshCol::HBndBox2dTree& aWireBoxTree2  = aWireSegTree2.second;
93
94     BRepMesh_WireChecker::BndBox2dTreeSelector aSelector(aWireSegTree2.first->size());
95     for (Standard_Integer aSegmentId1 = 0; aSegmentId1 < aWireLen1; ++aSegmentId1)
96     {
97 #ifdef HAVE_TBB
98       // Break execution in case if flag was raised by another thread
99       if (*myStatus == BRepMesh_SelfIntersectingWire)
100         return;
101 #endif
102
103       aSelector.Clear();
104       aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd());
105       if (isSelfIntCheck)
106         aSelector.SetSkippedIndex(aSegmentId1);
107
108       if (aWireBoxTree2->Select(aSelector) == 0)
109         continue;
110
111       const BRepMeshCol::Segment& aSegment1 = aWireSegments1[aSegmentId1];
112       const BRepMeshCol::Array1OfInteger& aSelected = aSelector.Indices();
113       const Standard_Integer aSelectedNb = aSelector.IndicesNb();
114       for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt)
115       {
116 #ifdef HAVE_TBB
117         // Break execution in case if flag was raised by another thread
118         if (*myStatus == BRepMesh_SelfIntersectingWire)
119           return;
120 #endif
121
122         const Standard_Integer aSegmentId2 = aSelected(aBndIt);
123         const BRepMeshCol::Segment& aSegment2 = aWireSegments2[aSegmentId2];
124
125         gp_Pnt2d aIntPnt;
126         BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
127           aSegment1.StartPnt, aSegment1.EndPnt, 
128           aSegment2.StartPnt, aSegment2.EndPnt,
129           Standard_False, Standard_False,
130           aIntPnt);
131
132         if (aIntStatus == BRepMesh_GeomTool::Cross)
133         {
134           // TODO: remove this block after implementation of LoopChecker2d.
135           if (isSelfIntCheck)
136           {
137             gp_XY aPrevVec;
138             Standard_Real aSumS = 0.;
139             const gp_XY& aRefPnt  = aIntPnt.Coord();
140             for (Standard_Integer i = aSegmentId1; i < aSegmentId2; ++i)
141             {
142               const BRepMeshCol::Segment& aSeg = aWireSegments1[i];
143               gp_XY aCurVec = aSeg.EndPnt - aRefPnt;
144
145               if (aCurVec.SquareModulus() < gp::Resolution())
146                 continue;
147
148               if (aPrevVec.SquareModulus() > gp::Resolution())
149                 aSumS += aPrevVec ^ aCurVec;
150
151               aPrevVec = aCurVec;
152             }
153
154             if (Abs(aSumS / 2.) < MIN_LOOP_S)
155               continue;
156           }
157
158 #ifdef HAVE_TBB
159           Standard_Mutex::Sentry aSentry(myMutex);
160 #endif
161           *myStatus = BRepMesh_SelfIntersectingWire;
162           return;
163         }
164       }
165     }
166   }
167 }