0031662: Modeling Algorithms - Incomplete result of section operation
[occt.git] / src / TopTrans / TopTrans_CurveTransition.cxx
1 // Created on: 1992-01-23
2 // Created by: Didier PIFFAULT
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
18 #include <gp_Dir.hxx>
19 #include <TopAbs.hxx>
20 #include <TopTrans_CurveTransition.hxx>
21
22 #define GREATER 1
23 #define SAME 0
24 #define LOWER -1
25
26 //=======================================================================
27 //function : TopTrans_CurveTransition
28 //purpose  : Empty Constructor.
29 //=======================================================================
30
31 TopTrans_CurveTransition::TopTrans_CurveTransition ()
32 {
33 }
34
35 //=======================================================================
36 //function : Reset
37 //purpose  : Initializer for a complex curve transition with the elements
38 //           of the intersecting curve.
39 //=======================================================================
40
41 void TopTrans_CurveTransition::Reset (const gp_Dir& Tgt,
42                                       const gp_Dir& Norm,
43                                       const Standard_Real Curv)
44 {
45        myTgt=Tgt; myNorm=Norm; myCurv=Curv; Init=Standard_True;
46 }
47
48 //=======================================================================
49 //function : Reset
50 //purpose  : Initializer for a complex curve transition with the elements
51 //           of the intersecting straight line.
52 //=======================================================================
53
54 void TopTrans_CurveTransition::Reset (const gp_Dir& Tgt)
55 {
56        myTgt=Tgt; myCurv=0.; Init=Standard_True;
57 }
58
59 //=======================================================================
60 //function : Compare
61 //purpose  : Compare the elements of  an interference  on  an intersected
62 //           curve with the interference stored in the complex Transition.
63 //=======================================================================
64
65 void TopTrans_CurveTransition::Compare (const Standard_Real Tole,
66                                         const gp_Dir& T,
67                                         const gp_Dir& N,
68                                         const Standard_Real C,
69                                         const TopAbs_Orientation St,
70                                         const TopAbs_Orientation Or)
71 {
72   // S is the transition, how the curve cross the boundary
73   // O is the orientation, how the intersection is set on the boundary
74   TopAbs_Orientation S = St;
75   TopAbs_Orientation O = Or;
76
77   // adjustment for INTERNAL transition
78   if (S == TopAbs_INTERNAL) {
79     if (T * myTgt < 0)
80       S = TopAbs::Reverse(O);
81     else
82       S = O;
83   }
84
85   // It is the first comparaison for this complex transition 
86   if (Init) {
87     Init=Standard_False;
88     TgtFirst =T;
89     NormFirst=N;
90     CurvFirst=C;
91     TranFirst=S;
92     TgtLast  =T;
93     NormLast =N;
94     CurvLast =C;
95     TranLast =S;
96     switch (O) {
97       // Interference en fin d'arete il faut inverser la tangente 
98     case TopAbs_REVERSED :
99       TgtFirst.Reverse();
100       TgtLast.Reverse();
101       break;
102     case TopAbs_INTERNAL :
103       // Interference en milieu d'arete il faut inverser en fonction de la
104       // position de la tangente de reference
105       if (myTgt*T>0) TgtFirst.Reverse();
106       else           TgtLast.Reverse();
107       break;
108     case TopAbs_FORWARD :
109     case TopAbs_EXTERNAL :
110       break;
111     }
112   }
113
114   // Compare with the existent first and last transition :
115   else {
116     Standard_Boolean FirstSet=Standard_False;
117     Standard_Real cosAngWithT=myTgt*T;
118     switch (O) {
119     case TopAbs_REVERSED :
120       cosAngWithT= -cosAngWithT;
121       break;
122     case TopAbs_INTERNAL :
123       if (cosAngWithT>0) cosAngWithT=-cosAngWithT;
124       break;
125     case TopAbs_FORWARD :
126     case TopAbs_EXTERNAL :
127       break;
128     }
129     Standard_Real cosAngWith1=myTgt*TgtFirst;
130     
131     switch (Compare(cosAngWithT, cosAngWith1, Tole)) {
132       
133     case LOWER :
134       // If the angle is greater than the first the new become the first
135       FirstSet=Standard_True;
136       TgtFirst =T;
137       switch (O) {
138       case TopAbs_REVERSED :
139         TgtFirst.Reverse();
140         break;
141       case TopAbs_INTERNAL :
142         if (myTgt*T>0) TgtFirst.Reverse();
143         break;
144       case TopAbs_FORWARD :
145       case TopAbs_EXTERNAL :
146         break;
147       }
148       NormFirst=N;
149       CurvFirst=C;
150       TranFirst=S;
151       break;
152
153     case SAME :
154       // If same angles we look at the Curvature
155       if (IsBefore(Tole, cosAngWithT, N, C, NormFirst, CurvFirst)) {
156         FirstSet=Standard_True;
157         TgtFirst =T;
158         switch (O) {
159         case TopAbs_REVERSED :
160           TgtFirst.Reverse();
161           break;
162         case TopAbs_INTERNAL :
163           if (myTgt*T>0) TgtFirst.Reverse();
164           break;
165         case TopAbs_FORWARD :
166         case TopAbs_EXTERNAL :
167           break;
168         }
169         NormFirst=N;
170         CurvFirst=C;
171         TranFirst=S;
172       }
173       break;
174   
175     case GREATER:
176       break;
177     }
178
179     if (!FirstSet || O==TopAbs_INTERNAL) {
180       // Dans les cas de tangence le premier peut etre aussi le dernier
181       if (O==TopAbs_INTERNAL) cosAngWithT=-cosAngWithT;
182       Standard_Real cosAngWith2=myTgt*TgtLast;
183       
184       switch (Compare(cosAngWithT, cosAngWith2, Tole)) {
185         
186       case GREATER:
187         // If the angle is lower than the last the new become the last
188         TgtLast  =T;
189         switch (O) {
190         case TopAbs_REVERSED :
191           TgtLast.Reverse();
192           break;
193         case TopAbs_INTERNAL :
194           if (myTgt*T<0) TgtLast.Reverse();
195           break;
196         case TopAbs_FORWARD :
197         case TopAbs_EXTERNAL :
198           break;
199         }
200         NormLast =N;
201         CurvLast =C;
202         TranLast =S;
203         break;
204         
205       case SAME:
206         // If the angle is the same we look at the curvature
207         if (IsBefore(Tole, cosAngWithT, NormLast, CurvLast, N, C)) {
208           TgtLast =T;
209           switch (O) {
210           case TopAbs_REVERSED :
211             TgtLast.Reverse();
212             break;
213           case TopAbs_INTERNAL :
214             if (myTgt*T<0) TgtLast.Reverse();
215             break;
216           case TopAbs_FORWARD :
217           case TopAbs_EXTERNAL :
218             break;
219           }
220           NormLast=N;
221           CurvLast=C;
222           TranLast=S;
223         }
224       }
225     }
226   }
227 }
228
229 //=======================================================================
230 //function : StateBefore
231 //purpose  : Give the state of the curv before the interference.
232 //=======================================================================
233
234 TopAbs_State TopTrans_CurveTransition::StateBefore () const
235 {
236   if (Init) return TopAbs_UNKNOWN;
237   switch (TranFirst)
238     {
239     case TopAbs_FORWARD  :
240     case TopAbs_EXTERNAL :
241       return TopAbs_OUT;
242     case TopAbs_REVERSED :
243     case TopAbs_INTERNAL :
244       return TopAbs_IN;
245     }
246   return TopAbs_OUT;
247 }
248
249 //=======================================================================
250 //function : StateAfter
251 //purpose  : give the state of the curve after the interference.
252 //=======================================================================
253
254 TopAbs_State TopTrans_CurveTransition::StateAfter () const
255 {
256   if (Init) return TopAbs_UNKNOWN;
257   switch (TranLast)
258     {
259     case TopAbs_FORWARD  :
260     case TopAbs_INTERNAL :
261       return TopAbs_IN;
262     case TopAbs_REVERSED :
263     case TopAbs_EXTERNAL :
264       return TopAbs_OUT;
265     }
266   return TopAbs_OUT;
267 }
268
269
270 //=======================================================================
271 //function : IsBefore
272 //purpose  : Compare the curvature of the two transition and return true
273 //           if T1 is before T2
274 //=======================================================================
275
276 Standard_Boolean TopTrans_CurveTransition::IsBefore
277   (const Standard_Real    Tole,
278    const Standard_Real    CosAngl,
279    const gp_Dir&          N1, 
280    const Standard_Real    C1,
281    const gp_Dir&          N2,
282    const Standard_Real    C2) const
283 {
284   Standard_Real TN1=myTgt*N1;
285   Standard_Real TN2=myTgt*N2;
286   Standard_Boolean OneBefore=Standard_False;
287
288   if (Abs(TN1)<=Tole || Abs(TN2)<=Tole) {
289     // Tangent : The first is the interference which have the nearest curvature
290     //           from the reference.
291     if (myCurv==0) {
292       // The reference is straight
293       // The first is the interference which have the lowest curvature.
294       if (C1<C2) OneBefore=Standard_True;
295 //  Modified by Sergey KHROMOV - Wed Dec 27 17:08:49 2000 Begin
296       if (CosAngl>0)
297         OneBefore=!OneBefore;
298 //  Modified by Sergey KHROMOV - Wed Dec 27 17:08:50 2000 End
299     }
300     else {
301       // The reference is curv 
302       // The first is the interference which have the nearest curvature
303       // in the direction
304       Standard_Real deltaC1, deltaC2;
305       if (C1==0. || myCurv==0.) {
306         deltaC1=C1-myCurv;
307       }
308       else {
309         deltaC1=(C1-myCurv)*(N1*myNorm);
310       }
311       if (C2==0. || myCurv==0.) {
312         deltaC2=C2-myCurv;
313       }
314       else {
315         deltaC2=(C2-myCurv)*(N2*myNorm);
316       }
317       if (deltaC1 < deltaC2) OneBefore=Standard_True;
318       if (CosAngl>0) OneBefore=!OneBefore;
319     }
320   }
321   else if (TN1<0) {
322     // Before the first interference we are in the curvature
323     if (TN2>0) {
324       // Before the second  interference we are out the curvature
325       // The first interference is before  /* ->)( */
326       OneBefore=Standard_True;
327     }
328     else {
329       // Before the second interference we are in the curvature
330       if (C1>C2) {
331         // We choice the greater curvature
332         // The first interference is before   /* ->)) */
333         OneBefore=Standard_True;
334       }
335     }
336   }
337   else if (TN1>0) {
338     // Before the first interference we are out the curvature
339     if (TN2>0) {
340       // Before the second interference we are out the curvature /* ->(( */
341       if (C1<C2) {
342         // We choice the lower curvature
343         // The first interference is before 
344         OneBefore=Standard_True;
345       }
346     }
347   }
348   return OneBefore;
349 }
350
351
352 //=======================================================================
353 //function : Compare
354 //purpose  : Compare two angles
355 //=======================================================================
356
357 Standard_Integer TopTrans_CurveTransition::Compare(const Standard_Real Ang1, 
358                                           const Standard_Real Ang2,
359                                           const Standard_Real Tole) const
360 {
361   Standard_Integer res=SAME;
362   if (Ang1 - Ang2 > Tole) res=GREATER;
363   else if (Ang2 - Ang1 > Tole) res=LOWER;
364
365   return res;
366 }