9080aeafc0148bb4769e760827069640570eefdd
[occt.git] / src / TopClass / TopClass_Classifier2d.gxx
1 // File:        TopClass_Classifier2d.gxx
2 // Created:     Tue Nov 17 17:47:02 1992
3 // Author:      Remi LEQUETTE
4 //              <rle@phylox>
5
6 // Modified:    Mon May 13 15:20:43 1996
7 // Author:      Laurent BUCHARD
8 //              <lbr@sherlox>
9 //-- Reinitialisation des transitions complexes
10
11 //  Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627
12
13
14 #include <IntRes2d_IntersectionSegment.hxx>
15 #include <IntRes2d_IntersectionPoint.hxx>
16 #include <gp_Vec2d.hxx>
17
18 //=======================================================================
19 //function : TopClass_Classifier2d
20 //purpose  : 
21 //=======================================================================
22
23 TopClass_Classifier2d::TopClass_Classifier2d() :
24        myIsSet(Standard_False),
25        myFirstCompare(Standard_True),
26        myIsHeadOrEnd(Standard_False), // skv OCC12627
27        myState(TopAbs_UNKNOWN)        // skv OCC12627
28
29 {
30 }
31
32 //=======================================================================
33 //function : Reset
34 //purpose  : 
35 //=======================================================================
36
37 void TopClass_Classifier2d::Reset(const gp_Lin2d& L,  
38                                   const Standard_Real P,
39                                   const Standard_Real Tol)
40 {
41   myLin = L;
42   myParam = P;
43   myTolerance = Tol;
44   myState = TopAbs_UNKNOWN;
45   myFirstCompare = Standard_True;
46   myFirstTrans = Standard_True;
47   myClosest = 0;
48   myIsSet = Standard_True;
49 //  Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627 Begin
50   myIsHeadOrEnd = Standard_False;
51 //  Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627 End
52 }
53
54 //=======================================================================
55 //function : Compare
56 //purpose  : 
57 //=======================================================================
58
59 void TopClass_Classifier2d::Compare(const TheEdge& E,
60                                     const TopAbs_Orientation Or)
61 {
62   // intersect the edge and the segment
63   myClosest = 0;
64   myIntersector.Perform(myLin,myParam,myTolerance,E);
65   if (!myIntersector.IsDone()) return;
66   if ((myIntersector.NbPoints()   == 0)&&
67       (myIntersector.NbSegments() == 0)) return;
68
69   // find the closest point
70   Standard_Integer iPoint, iSegment, nbPoints, nbSegments;
71 #ifndef DEB
72   const IntRes2d_IntersectionPoint *PClosest = NULL;
73 #else 
74   const IntRes2d_IntersectionPoint *PClosest;
75 #endif
76   Standard_Real dMin = RealLast();
77   nbPoints = myIntersector.NbPoints();
78   for (iPoint = 1; iPoint <= nbPoints;  iPoint++)  {
79     const IntRes2d_IntersectionPoint& PInter = myIntersector.Point(iPoint);
80     // test for ON
81     if (PInter.TransitionOfFirst().PositionOnCurve() == IntRes2d_Head) {
82       myClosest = iPoint;
83       myState = TopAbs_ON;
84       return;
85     }
86     Standard_Real paramfirst = PInter.ParamOnFirst();
87     if (paramfirst <  dMin) {
88       myClosest = iPoint;
89       PClosest = &PInter;
90       dMin = paramfirst;
91     }
92   }
93
94   // for the segments we only test the first point
95   nbSegments = myIntersector.NbSegments();
96   for (iSegment = 1; iSegment <= nbSegments;  iSegment++)  {
97     const IntRes2d_IntersectionSegment& SegInter = 
98       myIntersector.Segment(iSegment);
99     const IntRes2d_IntersectionPoint& PInter = SegInter.FirstPoint();
100     if (PInter.TransitionOfFirst().PositionOnCurve() == IntRes2d_Head) {
101       myClosest = nbPoints + iSegment+  iSegment - 1;
102       myState = TopAbs_ON;
103       return;
104     }
105     Standard_Real paramfirst = PInter.ParamOnFirst();
106     if (paramfirst <  dMin) {
107       myClosest = nbPoints + iSegment+iSegment - 1;
108       PClosest = &PInter;
109       dMin = paramfirst;
110     }
111   }
112
113   // if no point was found return
114   if (myClosest == 0) return;
115
116   // if the Edge is INTERNAL or EXTERNAL, no problem
117   if (Or == TopAbs_INTERNAL) {
118     myState = TopAbs_IN;
119     return;
120   }
121   else if (Or == TopAbs_EXTERNAL) {
122     myState = TopAbs_OUT;
123     return;
124   }
125
126
127   if ( ! myFirstCompare ) {
128     Standard_Boolean b = (dMin > myParam);
129     if (b) {
130       // dMin > myParam : le point le plus proche (dMin) trouve dans CETTE
131       // intersection ligne,arete n'est pas le plus proche
132       // de TOUS les points d'intersection avec les autres aretes (myParam).
133       return;
134     }
135   }
136   
137   // process the closest point PClosest, found at dMin on line.
138   myFirstCompare = Standard_False;
139
140   if(myParam > dMin) {  //-- lbr le 13 mai 96 
141     myFirstTrans = Standard_True; 
142   } 
143   
144   myParam = dMin;
145   const IntRes2d_Transition& T2 = PClosest->TransitionOfSecond();
146 //  Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627 Begin
147 //   Standard_Boolean isHeadorEnd = (T2.PositionOnCurve() == IntRes2d_Head) ||
148 //                                  (T2.PositionOnCurve() == IntRes2d_End);
149   myIsHeadOrEnd = (T2.PositionOnCurve() == IntRes2d_Head) ||
150                   (T2.PositionOnCurve() == IntRes2d_End);
151 //  Modified by skv - Wed Jul 12 15:20:58 2006 OCC12627 End
152   
153   // transition on the segment
154 #ifndef DEB
155   TopAbs_Orientation SegTrans = TopAbs_FORWARD;
156 #else
157   TopAbs_Orientation SegTrans;
158 #endif
159   const IntRes2d_Transition& T1 = PClosest->TransitionOfFirst();
160   switch (T1.TransitionType()) {
161   case IntRes2d_In :
162     if (Or == TopAbs_REVERSED)   SegTrans = TopAbs_REVERSED;
163     else                         SegTrans = TopAbs_FORWARD;
164     break;
165   case IntRes2d_Out :
166     if (Or == TopAbs_REVERSED)   SegTrans = TopAbs_FORWARD;
167     else                         SegTrans = TopAbs_REVERSED;
168     break;
169   case IntRes2d_Touch :
170     switch (T1.Situation()) {
171     case IntRes2d_Inside :
172       if (Or == TopAbs_REVERSED) SegTrans = TopAbs_EXTERNAL;
173       else                       SegTrans = TopAbs_INTERNAL;
174       break;
175     case IntRes2d_Outside :
176       if (Or == TopAbs_REVERSED) SegTrans = TopAbs_INTERNAL;
177       else                       SegTrans = TopAbs_EXTERNAL;
178       break;
179     case IntRes2d_Unknown :      return;
180     }
181     break;
182   case IntRes2d_Undecided :      return;
183   }
184
185   // are we inside the Edge ?
186   //  const IntRes2d_Transition& T2 = PClosest->TransitionOfSecond();
187   if ( ! myIsHeadOrEnd ) {
188     // PClosest is inside the edge
189     switch (SegTrans) {
190
191     case TopAbs_FORWARD :
192     case TopAbs_EXTERNAL :
193       myState = TopAbs_OUT;
194       break;
195
196     case TopAbs_REVERSED :
197     case TopAbs_INTERNAL :
198       myState = TopAbs_IN;
199       break;
200     }
201   }
202   else {
203     // PClosest is Head or End of the edge : update the complex transition
204     gp_Dir2d Tang2d,Norm2d;
205     Standard_Real Curv;
206     myIntersector.LocalGeometry
207       (E,PClosest->ParamOnSecond(),Tang2d,Norm2d,Curv);
208     gp_Dir Tang(Tang2d.X(),Tang2d.Y(),0.);
209     gp_Dir Norm(Norm2d.X(),Norm2d.Y(),0.);
210     if (myFirstTrans) {
211       gp_Dir D(myLin.Direction().X(),myLin.Direction().Y(),0.);
212       myTrans.Reset(D);
213       myFirstTrans = Standard_False;
214     }
215     
216     TopAbs_Orientation Ort;
217     if (T2.PositionOnCurve() == IntRes2d_Head) Ort = TopAbs_FORWARD;
218     else                                       Ort = TopAbs_REVERSED;
219     myTrans.Compare(RealEpsilon(), Tang, Norm,  Curv, SegTrans, Ort);
220     myState = myTrans.StateBefore();
221   }
222 }
223
224
225
226
227
228
229
230
231
232
233