/*=========================================================================

  Program:   Visualization Toolkit
  Module:    controls.cpp
  Language:  C++
  Date:      Date: 08/15/2002 17:00:00 
  Version:   Revision: 1.0 

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen 
All rights reserved.

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 following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 THE AUTHORS 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.

=========================================================================*/

/*************************************************************
Right now the controls class contains many unnecessary methods
and much extraneous information.  However, I think I will leave
it for now in case anything needs to be changed later.  
**************************************************************/


#include "controls.h"
#include "vtkMath.h"
#include "vtkPropPicker.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkObjectFactory.h"
#include "vtkCommand.h"
#include "vtkAssemblyNode.h"
#include "vtkInteractorStyleUser.h"
#include "vtkWindowToImageFilter.h"
#include "vtkPostScriptWriter.h"
#include "vtkRenderLargeImage.h"
#include <string>
#include <iostream.h>
#include <math.h>

#include "grid3D.h"
#include "coastlines.h"
#include "textDisplay.h"
#include "topography.h"
#include "visibility.h"
//---------------------------------------------------------------------------
controls* controls::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("controls");
  if(ret) {
    return (controls*)ret;
  }
  // If the factory was unable to create the object, then create it here.  
  return new controls;
}

controls::controls()
{
  // for actor interactions
  this->MotionFactor      = 10.0;
  this->InteractionPicker = vtkPropPicker::New();
  this->PropPicked        = 0;
  this->InteractionProp   = NULL;

  this->FOCAL_LENGTH = 0.5;

  // set to default modes
  this->TrackballMode     = VTKIS_TRACK;       // Set to trackball by default!
  this->ActorMode         = VTKIS_CAMERA;      // Not sure what this is.
  this->ControlMode       = VTKIS_CONTROL_OFF; // Or this...
  this->OldX              = 0.0;
  this->OldY              = 0.0;
  this->Preprocess        = 1;
  this->RadianToDegree    = 180.0 / vtkMath::Pi();

  this->NewPickPoint[0]   = 0.0;
  this->NewPickPoint[1]   = 0.0;
  this->NewPickPoint[2]   = 0.0;
  this->NewPickPoint[3]   = 1.0;
  this->OldPickPoint[0]   = 0.0;
  this->OldPickPoint[1]   = 0.0;
  this->OldPickPoint[2]   = 0.0;
  this->OldPickPoint[3]   = 1.0;
  this->MotionVector[0]   = 0.0;
  this->MotionVector[1]   = 0.0;
  this->MotionVector[2]   = 0.0;
  this->ViewLook[0]       = 0.0;
  this->ViewLook[1]       = 0.0;
  this->ViewLook[2]       = 0.0;
  this->ViewPoint[0]      = 0.0;
  this->ViewPoint[1]      = 0.0;
  this->ViewPoint[2]      = 0.0;
  this->ViewFocus[0]      = 0.0;
  this->ViewFocus[1]      = 0.0;
  this->ViewFocus[2]      = 0.0;
  this->ViewUp[0]         = 0.0;
  this->ViewUp[1]         = 0.0;
  this->ViewUp[2]         = 0.0;
  this->ViewRight[0]      = 0.0;
  this->ViewRight[1]      = 0.0;
  this->ViewRight[2]      = 0.0;  

  this->Origin[0]         = 0.0;
  this->Origin[1]         = 0.0;
  this->Origin[2]         = 0.0;
  this->Position[0]       = 0.0;
  this->Position[1]       = 0.0;
  this->Position[2]       = 0.0;
  this->ObjCenter[0]      = 0.0;
  this->ObjCenter[1]      = 0.0;
  this->ObjCenter[2]      = 0.0;  
  this->DispObjCenter[0]  = 0.0;
  this->DispObjCenter[1]  = 0.0;
  this->DispObjCenter[2]  = 0.0;
  this->Radius            = 0.0;

  //this->KeyPressTag = 0;
  this->Char = '\0';
  this->KeySym = (char *) "";

  // sets flag; will be changed in methods
  this->shiftClick = false;
  this->ctrlClick = false;
}

controls::~controls() 
{
  this->InteractionPicker->Delete();
}



//----------------------------------------------------------------------------
// Intercept any keypresses which are style independent here and do the rest in
// subclasses - none really required yet!
//----------------------------------------------------------------------------
void controls::OnChar(int ctrl, int shift, 
                                     char keycode, int repeatcount) 
{
  // first invoke superclass method
  //this->vtkInteractorStyle::OnChar(ctrl,shift,keycode,repeatcount);
  vtkRenderWindowInteractor *rwi = this->Interactor;

  // catch additional keycodes
  switch (keycode) {
    
  // Bail keycodes...
  case 27: // ESC key
  case 'Q':
  case 'q':
      rwi->ExitCallback();
      break;

  }
}

//----------------------------------------------------------------------------

void controls::OnKeyPress(int ctrl, int shift, char keycode, char *keysym,  int repeatcount)
{
    //invoke the interactor
    vtkRenderWindowInteractor *rwi = this->Interactor;


        switch(keycode)
        {
            // rotates left
            case 'h':
            case 'H':
                OnLeftArrowDown();  
                break;

            // rotates right
            case 'l':
            case 'L':
                OnRightArrowDown(); 
                break;

            // rotates down
            case 'j':
            case 'J':
                OnDownArrowDown();  
                break;

            // rotates up
            case 'k':
            case 'K':
                OnUpArrowDown();
                break;

            //zooms to lat and long.
            case 'z':
            case 'Z':
                ZoomToLocation();
                break;

            // tweaks topography visibility
            case 't':
            case 'T':
                ChangeVisibility('t');
                break;

            // tweaks coastline visibility
            case 'c':
            case 'C':
                ChangeVisibility('c');
                break;

            // tweaks gridline visibility
            case 'g':
            case 'G':
                ChangeVisibility('g');
                break;
        
            // zooms (dollies) in (closer to)
            case '<':
            case ',':
                OnZoomIn();
                break;

            // zooms (dollies) out (further away)
            case '>':
            case '.':
                OnZoomOut();
                break;

            // saves image in PostScript file
            case 'p':
            case 'P':
                SaveToPostScript();
                break;

            // saves high-resolution image in PostScript file
            case 'v':
            case 'V':
                SaveToHiResPostScript();
                break;

            // returns to start settings
            case 'r':
            case 'R':
                OriginalSettings();
                break;

            default:
                break;

        }
        //makes sure changes are seen on RenderWindow
        rwi->Render();
}

//----------------------------------------------------------------------------

void controls::OnRightArrowDown() 
{
    int X = 0, Y = 0;
    vtkRenderWindowInteractor *rwi = this->Interactor;
    this->UpdateInternalState(NULL, NULL, X, Y);
    this->FindPokedCamera(X,Y);
    
    this->CurrentCamera->Azimuth(30);
    rwi->Render(); 
}

//----------------------------------------------------------------------------

void controls::OnDownArrowDown() 
{
    int X = 0, Y = 0;
    vtkRenderWindowInteractor *rwi = this->Interactor;
 this->UpdateInternalState(NULL, NULL, X, Y);
 this->FindPokedCamera(X,Y);
  
        this->CurrentCamera->Elevation(-30);
        rwi->Render(); 
}

//----------------------------------------------------------------------------

void controls::OnUpArrowDown() 
{
    int X = 0, Y = 0;
    vtkRenderWindowInteractor *rwi = this->Interactor;
 this->UpdateInternalState(NULL, NULL, X, Y);
 this->FindPokedCamera(X,Y);


 //double* position = this->CurrentCamera->GetPosition()
        //cout<<"position  is " <<
  
        this->CurrentCamera->Elevation(30);
        rwi->Render(); 
}

//----------------------------------------------------------------------------

void controls::OnZoomIn() 
{
    int X = 0, Y = 0;
    vtkRenderWindowInteractor *rwi = this->Interactor;
 this->UpdateInternalState(NULL, NULL, X, Y);
 this->FindPokedCamera(X,Y);
  
        this->CurrentCamera->Dolly(1.2);
        this->CurrentCamera->SetClippingRange(.01, 10000);
        rwi->Render(); 
}

//----------------------------------------------------------------------------

void controls::OnZoomOut() 
{
    int X = 0, Y = 0;
    vtkRenderWindowInteractor *rwi = this->Interactor;
 this->UpdateInternalState(NULL, NULL, X, Y);
 this->FindPokedCamera(X,Y);
  
        this->CurrentCamera->Dolly(.8);
        this->CurrentCamera->SetClippingRange(.01, 1000);
        rwi->Render(); 
}

//----------------------------------------------------------------------------

