python draw parallelepiped

后端 未结 4 684
庸人自扰
庸人自扰 2021-02-08 05:25

I am trying to draw a parallelepiped. Actually I started from the python script drawing a cube as:

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
imp         


        
4条回答
  •  无人及你
    2021-02-08 06:00

    See my other answer (https://stackoverflow.com/a/49766400/3912576) for a simpler solution.

    Here is a more complicated set of functions which make matplotlib scale better and always forces the input to be a cube.

    The first parameter passed to cubify_cube_definition is the starting point, the second parameter is the second point, cube length is defined from this point, the third is a rotation point, it will be moved to match the length of the first and second.

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
    
    def cubify_cube_definition(cube_definition):
        cube_definition_array = [
            np.array(list(item))
            for item in cube_definition
        ]
        start = cube_definition_array[0]
        length_decider_vector = cube_definition_array[1] - cube_definition_array[0]   
        length = np.linalg.norm(length_decider_vector)
    
        rotation_decider_vector = (cube_definition_array[2] - cube_definition_array[0])
        rotation_decider_vector = rotation_decider_vector / np.linalg.norm(rotation_decider_vector) * length
    
        orthogonal_vector = np.cross(length_decider_vector, rotation_decider_vector)
        orthogonal_vector = orthogonal_vector / np.linalg.norm(orthogonal_vector) * length
    
        orthogonal_length_decider_vector = np.cross(rotation_decider_vector, orthogonal_vector)
        orthogonal_length_decider_vector = (
            orthogonal_length_decider_vector / np.linalg.norm(orthogonal_length_decider_vector) * length)
    
        final_points = [
            tuple(start),
            tuple(start + orthogonal_length_decider_vector),
            tuple(start + rotation_decider_vector),
            tuple(start + orthogonal_vector)        
        ]
    
        return final_points
    
    
    def cube_vertices(cube_definition):
        cube_definition_array = [
            np.array(list(item))
            for item in cube_definition
        ]
    
        points = []
        points += cube_definition_array
        vectors = [
            cube_definition_array[1] - cube_definition_array[0],
            cube_definition_array[2] - cube_definition_array[0],
            cube_definition_array[3] - cube_definition_array[0]
        ]
    
        points += [cube_definition_array[0] + vectors[0] + vectors[1]]
        points += [cube_definition_array[0] + vectors[0] + vectors[2]]
        points += [cube_definition_array[0] + vectors[1] + vectors[2]]
        points += [cube_definition_array[0] + vectors[0] + vectors[1] + vectors[2]]
    
        points = np.array(points)
    
        return points
    
    
    def get_bounding_box(points): 
        x_min = np.min(points[:,0])
        x_max = np.max(points[:,0])
        y_min = np.min(points[:,1])
        y_max = np.max(points[:,1])
        z_min = np.min(points[:,2])
        z_max = np.max(points[:,2])
    
        max_range = np.array(
            [x_max-x_min, y_max-y_min, z_max-z_min]).max() / 2.0
    
        mid_x = (x_max+x_min) * 0.5
        mid_y = (y_max+y_min) * 0.5
        mid_z = (z_max+z_min) * 0.5
    
        return [
            [mid_x - max_range, mid_x + max_range],
            [mid_y - max_range, mid_y + max_range],
            [mid_z - max_range, mid_z + max_range]
        ]
    
    
    def plot_cube(cube_definition):
        points = cube_vertices(cube_definition)
    
        edges = [
            [points[0], points[3], points[5], points[1]],
            [points[1], points[5], points[7], points[4]],
            [points[4], points[2], points[6], points[7]],
            [points[2], points[6], points[3], points[0]],
            [points[0], points[2], points[4], points[1]],
            [points[3], points[6], points[7], points[5]]
        ]
    
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
    
        faces = Poly3DCollection(edges, linewidths=1, edgecolors='k')
        faces.set_facecolor((0,0,1,0.1))
    
        ax.add_collection3d(faces)
    
        bounding_box = get_bounding_box(points)
    
        ax.set_xlim(bounding_box[0])
        ax.set_ylim(bounding_box[1])
        ax.set_zlim(bounding_box[2])
    
        ax.set_xlabel('x')
        ax.set_ylabel('y')
        ax.set_zlabel('z')
        ax.set_aspect('equal')
    
    
    cube_definition = cubify_cube_definition([(0,0,0), (0,3,0), (1,1,0.3)])
    plot_cube(cube_definition)
    

    Which produces the following result:

提交回复
热议问题