973c2be1 |
1 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
2 | // |
973c2be1 |
3 | // This file is part of Open CASCADE Technology software library. |
b311480e |
4 | // |
d5f74e42 |
5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
9 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
10 | // |
973c2be1 |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
b311480e |
13 | |
42cf5bc1 |
14 | |
7fd59977 |
15 | #include <Bnd_Box.hxx> |
16 | #include <BRepBndLib.hxx> |
42cf5bc1 |
17 | #include <gp_Ax3.hxx> |
18 | #include <gp_Dir.hxx> |
19 | #include <gp_Pnt.hxx> |
20 | #include <gp_Trsf.hxx> |
21 | #include <gp_Vec.hxx> |
22 | #include <HLRAlgo_Projector.hxx> |
23 | #include <Precision.hxx> |
24 | #include <Standard_Type.hxx> |
7fd59977 |
25 | #include <TColgp_Array1OfPnt.hxx> |
26 | #include <TColgp_Array1OfVec.hxx> |
42cf5bc1 |
27 | #include <Vrml_Instancing.hxx> |
7fd59977 |
28 | #include <Vrml_MatrixTransform.hxx> |
42cf5bc1 |
29 | #include <Vrml_SFRotation.hxx> |
7fd59977 |
30 | #include <Vrml_TransformSeparator.hxx> |
42cf5bc1 |
31 | #include <VrmlConverter_Projector.hxx> |
7fd59977 |
32 | |
33 | VrmlConverter_Projector::VrmlConverter_Projector (const TopTools_Array1OfShape& Shapes, |
34 | const Quantity_Length Focus, |
35 | const Quantity_Length DX, |
36 | const Quantity_Length DY, |
37 | const Quantity_Length DZ, |
38 | const Quantity_Length XUp, |
39 | const Quantity_Length YUp, |
40 | const Quantity_Length ZUp, |
41 | const VrmlConverter_TypeOfCamera Camera, |
42 | const VrmlConverter_TypeOfLight Light) |
43 | |
44 | { |
45 | |
46 | myTypeOfCamera = Camera; |
47 | myTypeOfLight = Light; |
48 | |
49 | Standard_Integer i; |
50 | Bnd_Box box; |
51 | Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax, diagonal; |
52 | Standard_Real Xtarget, Ytarget, Ztarget, Angle, MaxAngle, Height, MaxHeight; |
53 | |
54 | for ( i=Shapes.Lower(); i <= Shapes.Upper(); i++) |
55 | { |
56 | BRepBndLib::AddClose(Shapes.Value(i), box); |
57 | } |
58 | |
59 | Standard_Real DistMax = 500000; |
60 | Standard_Real TolMin = 0.000001; |
61 | |
62 | box.Enlarge(TolMin); |
63 | box.Get( Xmin, Ymin, Zmin, Xmax, Ymax, Zmax ); |
64 | |
65 | if (box.IsOpenXmin()) Xmin = -DistMax; |
66 | if (box.IsOpenXmax()) Xmax = DistMax; |
67 | if (box.IsOpenYmin()) Ymin = -DistMax; |
68 | if (box.IsOpenYmax()) Ymax = DistMax; |
69 | if (box.IsOpenZmin()) Zmin = -DistMax; |
70 | if (box.IsOpenZmax()) Zmax = DistMax; |
71 | |
72 | Standard_Real xx = (Xmax - Xmin); |
73 | Standard_Real yy = (Ymax - Ymin); |
74 | Standard_Real zz = (Zmax - Zmin); |
75 | |
76 | Xtarget = (Xmin + Xmax)/2; |
77 | Ytarget = (Ymin + Ymax)/2; |
78 | Ztarget = (Zmin + Zmax)/2; |
79 | |
80 | // cout << " target: " << endl; |
81 | // cout << " X: " << Xtarget << " Y: " << Ytarget << " Z: " << Ztarget << endl; |
82 | |
83 | // gp_Pnt Target(Xtarget, Ytarget, Ztarget); |
84 | // gp_Vec VTarget(Target.X(),Target.Y(),Target.Z()); |
85 | |
86 | gp_Dir Zpers (DX,DY,DZ); |
87 | gp_Vec V(Zpers); |
88 | |
89 | diagonal = Sqrt (xx*xx + yy*yy + zz*zz); |
90 | |
91 | gp_Vec aVec = V.Multiplied(0.5*diagonal+TolMin+Focus); |
92 | |
93 | gp_Pnt Source; |
94 | Source.SetX(Xtarget+aVec.X()); |
95 | Source.SetY(Ytarget+aVec.Y()); |
96 | Source.SetZ(Ztarget+aVec.Z()); |
97 | |
98 | // cout << " source: " << endl; |
99 | // cout << " X: " << Source.X() << " Y: " << Source.Y() << " Z: " << Source.Z() << endl; |
100 | |
101 | gp_Vec VSource(Source.X(),Source.Y(),Source.Z()); |
102 | |
103 | // gp_Vec Proj(Source,Target); |
104 | // cout << " Vec(source-target): " << endl; |
105 | // cout << " X: " << Proj.X() << " Y: " << Proj.Y() << " Z: " << Proj.Z() << endl; |
106 | |
107 | gp_Dir Ypers (XUp,YUp,ZUp); |
108 | |
109 | if( Ypers.IsParallel(Zpers,Precision::Angular()) ) |
110 | { |
111 | Standard_Failure::Raise("Projection Vector is Parallel to High Point Direction"); |
112 | } |
113 | gp_Dir Xpers = Ypers.Crossed(Zpers); |
114 | |
115 | // cout << " Dir(Zpers): " << endl; |
116 | // cout << " X: " << Zpers.X() << " Y: " << Zpers.Y() << " Z: " << Zpers.Z() << endl; |
117 | // cout << " Dir(Xpers): " << endl; |
118 | // cout << " X: " << Xpers.X() << " Y: " << Xpers.Y() << " Z: " << Xpers.Z() << endl; |
119 | |
120 | gp_Ax3 Axe (Source, Zpers, Xpers); |
121 | |
122 | gp_Trsf T; |
123 | |
124 | // Makes the transformation allowing passage from the basic |
125 | // coordinate system |
126 | // {P(0.,0.,0.), VX (1.,0.,0.), VY (0.,1.,0.), VZ (0., 0. ,1.) } |
127 | // to the local coordinate system defined with the Ax3 ToSystem. |
128 | // Same utilisation as the previous method. FromSystem1 is |
129 | // defaulted to the absolute coordinate system. |
130 | T.SetTransformation(Axe); |
131 | |
132 | Standard_Boolean Pers = Standard_False; |
133 | if (Camera == VrmlConverter_PerspectiveCamera) Pers = Standard_True; |
134 | |
135 | //build a Projector with automatic minmax directions |
136 | myProjector = HLRAlgo_Projector(T,Pers,Focus); |
137 | |
138 | gp_Trsf T3; |
139 | T3 = T.Inverted(); |
140 | // T3.SetTranslationPart(gp_Vec (0,0,0)); |
141 | |
142 | myMatrixTransform.SetMatrix(T3); |
143 | |
144 | // For VRweb1.3 |
145 | // gp_Trsf T1 = T; |
146 | // T1.SetTranslationPart(gp_Vec (0,0,0)); |
147 | // myMatrixTransform.SetMatrix(T1); |
148 | |
149 | // |
150 | //== definitions cameras and lights |
151 | // |
152 | |
153 | if (Light == VrmlConverter_DirectionLight) |
154 | { |
155 | myDirectionalLight.SetDirection(Zpers.Reversed()); |
156 | } |
157 | |
158 | if (Light == VrmlConverter_PointLight) |
159 | { |
160 | myPointLight.SetLocation(VSource); |
161 | } |
162 | |
163 | if (Light == VrmlConverter_SpotLight || Camera != VrmlConverter_NoCamera ) |
164 | { |
165 | |
166 | /* |
167 | gp_Dir Zmain (0,0,1); |
168 | gp_Dir Xmain (1,0,0); |
169 | |
170 | |
171 | gp_Dir Dturn; |
172 | Standard_Real AngleTurn; |
173 | |
174 | if( Zmain.IsParallel(Zpers,Precision::Angular()) ) |
175 | { |
176 | if ( Zmain.IsOpposite(Zpers,Precision::Angular()) ) |
177 | { |
178 | Dturn = Zpers; |
179 | AngleTurn = - Xmain.Angle(Xpers); |
180 | } |
181 | Dturn = Zpers; |
182 | AngleTurn = Xmain.Angle(Xpers); |
183 | } |
184 | else |
185 | { |
186 | Dturn = Zmain.Crossed(Zpers); |
187 | AngleTurn = Zmain.Angle(Zpers); |
188 | } |
189 | */ |
190 | |
191 | gp_Pnt CurP; |
192 | TColgp_Array1OfPnt ArrP(1,8); |
193 | |
194 | CurP.SetCoord(Xmin, Ymin, Zmin); |
195 | ArrP.SetValue(1,CurP); |
196 | CurP.SetCoord(Xmin+xx, Ymin, Zmin); |
197 | ArrP.SetValue(2,CurP); |
198 | CurP.SetCoord(Xmin+xx, Ymin+yy, Zmin); |
199 | ArrP.SetValue(3,CurP); |
200 | CurP.SetCoord(Xmin, Ymin+yy, Zmin); |
201 | ArrP.SetValue(4,CurP); |
202 | |
203 | CurP.SetCoord(Xmin, Ymin, Zmax); |
204 | ArrP.SetValue(5,CurP); |
205 | CurP.SetCoord(Xmin+xx, Ymin, Zmax); |
206 | ArrP.SetValue(6,CurP); |
207 | CurP.SetCoord(Xmin+xx, Ymin+yy, Zmax); |
208 | ArrP.SetValue(7,CurP); |
209 | CurP.SetCoord(Xmin, Ymin+yy, Zmax); |
210 | ArrP.SetValue(8,CurP); |
211 | |
212 | // |
213 | gp_Vec V1, V2; |
214 | gp_Pnt P1, P2; |
215 | |
216 | MaxHeight = TolMin; |
217 | MaxAngle = TolMin; |
218 | |
219 | for ( i=ArrP.Lower(); i <= ArrP.Upper(); i++) |
220 | { |
221 | P1 = ArrP.Value(i); |
222 | P2 = P1.Transformed (T); |
223 | |
224 | V1.SetX(P2.X()); |
225 | V1.SetY(P2.Y()); |
226 | V1.SetZ(P2.Z()); |
227 | |
228 | V2.SetX(P2.X()); |
229 | V2.SetY(0); |
230 | V2.SetZ(P2.Z()); |
231 | |
232 | // cout << " Angle: " << V1.Angle(V2) << endl; |
233 | // cout << " ****************** " << endl; |
234 | if ( Abs(V1.Angle(V2)) > Abs(MaxAngle) ) MaxAngle = Abs(V1.Angle(V2)); |
235 | |
236 | V2.SetX(0); |
237 | V2.SetY(P2.Y()); |
238 | V2.SetZ(P2.Z()); |
239 | |
240 | // cout << " Angle: " << V1.Angle(V2) << endl; |
241 | // cout << " ****************** " << endl; |
242 | if ( Abs(V1.Angle(V2)) > Abs(MaxAngle) ) MaxAngle = Abs(V1.Angle(V2)); |
243 | |
244 | if ( Abs(P2.Y()) > Abs(MaxHeight) ) |
245 | { |
246 | // cout << " Height Y: " << P2.Y() << endl; |
247 | // cout << " ****************** " << endl; |
248 | MaxHeight = Abs(P2.Y()); |
249 | } |
250 | |
251 | if ( Abs(P2.X()) > Abs(MaxHeight) ) |
252 | { |
253 | // cout << " Height X: " << P2.X() << endl; |
254 | // cout << " ****************** " << endl; |
255 | MaxHeight = Abs(P2.X()); |
256 | } |
257 | } |
258 | Height = MaxHeight; |
259 | // cout << " MaxHeight: " << Height << endl; |
260 | // cout << " ****************** " << endl; |
261 | |
262 | Angle = MaxAngle; |
263 | // cout << " MaxAngle: " << Angle << endl; |
264 | // cout << " ****************** " << endl; |
265 | |
266 | if (Light == VrmlConverter_SpotLight) |
267 | { |
268 | mySpotLight.SetLocation(VSource); |
269 | mySpotLight.SetDirection(Zpers.Reversed()); |
270 | mySpotLight.SetCutOffAngle(2*Angle); |
271 | } |
272 | |
273 | if (Camera == VrmlConverter_PerspectiveCamera) |
274 | { |
275 | // myPerspectiveCamera.SetPosition(VSource); |
276 | // myPerspectiveCamera.SetOrientation(Vrml_SFRotation (Dturn.X(),Dturn.Y(),Dturn.Z(),AngleTurn)); |
277 | myPerspectiveCamera.SetFocalDistance(Focus); |
278 | myPerspectiveCamera.SetAngle(2*Angle); |
279 | } |
280 | |
281 | if (Camera == VrmlConverter_OrthographicCamera) |
282 | { |
283 | // myOrthographicCamera.SetPosition(VSource); |
284 | // myOrthographicCamera.SetOrientation(Vrml_SFRotation (Dturn.X(),Dturn.Y(),Dturn.Z(),AngleTurn)); |
285 | myOrthographicCamera.SetFocalDistance(Focus); |
286 | myOrthographicCamera.SetHeight(2*Height); |
287 | } |
288 | |
289 | } |
290 | } |
291 | |
292 | void VrmlConverter_Projector::Add(Standard_OStream& anOStream) const |
293 | { |
294 | switch ( myTypeOfCamera ) |
295 | { |
296 | case VrmlConverter_NoCamera: break; |
297 | case VrmlConverter_PerspectiveCamera: |
298 | { |
299 | Vrml_TransformSeparator TS; |
300 | TS.Print(anOStream); |
301 | myMatrixTransform.Print(anOStream); |
302 | Vrml_Instancing I1 ("Perspective Camera"); |
303 | I1.DEF(anOStream); |
304 | myPerspectiveCamera.Print(anOStream); |
305 | TS.Print(anOStream); |
306 | } |
307 | break; |
308 | case VrmlConverter_OrthographicCamera: |
309 | { |
310 | Vrml_TransformSeparator TS; |
311 | TS.Print(anOStream); |
312 | myMatrixTransform.Print(anOStream); |
313 | Vrml_Instancing I2 ("Orthographic Camera"); |
314 | I2.DEF(anOStream); |
315 | myOrthographicCamera.Print(anOStream); |
316 | TS.Print(anOStream); |
317 | } |
318 | break; |
319 | } |
320 | |
321 | switch ( myTypeOfLight ) |
322 | { |
323 | case VrmlConverter_NoLight: break; |
324 | case VrmlConverter_DirectionLight: |
325 | { |
326 | myDirectionalLight.Print(anOStream); |
327 | } |
328 | break; |
329 | case VrmlConverter_PointLight: |
330 | { |
331 | myPointLight.Print(anOStream); |
332 | } |
333 | break; |
334 | case VrmlConverter_SpotLight: |
335 | { |
336 | mySpotLight.Print(anOStream); |
337 | } |
338 | break; |
339 | } |
340 | |
341 | } |
342 | |
343 | void VrmlConverter_Projector::SetCamera(const VrmlConverter_TypeOfCamera aCamera) |
344 | { |
345 | myTypeOfCamera = aCamera; |
346 | } |
347 | |
348 | VrmlConverter_TypeOfCamera VrmlConverter_Projector::Camera() const |
349 | { |
350 | return myTypeOfCamera; |
351 | } |
352 | |
353 | void VrmlConverter_Projector::SetLight(const VrmlConverter_TypeOfLight aLight) |
354 | { |
355 | myTypeOfLight = aLight; |
356 | } |
357 | |
358 | VrmlConverter_TypeOfLight VrmlConverter_Projector::Light() const |
359 | { |
360 | return myTypeOfLight; |
361 | } |
362 | |
363 | HLRAlgo_Projector VrmlConverter_Projector::Projector () const |
364 | { |
365 | return myProjector; |
366 | } |