void controls::OriginalSettings() 
{
    int X = 0, Y = 0;
    vtkRenderWindowInteractor *rwi = this->Interactor;
 this->UpdateInternalState(NULL, NULL, X, Y);
 this->FindPokedCamera(X,Y);

        this->CurrentCamera->SetClippingRange(.01, 1000);
        this->CurrentCamera->SetViewUp(0.0, 1.0, 0.0);
        this->CurrentCamera->OrthogonalizeViewUp();
        this->CurrentCamera->SetPosition(6.0, 0.0, 0.0);
        this->CurrentCamera->Roll(-90);
        this->CurrentCamera->Azimuth(-30);
        this->CurrentCamera->Elevation(60);
        this->CurrentCamera->Dolly(1.0);
        
        rwi->Render(); 
}

//----------------------------------------------------------------------------

void controls::SaveToPostScript() 
{
    const int ltmp = 512;

    char psfilename[ltmp];
    int itmp;
    for (itmp=0; itmp<ltmp; itmp++)
                psfilename[itmp] = 0;

    char* psfile = "tmp.ps";
    vtkWindowToImageFilter *w2i = vtkWindowToImageFilter::New();
    w2i->SetInput(renWin);
    vtkPostScriptWriter *writer = vtkPostScriptWriter::New();
    writer->SetInput(w2i->GetOutput());
    cout << "Enter PostScript filename for saved image ["
         << psfile << "]: " << flush;
    cin.setf(ios::skipws);
    cin.width(1);
    cin.getline(psfilename,ltmp);
    if (strlen(psfilename) > 0) psfile = psfilename;
    cout << "PostScript will be saved to " << psfile << endl;
    writer->SetFileName(psfile);
    writer->Write();
}

//----------------------------------------------------------------------------
void controls::SaveToHiResPostScript() 
{
    const int ltmp = 512;

    char psfilename[ltmp];
    int itmp;
    for (itmp=0; itmp<ltmp; itmp++)
                psfilename[itmp] = 0;

    char* psfile = "hires.ps";
    vtkRenderLargeImage *renderLarge = vtkRenderLargeImage::New();
    renderLarge->SetInput(renderer);
    renderLarge->SetMagnification(4);
    vtkPostScriptWriter *writer = vtkPostScriptWriter::New();
    writer->SetInput(renderLarge->GetOutput());
    cout << "Enter PostScript filename for high-resolution image ["
         << psfile << "]: " << flush;
    cin.setf(ios::skipws);
    cin.width(1);
    cin.getline(psfilename,ltmp);
    if (strlen(psfilename) > 0) psfile = psfilename;
    cout << "High-resolution PostScript will be saved to " << psfile << endl;
    writer->SetFileName(psfile);
    writer->Write();
}

//----------------------------------------------------------------------------

void controls::ZoomToLocation()
{
    int X = 0, Y = 0; //not sure what these do

    double Lat;
    double Long;
    double Distance = 20.0;
    double DollyDistance = 200.0;
    const int ignorer = 8;
    cout<<"\nEnter Latitude and Longitude of new viewpoint.\n"<<endl;

    for(;;)
    {   
        cout<<"Latitude: "<<flush;
        cin >> Lat;

        if (cin)
        {
            cin.ignore(ignorer, '\n');
            if(Lat >=90)
            {
                Lat = 87;
                cout<<"Latitude >= 90 degrees\n is now "<<Lat;
            }
            else if (Lat <=-90)
            {
                Lat = -87;
            }
            
            break;
        }
        cin.clear();
        cin.ignore(ignorer, '\n');
        cout<<"Input was bad\n"<<endl;
    }

    for(;;)
    {   
        cout<<"\nLongitude: "<<flush;
        cin >> Long;

        if (cin)
        {
            cin.ignore(ignorer, '\n');
            
        //program breaks if lat is exacly 90 need to fix
        //fixed by setting lat to 87.  this was the orthogonal view is not reset
            break;
        }
        cin.clear();
        cin.ignore(ignorer, '\n');
        cout<<"Input was bad\n"<<endl;
    }


    const double piOver180 = 3.14159/180;
//  Lat = Lat;
    Lat*=piOver180;
    Long*=piOver180;
    
//*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/


    //Longitude is Theta
    //Latitude is Phi

    //double x = cos(Long)*cos(Lat);
    //double y = sin(Long);
    //double z = cos(Long)*sin(Lat);

    cout << "Cartesian transformation:\n"
         << "Latitude [radian] = " << Lat << ", longitude = " << Long << endl;
    double x = Distance * (cos(Lat))*(cos(Long));
    double y = Distance * (cos(Lat))*(sin(Long));
    double z = Distance * sin(Lat);
    cout << "X = " << x << ", Y = " << y << ", Z = " << z << endl;


    cout<<Distance<<endl;

        vtkRenderWindowInteractor *rwi = this->Interactor;
        
        //extern vtkRenderer *renderer;

        renWin->AddRenderer(renderer);// A Window has a Renderer
        iren->SetRenderWindow(renWin);// An Interactor has a Window

        this->UpdateInternalState(NULL, NULL, X, Y);
        this->FindPokedCamera(X,Y);
        
        this->CurrentCamera->SetClippingRange(.01, 1000);

      //this->CurrentCamera = renderer->GetActiveCamera();
        this->CurrentCamera->SetViewUp(0.0, 1.0, 0.0);
        this->CurrentCamera->OrthogonalizeViewUp();
        this->CurrentCamera->SetPosition(6.0, 0.0, 0.0);
        this->CurrentCamera->Roll(-90);
        this->CurrentCamera->Azimuth(-30);
        this->CurrentCamera->Elevation(60);
        this->CurrentCamera->Dolly(1.0);
        this->CurrentCamera->Zoom(1.5);
        //this->CurrentCamera->GetViewPlaneNormal();
        //this->CurrentCamera->SetFocalPoint(0,0,0);

        this->CurrentCamera->SetPosition(x, y, z);

        cout << "Dolly Distance " << DollyDistance << endl;
        //this->CurrentCamera->Dolly(DollyDistance);
        this->CurrentCamera->Dolly(1.0);
        //this->CurrentCamera->ComputeViewPlaneNormal();

        
        renderer->SetActiveCamera(this->CurrentCamera);
        renderer->ResetCamera();




        rwi->Render();

} 

//----------------------------------------------------------------------------

void controls::ChangeVisibility(char mode)
{
    int X = 0, Y = 0;
    vtkRenderWindowInteractor *rwi = this->Interactor;
        this->UpdateInternalState(NULL, NULL, X, Y);
        this->FindPokedCamera(X,Y);

    //cout<<"in changeVisibility\n"<<flush;
        //    extern topography *colorDepths;
        //    extern coastlines *presentEarth;
         //   extern gridlines *horizGrid;
    switch(mode)
    {
        case 't':
            colorDepths->changeTopographyOn();
           break;
        case 'c':
            presentEarth->changeConOutlinesOn();
           break;
        case 'g':
            horizGrid->changeGridOn();
            break;
        default:
                break;
    }
        //    cout << "G - " << horizGrid->GetGridOn() << endl;
        //    cout << "C - " << presentEarth->getConOutlinesOn() << endl;
        //    cout << "T - " << colorDepths->getTopographyOn() << endl;
        extern visibility *seeActors;
        seeActors->UpdateNow();
    
    //rwi->Render();


}

/********************** somewhat modified methods ******************************/

//----------------------------------------------------------------------------
void controls::OnLeftButtonDown(int ctrl, int shift, 
                                               int X, int Y) 
{
    //cout<<"Inside OnLeftButtonDown\n";
    this->OldX = X;
    this->OldY = Y;

    this->UpdateInternalState(ctrl, shift, X, Y);

    if (this->ShiftKey && this->State == VTKIS_START) //change elevation dialog
    {
        this->shiftClick=true;
        this->ctrlClick=false;
        //cout << "I hit shift and left-clicked" << endl;
        vtkRenderWindowInteractor *rwi = this->Interactor;    
        vtkAssemblyPath *path = NULL;
        this->FindPokedRenderer(this->LastPos[0], this->LastPos[1]);
        rwi->StartPickCallback();
        rwi->GetPicker()->Pick(this->LastPos[0], this->LastPos[1],
                         defaultLandElevation, this->CurrentRenderer);
        vtkAbstractPropPicker *picker;
        if ((picker = vtkAbstractPropPicker::SafeDownCast(rwi->GetPicker())))
        {
          path = picker->GetPath();
        }
        
        if (path == NULL)
        {
          this->HighlightProp(NULL);
          this->PropPicked = 0;
        } 
        else
        {
          this->PropPicked = 1;
        }
        rwi->EndPickCallback();

    }
    else if (this->CtrlKey && this->State == VTKIS_START)
    {
        this->ctrlClick=true;
        this->shiftClick=false;
        //cout << "I ctrl-clicked" << endl;
        vtkRenderWindowInteractor *rwi = this->Interactor;
        vtkAssemblyPath *path = NULL;
        this->FindPokedRenderer(this->LastPos[0], this->LastPos[1]);
        rwi->StartPickCallback();
        rwi->GetPicker()->Pick(this->LastPos[0], this->LastPos[1],
                               0.0, this->CurrentRenderer);
        vtkAbstractPropPicker *picker;
        if ((picker = vtkAbstractPropPicker::SafeDownCast(rwi->GetPicker())))
        {
          path = picker->GetPath();
        }

        if (path == NULL)
        {
          this->HighlightProp(NULL);
          this->PropPicked = 0;
        }
            else
        {
          this->PropPicked = 1;
        }
        rwi->EndPickCallback();
    }
    else if (this->State == VTKIS_START) // print picked cell info?
    { 
        this->shiftClick=false;
        this->ctrlClick=false;
        //cout << "I left-clicked" << endl;
        vtkRenderWindowInteractor *rwi = this->Interactor;
        vtkAssemblyPath *path = NULL;
        this->FindPokedRenderer(this->LastPos[0], this->LastPos[1]);
        rwi->StartPickCallback();
        rwi->GetPicker()->Pick(this->LastPos[0], this->LastPos[1],
                               0.0, this->CurrentRenderer);
        vtkAbstractPropPicker *picker;
        if ((picker = vtkAbstractPropPicker::SafeDownCast(rwi->GetPicker())))
        {
          path = picker->GetPath();
        }

        if (path == NULL)
        {
          this->HighlightProp(NULL);
          this->PropPicked = 0;
        }
            else
        {
          this->PropPicked = 1;
        }
        rwi->EndPickCallback();
    } 
    else
    {
        cout << "What did I do?" << endl;
        this->FindPokedCamera(X, Y);
        this->Preprocess = 1;
        if (this->HasObserver(vtkCommand::LeftButtonPressEvent))
        {
           this->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL);
        }
        else
        {
            if (this->ActorMode)
            {
                this->FindPickedActor(X,Y);
            }
            if (this->ShiftKey)
            { // I haven't got a Middle button !
                if (this->CtrlKey)
                {
                    this->StartDolly();
                }
                else
                {
                    this->StartPan();
                    cout<<"I hit shift and left-clicked"<<endl;
                }
            }
            else
            {
                if (this->CtrlKey)
                {
                    this->StartSpin();
                }
                else
                {
                    this->StartRotate();
                } // end if CtrlKey
            } // end if ShiftKey && State
        } // end if HasObserver
    } // end if ShiftKey
} // end OnLeftButtonDown

//----------------------------------------------------------------------------
void controls::OnLeftButtonUp(int ctrl, int shift, int X, int Y) 
{
  //
  this->UpdateInternalState(ctrl, shift, X, Y);

  //
  if (this->HasObserver(vtkCommand::LeftButtonReleaseEvent)) {
    this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL);
  } else  {
    
    if (this->ShiftKey)  {
      if (this->CtrlKey) {
        this->EndDolly();
      } else {
        this->EndPan();
      }
    }  else {
      if (this->CtrlKey) {
        this->EndSpin();
      } else {
        this->EndRotate();
      }
    }
  }
  this->OldX = 0.0;
  this->OldY = 0.0;
}

//----------------------------------------------------------------------------
void controls::OnMiddleButtonDown(int ctrl, int shift, 
                                                 int X, int Y) 
{
  this->OldX = X;
  this->OldY = Y;
  //
  this->UpdateInternalState(ctrl, shift, X, Y);
  //
  this->Preprocess = 1;
  this->FindPokedCamera(X, Y);
  //
  if (this->HasObserver(vtkCommand::MiddleButtonPressEvent)) {
    this->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL);
  } else {
    if (this->ActorMode) {
      this->FindPickedActor(X,Y);    
    }

    if (this->CtrlKey) {
      this->StartDolly();
    } else {
      this->StartPan();
    }
  }
}

//----------------------------------------------------------------------------
void controls::OnMiddleButtonUp(int ctrl, int shift, 
                                                   int X, int Y) 
{
  //
  this->UpdateInternalState(ctrl, shift, X, Y);
  //
  if (this->HasObserver(vtkCommand::MiddleButtonReleaseEvent)) {
    this->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent,NULL);
  } else {
    if (this->CtrlKey) {
          this->EndDolly();
    } else {
      this->EndPan();
    }
  }
  this->OldX = 0.0;
  this->OldY = 0.0;
  if (this->ActorMode && this->PropPicked) {
    this->HighlightProp3D(this->InteractionProp);
  } else if (this->ActorMode) {
    this->HighlightProp3D(NULL);
  }
}

//----------------------------------------------------------------------------
void controls::OnRightButtonDown(int ctrl, int shift, 
                                                    int X, int Y) 
{
  this->OldX = X;
  this->OldY = Y;
  //
  this->UpdateInternalState(ctrl, shift, X, Y);
  this->FindPokedCamera(X, Y);
  this->Preprocess = 1;
  if (this->HasObserver(vtkCommand::RightButtonPressEvent)) {
    this->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL);
  } else {
    if (this->ActorMode) {
      this->FindPickedActor(X,Y);    
      this->StartUniformScale();
    } else {
      this->StartZoom();
    }
  }
}

//----------------------------------------------------------------------------
void controls::OnRightButtonUp(int ctrl, int shift, 
                                                  int X, int Y) 
{
  //
  this->UpdateInternalState(ctrl, shift, X, Y);
  //
  if (this->HasObserver(vtkCommand::RightButtonReleaseEvent)) {
    this->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL);
  } else {
    if (this->ActorMode) {
      this->EndUniformScale();
    } else {
      this->EndZoom();
    }
  }
  this->OldX = 0.0;
  this->OldY = 0.0;
  if (this->ActorMode && this->PropPicked) {
    this->HighlightProp3D(this->InteractionProp);
  } else if (this->ActorMode) {
    this->HighlightProp3D(NULL);
  }
}


void controls::OnLeftArrowDown()
{
    int X = 0, Y = 0;
    vtkRenderWindowInteractor *rwi = this->Interactor;
     this->UpdateInternalState(NULL, NULL, X, Y);
     this->FindPokedCamera(X,Y);

     if (this->HasObserver(vtkCommand::KeyPressEvent)) 
    {
    this->InvokeEvent(vtkCommand::KeyPressEvent,NULL);
    }
  else 
    {
    //  vtkRenderWindowInteractor *rwi = this->Interactor;
//  cout<<"Onleftarrowdown\n";
      //this->StartRotate();
        this->CurrentCamera->Azimuth(-30);
    }
    rwi->Render();
 // cout<<"after azi in lad\n";
        
}



/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/*********** CODE THAT I DID NOT MESS WITH MUCH MIGHT NOT NEED **************/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/


//----------------------------------------------------------------------------
// Implementations of Joystick Camera/Actor motions follow
//----------------------------------------------------------------------------
// Description:
// rotate the camera in trackball (motion sensitive) style
void controls::TrackballRotateCamera(int x, int y)
{

  if ((this->OldX != x) || (this->OldY != y)) {
    
    double rxf = (double)(x - this->OldX) * this->DeltaAzimuth *
      this->MotionFactor;
    double ryf = (double)(y - this->OldY) * this->DeltaElevation *
      this->MotionFactor;
    
    this->CurrentCamera->Azimuth(rxf);
    this->CurrentCamera->Elevation(ryf);
    this->CurrentCamera->OrthogonalizeViewUp();
    this->CurrentRenderer->ResetCameraClippingRange();
    vtkRenderWindowInteractor *rwi = this->Interactor;
    if (rwi->GetLightFollowCamera()) {
      // get the first light
      this->CurrentLight->SetPosition(this->CurrentCamera->GetPosition());
      this->CurrentLight->SetFocalPoint(this->CurrentCamera->GetFocalPoint());
    } 
    this->OldX = x;
    this->OldY = y;
    rwi->Render();
  }
}

// Description:
// spin the camera in trackball (motion sensitive) style
void controls::TrackballSpinCamera(int x, int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  if ((this->OldX != x) || (this->OldY != y)) {
    double newAngle = atan2((double)(y - this->Center[1]),
                            (double)(x - this->Center[0]));
    double oldAngle = atan2((double)(this->OldY -this->Center[1]),
                            (double)(this->OldX - this->Center[0]));
  
    newAngle *= this->RadianToDegree;
    oldAngle *= this->RadianToDegree;

    this->CurrentCamera->Roll(newAngle - oldAngle);
    this->CurrentCamera->OrthogonalizeViewUp();
      
    this->OldX = x;
    this->OldY = y;
    rwi->Render();
  }
}


