text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkInteractorStyleUnicam.h
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  
       This software is distributed WITHOUT ANY WARRANTY; without even
       the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE.  See the above copyright notice for more information.
  
  =========================================================================*/
  
  /*
   * This work (vtkInteractorStyleUnicam.h) was produced under a grant from
   * the Department of Energy to Brown University.  Neither Brown University
   * nor the authors assert any copyright with respect to this work and it may
   * be used, reproduced, and distributed without permission.
   */
  
  // .NAME vtkInteractorStyleUnicam - provides Unicam navigation style
  // .SECTION Description
  // UniCam is a camera interactor.  Here, just the primary features of the
  // UniCam technique are implemented.  UniCam requires just one mouse button
  // and supports context sensitive dollying, panning, and rotation.  (In this
  // implementation, it uses the right mouse button, leaving the middle and
  // left available for other functions.) For more information, see the paper
  // at:
  //
  //    ftp://ftp.cs.brown.edu/pub/papers/graphics/research/unicam.pdf
  //
  // The following is a brief description of the UniCam Camera Controls.  You
  // can perform 3 operations on the camera: rotate, pan, and dolly the camera.
  // All operations are reached through the right mouse button & mouse
  // movements.
  //
  // IMPORTANT: UniCam assumes there is an axis that makes sense as a "up"
  // vector for the world.  By default, this axis is defined to be the
  // vector <0,0,1>.  You can set it explicitly for the data you are
  // viewing with the 'SetWorldUpVector(..)' method in C++, or similarly
  // in Tcl/Tk (or other interpreted languages).
  //
  // 1. ROTATE:
  //
  // Position the cursor over the point you wish to rotate around and press and
  // release the left mouse button.  A 'focus dot' appears indicating the
  // point that will be the center of rotation.  To rotate, press and hold the
  // left mouse button and drag the mouse.. release the button to complete the
  // rotation.
  //
  // Rotations can be done without placing a focus dot first by moving the
  // mouse cursor to within 10% of the window border & pressing and holding the
  // left button followed by dragging the mouse.  The last focus dot position
  // will be re-used.
  //
  // 2. PAN:
  //
  // Click and hold the left mouse button, and initially move the mouse left
  // or right.  The point under the initial pick will pick correlate w/ the
  // mouse tip-- (i.e., direct manipulation).
  //
  // 3. DOLLY (+ PAN):
  //
  // Click and hold the left mouse button, and initially move the mouse up or
  // down.  Moving the mouse down will dolly towards the picked point, and moving
  // the mouse up will dolly away from it.  Dollying occurs relative to the
  // picked point which simplifies the task of dollying towards a region of
  // interest. Left and right mouse movements will pan the camera left and right.
  //
  // .SECTION Caveats
  // (NOTE: This implementation of Unicam assumes a perspective camera.  It
  // could be modified relatively easily to also support an orthographic
  // projection.)
  
  
  #ifndef vtkInteractorStyleUnicam_h
  #define vtkInteractorStyleUnicam_h
  
  #include "vtkInteractionStyleModule.h" // For export macro
  #include "vtkInteractorStyle.h"
  
  class vtkCamera;
  class vtkWorldPointPicker;
  
  //
  // XXX - would have preferred to make these enumerations within the class,
  //    enum { NONE=0, BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT };
  //    enum {CAM_INT_ROT, CAM_INT_CHOOSE, CAM_INT_PAN, CAM_INT_DOLLY};
  // but vtkWrapTcl signaled a "syntax error" when it parsed the 'enum' line.
  // So, am making them defines which is what the other classes that want
  // to have constants appear to do.
  //
  // buttons pressed
  #define VTK_UNICAM_NONE           0
  #define VTK_UNICAM_BUTTON_LEFT    1
  #define VTK_UNICAM_BUTTON_MIDDLE  2
  #define VTK_UNICAM_BUTTON_RIGHT   3
  //
  // camera modes
  #define VTK_UNICAM_CAM_INT_ROT    0
  #define VTK_UNICAM_CAM_INT_CHOOSE 1
  #define VTK_UNICAM_CAM_INT_PAN    2
  #define VTK_UNICAM_CAM_INT_DOLLY  3
  
  class VTKINTERACTIONSTYLE_EXPORT vtkInteractorStyleUnicam : public vtkInteractorStyle
  {
  public:
    static vtkInteractorStyleUnicam *New();
    vtkTypeMacro(vtkInteractorStyleUnicam,vtkInteractorStyle);
    void PrintSelf(ostream& os, vtkIndent indent);
  
    void SetWorldUpVector(double a[3]) {this->SetWorldUpVector(a[0],a[1],a[2]);}
    void SetWorldUpVector(double x, double y, double z);
    vtkGetVectorMacro(WorldUpVector, double, 3);
  
    // Description:
    // Concrete implementation of event bindings
    virtual void OnMouseMove();
    virtual void OnLeftButtonDown();
    virtual void OnLeftButtonUp();
    virtual void OnLeftButtonMove();
  
    // Description:
    // OnTimer calls RotateCamera, RotateActor etc which should be overridden by
    // style subclasses.
    virtual void OnTimer();
  
  protected:
    vtkInteractorStyleUnicam();
    virtual ~vtkInteractorStyleUnicam();
  
    vtkWorldPointPicker *InteractionPicker;
  
    int      ButtonDown;   // which button is down
    double   DTime;        // time mouse button was pressed
    double   Dist;         // distance the mouse has moved since button press
    double    StartPix[2]; // pixel mouse movement started at
    double    LastPos[2];  // normalized position of mouse last frame
    double    LastPix[2];  // pixel position of mouse last frame
    double    DownPt[3];   // 3D point under cursor when mouse button pressed
    double    Center [3];   // center of camera rotation
  
    double    WorldUpVector[3]; // what the world thinks the 'up' vector is
  
    vtkActor    *FocusSphere; // geometry for indicating center of rotation
    int          IsDot;       // flag-- is the FocusSphere being displayed?
    vtkRenderer *FocusSphereRenderer;  // renderer for 'FocusSphere'
  
    int state;                 // which navigation mode was selected?
  
    void ChooseXY( int X, int Y );  // method for choosing type of navigation
    void RotateXY( int X, int Y );  // method for rotating
    void DollyXY( int X, int Y );  // method for dollying
    void PanXY( int X, int Y );  // method for panning
  
    // conveinence methods for translating & rotating the camera
    void  MyTranslateCamera(double v[3]);
    void  MyRotateCamera(double cx, double cy, double cz,
                         double ax, double ay, double az,
                         double angle);
  
    // Given a 3D point & a vtkCamera, compute the vectors that extend
    // from the projection of the center of projection to the center of
    // the right-edge and the center of the top-edge onto the plane
    // containing the 3D point & with normal parallel to the camera's
    // projection plane.
    void  GetRightVandUpV(double *p, vtkCamera *cam,
                          double *rightV, double *upV);
  
    // takes in pixels, returns normalized window coordinates
    void  NormalizeMouseXY(int X, int Y, double *NX, double *NY);
  
    // return the aspect ratio of the current window
    double WindowAspect();
  private:
    vtkInteractorStyleUnicam(const vtkInteractorStyleUnicam&);  // Not implemented.
    void operator=(const vtkInteractorStyleUnicam&);  // Not implemented.
  };
  
  #endif  // vtkInteractorStyleUnicam_h
  
  
  
  