0024032: An exception raised during projection of the curve on the surface
[occt.git] / src / ProjLib / ProjLib_Torus.cxx
1 // Created on: 1993-08-24
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-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
23 #include <ProjLib_Torus.ixx>
24
25 #include <Precision.hxx>
26 #include <gp.hxx>
27 #include <gp_Vec.hxx>
28 #include <gp_Vec2d.hxx>
29 #include <gp_Dir2d.hxx>
30
31 #include <Precision.hxx>
32
33 //=======================================================================
34 //function : ProjLib_Torus
35 //purpose  : 
36 //=======================================================================
37
38 ProjLib_Torus::ProjLib_Torus()
39 {
40 }
41
42
43 //=======================================================================
44 //function : ProjLib_Torus
45 //purpose  : 
46 //=======================================================================
47
48 ProjLib_Torus::ProjLib_Torus(const gp_Torus& To)
49 {
50   Init(To);
51 }
52
53
54 //=======================================================================
55 //function : ProjLib_Torus
56 //purpose  : 
57 //=======================================================================
58
59 ProjLib_Torus::ProjLib_Torus(const gp_Torus& To, const gp_Circ& C)
60 {
61   Init(To);
62   Project(C);
63 }
64
65
66 //=======================================================================
67 //function : Init
68 //purpose  : 
69 //=======================================================================
70
71 void  ProjLib_Torus::Init(const gp_Torus& To)
72 {
73   myType  = GeomAbs_OtherCurve;
74   myTorus = To;
75   myIsPeriodic = Standard_False;
76   isDone = Standard_False;
77 }
78
79
80 //=======================================================================
81 //function : EvalPnt2d / EvalDir2d
82 //purpose  : returns the Projected Pnt / Dir in the parametrization range
83 //           of myPlane.
84 //           P is a point on a torus with the same Position as To,
85 //           but with a major an minor radius equal to 1. 
86 //           ( in order to avoid to divide by Radius)
87 //                / X = (1+cosV)*cosU        U = Atan(Y/X)
88 //            P = | Y = (1+cosV)*sinU   ==>
89 //                \ Z = sinV                 V = ASin( Z)
90 //=======================================================================
91
92 static gp_Pnt2d EvalPnt2d( const gp_Vec& Ve, const gp_Torus& To)
93 {
94   Standard_Real X = Ve.Dot(gp_Vec(To.Position().XDirection()));
95   Standard_Real Y = Ve.Dot(gp_Vec(To.Position().YDirection()));
96   Standard_Real U,V;
97
98   if ( Abs(X) > Precision::PConfusion() ||
99        Abs(Y) > Precision::PConfusion() ) {
100     U = ATan2(Y,X);
101   }
102   else {
103     U = 0.;
104   }
105
106   V = 0.;
107
108   return gp_Pnt2d( U, V);
109 }
110
111
112 //=======================================================================
113 //function : Project
114 //purpose  : 
115 //=======================================================================
116
117 void  ProjLib_Torus::Project(const gp_Circ& C)
118 {
119   myType = GeomAbs_Line;
120
121   gp_Vec Xc( C.Position().XDirection());
122   gp_Vec Yc( C.Position().YDirection());
123   gp_Vec Xt( myTorus.Position().XDirection());
124   gp_Vec Yt( myTorus.Position().YDirection());
125   gp_Vec Zt( myTorus.Position().Direction());
126   gp_Vec OC( myTorus.Location(), C.Location());
127   
128 //  if (OC.Magnitude() < Precision::Confusion()      ||
129 //      OC.IsParallel(myTorus.Position().Direction(),
130 //                  Precision::Angular())) {
131
132   if (OC.Magnitude() < Precision::Confusion()      ||
133       C.Position().Direction().IsParallel(myTorus.Position().Direction(),
134                                           Precision::Angular())) {
135     // Iso V
136     gp_Pnt2d P1 = EvalPnt2d( Xc, myTorus);  // evaluate U1
137     gp_Pnt2d P2 = EvalPnt2d( Yc, myTorus);  // evaluate U2
138     Standard_Real Z = OC.Dot(myTorus.Position().Direction());
139     Z /= myTorus.MinorRadius();
140     
141     Standard_Real V;
142
143     if ( Z > 1.) {         
144       V = M_PI/2.;          // protection stupide 
145     }                     // contre les erreurs de calcul
146     else if ( Z < -1.) {  // il arrive que Z soit legerement 
147       V = -M_PI/2;          // superieur a 1.
148     }
149     else {
150       V = ASin(Z);
151     }
152
153     if (C.Radius() < myTorus.MajorRadius()) {
154       V = M_PI - V;
155     }
156     else if ( V < 0.) {
157       V += 2*M_PI;
158     }
159     P1.SetY(V);
160     P2.SetY(V);
161     gp_Vec2d V2d ( P1, P2);
162     // Normalement Abs( P1.X() - P2.X()) = PI/2
163     // Si != PI/2, on a traverse la periode => On reverse la Direction
164     if ( Abs( P1.X() - P2.X()) > M_PI) V2d.Reverse();
165     
166     gp_Dir2d D2( V2d);
167     if ( P1.X() < 0) 
168       P1.SetX( 2*M_PI + P1.X());
169     myLin = gp_Lin2d( P1, D2);
170   }
171   else {
172     // Iso U  -> U = angle( Xt, OC)
173     Standard_Real U = Xt.AngleWithRef( OC, Xt^Yt);
174     if ( U < 0.) 
175       U += 2*M_PI;
176     
177     // Origine de la droite
178     Standard_Real V1 = OC.AngleWithRef(Xc, OC^Zt);
179     if ( V1 < 0.)
180       V1 += 2*M_PI;
181
182     gp_Pnt2d P1( U, V1);
183     
184     // Direction de la droite
185     gp_Dir2d D2 = gp::DY2d();
186     if ( ((OC^Zt)*(Xc^Yc)) < 0.) {
187       D2.Reverse();
188     }
189     
190     myLin = gp_Lin2d( P1, D2);
191   }
192   isDone = Standard_True;
193 }
194
195 void  ProjLib_Torus::Project(const gp_Lin& L)
196 {
197  ProjLib_Projector::Project(L);
198 }
199
200 void  ProjLib_Torus::Project(const gp_Elips& E)
201 {
202  ProjLib_Projector::Project(E);
203 }
204
205 void  ProjLib_Torus::Project(const gp_Parab& P)
206 {
207  ProjLib_Projector::Project(P);
208 }
209
210 void  ProjLib_Torus::Project(const gp_Hypr& H)
211 {
212  ProjLib_Projector::Project(H);
213 }
214