// Description:
// pan the camera in trackball (motion sensitive) style
void controls::TrackballPanCamera(int x, int y)
{
  if ((this->OldX != x) || (this->OldY != y)) {
    if (this->Preprocess) {
      // calculate the focal depth since we'll be using it a lot
      this->CurrentCamera->GetFocalPoint(this->ViewFocus);
      this->ComputeWorldToDisplay(this->ViewFocus[0], this->ViewFocus[1],
                                  this->ViewFocus[2], this->ViewFocus);
      this->FocalDepth = this->ViewFocus[2];

      this->Preprocess = 0;
    }

    this->ComputeDisplayToWorld(double(x), double(y),
                                this->FocalDepth,
                                this->NewPickPoint);
    
    // has to recalc old mouse point since the viewport has moved,
    // so can't move it outside the loop
    this->ComputeDisplayToWorld(double(this->OldX),double(this->OldY),
                                this->FocalDepth, this->OldPickPoint);

    // camera motion is reversed
    this->MotionVector[0] = this->OldPickPoint[0] - this->NewPickPoint[0];
    this->MotionVector[1] = this->OldPickPoint[1] - this->NewPickPoint[1];
    this->MotionVector[2] = this->OldPickPoint[2] - this->NewPickPoint[2];
    
    this->CurrentCamera->GetFocalPoint(this->ViewFocus);
    this->CurrentCamera->GetPosition(this->ViewPoint);
    this->CurrentCamera->SetFocalPoint(this->MotionVector[0] +
                                       this->ViewFocus[0],
                                       this->MotionVector[1] +
                                       this->ViewFocus[1],
                                       this->MotionVector[2] +
                                       this->ViewFocus[2]);
    this->CurrentCamera->SetPosition(this->MotionVector[0] +
                                     this->ViewPoint[0],
                                     this->MotionVector[1] +
                                     this->ViewPoint[1],
                                     this->MotionVector[2] +
                                     this->ViewPoint[2]);
      
    vtkRenderWindowInteractor *rwi = this->Interactor;
    if (rwi->GetLightFollowCamera())
      {
        /* get the first light */
        this->CurrentLight->SetPosition(this->CurrentCamera->GetPosition());
        this->CurrentLight->SetFocalPoint(this->CurrentCamera->GetFocalPoint());
      }
    
    this->OldX = x;
    this->OldY = y;
    rwi->Render();
  }
}

// Description:
// dolly the camera in trackball (motion sensitive) style
// dolly is based on distance from center of screen,
// and the upper half is positive, lower half is negative
void controls::TrackballDollyCamera(int x, int y)
{
  if (this->OldY != y) {
    double dyf = this->MotionFactor * (double)(y - this->OldY) /
      (double)(this->Center[1]);
    double zoomFactor = pow((double)1.1, dyf);
          
    if (this->CurrentCamera->GetParallelProjection()) {
      this->CurrentCamera->
        SetParallelScale(this->CurrentCamera->GetParallelScale()/zoomFactor);
    }
    else {
      this->CurrentCamera->Dolly(zoomFactor);
      this->CurrentRenderer->ResetCameraClippingRange();
    }
    
    vtkRenderWindowInteractor *rwi = this->Interactor;
    if (rwi->GetLightFollowCamera()) {
      /* get the first light */
      this->CurrentLight->SetPosition(this->CurrentCamera->GetPosition());
      this->CurrentLight->SetFocalPoint(this->CurrentCamera->GetFocalPoint());
    }

    this->OldX = x;
    this->OldY = y;
    rwi->Render();
  }
}

// Description:
// rotate the actor in trackball (motion sensitive) style
void controls::TrackballRotateActor(int x, int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  if ((this->OldX != x) || (this->OldY != y)) {

    if (this->Preprocess) {
      float *center = this->InteractionProp->GetCenter();
      this->ObjCenter[0] = center[0];
      this->ObjCenter[1] = center[1];
      this->ObjCenter[2] = center[2];

      // GetLength gets the length of the diagonal of the bounding box
      double boundRadius = this->InteractionProp->GetLength() * 0.5;

      // get the view up and view right vectors
      this->CurrentCamera->OrthogonalizeViewUp();
      this->CurrentCamera->ComputeViewPlaneNormal();
      this->CurrentCamera->GetViewUp(this->ViewUp);
      vtkMath::Normalize(this->ViewUp);
      this->CurrentCamera->GetViewPlaneNormal(this->ViewLook);
      vtkMath::Cross(this->ViewUp, this->ViewLook, this->ViewRight);
      vtkMath::Normalize(this->ViewRight);

      // get the furtherest point from object position+origin
      double outsidept[3];
      outsidept[0] = this->ObjCenter[0] + this->ViewRight[0] * boundRadius;
      outsidept[1] = this->ObjCenter[1] + this->ViewRight[1] * boundRadius;
      outsidept[2] = this->ObjCenter[2] + this->ViewRight[2] * boundRadius;

      // convert them to display coord
      this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                                  this->ObjCenter[2], this->DispObjCenter);
      this->ComputeWorldToDisplay(outsidept[0], outsidept[1],
                                  outsidept[2], outsidept);

      // get the radius in display coord
      double ftmp[3];
      ftmp[0] = this->DispObjCenter[0];
      ftmp[1] = this->DispObjCenter[1];
      ftmp[2] = this->DispObjCenter[2];

      this->Radius = sqrt(vtkMath::Distance2BetweenPoints(ftmp, outsidept));
      this->HighlightProp3D(NULL);
      this->Preprocess = 0;
    }

    double nxf = (double)(x - this->DispObjCenter[0]) / this->Radius;
    double nyf = (double)(y - this->DispObjCenter[1]) / this->Radius;
    double oxf = (double)(this->OldX - this->DispObjCenter[0]) / this->Radius;
    double oyf = (double)(this->OldY - this->DispObjCenter[1]) / this->Radius;

    if (((nxf * nxf + nyf * nyf) <= 1.0) &&
        ((oxf * oxf + oyf * oyf) <= 1.0)) {
            
      double newXAngle = asin(nxf) * this->RadianToDegree;
      double newYAngle = asin(nyf) * this->RadianToDegree;
      double oldXAngle = asin(oxf) * this->RadianToDegree;
      double oldYAngle = asin(oyf) * this->RadianToDegree;

      double scale[3];
      scale[0] = scale[1] = scale[2] = 1.0;
      double **rotate = new double*[2];
      rotate[0] = new double[4];
      rotate[1] = new double[4];

      rotate[0][0] = newXAngle - oldXAngle;
      rotate[0][1] = this->ViewUp[0];
      rotate[0][2] = this->ViewUp[1];
      rotate[0][3] = this->ViewUp[2];
      
      rotate[1][0] = oldYAngle - newYAngle;
      rotate[1][1] = this->ViewRight[0];
      rotate[1][2] = this->ViewRight[1];
      rotate[1][3] = this->ViewRight[2];
      
      
      this->Prop3DTransform(this->InteractionProp,
                            this->ObjCenter,
                            2, rotate, scale);

      delete [] rotate[0];
      delete [] rotate[1];
      delete [] rotate;
      
      this->OldX = x;
      this->OldY = y;
      this->CurrentRenderer->ResetCameraClippingRange();
      rwi->Render();
    }
  }
}

// Description:
// spin the actor in trackball (motion sensitive) style
void controls::TrackballSpinActor(int x, int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  if ((this->OldX != x) || (this->OldY != y)) {
    if (this->Preprocess) {
      // get the position plus origin of the object
      float *center = this->InteractionProp->GetCenter();
      this->ObjCenter[0] = center[0];
      this->ObjCenter[1] = center[1];
      this->ObjCenter[2] = center[2];

      // get the axis to rotate around = vector from eye to origin
      if (this->CurrentCamera->GetParallelProjection()) {
        this->CurrentCamera->ComputeViewPlaneNormal();
        this->CurrentCamera->GetViewPlaneNormal(this->MotionVector);
      }
      else {   
        this->CurrentCamera->GetPosition(this->ViewPoint);
        this->MotionVector[0] = this->ViewPoint[0] - this->ObjCenter[0];
        this->MotionVector[1] = this->ViewPoint[1] - this->ObjCenter[1];
        this->MotionVector[2] = this->ViewPoint[2] - this->ObjCenter[2];
        vtkMath::Normalize(this->MotionVector);
      }
      
      this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                                  this->ObjCenter[2], this->DispObjCenter);

      this->HighlightProp3D(NULL);
      this->Preprocess = 0;
    }
    
    // this has to be in the loop
    double newAngle = atan2((double)(y - this->DispObjCenter[1]),
                            (double)(x - this->DispObjCenter[0]));
    double oldAngle = atan2((double)(this->OldY - this->DispObjCenter[1]),
                            (double)(this->OldX - this->DispObjCenter[0]));
    
    newAngle *= this->RadianToDegree;
    oldAngle *= this->RadianToDegree;

    double scale[3];
    scale[0] = scale[1] = scale[2] = 1.0;
    double **rotate = new double*[1];
    rotate[0] = new double[4];

    rotate[0][0] = newAngle - oldAngle;
    rotate[0][1] = this->MotionVector[0];
    rotate[0][2] = this->MotionVector[1];
    rotate[0][3] = this->MotionVector[2];
  
    this->Prop3DTransform(this->InteractionProp,
                          this->ObjCenter,
                          1, rotate, scale);

    delete [] rotate[0];
    delete [] rotate;
    
    this->OldX = x;
    this->OldY = y;
    this->CurrentRenderer->ResetCameraClippingRange();
    rwi->Render();
  }
}

