0025624: Visualization - selection is incorrect in perspective mode in a specific...
[occt.git] / src / Select3D / Select3D_Projector.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 6b65e87..f7975cb
-// File:       Select3D_Projector.cxx
-// Created:    Fri Mar 13 11:08:32 1992
-// Author:     Christophe MARION
-//             <cma@sdsun2>
-
-#define IMP240100      //GG 
-//                     Change RefToPix()/Convert() to Project() method.
+// Created on: 1992-03-13
+// Created by: Christophe MARION
+// Copyright (c) 1992-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <Select3D_Projector.ixx>
 #include <Precision.hxx>
 #include <gp_Ax3.hxx>
 #include <gp_Vec.hxx>
 #include <gp_Vec2d.hxx>
+#include <gp_Mat.hxx>
+#include <Graphic3d_Vec4.hxx>
+
+namespace
+{
+  //=======================================================================
+  //function : TrsfType
+  //purpose  :
+  //=======================================================================
+  static Standard_Integer TrsfType(const gp_GTrsf& theTrsf)
+  {
+    const gp_Mat& aMat = theTrsf.VectorialPart();
+    if ((Abs (aMat.Value (1, 1) - 1.0) < 1e-15)
+     && (Abs (aMat.Value (2, 2) - 1.0) < 1e-15)
+     && (Abs (aMat.Value (3, 3) - 1.0) < 1e-15))
+    {
+      return 1; // top
+    }
+    else if ((Abs (aMat.Value (1, 1) - 0.7071067811865476) < 1e-15)
+          && (Abs (aMat.Value (1, 2) + 0.5) < 1e-15)
+          && (Abs (aMat.Value (1, 3) - 0.5) < 1e-15)
+          && (Abs (aMat.Value (2, 1) - 0.7071067811865476) < 1e-15)
+          && (Abs (aMat.Value (2, 2) - 0.5) < 1e-15)
+          && (Abs (aMat.Value (2, 3) + 0.5) < 1e-15)
+          && (Abs (aMat.Value (3, 1)) < 1e-15)
+          && (Abs (aMat.Value (3, 2) - 0.7071067811865476) < 1e-15)
+          && (Abs (aMat.Value (3, 3) - 0.7071067811865476) < 1e-15))
+    {
+      return 0; // inverse axo
+    }
+    else if ((Abs (aMat.Value (1, 1) - 1.0) < 1e-15)
+          && (Abs (aMat.Value (2, 3) - 1.0) < 1e-15)
+          && (Abs (aMat.Value (3, 2) + 1.0) < 1e-15))
+    {
+      return 2; // front
+    }
+    else if ((Abs (aMat.Value (1, 1) - 0.7071067811865476) < 1e-15)
+          && (Abs (aMat.Value (1, 2) - 0.7071067811865476) < 1e-15)
+          && (Abs (aMat.Value (1, 3)) < 1e-15)
+          && (Abs (aMat.Value (2, 1) + 0.5) < 1e-15)
+          && (Abs (aMat.Value (2, 2) - 0.5) < 1e-15)
+          && (Abs (aMat.Value (2, 3) - 0.7071067811865476) < 1e-15)
+          && (Abs (aMat.Value (3, 1) - 0.5) < 1e-15)
+          && (Abs (aMat.Value (3, 2) + 0.5) < 1e-15)
+          && (Abs (aMat.Value (3, 3) - 0.7071067811865476) < 1e-15))
+    {
+      return 3; // axo
+    }
+
+    return -1;
+  }
+
+   //====== TYPE 0 (inverse axonometric)
+   // (0.7071067811865476, -0.5               ,  0.4999999999999999)
+   // (0.7071067811865475,  0.5000000000000001, -0.5              )
+   // (0.0,                 0.7071067811865475,  0.7071067811865476)
+
+   // ====== TYPE 1 (top)
+   // (1.0, 0.0, 0.0)
+   // (0.0, 1.0, 0.0)
+   // (0.0, 0.0, 1.0)
+
+   // ======= TYPE 2 (front)
+   // (1.0,  0.0                   , 0.0)
+   // (0.0,  1.110223024625157e-16 , 1.0)
+   // (0.0, -1.0                   , 1.110223024625157e-16)
+
+   // ======= TYPE 3 (axonometric)
+   // ( 0.7071067811865476, 0.7071067811865475, 0.0)
+   // (-0.5               , 0.5000000000000001, 0.7071067811865475)
+   // ( 0.4999999999999999, -0.5              , 0.7071067811865476)
+}
 
 // formula for derivating a perspective, from Mathematica
 
