Integration of OCCT 6.5.0 from SVN
[occt.git] / src / Contap / Contap_SurfProps.gxx
1 // File:        Contap_SurfProps.gxx
2 // Created:     Fri Feb 24 15:37:28 1995
3 // Author:      Jacques GOUSSARD
4 //              <jag@topsn2>
5
6
7 #include <ElSLib.hxx>
8
9 //=======================================================================
10 //function : Normale
11 //purpose  : 
12 //=======================================================================
13
14 void Contap_SurfProps::Normale(const TheSurface& S, 
15                                const Standard_Real U, 
16                                const Standard_Real V,
17                                gp_Pnt& P,
18                                gp_Vec& Norm)
19 {
20
21   GeomAbs_SurfaceType typS = TheSurfaceTool::GetType(S);
22   switch (typS) {
23   case GeomAbs_Plane:
24     {
25       gp_Pln pl(TheSurfaceTool::Plane(S));
26       Norm = pl.Axis().Direction();
27       P = ElSLib::Value(U,V,pl);
28       if (!pl.Direct()) {
29         Norm.Reverse();
30       }
31     }
32     break;
33
34
35   case GeomAbs_Sphere:
36     {
37       gp_Sphere sp(TheSurfaceTool::Sphere(S));
38       P = ElSLib::Value(U,V,sp);
39       Norm = gp_Vec(sp.Location(),P);
40       if (sp.Direct()) {
41         Norm.Divide(sp.Radius());
42       }
43       else {
44         Norm.Divide(-sp.Radius());
45       }
46     }
47     break;
48
49   case GeomAbs_Cylinder:
50     {
51       gp_Cylinder cy(TheSurfaceTool::Cylinder(S));
52       P = ElSLib::Value(U,V,cy);
53       Norm.SetLinearForm(Cos(U),cy.XAxis().Direction(),
54                          Sin(U),cy.YAxis().Direction());
55       if (!cy.Direct()) {
56         Norm.Reverse();
57       }
58     }
59     break;
60
61
62   case GeomAbs_Cone:
63     {
64       gp_Cone co(TheSurfaceTool::Cone(S));
65       P = ElSLib::Value(U,V,co);
66       Standard_Real Angle = co.SemiAngle();
67       Standard_Real Sina = sin(Angle);
68       Standard_Real Cosa = cos(Angle);
69       Standard_Real Rad = co.RefRadius(); 
70
71       Standard_Real Vcalc = V;
72       if (Abs(V*Sina + Rad) <= 1e-12) { // on est a l`apex
73         /*
74            Standard_Real Vfi = TheSurfaceTool::FirstVParameter(S);
75            if (Vfi < -Rad/Sina) { // partie valide pour V < Vapex
76            Vcalc = V - 1;
77            }
78            else {
79            Vcalc = V + 1.;
80            }
81            */
82         Norm.SetCoord(0,0,0);
83         return;
84       }
85
86       if (Rad + Vcalc*Sina < 0.) {
87         Norm.SetLinearForm(Sina,       co.Axis().Direction(),
88                            Cosa*cos(U),co.XAxis().Direction(),
89                            Cosa*sin(U),co.YAxis().Direction());
90       }
91       else {
92         Norm.SetLinearForm(-Sina,       co.Axis().Direction(),
93                             Cosa*cos(U),co.XAxis().Direction(),
94                             Cosa*sin(U),co.YAxis().Direction());
95       }
96       if (!co.Direct()) {
97         Norm.Reverse();
98       }
99     }
100     break;
101   default:
102     {
103       gp_Vec d1u,d1v;
104       TheSurfaceTool::D1(S,U,V,P,d1u,d1v);
105       Norm = d1u.Crossed(d1v);
106     }
107     break;
108
109
110   }
111 }
112
113
114 //=======================================================================
115 //function : DerivAndNorm
116 //purpose  : 
117 //=======================================================================
118
119 void Contap_SurfProps::DerivAndNorm(const TheSurface& S, 
120                                     const Standard_Real U, 
121                                     const Standard_Real V,
122                                     gp_Pnt& P,
123                                     gp_Vec& d1u,
124                                     gp_Vec& d1v,
125                                     gp_Vec& Norm)
126 {
127
128   GeomAbs_SurfaceType typS = TheSurfaceTool::GetType(S);
129   switch (typS) {
130   case GeomAbs_Plane:
131     {
132       gp_Pln pl(TheSurfaceTool::Plane(S));
133       Norm = pl.Axis().Direction();
134       ElSLib::D1(U,V,pl,P,d1u,d1v);
135       if (!pl.Direct()) {
136         Norm.Reverse();
137       }
138     }
139     break;
140
141
142   case GeomAbs_Sphere:
143     {
144       gp_Sphere sp(TheSurfaceTool::Sphere(S));
145       ElSLib::D1(U,V,sp,P,d1u,d1v);
146       Norm = gp_Vec(sp.Location(),P);
147       if (sp.Direct()) {
148         Norm.Divide(sp.Radius());
149       }
150       else {
151         Norm.Divide(-sp.Radius());
152       }
153     }
154     break;
155
156   case GeomAbs_Cylinder:
157     {
158       gp_Cylinder cy(TheSurfaceTool::Cylinder(S));
159       ElSLib::D1(U,V,cy,P,d1u,d1v);
160       Norm.SetLinearForm(Cos(U),cy.XAxis().Direction(),
161                          Sin(U),cy.YAxis().Direction());
162       if (!cy.Direct()) {
163         Norm.Reverse();
164       }
165     }
166     break;
167
168
169   case GeomAbs_Cone:
170     {
171       gp_Cone co(TheSurfaceTool::Cone(S));
172       ElSLib::D1(U,V,co,P,d1u,d1v);
173       Standard_Real Angle = co.SemiAngle();
174       Standard_Real Sina = Sin(Angle);
175       Standard_Real Cosa = Cos(Angle);
176       Standard_Real Rad = co.RefRadius(); 
177
178       Standard_Real Vcalc = V;
179       if (Abs(V*Sina + Rad) <= RealEpsilon()) { // on est a l`apex
180         Standard_Real Vfi = TheSurfaceTool::FirstVParameter(S);
181         if (Vfi < -Rad/Sina) { // partie valide pour V < Vapex
182           Vcalc = V - 1;
183         }
184         else {
185           Vcalc = V + 1.;
186         }
187       }
188
189       if (Rad + Vcalc*Sina < 0.) {
190         Norm.SetLinearForm(Sina,       co.Axis().Direction(),
191                            Cosa*Cos(U),co.XAxis().Direction(),
192                            Cosa*Sin(U),co.YAxis().Direction());
193       }
194       else {
195         Norm.SetLinearForm(-Sina,       co.Axis().Direction(),
196                             Cosa*Cos(U),co.XAxis().Direction(),
197                             Cosa*Sin(U),co.YAxis().Direction());
198       }
199       if (!co.Direct()) {
200         Norm.Reverse();
201       }
202     }
203     break;
204   default:
205     {
206       TheSurfaceTool::D1(S,U,V,P,d1u,d1v);
207       Norm = d1u.Crossed(d1v);
208     }
209     break;
210   }
211 }
212
213
214 //=======================================================================
215 //function : NormAndDn
216 //purpose  : 
217 //=======================================================================
218
219 void Contap_SurfProps::NormAndDn(const TheSurface& S, 
220                                  const Standard_Real U, 
221                                  const Standard_Real V,
222                                  gp_Pnt& P,
223                                  gp_Vec& Norm,
224                                  gp_Vec& Dnu,
225                                  gp_Vec& Dnv)
226 {
227
228   GeomAbs_SurfaceType typS = TheSurfaceTool::GetType(S);
229   switch (typS) {
230   case GeomAbs_Plane:
231     {
232       gp_Pln pl(TheSurfaceTool::Plane(S));
233       P = ElSLib::Value(U,V,pl);
234       Norm = pl.Axis().Direction();
235       if (!pl.Direct()) {
236         Norm.Reverse();
237       }
238       Dnu = Dnv = gp_Vec(0.,0.,0.);
239     }
240     break;
241
242   case GeomAbs_Sphere:
243     {
244       gp_Sphere sp(TheSurfaceTool::Sphere(S));
245       ElSLib::D1(U,V,sp,P,Dnu,Dnv);
246       Norm = gp_Vec(sp.Location(),P);
247       Standard_Real Rad = sp.Radius();
248       if (!sp.Direct()) {
249         Rad = -Rad;
250       }
251       Norm.Divide(Rad);
252       Dnu.Divide(Rad);
253       Dnv.Divide(Rad);
254     }
255     break;
256
257   case GeomAbs_Cylinder:
258     {
259       gp_Cylinder cy(TheSurfaceTool::Cylinder(S));
260       P = ElSLib::Value(U,V,cy);
261       Norm.SetLinearForm(Cos(U),cy.XAxis().Direction(),
262                          Sin(U),cy.YAxis().Direction());
263       Dnu.SetLinearForm(-Sin(U),cy.XAxis().Direction(),
264                          Cos(U),cy.YAxis().Direction());
265       if (!cy.Direct()) {
266         Norm.Reverse();
267         Dnu.Reverse();
268       }
269       Dnv = gp_Vec(0.,0.,0.);
270     }
271     break;
272
273   case GeomAbs_Cone:
274     {
275
276       gp_Cone co(TheSurfaceTool::Cone(S));
277       P = ElSLib::Value(U,V,co);
278       Standard_Real Angle = co.SemiAngle();
279       Standard_Real Sina = Sin(Angle);
280       Standard_Real Cosa = Cos(Angle);
281       Standard_Real Rad = co.RefRadius(); 
282       Standard_Real Vcalc = V;
283       if (Abs(V*Sina + Rad) <= RealEpsilon()) { // on est a l`apex
284         Standard_Real Vfi = TheSurfaceTool::FirstVParameter(S);
285         if (Vfi < -Rad/Sina) { // partie valide pour V < Vapex
286           Vcalc = V - 1;
287         }
288         else {
289           Vcalc = V + 1.;
290         }
291       }
292
293       if (Rad + Vcalc*Sina < 0.) {
294         Norm.SetLinearForm(Sina,       co.Axis().Direction(),
295                            Cosa*Cos(U),co.XAxis().Direction(),
296                            Cosa*Sin(U),co.YAxis().Direction());
297       }
298       else {
299         Norm.SetLinearForm(-Sina,       co.Axis().Direction(),
300                             Cosa*Cos(U),co.XAxis().Direction(),
301                             Cosa*Sin(U),co.YAxis().Direction());
302       }
303       Dnu.SetLinearForm(-Cosa*Sin(U),co.XAxis().Direction(),
304                          Cosa*Cos(U),co.YAxis().Direction());
305       if (!co.Direct()) {
306         Norm.Reverse();
307         Dnu.Reverse();
308       }
309       Dnv = gp_Vec(0.,0.,0.);
310     }
311     break;
312   
313   default: 
314     {
315       gp_Vec d1u,d1v,d2u,d2v,d2uv;
316       TheSurfaceTool::D2(S,U,V,P,d1u,d1v,d2u,d2v,d2uv);
317       Norm = d1u.Crossed(d1v);
318       Dnu = d2u.Crossed(d1v) + d1u.Crossed(d2uv);
319       Dnv = d2uv.Crossed(d1v) + d1u.Crossed(d2v);
320     }
321     break;
322   }
323 }
324