0025265: Perspective projection - selecting front point of two
[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),
110 myType (-1)
7fd59977 111{
197ac94e 112 SetView (theView);
7fd59977 113}
114
4952a30a 115//=======================================================================
116//function : Select3D_Projector
117//purpose :
118//=======================================================================
4952a30a 119Select3D_Projector::Select3D_Projector()
197ac94e 120: myPersp (Standard_False),
121 myFocus (0.0),
122 myType (-1)
7fd59977 123{
124 Scaled();
4952a30a 125}
7fd59977 126
127//=======================================================================
128//function : Select3D_Projector
4952a30a 129//purpose :
7fd59977 130//=======================================================================
197ac94e 131Select3D_Projector::Select3D_Projector (const gp_Ax2& theCS)
132: myPersp (Standard_False),
133 myFocus (0.0),
134 myType (-1)
7fd59977 135{
197ac94e 136 myScaledTrsf.SetTransformation (theCS);
137 myGTrsf.SetTrsf (myScaledTrsf);
7fd59977 138 Scaled();
7fd59977 139}
140
141//=======================================================================
142//function : Select3D_Projector
4952a30a 143//purpose :
7fd59977 144//=======================================================================
197ac94e 145Select3D_Projector::Select3D_Projector (const gp_Ax2& theCS, const Standard_Real theFocus)
146: myPersp (Standard_True),
147 myFocus (theFocus),
148 myType (-1)
7fd59977 149{
197ac94e 150 myScaledTrsf.SetTransformation (theCS);
151 myGTrsf.SetTrsf (myScaledTrsf);
7fd59977 152 Scaled();
7fd59977 153}
154
155//=======================================================================
156//function : Select3D_Projector
4952a30a 157//purpose :
7fd59977 158//=======================================================================
197ac94e 159Select3D_Projector::Select3D_Projector (const gp_Trsf& theViewTrsf,
160 const Standard_Boolean theIsPersp,
161 const Standard_Real theFocus)
162: myPersp (theIsPersp),
163 myFocus (theFocus),
164 myGTrsf (theViewTrsf),
165 myScaledTrsf (theViewTrsf),
166 myType (-1)
7fd59977 167{
7fd59977 168 Scaled();
169}
170
171//=======================================================================
172//function : Select3D_Projector
4952a30a 173//purpose :
7fd59977 174//=======================================================================
197ac94e 175Select3D_Projector::Select3D_Projector (const gp_GTrsf& theViewTrsf,
176 const Standard_Boolean theIsPersp,
177 const Standard_Real theFocus)
178: myPersp (theIsPersp),
179 myFocus (theFocus),
180 myGTrsf (theViewTrsf),
181 myScaledTrsf (theViewTrsf.Trsf()),
182 myType (-1)
7fd59977 183{
184 Scaled();
7fd59977 185}
186
7fd59977 187//=======================================================================
197ac94e 188//function : Select3D_Projector
4952a30a 189//purpose :
7fd59977 190//=======================================================================
197ac94e 191Select3D_Projector::Select3D_Projector (const Graphic3d_Mat4d& theViewTrsf,
192 const Graphic3d_Mat4d& theProjTrsf)
193: myPersp (Standard_False),
194 myFocus (0.0),
195 myType (-1)
7fd59977 196{
197ac94e 197 Set (theViewTrsf, theProjTrsf);
7fd59977 198}
199
200//=======================================================================
197ac94e 201//function : Set
4952a30a 202//purpose :
7fd59977 203//=======================================================================
197ac94e 204void Select3D_Projector::Set (const gp_Trsf& theViewTrsf,
205 const Standard_Boolean theIsPersp,
206 const Standard_Real theFocus)
207{
208 myPersp = theIsPersp;
209 myFocus = theFocus;
210 myScaledTrsf = theViewTrsf;
211 myProjTrsf.InitIdentity();
212 Scaled();
7fd59977 213}
214
197ac94e 215//=======================================================================
216//function : Set
217//purpose :
218//=======================================================================
219void Select3D_Projector::Set (const Graphic3d_Mat4d& theViewTrsf,
220 const Graphic3d_Mat4d& theProjTrsf)
4952a30a 221{
197ac94e 222 // Copy elements corresponding to common view-transformation
223 for (Standard_Integer aRowIt = 0; aRowIt < 3; ++aRowIt)
224 {
225 for (Standard_Integer aColIt = 0; aColIt < 4; ++aColIt)
226 {
227 myGTrsf.SetValue (aRowIt + 1, aColIt + 1, theViewTrsf.GetValue (aRowIt, aColIt));
7fd59977 228 }
229 }
197ac94e 230
231 // Adapt scaled transformation for compatibilty
232 gp_Dir aViewY (theViewTrsf.GetValue (0, 1), theViewTrsf.GetValue (1, 1), theViewTrsf.GetValue (2, 1));
233 gp_Dir aViewZ (theViewTrsf.GetValue (0, 2), theViewTrsf.GetValue (1, 2), theViewTrsf.GetValue (2, 2));
234 gp_XYZ aViewT (theViewTrsf.GetValue (0, 3), theViewTrsf.GetValue (1, 3), theViewTrsf.GetValue (2, 3));
235 gp_Dir aViewX = aViewY ^ aViewZ;
236 gp_Ax3 aViewAx3 (gp_Pnt (aViewT), aViewZ, aViewX);
237 myScaledTrsf.SetTransformation (aViewAx3);
238
239 myPersp = Standard_False;
240 myFocus = 0.0;
241 myProjTrsf = theProjTrsf;
242 Scaled();
7fd59977 243}
244
245//=======================================================================
197ac94e 246//function : SetView
4952a30a 247//purpose :
7fd59977 248//=======================================================================
197ac94e 249void Select3D_Projector::SetView (const Handle(V3d_View)& theView)
7fd59977 250{
197ac94e 251 const Graphic3d_Mat4d& aViewTrsf = theView->Camera()->OrientationMatrix();
252 const Graphic3d_Mat4d& aProjTrsf = theView->Camera()->ProjectionMatrix();
7fd59977 253
197ac94e 254 gp_XYZ aFrameScale = theView->Camera()->ViewDimensions();
255 Graphic3d_Mat4d aScale;
256 aScale.ChangeValue (0, 0) = aFrameScale.X();
257 aScale.ChangeValue (1, 1) = aFrameScale.Y();
258 aScale.ChangeValue (2, 2) = aFrameScale.Z();
259 Graphic3d_Mat4d aScaledProjTrsf = aScale * aProjTrsf;
7fd59977 260
197ac94e 261 Set (aViewTrsf, aScaledProjTrsf);
7fd59977 262}
263
264//=======================================================================
197ac94e 265//function : Scaled
4952a30a 266//purpose :
7fd59977 267//=======================================================================
197ac94e 268void Select3D_Projector::Scaled (const Standard_Boolean theToCheckOptimized)
7fd59977 269{
197ac94e 270 myType = -1;
271
272 if (!theToCheckOptimized && !myPersp && myProjTrsf.IsIdentity())
273 {
274 myType = TrsfType (myGTrsf);
7fd59977 275 }
197ac94e 276
277 myInvTrsf = myGTrsf.Inverted();
7fd59977 278}
197ac94e 279
7fd59977 280//=======================================================================
281//function : Project
4952a30a 282//purpose :
7fd59977 283//=======================================================================
197ac94e 284void Select3D_Projector::Project (const gp_Pnt& theP, gp_Pnt2d& thePout) const
7fd59977 285{
197ac94e 286 Standard_Real aXout = 0.0;
287 Standard_Real aYout = 0.0;
288 Standard_Real aZout = 0.0;
289 Project (theP, aXout, aYout, aZout);
290 thePout.SetCoord (aXout, aYout);
7fd59977 291}
292
7fd59977 293//=======================================================================
197ac94e 294//function : Project
4952a30a 295//purpose :
7fd59977 296//=======================================================================
197ac94e 297void Select3D_Projector::Project (const gp_Pnt& theP,
298 Standard_Real& theX,
299 Standard_Real& theY,
300 Standard_Real& theZ) const
7fd59977 301{
197ac94e 302 Graphic3d_Vec4d aTransformed (0.0, 0.0, 0.0, 1.0);
4952a30a 303
197ac94e 304 // view transformation
305 switch (myType)
b5ac8292 306 {
197ac94e 307 case 0 : // inverse axo
308 {
309 Standard_Real aX07 = theP.X() * 0.7071067811865475;
310 Standard_Real aY05 = theP.Y() * 0.5;
311 Standard_Real aZ05 = theP.Z() * 0.5;
312 aTransformed.x() = aX07 - aY05 + aZ05;
313 aTransformed.y() = aX07 + aY05 - aZ05;
314 aTransformed.z() = 0.7071067811865475 * (theP.Y() + theP.Z());
315 break;
316 }
b5ac8292 317
197ac94e 318 case 1 : // top
319 {
320 aTransformed.x() = theP.X();
321 aTransformed.y() = theP.Y();
322 aTransformed.z() = theP.Z();
323 break;
324 }
b5ac8292 325
197ac94e 326 case 2 : // front
327 {
328 aTransformed.x() = theP.X();
329 aTransformed.y() = theP.Z();
330 aTransformed.z() = -theP.Y();
331 break;
332 }
b5ac8292 333
197ac94e 334 case 3 : // axo
b5ac8292 335 {
197ac94e 336 Standard_Real aXmy05 = (theP.X() - theP.Y()) * 0.5;
337 Standard_Real aZ07 = theP.Z() * 0.7071067811865476;
338 aTransformed.x() = 0.7071067811865476 * (theP.X() + theP.Y());
339 aTransformed.y() = -aXmy05 + aZ07;
340 aTransformed.z() = aXmy05 + aZ07;
341 break;
b5ac8292 342 }
197ac94e 343
344 default :
b5ac8292 345 {
197ac94e 346 gp_Pnt aTransformPnt = theP;
347 Transform (aTransformPnt);
348 aTransformed.x() = aTransformPnt.X();
349 aTransformed.y() = aTransformPnt.Y();
350 aTransformed.z() = aTransformPnt.Z();
b5ac8292 351 }
197ac94e 352 }
b5ac8292 353
197ac94e 354 // projection transformation
355 if (myPersp)
356 {
357 // simplified perspective
358 Standard_Real aDistortion = 1.0 - aTransformed.z() / myFocus;
359 theX = aTransformed.x() / aDistortion;
360 theY = aTransformed.y() / aDistortion;
361 theZ = aTransformed.z();
362 return;
7fd59977 363 }
197ac94e 364
365 if (myProjTrsf.IsIdentity())
b5ac8292 366 {
197ac94e 367 // no projection transformation
368 theX = aTransformed.x();
369 theY = aTransformed.y();
370 theZ = aTransformed.z();
371 return;
7fd59977 372 }
b5ac8292 373
197ac94e 374 Graphic3d_Vec4d aProjected = myProjTrsf * aTransformed;
b5ac8292 375
197ac94e 376 theX = aProjected.x() / aProjected.w();
377 theY = aProjected.y() / aProjected.w();
378 theZ = aProjected.z() / aProjected.w();
7fd59977 379}
380
197ac94e 381//=======================================================================
382//function : Project
383//purpose :
384//=======================================================================
385void Select3D_Projector::Project (const gp_Pnt& theP,
386 const gp_Vec& theD1,
387 gp_Pnt2d& thePout,
388 gp_Vec2d& theD1out) const
389{
390 // view transformation
391 gp_Pnt aTP = theP;
392 Transform (aTP);
7fd59977 393
197ac94e 394 gp_Vec aTD1 = theD1;
395 Transform (aTD1);
396
397 // projection transformation
398 if (myPersp)
399 {
400 // simplified perspective
401 Standard_Real aDist = 1.0 - aTP.Z() / myFocus;
402 thePout.SetCoord (aTP.X() / aDist, aTP.Y() / aDist);
403 theD1out.SetCoord (aTD1.X() / aDist + aTP.X() * aTD1.Z() / (myFocus * aDist * aDist),
404 aTD1.Y() / aDist + aTP.Y() * aTD1.Z() / (myFocus * aDist * aDist));
405 return;
406 }
407
408 if (myProjTrsf.IsIdentity())
409 {
410 // no projection transformation
411 thePout.SetCoord (aTP.X(), aTP.Y());
412 theD1out.SetCoord (aTD1.X(), aTD1.Y());
413 }
414
415 Graphic3d_Vec4d aTransformedPnt1 (aTP.X(), aTP.Y(), aTP.Z(), 1.0);
416 Graphic3d_Vec4d aTransformedPnt2 (aTP.X() + aTD1.X(), aTP.Y() + aTD1.Y(), aTP.Z() + aTD1.Z(), 1.0);
417
418 Graphic3d_Vec4d aProjectedPnt1 = myProjTrsf * aTransformedPnt1;
419 Graphic3d_Vec4d aProjectedPnt2 = myProjTrsf * aTransformedPnt2;
420
421 aProjectedPnt1 /= aProjectedPnt1.w();
422 aProjectedPnt2 /= aProjectedPnt2.w();
423
424 Graphic3d_Vec4d aProjectedD1 = aProjectedPnt2 - aProjectedPnt1;
425
426 thePout.SetCoord (aProjectedPnt1.x(), aProjectedPnt1.y());
427 theD1out.SetCoord (aProjectedD1.x(), aProjectedD1.y());
428}
429
430//=======================================================================
431//function : Shoot
432//purpose :
433//=======================================================================
434gp_Lin Select3D_Projector::Shoot (const Standard_Real theX, const Standard_Real theY) const
7fd59977 435{
197ac94e 436 gp_Lin aViewLin;
437
438 if (myPersp)
439 {
440 // simplified perspective
441 aViewLin = gp_Lin (gp_Pnt (0.0, 0.0, myFocus), gp_Dir (theX, theY, -myFocus));
442 }
443 else if (myProjTrsf.IsIdentity())
444 {
445 // no projection transformation
446 aViewLin = gp_Lin (gp_Pnt (theX, theY, 0.0), gp_Dir (0.0, 0.0, -1.0));
447 }
448 else
449 {
450 // get direction of projection over the point in view space
451 Graphic3d_Mat4d aProjInv;
452 if (!myProjTrsf.Inverted (aProjInv))
453 {
454 return gp_Lin();
455 }
456
ba4feb76 457 Graphic3d_Vec4d aVPnt1 = aProjInv * Graphic3d_Vec4d (theX, theY, 0.0, 1.0);
197ac94e 458 Graphic3d_Vec4d aVPnt2 = aProjInv * Graphic3d_Vec4d (theX, theY, 10.0, 1.0);
459 aVPnt1 /= aVPnt1.w();
ba4feb76 460 aVPnt2 /= aVPnt2.w();
197ac94e 461
462 gp_Vec aViewDir (aVPnt2.x() - aVPnt1.x(), aVPnt2.y() - aVPnt1.y(), aVPnt2.z() - aVPnt1.z());
463
464 aViewLin = gp_Lin (gp_Pnt (aVPnt1.x(), aVPnt1.y(), aVPnt1.z()), gp_Dir (aViewDir));
465 }
466
467 // view transformation
468 Transform (aViewLin, myInvTrsf);
4952a30a 469
197ac94e 470 return aViewLin;
4952a30a 471}