-//        X'[t]      X[t] Z'[t]                                     
-// D1 =  -------- + -------------                                   
-//           Z[t]          Z[t] 2                                   
-//       1 - ----   f (1 - ----)                                    
-//            f             f                                       
+//        X'[t]      X[t] Z'[t]
+// D1 =  -------- + -------------
+//           Z[t]          Z[t] 2
+//       1 - ----   f (1 - ----)
+//            f             f
 
 //=======================================================================
 //function : Select3D_Projector
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-
-Select3D_Projector::Select3D_Projector(const Handle(V3d_View)& aViou):
-myPersp(aViou->Type()==V3d_PERSPECTIVE),
-myFocus(aViou->Focale()),
-myD1(1,0),
-myD2(0,1),
-myD3(1,1),
-myView(aViou)
+Select3D_Projector::Select3D_Projector (const Handle(V3d_View)& theView)
+: myPersp (Standard_False),
+  myFocus (0.0),
+  myZNear (0.0),
+  myZFar (10.0),
+  myType (-1)
 {
-  Standard_Real Xat,Yat,Zat,XUp,YUp,ZUp,DX,DY,DZ;
-  //Standard_Boolean Pers=Standard_False;
-  
-  aViou->At(Xat,Yat,Zat);
-  aViou->Up(XUp,YUp,ZUp);
-  aViou->Proj(DX,DY,DZ);
-  gp_Pnt At (Xat,Yat,Zat); 
-  gp_Dir Zpers (DX,DY,DZ);
-  gp_Dir Ypers (XUp,YUp,ZUp);
-  gp_Dir Xpers = Ypers.Crossed(Zpers);
-  gp_Ax3 Axe (At, Zpers, Xpers);
-  myScaledTrsf.SetTransformation(Axe);
-  myGTrsf.SetTrsf(myScaledTrsf);
-  Scaled();
-  
+  SetView (theView);
 }
 
-Select3D_Projector::Select3D_Projector () :
-myPersp(Standard_False),myFocus(0),myD1(1,0),myD2(0,1),myD3(1,1)
+//=======================================================================
+//function : Select3D_Projector
+//purpose  :
+//=======================================================================
+Select3D_Projector::Select3D_Projector()
+: myPersp (Standard_False),
+  myFocus (0.0),
+  myZNear (0.0),
+  myZFar (10.0),
+  myType (-1)
 {
   Scaled();
-  SetDirection();
-} 
+}
 
 //=======================================================================
 //function : Select3D_Projector
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-Select3D_Projector::Select3D_Projector 
-  (const gp_Ax2& CS) :
-  myPersp(Standard_False), myFocus(0)
+Select3D_Projector::Select3D_Projector (const gp_Ax2& theCS)
+: myPersp (Standard_False),
+  myFocus (0.0),
+  myZNear (0.0),
+  myZFar (10.0),
+  myType (-1)
 {
-  myScaledTrsf.SetTransformation(CS);
-  myGTrsf.SetTrsf(myScaledTrsf);
+  myScaledTrsf.SetTransformation (theCS);
+  myGTrsf.SetTrsf (myScaledTrsf);
   Scaled();
-  SetDirection();
 }
 
 //=======================================================================
 //function : Select3D_Projector
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-Select3D_Projector::Select3D_Projector 
-  (const gp_Ax2& CS, 
-   const Standard_Real Focus) :
-  myPersp(Standard_True), myFocus(Focus)
+Select3D_Projector::Select3D_Projector (const gp_Ax2& theCS, const Standard_Real theFocus)
+: myPersp (Standard_True),
+  myFocus (theFocus),
+  myZNear (0.0),
+  myZFar (10.0),
+  myType (-1)
 {
-  myScaledTrsf.SetTransformation(CS);
-  myGTrsf.SetTrsf(myScaledTrsf);
+  myScaledTrsf.SetTransformation (theCS);
+  myGTrsf.SetTrsf (myScaledTrsf);
   Scaled();
-  SetDirection();
 }
 
 //=======================================================================
 //function : Select3D_Projector
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-Select3D_Projector::Select3D_Projector 
-  (const gp_Trsf& T, 
-   const Standard_Boolean Persp,
-   const Standard_Real Focus) :
-  myPersp(Persp),
-  myFocus(Focus),
-  myScaledTrsf(T)
+Select3D_Projector::Select3D_Projector (const gp_Trsf& theViewTrsf,
+                                        const Standard_Boolean theIsPersp,
+                                        const Standard_Real theFocus)
+: myPersp (theIsPersp),
+  myFocus (theFocus),
+  myGTrsf (theViewTrsf),
+  myScaledTrsf (theViewTrsf),
+  myZNear (0.0),
+  myZFar (10.0),
+  myType (-1)
 {
-  myGTrsf.SetTrsf(myScaledTrsf);
   Scaled();
-  SetDirection();
 }
 
 //=======================================================================
 //function : Select3D_Projector
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-Select3D_Projector::Select3D_Projector 
-  (const gp_Trsf& T, 
-   const Standard_Boolean Persp,
-   const Standard_Real Focus,
-   const gp_Vec2d& v1,
-   const gp_Vec2d& v2,
-   const gp_Vec2d& v3) :
-  myPersp(Persp),
-  myFocus(Focus),
-  myScaledTrsf(T),
-  myD1(v1),
-  myD2(v2),
-  myD3(v3)
+Select3D_Projector::Select3D_Projector (const gp_GTrsf& theViewTrsf,
+                                        const Standard_Boolean theIsPersp,
+                                        const Standard_Real theFocus)
+: myPersp (theIsPersp),
+  myFocus (theFocus),
+  myGTrsf (theViewTrsf),
+  myScaledTrsf (theViewTrsf.Trsf()),
+  myZNear (0.0),
+  myZFar (10.0),
+  myType (-1)
 {
-  myGTrsf.SetTrsf(myScaledTrsf);
   Scaled();
 }
 
 //=======================================================================
 //function : Select3D_Projector
-//purpose  : 
+//purpose  :
 //=======================================================================
+Select3D_Projector::Select3D_Projector (const Graphic3d_Mat4d& theViewTrsf,
+                                        const Graphic3d_Mat4d& theProjTrsf,
+                                        const Standard_Real theZNear,
+                                        const Standard_Real theZFar)
+: myPersp (Standard_False),
+  myFocus (0.0),
+  myType (-1)
+{
+  Set (theViewTrsf, theProjTrsf, theZNear, theZFar);
+}
 
-Select3D_Projector::Select3D_Projector 
-  (const gp_GTrsf& GT, 
-   const Standard_Boolean Persp,
-   const Standard_Real Focus) :
-  myPersp(Persp),
-  myFocus(Focus),
-  myGTrsf(GT)
+//=======================================================================
+//function : Set
+//purpose  :
+//=======================================================================
+void Select3D_Projector::Set (const gp_Trsf& theViewTrsf,
+                              const Standard_Boolean theIsPersp,
+                              const Standard_Real theFocus)
 {
+  myPersp      = theIsPersp;
+  myFocus      = theFocus;
+  myScaledTrsf = theViewTrsf;
+  myProjTrsf.InitIdentity();
   Scaled();
-  SetDirection();
 }
 
-void Select3D_Projector::Delete()
-{}
-
 //=======================================================================
 //function : Set
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-void Select3D_Projector::Set
-  (const gp_Trsf& T, 
-   const Standard_Boolean Persp,
-   const Standard_Real Focus) 
+void Select3D_Projector::Set (const Graphic3d_Mat4d& theViewTrsf,
+                              const Graphic3d_Mat4d& theProjTrsf,
+                              const Standard_Real theZNear,
+                              const Standard_Real theZFar)
 {
-  myPersp      = Persp;
-  myFocus      = Focus;
-  myScaledTrsf = T;
+  // Copy elements corresponding to common view-transformation
+  for (Standard_Integer aRowIt = 0; aRowIt < 3; ++aRowIt)
+  {
+    for (Standard_Integer aColIt = 0; aColIt < 4; ++aColIt)
+    {
+      myGTrsf.SetValue (aRowIt + 1, aColIt + 1, theViewTrsf.GetValue (aRowIt, aColIt));
+    }
+  }
+
+  // Adapt scaled transformation for compatibilty
+  gp_Dir aViewY (theViewTrsf.GetValue (0, 1), theViewTrsf.GetValue (1, 1), theViewTrsf.GetValue (2, 1));
+  gp_Dir aViewZ (theViewTrsf.GetValue (0, 2), theViewTrsf.GetValue (1, 2), theViewTrsf.GetValue (2, 2));
+  gp_XYZ aViewT (theViewTrsf.GetValue (0, 3), theViewTrsf.GetValue (1, 3), theViewTrsf.GetValue (2, 3));
+  gp_Dir aViewX = aViewY ^ aViewZ;
+  gp_Ax3 aViewAx3 (gp_Pnt (aViewT), aViewZ, aViewX);
+  myScaledTrsf.SetTransformation (aViewAx3);
+
+  myPersp    = Standard_False;
+  myFocus    = 0.0;
+  myProjTrsf = theProjTrsf;
+  myZNear    = theZNear;
+  myZFar     = theZFar;
   Scaled();
-  SetDirection();
 }
 
 //=======================================================================
-//function : Scaled
-//purpose  : 
+//function : SetView
+//purpose  :
 //=======================================================================
+void Select3D_Projector::SetView (const Handle(V3d_View)& theView)
+{
+  const Graphic3d_Mat4d& aViewTrsf = theView->Camera()->OrientationMatrix();
+  const Graphic3d_Mat4d& aProjTrsf = theView->Camera()->ProjectionMatrix();
+
+  gp_XYZ aFrameScale = theView->Camera()->ViewDimensions();
+  Graphic3d_Mat4d aScale;
+  aScale.ChangeValue (0, 0) = aFrameScale.X();
+  aScale.ChangeValue (1, 1) = aFrameScale.Y();
+  aScale.ChangeValue (2, 2) = aFrameScale.Z();
+  Graphic3d_Mat4d aScaledProjTrsf = aScale * aProjTrsf;
+
+  Set (aViewTrsf,
+       aScaledProjTrsf,
+       theView->Camera()->ZNear(),
+       theView->Camera()->ZFar());
+}
 
-#include <gp_Mat.hxx>
+//=======================================================================
+//function : Scaled
+//purpose  :
+//=======================================================================
+void Select3D_Projector::Scaled (const Standard_Boolean theToCheckOptimized)
+{
+  myType = -1;
 
-static Standard_Integer TrsfType(const gp_GTrsf& Trsf) { 
-  const gp_Mat& Mat = Trsf.VectorialPart();
-  if(   (Abs(Mat.Value(1,1)-1.0) < 1e-15) 
-     && (Abs(Mat.Value(2,2)-1.0) < 1e-15)
-     && (Abs(Mat.Value(3,3)-1.0) < 1e-15)) { 
-    return(1); //-- top
-  }
-  else if(   (Abs(Mat.Value(1,1)-0.7071067811865476) < 1e-15)
-         && (Abs(Mat.Value(1,2)+0.5) < 1e-15)
-         && (Abs(Mat.Value(1,3)-0.5) < 1e-15)
-         
-         && (Abs(Mat.Value(2,1)-0.7071067811865476) < 1e-15)
-         && (Abs(Mat.Value(2,2)-0.5) < 1e-15)
-         && (Abs(Mat.Value(2,3)+0.5) < 1e-15)
-         
-         && (Abs(Mat.Value(3,1)) < 1e-15)  
-         && (Abs(Mat.Value(3,2)-0.7071067811865476) < 1e-15)
-         && (Abs(Mat.Value(3,3)-0.7071067811865476) < 1e-15)) { 
-    return(0); //-- 
-  }
-  else if(   (Abs(Mat.Value(1,1)-1.0) < 1e-15) 
-         && (Abs(Mat.Value(2,3)-1.0) < 1e-15)
-         && (Abs(Mat.Value(3,2)+1.0) < 1e-15)) { 
-    return(2); //-- front
+  if (!theToCheckOptimized && !myPersp && myProjTrsf.IsIdentity())
+  {
+    myType = TrsfType (myGTrsf);
   }
-  else if(   (Abs(Mat.Value(1,1)-0.7071067811865476) < 1e-15)
-         && (Abs(Mat.Value(1,2)-0.7071067811865476) < 1e-15)
-         && (Abs(Mat.Value(1,3)) < 1e-15)
-         
-         && (Abs(Mat.Value(2,1)+0.5) < 1e-15)
-         && (Abs(Mat.Value(2,2)-0.5) < 1e-15)
-         && (Abs(Mat.Value(2,3)-0.7071067811865476) < 1e-15)
-         
-         && (Abs(Mat.Value(3,1)-0.5) < 1e-15)  
-         && (Abs(Mat.Value(3,2)+0.5) < 1e-15)
-         && (Abs(Mat.Value(3,3)-0.7071067811865476) < 1e-15)) { 
-    return(3); //-- axo
-  }
-  return(-1);
-}
 
-void Select3D_Projector::Scaled (const Standard_Boolean On)
-{ 
-  myType=-1;
-  if (!On) {
-    if (!myPersp) { 
-      //myGTrsf.SetTranslationPart(gp_XYZ(0.,0.,0.));
-      myType=TrsfType(myGTrsf); 
-    }
-  }
-  myInvTrsf = myGTrsf;
-  myInvTrsf.Invert();
+  myInvTrsf = myGTrsf.Inverted();
 }
 
 //=======================================================================
 //function : Project
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-void Select3D_Projector::Project (const gp_Pnt& P, gp_Pnt2d& Pout) const
+void Select3D_Projector::Project (const gp_Pnt& theP, gp_Pnt2d& thePout) const
 {
-
-  if(!myView.IsNull()){
-    Standard_Real Xout,Yout;
-//    V3d_View
-#ifdef IMP240100
-    myView->Project(P.X(),P.Y(),P.Z(),Xout,Yout);
-#else
-    Standard_Integer Xp,Yp;
-    myView->RefToPix(P.X(),P.Y(),P.Z(),Xp,Yp);
-    myView->Convert(Xp,Yp,Xout,Yout);
-#endif
-    Pout.SetCoord(Xout,Yout);
-  }
-  else{
-    if(myType!=-1) { 
-      Standard_Real X,Y;
-      switch (myType) { 
-      case 0: {  //-- axono standard
-       Standard_Real x07 = P.X()*0.7071067811865475;
-       Standard_Real y05 = P.Y()*0.5;
-       Standard_Real z05 = P.Z()*0.5;
-       X=x07-y05+z05;
-       Y=x07+y05-z05;
-       //-- Z=0.7071067811865475*(P.Y()+P.Z());
-       break;
-      }
-      case 1: { //-- top
-       X=P.X(); Y=P.Y(); //-- Z=P.Z();
-       Pout.SetCoord(X,Y);
-       break;
-      }
-      case 2: { 
-       X=P.X(); Y=P.Z(); //-- Z=-P.Y();
-       Pout.SetCoord(X,Y);
-       break;
-      }
-      case 3: { 
-       Standard_Real xmy05 = (P.X()-P.Y())*0.5;
-       Standard_Real z07 = P.Z()*0.7071067811865476;
-       X=0.7071067811865476*(P.X()+P.Y());
-       Y=-xmy05+z07;
-       Pout.SetCoord(X,Y);
-       //-- Z= xmy05+z07;
-       break;
-      }
-      default: { 
-       gp_Pnt P2 = P;
-       Transform(P2);
-       if (myPersp) {
-         Standard_Real R = 1.-P2.Z()/myFocus;
-         Pout.SetCoord(P2.X()/R,P2.Y()/R);
-       }
-       else 
-         Pout.SetCoord(P2.X(),P2.Y());    
-       break;
-      }
-      }
-    }
-    else { 
-      gp_Pnt P2 = P;
-      Transform(P2);
-      if (myPersp) {
-       Standard_Real R = 1.-P2.Z()/myFocus;
-       Pout.SetCoord(P2.X()/R,P2.Y()/R);
-      }
-      else 
-       Pout.SetCoord(P2.X(),P2.Y()); 
-    }
-  }
-  
-
+  Standard_Real aXout = 0.0;
+  Standard_Real aYout = 0.0;
+  Standard_Real aZout = 0.0;
+  Project (theP, aXout, aYout, aZout);
+  thePout.SetCoord (aXout, aYout);
 }
 
 //=======================================================================
 //function : Project
-//purpose  : 
+//purpose  :
 //=======================================================================
-/*  ====== TYPE 0  (??)
-   (0.7071067811865476, -0.5               ,  0.4999999999999999)
-   (0.7071067811865475,  0.5000000000000001, -0.5              )
-   (0.0,                 0.7071067811865475,  0.7071067811865476)
-
-  ====== TYPE 1 (top)
-(1.0, 0.0, 0.0)
-(0.0, 1.0, 0.0)
-(0.0, 0.0, 1.0)
-
- ======= TYPE 2 (front)
-(1.0,  0.0                   , 0.0)
-(0.0,  1.110223024625157e-16 , 1.0)
-(0.0, -1.0                   , 1.110223024625157e-16)
-
- ======= TYPE 3 
-( 0.7071067811865476, 0.7071067811865475, 0.0)
-(-0.5               , 0.5000000000000001, 0.7071067811865475)
-( 0.4999999999999999, -0.5              , 0.7071067811865476)
-*/
-void Select3D_Projector::Project (const gp_Pnt& P,
-                                Standard_Real& X,
-                                Standard_Real& Y,
-                                Standard_Real& Z) const
+void Select3D_Projector::Project (const gp_Pnt& theP,
+                                  Standard_Real& theX,
+                                  Standard_Real& theY,
+                                  Standard_Real& theZ) const
 {
-  if(!myView.IsNull()){
-//    Standard_Real Xout,Yout;
-//    V3d_View
-#ifdef IMP240100
-    myView->Project(P.X(),P.Y(),P.Z(),X,Y);
-#else
-    Standard_Integer Xp,Yp;
-    myView->RefToPix(P.X(),P.Y(),P.Z(),Xp,Yp);
-    myView->Convert(Xp,Yp,X,Y);
-#endif
-  }
-  else{
-    if(myType!=-1) { 
-      switch (myType) { 
-      case 0: {  //-- axono standard
-       Standard_Real x07 = P.X()*0.7071067811865475;
-       Standard_Real y05 = P.Y()*0.5;
-       Standard_Real z05 = P.Z()*0.5;
-       X=x07-y05+z05;
-       Y=x07+y05-z05;
-       Z=0.7071067811865475*(P.Y()+P.Z());
-       break;
-      }
-      case 1: { //-- top
-       X=P.X(); Y=P.Y(); Z=P.Z();
-       break;
-      }
-      case 2: { 
-       X=P.X(); Y=P.Z(); Z=-P.Y();
-       break;
-      }
-      case 3: { 
-       Standard_Real xmy05 = (P.X()-P.Y())*0.5;
-       Standard_Real z07 = P.Z()*0.7071067811865476;
-       X=0.7071067811865476*(P.X()+P.Y());
-       Y=-xmy05+z07;
-       Z= xmy05+z07;
-       break;
-      }
-      default: { 
-       gp_Pnt P2 = P;
-       Transform(P2);
-       P2.Coord(X,Y,Z);
-       break;
-      }
-      }
+  Graphic3d_Vec4d aTransformed (0.0, 0.0, 0.0, 1.0);
+
+  // view transformation
+  switch (myType)
+  {
+    case 0 : // inverse axo
+    {
+      Standard_Real aX07 = theP.X() * 0.7071067811865475;
+      Standard_Real aY05 = theP.Y() * 0.5;
+      Standard_Real aZ05 = theP.Z() * 0.5;
+      aTransformed.x() = aX07 - aY05 + aZ05;
+      aTransformed.y() = aX07 + aY05 - aZ05;
+      aTransformed.z() = 0.7071067811865475 * (theP.Y() + theP.Z());
+      break;
     }
-    else { 
-      gp_Pnt P2 = P;
-      Transform(P2);
-      P2.Coord(X,Y,Z);
-      if (myPersp) {
-       Standard_Real R = 1 - Z / myFocus;
-       X = X / R;
-       Y = Y / R;
-      }
+
+    case 1 : // top
+    {
+      aTransformed.x() = theP.X();
+      aTransformed.y() = theP.Y();
+      aTransformed.z() = theP.Z();
+      break;
+    }
+
+    case 2 : // front
+    {
+      aTransformed.x() =  theP.X();
+      aTransformed.y() =  theP.Z();
+      aTransformed.z() = -theP.Y();
+      break;
+    }
+
+    case 3 : // axo
+    {
+      Standard_Real aXmy05 = (theP.X() - theP.Y()) * 0.5;
+      Standard_Real aZ07 = theP.Z() * 0.7071067811865476;
+      aTransformed.x() = 0.7071067811865476 * (theP.X() + theP.Y());
+      aTransformed.y() = -aXmy05 + aZ07;
+      aTransformed.z() =  aXmy05 + aZ07;
+      break;
+    }
+
+    default :
+    {
+      gp_Pnt aTransformPnt = theP;
+      Transform (aTransformPnt);
+      aTransformed.x() = aTransformPnt.X();
+      aTransformed.y() = aTransformPnt.Y();
+      aTransformed.z() = aTransformPnt.Z();
     }
   }
+
+  // projection transformation
+  if (myPersp)
+  {
+    // simplified perspective
+    Standard_Real aDistortion = 1.0 - aTransformed.z() / myFocus;
+    theX = aTransformed.x() / aDistortion;
+    theY = aTransformed.y() / aDistortion;
+    theZ = aTransformed.z();
+    return;
+  }
+
+  if (myProjTrsf.IsIdentity())
+  {
+    // no projection transformation
+    theX = aTransformed.x();
+    theY = aTransformed.y();
+    theZ = aTransformed.z();
+    return;
+  }
+
+  Graphic3d_Vec4d aProjected = myProjTrsf * aTransformed;
+
+  theX = aProjected.x() / aProjected.w();
+  theY = aProjected.y() / aProjected.w();
+  theZ = aProjected.z() / aProjected.w();
 }
+
 //=======================================================================
 //function : Project
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-void Select3D_Projector::Project (const gp_Pnt& P,
-                                const gp_Vec& D1,
-                                gp_Pnt2d& Pout,
-                                gp_Vec2d& D1out) const
+void Select3D_Projector::Project (const gp_Pnt& theP,
+                                  const gp_Vec& theD1,
+                                  gp_Pnt2d& thePout,
+                                  gp_Vec2d& theD1out) const
 {
-  gp_Pnt PP = P;
-  Transform(PP);
-  gp_Vec DD1 = D1;
-  Transform(DD1);
-  if (myPersp) {
-    Standard_Real R = 1. - PP.Z() / myFocus;
-    Pout .SetCoord(PP .X()/R , PP.Y()/R);
-    D1out.SetCoord(DD1.X()/R + PP.X()*DD1.Z()/(myFocus * R*R),
-                  DD1.Y()/R + PP.Y()*DD1.Z()/(myFocus * R*R));
+  // view transformation
+  gp_Pnt aTP = theP;
+  Transform (aTP);
+
+  gp_Vec aTD1 = theD1;
+  Transform (aTD1);
+
+  // projection transformation
+  if (myPersp)
+  {
+    // simplified perspective
+    Standard_Real aDist = 1.0 - aTP.Z() / myFocus;
+    thePout.SetCoord (aTP.X() / aDist, aTP.Y() / aDist);
+    theD1out.SetCoord (aTD1.X() / aDist + aTP.X() * aTD1.Z() / (myFocus * aDist * aDist),
+                       aTD1.Y() / aDist + aTP.Y() * aTD1.Z() / (myFocus * aDist * aDist));
+    return;
   }
-  else {
-    Pout .SetCoord(PP .X(),PP .Y());
-    D1out.SetCoord(DD1.X(),DD1.Y());
+
+  if (myProjTrsf.IsIdentity())
+  {
+    // no projection transformation
+    thePout.SetCoord (aTP.X(), aTP.Y());
+    theD1out.SetCoord (aTD1.X(), aTD1.Y());
   }
-}
 
-//=======================================================================
-//function : BoxAdd
-//purpose  : 
-//=======================================================================
+  Graphic3d_Vec4d aTransformedPnt1 (aTP.X(), aTP.Y(), aTP.Z(), 1.0);
+  Graphic3d_Vec4d aTransformedPnt2 (aTP.X() + aTD1.X(), aTP.Y() + aTD1.Y(), aTP.Z() + aTD1.Z(), 1.0);
 
-void Select3D_Projector::BoxAdd
-  (const gp_Pnt2d& P,
-   Bnd_Box& B) const
-{
-  gp_Vec2d V(P.X(),P.Y());
-  gp_Pnt PP(myD1 * V, myD2 * V, myD3 * V);
-  B.Add(PP);
+  Graphic3d_Vec4d aProjectedPnt1 = myProjTrsf * aTransformedPnt1;
+  Graphic3d_Vec4d aProjectedPnt2 = myProjTrsf * aTransformedPnt2;
+
+  aProjectedPnt1 /= aProjectedPnt1.w();
+  aProjectedPnt2 /= aProjectedPnt2.w();
+
+  Graphic3d_Vec4d aProjectedD1 = aProjectedPnt2 - aProjectedPnt1;
+
+  thePout.SetCoord (aProjectedPnt1.x(), aProjectedPnt1.y());
+  theD1out.SetCoord (aProjectedD1.x(), aProjectedD1.y());
 }
 
 //=======================================================================
 //function : Shoot
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-gp_Lin Select3D_Projector::Shoot
-  (const Standard_Real X,
-   const Standard_Real Y) const
+gp_Lin Select3D_Projector::Shoot (const Standard_Real theX, const Standard_Real theY) const
 {
-  gp_Lin L;
-  
-  if (myPersp) {
-    L = gp_Lin(gp_Pnt(0,0, myFocus),
-              gp_Dir(X,Y,-myFocus));
+  gp_Lin aViewLin;
+
+  if (myPersp)
+  {
+    // simplified perspective
+    aViewLin = gp_Lin (gp_Pnt (0.0, 0.0, myFocus), gp_Dir (theX, theY, -myFocus));
   }
-  else {
-    L = gp_Lin(gp_Pnt(X,Y,0),
-              gp_Dir(0,0,-1));
+  else if (myProjTrsf.IsIdentity())
+  {
+    // no projection transformation
+    aViewLin = gp_Lin (gp_Pnt (theX, theY, 0.0), gp_Dir (0.0, 0.0, -1.0));
   }
-  Transform(L, myInvTrsf);
-  return L;
-}
+  else
+  {
+    // get direction of projection over the point in view space
+    Graphic3d_Mat4d aProjInv;
+    if (!myProjTrsf.Inverted (aProjInv))
+    {
+      return gp_Lin();
+    }
 
+    Graphic3d_Vec4d aVPnt1 = aProjInv * Graphic3d_Vec4d (theX, theY, myZNear, 1.0);
+    Graphic3d_Vec4d aVPnt2 = aProjInv * Graphic3d_Vec4d (theX, theY, myZFar, 1.0);
+    aVPnt1 /= aVPnt1.w();
+    aVPnt2 /= aVPnt2.w();
 
-//=======================================================================
-//function : SetDirection
-//purpose  : 
-//=======================================================================
+    gp_Vec aViewDir (aVPnt2.x() - aVPnt1.x(), aVPnt2.y() - aVPnt1.y(), aVPnt2.z() - aVPnt1.z());
 
-void Select3D_Projector::SetDirection () 
-{
-  gp_Vec V1(1,0,0);
-  Transform(V1);
-  if ((Abs(V1.X()) + Abs(V1.Y())) < Precision::Angular()) V1.SetCoord(1,1,0);
-  gp_Vec2d D1(V1.X(),V1.Y());
-  myD1.SetCoord(-D1.Y(),D1.X());
-  gp_Vec V2(0,1,0);
-  Transform(V2);
-  if ((Abs(V2.X()) + Abs(V2.Y())) < Precision::Angular()) V2.SetCoord(1,1,0);
-  gp_Vec2d D2(V2.X(),V2.Y());
-  myD2.SetCoord(-D2.Y(),D2.X());
-  gp_Vec V3(0,0,1);
-  Transform(V3);
-  if ((Abs(V3.X()) + Abs(V3.Y())) < Precision::Angular()) V3.SetCoord(1,1,0);
-  gp_Vec2d D3(V3.X(),V3.Y());
-  myD3.SetCoord(-D3.Y(),D3.X());
-}
+    aViewLin = gp_Lin (gp_Pnt (aVPnt1.x(), aVPnt1.y(), aVPnt1.z()), gp_Dir (aViewDir));
+  }
 
-void Select3D_Projector::SetView(const Handle(V3d_View)& aViou)
-{
-  myView = aViou;
-  myPersp = aViou->Type()==V3d_PERSPECTIVE;
-  myFocus= aViou->Focale();
-  Standard_Real Xat,Yat,Zat,XUp,YUp,ZUp,DX,DY,DZ;
-  //Standard_Boolean Pers=Standard_False;
-  
-  aViou->At(Xat,Yat,Zat);
-  aViou->Up(XUp,YUp,ZUp);
-  aViou->Proj(DX,DY,DZ);
-  gp_Pnt At (Xat,Yat,Zat); 
-  gp_Dir Zpers (DX,DY,DZ);
-  gp_Dir Ypers (XUp,YUp,ZUp);
-  gp_Dir Xpers = Ypers.Crossed(Zpers);
-  gp_Ax3 Axe (At, Zpers, Xpers);
-  myScaledTrsf.SetTransformation(Axe);
-  Scaled();
-  
+  // view transformation
+  Transform (aViewLin, myInvTrsf);
+
+  return aViewLin;
 }