Module voxelfuse_examples.primitive_generation.primitive_generation_matplotlib

Generate a series of primitive solids and display them using matplotlib


Copyright 2021 - Cole Brauer, Dan Aukes

Expand source code
"""
Generate a series of primitive solids and display them using matplotlib

----

Copyright 2021 - Cole Brauer, Dan Aukes
"""

import time
import numpy as np
import matplotlib.pyplot as plt
import voxelfuse as vf

def set_axes_equal(ax):
    '''
    Make axes of 3D plot have equal scale so that spheres appear as spheres,
    cubes as cubes, etc..  This is one possible solution to Matplotlib's
    ax.set_aspect('equal') and ax.axis('equal') not working for 3D.

    Input
      ax: a matplotlib axis, e.g., as output from plt.gca().
    '''

    x_limits = ax.get_xlim3d()
    y_limits = ax.get_ylim3d()
    z_limits = ax.get_zlim3d()

    x_range = abs(x_limits[1] - x_limits[0])
    x_middle = np.mean(x_limits)
    y_range = abs(y_limits[1] - y_limits[0])
    y_middle = np.mean(y_limits)
    z_range = abs(z_limits[1] - z_limits[0])
    z_middle = np.mean(z_limits)

    # The plot bounding box is a sphere in the sense of the infinity
    # norm, hence I call half the max range the plot radius.
    plot_radius = 0.5*max([x_range, y_range, z_range])

    ax.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius])
    ax.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius])
    ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])

if __name__=='__main__':
    # Save start time
    t1 = time.time()

    model1 = vf.cube(11, (0, 0, 0), 1)
    model2 = vf.cuboid((11, 20, 6), (13, 0, 0), 2)
    model3 = vf.sphere(5, (31, 5, 5), 3)
    model4 = vf.cylinder(5, 15, (44, 5, 0), 4)
    model5 = vf.cone(1, 5, 15, (57, 5, 0), 5)
    model6 = vf.pyramid(0, 5, 15, (70, 5, 0), 6)

    model_result = model1 | model2 | model3 | model4 | model5 | model6

    # Find exterior voxels
    interiorVoxels = model_result.erode(radius=1, connectivity=1)
    exteriorVoxels = model_result.difference(interiorVoxels)
    voxels = exteriorVoxels.voxels

    # Get colors
    colors = np.empty(voxels.shape, dtype=object)
    colors[:] = 'white'
    colors[voxels == 1] = 'red'
    colors[voxels == 2] = 'green'
    colors[voxels == 3] = 'blue'
    colors[voxels == 4] = 'gray'
    colors[voxels == 5] = 'black'
    colors[voxels == 6] = 'cyan'

    # Plot
    fig = plt.figure()
    ax3d = fig.add_subplot(projection='3d')
    ax3d.voxels(voxels, facecolors=colors)
    set_axes_equal(ax3d)
    plt.show()

    # Get elapsed time
    t2 = time.time()
    time_matplotlib = t2 - t1
    print('Time to generate plot: ' + str(time_matplotlib) + ' sec')

Functions

def set_axes_equal(ax)

Make axes of 3D plot have equal scale so that spheres appear as spheres, cubes as cubes, etc.. This is one possible solution to Matplotlib's ax.set_aspect('equal') and ax.axis('equal') not working for 3D.

Input ax: a matplotlib axis, e.g., as output from plt.gca().

Expand source code
def set_axes_equal(ax):
    '''
    Make axes of 3D plot have equal scale so that spheres appear as spheres,
    cubes as cubes, etc..  This is one possible solution to Matplotlib's
    ax.set_aspect('equal') and ax.axis('equal') not working for 3D.

    Input
      ax: a matplotlib axis, e.g., as output from plt.gca().
    '''

    x_limits = ax.get_xlim3d()
    y_limits = ax.get_ylim3d()
    z_limits = ax.get_zlim3d()

    x_range = abs(x_limits[1] - x_limits[0])
    x_middle = np.mean(x_limits)
    y_range = abs(y_limits[1] - y_limits[0])
    y_middle = np.mean(y_limits)
    z_range = abs(z_limits[1] - z_limits[0])
    z_middle = np.mean(z_limits)

    # The plot bounding box is a sphere in the sense of the infinity
    # norm, hence I call half the max range the plot radius.
    plot_radius = 0.5*max([x_range, y_range, z_range])

    ax.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius])
    ax.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius])
    ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])