Commit | Line | Data |
---|---|---|
7fd59977 | 1 | /*********************************************************************** |
2 | ||
3 | V3d_PositionLight.cxx | |
4 | Created: 30-03-98 ZOV (ZELENKOV Oleg) | |
5 | ||
6 | ************************************************************************/ | |
7 | ||
8 | #include <V3d.hxx> | |
9 | #include <V3d_PositionLight.ixx> | |
10 | #include <Graphic3d_Vector.hxx> | |
11 | #include <Graphic3d_Vertex.hxx> | |
12 | #include <Graphic3d_Structure.hxx> | |
13 | #include <Graphic3d_Group.hxx> | |
14 | #include <Graphic3d_Array1OfVertex.hxx> | |
15 | #include <Graphic3d_AspectMarker3d.hxx> | |
16 | #include <Graphic3d_AspectLine3d.hxx> | |
17 | #include <Graphic3d_AspectText3d.hxx> | |
18 | #include <V3d_SpotLight.hxx> | |
19 | #include <Visual3d_Light.hxx> | |
20 | #include <Visual3d_ViewManager.hxx> | |
21 | #include <Visual3d_ContextPick.hxx> | |
22 | #include <Visual3d_PickDescriptor.hxx> | |
23 | #include <Visual3d_HSequenceOfPickPath.hxx> | |
24 | #include <Visual3d_PickPath.hxx> | |
25 | #include <Viewer_BadValue.hxx> | |
26 | #include <gp_Dir.hxx> | |
27 | #include <gp_Ax1.hxx> | |
28 | #include <gp_Vec.hxx> | |
29 | #include <gp_Pnt.hxx> | |
30 | #include <gp_Trsf.hxx> | |
31 | #include <TCollection_AsciiString.hxx> | |
32 | #ifdef WNT | |
33 | # include <WNT_Window.hxx> | |
34 | #else | |
35 | # include <Xw_Window.hxx> | |
36 | #endif | |
37 | ||
38 | V3d_PositionLight::V3d_PositionLight(const Handle(V3d_Viewer)& VM) : V3d_Light(VM) { | |
39 | } | |
40 | ||
41 | void V3d_PositionLight::SetTarget(const Standard_Real X, const Standard_Real Y, const Standard_Real Z) { | |
42 | ||
43 | Standard_Real Xc,Yc,Zc, Xp,Yp,Zp; | |
44 | ||
81bba717 | 45 | // Recalculation of the position |
7fd59977 | 46 | MyTarget.Coord(Xc,Yc,Zc); |
47 | Position (Xp,Yp,Zp) ; | |
48 | ||
49 | Xp = Xp + (X - Xc); | |
50 | Yp = Yp + (Y - Yc); | |
51 | Zp = Zp + (Z - Zc); | |
52 | ||
53 | // Affectation | |
54 | MyTarget.SetCoord(X,Y,Z); | |
55 | SetPosition(Xp,Yp,Zp) ; | |
56 | } | |
57 | ||
58 | void V3d_PositionLight::SetRadius(const Standard_Real Radius) { | |
59 | ||
60 | Viewer_BadValue_Raise_if( Radius <= 0. , "V3d_PositionLight::SetRadius, bad radius"); | |
61 | Viewer_BadValue_Raise_if( MyType == V3d_DIRECTIONAL , "V3d_PositionLight::SetRadius, bad light type"); | |
62 | ||
63 | Standard_Real X0,Y0,Z0, Xn,Yn,Zn, Xp,Yp,Zp; | |
64 | ||
81bba717 | 65 | // The target point remains unchanged, only the position of the light is modified |
66 | // by preserving the direction. | |
7fd59977 | 67 | Position (Xp,Yp,Zp); |
68 | Graphic3d_Vector D(MyTarget, Graphic3d_Vertex(Xp, Yp, Zp)); | |
69 | D.Normalize(); | |
70 | D.Coord(Xn,Yn,Zn); | |
71 | MyTarget.Coord(X0,Y0,Z0); | |
72 | Xn = X0 + Radius*Xn; | |
73 | Yn = Y0 + Radius*Yn; | |
74 | Zn = Z0 + Radius*Zn; | |
75 | ||
76 | SetPosition(Xn,Yn,Zn) ; | |
77 | } | |
78 | ||
79 | void V3d_PositionLight::OnHideFace(const Handle(V3d_View)& aView) { | |
80 | ||
81 | Standard_Real Xp,Yp,Zp, X,Y,Z, VX,VY,VZ; | |
82 | ||
83 | Position (Xp,Yp,Zp); | |
84 | V3d_Light::SymetricPointOnSphere (aView, | |
85 | MyTarget, Graphic3d_Vertex(Xp,Yp,Yp), Radius(), X,Y,Z, VX,VY,VZ); | |
86 | ||
81bba717 | 87 | // This is a visible point |
7fd59977 | 88 | if ((VX*(X-Xp) < 0.) && (VY*(Y-Yp) < 0.) && (VZ*(Z-Zp) < 0.)) |
89 | SetPosition (X,Y,Z); | |
90 | } | |
91 | ||
92 | void V3d_PositionLight::OnSeeFace(const Handle(V3d_View)& aView) { | |
93 | ||
94 | Standard_Real Xp,Yp,Zp, X,Y,Z, VX,VY,VZ; | |
95 | ||
96 | Position (Xp,Yp,Zp); | |
97 | V3d_Light::SymetricPointOnSphere (aView, | |
98 | MyTarget, Graphic3d_Vertex(Xp,Yp,Yp), Radius(), X,Y,Z, VX,VY,VZ); | |
99 | ||
81bba717 | 100 | // This is a hidden point |
7fd59977 | 101 | if ((VX*(X-Xp) > 0.) && (VY*(Y-Yp) > 0.) && (VZ*(Z-Zp) > 0.)) |
102 | SetPosition (X,Y,Z); | |
103 | } | |
104 | ||
105 | Standard_Boolean V3d_PositionLight::SeeOrHide(const Handle(V3d_View)& aView) const { | |
106 | ||
107 | Standard_Real Xp,Yp,Zp, X,Y,Z, VX,VY,VZ; | |
108 | ||
109 | Position (Xp,Yp,Zp); | |
110 | V3d_Light::SymetricPointOnSphere (aView, | |
111 | MyTarget, Graphic3d_Vertex(Xp,Yp,Yp), Radius(), X,Y,Z, VX,VY,VZ); | |
112 | ||
81bba717 | 113 | // Is it a visible or a hidden point |
7fd59977 | 114 | return ( (VX*(X-Xp) > 0.) || (VY*(Y-Yp) > 0.) || (VZ*(Z-Zp) > 0.) )? |
81bba717 | 115 | // the source is on the hidden face |
7fd59977 | 116 | Standard_False: |
81bba717 | 117 | // the source is on the visible face. |
7fd59977 | 118 | Standard_True; |
119 | } | |
120 | ||
121 | void V3d_PositionLight::Target(Standard_Real& Xp, Standard_Real& Yp, Standard_Real& Zp)const { | |
122 | ||
123 | MyTarget.Coord(Xp,Yp,Zp) ; | |
124 | } | |
125 | ||
126 | void V3d_PositionLight::Display( const Handle(V3d_View)& aView, | |
127 | const V3d_TypeOfRepresentation TPres ) { | |
128 | ||
129 | Graphic3d_Array1OfVertex PRadius(0,1); | |
130 | Graphic3d_Vertex PText ; | |
131 | Standard_Real X,Y,Z,Rayon; | |
132 | Standard_Real X0,Y0,Z0,VX,VY,VZ; | |
133 | Standard_Real X1,Y1,Z1; | |
134 | Standard_Real DXRef,DYRef,DZRef,DXini,DYini,DZini; | |
135 | Standard_Real R1,G1,B1; | |
136 | V3d_TypeOfRepresentation Pres; | |
137 | V3d_TypeOfUpdate UpdSov; | |
138 | ||
81bba717 | 139 | // Creation of a structure of markable elements (position of the |
140 | // light, and the domain of lighting represented by a circle) | |
141 | // Creation of a structure snopick of non-markable elements (target, meridian and | |
142 | // parallel). | |
143 | ||
7fd59977 | 144 | |
145 | Pres = TPres; | |
146 | Handle(V3d_Viewer) TheViewer = aView->Viewer(); | |
147 | UpdSov = TheViewer->UpdateMode(); | |
148 | TheViewer->SetUpdateMode(V3d_WAIT); | |
149 | if (!MyGraphicStructure.IsNull()) { | |
150 | MyGraphicStructure->Disconnect(MyGraphicStructure1); | |
151 | MyGraphicStructure->Clear(); | |
152 | MyGraphicStructure1->Clear(); | |
153 | if (Pres == V3d_SAMELAST) Pres = MyTypeOfRepresentation; | |
154 | } | |
155 | else { | |
156 | if (Pres == V3d_SAMELAST) Pres = V3d_SIMPLE; | |
157 | Handle(Graphic3d_Structure) slight = new Graphic3d_Structure(TheViewer->Viewer()); | |
158 | MyGraphicStructure = slight; | |
159 | Handle(Graphic3d_Structure) snopick = new Graphic3d_Structure(TheViewer->Viewer()); | |
160 | MyGraphicStructure1 = snopick; | |
161 | } | |
162 | ||
163 | ||
164 | Handle(Graphic3d_Group) gradius; | |
165 | Handle(Graphic3d_Group) gExtArrow; | |
166 | Handle(Graphic3d_Group) gIntArrow; | |
167 | ||
168 | if (MyType != V3d_DIRECTIONAL) { | |
169 | if (Pres == V3d_COMPLETE) { | |
170 | gradius = new Graphic3d_Group(MyGraphicStructure); | |
171 | gExtArrow = new Graphic3d_Group(MyGraphicStructure); | |
172 | gIntArrow = new Graphic3d_Group(MyGraphicStructure); | |
173 | } | |
174 | } | |
175 | Handle(Graphic3d_Group) glight = new Graphic3d_Group(MyGraphicStructure); | |
176 | Handle(Graphic3d_Group) gsphere; | |
177 | if (Pres == V3d_COMPLETE || Pres == V3d_PARTIAL) gsphere = new Graphic3d_Group(MyGraphicStructure); | |
178 | ||
179 | Handle(Graphic3d_Group) gnopick = new Graphic3d_Group(MyGraphicStructure1); | |
180 | MyGraphicStructure1->SetPick(Standard_False); | |
181 | ||
182 | X0 = MyTarget.X(); | |
183 | Y0 = MyTarget.Y(); | |
184 | Z0 = MyTarget.Z(); | |
185 | ||
81bba717 | 186 | // Display of the light position. |
7fd59977 | 187 | |
7fd59977 | 188 | this->Color(Quantity_TOC_RGB,R1,G1,B1); |
189 | Quantity_Color Col1(R1,G1,B1,Quantity_TOC_RGB); | |
190 | Handle(Graphic3d_AspectLine3d) Asp1 = new Graphic3d_AspectLine3d(); | |
191 | Asp1->SetColor(Col1); | |
192 | glight->SetPrimitivesAspect(Asp1); | |
193 | this->Symbol(glight,aView); | |
194 | ||
81bba717 | 195 | // Display of the marking sphere (limit at the circle). |
7fd59977 | 196 | |
197 | if (Pres == V3d_COMPLETE || Pres == V3d_PARTIAL) { | |
198 | ||
199 | Rayon = this->Radius(); | |
200 | aView->Proj(VX,VY,VZ); | |
7fd59977 | 201 | V3d::CircleInPlane(gsphere,X0,Y0,Z0,VX,VY,VZ,Rayon); |
202 | ||
203 | ||
204 | if (MyType != V3d_DIRECTIONAL) { | |
205 | ||
81bba717 | 206 | //Display of the radius of the sphere (line + text) |
7fd59977 | 207 | |
208 | if (Pres == V3d_COMPLETE) { | |
7fd59977 | 209 | PRadius(0).SetCoord(X0,Y0,Z0); |
210 | this->Position(X,Y,Z); | |
211 | PRadius(1).SetCoord(X,Y,Z); | |
212 | gnopick->Polyline(PRadius); | |
213 | V3d::ArrowOfRadius(gExtArrow,X-(X-X0)/10., | |
214 | Y-(Y-Y0)/10., | |
c6541a0c D |
215 | Z-(Z-Z0)/10.,X-X0,Y-Y0,Z-Z0,M_PI/15.,Rayon/20.); |
216 | V3d::ArrowOfRadius(gIntArrow,X0,Y0,Z0,X0-X,Y0-Y,Z0-Z,M_PI/15.,Rayon/20.); | |
7fd59977 | 217 | TCollection_AsciiString ValOfRadius(Rayon); |
218 | PText.SetCoord( (X0+X)/2., (Y0+Y)/2. , (Z0+Z)/2. ); | |
219 | gradius->Text(ValOfRadius.ToCString(),PText,0.01); | |
220 | } | |
221 | } | |
222 | ||
223 | ||
81bba717 | 224 | // Display of the meridian |
7fd59977 | 225 | |
226 | Quantity_Color Col2(Quantity_NOC_GREEN); | |
227 | Handle(Graphic3d_AspectLine3d) Asp2 = new Graphic3d_AspectLine3d | |
228 | (Col2,Aspect_TOL_SOLID,1.); | |
229 | gnopick->SetPrimitivesAspect(Asp2); | |
230 | ||
81bba717 | 231 | // Definition of the axis of circle |
7fd59977 | 232 | aView->Up(DXRef,DYRef,DZRef); |
233 | this->Position(X,Y,Z); | |
234 | DXini = X-X0; DYini = Y-Y0; DZini = Z-Z0; | |
235 | VX = DYRef*DZini - DZRef*DYini; | |
236 | VY = DZRef*DXini - DXRef*DZini; | |
237 | VZ = DXRef*DYini - DYRef*DXini; | |
238 | ||
239 | V3d::CircleInPlane(gnopick,X0,Y0,Z0,VX,VY,VZ,Rayon); | |
240 | ||
81bba717 | 241 | // Display of the parallel |
7fd59977 | 242 | |
81bba717 | 243 | // Definition of the axis of circle |
7fd59977 | 244 | aView->Proj(VX,VY,VZ); |
245 | aView->Up(X1,Y1,Z1); | |
246 | DXRef = VY * Z1 - VZ * Y1; | |
247 | DYRef = VZ * X1 - VX * Z1; | |
248 | DZRef = VX * Y1 - VY * X1; | |
249 | this->Position(X,Y,Z); | |
250 | DXini = X-X0; DYini = Y-Y0; DZini = Z-Z0; | |
251 | VX = DYRef*DZini - DZRef*DYini; | |
252 | VY = DZRef*DXini - DXRef*DZini; | |
253 | VZ = DXRef*DYini - DYRef*DXini; | |
254 | ||
255 | V3d::CircleInPlane(gnopick,X0,Y0,Z0,VX,VY,VZ,Rayon); | |
256 | } | |
257 | ||
258 | MyGraphicStructure->Connect(MyGraphicStructure1,Graphic3d_TOC_DESCENDANT); | |
259 | MyTypeOfRepresentation = Pres; | |
260 | MyGraphicStructure->Display(); | |
261 | TheViewer->SetUpdateMode(UpdSov); | |
262 | } | |
263 | ||
7fd59977 | 264 | |
265 | void V3d_PositionLight::Tracking( const Handle(V3d_View)& aView, | |
266 | const V3d_TypeOfPickLight WhatPick, | |
267 | const Standard_Integer Xpix, | |
268 | const Standard_Integer Ypix) { | |
269 | ||
270 | // Quantity_Color Col ; | |
271 | Standard_Real xPos, yPos, zPos; | |
272 | Standard_Real XPp,YPp,PXT,PYT,X,Y,Z,Rayon,Ylim; | |
273 | Standard_Real XMinTrack,XMaxTrack,YMinTrack,YMaxTrack; | |
274 | Standard_Real XT,YT,ZT,X0,Y0,Z0,XP,YP,ZP,VX,VY,VZ,A,B,C,Delta; | |
275 | Standard_Real DX,DY,PXP,PYP,Xproj,Yproj; | |
276 | Standard_Real A1,A2,B1,B2,Rap,OldRprj,NewRprj; | |
277 | Standard_Real Xi,Yi,Zi,DeltaX,DeltaY,DeltaZ,Lambda; | |
278 | Standard_Integer IPX,IPY; | |
279 | ||
280 | aView->Convert(Xpix,Ypix,XPp,YPp); | |
281 | X0 = MyTarget.X(); | |
282 | Y0 = MyTarget.Y(); | |
283 | Z0 = MyTarget.Z(); | |
284 | aView->Project(X0,Y0,Z0,PXT,PYT); | |
285 | aView->Convert(PXT,PYT,IPX,IPY); | |
81bba717 | 286 | // Coord 3d in the plane of projection of the target. |
7fd59977 | 287 | aView->Convert(IPX,IPY,XT,YT,ZT); |
288 | switch (WhatPick) { | |
289 | case V3d_POSITIONLIGHT : | |
81bba717 | 290 | // The Coordinates should remain inside of the sphere |
7fd59977 | 291 | Rayon = Radius(); |
292 | XMinTrack = PXT - Rayon; | |
293 | XMaxTrack = PXT + Rayon; | |
294 | Ylim = Sqrt( Square(Rayon) - Square(XPp - PXT) ); | |
295 | YMinTrack = PYT - Ylim; | |
296 | YMaxTrack = PYT + Ylim; | |
297 | if (XPp >= XMinTrack && XPp <= XMaxTrack) { | |
298 | if (YPp >= YMinTrack && YPp <= YMaxTrack) { | |
299 | aView->ProjReferenceAxe(Xpix,Ypix,XP,YP,ZP,VX,VY,VZ); | |
300 | DeltaX = X0 - XP; | |
301 | DeltaY = Y0 - YP; | |
302 | DeltaZ = Z0 - ZP; | |
303 | ||
81bba717 | 304 | // The point of intersection of straight lines defined by : |
305 | // - Straight line passing by the point of projection and the eye | |
306 | // if this is a perspective, parralel to the normal of the view | |
307 | // if this is an axonometric view. | |
308 | // position in the view is parallel to the normal of the view | |
309 | // - The distance position of the target camera is equal to the radius. | |
7fd59977 | 310 | |
311 | A = VX*VX + VY*VY + VZ*VZ ; | |
312 | B = -2. * (VX*DeltaX + VY*DeltaY + VZ*DeltaZ); | |
313 | C = DeltaX*DeltaX + DeltaY*DeltaY + DeltaZ*DeltaZ | |
314 | - Rayon*Rayon ; | |
315 | Delta = B*B - 4.*A*C; | |
316 | if ( Delta >= 0 ) { | |
317 | Lambda = (-B + Sqrt(Delta))/(2.*A); | |
318 | X = XP + Lambda*VX; | |
319 | Y = YP + Lambda*VY; | |
320 | Z = ZP + Lambda*VZ; | |
321 | SetPosition(X,Y,Z); | |
322 | ||
323 | if (MyType == V3d_SPOT) | |
324 | ((V3d_SpotLight*)this)->SetDirection(X0-X,Y0-Y,Z0-Z); | |
325 | ||
326 | Display(aView,MyTypeOfRepresentation); | |
327 | (aView->Viewer())->UpdateLights(); | |
328 | } | |
329 | } | |
330 | } | |
331 | break; | |
332 | ||
333 | case V3d_SPACELIGHT : | |
334 | aView->Convert(PXT,PYT,IPX,IPY); | |
81bba717 | 335 | // In this case Xpix,Ypix correspond to a distance, relative |
336 | // to the translation that is planned to be performed on the sphere. | |
7fd59977 | 337 | aView->Convert(IPX+Xpix,IPY+Ypix,X,Y,Z); |
338 | X = X+X0-XT; | |
339 | Y = Y+Y0-YT; | |
340 | Z = Z+Z0-ZT; | |
341 | SetTarget(X,Y,Z); | |
342 | Display(aView,MyTypeOfRepresentation); | |
343 | (aView->Viewer())->UpdateLights(); | |
344 | break; | |
345 | ||
346 | case V3d_ExtRADIUSLIGHT : | |
347 | if (MyType == V3d_DIRECTIONAL) | |
348 | break; | |
81bba717 | 349 | // it is attempted to preserve the target direction position of the |
350 | // source ==> the point is projected on the target source direction. | |
7fd59977 | 351 | this->Position(Xi,Yi,Zi); |
352 | aView->Project(Xi,Yi,Zi,PXP,PYP); | |
353 | DX = PXP - PXT; | |
354 | DY = PYP - PYT; | |
355 | A1 = DY/DX ; B1 = PYT - A1*PXT; | |
356 | A2 = -DX/DY; B2 = YPp - A2*XPp; | |
357 | Xproj = (B2 - B1) / (A1 - A2); | |
358 | Yproj = A1*Xproj + B1; | |
359 | if ( (DX*(Xproj-PXT) > 0.) && (DY*(Yproj-PYT) > 0.) ) { | |
360 | OldRprj = Sqrt ( Square (PXP-PXT) + Square (PYP-PYT) ); | |
361 | NewRprj = Sqrt ( Square (Xproj-PXT) + Square (Yproj-PYT) ); | |
362 | Rap = NewRprj/OldRprj; | |
363 | Rayon = Radius(); | |
364 | Rayon = Rayon * Rap; | |
365 | SetRadius(Rayon); | |
366 | Display(aView,MyTypeOfRepresentation); | |
367 | (aView->Viewer())->UpdateLights(); | |
368 | } | |
369 | break; | |
370 | ||
371 | case V3d_IntRADIUSLIGHT : | |
372 | if (MyType == V3d_DIRECTIONAL) | |
373 | break; | |
81bba717 | 374 | // it is attempted to preserve the target direction position of the |
375 | // source ==> the point is projected on the target source direction. | |
7fd59977 | 376 | Position(Xi,Yi,Zi); |
377 | aView->Project(Xi,Yi,Zi,PXP,PYP); | |
378 | DX = PXP - PXT; | |
379 | DY = PYP - PYT; | |
380 | A1 = DY/DX ; B1 = PYT - A1*PXT; | |
381 | A2 = -DX/DY; B2 = YPp - A2*XPp; | |
382 | Xproj = (B2 - B1) / (A1 - A2); | |
383 | Yproj = A1*Xproj + B1; | |
384 | if ( (DX*(Xproj-PXP) < 0.) && (DY*(Yproj-PYP) < 0.) ) { | |
385 | OldRprj = Sqrt ( Square (PXP-PXT) + Square (PYP-PYT) ); | |
386 | NewRprj = Sqrt ( Square (Xproj-PXP) + Square (Yproj-PYP) ); | |
387 | Rap = NewRprj/OldRprj; | |
388 | Rayon = Radius(); | |
389 | Rayon = Rayon * Rap; | |
81bba717 | 390 | // the source should remain at a fixed position, |
391 | // only the target is modified. | |
7fd59977 | 392 | Position (xPos, yPos, zPos); |
393 | Graphic3d_Vector Dir(Graphic3d_Vertex(xPos,yPos,zPos), MyTarget); | |
394 | Dir.Normalize(); | |
395 | Dir.Coord(X,Y,Z); | |
396 | X = Xi + Rayon*X; | |
397 | Y = Yi + Rayon*Y; | |
398 | Z = Zi + Rayon*Z; | |
81bba717 | 399 | // the source should remain at a fixed position, |
400 | // only the target is modified. | |
7fd59977 | 401 | MyTarget.SetCoord(X,Y,Z); |
402 | Display(aView,MyTypeOfRepresentation); | |
403 | (aView->Viewer())->UpdateLights(); | |
404 | } | |
405 | break; | |
406 | ||
407 | case V3d_RADIUSTEXTLIGHT : | |
408 | break; | |
409 | ||
410 | case V3d_NOTHING : | |
411 | break; | |
412 | } | |
413 | } | |
414 | ||
415 | Standard_Real V3d_PositionLight::Radius() const { | |
416 | ||
417 | Standard_Real Xp,Yp,Zp, Xc,Yc,Zc; | |
418 | ||
419 | Position (Xp,Yp,Zp); | |
420 | MyTarget.Coord(Xc,Yc,Zc); | |
421 | ||
422 | return Sqrt (Square(Xc - Xp) + Square(Yc - Yp) + Square(Zc - Zp)); | |
423 | } | |
424 | ||
425 | void V3d_PositionLight::Erase() { | |
426 | ||
427 | if (!MyGraphicStructure.IsNull()) MyGraphicStructure->Erase(); | |
428 | if (!MyGraphicStructure1.IsNull()) MyGraphicStructure1->Erase(); | |
429 | } | |
430 |