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