7fd59977 |
1 | /*********************************************************************** |
2 | |
3 | FONCTION : |
4 | ---------- |
5 | Classe V3d_Camera : |
6 | |
7 | HISTORIQUE DES MODIFICATIONS : |
8 | -------------------------------- |
9 | 00-09-92 : GG ; Creation. |
10 | 18-06-96 : FMN ; Ajout MyGraphicStructure1 pour sauvegarder snopick |
11 | 24-12-97 : FMN ; Remplacement de math par MathGra |
12 | 31-12-97 : CAL ; Suppression de MathGra |
13 | 21-01-98 : CAL ; Window de Xw et WNT remplacee par Aspect_Window |
14 | 23-02-98 : FMN ; Remplacement PI par Standard_PI |
15 | 02.15.100 : JR : Clutter |
16 | |
17 | ************************************************************************/ |
18 | |
19 | /*----------------------------------------------------------------------*/ |
20 | /* |
21 | * Includes |
22 | */ |
23 | |
24 | #include <V3d_Camera.ixx> |
25 | #include <V3d.hxx> |
26 | #include <V3d_PerspectiveView.hxx> |
27 | #include <Graphic3d_Vector.hxx> |
28 | #include <Graphic3d_Vertex.hxx> |
29 | #include <Graphic3d_Structure.hxx> |
30 | #include <Graphic3d_Group.hxx> |
31 | #include <Graphic3d_Array1OfVertex.hxx> |
32 | #include <Graphic3d_AspectMarker3d.hxx> |
33 | #include <Graphic3d_AspectLine3d.hxx> |
34 | #include <Graphic3d_AspectText3d.hxx> |
35 | #include <Visual3d_ViewManager.hxx> |
36 | #include <Visual3d_ContextPick.hxx> |
37 | #include <Visual3d_PickDescriptor.hxx> |
38 | #include <Visual3d_HSequenceOfPickPath.hxx> |
39 | #include <Visual3d_PickPath.hxx> |
40 | #include <Viewer_BadValue.hxx> |
41 | #include <gp_Dir.hxx> |
42 | #include <gp_Ax1.hxx> |
43 | #include <gp_Vec.hxx> |
44 | #include <gp_Pnt.hxx> |
45 | #include <gp_Trsf.hxx> |
46 | #include <TColStd_Array2OfReal.hxx> |
47 | #include <TCollection_AsciiString.hxx> |
48 | #include <Aspect_Window.hxx> |
49 | |
50 | //-Declarations |
51 | #define DEUXPI (2.*Standard_PI) |
52 | |
53 | //-Constructors |
54 | |
55 | V3d_Camera::V3d_Camera(const Handle(V3d_View)& aView) { |
56 | Standard_Real X,Y,Z; |
57 | Graphic3d_Vertex P,T; |
58 | |
81bba717 |
59 | // The eye point defines the position of the camera |
7fd59977 |
60 | aView->Eye(X,Y,Z); |
61 | P.SetCoord(X,Y,Z); |
62 | MyPosition = P; |
81bba717 |
63 | // The target point defines the target of the camera |
7fd59977 |
64 | aView->At(X,Y,Z); |
65 | T.SetCoord(X,Y,Z); |
66 | MyTarget = T; |
81bba717 |
67 | // Incline Angle of the camera |
7fd59977 |
68 | MyAngle = aView->Twist(); |
81bba717 |
69 | // Aperture Angle of the camera |
7fd59977 |
70 | MyAperture = (aView->DynamicType()==STANDARD_TYPE(V3d_PerspectiveView)) ? |
71 | ((Handle(V3d_PerspectiveView)&)aView)->Angle() : 0.; |
72 | |
73 | } |
74 | |
75 | //-Methods, in order |
76 | |
77 | void V3d_Camera::SetPosition(const Standard_Real Xp, const Standard_Real Yp, const Standard_Real Zp) { |
78 | |
79 | MyPosition.SetCoord(Xp,Yp,Zp) ; |
80 | } |
81 | |
82 | void V3d_Camera::SetAngle(const Standard_Real Angle) { |
83 | |
84 | Viewer_BadValue_Raise_if( Abs(Angle) > DEUXPI, "V3d_Camera::SetAngle, bad angle" ); |
85 | MyAngle = Angle ; |
86 | } |
87 | |
88 | void V3d_Camera::SetAperture(const Standard_Real Angle) { |
89 | |
90 | Viewer_BadValue_Raise_if( Angle <= 0. || Angle >= Standard_PI ,"V3d_Camera::SetAperture, bad angle"); |
91 | MyAperture = Angle ; |
92 | } |
93 | |
94 | void V3d_Camera::SetTarget(const Standard_Real X, const Standard_Real Y, const Standard_Real Z) { |
95 | |
96 | MyTarget.SetCoord(X,Y,Z); |
97 | } |
98 | |
99 | void V3d_Camera::SetRadius(const Standard_Real Radius) { |
100 | |
101 | Viewer_BadValue_Raise_if( Radius <= 0., "V3d_Camera::SetRadius, bad radius"); |
102 | |
103 | Standard_Real X0,Y0,Z0,Xn,Yn,Zn; |
104 | |
81bba717 |
105 | // Targer point remains unchanged, only the position of the camera is modified |
106 | // preserving the direction. |
7fd59977 |
107 | Graphic3d_Vector D(MyTarget,MyPosition); |
108 | D.Normalize(); |
109 | D.Coord(Xn,Yn,Zn); |
110 | MyTarget.Coord(X0,Y0,Z0); |
111 | Xn = X0 + Radius*Xn; |
112 | Yn = Y0 + Radius*Yn; |
113 | Zn = Z0 + Radius*Zn; |
114 | MyPosition.SetCoord(Xn,Yn,Zn) ; |
115 | |
116 | } |
117 | |
118 | void V3d_Camera::OnHideFace(const Handle(V3d_View)& aView) { |
119 | |
120 | Standard_Real XP,YP,ZP,Rayon,X,Y,Z,VX,VY,VZ; |
121 | |
122 | Rayon = this->Radius(); |
123 | MyPosition.Coord(XP,YP,ZP); |
124 | SymetricPointOnSphere(aView,MyTarget,MyPosition,Rayon,X,Y,Z,VX,VY,VZ); |
81bba717 |
125 | // This point is visible |
7fd59977 |
126 | if ( (VX*(X-XP) < 0.) && (VY*(Y-YP) < 0.) && (VZ*(Z-ZP) < 0.) ) { |
127 | this->SetPosition(X,Y,Z); |
128 | } |
129 | } |
130 | |
131 | void V3d_Camera::OnSeeFace(const Handle(V3d_View)& aView) { |
132 | |
133 | Standard_Real XP,YP,ZP,Rayon,X,Y,Z,VX,VY,VZ; |
134 | |
135 | Rayon = this->Radius(); |
136 | MyPosition.Coord(XP,YP,ZP); |
137 | SymetricPointOnSphere(aView,MyTarget,MyPosition,Rayon,X,Y,Z,VX,VY,VZ); |
81bba717 |
138 | // This point is hidden |
7fd59977 |
139 | if ( (VX*(X-XP) > 0.) && (VY*(Y-YP) > 0.) && (VZ*(Z-ZP) > 0.) ) { |
140 | this->SetPosition(X,Y,Z); |
141 | } |
142 | } |
143 | |
144 | Standard_Boolean V3d_Camera::SeeOrHide(const Handle(V3d_View)& aView) const { |
145 | |
146 | Standard_Real XP,YP,ZP,Rayon,X,Y,Z,VX,VY,VZ; |
147 | Standard_Boolean Val; |
148 | |
149 | Rayon = this->Radius(); |
150 | MyPosition.Coord(XP,YP,ZP); |
151 | SymetricPointOnSphere(aView,MyTarget,MyPosition,Rayon,X,Y,Z,VX,VY,VZ); |
81bba717 |
152 | // Is it a visible or a hidden point? |
7fd59977 |
153 | if ( (VX*(X-XP) > 0.) || (VY*(Y-YP) > 0.) || (VZ*(Z-ZP) > 0.) ) |
81bba717 |
154 | // the source is on the hidden face |
7fd59977 |
155 | Val = Standard_False; |
156 | else |
81bba717 |
157 | // the source is on the visible face. |
7fd59977 |
158 | Val = Standard_True; |
159 | |
160 | return Val; |
161 | |
162 | } |
163 | |
164 | void V3d_Camera::Position(Standard_Real& Xp, Standard_Real& Yp, Standard_Real& Zp)const { |
165 | |
166 | MyPosition.Coord(Xp,Yp,Zp) ; |
167 | } |
168 | |
169 | Standard_Real V3d_Camera::Angle()const { |
170 | |
171 | return MyAngle ; |
172 | } |
173 | |
174 | Standard_Real V3d_Camera::Aperture()const { |
175 | |
176 | return MyAperture ; |
177 | } |
178 | |
179 | void V3d_Camera::Target(Standard_Real& Xp, Standard_Real& Yp, Standard_Real& Zp)const { |
180 | |
181 | // Graphic3d_Vertex P ; |
182 | MyTarget.Coord(Xp,Yp,Zp) ; |
183 | } |
184 | |
185 | Standard_Real V3d_Camera::Radius() const { |
186 | |
187 | Standard_Real Xp,Yp,Zp,Xc,Yc,Zc,Radius; |
188 | MyPosition.Coord(Xp,Yp,Zp); |
189 | MyTarget.Coord(Xc,Yc,Zc); |
190 | Radius = Square(Xc - Xp) + Square(Yc - Yp) + Square(Zc - Zp); |
191 | Radius = Sqrt(Radius); |
192 | return Radius ; |
193 | } |
194 | |
195 | void V3d_Camera::Symbol (const Handle(Graphic3d_Group)& gsymbol, |
196 | // const Handle(V3d_View)& aView) const { |
197 | const Handle(V3d_View)& ) const { |
198 | |
199 | Standard_Real X0,Y0,Z0,XP,YP,ZP,Dx,Dy,Dz,Lng; |
200 | Standard_Real Xc1,Yc1,Zc1,Xc2,Yc2,Zc2,Xi,Yi,Zi,Xj,Yj,Zj; |
201 | Standard_Real Xn,Yn,Zn,X,Y,Z,Norme; |
202 | Standard_Real cosinus,sinus; |
203 | Standard_Real Alpha = Standard_PI/4.; |
204 | Standard_Integer NbPoints = 4, i; |
205 | Graphic3d_Array1OfVertex VN1(1,NbPoints+1); |
206 | Graphic3d_Array1OfVertex VN2(1,NbPoints+1); |
207 | Graphic3d_Array1OfVertex V2(1,2); |
208 | |
81bba717 |
209 | // Direction of the camera |
7fd59977 |
210 | MyPosition.Coord(XP,YP,ZP); |
211 | MyTarget.Coord(X0,Y0,Z0); |
212 | Dx = X0 - XP; Dy = Y0 - YP; Dz = Z0 - ZP; |
213 | Lng = this->Radius()/10.; |
214 | |
81bba717 |
215 | // Find centers of base squares of the case of the camera : |
7fd59977 |
216 | Xc1 = XP - Dx * Lng; Yc1 = YP - Dy * Lng; Zc1 = ZP - Dz * Lng; |
217 | Xc2 = XP + Dx * Lng; Yc2 = YP + Dy * Lng; Zc2 = ZP + Dz * Lng; |
218 | |
81bba717 |
219 | // Construction of a mark i,j for rectangles : |
7fd59977 |
220 | Xn=0., Yn=0., Zn=0.; |
221 | |
222 | if ( Abs(Dx) <= Abs(Dy) && Abs(Dx) <= Abs(Dz)) Xn=1.; |
223 | else if ( Abs(Dy) <= Abs(Dz) && Abs(Dy) <= Abs(Dx)) Yn=1.; |
224 | else Zn=1.; |
225 | Xi = Dy * Zn - Dz * Yn; |
226 | Yi = Dz * Xn - Dx * Zn; |
227 | Zi = Dx * Yn - Dy * Xn; |
228 | |
229 | Norme = Sqrt ( Xi*Xi + Yi*Yi + Zi*Zi ); |
230 | Xi= Xi / Norme; Yi = Yi / Norme; Zi = Zi/Norme; |
231 | |
232 | Xj = Dy * Zi - Dz * Yi; |
233 | Yj = Dz * Xi - Dx * Zi; |
234 | Zj = Dx * Yi - Dy * Xi; |
235 | |
81bba717 |
236 | // Scheme of the case |
7fd59977 |
237 | for (i = 1 ; i <= NbPoints ; i++) { |
238 | |
239 | cosinus = Cos ( Alpha + (i - 1) * Standard_PI/2. ); |
240 | sinus = Sin ( Alpha + (i - 1) * Standard_PI/2. ); |
241 | |
81bba717 |
242 | // First base square |
7fd59977 |
243 | X = Xc1 + (cosinus * Xi + sinus * Xj) * Lng / 2.; |
244 | Y = Yc1 + (cosinus * Yi + sinus * Yj) * Lng / 2.; |
245 | Z = Zc1 + (cosinus * Zi + sinus * Zj) * Lng / 2.; |
246 | VN1(i).SetCoord(X,Y,Z); |
247 | if(i==1) VN1(NbPoints+1).SetCoord(X,Y,Z); |
248 | V2(1).SetCoord(X,Y,Z); |
249 | |
81bba717 |
250 | // Second base square |
7fd59977 |
251 | X = Xc2 + (cosinus * Xi + sinus * Xj) * Lng / 2.; |
252 | Y = Yc2 + (cosinus * Yi + sinus * Yj) * Lng / 2.; |
253 | Z = Zc2 + (cosinus * Zi + sinus * Zj) * Lng / 2.; |
254 | VN2(i).SetCoord(X,Y,Z); |
255 | if(i==1) VN2(NbPoints+1).SetCoord(X,Y,Z); |
256 | V2(2).SetCoord(X,Y,Z); |
257 | |
258 | gsymbol->Polyline(V2); |
259 | } |
260 | gsymbol->Polyline(VN1); |
261 | gsymbol->Polyline(VN2); |
262 | |
81bba717 |
263 | // Scheme of the objective |
7fd59977 |
264 | for (i = 1 ; i <= NbPoints ; i++) { |
265 | |
266 | cosinus = Cos ( Alpha + (i - 1) * Standard_PI/2. ); |
267 | sinus = Sin ( Alpha + (i - 1) * Standard_PI/2. ); |
268 | |
269 | // Premier carre de base |
270 | X = Xc2 + (cosinus * Xi + sinus * Xj) * Lng / 6.; |
271 | Y = Yc2 + (cosinus * Yi + sinus * Yj) * Lng / 6.; |
272 | Z = Zc2 + (cosinus * Zi + sinus * Zj) * Lng / 6.; |
273 | VN1(i).SetCoord(X,Y,Z); |
274 | if(i==1) VN1(NbPoints+1).SetCoord(X,Y,Z); |
275 | V2(1).SetCoord(X,Y,Z); |
276 | |
81bba717 |
277 | // Second base square |
7fd59977 |
278 | X = Xc2 + Dx * Lng / 6. + (cosinus * Xi + sinus * Xj) * Lng / 3.; |
279 | Y = Yc2 + Dy * Lng / 6. + (cosinus * Yi + sinus * Yj) * Lng / 3.; |
280 | Z = Zc2 + Dz * Lng / 6. + (cosinus * Zi + sinus * Zj) * Lng / 3.; |
281 | VN2(i).SetCoord(X,Y,Z); |
282 | if(i==1) VN2(NbPoints+1).SetCoord(X,Y,Z); |
283 | V2(2).SetCoord(X,Y,Z); |
284 | |
285 | gsymbol->Polyline(V2); |
286 | } |
287 | gsymbol->Polyline(VN1); |
288 | gsymbol->Polyline(VN2); |
289 | |
290 | } |
291 | |
292 | void V3d_Camera::Display( const Handle(V3d_View)& aView, |
293 | const V3d_TypeOfRepresentation TPres) { |
294 | |
295 | Graphic3d_Array1OfVertex PRadius(0,1); |
296 | Graphic3d_Vertex PText ; |
297 | Standard_Real X,Y,Z,Rayon; |
298 | Standard_Real X0,Y0,Z0,VX,VY,VZ; |
299 | Standard_Real X1,Y1,Z1,XT,YT,ZT,PXT,PYT; |
300 | Standard_Real DXRef,DYRef,DZRef,DXini,DYini,DZini; |
301 | Standard_Integer IXP,IYP; |
302 | V3d_TypeOfRepresentation Pres; |
303 | V3d_TypeOfUpdate UpdSov; |
304 | |
305 | |
81bba717 |
306 | // Creation of a structure of markable elements (position of the |
307 | // camera, and the sphere of displacement of this camera) |
7fd59977 |
308 | |
309 | Pres = TPres; |
310 | Handle(V3d_Viewer) TheViewer = aView->Viewer(); |
311 | UpdSov = TheViewer->UpdateMode(); |
312 | TheViewer->SetUpdateMode(V3d_WAIT); |
313 | if (!MyGraphicStructure.IsNull()) { |
314 | MyGraphicStructure->Disconnect(MyGraphicStructure1); |
315 | MyGraphicStructure->Clear(); |
316 | MyGraphicStructure1->Clear(); |
317 | if (Pres == V3d_SAMELAST) Pres = MyTypeOfRepresentation; |
318 | } |
319 | else { |
320 | if (Pres == V3d_SAMELAST) Pres = V3d_SIMPLE; |
321 | Handle(Graphic3d_Structure) scamera = new Graphic3d_Structure(TheViewer->Viewer()); |
322 | MyGraphicStructure = scamera; |
323 | Handle(Graphic3d_Structure) snopick = new Graphic3d_Structure(TheViewer->Viewer()); |
324 | MyGraphicStructure1 = snopick; |
325 | } |
326 | |
327 | Handle(Graphic3d_Group) gradius; |
328 | Handle(Graphic3d_Group) gExtArrow; |
329 | Handle(Graphic3d_Group) gIntArrow; |
330 | if (Pres == V3d_COMPLETE) { |
331 | gradius = new Graphic3d_Group(MyGraphicStructure); |
332 | gExtArrow = new Graphic3d_Group(MyGraphicStructure); |
333 | gIntArrow = new Graphic3d_Group(MyGraphicStructure); |
334 | } |
335 | Handle(Graphic3d_Group) gcamera = new Graphic3d_Group(MyGraphicStructure); |
336 | Handle(Graphic3d_Group) gsphere; |
337 | if (Pres == V3d_COMPLETE || Pres == V3d_PARTIAL) gsphere = new Graphic3d_Group(MyGraphicStructure); |
338 | |
81bba717 |
339 | // Creation of a structure of non-markable elements (meridian and |
340 | // parallel ). |
7fd59977 |
341 | Handle(Graphic3d_Group) gnopick = new Graphic3d_Group(MyGraphicStructure1); |
342 | MyGraphicStructure1->SetPick(Standard_False); |
343 | |
344 | MyTarget.Coord(X0,Y0,Z0); |
345 | |
81bba717 |
346 | // Display of the position of the camera. |
7fd59977 |
347 | |
348 | gcamera->SetPickId(1); |
349 | if (Pres == V3d_SIMPLE) { |
81bba717 |
350 | // a viewfinder is drawn |
7fd59977 |
351 | Graphic3d_Array1OfVertex PViseur(1,2); |
352 | aView->Project(X0,Y0,Z0,PXT,PYT); |
353 | aView->Convert(PXT,PYT,IXP,IYP); |
354 | aView->Convert(IXP,IYP,XT,YT,ZT); |
355 | aView->Convert(IXP+20,IYP,X,Y,Z); |
356 | PViseur(1).SetCoord(X+X0-XT,Y+Y0-YT,Z+Z0-ZT); |
357 | aView->Convert(IXP-20,IYP,X,Y,Z); |
358 | PViseur(2).SetCoord(X+X0-XT,Y+Y0-YT,Z+Z0-ZT); |
359 | gcamera->Polyline(PViseur); |
360 | aView->Convert(IXP,IYP-20,X,Y,Z); |
361 | PViseur(1).SetCoord(X+X0-XT,Y+Y0-YT,Z+Z0-ZT); |
362 | aView->Convert(IXP,IYP+20,X,Y,Z); |
363 | PViseur(2).SetCoord(X+X0-XT,Y+Y0-YT,Z+Z0-ZT); |
364 | gcamera->Polyline(PViseur); |
365 | } |
81bba717 |
366 | // a camera is drawn |
7fd59977 |
367 | else this->Symbol(gcamera,aView); |
368 | |
81bba717 |
369 | // Display of the marking sphere (limited to circle). |
7fd59977 |
370 | |
371 | if (Pres == V3d_COMPLETE || Pres == V3d_PARTIAL) { |
372 | |
373 | Rayon = this->Radius(); |
374 | aView->Proj(VX,VY,VZ); |
375 | gsphere->SetPickId(2); |
376 | V3d::CircleInPlane(gsphere,X0,Y0,Z0,VX,VY,VZ,Rayon); |
377 | |
81bba717 |
378 | // Display of the radius of the sphere (line + text) |
7fd59977 |
379 | |
380 | if (Pres == V3d_COMPLETE) { |
381 | gradius->SetPickId(3); |
382 | gExtArrow->SetPickId(4); |
383 | gIntArrow->SetPickId(5); |
384 | PRadius(0).SetCoord(X0,Y0,Z0); |
385 | MyPosition.Coord(X,Y,Z); |
386 | PRadius(1).SetCoord(X,Y,Z); |
387 | gnopick->Polyline(PRadius); |
388 | V3d::ArrowOfRadius(gExtArrow,X-(X-X0)/10., |
389 | Y-(Y-Y0)/10., |
390 | Z-(Z-Z0)/10.,X-X0,Y-Y0,Z-Z0,Standard_PI/15.,Rayon/20.); |
391 | V3d::ArrowOfRadius(gIntArrow,X0,Y0,Z0,X0-X,Y0-Y,Z0-Z,Standard_PI/15., |
392 | Rayon/20.); |
393 | TCollection_AsciiString ValOfRadius(Rayon); |
394 | PText.SetCoord( (X0+X)/2., (Y0+Y)/2. , (Z0+Z)/2. ); |
395 | gradius->Text(ValOfRadius.ToCString(),PText,0.01); |
396 | } |
397 | |
81bba717 |
398 | // Display of the meridian |
7fd59977 |
399 | |
400 | Quantity_Color Col2(Quantity_NOC_GREEN); |
401 | Handle(Graphic3d_AspectLine3d) Asp2 = new Graphic3d_AspectLine3d |
402 | (Col2,Aspect_TOL_SOLID,1.); |
403 | gnopick->SetPrimitivesAspect(Asp2); |
404 | |
81bba717 |
405 | // Definition of the axis of circle |
7fd59977 |
406 | aView->Up(DXRef,DYRef,DZRef); |
407 | this->Position(X,Y,Z); |
408 | DXini = X-X0; DYini = Y-Y0; DZini = Z-Z0; |
409 | VX = DYRef*DZini - DZRef*DYini; |
410 | VY = DZRef*DXini - DXRef*DZini; |
411 | VZ = DXRef*DYini - DYRef*DXini; |
412 | |
413 | V3d::CircleInPlane(gnopick,X0,Y0,Z0,VX,VY,VZ,Rayon); |
414 | |
81bba717 |
415 | // Display of the parallel |
7fd59977 |
416 | |
81bba717 |
417 | // Definition of the axis of circle |
7fd59977 |
418 | aView->Proj(VX,VY,VZ); |
419 | aView->Up(X1,Y1,Z1); |
420 | DXRef = VY * Z1 - VZ * Y1; |
421 | DYRef = VZ * X1 - VX * Z1; |
422 | DZRef = VX * Y1 - VY * X1; |
423 | this->Position(X,Y,Z); |
424 | DXini = X-X0; DYini = Y-Y0; DZini = Z-Z0; |
425 | VX = DYRef*DZini - DZRef*DYini; |
426 | VY = DZRef*DXini - DXRef*DZini; |
427 | VZ = DXRef*DYini - DYRef*DXini; |
428 | |
429 | V3d::CircleInPlane(gnopick,X0,Y0,Z0,VX,VY,VZ,Rayon); |
430 | |
431 | } |
432 | |
433 | MyGraphicStructure->Connect(MyGraphicStructure1,Graphic3d_TOC_DESCENDANT); |
434 | MyTypeOfRepresentation = Pres; |
435 | MyGraphicStructure->Display(); |
436 | TheViewer->SetUpdateMode(UpdSov); |
437 | } |
438 | |
439 | void V3d_Camera::Erase() { |
440 | |
441 | if (!MyGraphicStructure.IsNull()) MyGraphicStructure->Erase(); |
442 | if (!MyGraphicStructure1.IsNull()) MyGraphicStructure1->Erase(); |
443 | } |
444 | |
445 | V3d_TypeOfPickCamera V3d_Camera::Pick(const Handle(V3d_View)& aView, |
446 | const Standard_Integer Xpix, |
447 | const Standard_Integer Ypix) const |
448 | { |
449 | |
450 | Standard_Integer i, Lng, Id; |
451 | Standard_Boolean kcont; |
452 | V3d_TypeOfPickCamera TPick; |
453 | |
454 | Handle(Visual3d_ViewManager) VM = (aView->Viewer())->Viewer(); |
455 | Visual3d_ContextPick CTXP; |
456 | Visual3d_PickDescriptor Pdes = VM->Pick(CTXP,aView->Window (),Xpix,Ypix); |
457 | Visual3d_PickPath OnePPath; |
458 | Handle(Visual3d_HSequenceOfPickPath) PPath = Pdes.PickPath(); |
459 | Lng = PPath->Length(); |
460 | kcont = Standard_True; |
461 | TPick = V3d_NOTHINGCAMERA; |
462 | for (i=1; i<=Lng && kcont; i++) { |
463 | OnePPath = PPath->Value(i); |
464 | Id = OnePPath.PickIdentifier(); |
465 | if (MyGraphicStructure == OnePPath.StructIdentifier()){ |
466 | switch (Id) { |
467 | case 1 : TPick = V3d_POSITIONCAMERA; |
468 | break; |
469 | case 2 : TPick = V3d_SPACECAMERA; |
470 | break; |
471 | case 3 : TPick = V3d_RADIUSTEXTCAMERA; |
472 | break; |
473 | case 4 : TPick = V3d_ExtRADIUSCAMERA; |
474 | break; |
475 | case 5 : TPick = V3d_IntRADIUSCAMERA; |
476 | break; |
477 | } |
478 | kcont = Standard_False; |
479 | } |
480 | } |
481 | return TPick; |
482 | } |
483 | |
484 | void V3d_Camera::Tracking( const Handle(V3d_View)& aView, |
485 | const V3d_TypeOfPickCamera WhatPick, |
486 | const Standard_Integer Xpix, |
487 | const Standard_Integer Ypix) { |
488 | |
489 | |
490 | Standard_Real XPp,YPp,PXT,PYT,X,Y,Z,Rayon,Ylim; |
491 | Standard_Real XMinTrack,XMaxTrack,YMinTrack,YMaxTrack; |
492 | Standard_Real XT,YT,ZT,X0,Y0,Z0,XP,YP,ZP,VX,VY,VZ,A,B,C,Delta; |
493 | Standard_Real DX,DY,PXP,PYP,Xproj,Yproj; |
494 | Standard_Real A1,A2,B1,B2,Rap,OldRprj,NewRprj; |
495 | Standard_Real Xi,Yi,Zi,DeltaX,DeltaY,DeltaZ,Lambda; |
496 | Standard_Integer IPX,IPY; |
497 | |
498 | |
499 | aView->Convert(Xpix,Ypix,XPp,YPp); |
500 | MyTarget.Coord(X0,Y0,Z0); |
501 | aView->Project(X0,Y0,Z0,PXT,PYT); |
502 | aView->Convert(PXT,PYT,IPX,IPY); |
81bba717 |
503 | // Coord 3d in the plane of projection of the target. |
7fd59977 |
504 | aView->Convert(IPX,IPY,XT,YT,ZT); |
505 | switch (WhatPick) { |
506 | case V3d_POSITIONCAMERA : |
81bba717 |
507 | // Coordinates should remain inside of the sphere |
7fd59977 |
508 | Rayon = this->Radius(); |
509 | XMinTrack = PXT - Rayon; |
510 | XMaxTrack = PXT + Rayon; |
511 | Ylim = Sqrt( Square(Rayon) - Square(XPp - PXT) ); |
512 | YMinTrack = PYT - Ylim; |
513 | YMaxTrack = PYT + Ylim; |
514 | if (XPp >= XMinTrack && XPp <= XMaxTrack) { |
515 | if (YPp >= YMinTrack && YPp <= YMaxTrack) { |
516 | aView->ProjReferenceAxe(Xpix,Ypix,XP,YP,ZP,VX,VY,VZ); |
517 | DeltaX = X0 - XP; |
518 | DeltaY = Y0 - YP; |
519 | DeltaZ = Z0 - ZP; |
520 | |
81bba717 |
521 | // The point of intersection of straight lines defined by : |
522 | // - Straight line passing by the point of projection and the eye |
523 | // if this is a perspective, parallel to the normal of the |
524 | // view if there is an axonometric view. |
525 | // position in the view is parallel to the normal of the view |
526 | // - The distance position of the target camera cible is equal |
527 | // to the radius. |
7fd59977 |
528 | |
529 | A = VX*VX + VY*VY + VZ*VZ ; |
530 | B = -2. * (VX*DeltaX + VY*DeltaY + VZ*DeltaZ); |
531 | C = DeltaX*DeltaX + DeltaY*DeltaY + DeltaZ*DeltaZ |
532 | - Rayon*Rayon ; |
533 | Delta = B*B - 4.*A*C; |
534 | if ( Delta >= 0 ) { |
535 | Lambda = (-B + Sqrt(Delta))/(2.*A); |
536 | X = XP + Lambda*VX; |
537 | Y = YP + Lambda*VY; |
538 | Z = ZP + Lambda*VZ; |
539 | MyPosition.SetCoord(X,Y,Z); |
540 | this->Display(aView,MyTypeOfRepresentation); |
541 | aView->Update(); |
542 | } |
543 | } |
544 | |
545 | break; |
546 | } |
547 | case V3d_SPACECAMERA : |
548 | aView->Convert(PXT,PYT,IPX,IPY); |
81bba717 |
549 | // In case Xpix,Ypix corresponding to a distance , relative |
550 | // to the translation that is planned to be done on the sphere. |
7fd59977 |
551 | aView->Convert(IPX+Xpix,IPY+Ypix,X,Y,Z); |
552 | X = X+X0-XT; |
553 | Y = Y+Y0-YT; |
554 | Z = Z+Z0-ZT; |
555 | MyTarget.SetCoord(X,Y,Z); |
556 | MyPosition.Coord(Xi,Yi,Zi); |
557 | Xi = Xi + (X - X0); |
558 | Yi = Yi + (Y - Y0); |
559 | Zi = Zi + (Z - Z0); |
560 | MyPosition.SetCoord(Xi,Yi,Zi); |
561 | this->Display(aView,MyTypeOfRepresentation); |
562 | aView->Update(); |
563 | break; |
564 | |
565 | case V3d_ExtRADIUSCAMERA : |
81bba717 |
566 | // It is attempted to preserve the target positioning direction of the |
567 | // camera ==> the point is projected on the target camera direction. |
7fd59977 |
568 | this->Position(Xi,Yi,Zi); |
569 | aView->Project(Xi,Yi,Zi,PXP,PYP); |
570 | DX = PXP - PXT; |
571 | DY = PYP - PYT; |
572 | A1 = DY/DX ; B1 = PYT - A1*PXT; |
573 | A2 = -DX/DY; B2 = YPp - A2*XPp; |
574 | Xproj = (B2 - B1) / (A1 - A2); |
575 | Yproj = A1*Xproj + B1; |
576 | if ( (DX*(Xproj-PXT) > 0.) && (DY*(Yproj-PYT) > 0.) ) { |
577 | OldRprj = Sqrt ( Square (PXP-PXT) + Square (PYP-PYT) ); |
578 | NewRprj = Sqrt ( Square (Xproj-PXT) + Square (Yproj-PYT) ); |
579 | Rap = NewRprj/OldRprj; |
580 | Rayon = this->Radius(); |
581 | Rayon = Rayon * Rap; |
582 | this->SetRadius(Rayon); |
583 | this->Display(aView,MyTypeOfRepresentation); |
584 | aView->Update(); |
585 | } |
586 | break; |
587 | case V3d_IntRADIUSCAMERA : |
81bba717 |
588 | // It is attempted to preserve the target positioning direction of the |
589 | // camera ==> the point is projected on the target camera direction. |
7fd59977 |
590 | this->Position(Xi,Yi,Zi); |
591 | aView->Project(Xi,Yi,Zi,PXP,PYP); |
592 | DX = PXP - PXT; |
593 | DY = PYP - PYT; |
594 | A1 = DY/DX ; B1 = PYT - A1*PXT; |
595 | A2 = -DX/DY; B2 = YPp - A2*XPp; |
596 | Xproj = (B2 - B1) / (A1 - A2); |
597 | Yproj = A1*Xproj + B1; |
598 | if ( (DX*(Xproj-PXP) < 0.) && (DY*(Yproj-PYP) < 0.) ) { |
599 | OldRprj = Sqrt ( Square (PXP-PXT) + Square (PYP-PYT) ); |
600 | NewRprj = Sqrt ( Square (Xproj-PXP) + Square (Yproj-PYP) ); |
601 | Rap = NewRprj/OldRprj; |
602 | Rayon = this->Radius(); |
603 | Rayon = Rayon * Rap; |
81bba717 |
604 | // the camera should remain at a fixed position, only the target is modified. |
7fd59977 |
605 | Graphic3d_Vector Dir(MyPosition,MyTarget); |
606 | Dir.Normalize(); |
607 | Dir.Coord(X,Y,Z); |
608 | X = Xi + Rayon*X; |
609 | Y = Yi + Rayon*Y; |
610 | Z = Zi + Rayon*Z; |
611 | MyTarget.SetCoord(X,Y,Z); |
612 | this->Display(aView,MyTypeOfRepresentation); |
613 | aView->Update(); |
614 | } |
615 | break; |
616 | case V3d_RADIUSTEXTCAMERA : |
617 | break; |
618 | case V3d_NOTHINGCAMERA : |
619 | break; |
620 | } |
621 | } |
622 | |
623 | void V3d_Camera::AerialPilot( const Handle(V3d_View)& aView, |
624 | const Standard_Integer Xpix, |
625 | const Standard_Integer Ypix) { |
626 | |
627 | Standard_Real Xp,Yp,Zp,Xc,Yc,Zc,Xv,Yv,Zv,Xf,Yf,Zf; |
628 | Standard_Real VX,VY,VZ,DXH,DYH,DZH,A,B,C,PXT,PYT,X1,Y1,Z1,Dist; |
629 | Standard_Real Height,Width,Beta,CosBeta,SinBeta,Coef; |
630 | Standard_Integer IPX,IPY,IHeight,IWidth; |
631 | TColStd_Array2OfReal MatRot(0,2,0,2); |
632 | |
633 | |
634 | MyPosition.Coord(Xp,Yp,Zp); |
635 | MyTarget.Coord(Xc,Yc,Zc); |
636 | aView->At(Xv,Yv,Zv); |
637 | aView->Project(Xv,Yv,Zv,PXT,PYT); |
638 | aView->Convert(PXT,PYT,IPX,IPY); |
81bba717 |
639 | // Find the pitching ==> Xpix = IPX and Ypix inverted |
640 | // The target point turns around an axis passing through the eye and the |
641 | // direction of vector belonging to the view plane |
642 | // and perpendicular to the vector above the view. |
7fd59977 |
643 | if ( Ypix != IPY ) { |
644 | aView->Size(Width,Height); |
645 | IHeight = aView->Convert(Height); |
646 | Beta = ((IPY - Ypix)*Standard_PI)/(IHeight*2.); |
647 | aView->Proj(VX,VY,VZ); |
648 | aView->Up(DXH,DYH,DZH); |
649 | A = VY*DZH - VZ*DYH; |
650 | B = VZ*DXH - VX*DZH; |
651 | C = VX*DYH - VY*DXH; |
652 | Dist = Sqrt( A*A + B*B + C*C); |
653 | A = A/Dist; B = B/Dist; C = C/Dist; |
654 | CosBeta = Cos(Beta); |
655 | SinBeta = Sin(Beta); |
656 | Coef = 1. - CosBeta; |
657 | MatRot(0,0) = A * A + (1. - A * A) * CosBeta; |
658 | MatRot(0,1) = -C * SinBeta + Coef * A * B; |
659 | MatRot(0,2) = B * SinBeta + Coef * A * C; |
660 | MatRot(1,0) = C * SinBeta + Coef * A * B; |
661 | MatRot(1,1) = B * B + (1. - B * B) * CosBeta; |
662 | MatRot(1,2) = -A * SinBeta + Coef * B * C; |
663 | MatRot(2,0) = -B * SinBeta + Coef * A * C; |
664 | MatRot(2,1) = A * SinBeta + Coef * B * C; |
665 | MatRot(2,2) = C * C + (1. - C * C) * CosBeta; |
666 | Xf = Xp * MatRot(0,0) + Yp * MatRot(0,1) + Zp * MatRot(0,2); |
667 | Yf = Xp * MatRot(1,0) + Yp * MatRot(1,1) + Zp * MatRot(1,2); |
668 | Zf = Xp * MatRot(2,0) + Yp * MatRot(2,1) + Zp * MatRot(2,2); |
81bba717 |
669 | // Rotation of the target point (target of the camera) |
7fd59977 |
670 | X1 = Xc * MatRot(0,0) + Yc * MatRot(0,1) + Zc * MatRot(0,2); |
671 | Y1 = Xc * MatRot(1,0) + Yc * MatRot(1,1) + Zc * MatRot(1,2); |
672 | Z1 = Xc * MatRot(2,0) + Yc * MatRot(2,1) + Zc * MatRot(2,2); |
673 | Xc = X1 + Xp - Xf ; Yc = Y1 + Yp - Yf ; Zc = Z1 + Zp - Zf; |
674 | MyTarget.SetCoord(Xc,Yc,Zc); |
675 | } |
81bba717 |
676 | // Find the rolling determined by Xpix |
7fd59977 |
677 | if ( Xpix != IPX ) { |
678 | IWidth = aView->Convert(Width); |
679 | Beta = ((IPX - Xpix)*Standard_PI)/(IWidth*2.); |
680 | MyAngle = MyAngle + Beta; |
681 | } |
682 | } |
683 | |
684 | |
685 | void V3d_Camera::EarthPilot( const Handle(V3d_View)& aView, |
686 | const Standard_Integer Xpix, |
687 | const Standard_Integer Ypix) { |
81bba717 |
688 | // Piloting in land mode, resembles to the car driving |
689 | // In this case, only the target point is modified. |
7fd59977 |
690 | |
691 | Standard_Real Xp,Yp,Zp,Xc,Yc,Zc,Xv,Yv,Zv,Xf,Yf,Zf; |
692 | Standard_Real VX,VY,VZ,DXH,DYH,DZH,A,B,C,PXT,PYT,X1,Y1,Z1,Dist; |
693 | Standard_Real Height,Width,Beta,CosBeta,SinBeta,Coef; |
694 | Standard_Integer IPX,IPY,IHeight,IWidth; |
695 | TColStd_Array2OfReal MatRot(0,2,0,2); |
696 | |
697 | MyPosition.Coord(Xp,Yp,Zp); |
698 | MyTarget.Coord(Xc,Yc,Zc); |
699 | aView->At(Xv,Yv,Zv); |
700 | aView->Project(Xv,Yv,Zv,PXT,PYT); |
701 | aView->Convert(PXT,PYT,IPX,IPY); |
81bba717 |
702 | // Find the pitching ==> Xpix = IPX and Ypix inverted |
703 | // The target point turns around an axis passing through the eye and the |
704 | // direction of vector belonging to the view plane |
705 | // and perpendicular to the vector above the view. |
7fd59977 |
706 | if ( Ypix != IPY ) { |
707 | aView->Size(Width,Height); |
708 | IHeight = aView->Convert(Height); |
709 | Beta = ((IPY - Ypix)*Standard_PI)/(IHeight*2.); |
710 | aView->Proj(VX,VY,VZ); |
711 | aView->Up(DXH,DYH,DZH); |
712 | A = VY*DZH - VZ*DYH; |
713 | B = VZ*DXH - VX*DZH; |
714 | C = VX*DYH - VY*DXH; |
715 | Dist = Sqrt( A*A + B*B + C*C); |
716 | A = A/Dist; B = B/Dist; C = C/Dist; |
717 | CosBeta = Cos(Beta); |
718 | SinBeta = Sin(Beta); |
719 | Coef = 1. - CosBeta; |
720 | MatRot(0,0) = A * A + (1. - A * A) * CosBeta; |
721 | MatRot(0,1) = -C * SinBeta + Coef * A * B; |
722 | MatRot(0,2) = B * SinBeta + Coef * A * C; |
723 | MatRot(1,0) = C * SinBeta + Coef * A * B; |
724 | MatRot(1,1) = B * B + (1. - B * B) * CosBeta; |
725 | MatRot(1,2) = -A * SinBeta + Coef * B * C; |
726 | MatRot(2,0) = -B * SinBeta + Coef * A * C; |
727 | MatRot(2,1) = A * SinBeta + Coef * B * C; |
728 | MatRot(2,2) = C * C + (1. - C * C) * CosBeta; |
729 | Xf = Xp * MatRot(0,0) + Yp * MatRot(0,1) + Zp * MatRot(0,2); |
730 | Yf = Xp * MatRot(1,0) + Yp * MatRot(1,1) + Zp * MatRot(1,2); |
731 | Zf = Xp * MatRot(2,0) + Yp * MatRot(2,1) + Zp * MatRot(2,2); |
81bba717 |
732 | // Rotation of the target point (target of the camera) |
7fd59977 |
733 | X1 = Xc * MatRot(0,0) + Yc * MatRot(0,1) + Zc * MatRot(0,2); |
734 | Y1 = Xc * MatRot(1,0) + Yc * MatRot(1,1) + Zc * MatRot(1,2); |
735 | Z1 = Xc * MatRot(2,0) + Yc * MatRot(2,1) + Zc * MatRot(2,2); |
736 | Xc = X1 + Xp - Xf ; Yc = Y1 + Yp - Yf ; Zc = Z1 + Zp - Zf; |
737 | } |
81bba717 |
738 | // Find turning ==> Ypix = IPY . The target point rotates around |
739 | // an axis // a vector above passing through the eye |
7fd59977 |
740 | if ( Xpix != IPX ) { |
741 | IWidth = aView->Convert(Width); |
742 | Beta = ((IPX - Xpix)*Standard_PI)/(IWidth*2.); |
743 | aView->Up(A,B,C); |
744 | Dist = Sqrt( A*A + B*B + C*C); |
745 | A = A/Dist; B = B/Dist; C = C/Dist; |
746 | CosBeta = Cos(Beta); |
747 | SinBeta = Sin(Beta); |
748 | Coef = 1. - CosBeta; |
749 | MatRot(0,0) = A * A + (1. - A * A) * CosBeta; |
750 | MatRot(0,1) = -C * SinBeta + Coef * A * B; |
751 | MatRot(0,2) = B * SinBeta + Coef * A * C; |
752 | MatRot(1,0) = C * SinBeta + Coef * A * B; |
753 | MatRot(1,1) = B * B + (1. - B * B) * CosBeta; |
754 | MatRot(1,2) = -A * SinBeta + Coef * B * C; |
755 | MatRot(2,0) = -B * SinBeta + Coef * A * C; |
756 | MatRot(2,1) = A * SinBeta + Coef * B * C; |
757 | MatRot(2,2) = C * C + (1. - C * C) * CosBeta; |
758 | Xf = Xp * MatRot(0,0) + Yp * MatRot(0,1) + Zp * MatRot(0,2); |
759 | Yf = Xp * MatRot(1,0) + Yp * MatRot(1,1) + Zp * MatRot(1,2); |
760 | Zf = Xp * MatRot(2,0) + Yp * MatRot(2,1) + Zp * MatRot(2,2); |
81bba717 |
761 | // Rotation of the target point (target of the camera) |
7fd59977 |
762 | X1 = Xc * MatRot(0,0) + Yc * MatRot(0,1) + Zc * MatRot(0,2); |
763 | Y1 = Xc * MatRot(1,0) + Yc * MatRot(1,1) + Zc * MatRot(1,2); |
764 | Z1 = Xc * MatRot(2,0) + Yc * MatRot(2,1) + Zc * MatRot(2,2); |
765 | Xc = X1 + Xp - Xf ; Yc = Y1 + Yp - Yf ; Zc = Z1 + Zp - Zf; |
766 | } |
767 | MyTarget.SetCoord(Xc,Yc,Zc); |
768 | } |
769 | |
770 | void V3d_Camera::Move (const Standard_Real Dist) { |
81bba717 |
771 | // Displacement of the camera by preserving the direction camera - target. |
7fd59977 |
772 | |
773 | Standard_Real XP,YP,ZP,X0,Y0,Z0,DX,DY,DZ,Norme; |
774 | |
775 | MyPosition.Coord(XP,YP,ZP); |
776 | MyTarget.Coord(X0,Y0,Z0); |
777 | DX = X0 - XP; DY = Y0 - YP; DZ = Z0 - ZP; |
778 | Norme = Sqrt(DX*DX + DY*DY + DZ*DZ); |
779 | DX = Dist*DX/Norme; DY = Dist*DY/Norme; DZ = Dist*DZ/Norme; |
780 | XP = XP + DX; YP = YP + DY; ZP = ZP + DZ; |
781 | X0 = X0 + DX; Y0 = Y0 + DY; Z0 = Z0 + DZ; |
782 | MyPosition.SetCoord(XP,YP,ZP); |
783 | MyTarget.SetCoord(X0,Y0,Z0); |
784 | } |
785 | |
786 | void V3d_Camera::GoUp (const Standard_Real Haut) { |
787 | |
81bba717 |
788 | // Displacement of the camera by axis z, preserving the direction camera - |
789 | // target of the camera |
7fd59977 |
790 | |
791 | MyPosition.SetZCoord(MyPosition.Z()+Haut); |
792 | MyTarget.SetZCoord(MyTarget.Z()+Haut); |
793 | } |
794 | |
795 | void V3d_Camera::SymetricPointOnSphere (const Handle(V3d_View)& aView, const Graphic3d_Vertex &Center, const Graphic3d_Vertex &aPoint, const Standard_Real Rayon, Standard_Real& X, Standard_Real& Y, Standard_Real& Z, Standard_Real& VX, Standard_Real& VY, Standard_Real& VZ ) { |
796 | |
797 | Standard_Real X0,Y0,Z0,XP,YP,ZP; |
798 | Standard_Real PXP,PYP,DeltaX,DeltaY,DeltaZ; |
799 | Standard_Real A,B,C,Delta,Lambda; |
800 | Standard_Integer IPX,IPY; |
801 | |
802 | Center.Coord(X0,Y0,Z0); |
803 | aPoint.Coord(XP,YP,ZP); |
804 | aView->Project(XP,YP,ZP,PXP,PYP); |
805 | aView->Convert(PXP,PYP,IPX,IPY); |
806 | aView->ProjReferenceAxe(IPX,IPY,X,Y,Z,VX,VY,VZ); |
807 | DeltaX = X0 - XP; |
808 | DeltaY = Y0 - YP; |
809 | DeltaZ = Z0 - ZP; |
810 | |
81bba717 |
811 | // The point of intersection of straight lines defined by : |
812 | // - Straight line passing by the point of projection and the eye |
813 | // if this is a perspective, parallel to the normal of the |
814 | // view if there is an axonometric view. |
815 | // position in the view is parallel to the normal of the view |
816 | // - The distance position of the target camera cible is equal |
817 | // to the radius. |
7fd59977 |
818 | |
819 | A = VX*VX + VY*VY + VZ*VZ ; |
820 | B = -2. * (VX*DeltaX + VY*DeltaY + VZ*DeltaZ); |
821 | C = DeltaX*DeltaX + DeltaY*DeltaY + DeltaZ*DeltaZ |
822 | - Rayon*Rayon ; |
823 | Delta = B*B - 4.*A*C; |
824 | if ( Delta >= 0 ) { |
825 | Lambda = (-B + Sqrt(Delta))/(2.*A); |
826 | if ( Lambda >= -0.0001 && Lambda <= 0.0001 ) |
827 | Lambda = (-B - Sqrt(Delta))/(2.*A); |
828 | X = XP + Lambda*VX; |
829 | Y = YP + Lambda*VY; |
830 | Z = ZP + Lambda*VZ; |
831 | } |
832 | else { |
833 | X = XP; Y = YP; Z = ZP; |
834 | } |
835 | } |