0023839: Projection algorithm produces wrong results for set of data
[occt.git] / src / ProjLib / ProjLib_Cone.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
24 #include <ProjLib_Cone.ixx>
25
26 #include <Precision.hxx>
27 #include <gp.hxx>
28 #include <gp_Vec.hxx>
29 #include <gp_Trsf.hxx>
30 #include <gp_Vec2d.hxx>
31 #include <ElSLib.hxx>
32
33 //=======================================================================
34 //function : ProjLib_Cone
35 //purpose  : 
36 //=======================================================================
37
38 ProjLib_Cone::ProjLib_Cone()
39 {
40 }
41
42
43 //=======================================================================
44 //function : ProjLib_Cone
45 //purpose  : 
46 //=======================================================================
47
48 ProjLib_Cone::ProjLib_Cone(const gp_Cone& Co)
49 {
50   Init(Co);
51 }
52
53
54 //=======================================================================
55 //function : ProjLib_Cone
56 //purpose  : 
57 //=======================================================================
58
59 ProjLib_Cone::ProjLib_Cone(const gp_Cone& Co, const gp_Lin& L)
60 {
61   Init(Co);
62   Project(L);
63 }
64
65
66 //=======================================================================
67 //function : ProjLib_Cone
68 //purpose  : 
69 //=======================================================================
70
71 ProjLib_Cone::ProjLib_Cone(const gp_Cone& Co, const gp_Circ& C)
72 {
73   Init(Co);
74   Project(C);
75 }
76
77
78 //=======================================================================
79 //function : Init
80 //purpose  : 
81 //=======================================================================
82
83 void  ProjLib_Cone::Init(const gp_Cone& Co)
84 {
85   myType = GeomAbs_OtherCurve;
86   myCone = Co;
87   myIsPeriodic = Standard_False;
88   isDone = Standard_False;
89 }
90
91
92 //=======================================================================
93 //function : EvalPnt2d / EvalDir2d
94 //purpose  : returns the Projected Pnt / Dir in the parametrization range
95 //           of myPlane.
96 //=======================================================================
97
98 #ifdef DEB
99 static gp_Pnt2d EvalPnt2d( const gp_Pnt& P, const gp_Cone& C)
100 {
101   gp_Vec OP( C.Location(),P);
102   Standard_Real X = OP.Dot(gp_Vec(C.Position().XDirection()));
103   Standard_Real Y = OP.Dot(gp_Vec(C.Position().YDirection()));
104   Standard_Real Z = OP.Dot(gp_Vec(C.Position().Direction()));
105   Standard_Real U,V;
106
107   if ( Abs(X) > Precision::PConfusion() ||
108        Abs(Y) > Precision::PConfusion() ) {
109     U = ATan2(Y,X);
110   }
111   else {
112     U = 0.;
113   }
114
115   V = Z / Cos(C.SemiAngle());
116
117   return gp_Pnt2d( U, Z);
118 }
119 #endif
120
121 //=======================================================================
122 //function : Project
123 //purpose  : 
124 //=======================================================================
125
126 void  ProjLib_Cone::Project(const gp_Lin& L)
127 {
128
129   Standard_Real U,V;
130   
131   // Compute V
132   V = gp_Vec(myCone.Location(),L.Location())
133     .Dot(gp_Vec(myCone.Position().Direction()));
134   V /= Cos( myCone.SemiAngle());
135
136   // Compute U
137   gp_Ax3 CPos  = myCone.Position();
138   gp_Dir ZCone = CPos.XDirection() ^ CPos.YDirection();
139   
140   gp_Ax3 RightHanded(CPos.Location(), ZCone, CPos.XDirection());
141   gp_Trsf T;
142   T.SetTransformation(RightHanded);
143
144   gp_Dir D = L.Position().Direction();
145   D.Transform(T);
146
147   if ( D.Z() < 0.) D.Reverse();
148   D.SetCoord(3, 0.);
149   U = gp::DX().AngleWithRef( D, gp::DZ());
150
151   Standard_Integer a1 = 
152     (ZCone.IsEqual(CPos.Direction(), Precision::Angular())) ? 1 : -1;
153   Standard_Integer a2 = 
154     (myCone.SemiAngle() > 0) ? 1 : -1;
155   if ( ( a1 * a2) == -1) U -= M_PI;
156
157   if ( U < 0.) U += 2.*M_PI;
158
159   gp_Pnt P;
160   gp_Vec Vu, Vv;
161
162   ElSLib::ConeD1(U, V, CPos, myCone.RefRadius(), myCone.SemiAngle(),
163                  P, Vu, Vv);
164
165   if(Vv.IsParallel(gp_Vec(L.Position().Direction()), Precision::Angular())) {
166
167     myType = GeomAbs_Line;
168
169     gp_Pnt2d P2d(U,V);
170   
171     Standard_Real Signe = L.Direction().Dot(myCone.Position().Direction());
172     Signe = (Signe > 0.) ? 1. : -1.;
173     gp_Dir2d D2d(0., Signe);
174   
175     myLin = gp_Lin2d( P2d, D2d);
176
177     isDone = Standard_True;
178   }
179     
180 }
181
182
183 //=======================================================================
184 //function : Project
185 //purpose  : 
186 //=======================================================================
187
188 void  ProjLib_Cone::Project(const gp_Circ& C)
189 {
190   myType = GeomAbs_Line;
191
192   gp_Ax3 ConePos = myCone.Position();
193   gp_Ax3 CircPos = C.Position();
194
195   gp_Dir ZCone = ConePos.XDirection().Crossed(ConePos.YDirection());
196   gp_Dir ZCir =  CircPos.XDirection().Crossed(CircPos.YDirection());
197
198   Standard_Real U, V;
199   Standard_Real x = ConePos.XDirection().Dot(CircPos.XDirection());
200   Standard_Real y = ConePos.YDirection().Dot(CircPos.XDirection());
201   Standard_Real z 
202     = gp_Vec(myCone.Location(),C.Location()).Dot(ConePos.Direction());
203   
204   // pour trouver le point U V, on reprend le code de ElSLib
205   // sans appliquer la Trsf au point ( aller retour inutile).
206   if ( x == 0.0 && y == 0.0 ) {
207     U = 0.;
208   }
209   else if ( -myCone.RefRadius() > z * Tan(myCone.SemiAngle())) {
210     U = ATan2(-y, -x);
211   }
212   else {
213     U = ATan2( y, x);
214   }
215   if ( U < 0.) U += 2*M_PI;
216
217   V = z / Cos(myCone.SemiAngle());
218
219   gp_Pnt2d P2d1 (U, V);
220   gp_Dir2d D2d;
221   if ( ZCone.Dot(ZCir) > 0.) 
222     D2d.SetCoord(1., 0.);
223   else
224     D2d.SetCoord(-1., 0.);
225
226   myLin = gp_Lin2d(P2d1, D2d);
227   isDone = Standard_True;
228 }
229
230 void  ProjLib_Cone::Project(const gp_Elips& E)
231 {
232   ProjLib_Projector::Project(E);
233 }
234
235 void  ProjLib_Cone::Project(const gp_Parab& P)
236 {
237  ProjLib_Projector::Project(P);
238 }
239
240 void  ProjLib_Cone::Project(const gp_Hypr& H)
241 {
242  ProjLib_Projector::Project(H);
243 }
244