void
VisWinFrame::GetRange(double &min_x, double &max_x, double &min_y, double &max_y)
{
    VisWindow *vw = mediator;

    switch (vw->GetWindowMode())
    {
      case WINMODE_2D:
        {
        const avtView2D view2D = vw->GetView2D();
        min_x = view2D.window[0];
        max_x = view2D.window[1];
        min_y = view2D.window[2];
        max_y = view2D.window[3];
        }
        break;
      case WINMODE_CURVE:
        {
            const avtViewCurve viewCurve = vw->GetViewCurve();
            min_x = viewCurve.domain[0];
            max_x = viewCurve.domain[1];
            min_y = viewCurve.range[0];
            max_y = viewCurve.range[1];
        }
        break;
      default:
        break;
    }
}
void
VisWinFrame::UpdateView(void)
{
    double  min_x = 0., max_x = 0., min_y = 0., max_y = 0.;
    GetRange(min_x, max_x, min_y, max_y);

    //
    // We put the topBorder in reverse so that its ticks would appear on the
    // correct side of the viewport.  Must propogate kludge by sending
    // range in backwards.
    //
    leftBorder->SetRange(max_y, min_y);
    leftBorder->SetUseOrientationAngle(1);
    leftBorder->SetOrientationAngle(-1.5707963);

    rightBorder->SetRange(min_y, max_y);
    rightBorder->SetUseOrientationAngle(1);
    rightBorder->SetOrientationAngle(1.5707963);

    bottomBorder->SetRange(min_x, max_x);
    bottomBorder->SetUseOrientationAngle(1);
    bottomBorder->SetOrientationAngle(0.);

    topBorder->SetRange(max_x, min_x);
    topBorder->SetUseOrientationAngle(1);
    topBorder->SetOrientationAngle(3.1415926);

    VisWindow *vw = mediator;
    bool logScale[2] = { false, false};
    if (vw->GetWindowMode() == WINMODE_CURVE)
    {
        const avtViewCurve viewCurve = vw->GetViewCurve();
        logScale[0] = viewCurve.domainScale == LOG;
        logScale[1] = viewCurve.rangeScale == LOG;
    }
    else if (vw->GetWindowMode() == WINMODE_2D)
    {
        const avtView2D view2D = vw->GetView2D();
        logScale[0] = view2D.xScale == LOG;
        logScale[1] = view2D.yScale == LOG;
    }
    topBorder->SetLogScale((int)logScale[0]);
    bottomBorder->SetLogScale((int)logScale[0]);
    rightBorder->SetLogScale((int)logScale[1]);
    leftBorder->SetLogScale((int)logScale[1]);
}
void
NavigateCurve::PanCamera(const int x, const int y)
{
    vtkRenderWindowInteractor *rwi = Interactor;

    if ((OldX != x) || (OldY != y))
    {
        //
        // Determine the size of the window.
        //
        int       size[2];

        rwi->GetSize(size);

        //
        // Get the current view information.
        //
        VisWindow *vw = proxy;

        double    pan[2];

        avtViewCurve newViewCurve = vw->GetViewCurve();

        pan[0] = (double)(x - OldX) /
                 ((newViewCurve.viewport[1] - newViewCurve.viewport[0]) *
                  (double)(size[0])) *
                 (newViewCurve.domain[1] - newViewCurve.domain[0]);
        pan[1] = (double)(y - OldY) /
                 ((newViewCurve.viewport[3] - newViewCurve.viewport[2]) *
                  (double)(size[1])) *
                 (newViewCurve.range[1] - newViewCurve.range[0]);

        newViewCurve.domain[0] -= pan[0];
        newViewCurve.domain[1] -= pan[0];
        newViewCurve.range[0]  -= pan[1];
        newViewCurve.range[1]  -= pan[1];

        vw->SetViewCurve(newViewCurve);

        OldX = x;
        OldY = y;
        rwi->Render();
    }
}
void
ZoomCurve::ZoomCamera(const int x, const int y)
{
    vtkRenderWindowInteractor *rwi = Interactor;

    if (OldY != y)
    {
        //
        // Calculate the zoom factor.
        //
        double dyf = MotionFactor * (double)(y - OldY) /
                         (double)(Center[1]);
        double zoomFactor = pow((double)1.1, dyf);

        //
        // Calculate the new window.
        //
        VisWindow *vw = proxy;

        avtViewCurve newViewCurve = vw->GetViewCurve();

        double dX = ((1. / zoomFactor) - 1.) *
                    ((newViewCurve.domain[1] - newViewCurve.domain[0]) / 2.);
        double dY = ((1. / zoomFactor) - 1.) *
                    ((newViewCurve.range[1] - newViewCurve.range[0]) / 2.);

        newViewCurve.domain[0] -= dX;
        newViewCurve.domain[1] += dX;
        newViewCurve.range[0]  -= dY;
        newViewCurve.range[1]  += dY;

        vw->SetViewCurve(newViewCurve);

        OldX = x;
        OldY = y;
        rwi->Render();
    }
}
void
NavigateCurve::ZoomCamera(double f)
{
    double zoomFactor = pow((double)1.1, f);

    //
    // Calculate the new parallel scale.
    //
    VisWindow *vw = proxy;

    avtViewCurve newViewCurve = vw->GetViewCurve();
    double dX = ((1. / zoomFactor) - 1.) *
                ((newViewCurve.domain[1] - newViewCurve.domain[0]) / 2.);
    double dY = ((1. / zoomFactor) - 1.) *
                ((newViewCurve.range[1] - newViewCurve.range[0]) / 2.);

    newViewCurve.domain[0] -= dX;
    newViewCurve.domain[1] += dX;
    newViewCurve.range[0]  -= dY;
    newViewCurve.range[1]  += dY;

    vw->SetViewCurve(newViewCurve);
}
void
ZoomCurve::ZoomCamera(void)
{
    if (!SufficientDistanceMoved())
    {
        //
        // This is a point, line, or very, very small rectangle.
        //
        return;
    }

    //
    // Figure out the lower left and upper right hand corners in
    // display space.
    //
    double leftX   = (double) (anchorX < lastX ? anchorX : lastX);
    double rightX  = (double) (anchorX > lastX ? anchorX : lastX);
    double bottomY = (double) (anchorY < lastY ? anchorY : lastY);
    double topY    = (double) (anchorY > lastY ? anchorY : lastY);
    double dummyZ  = 0.;

    //
    // Convert them to world coordinates.
    //
    vtkRenderer *canvas = proxy.GetCanvas();

    canvas->DisplayToNormalizedDisplay(leftX, topY);
    canvas->NormalizedDisplayToViewport(leftX, topY);
    canvas->ViewportToNormalizedViewport(leftX, topY);
    canvas->NormalizedViewportToView(leftX, topY, dummyZ);
    canvas->ViewToWorld(leftX, topY, dummyZ);

    canvas->DisplayToNormalizedDisplay(rightX, bottomY);
    canvas->NormalizedDisplayToViewport(rightX, bottomY);
    canvas->ViewportToNormalizedViewport(rightX, bottomY);
    canvas->NormalizedViewportToView(rightX, bottomY, dummyZ);
    canvas->ViewToWorld(rightX, bottomY, dummyZ);

    //
    // Set the new view window.
    //
    VisWindow *vw = proxy;

    avtViewCurve newViewCurve=vw->GetViewCurve();

    int       size[2];

    vtkRenderWindowInteractor *rwi = Interactor;
    rwi->GetSize(size);

    double s = newViewCurve.GetScaleFactor(size);

    if (!controlKeyDown) // zoom
    {
        newViewCurve.domain[0] = leftX;
        newViewCurve.domain[1] = rightX;
        newViewCurve.range[0]  = bottomY/s;
        newViewCurve.range[1]  = topY/s;
    }
    else // un-zoom 
    {
        float win1[4], win2[4], win3[4], win4[4];

        // window created by rubber band
        win1[0] = leftX;
        win1[1] = rightX;
        win1[2] = bottomY;
        win1[3] = topY;
        float win1_w = win1[1] - win1[0];
        float win1_h = win1[3] - win1[2];

        // the current window 
        win2[0] = newViewCurve.domain[0];
        win2[1] = newViewCurve.domain[1];
        win2[2] = newViewCurve.range[0];
        win2[3] = newViewCurve.range[1];
        float win2_w = win2[1] - win2[0];
        float win2_h = win2[3] - win2[2];

        float scaleX = win1_w / win2_w;
        float scaleY = win1_h / win2_h;

        if (scaleY < scaleX)
        {
            float midX = (win2[0] + win2[1]) / 2.;
            float halfw = (win2_h) * (win1_w / win1_h) / 2.;
            win3[0] = midX - halfw;
            win3[1] = midX + halfw;
            win3[2] = win2[2];
            win3[3] = win2[3];
        }
        else 
        {
            float midY = (win2[2] + win2[3]) /2.;
            float halfh = (win2_w) * (win1_h / win1_w) / 2.;
            win3[0] = win2[0];
            win3[1] = win2[1]; 
            win3[2] = midY - halfh;
            win3[3] = midY + halfh;
        }

        float win3_w = (win3[1] - win3[0]);
        float win3_h = (win3[3] - win3[2]);

        win4[0] = ((win1[0] - win2[0]) / win2_w) * win3_w + win3[0];
        win4[1] = ((win1[1] - win2[0]) / win2_w) * win3_w + win3[0];
        win4[2] = ((win1[2] - win2[2]) / win2_h) * win3_h + win3[2];
        win4[3] = ((win1[3] - win2[2]) / win2_h) * win3_h + win3[2];

        float win4_w = (win4[1] - win4[0]);
        float win4_h = (win4[3] - win4[2]);

        newViewCurve.domain[0] = (win3[0] - win4[0]) * win3_w / win4_w + win3[0];
        newViewCurve.domain[1] = (win3[1] - win4[0]) * win3_w / win4_w + win3[0];
        newViewCurve.range[0]  = (win3[2] - win4[2]) * win3_h / win4_h + win3[2];
        newViewCurve.range[1]  = (win3[3] - win4[2]) * win3_h / win4_h + win3[2];

        newViewCurve.range[0] /= s;
        newViewCurve.range[1] /= s;
    }

    vw->SetViewCurve(newViewCurve);

    //
    // It looks like we need to explicitly re-render.
    //
    proxy.Render();
}