// Description:
// pan the actor in trackball (motion sensitive) style
void controls::TrackballPanActor(int x, int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  if ((this->OldX != x) || (this->OldY != y)) {
    if (this->Preprocess) {
      // use initial center as the origin from which to pan
      float *center = this->InteractionProp->GetCenter();
      this->ObjCenter[0] = center[0];
      this->ObjCenter[1] = center[1];
      this->ObjCenter[2] = center[2];
      this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                                  this->ObjCenter[2], this->DispObjCenter);
      this->FocalDepth = this->DispObjCenter[2];
      
      this->HighlightProp3D(NULL);
      this->Preprocess = 0;
    }
  
    this->ComputeDisplayToWorld(double(x), double(y),
                                this->FocalDepth,
                                this->NewPickPoint);

    this->ComputeDisplayToWorld(double(this->OldX), double(this->OldY),
                                this->FocalDepth, this->OldPickPoint);

    this->MotionVector[0] = this->NewPickPoint[0] - this->OldPickPoint[0];
    this->MotionVector[1] = this->NewPickPoint[1] - this->OldPickPoint[1];
    this->MotionVector[2] = this->NewPickPoint[2] - this->OldPickPoint[2];

    if (this->InteractionProp->GetUserMatrix() != NULL) {
      vtkTransform *t = vtkTransform::New();
      t->PostMultiply();
      t->SetMatrix(this->InteractionProp->GetUserMatrix());
      t->Translate(this->MotionVector[0], this->MotionVector[1], 
                   this->MotionVector[2]);
      this->InteractionProp->GetUserMatrix()->DeepCopy(t->GetMatrix());
      t->Delete();
    }
    else {
      this->InteractionProp->AddPosition(this->MotionVector);
    }
      
    this->OldX = x;
    this->OldY = y;
    rwi->Render();
  }
}


// Description:
// Dolly the actor in trackball (motion sensitive) style
void controls::TrackballDollyActor(int x, int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  if (this->OldY != y) {
    if (this->Preprocess) {
      this->CurrentCamera->GetPosition(this->ViewPoint);
      this->CurrentCamera->GetFocalPoint(this->ViewFocus);

      this->HighlightProp3D(NULL);
      this->Preprocess = 0;
    }
    
    double yf = (double)(this->OldY - y) / (double)(this->Center[1]) *
      this->MotionFactor;
    double dollyFactor = pow((double)1.1, yf);

    dollyFactor -= 1.0;
    this->MotionVector[0] = (this->ViewPoint[0] -
                             this->ViewFocus[0]) * dollyFactor;
    this->MotionVector[1] = (this->ViewPoint[1] -
                             this->ViewFocus[1]) * dollyFactor;
    this->MotionVector[2] = (this->ViewPoint[2] -
                             this->ViewFocus[2]) * dollyFactor;
    
    if (this->InteractionProp->GetUserMatrix() != NULL) {
      vtkTransform *t = vtkTransform::New();
      t->PostMultiply();
      t->SetMatrix(this->InteractionProp->GetUserMatrix());
      t->Translate(this->MotionVector[0], this->MotionVector[1], 
                   this->MotionVector[2]);
      this->InteractionProp->GetUserMatrix()->DeepCopy(t->GetMatrix());
      t->Delete();
    }
    else {
      this->InteractionProp->AddPosition(this->MotionVector);
    }
  
    this->OldX = x;
    this->OldY = y;
    rwi->Render();
  }
}

// Description:
// Scale the actor in trackball (motion sensitive) style
void controls::TrackballScaleActor(int x, int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  if ((this->OldX != x) || (this->OldY != y)) {
    if (this->Preprocess) {
      float *center = this->InteractionProp->GetCenter();
      this->ObjCenter[0] = center[0];
      this->ObjCenter[1] = center[1];
      this->ObjCenter[2] = center[2];

      this->HighlightProp3D(NULL);
      this->Preprocess = 0;
    }
    
    double yf = (double)(y - this->OldY) / (double)(this->Center[1]) *
      this->MotionFactor;
    double scaleFactor = pow((double)1.1, yf);

    double **rotate = NULL;

    double scale[3];
    scale[0] = scale[1] = scale[2] = scaleFactor;

    this->Prop3DTransform(this->InteractionProp,
                          this->ObjCenter,
                          0, rotate, scale);

    this->OldX = x;
    this->OldY = y;
    this->CurrentRenderer->ResetCameraClippingRange();
    rwi->Render();
  }
}

void controls::PrintSelf(ostream& os, vtkIndent indent) 
{
  this->vtkInteractorStyle::PrintSelf(os,indent);

  os << indent << "Interaction Picker: " 
     << this->InteractionPicker << endl;
  os << indent << "Actor Picked: " <<
    (this->PropPicked ? "Yes\n" : "No\n");
  if ( this->InteractionProp ) {
    os << indent << "Interacting Actor: " << this->InteractionProp << "\n";
  } else {
    os << indent << "Interacting Actor: (none)\n";
  }
  os << indent << "Mode: " <<
    (this->ActorMode ? "Actor\n" : "Camera\n");
  os << indent << "Mode: " <<
    (this->TrackballMode ? "Trackball\n" : "Joystick\n");
  os << indent << "Control Key: " <<
    (this->ControlMode ? "On\n" : "Off\n");
  os << indent << "Preprocessing: " <<
    (this->Preprocess ? "Yes\n" : "No\n");

}

void controls::JoystickRotateActor(int x, int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  if (this->Preprocess) {
    // first get the origin of the assembly
    float *center = this->InteractionProp->GetCenter();
    this->ObjCenter[0] = center[0];
    this->ObjCenter[1] = center[1];
    this->ObjCenter[2] = center[2];

    // GetLength gets the length of the diagonal of the bounding box
    double boundRadius = this->InteractionProp->GetLength() * 0.5;

    // get the view up and view right vectors
    this->CurrentCamera->OrthogonalizeViewUp();
    this->CurrentCamera->ComputeViewPlaneNormal();
    this->CurrentCamera->GetViewUp(this->ViewUp);
    vtkMath::Normalize(this->ViewUp);
    this->CurrentCamera->GetViewPlaneNormal(this->ViewLook);
    vtkMath::Cross(this->ViewUp, this->ViewLook, this->ViewRight);
    vtkMath::Normalize(this->ViewRight);

    // get the furtherest point from object bounding box center
    float outsidept[3];
    outsidept[0] = this->ObjCenter[0] + this->ViewRight[0] * boundRadius;
    outsidept[1] = this->ObjCenter[1] + this->ViewRight[1] * boundRadius;
    outsidept[2] = this->ObjCenter[2] + this->ViewRight[2] * boundRadius;

    // convert to display coord
    this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                                this->ObjCenter[2], this->DispObjCenter);
    this->ComputeWorldToDisplay(outsidept[0], outsidept[1],
                                outsidept[2], outsidept);

    this->Radius = sqrt(vtkMath::Distance2BetweenPoints(this->DispObjCenter,
                                                        outsidept));

    this->HighlightProp3D(NULL);
    this->Preprocess = 0;
  }


  double nxf = (double)(x - this->DispObjCenter[0]) / this->Radius;
  double nyf = (double)(y - this->DispObjCenter[1]) / this->Radius;

  if (nxf > 1.0) {
    nxf = 1.0;
  } else if (nxf < -1.0) {
    nxf = -1.0;
  }

  if (nyf > 1.0) {
    nyf = 1.0;
  } else if (nyf < -1.0) {
    nyf = -1.0;
  }

  double newXAngle = asin(nxf) * this->RadianToDegree / this->MotionFactor;
  double newYAngle = asin(nyf) * this->RadianToDegree / this->MotionFactor;

  double scale[3];
  scale[0] = scale[1] = scale[2] = 1.0;
  double **rotate = new double*[2];
  rotate[0] = new double[4];
  rotate[1] = new double[4];

  rotate[0][0] = newXAngle;
  rotate[0][1] = this->ViewUp[0];
  rotate[0][2] = this->ViewUp[1];
  rotate[0][3] = this->ViewUp[2];

  rotate[1][0] = -newYAngle;
  rotate[1][1] = this->ViewRight[0];
  rotate[1][2] = this->ViewRight[1];
  rotate[1][3] = this->ViewRight[2];


  this->Prop3DTransform(this->InteractionProp,
                        this->ObjCenter,
                        2, rotate, scale);

  delete [] rotate[0];
  delete [] rotate[1];
  delete [] rotate;

  rwi->Render();
}

