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
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: