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