Search code examples
python3dpolygonvtkpyvista

How to extrude an irregular polygon?


I have a set of 2D vertex coordinates in the plane (assume xy-plane) and I would like to extrude this in the z-direction to form a PolyData object that I can transform and render.

The ideal function would take an nx2 ndarray of vertices and a height and return a PolyData.

A fallback solution would be to do this in VTK and wrap the result as a PyVista object.


Solution

  • The straightforward solution of embedding your 2d vertices in 3d to create an actual polygon and extruding that works fine:

    import numpy as np
    import pyvista as pv
    
    rng = np.random.default_rng()
    
    # create dummy data
    N = 10
    angles = np.linspace(0, 2*np.pi, N, endpoint=False)
    radii = rng.uniform(0.5, 1.5, N)
    coords = np.array([np.cos(angles), np.sin(angles)]) * radii
    points_2d = coords.T  # shape (N, 2)
    
    # embed in 3d, create polygon
    points_3d = np.pad(points_2d, [(0, 0), (0, 1)])  # shape (N, 3)
    polygon = pv.lines_from_points(points_3d, close=True)
    
    # extrude along z and plot
    body = polygon.extrude((0, 0, 0.5))
    body.plot(color='white', specular=1, screenshot='extruded.png')
    

    successfully extruded surface: wall with a base shaped like a random polygon

    If you need a closed surface after extrusion you have to start with a solid polygon (i.e. a face rather than a line) and pass capping=True to extrude() (starting from PyVista version 0.32.0):

    # embed in 3d, create filled polygon
    points_3d = np.pad(points_2d, [(0, 0), (0, 1)])  # shape (N, 3)
    face = [N + 1] + list(range(N)) + [0]  # cell connectivity for a single cell
    polygon = pv.PolyData(points_3d, faces=face)
    
    # extrude along z and plot
    body = polygon.extrude((0, 0, 0.5), capping=True)
    body.plot(color='white', specular=1, screenshot='extruded.png')
    

    similar to before, but the surface is capped