[vtkusers] Clipping problem when panning

John Platt jcplatt at dsl.pipex.com
Wed Aug 21 08:52:16 EDT 2013


SnippetHi Serge,

This is the same as ResetCamera() followed by a zoom factor based on the 
extreme (x,y) view coordinates rather than a bounding sphere...


void CameraHelper::Fit()

{

// Move the camera so that it's focal point is the centre of the bounding 
box

// preserving the view plane normal (vector defined from camera position to

// focal point). The parallel scale is adjusted to maximize the scene in the

// viewport. This is identical to ResetCamera() except the scale factor is

// calculated from extreme x & y rather than the bounding sphere.


// Compute the bounding box of all the visible 3D props in World 
coordinates.

double allBounds[6];

m_vtkRenderer->ComputeVisiblePropBounds( allBounds );

// Only proceed if there are visible 3D props.

if ( vtkMath::AreBoundsInitialized( allBounds ) )

{

// Reposition the camera to view the centre point of the visible 3D actors.

// The camera is moved so that it's focal point is the centre of the 
bounding

// box, and the distance and position adjusted to preserve the view plane

// normal (vector defined from camera position to focal point).

m_vtkRenderer->ResetCamera();

// Find the extreme x & y positions of the bounding box in View (camera)

// coordinates. The origin of the View coordinate system is the middle of

// the viewport with axes extending from -1 to 1 in all three dimensions.

double maxAbsViewX = -1.0;

double maxAbsViewY = -1.0;

for ( int k = 0; k < 2; k++ )

{

for ( int j = 0; j < 2; j++ )

{

for ( int i = 0; i < 2; i++ )

{

// The View coordinates overwrite the World coordinates and

// therfore the copying cannot be done in the outer loops.

double x = allBounds[i];

double y = allBounds[2+j];

double z = allBounds[4+k];

m_vtkRenderer->WorldToView( x, y, z );

if ( abs( x ) > maxAbsViewX ) maxAbsViewX = abs( x );

if ( abs( y ) > maxAbsViewY ) maxAbsViewY = abs( y );

}

}

}

// Allow a margin so the fit is not too tight.

double viewMargin = PixelsToView( m_marginPixels );

maxAbsViewX += viewMargin;

maxAbsViewY += viewMargin;

// ResetCamera() uses the bounding sphere to fit the props. Calculate a

// new scale ( greater than 1 ) to fit the extreme X or Y. This should be

// close to 1 because of the ResetCamera() call above.

const double* aspectRatio = m_vtkRenderer->GetAspect();

double scaleX = aspectRatio[1]/( maxAbsViewX );

double scaleY = 1.0/maxAbsViewY;

double scale = scaleX > scaleY ? scaleY : scaleX;

// In parallel mode, Zoom() decreases the parallel scale by the specified

// factor. A scale > 1 is a zoom-in, and a scale < 1 is a zoom-out.

m_vtkRenderer->GetActiveCamera()->Zoom( scale );

}

}

Sorry about the format - I use a poor man's mail client.

John.



----- Original Message ----- 
From: Serge Lalonde
To: vtkusers at vtk.org
Sent: Wednesday, August 21, 2013 1:29 PM
Subject: Re: [vtkusers] Clipping problem when panning


Hi John,

Is that the same as ResetCamera? If not, how is it different and where can I 
find the code for it in ParaView? Maybe I can add that also.

Thanks.


On 8/20/2013 5:27 PM, John Platt wrote:

Hi Serge,

If it helps your sanity, I can repeat this clipping problem in VTK 5.10 
using the default interactor with QVTKWidget, which I believe is trackball 
camera, and parallel projection on.

When this happens, I have a 'Fit' option which moves the focal point of the 
camera to the centre of the actors and adjusts the parallel scale to fill 
the view.

John.
----- Original Message ----- 
From: Serge Lalonde
To: vtkusers at vtk.org
Sent: Tuesday, August 20, 2013 8:12 PM
Subject: Re: [vtkusers] Clipping problem when panning


Well, since I got no responses, I dug deeper and found the code in ParaView 
that does the rotation and spinning around the center of the visible actors, 
extracted it and put it into a vtkInteractorStyleTrackballCamera subclass. 
It hasn't been extensively tested yet, but it seems to work well.

Here it is in case it helps save anybody else 3 days of work.


   // Our subclass of the trackball camera to change the center of rotation 
to be the average
   // center of all visible actors instead of the center of the viewport, 
which always gets clipped.
   // The default implementation is badly broken and doesn't look to be 
fixed anytime soon.
   // The clipping might be fixed with the changes I submitted: 
http://www.vtk.org/Bug/view.php?id=7823
   // The new rotation code was taken from ParaView. Specifically,
   // - Rotate(): vtkPVTrackballRotate.cxx OnMouseMove()
   // - Spin(): vtkPVTrackballRoll.cxx OnMouseMove()
   // - UpdateScreenCenterOfRotation(): vtkCameraManipulator.cxx 
