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