text: /*****************************************************************************
  *
  * Copyright (c) 2000 - 2014, Lawrence Livermore National Security, LLC
  * Produced at the Lawrence Livermore National Laboratory
  * LLNL-CODE-442911
  * All rights reserved.
  *
  * This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
  * full copyright notice is contained in the file COPYRIGHT located at the root
  * of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
  *
  * Redistribution  and  use  in  source  and  binary  forms,  with  or  without
  * modification, are permitted provided that the following conditions are met:
  *
  *  - Redistributions of  source code must  retain the above  copyright notice,
  *    this list of conditions and the disclaimer below.
  *  - Redistributions in binary form must reproduce the above copyright notice,
  *    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
  *    documentation and/or other materials provided with the distribution.
  *  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
  *    be used to endorse or promote products derived from this software without
  *    specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
  * ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
  * LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
  * DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
  * CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
  * LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
  * OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  * DAMAGE.
  *
  *****************************************************************************/
  
  // ************************************************************************* //
  //                            VisitInteractor.h                              //
  // ************************************************************************* //
  
  #ifndef VISIT_INTERACTOR_H
  #define VISIT_INTERACTOR_H
  #include <viswindow_exports.h>
  
  
  #include <vtkInteractorStyleTrackballCamera.h>
  #include <avtViewInfo.h>
  
  class VisWindow;
  class VisWindowInteractorProxy;
  
  
  typedef   void (*ViewCallback)(VisWindow *);
  
  
  // ****************************************************************************
  //  Class: VisitInteractor
  //
  //  Purpose:
  //    An abstract type that all of Visit's interactions should be derived
  //    from.  This is a derived type of vtkInteractorStyle because it is not 
  //    easy to remap the mouse button presses through interactor's method, but
  //    very easy to redefine the virtual methods for each button 
  //    press/release.  It is derived from a trackball interactor so that we 
  //    can use the trackball features free of charge.
  //
  //  Note:    Although this type is derived from a VTK type, it does not follow
  //           the VTK contructor (ie New) and memory management (object factory)
  //           constructs of VTK.
  //
  //  Programmer: Hank Childs
  //  Creation:   May 19, 2000
  //
  //  Modifications:
  //    Hank Childs, Thu Jul  6 14:48:45 PDT 2000
  //    Disable keystrokes.
  //
  //    Hank Childs, Mon Dec 18 09:18:35 PST 2000
  //    Removed bounding box mode as a part of a VisIt interactor.
  //
  //    Hank Childs, Tue Jul 17 08:54:08 PDT 2001
  //    Add callback when the view changes.
  //
  //    Eric Brugger, Tue Aug 21 09:54:42 PDT 2001
  //    I removed the avtViewInfo argument from ViewCallback.
  //
  //    Hank Childs, Mon Mar 18 13:17:52 PST 2002
  //    Added better support for keeping track of button-push operations.
  //
  //    Eric Brugger, Thu Apr 11 16:05:10 PDT 2002
  //    I moved the vector and matrix manipulation methods from Navigate3D
  //    to VisitInteractor.
  //
  //    Kathleen Bonnell, Fri Dec 13 14:07:15 PST 2002
  //    Inherit from vtkInteractorStyleTrackballCamera as 
  //    vtkInteractorStyleTrackball has been deprecated.  Comply with new
  //    interactor interface by removing arguments from all Button methods, 
  //    OnMouseMove, and PrepTrackball.  Added members that were part of old
  //    parent class, but are not in the new: OldX/Y, Center, MotionFactor.
  //
  //    Hank Childs, Tue Jul 20 10:54:45 PDT 2004
  //    Add methods to check on whether buttons are depressed.
  //
  //    Eric Brugger, Mon Nov 22 08:30:11 PST 2004
  //    I added ZoomCamera2D.
  //
  //    Eric Brugger, Tue Dec 28 13:30:15 PST 2004
  //    I moved RotateCamera, PanCamera and ZoomCamera from the FlyThrough
  //    class as RotateAboutCamera3D, PanCamera3D and DollyCameraAndFocus3D.
  //    I moved RotateCamera, PanCamera and ZoomCamera from the Navigate3D
  //    class as RotateAboutFocus3D, PanImage3D and ZoomImage3D.  I added
  //    DollyCameraTowardFocus3D.
  //
  //    Hank Childs, Thu Dec 29 10:30:53 PST 2005
  //    Added Boolean argument to IssueViewCallback.
  //
  //    Gunther H. Weber, Tue Aug  7 13:50:25 PDT 2007
  //    Split ZoomImage3D and ZoomCamera2D into two functions, one computing the
  //    zoom factor from the mouse move and one computing the zommed view so that
  //    mouse wheel events can make use of this function.
  //
  //    Hank Childs, Tue Jan  8 11:22:44 PST 2008
  //    Disallow mouse wheel movements where they are not intended.
  //
  // ****************************************************************************
  
  class VISWINDOW_API VisitInteractor : public vtkInteractorStyleTrackballCamera
  {
    public:
                                  VisitInteractor(VisWindowInteractorProxy &);
      virtual                    ~VisitInteractor();
   
      static void                 RegisterViewCallback(ViewCallback);
  
      virtual void                OnLeftButtonDown();
      virtual void                OnLeftButtonUp();
      virtual void                OnMiddleButtonDown();
      virtual void                OnMiddleButtonUp();
      virtual void                OnRightButtonDown();
      virtual void                OnRightButtonUp();
      virtual void                OnChar();
  
      // Define these to make sure they are no-ops, and that we don't get the
      // VTK behavior.  Derived classes are welcome to redefine them.
      virtual void                OnMouseWheelForward() {;};
      virtual void                OnMouseWheelBackward() {;};
  
      virtual void                OnMouseMove();
  
      virtual void                StartLeftButtonAction();
      virtual void                AbortLeftButtonAction();
      virtual void                EndLeftButtonAction();
  
      virtual void                StartMiddleButtonAction();
      virtual void                AbortMiddleButtonAction();
      virtual void                EndMiddleButtonAction();
  
      virtual void                StartRightButtonAction();
      virtual void                AbortRightButtonAction();
      virtual void                EndRightButtonAction();
  
      virtual void                SetInteractor(vtkRenderWindowInteractor *);
  
      virtual bool                LeftButtonIsDown(void)
                                                    { return leftButtonDown; };
      virtual bool                MiddleButtonIsDown(void)
                                                    { return middleButtonDown; };
      virtual bool                RightButtonIsDown(void)
                                                    { return rightButtonDown; };
  
    protected:
      VisWindowInteractorProxy   &proxy;
  
      int                         lastX, lastY;
      int                         lastCallbackX, lastCallbackY;
      bool                        leftButtonDown;
      bool                        middleButtonDown;
      bool                        rightButtonDown;
  
      float                       OldX, OldY;
      float                       spinOldX, spinOldY;
      int                         spinNewX, spinNewY;
      float                       Center[2];
      float                       MotionFactor;
  
  
      void                        PrepTrackball();
      void                        NewButtonPress();
  
      void                        MotionBegin(void);
      void                        MotionEnd(void);
      void                        IssueViewCallback(bool = false);
      void                        StartBoundingBox(void);
      void                        EndBoundingBox(void);
  
      void                        ZoomCamera2D(double);
      void                        ZoomCamera2D(const int, const int);
      void                        PanImage3D(const int, const int);
      void                        PanCamera3D(const int, const int);
      void                        ZoomImage3D(double);
      void                        ZoomImage3D(const int, const int);
      void                        DollyCameraTowardFocus3D(const int, const int);
      void                        DollyCameraAndFocus3D(const int, const int);
      void                        RotateAboutFocus3D(const int, const int,
                                      const bool);
      void                        RotateAboutCamera3D(const int, const int);
  
      inline void                 VectorSet(double *, const double, const double,
                                      const double) const;
      inline void                 VectorCross(const double *, const double *,
                                      double *) const;
      inline void                 VectorCopy(const double *, double *) const;
      inline void                 VectorSubtract(const double *, const double *,
                                      double *) const;
      inline double               VectorLength(const double *) const;
      inline void                 VectorScale(double *, const double) const;
      inline void                 VectorPrint(const char *, const double *) const;
      inline void                 VectorMatrixMult(const double [3],
                                      const double [3][3], double [3]) const;
  
      inline void                 MatrixSet(double [3][3], const double [3],
                                      const double [3], const double [3]) const;
      inline void                 MatrixTranspose(const double [3][3],
                                      double [3][3]) const;
      inline void                 MatrixMult(const double [3][3],
                                      const double [3][3], double [3][3]) const;
      inline void                 MatrixPrint(const char *, const double [3][3])
                                      const;
  
    private:
      static ViewCallback         viewCallback;
  };
  
  // ****************************************************************************
  //  Method: VisitInteractor::VectorSet
  //
  //  Purpose:
  //    Set a 3 dimensional vector given its components.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::VectorSet(double v[3], const double v0, const double v1,
      const double v2) const
  {
      v[0] = v0;
      v[1] = v1;
      v[2] = v2;
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::VectorCross
  //
  //  Purpose:
  //    Calculate the cross product of two 3 dimensional vectors.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::VectorCross(const double v1[3], const double v2[3],
      double vout[3]) const
  {
      vout[0] = (v1[1]*v2[2]) - (v1[2]*v2[1]);
      vout[1] = (v1[2]*v2[0]) - (v1[0]*v2[2]);
      vout[2] = (v1[0]*v2[1]) - (v1[1]*v2[0]);
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::VectorCopy
  //
  //  Purpose:
  //    Copy a 3 dimensional vector.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::VectorCopy(const double v[3], double vout[3]) const
  {
      vout[0] = v[0];
      vout[1] = v[1];
      vout[2] = v[2];
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::VectorSubtract
  //
  //  Purpose:
  //    Calculate the difference between two 3 dimensional vectors.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::VectorSubtract(const double v1[3], const double v2[3],
      double vout[3]) const
  {
      vout[0] = v1[0] - v2[0];
      vout[1] = v1[1] - v2[1];
      vout[2] = v1[2] - v2[2];
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::VectorLength
  //
  //  Purpose:
  //    Calculate the length of a 3 dimensional vector.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline double
  VisitInteractor::VectorLength(const double v[3]) const
  {
      return sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]));
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::VectorScale
  //
  //  Purpose:
  //    Scale a 3 dimensional vector.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::VectorScale(double v[3], const double scale) const
  {
      v[0] *= scale;
      v[1] *= scale;
      v[2] *= scale;
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::VectorPrint
  //
  //  Purpose:
  //    Print a 3 dimensional vector.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::VectorPrint(const char *name, const double v[3]) const
  {
      cout << name << " = ";
      cout << v[0] << ", " << v[1] << ", " << v[2] << endl;
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::VectorMatrixMult
  //
  //  Purpose:
  //    Multiply a 3 dimensional vector against a 3x3 matrix.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::VectorMatrixMult(const double v1[3], const double m[3][3],
      double vout[3]) const
  {
      vout[0] = v1[0]*m[0][0] + v1[1]*m[1][0] + v1[2]*m[2][0];
      vout[1] = v1[0]*m[0][1] + v1[1]*m[1][1] + v1[2]*m[2][1];
      vout[2] = v1[0]*m[0][2] + v1[1]*m[1][2] + v1[2]*m[2][2];
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::MatrixSet
  //
  //  Purpose:
  //    Set a 3x3 matrix given three 3 dimensional vectors.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::MatrixSet(double mout[3][3], const double v0[3],
      const double v1[3], const double v2[3]) const
  {
      mout[0][0] = v0[0];
      mout[0][1] = v1[0];
      mout[0][2] = v2[0];
      mout[1][0] = v0[1];
      mout[1][1] = v1[1];
      mout[1][2] = v2[1];
      mout[2][0] = v0[2];
      mout[2][1] = v1[2];
      mout[2][2] = v2[2];
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::MatrixTranspose
  //
  //  Purpose:
  //    Transpose a 3x3 matrix.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::MatrixTranspose(const double m[3][3], double mout[3][3]) const
  {
      mout[0][0] = m[0][0];
      mout[0][1] = m[1][0];
      mout[0][2] = m[2][0];
      mout[1][0] = m[0][1];
      mout[1][1] = m[1][1];
      mout[1][2] = m[2][1];
      mout[2][0] = m[0][2];
      mout[2][1] = m[1][2];
      mout[2][2] = m[2][2];
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::MatrixMult
  //
  //  Purpose:
  //    Multiply two 3x3 matrices together.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::MatrixMult(const double m1[3][3], double const m2[3][3],
      double mout[3][3]) const
  {
      mout[0][0] = m1[0][0]*m2[0][0] + m1[0][1]*m2[1][0] + m1[0][2]*m2[2][0];
      mout[0][1] = m1[0][0]*m2[0][1] + m1[0][1]*m2[1][1] + m1[0][2]*m2[2][1];
      mout[0][2] = m1[0][0]*m2[0][2] + m1[0][1]*m2[1][2] + m1[0][2]*m2[2][2];
      mout[1][0] = m1[1][0]*m2[0][0] + m1[1][1]*m2[1][0] + m1[1][2]*m2[2][0];
      mout[1][1] = m1[1][0]*m2[0][1] + m1[1][1]*m2[1][1] + m1[1][2]*m2[2][1];
      mout[1][2] = m1[1][0]*m2[0][2] + m1[1][1]*m2[1][2] + m1[1][2]*m2[2][2];
      mout[2][0] = m1[2][0]*m2[0][0] + m1[2][1]*m2[1][0] + m1[2][2]*m2[2][0];
      mout[2][1] = m1[2][0]*m2[0][1] + m1[2][1]*m2[1][1] + m1[2][2]*m2[2][1];
      mout[2][2] = m1[2][0]*m2[0][2] + m1[2][1]*m2[1][2] + m1[2][2]*m2[2][2];
  }
  
  // ****************************************************************************
  //  Method: VisitInteractor::MatrixPrint
  //
  //  Purpose:
  //    Print a 3x3 matrix.
  //
  //  Programmer: Eric Brugger
  //  Creation:   August 10, 2001
  //
  // ****************************************************************************
  
  inline void
  VisitInteractor::MatrixPrint(const char *name, const double m[3][3]) const
  {
      size_t       i;
      size_t       nSpaces = strlen(name) + 3;
  
      cout << name << " = ";
      cout << m[0][0] << ", " << m[0][1] << ", " << m[0][2] << endl;
      for (i = 0; i < nSpaces; i++) cout << " ";
      cout << m[1][0] << ", " << m[1][1] << ", " << m[1][2] << endl;
      for (i = 0; i < nSpaces; i++) cout << " ";
      cout << m[2][0] << ", " << m[2][1] << ", " << m[2][2] << endl;
  }
  
  #endif
  