ComputeDisplayCenter()
   class InteractorStyleTrackballCamera: public 
vtkInteractorStyleTrackballCamera
   {
   public:
      static InteractorStyleTrackballCamera *New();
      vtkTypeMacro(InteractorStyleTrackballCamera, 
vtkInteractorStyleTrackballCamera);

      // This only gets called is CurrentRenderer isn't NULL.
      virtual void StartRotate()
      {
         Superclass::StartRotate();
         UpdateCenterOfRotation(CurrentRenderer);
      }

      // This only gets called is CurrentRenderer isn't NULL.
      virtual void StartSpin()
      {
         Superclass::StartSpin();
         UpdateCenterOfRotation(CurrentRenderer);
         UpdateScreenCenterOfRotation(CurrentRenderer);
      }

      virtual void Rotate()
      {
         if (CurrentRenderer == NULL)
            return;

         vtkRenderer *ren= CurrentRenderer;
         vtkCamera *camera= ren->GetActiveCamera();
         vtkRenderWindowInteractor *rwi= Interactor;
         vtkTransform *transform= vtkTransform::New();

         double scale= vtkMath::Norm(camera->GetPosition());
         if (scale <= 0.0)
         {
            scale= vtkMath::Norm(camera->GetFocalPoint());
            if (scale <= 0.0)
               scale= 1.0;
         }
         double *temp= camera->GetFocalPoint();
         camera->SetFocalPoint(temp[0]/scale, temp[1]/scale, temp[2]/scale);
         temp= camera->GetPosition();
         camera->SetPosition(temp[0]/scale, temp[1]/scale, temp[2]/scale);

         double v2[3];
         // translate to center
         transform->Identity();
         transform->Translate(m_center[0]/scale, m_center[1]/scale, 
m_center[2]/scale);

         int dx= rwi->GetLastEventPosition()[0] - 
rwi->GetEventPosition()[0];
         int dy= rwi->GetLastEventPosition()[1] - 
rwi->GetEventPosition()[1];

         // azimuth
         camera->OrthogonalizeViewUp();
         double *viewUp= camera->GetViewUp();
         int *size= ren->GetSize();
         transform->RotateWXYZ(360.0*dx/size[0], viewUp[0], viewUp[1], 
viewUp[2]);

         // elevation
         vtkMath::Cross(camera->GetDirectionOfProjection(), viewUp, v2);
         transform->RotateWXYZ(-360.0*dy/size[1], v2[0], v2[1], v2[2]);

         // translate back
         transform->Translate(-m_center[0]/scale, -m_center[1]/scale, -m_center[2]/scale);

         camera->ApplyTransform(transform);
         camera->OrthogonalizeViewUp();

         // For rescale back.
         temp= camera->GetFocalPoint();
         camera->SetFocalPoint(temp[0]*scale, temp[1]*scale, temp[2]*scale);
         temp= camera->GetPosition();
         camera->SetPosition(temp[0]*scale, temp[1]*scale, temp[2]*scale);

         ren->ResetCameraClippingRange();

         rwi->Render();
         transform->Delete();
      }

      virtual void Spin()
      {
         if (CurrentRenderer == NULL)
            return;

         vtkRenderer *ren= CurrentRenderer;
         vtkCamera *camera= ren->GetActiveCamera();
         vtkRenderWindowInteractor *rwi= Interactor;
         double axis[3];

         // compute view vector (rotation axis)
         double *pos= camera->GetPosition();
         double *fp= camera->GetFocalPoint();

         axis[0]= fp[0] - pos[0];
         axis[1]= fp[1] - pos[1];
         axis[2]= fp[2] - pos[2];

         int x1, x2, y1, y2;
         x1= rwi->GetLastEventPosition()[0] - (int) m_display_center[0];
         x2= rwi->GetEventPosition()[0] - (int) m_display_center[0];
         y1= rwi->GetLastEventPosition()[1] - (int) m_display_center[1];
         y2= rwi->GetEventPosition()[1] - (int) m_display_center[1];
         if ((x2 == 0.0 && y2 == 0.0) || (x1 == 0.0 && y1 == 0.0))
         {
            //don't ever want to divide by zero
            return;
         }

         // - divide by magnitudes to get angle
         double angle= vtkMath::DegreesFromRadians((x1*y2 - 
y1*x2)/(sqrt(static_cast<double>(x1*x1 + 
y1*y1))*sqrt(static_cast<double>(x2*x2 + y2*y2))));

         // translate to center
         vtkTransform *transform= vtkTransform::New();
         transform->Identity();
         transform->Translate(m_center[0], m_center[1], m_center[2]);

         // roll
         transform->RotateWXYZ(angle, axis[0], axis[1], axis[2]);

         // translate back
         transform->Translate(-m_center[0], -m_center[1], -m_center[2]);

         camera->ApplyTransform(transform);
         camera->OrthogonalizeViewUp();
         ren->ResetCameraClippingRange();

         rwi->Render();
         transform->Delete();
      }

   protected:
      InteractorStyleTrackballCamera()
      {
         m_center[0]= m_center[1]= m_center[2]= m_display_center[0]= 
m_display_center[1]= 0;
      }

      // Calculate the center of the visible actors.
      void UpdateCenterOfRotation(vtkRenderer *ren)
      {
         vtkActorCollection *actors= ren->GetActors();
         vtkCollectionSimpleIterator cookie;
         vtkActor *actor;

         m_center[0]= m_center[1]= m_center[2]= 0;
         actors->InitTraversal(cookie);
         while ((actor= actors->GetNextActor(cookie)) != NULL)
         {
            if (actor->GetVisibility())
            {
               double *actor_center= actor->GetCenter();

               m_center[0]+= actor_center[0];
               m_center[1]+= actor_center[1];
               m_center[2]+= actor_center[2];
            }
         }
         m_center[0]/= actors->GetNumberOfItems();
         m_center[1]/= actors->GetNumberOfItems();
         m_center[2]/= actors->GetNumberOfItems();
      }

      // Updates the screen center of rotation. Must be called after 
UpdateCenterOfRotation(),
      void UpdateScreenCenterOfRotation(vtkRenderer *ren)
      {
         double *pt;

         // save the center of rotation in screen coordinates
         ren->SetWorldPoint(m_center[0], m_center[1], m_center[2], 1.0);
         ren->WorldToDisplay();
         pt= ren->GetDisplayPoint();
         m_display_center[0]= pt[0];
         m_display_center[1]= pt[1];
      }

   private:
      double m_center[3],         // In model coordinates.
             m_display_center[2]; // In display coordinates.
   };
   vtkStandardNewMacro(InteractorStyleTrackballCamera);