void controls::JoystickSpinActor(int vtkNotUsed(x), int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  // get the axis to rotate around = vector from eye to origin
  if (this->Preprocess) {

    float *center = this->InteractionProp->GetCenter();
    this->ObjCenter[0] = center[0];
    this->ObjCenter[1] = center[1];
    this->ObjCenter[2] = center[2];

    if (this->CurrentCamera->GetParallelProjection()) {
      // if parallel projection, want to get the view plane normal...
      this->CurrentCamera->ComputeViewPlaneNormal();
      this->CurrentCamera->GetViewPlaneNormal(this->MotionVector);
    } else {
      // perspective projection, get vector from eye to center of actor
      this->CurrentCamera->GetPosition(this->ViewPoint);
      this->MotionVector[0] = this->ViewPoint[0] - this->ObjCenter[0];
      this->MotionVector[1] = this->ViewPoint[1] - this->ObjCenter[1];
      this->MotionVector[2] = this->ViewPoint[2] - this->ObjCenter[2];
      vtkMath::Normalize(this->MotionVector);
    }

    this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                                this->ObjCenter[2], this->DispObjCenter);

    this->HighlightProp3D(NULL);
    this->Preprocess = 0;
  }

  double yf = (double)(y -this->DispObjCenter[1]) / (double)(this->Center[1]);
  if (yf > 1.0) {
    yf = 1.0;
  } else if (yf < -1.0) {
    yf = -1.0;
  }

  double newAngle = asin(yf) * this->RadianToDegree / this->MotionFactor;

  double scale[3];
  scale[0] = scale[1] = scale[2] = 1.0;
  double **rotate = new double*[1];
  rotate[0] = new double[4];

  rotate[0][0] = newAngle;
  rotate[0][1] = this->MotionVector[0];
  rotate[0][2] = this->MotionVector[1];
  rotate[0][3] = this->MotionVector[2];

  this->Prop3DTransform(this->InteractionProp,
                        this->ObjCenter,
                        1, rotate, scale);

  delete [] rotate[0];
  delete [] rotate;

  rwi->Render();
}

void controls::JoystickPanActor(int x, int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  if (this->Preprocess) {
    // use initial center as the origin from which to pan
    float *center = this->InteractionProp->GetCenter();
    this->ObjCenter[0] = center[0];
    this->ObjCenter[1] = center[1];
    this->ObjCenter[2] = center[2];

    this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                                this->ObjCenter[2], this->DispObjCenter);
    this->FocalDepth = this->DispObjCenter[2];

    this->HighlightProp3D(NULL);
    this->Preprocess = 0;
  }

  this->ComputeDisplayToWorld(double(x), double(y),
                              this->FocalDepth,
                              this->NewPickPoint);

  /*
   * Compute a translation vector, moving everything 1/10
   * the distance to the cursor. (Arbitrary scale factor)
   */
  this->MotionVector[0] = (this->NewPickPoint[0] -
                           this->ObjCenter[0]) / this->MotionFactor;
  this->MotionVector[1] = (this->NewPickPoint[1] -
                           this->ObjCenter[1]) / this->MotionFactor;
  this->MotionVector[2] = (this->NewPickPoint[2] -
                           this->ObjCenter[2]) / this->MotionFactor;

  if (this->InteractionProp->GetUserMatrix() != NULL) {
    vtkTransform *t = vtkTransform::New();
    t->PostMultiply();
    t->SetMatrix(this->InteractionProp->GetUserMatrix());
    t->Translate(this->MotionVector[0], this->MotionVector[1],
                 this->MotionVector[2]);
    this->InteractionProp->GetUserMatrix()->DeepCopy(t->GetMatrix());
    t->Delete();
  } else {
    this->InteractionProp->AddPosition(this->MotionVector);
  }

  rwi->Render();
}

void controls::JoystickDollyActor(int vtkNotUsed(x), int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  // dolly is based on distance from center of screen,
  // and the upper half is positive, lower half is negative

  if (this->Preprocess) {
    this->CurrentCamera->GetPosition(this->ViewPoint);
    this->CurrentCamera->GetFocalPoint(this->ViewFocus);

    // use initial center as the origin from which to pan
    float *center = this->InteractionProp->GetCenter();
    this->ObjCenter[0] = center[0];
    this->ObjCenter[1] = center[1];
    this->ObjCenter[2] = center[2];
    this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                                this->ObjCenter[2], this->DispObjCenter);

    this->HighlightProp3D(NULL);
    this->Preprocess = 0;
  }

  double yf = (double)(y - this->DispObjCenter[1]) /
    (double)(this->Center[1]);
  double dollyFactor = pow((double)1.1, yf);

  dollyFactor -= 1.0;
  this->MotionVector[0] = (this->ViewPoint[0] -
                           this->ViewFocus[0]) * dollyFactor;
  this->MotionVector[1] = (this->ViewPoint[1] -
                           this->ViewFocus[1]) * dollyFactor;
  this->MotionVector[2] = (this->ViewPoint[2] -
                           this->ViewFocus[2]) * dollyFactor;

  if (this->InteractionProp->GetUserMatrix() != NULL) {
    vtkTransform *t = vtkTransform::New();
    t->PostMultiply();
    t->SetMatrix(this->InteractionProp->GetUserMatrix());
    t->Translate(this->MotionVector[0], this->MotionVector[1],
                 this->MotionVector[2]);
    this->InteractionProp->GetUserMatrix()->DeepCopy(t->GetMatrix());
    t->Delete();
  } else {
    this->InteractionProp->AddPosition(this->MotionVector);
  }

  rwi->Render();
}

void controls::JoystickScaleActor(int vtkNotUsed(x), int y)
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  // Uniform scale is based on distance from center of screen,
  // and the upper half is positive, lower half is negative

  if (this->Preprocess) {
    // use bounding box center as the origin from which to pan
    float *center = this->InteractionProp->GetCenter();
    this->ObjCenter[0] = center[0];
    this->ObjCenter[1] = center[1];
    this->ObjCenter[2] = center[2];

    this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                                this->ObjCenter[2], this->DispObjCenter);

    this->HighlightProp3D(NULL);
    this->Preprocess = 0;
  }

  double yf = (double)(y - this->DispObjCenter[1]) /
    (double)(this->Center[1]);
  double scaleFactor = pow((double)1.1, yf);

  double **rotate = NULL;

  double scale[3];
  scale[0] = scale[1] = scale[2] = scaleFactor;

  this->Prop3DTransform(this->InteractionProp,
                        this->ObjCenter,
                        0, rotate, scale);

  rwi->Render();
}


//----------------------------------------------------------------------------
void controls::Prop3DTransform(vtkProp3D *prop3D,
                                              double *boxCenter,
                                              int numRotation,
                                              double **rotate,
                                              double *scale)
{
  vtkMatrix4x4 *oldMatrix = vtkMatrix4x4::New();
  prop3D->GetMatrix(oldMatrix);
  
  float orig[3];
  prop3D->GetOrigin(orig);
  
  vtkTransform *newTransform = vtkTransform::New();
  newTransform->PostMultiply();
  if (prop3D->GetUserMatrix() != NULL) {
    newTransform->SetMatrix(prop3D->GetUserMatrix());
  } else {
    newTransform->SetMatrix(oldMatrix);
  }
  
  newTransform->Translate(-(boxCenter[0]), -(boxCenter[1]), -(boxCenter[2]));
  
  for (int i = 0; i < numRotation; i++) {
    newTransform->RotateWXYZ(rotate[i][0], rotate[i][1],
                             rotate[i][2], rotate[i][3]);
  }
  
  if ((scale[0] * scale[1] * scale[2]) != 0.0) {
    newTransform->Scale(scale[0], scale[1], scale[2]);
  }
  
  newTransform->Translate(boxCenter[0], boxCenter[1], boxCenter[2]);
  
  // now try to get the composit of translate, rotate, and scale
  newTransform->Translate(-(orig[0]), -(orig[1]), -(orig[2]));
  newTransform->PreMultiply();
  newTransform->Translate(orig[0], orig[1], orig[2]);
  
  if (prop3D->GetUserMatrix() != NULL) {
    newTransform->GetMatrix(prop3D->GetUserMatrix());
  } else {
    prop3D->SetPosition(newTransform->GetPosition());
    prop3D->SetScale(newTransform->GetScale());
    prop3D->SetOrientation(newTransform->GetOrientation());
  }
  oldMatrix->Delete();
  newTransform->Delete();
}

