0025624: Visualization - selection is incorrect in perspective mode in a specific...
[occt.git] / src / Select3D / Select3D_Projector.cxx
CommitLineData
b311480e 1// Created on: 1992-03-13
2// Created by: Christophe MARION
3// Copyright (c) 1992-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
7fd59977 17#include <Select3D_Projector.ixx>
18#include <Precision.hxx>
19#include <gp_Ax3.hxx>
20#include <gp_Vec.hxx>
21#include <gp_Vec2d.hxx>
197ac94e 22#include <gp_Mat.hxx>
23#include <Graphic3d_Vec4.hxx>
24
25namespace
26{
27 //=======================================================================
28 //function : TrsfType
29 //purpose :
30 //=======================================================================
31 static Standard_Integer TrsfType(const gp_GTrsf& theTrsf)
32 {
33 const gp_Mat& aMat = theTrsf.VectorialPart();
34 if ((Abs (aMat.Value (1, 1) - 1.0) < 1e-15)
35 && (Abs (aMat.Value (2, 2) - 1.0) < 1e-15)
36 && (Abs (aMat.Value (3, 3) - 1.0) < 1e-15))
37 {
38 return 1; // top
39 }
40 else if ((Abs (aMat.Value (1, 1) - 0.7071067811865476) < 1e-15)
41 && (Abs (aMat.Value (1, 2) + 0.5) < 1e-15)
42 && (Abs (aMat.Value (1, 3) - 0.5) < 1e-15)
43 && (Abs (aMat.Value (2, 1) - 0.7071067811865476) < 1e-15)
44 && (Abs (aMat.Value (2, 2) - 0.5) < 1e-15)
45 && (Abs (aMat.Value (2, 3) + 0.5) < 1e-15)
46 && (Abs (aMat.Value (3, 1)) < 1e-15)
47 && (Abs (aMat.Value (3, 2) - 0.7071067811865476) < 1e-15)
48 && (Abs (aMat.Value (3, 3) - 0.7071067811865476) < 1e-15))
49 {
50 return 0; // inverse axo
51 }
52 else if ((Abs (aMat.Value (1, 1) - 1.0) < 1e-15)
53 && (Abs (aMat.Value (2, 3) - 1.0) < 1e-15)
54 && (Abs (aMat.Value (3, 2) + 1.0) < 1e-15))
55 {
56 return 2; // front
57 }
58 else if ((Abs (aMat.Value (1, 1) - 0.7071067811865476) < 1e-15)
59 && (Abs (aMat.Value (1, 2) - 0.7071067811865476) < 1e-15)
60 && (Abs (aMat.Value (1, 3)) < 1e-15)
61 && (Abs (aMat.Value (2, 1) + 0.5) < 1e-15)
62 && (Abs (aMat.Value (2, 2) - 0.5) < 1e-15)
63 && (Abs (aMat.Value (2, 3) - 0.7071067811865476) < 1e-15)
64 && (Abs (aMat.Value (3, 1) - 0.5) < 1e-15)
65 && (Abs (aMat.Value (3, 2) + 0.5) < 1e-15)
66 && (Abs (aMat.Value (3, 3) - 0.7071067811865476) < 1e-15))
67 {
68 return 3; // axo
69 }
70
71 return -1;
72 }
73
74 //====== TYPE 0 (inverse axonometric)
75 // (0.7071067811865476, -0.5 , 0.4999999999999999)
76 // (0.7071067811865475, 0.5000000000000001, -0.5 )
77 // (0.0, 0.7071067811865475, 0.7071067811865476)
78
79 // ====== TYPE 1 (top)
80 // (1.0, 0.0, 0.0)
81 // (0.0, 1.0, 0.0)
82 // (0.0, 0.0, 1.0)
83
84 // ======= TYPE 2 (front)
85 // (1.0, 0.0 , 0.0)
86 // (0.0, 1.110223024625157e-16 , 1.0)
87 // (0.0, -1.0 , 1.110223024625157e-16)
88
89 // ======= TYPE 3 (axonometric)
90 // ( 0.7071067811865476, 0.7071067811865475, 0.0)
91 // (-0.5 , 0.5000000000000001, 0.7071067811865475)
92 // ( 0.4999999999999999, -0.5 , 0.7071067811865476)
93}
7fd59977 94
95// formula for derivating a perspective, from Mathematica
96
4952a30a 97// X'[t] X[t] Z'[t]
98// D1 = -------- + -------------
99// Z[t] Z[t] 2
100// 1 - ---- f (1 - ----)
101// f f
7fd59977 102
103//=======================================================================
104//function : Select3D_Projector
4952a30a 105//purpose :
7fd59977 106//=======================================================================
197ac94e 107Select3D_Projector::Select3D_Projector (const Handle(V3d_View)& theView)
108: myPersp (Standard_False),
109 myFocus (0.0),
42b96b07 110 myZNear (0.0),
111 myZFar (10.0),
197ac94e 112 myType (-1)
7fd59977 113{
197ac94e 114 SetView (theView);
7fd59977 115}
116
4952a30a 117//=======================================================================
118//function : Select3D_Projector
119//purpose :
120//=======================================================================
4952a30a 121Select3D_Projector::Select3D_Projector()
197ac94e 122: myPersp (Standard_False),
123 myFocus (0.0),
42b96b07 124 myZNear (0.0),
125 myZFar (10.0),
197ac94e 126 myType (-1)
7fd59977 127{
128 Scaled();
4952a30a 129}
7fd59977 130
131//=======================================================================
132//function : Select3D_Projector
4952a30a 133//purpose :
7fd59977 134//=======================================================================
197ac94e 135Select3D_Projector::Select3D_Projector (const gp_Ax2& theCS)
136: myPersp (Standard_False),
137 myFocus (0.0),
42b96b07 138 myZNear (0.0),
139 myZFar (10.0),
197ac94e 140 myType (-1)
7fd59977 141{
197ac94e 142 myScaledTrsf.SetTransformation (theCS);
143 myGTrsf.SetTrsf (myScaledTrsf);
7fd59977 144 Scaled();
7fd59977 145}
146
147//=======================================================================
148//function : Select3D_Projector
4952a30a 149//purpose :
7fd59977 150//=======================================================================
197ac94e 151Select3D_Projector::Select3D_Projector (const gp_Ax2& theCS, const Standard_Real theFocus)
152: myPersp (Standard_True),
153 myFocus (theFocus),
42b96b07 154 myZNear (0.0),
155 myZFar (10.0),
197ac94e 156 myType (-1)
7fd59977 157{
197ac94e 158 myScaledTrsf.SetTransformation (theCS);
159 myGTrsf.SetTrsf (myScaledTrsf);
7fd59977 160 Scaled();
7fd59977 161}
162
163//=======================================================================
164//function : Select3D_Projector
4952a30a 165//purpose :
7fd59977 166//=======================================================================
197ac94e 167Select3D_Projector::Select3D_Projector (const gp_Trsf& theViewTrsf,
168 const Standard_Boolean theIsPersp,
169 const Standard_Real theFocus)
170: myPersp (theIsPersp),
171 myFocus (theFocus),
172 myGTrsf (theViewTrsf),
173 myScaledTrsf (theViewTrsf),
42b96b07 174 myZNear (0.0),
175 myZFar (10.0),
197ac94e 176 myType (-1)
7fd59977 177{
7fd59977 178 Scaled();
7fd59977 179}
180
181//=======================================================================
182//function : Select3D_Projector
4952a30a 183//purpose :
7fd59977 184//=======================================================================
197ac94e 185Select3D_Projector::Select3D_Projector (const gp_GTrsf& theViewTrsf,
186 const Standard_Boolean theIsPersp,
187 const Standard_Real theFocus)
188: myPersp (theIsPersp),
189 myFocus (theFocus),
190 myGTrsf (theViewTrsf),
191 myScaledTrsf (theViewTrsf.Trsf()),
42b96b07 192 myZNear (0.0),
193 myZFar (10.0),
197ac94e 194 myType (-1)
7fd59977 195{
196 Scaled();
7fd59977 197}
198
7fd59977 199//=======================================================================
197ac94e 200//function : Select3D_Projector
4952a30a 201//purpose :
7fd59977 202//=======================================================================
197ac94e 203Select3D_Projector::Select3D_Projector (const Graphic3d_Mat4d& theViewTrsf,
42b96b07 204 const Graphic3d_Mat4d& theProjTrsf,
205 const Standard_Real theZNear,
206 const Standard_Real theZFar)
197ac94e 207: myPersp (Standard_False),
208 myFocus (0.0),
209 myType (-1)
7fd59977 210{
42b96b07 211 Set (theViewTrsf, theProjTrsf, theZNear, theZFar);
7fd59977 212}
213
214//=======================================================================
197ac94e 215//function : Set
4952a30a 216//purpose :
7fd59977 217//=======================================================================
197ac94e 218void Select3D_Projector::Set (const gp_Trsf& theViewTrsf,
219 const Standard_Boolean theIsPersp,
220 const Standard_Real theFocus)
221{
222 myPersp = theIsPersp;
223 myFocus = theFocus;
224 myScaledTrsf = theViewTrsf;
225 myProjTrsf.InitIdentity();
226 Scaled();
7fd59977 227}
228
197ac94e 229//=======================================================================
230//function : Set
231//purpose :
232//=======================================================================
233void Select3D_Projector::Set (const Graphic3d_Mat4d& theViewTrsf,
42b96b07 234 const Graphic3d_Mat4d& theProjTrsf,
235 const Standard_Real theZNear,
236 const Standard_Real theZFar)
4952a30a 237{
197ac94e 238 // Copy elements corresponding to common view-transformation
239 for (Standard_Integer aRowIt = 0; aRowIt < 3; ++aRowIt)
240 {
241 for (Standard_Integer aColIt = 0; aColIt < 4; ++aColIt)
242 {
243 myGTrsf.SetValue (aRowIt + 1, aColIt + 1, theViewTrsf.GetValue (aRowIt, aColIt));
7fd59977 244 }
245 }
197ac94e 246
247 // Adapt scaled transformation for compatibilty
248 gp_Dir aViewY (theViewTrsf.GetValue (0, 1), theViewTrsf.GetValue (1, 1), theViewTrsf.GetValue (2, 1));
249 gp_Dir aViewZ (theViewTrsf.GetValue (0, 2), theViewTrsf.GetValue (1, 2), theViewTrsf.GetValue (2, 2));
250 gp_XYZ aViewT (theViewTrsf.GetValue (0, 3), theViewTrsf.GetValue (1, 3), theViewTrsf.GetValue (2, 3));
251 gp_Dir aViewX = aViewY ^ aViewZ;
252 gp_Ax3 aViewAx3 (gp_Pnt (aViewT), aViewZ, aViewX);
253 myScaledTrsf.SetTransformation (aViewAx3);
254
255 myPersp = Standard_False;
256 myFocus = 0.0;
257 myProjTrsf = theProjTrsf;
42b96b07 258 myZNear = theZNear;
259 myZFar = theZFar;
197ac94e 260 Scaled();
7fd59977 261}
262
263//=======================================================================
197ac94e 264//function : SetView
4952a30a 265//purpose :
7fd59977 266//=======================================================================
197ac94e 267void Select3D_Projector::SetView (const Handle(V3d_View)& theView)
7fd59977 268{
197ac94e 269 const Graphic3d_Mat4d& aViewTrsf = theView->Camera()->OrientationMatrix();
270 const Graphic3d_Mat4d& aProjTrsf = theView->Camera()->ProjectionMatrix();
7fd59977 271
197ac94e 272 gp_XYZ aFrameScale = theView->Camera()->ViewDimensions();
273 Graphic3d_Mat4d aScale;
274 aScale.ChangeValue (0, 0) = aFrameScale.X();
275 aScale.ChangeValue (1, 1) = aFrameScale.Y();
276 aScale.ChangeValue (2, 2) = aFrameScale.Z();
277 Graphic3d_Mat4d aScaledProjTrsf = aScale * aProjTrsf;
7fd59977 278
42b96b07 279 Set (aViewTrsf,
280 aScaledProjTrsf,
281 theView->Camera()->ZNear(),
282 theView->Camera()->ZFar());
7fd59977 283}
284
285//=======================================================================
197ac94e 286//function : Scaled
4952a30a 287//purpose :
7fd59977 288//=======================================================================
197ac94e 289void Select3D_Projector::Scaled (const Standard_Boolean theToCheckOptimized)
7fd59977 290{
197ac94e 291 myType = -1;
292
293 if (!theToCheckOptimized && !myPersp && myProjTrsf.IsIdentity())
294 {
295 myType = TrsfType (myGTrsf);
7fd59977 296 }
197ac94e 297
298 myInvTrsf = myGTrsf.Inverted();
7fd59977 299}
197ac94e 300
7fd59977 301//=======================================================================
302//function : Project
4952a30a 303//purpose :
7fd59977 304//=======================================================================
197ac94e 305void Select3D_Projector::Project (const gp_Pnt& theP, gp_Pnt2d& thePout) const
7fd59977 306{
197ac94e 307 Standard_Real aXout = 0.0;
308 Standard_Real aYout = 0.0;
309 Standard_Real aZout = 0.0;
310 Project (theP, aXout, aYout, aZout);
311 thePout.SetCoord (aXout, aYout);
7fd59977 312}
313
7fd59977 314//=======================================================================
197ac94e 315//function : Project
4952a30a 316//purpose :
7fd59977 317//=======================================================================
197ac94e 318void Select3D_Projector::Project (const gp_Pnt& theP,
319 Standard_Real& theX,
320 Standard_Real& theY,
321 Standard_Real& theZ) const
7fd59977 322{
197ac94e 323 Graphic3d_Vec4d aTransformed (0.0, 0.0, 0.0, 1.0);
4952a30a 324
197ac94e 325 // view transformation
326 switch (myType)
b5ac8292 327 {
197ac94e 328 case 0 : // inverse axo
329 {
330 Standard_Real aX07 = theP.X() * 0.7071067811865475;
331 Standard_Real aY05 = theP.Y() * 0.5;
332 Standard_Real aZ05 = theP.Z() * 0.5;
333 aTransformed.x() = aX07 - aY05 + aZ05;
334 aTransformed.y() = aX07 + aY05 - aZ05;
335 aTransformed.z() = 0.7071067811865475 * (theP.Y() + theP.Z());
336 break;
337 }
b5ac8292 338
197ac94e 339 case 1 : // top
340 {
341 aTransformed.x() = theP.X();
342 aTransformed.y() = theP.Y();
343 aTransformed.z() = theP.Z();
344 break;
345 }
b5ac8292 346
197ac94e 347 case 2 : // front
348 {
349 aTransformed.x() = theP.X();
350 aTransformed.y() = theP.Z();
351 aTransformed.z() = -theP.Y();
352 break;
353 }
b5ac8292 354
197ac94e 355 case 3 : // axo
b5ac8292 356 {
197ac94e 357 Standard_Real aXmy05 = (theP.X() - theP.Y()) * 0.5;
358 Standard_Real aZ07 = theP.Z() * 0.7071067811865476;
359 aTransformed.x() = 0.7071067811865476 * (theP.X() + theP.Y());
360 aTransformed.y() = -aXmy05 + aZ07;
361 aTransformed.z() = aXmy05 + aZ07;
362 break;
b5ac8292 363 }
197ac94e 364
365 default :
b5ac8292 366 {
197ac94e 367 gp_Pnt aTransformPnt = theP;
368 Transform (aTransformPnt);
369 aTransformed.x() = aTransformPnt.X();
370 aTransformed.y() = aTransformPnt.Y();
371 aTransformed.z() = aTransformPnt.Z();
b5ac8292 372 }
197ac94e 373 }
b5ac8292 374
197ac94e 375 // projection transformation
376 if (myPersp)
377 {
378 // simplified perspective
379 Standard_Real aDistortion = 1.0 - aTransformed.z() / myFocus;
380 theX = aTransformed.x() / aDistortion;
381 theY = aTransformed.y() / aDistortion;
382 theZ = aTransformed.z();
383 return;
7fd59977 384 }
197ac94e 385
386 if (myProjTrsf.IsIdentity())
b5ac8292 387 {
197ac94e 388 // no projection transformation
389 theX = aTransformed.x();
390 theY = aTransformed.y();
391 theZ = aTransformed.z();
392 return;
7fd59977 393 }
b5ac8292 394
197ac94e 395 Graphic3d_Vec4d aProjected = myProjTrsf * aTransformed;
b5ac8292 396
197ac94e 397 theX = aProjected.x() / aProjected.w();
398 theY = aProjected.y() / aProjected.w();
399 theZ = aProjected.z() / aProjected.w();
7fd59977 400}
401
197ac94e 402//=======================================================================
403//function : Project
404//purpose :
405//=======================================================================
406void Select3D_Projector::Project (const gp_Pnt& theP,
407 const gp_Vec& theD1,
408 gp_Pnt2d& thePout,
409 gp_Vec2d& theD1out) const
410{
411 // view transformation
412 gp_Pnt aTP = theP;
413 Transform (aTP);
7fd59977 414
197ac94e 415 gp_Vec aTD1 = theD1;
416 Transform (aTD1);
417
418 // projection transformation
419 if (myPersp)
420 {
421 // simplified perspective
422 Standard_Real aDist = 1.0 - aTP.Z() / myFocus;
423 thePout.SetCoord (aTP.X() / aDist, aTP.Y() / aDist);
424 theD1out.SetCoord (aTD1.X() / aDist + aTP.X() * aTD1.Z() / (myFocus * aDist * aDist),
425 aTD1.Y() / aDist + aTP.Y() * aTD1.Z() / (myFocus * aDist * aDist));
426 return;
427 }
428
429 if (myProjTrsf.IsIdentity())
430 {
431 // no projection transformation
432 thePout.SetCoord (aTP.X(), aTP.Y());
433 theD1out.SetCoord (aTD1.X(), aTD1.Y());
434 }
435
436 Graphic3d_Vec4d aTransformedPnt1 (aTP.X(), aTP.Y(), aTP.Z(), 1.0);
437 Graphic3d_Vec4d aTransformedPnt2 (aTP.X() + aTD1.X(), aTP.Y() + aTD1.Y(), aTP.Z() + aTD1.Z(), 1.0);
438
439 Graphic3d_Vec4d aProjectedPnt1 = myProjTrsf * aTransformedPnt1;
440 Graphic3d_Vec4d aProjectedPnt2 = myProjTrsf * aTransformedPnt2;
441
442 aProjectedPnt1 /= aProjectedPnt1.w();
443 aProjectedPnt2 /= aProjectedPnt2.w();
444
445 Graphic3d_Vec4d aProjectedD1 = aProjectedPnt2 - aProjectedPnt1;
446
447 thePout.SetCoord (aProjectedPnt1.x(), aProjectedPnt1.y());
448 theD1out.SetCoord (aProjectedD1.x(), aProjectedD1.y());
449}
450
451//=======================================================================
452//function : Shoot
453//purpose :
454//=======================================================================
455gp_Lin Select3D_Projector::Shoot (const Standard_Real theX, const Standard_Real theY) const
7fd59977 456{
197ac94e 457 gp_Lin aViewLin;
458
459 if (myPersp)
460 {
461 // simplified perspective
462 aViewLin = gp_Lin (gp_Pnt (0.0, 0.0, myFocus), gp_Dir (theX, theY, -myFocus));
463 }
464 else if (myProjTrsf.IsIdentity())
465 {
466 // no projection transformation
467 aViewLin = gp_Lin (gp_Pnt (theX, theY, 0.0), gp_Dir (0.0, 0.0, -1.0));
468 }
469 else
470 {
471 // get direction of projection over the point in view space
472 Graphic3d_Mat4d aProjInv;
473 if (!myProjTrsf.Inverted (aProjInv))
474 {
475 return gp_Lin();
476 }
477
42b96b07 478 Graphic3d_Vec4d aVPnt1 = aProjInv * Graphic3d_Vec4d (theX, theY, myZNear, 1.0);
479 Graphic3d_Vec4d aVPnt2 = aProjInv * Graphic3d_Vec4d (theX, theY, myZFar, 1.0);
197ac94e 480 aVPnt1 /= aVPnt1.w();
ba4feb76 481 aVPnt2 /= aVPnt2.w();
197ac94e 482
483 gp_Vec aViewDir (aVPnt2.x() - aVPnt1.x(), aVPnt2.y() - aVPnt1.y(), aVPnt2.z() - aVPnt1.z());
484
485 aViewLin = gp_Lin (gp_Pnt (aVPnt1.x(), aVPnt1.y(), aVPnt1.z()), gp_Dir (aViewDir));
486 }
487
488 // view transformation
489 Transform (aViewLin, myInvTrsf);
4952a30a 490
197ac94e 491 return aViewLin;
4952a30a 492}