1 // Created on: 1993-03-04
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <Contap_ContAna.hxx>
20 #include <gp_Cone.hxx>
21 #include <gp_Cylinder.hxx>
25 #include <gp_Sphere.hxx>
27 #include <Standard_DomainError.hxx>
28 #include <Standard_OutOfRange.hxx>
29 #include <StdFail_NotDone.hxx>
31 static const Standard_Real Tolpetit = 1.e-8;
33 Contap_ContAna::Contap_ContAna (): done(Standard_False) {}
35 void Contap_ContAna::Perform (const gp_Sphere& S,
38 done = Standard_False;
39 typL = GeomAbs_Circle;
42 if (Abs(D.Dot(S.XAxis().Direction())) < 0.9999999999999) {
43 dir2 = D.Crossed(S.XAxis().Direction());
46 dir2 = D.Crossed(S.YAxis().Direction());
53 void Contap_ContAna::Perform (const gp_Sphere& S,
55 const Standard_Real Angle)
57 done = Standard_False;
58 typL = GeomAbs_Circle;
61 if (Abs(D.Dot(S.XAxis().Direction())) < 0.9999999999999) {
62 dir2 = D.Crossed(S.XAxis().Direction());
65 dir2 = D.Crossed(S.YAxis().Direction());
67 Standard_Real alpha = (S.Direct() ? Angle : -Angle);
68 pt1.SetXYZ(S.Location().XYZ() - S.Radius()*sin(alpha)*D.XYZ()) ;
69 prm = S.Radius()*cos(alpha);
74 void Contap_ContAna::Perform (const gp_Sphere& S,
77 done = Standard_False;
79 Standard_Real radius = S.Radius();
80 Standard_Real dist = Eye.Distance(S.Location());
85 prm = radius*sqrt(1.-radius*radius/(dist*dist));
90 gp_XYZ locxyz(S.Location().XYZ());
91 dir1.SetXYZ(Eye.XYZ()-locxyz);
92 pt1.SetXYZ(locxyz + (radius*radius/dist)*dir1.XYZ());
93 if (Abs(dir1.Dot(S.XAxis().Direction())) < 0.9999999999999) {
94 dir2 = dir1.Crossed(S.XAxis().Direction());
97 dir2 = dir1.Crossed(S.YAxis().Direction());
100 typL = GeomAbs_Circle;
103 done = Standard_True;
106 void Contap_ContAna::Perform (const gp_Cylinder& C,
109 done = Standard_False;
111 gp_XYZ normale(C.Position().Direction().XYZ());
112 normale.Cross(D.XYZ());
113 if (normale.Modulus() <= 1e-15) {
119 dir1 = C.Position().Direction();
121 pt1.SetXYZ(C.Location().XYZ() + C.Radius()*normale);
122 pt2.SetXYZ(C.Location().XYZ() - C.Radius()*normale);
126 done = Standard_True;
129 void Contap_ContAna::Perform (const gp_Cylinder& C,
131 const Standard_Real Angle)
133 done = Standard_False;
135 Standard_Real Coefcos = D.Dot(C.Position().XDirection());
136 Standard_Real Coefsin = D.Dot(C.Position().YDirection());
137 Standard_Real Coefcst = cos(M_PI*0.5 + Angle);
139 Standard_Real norm1 = Coefcos*Coefcos + Coefsin*Coefsin;
140 Standard_Real norm2 = sqrt(norm1);
142 if (Abs(Coefcst) < norm2) {
145 dir1 = dir2 = C.Position().Direction();
147 if (!C.Direct()) { // The normal is inverted.
152 // Necessary to solve Coefcos*cos(t) + Coefsin*sin(t) = Coefcst
153 // and the origins of solution are in the reference of the
154 // cylinder in (R*cost0, R*sint0,0) and (R*cost1,R*sint1,0)
155 // By setting cos(phi) = Coefcos/Sqrt(Coefcos**2 + Coefsin**2) and
156 // sin(phi) = Coefsin/Sqrt(Coefcos**2 + Coefsin**2)
157 // and by using trigonometric relations the values of cosinus
158 // and sinus to the solutions are obtained.
160 prm = Sqrt(norm1 - Coefcst*Coefcst);
161 Standard_Real cost0,sint0,cost1,sint1;
163 cost0 = (Coefcos*Coefcst - Coefsin*prm)/norm1;
164 cost1 = (Coefcos*Coefcst + Coefsin*prm)/norm1;
166 sint0 = ( Coefcos*prm + Coefsin*Coefcst)/norm1;
167 sint1 = (-Coefcos*prm + Coefsin*Coefcst)/norm1;
169 gp_XYZ Xdir(C.Position().XDirection().XYZ());
170 gp_XYZ Ydir(C.Position().YDirection().XYZ());
173 dirxyz.SetLinearForm(cost0,Xdir,sint0,Ydir);
174 dirxyz.Multiply(C.Radius());
175 pt1.SetXYZ(C.Location().XYZ().Added(dirxyz));
177 dirxyz.SetLinearForm(cost1,Xdir,sint1,Ydir);
178 dirxyz.Multiply(C.Radius());
179 pt2.SetXYZ(C.Location().XYZ().Added(dirxyz));
185 done = Standard_True;
188 void Contap_ContAna::Perform (const gp_Cylinder& C,
191 done = Standard_False;
193 Standard_Real radius = C.Radius();
194 gp_Lin theaxis(C.Axis());
195 Standard_Real dist = theaxis.Distance(Eye);
196 if (dist <= radius) {
201 prm = radius*sqrt(1.-radius*radius/(dist*dist));
202 dir1 = C.Axis().Direction();
204 gp_XYZ axeye(theaxis.Normal(Eye).Direction().XYZ()); // orientate the axis to the outside
205 gp_XYZ normale((theaxis.Direction().Crossed(axeye)).XYZ());
206 // normale.Normalize();
207 pt1.SetXYZ(C.Location().XYZ() + (radius*radius/dist)*axeye);
208 pt2.SetXYZ(pt1.XYZ() - prm*normale);
209 pt1.SetXYZ(pt1.XYZ() + prm*normale);
212 done = Standard_True;
215 void Contap_ContAna::Perform (const gp_Cone& C,
218 done = Standard_False;
220 Standard_Real Tgtalpha = Tan(C.SemiAngle());
222 Standard_Real Coefcos = D.Dot(C.Position().XDirection());
223 Standard_Real Coefsin = D.Dot(C.Position().YDirection());
224 Standard_Real Coefcst = D.Dot(C.Axis().Direction())*Tgtalpha;
226 Standard_Real norm1 = Coefcos*Coefcos + Coefsin*Coefsin;
227 Standard_Real norm2 = Sqrt(norm1);
228 // if (Abs(Abs(Coefcst)-norm2) <= Tolpetit) { // tol angulaire 1.e-8
229 // typL = GeomAbs_Line;
234 // else if (Abs(Coefcst) < norm2) {
236 if (Abs(Coefcst) < norm2) {
241 // Necessary to solve Coefcos*cos(t) + Coefsin*sin(t) = Coefcst
242 // and director vectors of solutions are
243 // cos(t0) * XDirection + sin(t0) * YDirection + ZDirection/Tgtalpha
244 // By setting cos(phi) = Coefcos/Sqrt(Coefcos**2 + Coefsin**2) and
245 // sin(phi) = Coefsin/Sqrt(Coefcos**2 + Coefsin**2)
246 // and by using trigonometric relations the values of cosinus
247 // and sinus to the solutions are obtained.
249 prm = Sqrt(norm1 - Coefcst*Coefcst);
250 Standard_Real cost0,sint0,cost1,sint1;
252 cost0 = (Coefcos*Coefcst - Coefsin*prm)/norm1;
253 cost1 = (Coefcos*Coefcst + Coefsin*prm)/norm1;
255 sint0 = ( Coefcos*prm + Coefsin*Coefcst)/norm1;
256 sint1 = (-Coefcos*prm + Coefsin*Coefcst)/norm1;
258 gp_XYZ Xdir(C.Position().XDirection().XYZ());
259 gp_XYZ Ydir(C.Position().YDirection().XYZ());
260 gp_XYZ Zdir(C.Axis().Direction().XYZ());
262 dirxyz.SetLinearForm(cost0,Xdir,sint0,Ydir,1./Tgtalpha,Zdir);
264 pt1.SetXYZ(pt1.XYZ()+dirxyz);
265 dirxyz.SetLinearForm(cost1,Xdir,sint1,Ydir,1./Tgtalpha,Zdir);
267 pt2.SetXYZ(pt2.XYZ()+dirxyz);
272 done = Standard_True;
275 void Contap_ContAna::Perform (const gp_Cone& C,
277 const Standard_Real Angle)
279 done = Standard_False;
282 Standard_Real Ang = C.SemiAngle();
283 Standard_Real Cosa = cos(Ang);
284 Standard_Real Sina = sin(Ang);
286 Standard_Real Coefcos = D.Dot(C.Position().XDirection());
287 Standard_Real Coefsin = D.Dot(C.Position().YDirection());
289 Standard_Real Coefcst1 = cos(M_PI*0.5 + Angle);
291 Standard_Real norm1 = Coefcos*Coefcos + Coefsin*Coefsin;
292 Standard_Real norm2 = Sqrt(norm1);
294 Standard_Real Coefnz = D.Dot(C.Axis().Direction())*Sina;
295 Standard_Real Coefcst = (Coefcst1 + Coefnz)/Cosa;
297 if (Abs(Coefcst) < norm2) {
303 // It is requiredto solve Coefcos*cos(t) + Coefsin*sin(t) = Coefcst
304 // and the director vectors of solutions are
305 // cos(t0) * XDirection + sin(t0) * YDirection + ZDirection/Tgtalpha
306 // By setting cos(phi) = Coefcos/Sqrt(Coefcos**2 + Coefsin**2) and
307 // sin(phi) = Coefsin/Sqrt(Coefcos**2 + Coefsin**2)
308 // and by using trigonometric relations the values of cosinus
309 // and sinus to the solutions are obtained.
311 prm = Sqrt(norm1 - Coefcst*Coefcst);
312 Standard_Real cost0,sint0,cost1,sint1;
314 cost0 = (Coefcos*Coefcst - Coefsin*prm)/norm1;
315 cost1 = (Coefcos*Coefcst + Coefsin*prm)/norm1;
317 sint0 = ( Coefcos*prm + Coefsin*Coefcst)/norm1;
318 sint1 = (-Coefcos*prm + Coefsin*Coefcst)/norm1;
320 gp_XYZ Xdir(C.Position().XDirection().XYZ());
321 gp_XYZ Ydir(C.Position().YDirection().XYZ());
322 gp_XYZ Zdir(C.Axis().Direction().XYZ());
327 dirxyz.SetLinearForm(cost0,Xdir,sint0,Ydir,Cosa/Sina,Zdir);
329 pt1.SetXYZ(pt1.XYZ()+dirxyz);
330 dirxyz.SetLinearForm(cost1,Xdir,sint1,Ydir,Cosa/Sina,Zdir);
332 pt2.SetXYZ(pt2.XYZ()+dirxyz);
335 Coefcst = (Coefcst1 - Coefnz)/Cosa;
337 if (Abs(Coefcst) < norm2) {
343 prm = Sqrt(norm1 - Coefcst*Coefcst);
344 Standard_Real cost0,sint0,cost1,sint1;
346 cost0 = (Coefcos*Coefcst - Coefsin*prm)/norm1;
347 cost1 = (Coefcos*Coefcst + Coefsin*prm)/norm1;
349 sint0 = ( Coefcos*prm + Coefsin*Coefcst)/norm1;
350 sint1 = (-Coefcos*prm + Coefsin*Coefcst)/norm1;
352 gp_XYZ Xdir(C.Position().XDirection().XYZ());
353 gp_XYZ Ydir(C.Position().YDirection().XYZ());
354 gp_XYZ Zdir(C.Axis().Direction().XYZ());
359 dirxyz.SetLinearForm(cost0,Xdir,sint0,Ydir,-Cosa/Sina,Zdir);
361 pt3.SetXYZ(pt3.XYZ()+dirxyz);
362 dirxyz.SetLinearForm(cost1,Xdir,sint1,Ydir,-Cosa/Sina,Zdir);
364 pt4.SetXYZ(pt4.XYZ()+dirxyz);
373 done = Standard_True;
376 void Contap_ContAna::Perform (const gp_Cone& C,
379 done = Standard_False;
381 Standard_Real Tgtalpha = Tan(C.SemiAngle());
383 gp_XYZ apexeye(Eye.XYZ());
384 apexeye.Subtract(C.Apex().XYZ());
386 Standard_Real Coefcos = apexeye.Dot(C.Position().XDirection().XYZ());
387 Standard_Real Coefsin = apexeye.Dot(C.Position().YDirection().XYZ());
388 Standard_Real Coefcst = apexeye.Dot(C.Axis().Direction().XYZ())*Tgtalpha;
390 Standard_Real norm1 = Coefcos*Coefcos + Coefsin*Coefsin;
391 Standard_Real norm2 = Sqrt(Coefcos*Coefcos + Coefsin*Coefsin);
392 // if (Abs(Abs(Coefcst)-norm2) <= Tolpetit) { // tol angulaire 1.e-8
393 // typL = GeomAbs_Line;
396 // dir1.SetXYZ(apexeye);
398 // else if (Abs(Coefcst) < norm2) {
400 if (Abs(Coefcst) < norm2) {
405 // It is required to solve Coefcos*cos(t) + Coefsin*sin(t) = Coefcst
406 // and the director vectors of solutions are
407 // cos(t0) * XDirection + sin(t0) * YDirection + ZDirection/Tgtalpha
408 // By setting cos(phi) = Coefcos/Sqrt(Coefcos**2 + Coefsin**2) and
409 // sin(phi) = Coefsin/Sqrt(Coefcos**2 + Coefsin**2)
410 // and by using trigonometric relations the values of cosinus
411 // and sinus to the solutions are obtained.
413 prm = Sqrt(norm1 - Coefcst*Coefcst);
414 Standard_Real cost0,sint0,cost1,sint1;
416 cost0 = (Coefcos*Coefcst - Coefsin*prm)/norm1;
417 cost1 = (Coefcos*Coefcst + Coefsin*prm)/norm1;
419 sint0 = ( Coefcos*prm + Coefsin*Coefcst)/norm1;
420 sint1 = (-Coefcos*prm + Coefsin*Coefcst)/norm1;
422 gp_XYZ Xdir(C.Position().XDirection().XYZ());
423 gp_XYZ Ydir(C.Position().YDirection().XYZ());
424 gp_XYZ Zdir(C.Axis().Direction().XYZ());
426 dirxyz.SetLinearForm(cost0,Xdir,sint0,Ydir,1./Tgtalpha,Zdir);
428 pt1.SetXYZ(pt1.XYZ()+dirxyz);
429 dirxyz.SetLinearForm(cost1,Xdir,sint1,Ydir,1./Tgtalpha,Zdir);
431 pt2.SetXYZ(pt2.XYZ()+dirxyz);
436 done = Standard_True;
439 gp_Lin Contap_ContAna::Line (const Standard_Integer Index) const
441 if (!done) {throw StdFail_NotDone();}
442 if (typL != GeomAbs_Line || nbSol == 0) {throw Standard_DomainError();}
443 if (Index <=0 || Index > nbSol) {throw Standard_OutOfRange();}
446 return gp_Lin(pt1,dir1);
448 return gp_Lin(pt2,dir2);
450 return gp_Lin(pt3,dir3);
452 return gp_Lin(pt4,dir4);
454 throw Standard_OutOfRange("Program error in Contap_ContAna");