Enable parallel projection without resetting the camera

To: @dgobbi

Dear Gobbi,

The equation you provided is producing different results than VTK. I found another equation in the VTK code that solved the problem:

ParallelScale = Distance * sin(0.5*ViewAngle)

Thank you very much for your help!

To: @lassoan

Dear Lasso,

I solved the problem by setting the position and the parallel projection scale of the active camera.

@dgobbi is right! There is a geometric relationship between parallel and perspective projections. I used this relationship to enable/disable the parallel projection of a same camera without producing the “reset camera” effect.

You’re right! It’s not a bug. However, I see this problem as an unwanted effect that could be solved within the VTK.

Thank you for your help!

Solution

parallel_projection_bug_solved.py
import vtk
import math

def keyboard_callback(caller, event):
    if caller.GetKeyCode() == 'p':
        camera = renderer.GetActiveCamera()
        angle = camera.GetViewAngle()
        angle = math.radians(angle)
        if camera.GetParallelProjection():
            point = camera.GetFocalPoint()
            direction = camera.GetDirectionOfProjection()
            scale = camera.GetParallelScale()
            distance = scale / math.sin(.5 * angle)
            x = point[0] - distance * direction[0]
            y = point[1] - distance * direction[1]
            z = point[2] - distance * direction[2]
            camera.SetPosition(x, y, z)
            camera.ParallelProjectionOff()
            renderer.ResetCameraClippingRange()
        else:
            distance = camera.GetDistance()
            scale = distance * math.sin(.5 * angle)
            camera.SetParallelScale(scale)
            camera.ParallelProjectionOn()
        window.Render()

source = vtk.vtkSphereSource()

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())

actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().EdgeVisibilityOn()

renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
renderer.SetBackground(.3, .3, .3)
renderer.GetActiveCamera().ParallelProjectionOn()
renderer.ResetCamera()

window = vtk.vtkRenderWindow()
window.AddRenderer(renderer)
window.SetSize(800, 600)

interactor = vtk.vtkRenderWindowInteractor()
interactor.AddObserver('KeyPressEvent', keyboard_callback)
interactor.SetRenderWindow(window)
interactor.SetInteractorStyle(vtk.vtkInteractorStyleRubberBandPick())
interactor.Start()

Untitled

Untitled

1 Like