[vtkusers] Scaling Glyphs by Camera but to a Limit

Stuart, Travis t.stuart at dautomation.com
Sun Dec 30 09:38:27 EST 2018


Hi,
I'm having trouble achieving a particular rendering behavior with VTK. I would like to render glyphs of my point cloud with a fixed screen size up until the camera is zoomed in close enough for the glyph to be its actual size. I want them to be scaled up but not down.

I can fake this behavior by rendering two sets on top of each other. One set not scaled and the other scaled by distance to camera. But this is not ideal for huge data sets and I'd like to learn the correct way to solve this with one set.

At first I thought the scale clamping functionality of the vtkGlyph3DMapper could do this but setting the range to clamp seems to just scale the 'DistanceToCamera' values to the range.

One idea I had was to create a programmable filter that takes the vtkDistanceToCamera as input and outputs the same object but with an additional array. The same 'DistanceToCamera' array but with capped values below a certain threshold. Like any value under 1 would be set to 1.

This is my failed attempt: It causes Python to immediately crash without error message.

cap_array_filter = vtk.vtkProgrammableFilter()
cap_array_filter.SetInputConnection(camera_dist_b.GetOutputPort())

def cap_array():
    d2c_array = cap_array_filter.GetPolyDataInput().GetPointData().GetArray('DistanceToCamera')

    new_array = vtk.vtkDoubleArray()
    new_array.SetName('DistanceToCameraCapped')

    for i in range(0, d2c_array.GetSize()):
        new_value = d2c_array.GetTuple1(i)
        if new_value < 1:
            new_value = 1

        new_array.InsertNextValue(new_value)

    cap_array_filter.GetPointData().AddArray(new_array)


cap_array_filter.SetExecuteMethod(cap_array)
camera_dist_b.SetInputConnection(cap_array_filter.GetOutputPort())

mapper_b = vtk.vtkGlyph3DMapper()
mapper_b.SetInputData(self.nominal_poly_data)
mapper_b.SetSourceConnection(sphere.GetOutputPort())

mapper_b.SetInputConnection(camera_dist_b.GetOutputPort())
mapper_b.SetInputArrayToProcess(0, 0, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS, 'DistanceToCameraCapped')


I also tried creating a VTKPythonAlgorithm to pass in a vtkDistanceToCamera and add the capped array. But I can't get the instance to initialize without errors so not much progress there.

class DistanceToCameraCapper(VTKPythonAlgorithmBase):
    def __init__(self):
        VTKPythonAlgorithmBase.__init__(self,
        nInputPorts=1, inputType= vtkDistanceToCamera,
        nOutputPorts=1, outputType= vtkDistanceToCamera)

    def RequestData(self, request, inInfo, outInfo):
        print('Executing')
        input = vtk.vtkDistanceToCamera.GetData(inInfo[0])
        output = vtk.vtkDistanceToCamera.GetData(outInfo)

        d2c = vtk.vtkDistanceToCamera()
        d2c.SetInputData(input)
        d2c.Update()
        output.ShallowCopy(d2c.GetOutput())

        return 1

I'd be grateful for any ideas or hints on how to accomplish this idea.

I've attached a demonstration. The red spheres are not scaled. The green spheres are scaled by distance to camera. The purple spheres show the visual behavior that I want. It's using the "fake" method of rendering two sets of spheres on top of each other. One set scaled and the other not.

Thanks,
Travis Stuart
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://vtk.org/pipermail/vtkusers/attachments/20181230/3afd0067/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: d2c limit example.py
Type: application/octet-stream
Size: 2844 bytes
Desc: d2c limit example.py
URL: <https://vtk.org/pipermail/vtkusers/attachments/20181230/3afd0067/attachment.obj>


More information about the vtkusers mailing list