0026106: BRepMesh - revision of data model
[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 //=======================================================================
24 //function : Constructor
25 //purpose  :
26 //=======================================================================
27 BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
28   const BRepMesh::Array1OfSegmentsTree& theWires,
29   BRepMesh_Status*                      theStatus,
30   Standard_Mutex*                       theMutex)
31 : myWires (theWires),
32   myStatus(theStatus),
33   myMutex (theMutex)
34 {
35 }
36
37 //=======================================================================
38 //function : Checker's body
39 //purpose  : 
40 //=======================================================================
41 void BRepMesh_WireInterferenceChecker::operator ()(
42   const Standard_Integer& theWireId) const
43 {
44   if (*myStatus == BRepMesh_SelfIntersectingWire)
45     return;
46
47   const BRepMesh::SegmentsTree&      aWireSegTree1  = myWires(theWireId);
48   const BRepMesh::HArray1OfSegments& aWireSegments1 = aWireSegTree1.first;
49   const BRepMesh::HBndBox2dTree&     aWireBoxTree1  = aWireSegTree1.second;
50
51   for (Standard_Integer aWireIt = theWireId; aWireIt <= myWires.Upper(); ++aWireIt)
52   {
53     // Break execution in case if flag was raised by another thread.
54     if (*myStatus == BRepMesh_SelfIntersectingWire)
55       return;
56
57     const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId);
58     const BRepMesh::SegmentsTree& aWireSegTree2 = 
59       isSelfIntCheck ? aWireSegTree1 : myWires(aWireIt);
60
61     const BRepMesh::HArray1OfSegments& aWireSegments2 = aWireSegTree2.first;
62     const BRepMesh::HBndBox2dTree&     aWireBoxTree2  = aWireSegTree2.second;
63
64     BRepMesh_WireChecker::BndBox2dTreeSelector aSelector (aWireSegments2->Size());
65
66     Standard_Integer aSegmentId1 = aWireSegments1->Lower();
67     for (; aSegmentId1 <= aWireSegments1->Upper(); ++aSegmentId1)
68     {
69       // Break execution in case if flag was raised by another thread
70       if (*myStatus == BRepMesh_SelfIntersectingWire)
71         return;
72
73       aSelector.Clear();
74       aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd());
75       if (isSelfIntCheck)
76         aSelector.SetSkippedIndex(aSegmentId1);
77
78       if (aWireBoxTree2->Select(aSelector) == 0)
79         continue;
80
81       const BRepMesh::Segment& aSegment1 = aWireSegments1->Value(aSegmentId1);
82       const BRepMesh::Array1OfInteger& aSelected = aSelector.Indices();
83       const Standard_Integer aSelectedNb = aSelector.IndicesNb();
84       for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt)
85       {
86         // Break execution in case if flag was raised by another thread
87         if (*myStatus == BRepMesh_SelfIntersectingWire)
88           return;
89
90         const Standard_Integer aSegmentId2 = aSelected(aBndIt);
91         const BRepMesh::Segment& aSegment2 = aWireSegments2->Value(aSegmentId2);
92
93         gp_Pnt2d aIntPnt;
94         BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
95           aSegment1.StartPnt, aSegment1.EndPnt, 
96           aSegment2.StartPnt, aSegment2.EndPnt,
97           Standard_False, Standard_False,
98           aIntPnt);
99
100         if (aIntStatus == BRepMesh_GeomTool::Cross)
101         {
102           // TODO: remove this block after implementation of LoopChecker2d.
103           if (isSelfIntCheck)
104           {
105             gp_XY aPrevVec;
106             Standard_Real aSumS = 0.;
107             const gp_XY& aRefPnt  = aIntPnt.Coord();
108             for (Standard_Integer i = aSegmentId1; i < aSegmentId2; ++i)
109             {
110               const BRepMesh::Segment& aSeg = aWireSegments1->Value(i);
111               gp_XY aCurVec = aSeg.EndPnt - aRefPnt;
112
113               if (aCurVec.SquareModulus() < gp::Resolution())
114                 continue;
115
116               if (aPrevVec.SquareModulus() > gp::Resolution())
117                 aSumS += aPrevVec ^ aCurVec;
118
119               aPrevVec = aCurVec;
120             }
121
122             if (Abs(aSumS / 2.) < MIN_LOOP_S)
123               continue;
124           }
125
126           Standard_Mutex::Sentry aSentry(myMutex);
127           *myStatus = BRepMesh_SelfIntersectingWire;
128
129           return;
130         }
131       }
132     }
133   }
134 }