杰瑞科技汇

VTK polyline在Python中如何高效绘制与处理?

Of course! Using VTK to create and work with polylines in Python is a fundamental task. A vtkPolyline is a cell that represents a sequence of connected points. It's different from a vtkPolyLine (note the capital 'L') which is a specific data cell type, and it's different from a vtkPolyData object, which is a collection of points and cells (like polylines, triangles, etc.).

VTK polyline在Python中如何高效绘制与处理?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering the basics, from creating a simple polyline to visualizing it in an interactive window.

The Core Concept: Points and Cells

In VTK, geometry is separated from topology:

  • Points (vtkPoints): A list of 3D coordinates (x, y, z). This is the "what" (the vertices).
  • Cells (vtkCellArray): A list of connections between points. This is the "how" (the lines, triangles, etc., that use the points).

A vtkPolyline is a specific type of cell that tells VTK: "Connect these point IDs in order to form a line."


Creating a Simple Polyline

This is the most basic example. We'll create a polyline with three points and display it.

VTK polyline在Python中如何高效绘制与处理?-图2
(图片来源网络,侵删)
import vtk
# 1. Create the points for the polyline
points = vtk.vtkPoints()
points.InsertNextPoint(0, 0, 0)  # Point 0
points.InsertNextPoint(1, 0, 0)  # Point 1
points.InsertNextPoint(1, 1, 0)  # Point 2
# 2. Create a vtkPolyline object and define its structure
# A vtkPolyline is a cell, so we create it as a VTK cell.
polyline = vtk.vtkPolyline()
polyline.GetPointIds().SetNumberOfIds(3) # Set the number of points in the line
# Assign the point IDs to the polyline
polyline.GetPointIds().SetId(0, 0) # First point of the line is points[0]
polyline.GetPointIds().SetId(1, 1) # Second point of the line is points[1]
polyline.GetPointIds().SetId(2, 2) # Third point of the line is points[2]
# 3. Create a vtkCellArray to store the polyline
# A vtkPolyData can contain multiple cells (lines, triangles, etc.),
# so we use a cell array as a container.
lines = vtk.vtkCellArray()
lines.InsertNextCell(polyline) # Add our polyline to the cell array
# 4. Create a vtkPolyData object and add the points and lines to it
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
polydata.SetLines(lines)
# 5. Create a mapper and an actor to visualize the polyline
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(polydata)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# 6. Set up the renderer, render window, and interactor
renderer = vtk.vtkRenderer()
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window_interactor = vtk.vtkRenderWindowInteractor()
render_window_interactor.SetRenderWindow(render_window)
# Add the actor to the scene
renderer.AddActor(actor)
renderer.SetBackground(0.1, 0.2, 0.4) # Set a background color
# Start the visualization
render_window.Render()
render_window_interactor.Start()

When you run this, a window will appear showing a simple L-shaped line.


Creating Multiple Polylines

What if you want to draw several separate lines? You just create more vtkPolyline objects and add them all to the same vtkCellArray.

import vtk
# --- Points ---
points = vtk.vtkPoints()
points.InsertNextPoint(0, 0, 0)
points.InsertNextPoint(1, 0, 0)
points.InsertNextPoint(1, 1, 0)
points.InsertNextPoint(2, 1, 0)
points.InsertNextPoint(3, 0, 0)
points.InsertNextPoint(4, 0, 0)
points.InsertNextPoint(4, 1, 0)
# --- Cell Array ---
lines = vtk.vtkCellArray()
# --- First Polyline (3 points) ---
polyline1 = vtk.vtkPolyline()
polyline1.GetPointIds().SetNumberOfIds(3)
polyline1.GetPointIds().SetId(0, 0)
polyline1.GetPointIds().SetId(1, 1)
polyline1.GetPointIds().SetId(2, 2)
lines.InsertNextCell(polyline1)
# --- Second Polyline (2 points) ---
polyline2 = vtk.vtkPolyline()
polyline2.GetPointIds().SetNumberOfIds(2)
polyline2.GetPointIds().SetId(0, 3)
polyline2.GetPointIds().SetId(1, 4)
lines.InsertNextCell(polyline2)
# --- Third Polyline (2 points) ---
polyline3 = vtk.vtkPolyline()
polyline3.GetPointIds().SetNumberOfIds(2)
polyline3.GetPointIds().SetId(0, 4)
polyline3.GetPointIds().SetId(1, 5)
lines.InsertNextCell(polyline3)
# --- Assemble into PolyData ---
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
polydata.SetLines(lines)
# --- Visualization (same as before) ---
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(polydata)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
renderer = vtk.vtkRenderer()
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window_interactor = vtk.vtkRenderWindowInteractor()
render_window_interactor.SetRenderWindow(render_window)
renderer.AddActor(actor)
renderer.SetBackground(0.1, 0.2, 0.4)
render_window.Render()
render_window_interactor.Start()