On 8/13/2013 8:59 AM, Serge Lalonde wrote:

I've gotten no replies to this question. Does that mean that no one else has 
had this problem?

Can someone please confirm that they're using panning with 
vtkInteractorStyleTrackballCamera without any problems in 5.10?

Thanks.


On 8/6/2013 10:49 AM, Serge Lalonde wrote:

I tried panning in ParaView and the clipping works properly. Is it using the 
vtkInteractorStyleTrackballCamera or something else?

The problem is that it looks like the rotation center is wrong after 
panning, causing the model to be rotated out of the clipping range. It looks 
like the rotation center is the center of the window instead of the center 
of the model. Also, I have multiple actors in the scene. Could that be a 
problem?

I'm not doing anything (that I can tell) to affect this. Could it be a bug 
in VTK 5.10? If so, does anyone know of a workaround?

Thanks!


On 8/2/2013 3:59 PM, Serge Lalonde wrote:

I notice that when using the vtkInteractorStyleTrackballCamera panning, I'll 
subsequently see a clipping problem if I rotate the actors afterwards.
Calling ResetCameraClippingRange() on the renderer has no effect. I'm using 
VTK 5.10.

Is there a workaround for this? It seems like a pretty serious problem. I 
searched the archives without much success for a fix for this.

Note: Back in October 2008 (5 years already!), when I was prototyping with 
VTK, I posted a fix to vtkusers and www.vtk.org/bug for vtkRenderer and 
vtkCamera that fixed a similar clipping problem in VTK 5.2. After examining 
the 5.10 source code, it looks like the fix was never integrated into VTK's 
official code branch. The page is http://www.vtk.org/Bug/view.php?id=7823 
and I noticed that its status is expired. Other users commented in that bug 
report that it fixed their problems and some even improved the fix.



-- 
www.infolytica.com
300 Leo Pariseau, Suite 2222, Montreal, QC, Canada, H2X 4B3
(514) 849-8752 x236, Fax: (514) 849-4239



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: 
http://www.vtk.org/Wiki/VTK_FAQ

Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers



-- 
www.infolytica.com
300 Leo Pariseau, Suite 2222, Montreal, QC, Canada, H2X 4B3
(514) 849-8752 x236, Fax: (514) 849-4239



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: 
http://www.vtk.org/Wiki/VTK_FAQ

Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers



-- 
www.infolytica.com
300 Leo Pariseau, Suite 2222, Montreal, QC, Canada, H2X 4B3
(514) 849-8752 x236, Fax: (514) 849-4239


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: 
http://www.vtk.org/Wiki/VTK_FAQ

Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers




_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: 
http://www.vtk.org/Wiki/VTK_FAQ

Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers



-- 
www.infolytica.com
300 Leo Pariseau, Suite 2222, Montreal, QC, Canada, H2X 4B3
(514) 849-8752 x236, Fax: (514) 849-4239



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the VTK FAQ at: 
http://www.vtk.org/Wiki/VTK_FAQ

Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers 





More information about the vtkusers mailing list