//----------------------------------------------------------------------------
// By overriding the RotateCamera, RotateActor members we can
// use this timer routine for Joystick or Trackball - quite tidy
//----------------------------------------------------------------------------
void controls::OnTimer(void) 
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  switch (this->State) {
    
    case VTKIS_START:
      if (this->AnimState == VTKIS_ANIM_ON) {
        rwi->DestroyTimer();
        rwi->Render();
        rwi->CreateTimer(VTKI_TIMER_FIRST);
      }
      break;
      
    case VTKIS_ROTATE:  // rotate with respect to an axis perp to look
      if (this->ActorMode && this->PropPicked) {
        if (this->TrackballMode) {
          this->TrackballRotateActor(this->LastPos[0],
                                     this->LastPos[1]);
        } else {
          this->JoystickRotateActor(this->LastPos[0],
                                    this->LastPos[1]);
        }
      } else if (!(this->ActorMode)) {
        if (this->TrackballMode) {
          this->TrackballRotateCamera(this->LastPos[0],
                                      this->LastPos[1]);
        } else {
          this->RotateCamera(this->LastPos[0],this->LastPos[1]);
        }
      }
      rwi->CreateTimer(VTKI_TIMER_UPDATE);
      break;
      
    case VTKIS_ZOOM: // move perpendicular to camera's look vector
      if (this->ActorMode && this->PropPicked) {
        if (this->TrackballMode) { 
          this->TrackballPanActor(this->LastPos[0],
                                  this->LastPos[1]);
        } else {
          this->JoystickPanActor(this->LastPos[0],
                                 this->LastPos[1]);
        }
      }
      else if (!(this->ActorMode)) {
        if (this->TrackballMode) {
          this->TrackballPanCamera(this->LastPos[0],
                                   this->LastPos[1]);
        } else {
          this->PanCamera(this->LastPos[0],this->LastPos[1]);
        }
      }
      rwi->CreateTimer(VTKI_TIMER_UPDATE);
      break;
      
    case VTKIS_PAN:
      if (!(this->ActorMode)) {
        if (this->TrackballMode) { 
          this->TrackballDollyCamera(this->LastPos[0],
                                     this->LastPos[1]);
        } else {
          this->DollyCamera(this->LastPos[0],this->LastPos[1]);
        }
      }
      rwi->CreateTimer(VTKI_TIMER_UPDATE);
      break;
      
    case VTKIS_SPIN:
      if (this->ActorMode && this->PropPicked) {
        if (this->TrackballMode) { 
          this->TrackballSpinActor(this->LastPos[0],
                                   this->LastPos[1]);
        } else {
          this->JoystickSpinActor(this->LastPos[0],
                                  this->LastPos[1]);
        }
      } else if (!(this->ActorMode)) {
        if (this->TrackballMode) {
          this->TrackballSpinCamera(this->LastPos[0],
                                    this->LastPos[1]);
        } else {
          this->SpinCamera(this->LastPos[0],this->LastPos[1]);
        }
      }
      rwi->CreateTimer(VTKI_TIMER_UPDATE);
      break;
      
    case VTKIS_DOLLY:  // move along camera's view vector
      if (this->ActorMode && this->PropPicked) {
        if (this->TrackballMode) { 
          this->TrackballDollyActor(this->LastPos[0],
                                    this->LastPos[1]);
        } else {
          this->JoystickDollyActor(this->LastPos[0],
                                   this->LastPos[1]);
        }
      }
      rwi->CreateTimer(VTKI_TIMER_UPDATE);
      break;
      
    case VTKIS_USCALE:
      if (this->ActorMode && this->PropPicked) {
        if (this->TrackballMode) {
          this->TrackballScaleActor(this->LastPos[0],
                                    this->LastPos[1]);
        } else {
          this->JoystickScaleActor(this->LastPos[0],
                                   this->LastPos[1]);
        }
      }
      rwi->CreateTimer(VTKI_TIMER_UPDATE);
      break;
      
    case VTKIS_TIMER:
      rwi->CreateTimer(VTKI_TIMER_UPDATE);
      break;

    default :
      break;
  }
}

void controls::Prop3DTransform(vtkProp3D *prop3D,
                                                float *boxCenter,
                                                int numRotation,
                                                double **rotate,
                                                double *scale)
{
  double boxCenter2[3];
  boxCenter2[0] = boxCenter[0];
  boxCenter2[1] = boxCenter[1];
  boxCenter2[2] = boxCenter[2];
  this->Prop3DTransform(prop3D,boxCenter2,numRotation,rotate,scale);
}

void controls::FindPickedActor(int X, int Y)
{
  this->InteractionPicker->Pick(X,Y, 0.0, this->CurrentRenderer);
  vtkProp *prop = this->InteractionPicker->GetProp();
  if ( prop != NULL ) {
    vtkProp3D *prop3D = vtkProp3D::SafeDownCast(prop);
    if ( prop3D != NULL ) {
      this->InteractionProp = prop3D;
    }
  }

  // refine the answer to whether an actor was picked.  CellPicker()
  // returns true from Pick() if the bounding box was picked,
  // but we only want something to be picked if a cell was actually
  // selected
  this->PropPicked = (this->InteractionProp != NULL);
}

//----------------------------------------------------------------------------
void controls::SetTrackballModeToTrackball()
{
  if (this->TrackballMode == VTKIS_TRACK) {
    return;
  }
  this->TrackballMode = VTKIS_TRACK;
  this->Modified();
}

//----------------------------------------------------------------------------
void controls::SetTrackballModeToJoystick()
{
  if (this->TrackballMode == VTKIS_JOY) {
    return;
  }
  this->TrackballMode = VTKIS_JOY;
  this->Modified();
}

//----------------------------------------------------------------------------
void controls::SetActorModeToCamera()
{
  if (this->ActorMode == VTKIS_CAMERA) {
    return;
  }
  this->ActorMode = VTKIS_CAMERA;
  this->Modified();
}

//----------------------------------------------------------------------------
void controls::SetActorModeToActor()
{
  if (this->ActorMode == VTKIS_ACTOR) {
    return;
  }
  this->ActorMode = VTKIS_ACTOR;
  this->Modified();
}






/******************** old code that may still come in handy **************/

/*  if (cin.bad())
    {
        Long = 0;
        //cin.clear();
        cout<<"Default longitude is "<<Long<<endl;
    } */
//  cout<<"\nChoose the distance. 1-10 (1-close; 10-far away).\n Distance(default 5): "<< flush;
//  cin >>Distance;
/*  if (cin.bad())
    {
        Distance = 5;
        //cin.clear();
        cout<<"Default distance is "<<Distance<<endl;
    } */
    //cout<<flush;
    //cin.clear();

/*  if((Long<90)||(Long>90))
        Long = 0;

    if (((int)Lat%360>360)||((int)Lat%360<-360)) //redundant to catch non-numeric values
        Lat=0;
*/

//  if((Distance>=1)&&(Distance<=10))
//      Distance = (Distance*Distance)/25;
//  else
    //  Distance = 1;
    
    


/*

//Used by the interactor to get stuff started
void controls::Start ( vtkInteractorStyleUser * style )
{
    style->StartUserInteraction();
        cout<< "Inside ocomp start"<< endl;
}

//Used by the interactor to stop
void controls::End ( vtkInteractorStyleUser * style )
{
    style->EndUserInteraction();
}  

void controls::GetKey(KeyPair *keyPair)
{
    
    //float FOCAL_LENGTH = 0.5;
    //KeyPair *keyPair = (KeyPair*) keyPairVoid;
    float cam[3], foc[3];
    //camera location; focal point location
    
    std::string key = keyPair->style->GetKeySym();
    
    //Right Cursor Key
    if ( key == "Right" )
    {
        keyPair->camera->Yaw( -2 );
        
        //Rerender
        keyPair->iren->Render();
    }
    
    //Left Cursor Key
    else if ( key == "Left" )
    {
        keyPair->camera->Yaw( 2 );
        
        //Rerender
        keyPair->iren->Render();
    }
    
    //Up Cursor Key
    else if ( key == "Up" )
    {
        //get and modify camera position and focal points
        keyPair->camera->GetPosition( cam );
        keyPair->camera->GetFocalPoint( foc );
        
        //reset the new points
        keyPair->camera->SetPosition( 
            cam[0] + (1/(2*FOCAL_LENGTH)) * (foc[0]-cam[0]),
            cam[1] + (1/(2*FOCAL_LENGTH)) * (foc[1]-cam[1]),
            cam[2] + (1/(2*FOCAL_LENGTH)) * (foc[2]-cam[2]) );
        keyPair->camera->SetFocalPoint(
            foc[0] + (1/(2*FOCAL_LENGTH)) * (foc[0]-cam[0]),
            foc[1] + (1/(2*FOCAL_LENGTH)) * (foc[1]-cam[1]),
            foc[2] + (1/(2*FOCAL_LENGTH)) * (foc[2]-cam[2]) ); 
        
        //Rerender
        keyPair->iren->Render();
    }
    
    //Down Cursor Key
    else if ( key == "Down" )
    {
        //get and modify camera position and focal points
        keyPair->camera->GetPosition( cam );
        keyPair->camera->GetFocalPoint( foc );
        
        //reset the new points
        keyPair->camera->SetPosition( 
            cam[0] - (1/(2*FOCAL_LENGTH)) * (foc[0]-cam[0]),
            cam[1] - (1/(2*FOCAL_LENGTH)) * (foc[1]-cam[1]),
            cam[2] - (1/(2*FOCAL_LENGTH)) * (foc[2]-cam[2]) );
        keyPair->camera->SetFocalPoint(
            foc[0] - (1/(2*FOCAL_LENGTH)) * (foc[0]-cam[0]),
            foc[1] - (1/(2*FOCAL_LENGTH)) * (foc[1]-cam[1]),
            foc[2] - (1/(2*FOCAL_LENGTH)) * (foc[2]-cam[2]) );
        
        //Rerender
        keyPair->iren->Render();
    }
    
    //Page Up
    else if ( key == "Prior" )
    {
        keyPair->camera->Pitch( 2 );
        keyPair->iren->Render();
    }
    
    //Page Down
    else if ( key == "Next" )
    {
        keyPair->camera->Pitch( -2 );
        keyPair->iren->Render();
    }
    
}

//This looks strange to many.
//
//What this is doing is setting the way the new
//  interactor works.
//Start is the function, above; style is the argument to that function
//End is the function, above; style is the arguement to that function
//GetKey is the function, above; keyPair is the SINGLE arguement to
//  that function.
void controls::Interactor2( vtkInteractorStyleUser * style, KeyPair * keyPair )
{
//  style->SetButtonPressMethod( (void(*)(void*))Start, style );
//  style->SetButtonReleaseMethod( (void(*)(void*)) End, style );
//  style->SetKeyPressMethod( (void (*)(void *)) GetKey, keyPair);
}

*/