This code will draw two separate line segments: one L-shape and one vertical line.


A More Pythonic Way: Using vtkPoints Directly

For simple polylines, you don't always need to explicitly create vtkPolyline objects. You can often pass a list of point IDs directly to vtkCellArray. This is a bit cleaner.

VTK polyline在Python中如何高效绘制与处理?-图3
(图片来源网络,侵删)
import vtk
import numpy as np
# 1. Create points using a NumPy array (often more convenient)
points_np = np.array([
    [0, 0, 0],
    [2, 0, 0],
    [2, 2, 0],
    [0, 2, 0],
    [1, 1, 2] # A point in the middle for a second line
])
points = vtk.vtkPoints()
points.SetData(np.vtk_array_from_numpy(points_np)) # Helper function needed
# 2. Create the cell array and add polylines by specifying point IDs
lines = vtk.vtkCellArray()
# First polyline: a square (4 points)
# We create a list of point IDs [0, 1, 2, 3]
square_ids = [0, 1, 2, 3]
lines.InsertNextCell(len(square_ids))
for i, id in enumerate(square_ids):
    lines.InsertCellPoint(id)
# Second polyline: a line from the square to the middle point
# We create a list of point IDs [3, 4]
line_ids = [3, 4]
lines.InsertNextCell(len(line_ids))
for i, id in enumerate(line_ids):
    lines.InsertCellPoint(id)
# 3. Assemble into PolyData
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
polydata.SetLines(lines)
# 4. Visualize
# ... (visualization code is the same as before)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(polydata)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
renderer = vtk.vtkRenderer()
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window_interactor = vtk.vtkRenderWindowInteractor()
render_window_interactor.SetRenderWindow(render_window)
renderer.AddActor(actor)
renderer.SetBackground(0.1, 0.2, 0.4)
renderer.ResetCamera() # Fit all actors in the view
render_window.Render()
render_window_interactor.Start()

Note: The np.vtk_array_from_numpy function is not standard. You can create it like this:

def np_vtk_array_from_numpy(np_array):
    # Handle different data types
    vtk_array = vtk.vtkDataArray.CreateDataArray(np_array.dtype)
    vtk_array.SetVoidArray(np_array, np.size(np_array), 1)
    return vtk_array

Or, more simply, just use points.InsertNextPoint(x, y, z) in a loop if you don't want to use NumPy.


Adding Data to the Polyline (Scalars)

A very powerful feature of VTK is associating data (like temperature, pressure, or just an index) with the points or cells of your geometry. This is essential for coloring your lines.

Here, we'll color the polyline based on a scalar value at each point.

import vtk
# 1. Create points and the polyline (same as the first example)
points = vtk.vtkPoints()
points.InsertNextPoint(0, 0, 0)
points.InsertNextPoint(1, 0, 0)
points.InsertNextPoint(1, 1, 0)
lines = vtk.vtkCellArray()
polyline = vtk.vtkPolyline()
polyline.GetPointIds().SetNumberOfIds(3)
polyline.GetPointIds().SetId(0, 0)
polyline.GetPointIds().SetId(1, 1)
polyline.GetPointIds().SetId(2, 2)
lines.InsertNextCell(polyline)
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
polydata.SetLines(lines)
# 2. Create scalar data for the points
# This will be an array of values, one for each point
scalars = vtk.vtkFloatArray()
scalars.SetName("PointValues") # Give the data a name
# Add a scalar value for each point
scalars.InsertNextValue(0.0) # Value for point 0
scalars.InsertNextValue(5.0) # Value for point 1
scalars.InsertNextValue(10.0) # Value for point 2
# 3. Add the scalar data to the polydata
polydata.GetPointData().SetScalars(scalars)
# 4. Create a mapper that uses the scalar data for coloring
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(polydata)
mapper.SetScalarRange(0.0, 10.0) # Set the range of scalar values to map to colors
# 5. Create actor and visualize
actor = vtk.vtkActor()
actor.SetMapper(mapper)
renderer = vtk.vtkRenderer()
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window_interactor = vtk.vtkRenderWindowInteractor()
render_window_interactor.SetRenderWindow(render_window)
renderer.AddActor(actor)
renderer.SetBackground(0.2, 0.3, 0.4)
# Add a scalar bar to see the color mapping
scalar_bar = vtk.vtkScalarBarActor()
scalar_bar.SetLookupTable(mapper.GetLookupTable())
scalar_bar.SetTitle("Point Value")
scalar_bar.SetNumberOfLabels(5)
renderer.AddActor2D(scalar_bar)
render_window.Render()
render_window_interactor.Start()

Now, the line will be colored, with the first segment (from 0 to 5) one color and the second segment (from 5 to 10) another. The scalar bar helps interpret the colors.

分享:
扫描分享到社交APP
上一篇
下一篇