web-dev-qa-db-de.com

python 3D-Würfel zeichnen

Ich versuche, ein Parallelepiped zu zeichnen. Eigentlich habe ich mit dem Python-Skript angefangen, einen Würfel zu zeichnen:

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

points = np.array([[-1, -1, -1],
                  [1, -1, -1 ],
                  [1, 1, -1],
                  [-1, 1, -1],
                  [-1, -1, 1],
                  [1, -1, 1 ],
                  [1, 1, 1],
                  [-1, 1, 1]])


fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

r = [-1,1]

X, Y = np.meshgrid(r, r)

ax.plot_surface(X,Y,1, alpha=0.5)
ax.plot_surface(X,Y,-1, alpha=0.5)
ax.plot_surface(X,-1,Y, alpha=0.5)
ax.plot_surface(X,1,Y, alpha=0.5)
ax.plot_surface(1,X,Y, alpha=0.5)
ax.plot_surface(-1,X,Y, alpha=0.5)

ax.scatter3D(points[:, 0], points[:, 1], points[:, 2])

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

Um ein Parallelepiped zu erhalten, habe ich die Punktematrix mit der folgenden Matrix multipliziert:

P = 

[[2.06498904e-01  -6.30755443e-07   1.07477548e-03]

 [1.61535574e-06   1.18897198e-01   7.85307721e-06]

 [7.08353661e-02   4.48415767e-06   2.05395893e-01]]

wie:

Z = np.zeros((8,3))

for i in range(8):

   Z[i,:] = np.dot(points[i,:],P)

Z = 10.0*Z

Meine Idee ist dann wie folgt zu repräsentieren:

ax.scatter3D(Z[:, 0], Z[:, 1], Z[:, 2])

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

Und das bekomme ich:

 enter image description here

Wie kann ich dann an diesen verschiedenen Punkten Flächen anbringen, um das Parallelepiped zu bilden (im Würfel oben)

8
rogwar

Flächen mit 3D PolyCollection plotten ( example )

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
import matplotlib.pyplot as plt

points = np.array([[-1, -1, -1],
                  [1, -1, -1 ],
                  [1, 1, -1],
                  [-1, 1, -1],
                  [-1, -1, 1],
                  [1, -1, 1 ],
                  [1, 1, 1],
                  [-1, 1, 1]])

P = [[2.06498904e-01 , -6.30755443e-07 ,  1.07477548e-03],
 [1.61535574e-06 ,  1.18897198e-01 ,  7.85307721e-06],
 [7.08353661e-02 ,  4.48415767e-06 ,  2.05395893e-01]]

Z = np.zeros((8,3))
for i in range(8): Z[i,:] = np.dot(points[i,:],P)
Z = 10.0*Z

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

r = [-1,1]

X, Y = np.meshgrid(r, r)
# plot vertices
ax.scatter3D(Z[:, 0], Z[:, 1], Z[:, 2])

# list of sides' polygons of figure
verts = [[Z[0],Z[1],Z[2],Z[3]],
 [Z[4],Z[5],Z[6],Z[7]], 
 [Z[0],Z[1],Z[5],Z[4]], 
 [Z[2],Z[3],Z[7],Z[6]], 
 [Z[1],Z[2],Z[6],Z[5]],
 [Z[4],Z[7],Z[3],Z[0]]]

# plot sides
ax.add_collection3d(Poly3DCollection(verts, 
 facecolors='cyan', linewidths=1, edgecolors='r', alpha=.25))

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

 enter image description here

7
pcu

Da der Titel dieser Frage "Python-Draw-3D-Würfel" lautet, habe ich diesen Artikel gefunden, als ich diese Frage googelte.

Für den Zweck derer, die dasselbe tun wie ich, die einfach einen Würfel zeichnen wollen, habe ich die folgende Funktion erstellt, die vier Punkte eines Würfels, eine Ecke zuerst und dann die drei benachbarten Punkte zu dieser Ecke nimmt.

Dann zeichnet er den Würfel.

Die Funktion ist unten:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

def plot_cube(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)

    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)

    # Plot the points themselves to force the scaling of the axes
    ax.scatter(points[:,0], points[:,1], points[:,2], s=0)

    ax.set_aspect('equal')


cube_definition = [
    (0,0,0), (0,1,0), (1,0,0), (0,0,1)
]
plot_cube(cube_definition)

Das Ergebnis geben:

 enter image description here

4
MeshachBlue

Fertig mit Matplotlib und Koordinatengeometrie 

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np


def cube_coordinates(Edge_len,step_size):
    X = np.arange(0,Edge_len+step_size,step_size)
    Y = np.arange(0,Edge_len+step_size,step_size)
    Z = np.arange(0,Edge_len+step_size,step_size)
    temp=list()
    for i in range(len(X)):
        temp.append((X[i],0,0))
        temp.append((0,Y[i],0))
        temp.append((0,0,Z[i]))
        temp.append((X[i],Edge_len,0))
        temp.append((Edge_len,Y[i],0))
        temp.append((0,Edge_len,Z[i]))
        temp.append((X[i],Edge_len,Edge_len))
        temp.append((Edge_len,Y[i],Edge_len))
        temp.append((Edge_len,Edge_len,Z[i]))
        temp.append((Edge_len,0,Z[i]))
        temp.append((X[i],0,Edge_len))
        temp.append((0,Y[i],Edge_len))
    return temp


Edge_len = 10


A=cube_coordinates(Edge_len,0.01)
A=list(set(A))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
A=Zip(*A)
X,Y,Z=list(A[0]),list(A[1]),list(A[2])
ax.scatter(X,Y,Z,c='g')

plt.show()
0
Preetham Dasari

In meiner anderen Antwort ( https://stackoverflow.com/a/49766400/3912576 ) finden Sie eine einfachere Lösung.

Hier ist ein komplizierter Satz von Funktionen, die die Matplotlib-Skala verbessern und die Eingabe immer zu einem Würfel machen.

Der erste an cubify_cube_definition übergebene Parameter ist der Startpunkt, der zweite Parameter ist der zweite Punkt, die Würfellänge wird von diesem Punkt aus definiert, der dritte ist ein Rotationspunkt. Er wird so verschoben, dass er der Länge des ersten und des zweiten entspricht.

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)

Was zu folgendem Ergebnis führt:

 enter image description here

0
MeshachBlue