/*void controls::SetKeyPressMethod(void (*f)(void*), void *arg)
{
  this->vtkSetOldCallback(this->KeyPressTag,
                    vtkCommand::KeyPressEvent,f,arg);
}

void controls::vtkSetOldCallback(unsigned long &tag, 
                                               unsigned long event, 
                                               void (*f)(void *), void *arg)
{
  if ( tag )
    {
    this->RemoveObserver(tag);
    }
  
  if ( f )
    {
    vtkOldStyleCallbackCommand *cbc = vtkOldStyleCallbackCommand::New();
    cbc->Callback = f;
    cbc->ClientData = arg;
    tag = this->AddObserver(event,cbc);
    cbc->Delete();
    }
}

void controls::vtkSetOldDelete(unsigned long tag, void (*f)(void *))
{
  vtkOldStyleCallbackCommand *cmd = 
    (vtkOldStyleCallbackCommand *)this->GetCommand(tag);
  if (cmd)
    {
    cmd->SetClientDataDeleteCallback(f);
    }
}

*/

/* void controls::RotateLeft()
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  vtkCamera *cam;

  if ( this->CurrentRenderer == NULL || this->InteractionProp == NULL )
    {
    return;
    }
  
  cam = this->CurrentRenderer->GetActiveCamera();
  
  // first get the origin of the assembly
  float *center = this->InteractionProp->GetCenter();
  this->ObjCenter[0] = center[0];
  this->ObjCenter[1] = center[1];
  this->ObjCenter[2] = center[2]; 
  
  // GetLength gets the length of the diagonal of the bounding box
  double boundRadius = this->InteractionProp->GetLength() * 0.5;
  
  // get the view up and view right vectors
  cam->OrthogonalizeViewUp();
  cam->ComputeViewPlaneNormal();
  cam->GetViewUp(this->ViewUp);
  vtkMath::Normalize(this->ViewUp);
  cam->GetViewPlaneNormal(this->ViewLook);
  vtkMath::Cross(this->ViewUp, this->ViewLook, this->ViewRight);
  vtkMath::Normalize(this->ViewRight);
  
  // get the furtherest point from object bounding box center
  float outsidept[3];
  outsidept[0] = this->ObjCenter[0] + this->ViewRight[0] * boundRadius;
  outsidept[1] = this->ObjCenter[1] + this->ViewRight[1] * boundRadius;
  outsidept[2] = this->ObjCenter[2] + this->ViewRight[2] * boundRadius;
  
  // convert to display coord
  this->ComputeWorldToDisplay(this->ObjCenter[0], this->ObjCenter[1],
                              this->ObjCenter[2], this->DispObjCenter);
  this->ComputeWorldToDisplay(outsidept[0], outsidept[1],
                              outsidept[2], outsidept);
  
  this->Radius = sqrt(vtkMath::Distance2BetweenPoints(this->DispObjCenter,
                                                      outsidept));
  
  this->HighlightProp3D(NULL);
  
  double nxf = (double)(x - this->DispObjCenter[0]) / this->Radius;
  double nyf = (double)(y - this->DispObjCenter[1]) / this->Radius; 
  
  if (nxf > 1.0)
    {
    nxf = 1.0;
    }
  else if (nxf < -1.0)
    {
    nxf = -1.0;
    }
  
  if (nyf > 1.0)
    {
    nyf = 1.0;
    }
  else if (nyf < -1.0)
    {
    nyf = -1.0;
    } 
  
  double newXAngle = asin(nxf) * this->RadianToDegree / this->MotionFactor;
  double newYAngle = asin(nyf) * this->RadianToDegree / this->MotionFactor;
  
  double scale[3];
  scale[0] = scale[1] = scale[2] = 1.0;
  double **rotate = new double*[2];
  rotate[0] = new double[4];
  rotate[1] = new double[4];
  
  rotate[0][0] = newXAngle;
  rotate[0][1] = this->ViewUp[0];
  rotate[0][2] = this->ViewUp[1];
  rotate[0][3] = this->ViewUp[2];
  
  rotate[1][0] = -newYAngle;
  rotate[1][1] = this->ViewRight[0];
  rotate[1][2] = this->ViewRight[1];
  rotate[1][3] = this->ViewRight[2];
  
  
  this->Prop3DTransform(this->InteractionProp,
                        this->ObjCenter,
                        2, rotate, scale);
  
  delete [] rotate[0];
  delete [] rotate[1];
  delete [] rotate;
  
  rwi->Render();
}

void controls::RotateRight()
{

} */




/*
void controls::OnLeftArrowUp(int X, int Y)
{
    //vtkRenderWindowInteractor *rwi = this->Interactor;
    this->UpdateInternalState(NULL, NULL, X, Y);
    this->FindPokedCamera(X,Y);

    if (this->HasObserver(vtkCommand::KeyPressEvent)) 
    {
        this->InvokeEvent(vtkCommand::KeyPressEvent,NULL);
    }
    else 
    {
    //  vtkRenderWindowInteractor *rwi = this->Interactor;
    //  cout<<"Onleftarrowdown\n";
    //this->EndRotate();
    //this->CurrentCamera->Azimuth(5);
    }
        //rwi->Render();
 // cout<<"after azi in lad\n";
        
}*/

/*
void controls::OnRightArrowUp(int X, int Y) 
{
        //vtkRenderWindowInteractor *rwi = this->Interactor;
 this->UpdateInternalState(NULL, NULL, X, Y);
  
        this->CurrentCamera->Azimuth(5);
        //rwi->Render(); 
}
*/

/*void controls::OnKeyRelease(int ctrl, int shift, 
                                          char keycode, char *keysym, 
                                          int vtkNotUsed(repeatcount))
{
        int x=0, y=0;

//  cout<<"inside keyrelease"<<endl;
//  vtkRenderWindowInteractor *rwi = this->Interactor;
    //cout<<"before cam"<<endl;
    //vtkCamera *cam = this->CurrentRenderer->GetActiveCamera();//vtkCamera::New();
    
    //cout<<"inside keyrelease after camera"<<endl;

  
    //  vtkInteractorStyleUser *isu = vtkInteractorStyleUser::New();
    //  char *key1 = isu->GetKeySym();
        switch(keycode)
        {
            case ',':
            case '<':
            OnLeftArrowUp(x,y);
                break;
            case '.':
            case '>':
            //this->EndRotate();
            //this->State = VTK_INTERACTOR_STYLE_ACTOR_ROTATE;
                break;
        }
    //  rwi->Render();


} */
/*
void  controls::StartState(int newstate) 
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  this->State = newstate;
  if (this->AnimState == VTKIS_ANIM_OFF) 
    {
    rwi->GetRenderWindow()->SetDesiredUpdateRate(.8);
    if ( !rwi->CreateTimer(VTKI_TIMER_FIRST) ) 
      {
      vtkErrorMacro(<< "Timer start failed");
      this->State = VTKIS_START;
      }
    }
}
//----------------------------------------------------------------------------
void  controls::StopState() 
{
  vtkRenderWindowInteractor *rwi = this->Interactor;
  this->State = VTKIS_START;
  if (this->AnimState == VTKIS_ANIM_OFF) 
    {   
    rwi->GetRenderWindow()->SetDesiredUpdateRate(.8);
    rwi->Render();
    if ( !rwi->DestroyTimer() ) 
      {
      vtkErrorMacro(<< "Timer stop failed");
      }
    }   
}
*/
