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