[vtkusers] vtkAxis

Dean Inglis dean.inglis at camris.ca
Wed Mar 24 14:11:20 EST 2004


Hi,

I was intrigues with James Robinson's code, since I've also always wanted
a camera following axes, so I revised a bit of the posted code and made
a class out of it.  I hope others will find the following input useful.
I noted upon implementing this myself that the axes appear to "wobble":
that is the origin of the axes would not remain centered in the allotted
viewport.

>Below is code taken directly from my application. I assume that you know
>already that the best way to achieve the effect of having an axis in the
>window is to create a separate renderer in an embedded viewport for those
>axis (pAxisRenderer in my code).

A more ideal way to do this is to avoid use of an "embedded viewport"
and make the axes derive from vtkActor2D, but James' solution works very
well,
especially if you set the background color of the second viewport to be the
same as the main one.

>part of the view. You then create a callback that tracks what the camera
for
>the main renderer is doing and in that callback you set the position
>parameters etc. of the axis renderer camera to mimic it. Finally, the trick
>to achieve the same scaling as you zoom in and out is to control the size
of
>the viewport relative to the window size.

The modified callback posted below also allows specifying which corner of
the
main window to reside in (requires an ivar to store this info).

>Also note that the bulk of this code is not attributable to me but to some
>good soul (don't have the time to respond) who answered a related question
>for me about 4 weeks ago.

That's what users' groups are also great for :)

Please see James' original post on this to see how the mods to the original
callback fit in.

Dean

void updateAxes(vtkObject* caller,
                                  unsigned long vtkNotUsed(event),
                                  void* arg,
                                  void* vtkNotUsed(whatIsThis))
{
  double    cPos[3], cFoc[3], aFoc[3];
  int       *size;

  if (pVTKView->pAxisRenderer == NULL) return ;
  size = pVTKView->RenderWindow->GetSize();

  vtkFloatingPointType ViewPortLeft, ViewPortBottom, ViewPortRight,
                       ViewPortTop ;

  if (pVTKView->AxesViewportFixed)
    {
//keep the axis window size a constant "AxesViewportSize" pixels squared
(ugly)

    ViewPortLeft = ( size[0]- pVTKView->AxesViewportSize )/
                    (vtkFloatingPointType)size[0] ;
    ViewPortRight  = 1.0 ;
    ViewPortBottom = 0.0 ;
    ViewPortTop    =
pVTKView->AxesViewportSize/(vtkFloatingPointType)size[1] ;
    }
  else
    {
// The Viewport changes to keep the same scale related to the window

    ViewPortLeft   = 1.0 - pVTKView->AxesViewportScaledSize ;
    ViewPortRight  = 1.0 ;
    ViewPortBottom = 0.0 ;
    ViewPortTop    = pVTKView->AxesViewportScaledSize ;
    }

  switch(pVTKView->GetCornerLocation())
   {
// 0 lower left, 1 lower right, 2 upper right, 3 upper left

   case 0: ViewPortRight = 1.0 - ViewPortLeft; ViewPortLeft = 0.0; break;
   case 2: ViewPortBottom = 1.0 - ViewPortTop; ViewPortTop = 1.0;  break;
   case 3: ViewPortBottom = 1.0 - ViewPortTop; ViewPortTop = 1.0;
             ViewPortRight = 1.0 - ViewPortLeft; ViewPortLeft = 0.0; break;
   }

  pVTKView->pAxisRenderer->SetViewport(ViewPortLeft,ViewPortBottom,
                                       ViewPortRight,ViewPortTop);

// focus at the origin of the axes
  pVTKView->pAxisRenderer->GetActiveCamera()->SetFocalPoint(0.0,0.0,0.0);

// set the axis camera according to the main renderer
  vtkCamera *cam = (vtkCamera *)arg;

// camera for the secondary renderer
  vtkCamera* cam2 = pVTKView->pAxisRenderer->GetActiveCamera();

  cam2->SetViewUp(cam->GetViewUp());
  cam->GetPosition(cPos);
  cam->GetFocalPoint(cFoc);
  cam2->SetPosition(cPos[0] - cFoc[0], cPos[1] - cFoc[1], cPos[2] -
cFoc[2]);

  pVTKView->pAxisRenderer->ResetCamera();

// the following corrects the "wobble"
// There are likely algebraic simplifications to speed things up, but it
seems to work

    double disp1[4], disp2[4];

    pVTKView->pAxisRenderer->SetWorldPoint(0.0,0.0,0.0,1.0);
    pVTKView->pAxisRenderer->WorldToDisplay();
    pVTKView->pAxisRenderer->GetDisplayPoint(disp1);

    pVTKView->pAxisRenderer->SetViewPoint(0.0,0.0,0.0);
    pVTKView->pAxisRenderer->ViewToDisplay();
    pVTKView->pAxisRenderer->GetDisplayPoint(disp2);

    pVTKView->pAxisRenderer->SetDisplayPoint(disp2[0], disp2[1], disp1[2]);
    pVTKView->pAxisRenderer->DisplayToWorld();
    double newPos[4] = {0.0,0.0,0.0,1.0};
    pVTKView->pAxisRenderer->GetWorldPoint(newPos);
    if (newPos[3])
      {
      newPos[0] /= newPos[3];
      newPos[1] /= newPos[3];
      newPos[2] /= newPos[3];
      newPos[3] = 1.0;
      }
    cam2->GetFocalPoint(cFoc);
    cam2->GetPosition(cPos);
    cam2->SetFocalPoint(cFoc[0] - newPos[0],
                        cFoc[1] - newPos[1], cFoc[2] - newPos[2]);
    cam2->SetPosition(  cPos[0] - newPos[0],
                        cPos[1] - newPos[1], cPos[2] - newPos[2]);

    pVTKView->pAxisRenderer->Render();
}





More information about the vtkusers mailing list