ea6ddbc04522b3bd2ef26dd09e92bfb14e092d55
[occt.git] / src / IntSurf / IntSurf_Quadric.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <IntSurf_Quadric.ixx>
16 #include <StdFail_NotDone.hxx>
17
18 #include <ElCLib.hxx>
19 #include <ElSLib.hxx>
20 #include <gp.hxx>
21
22
23
24 // ============================================================
25 IntSurf_Quadric::IntSurf_Quadric ():typ(GeomAbs_OtherSurface),
26    prm1(0.), prm2(0.), prm3(0.), prm4(0.)
27 {}
28 // ============================================================
29 IntSurf_Quadric::IntSurf_Quadric (const gp_Pln& P):
30       ax3(P.Position()),typ(GeomAbs_Plane)
31 {
32   ax3direc = ax3.Direct();
33   P.Coefficients(prm1,prm2,prm3,prm4); 
34 }
35 // ============================================================
36 IntSurf_Quadric::IntSurf_Quadric (const gp_Cylinder& C):
37
38        ax3(C.Position()),lin(ax3.Axis()),typ(GeomAbs_Cylinder)
39 {
40   prm2=prm3=prm4=0.0;
41   ax3direc=ax3.Direct();
42   prm1=C.Radius();
43 }
44 // ============================================================
45 IntSurf_Quadric::IntSurf_Quadric (const gp_Sphere& S):
46
47        ax3(S.Position()),lin(ax3.Axis()),typ(GeomAbs_Sphere)
48 {
49   prm2=prm3=prm4=0.0;
50   ax3direc = ax3.Direct();
51   prm1=S.Radius();
52 }
53 // ============================================================
54 IntSurf_Quadric::IntSurf_Quadric (const gp_Cone& C):
55
56        ax3(C.Position()),typ(GeomAbs_Cone)
57 {
58   ax3direc = ax3.Direct();
59   lin.SetPosition(ax3.Axis());
60   prm1 = C.RefRadius();
61   prm2 = C.SemiAngle();
62   prm3 = Cos(prm2);
63   prm4 = 0.0;
64 }
65 // ============================================================
66 void IntSurf_Quadric::SetValue (const gp_Pln& P)
67 {
68   typ = GeomAbs_Plane;
69   ax3 = P.Position();
70   ax3direc = ax3.Direct();
71   P.Coefficients(prm1,prm2,prm3,prm4); 
72 }
73 // ============================================================
74 void IntSurf_Quadric::SetValue (const gp_Cylinder& C)
75 {
76   typ = GeomAbs_Cylinder;
77   ax3 = C.Position();
78   ax3direc = ax3.Direct();
79   lin.SetPosition(ax3.Axis());
80   prm1 = C.Radius();
81   prm2=prm3=prm4=0.0;
82 }
83 // ============================================================
84 void IntSurf_Quadric::SetValue (const gp_Sphere& S)
85 {
86   typ = GeomAbs_Sphere;
87   ax3 = S.Position();
88   ax3direc = ax3.Direct();
89   lin.SetPosition(ax3.Axis());
90   prm1 = S.Radius();
91   prm2=prm3=prm4=0.0;
92 }
93 // ============================================================
94 void IntSurf_Quadric::SetValue (const gp_Cone& C)
95 {
96   typ = GeomAbs_Cone;
97   ax3 = C.Position();
98   ax3direc = ax3.Direct();
99   lin.SetPosition(ax3.Axis());
100   prm1 = C.RefRadius();
101   prm2 = C.SemiAngle();
102   prm3 = Cos(prm2);
103   prm4 = 0.0;
104 }
105 // ============================================================
106 Standard_Real IntSurf_Quadric::Distance (const gp_Pnt& P) const {
107   switch (typ) {
108   case GeomAbs_Plane:   // plan
109     return prm1*P.X() + prm2*P.Y() + prm3*P.Z() + prm4;
110   case GeomAbs_Cylinder:   // cylindre
111     return (lin.Distance(P) - prm1);
112   case GeomAbs_Sphere:   // sphere
113     return (lin.Location().Distance(P) - prm1);
114   case GeomAbs_Cone:   // cone
115     {
116       Standard_Real dist = lin.Distance(P);
117       Standard_Real U,V;
118       ElSLib::ConeParameters(ax3,prm1,prm2,P,U,V);
119       gp_Pnt Pp = ElSLib::ConeValue(U,V,ax3,prm1,prm2);
120       Standard_Real distp = lin.Distance(Pp);
121       dist = (dist-distp)/prm3;
122       return(dist);
123     }
124   default:
125     {
126     }
127     break;
128   }
129   return(0.0);
130 }
131 // ============================================================
132 gp_Vec IntSurf_Quadric::Gradient (const gp_Pnt& P) const {
133   gp_Vec grad;
134   switch (typ) {
135   case GeomAbs_Plane:   // plan
136     grad.SetCoord(prm1,prm2,prm3);
137     break;
138   case GeomAbs_Cylinder:   // cylindre
139     {
140       gp_XYZ PP(lin.Location().XYZ());
141       PP.Add(ElCLib::Parameter(lin,P)*lin.Direction().XYZ());
142       grad.SetXYZ(P.XYZ()-PP);
143       Standard_Real N = grad.Magnitude();
144       if(N>1e-14) { grad.Divide(N); } 
145       else { grad.SetCoord(0.0,0.0,0.0); } 
146     }
147     break;
148   case GeomAbs_Sphere:   // sphere
149     {
150       gp_XYZ PP(P.XYZ());
151       grad.SetXYZ((PP-lin.Location().XYZ()));
152       Standard_Real N = grad.Magnitude();
153       if(N>1e-14) { grad.Divide(N); } 
154       else { grad.SetCoord(0.0,0.0,0.0); }
155     }
156     break;
157   case GeomAbs_Cone:   // cone
158     {
159       Standard_Real U,V;
160       ElSLib::ConeParameters(ax3,prm1,prm2,P,U,V);
161       gp_Pnt Pp = ElSLib::ConeValue(U,V,ax3,prm1,prm2);
162       gp_Vec D1u,D1v;
163       ElSLib::ConeD1(U,V,ax3,prm1,prm2,Pp,D1u,D1v);
164       grad=D1u.Crossed(D1v);
165       if(ax3direc==Standard_False) { 
166         grad.Reverse();
167       }
168       grad.Normalize();
169     }
170     break;
171   default:
172     {}
173     break;
174   }
175   return grad;
176 }
177 // ============================================================
178 void IntSurf_Quadric::ValAndGrad (const gp_Pnt& P,
179                                    Standard_Real& Dist,
180                                    gp_Vec& Grad) const
181 {
182
183   switch (typ) {
184   case GeomAbs_Plane:   
185     {
186       Dist = prm1*P.X() + prm2*P.Y() + prm3*P.Z() + prm4;
187       Grad.SetCoord(prm1,prm2,prm3);
188     }
189     break;
190   case GeomAbs_Cylinder:   
191     {
192       Dist = lin.Distance(P) - prm1;
193       gp_XYZ PP(lin.Location().XYZ());
194       PP.Add(ElCLib::Parameter(lin,P)*lin.Direction().XYZ());
195       Grad.SetXYZ((P.XYZ()-PP));
196       Standard_Real N = Grad.Magnitude();
197       if(N>1e-14) { Grad.Divide(N); } 
198       else { Grad.SetCoord(0.0,0.0,0.0); }
199     }
200     break;
201   case GeomAbs_Sphere:  
202     {
203       Dist = lin.Location().Distance(P) - prm1;
204       gp_XYZ PP(P.XYZ());
205       Grad.SetXYZ((PP-lin.Location().XYZ()));
206       Standard_Real N = Grad.Magnitude();
207       if(N>1e-14) { Grad.Divide(N); } 
208       else { Grad.SetCoord(0.0,0.0,0.0); }
209     }
210     break;
211   case GeomAbs_Cone:  
212     {
213       Standard_Real dist = lin.Distance(P);
214       Standard_Real U,V;
215       gp_Vec D1u,D1v;
216       gp_Pnt Pp;
217       ElSLib::ConeParameters(ax3,prm1,prm2,P,U,V);
218       ElSLib::ConeD1(U,V,ax3,prm1,prm2,Pp,D1u,D1v);
219       Standard_Real distp = lin.Distance(Pp);
220       dist = (dist-distp)/prm3;
221       Dist = dist;
222       Grad=D1u.Crossed(D1v);
223       if(ax3direc==Standard_False) { 
224         Grad.Reverse();
225       }
226       //-- lbr le 7 mars 96 
227       //-- Si le gardient est nul, on est sur l axe 
228       //-- et dans ce cas dist vaut 0 
229       //-- On peut donc renvoyer une valeur quelconque. 
230       if(   Grad.X() > 1e-13 
231          || Grad.Y() > 1e-13 
232          || Grad.Z() > 1e-13) { 
233         Grad.Normalize();
234       }
235     }
236     break;
237   default:
238     {}
239     break;
240   }
241 }
242 // ============================================================
243 gp_Pnt IntSurf_Quadric::Value(const Standard_Real U,
244                                const Standard_Real V) const
245 {
246   switch (typ) {
247
248   case GeomAbs_Plane:  
249     return ElSLib::PlaneValue(U,V,ax3);
250   case GeomAbs_Cylinder:
251     return ElSLib::CylinderValue(U,V,ax3,prm1);
252   case GeomAbs_Sphere:
253     return ElSLib::SphereValue(U,V,ax3,prm1);
254   case GeomAbs_Cone:  
255     return ElSLib::ConeValue(U,V,ax3,prm1,prm2);
256   default:
257     {
258       gp_Pnt p(0,0,0);
259       return(p);
260     }
261     //break;
262   }
263 // pop : pour NT
264 //  return gp_Pnt(0,0,0);
265 }
266 // ============================================================
267 void IntSurf_Quadric::D1(const Standard_Real U,
268                          const Standard_Real V,
269                          gp_Pnt& P,
270                          gp_Vec& D1U,
271                          gp_Vec& D1V) const
272 {
273   switch (typ) {
274   case GeomAbs_Plane:  
275     ElSLib::PlaneD1(U,V,ax3,P,D1U,D1V);
276     break;
277   case GeomAbs_Cylinder:
278     ElSLib::CylinderD1(U,V,ax3,prm1,P,D1U,D1V);
279     break;
280   case GeomAbs_Sphere: 
281     ElSLib::SphereD1(U,V,ax3,prm1,P,D1U,D1V);
282     break;
283   case GeomAbs_Cone:  
284     ElSLib::ConeD1(U,V,ax3,prm1,prm2,P,D1U,D1V);
285     break;
286   default:
287     {
288     }
289     break;
290   }
291 }
292 // ============================================================
293 gp_Vec IntSurf_Quadric::DN(const Standard_Real U,
294                             const Standard_Real V,
295                             const Standard_Integer Nu,
296                             const Standard_Integer Nv) const
297 {
298   switch (typ) {
299   case GeomAbs_Plane: 
300     return ElSLib::PlaneDN(U,V,ax3,Nu,Nv);
301   case GeomAbs_Cylinder:
302     return ElSLib::CylinderDN(U,V,ax3,prm1,Nu,Nv);
303   case GeomAbs_Sphere:
304     return ElSLib::SphereDN(U,V,ax3,prm1,Nu,Nv);
305   case GeomAbs_Cone:  
306     return ElSLib::ConeDN(U,V,ax3,prm1,prm2,Nu,Nv);
307   default:
308     {
309       gp_Vec v(0,0,0);
310       return(v);
311     }
312     //break;
313   }
314 // pop : pour NT
315 //  return gp_Vec(0,0,0);
316 }
317 // ============================================================
318 gp_Vec IntSurf_Quadric::Normale(const Standard_Real U,
319                                  const Standard_Real V) const
320 {
321   switch (typ) {
322   case GeomAbs_Plane:  
323     if(ax3direc) 
324       return ax3.Direction();
325     else 
326       return ax3.Direction().Reversed();
327   case GeomAbs_Cylinder:  
328     return Normale(Value(U,V));
329   case GeomAbs_Sphere:  
330     return Normale(Value(U,V));
331   case GeomAbs_Cone:   
332     {
333       gp_Pnt P;
334       gp_Vec D1u,D1v;
335       ElSLib::ConeD1(U,V,ax3,prm1,prm2,P,D1u,D1v);
336       if(D1u.Magnitude()<0.0000001) { 
337         gp_Vec Vn(0.0,0.0,0.0); 
338         return(Vn);
339       }
340       return(D1u.Crossed(D1v));
341     }
342   default:     
343     {
344       gp_Vec v(0,0,0);
345       return(v);
346     }     
347   //  break;
348   }
349 // pop : pour NT
350 //  return gp_Vec(0,0,0);
351 }
352 // ============================================================
353 gp_Vec IntSurf_Quadric::Normale (const gp_Pnt& P) const
354 {
355   switch (typ) {
356   case GeomAbs_Plane:   
357     if(ax3direc) 
358       return ax3.Direction();
359     else 
360       return ax3.Direction().Reversed();
361   case GeomAbs_Cylinder:   
362     {
363       if(ax3direc) { 
364         return lin.Normal(P).Direction();
365       }
366       else { 
367         gp_Dir D(lin.Normal(P).Direction());
368         D.Reverse();
369         return(D);
370       }
371     }
372   case GeomAbs_Sphere:   
373     {
374       if(ax3direc) { 
375         gp_Vec ax3P(ax3.Location(),P);
376         return gp_Dir(ax3P);
377       }
378       else { 
379         gp_Vec Pax3(P,ax3.Location());
380         return gp_Dir(Pax3);
381       }
382     }
383   case GeomAbs_Cone:   
384     {
385       Standard_Real U,V;
386       ElSLib::ConeParameters(ax3,prm1,prm2,P,U,V);
387       return Normale(U,V);;
388     }
389   default:      
390     {
391       gp_Vec v(0,0,0);
392       return(v);
393     } //    break;
394   }
395 }
396 // ============================================================
397 void IntSurf_Quadric::Parameters (const gp_Pnt& P,
398                                    Standard_Real& U,
399                                    Standard_Real& V) const
400 {
401   switch (typ) {
402   case GeomAbs_Plane:   
403     ElSLib::PlaneParameters(ax3,P,U,V);
404     break;
405   case GeomAbs_Cylinder: 
406     ElSLib::CylinderParameters(ax3,prm1,P,U,V);
407     break;
408   case GeomAbs_Sphere:   
409     ElSLib::SphereParameters(ax3,prm1,P,U,V);
410     break;
411   case GeomAbs_Cone: 
412     {
413       ElSLib::ConeParameters(ax3,prm1,prm2,P,U,V);
414     }
415     break;
416   default:
417     {}
418     break;
419   }
420 }
421 // ============================================================
422
423
424
425
426