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