[vtkusers] Problem with zoom window code ported from TCL to C++ (from vtk3.2)

Ted Christiansen ted at caept.com
Thu Aug 22 12:34:35 EDT 2002


Hello,

I rewrote the code for zoom window from the TKinteractor.tcl (below).
It works most of the time but if I try to zoom in to a smaller feature
then it doesnt center the model as expected.  Has anyone else had this
problem, and if so what is the fix?

A sample application to test is available at
http://www.caept.com/vtk/test.exe

Using the zoom window toolbar button, try zooming in on the top left
corner of the block.  It will zoom in but the model will only show in
the top right corner of the view not at all centered as expected.

Your help is appreciated.

Ted

class CFEvisGLView
{

<snip>
 // zoom window
 void DoZoomWindow(CPoint point);
 CPoint    m_startdrag;
 CRect    m_previous;
 CRect    m_current;
 BOOL    m_dragging;
</snip>
};


/////////////////////////////////////////////////////////////////////////////

// Zoom window
// http://public.kitware.com/pipermail/vtkusers/2000-January/003119.html

// From TCL implementation: Tkinteractor.tcl
/////////////////////////////////////////////////////////////////////////////

void CFEvisGLView::DoZoomWindow(CPoint point)
{
 CRect viewdims;
 CPoint zoomboxcenter;

 vtkCamera *pCam = Renderer->GetActiveCamera();

 // get view dimensions
 GetClientRect(&viewdims);

 // get box center point in pixels
 zoomboxcenter = m_current.CenterPoint();
 // correct
 // zoomboxcenter.y = viewdims.CenterPoint().y - zoomboxcenter.y;

    // Convert the focal point to a display coordinate in order to get
the
    // depth of the focal point in display units
 double focalpoint[3];
 pCam->GetFocalPoint(focalpoint);
 Renderer->SetWorldPoint(focalpoint[0], focalpoint[1], focalpoint[2],
1.0);
    Renderer->WorldToDisplay();
    double displaypoint[3];
 Renderer->GetDisplayPoint(displaypoint);
 double focaldepth = displaypoint[2];



    // Convert the position of the camera to a display coordinate in
order
    // to get the depth of the camera in display coordinates. Note this
is
    // a negative number (behind the near clipping plane of 0) but it
works
    // ok anyway
 double camposition[3];
 pCam->GetPosition(camposition[0], camposition[1], camposition[2]);
 Renderer->SetWorldPoint(camposition[0], camposition[1], camposition[2],
1.0);
    Renderer->WorldToDisplay();
 Renderer->GetDisplayPoint(displaypoint);
 double positiondepth = displaypoint[2];


    // Find out the world position of where our new focal point should
    // be - it will be at the center of the box, back at the same focal
depth
    // Don't actually set it now - we need to do all our computations
before
    // we modify the camera
 Renderer->SetDisplayPoint(zoomboxcenter.x, zoomboxcenter.y,
focaldepth);
 Renderer->DisplayToWorld();
 float newfocalpoint[4];
 Renderer->GetWorldPoint(newfocalpoint);
 if (newfocalpoint[3] != 0.0) {
  newfocalpoint[0] = newfocalpoint[0] / newfocalpoint[3];
  newfocalpoint[1] = newfocalpoint[1] / newfocalpoint[3];
  newfocalpoint[2] = newfocalpoint[2] / newfocalpoint[3];
 }

    // Find out where the new camera position will be - at the center of

    // the rubber band box at the position depth. Don't set it yet...
    Renderer->SetDisplayPoint(zoomboxcenter.x, zoomboxcenter.y,
positiondepth);
 Renderer->DisplayToWorld();
 float newposition[4];
 Renderer->GetWorldPoint(newposition);
 if (newposition[3] != 0.0) {
  newposition[0] = newposition[0] / newposition[3];
  newposition[1] = newposition[1] / newposition[3];
  newposition[2] = newposition[2] / newposition[3];
 }

    // We figured out how to position the camera to be centered, now we
    // need to "zoom". In parallel, this is simple since we only need to

    // change our parallel scale to encompass the entire y range of the
    // rubber band box. In perspective, we assume the box is drawn on
the
    // near plane - this means that it is not possible that someone can
    // draw a rubber band box around a nearby object and dolly past it.
It
    // also means that you won't get very close to distance objects -
but that
    // seems better than getting lost.
 ASSERT(pCam->GetParallelProjection() == TRUE);
 // the new scale is just based on the y size of the rubber band box
 // compared to the y size of the window
 double newscale = pCam->GetParallelScale();
 newscale = newscale * m_current.Width() / viewdims.Width();
 TRACE("CFEvisGLView::DoZoomWindow, newscale=%f\n", newscale);

 // now we can actually modify the camera
 pCam->SetFocalPoint(newfocalpoint[0], newfocalpoint[1],
newfocalpoint[2]);
 pCam->SetPosition(newposition[0], newposition[1], newposition[2]);
 pCam->SetParallelScale(newscale);

 // redraw thus erasing rubberbanded box
 Invalidate(FALSE);
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20020822/3fdf3026/attachment.htm>


More information about the vtkusers mailing list