# How can I split a polyline into its linear segments?

A simple question that hopefully can be answered with a single link:

How to split a polyline into its `n` linear segments?

Let’s be given a polyline like the one that results from the PolyLine example. Is there a vtk filter producing a `vtkPolyData` object with `n` lines from this input? It’s sort of the inverse filter of `vtkStripper` that is able to join multiple line segments into a single polyline.

Thanks!

Here’s what I came up with, though I’m pretty convinced that there’re better approaches:

``````def polylineToMultiline(polyline):
# Assumption: points appear in the correct order: p0->p1->p2->p3...
points = polyline.GetPoints()
nPoints = points.GetNumberOfPoints()
cells = vtk.vtkCellArray()
for i in range(nPoints-1):
line = vtk.vtkLine()
line.GetPointIds().SetId(0,i)
line.GetPointIds().SetId(1,i+1)
cells.InsertNextCell(line)
poly = vtk.vtkPolyData()
poly.SetPoints(points)
poly.SetLines(cells)
return poly
``````

The above code assumes that the points from the polyline appear in the correct order. Note that this is not the case in general! To extract the points in the correct order, you would have to do something like the following:

``````def extractConsecutivePoints(poly):
# Travers the line(s) and add points while keeping their order.
cells = poly.GetLines()
cells.InitTraversal()
idList = vtk.vtkIdList()
points = vtk.vtkPoints()
while cells.GetNextCell(idList):
for i in range(0, idList.GetNumberOfIds()):
pId = idList.GetId(i)
points.InsertNextPoint(poly.GetPoint(pId))
return points``````

Here is a routine to do it with PyVista since you are using Python. This will work regardless of point ordering.

``````import pyvista as pv
import numpy as np

def segment_poly_cells(mesh):
"""`mesh` is a PyVista PolyData object
(wrapped vtkPolyData)
"""
if not pv.is_pyvista_dataset(mesh):
mesh = pv.wrap(mesh)
polylines = []
i, offset = 0, 0
cc = mesh.lines # fetch up front
while i < mesh.n_cells:
nn = cc[offset]
polylines.append(cc[offset+1:offset+1+nn])
offset += nn + 1
i += 1
#
lines = []
for poly in polylines:
lines.append(np.column_stack((poly[:-1], poly[1:])))
lines = np.vstack(lines)
cells = np.column_stack((np.full(len(lines), 2), lines))

segmented = pv.PolyData()
segmented.points = mesh.points
segmented.lines = cells
return segmented
``````

So if you have some `vtkPolyData` already, just do the folling and a new `vtkPolyData` mesh will be returned.

``````segmented = segment_poly_cells(polyline)
``````
1 Like

PyVista is nice, thanks!

What exactly does `mesh.lines` represent? A container of cells/points that belong to a line?

``mesh.lines = [n0, c00, c01, ..., n1, c10, c11, ... ]``

The `lines` property on `pyvista.PolyData` objects is just a NumPy wrapper around `vtk.vtkPolyData.GetLines().GetData()` and it is exactly what you have listed above. As a way to get all of the point IDs for each line in the mesh

``````[n0, c00, c01, ..., n1, c10, c11, ... ]
``````
1 Like

Here’s the best answer to this question. Just use a triangle filter:

``````def polylineToMultiline(source):
triangles = vtk.vtkTriangleFilter()
triangles.SetInputData(source)
triangles.Update()
return ensurePolyData(triangles)
``````

The documentation of vtkTriangleFilter states:

… [vtkTriangleFilter] also generates line segments from polylines unless PassLines is off, and generates individual vertex cells from vtkVertex point lists unless PassVerts is off.

The remaining question: vtkTriangleFilter to apply an operation on a polyline, what the hack?! It’s sometimes so difficult to find the right method in vtk.  1 Like

Huh! I didn’t realize that, good find!

``````import pyvista as pv