Simples Koordinatensystem in Python?
Hi,
ich bin gerade dabei ein Python Programm zu erstellen, mit welchem man Beziérkurven erstellen kann. Ich habe alle Koordinaten von allen Punkten als Variablen abrufbereit und würde jetzt nur gerne wissen, wie ich Punkte mit diesen Koordinaten erstelle, Linien zwischen bestimmten Punkten ziehe, etc.
Ich habe es mit matplotlib.pyplot versucht, aber es ist nichts brauchbares herausgekommen. Weiß irgendjemand, wie ich sonst ein Koordinatensystem erstelle, was sich möglichst auch aktualisieren kann, damit ich es live nach Belieben verändern kann?
Vielleicht könnte man ein Koordinatensystem mit tkinter machen, aber ich kenne mich mit GUIs in Python leider nicht aus.
Vielen Dank im Vorraus!
1 Antwort
Ich kann hier einfach mal eine ähnliche Application reinstellen, die wir in dre Uni programmiert hatten. Kann Fehler enthalten und trifft auch nicht ganz das, was du tun möchtest, aber sollte wohl hilfreich sein:
#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
def de_casteljau_step(P, t):
"""For a given control polygon P of length n, return a control polygon of
length n-1 by performing a single de Casteljau step with the given
floating point number t."""
assert len(P) > 1, 0 <= t <= 1
oneMinusT = 1-t;
ret = np.zeros((np.size(P,0)-1, 2));
for i in range(np.size(P, 0)-1):
ret[i][0] = oneMinusT*P[i][0] + t*P[i+1][0];
ret[i][1] = oneMinusT*P[i][1] + t*P[i+1][1];
return ret;
def de_casteljau(P, t):
"""Evaluate the Bezier curve specified by the control polygon P at a single
point corresponding to the given t in [0,1]. Returns a one-dimensional
NumPy array contining the x and y coordinate of the Point,
respectively."""
assert len(P) != 0
while np.size(P, 0) > 1:
P = de_casteljau_step(P, t);
return P[0];
def bezier1(P, m):
"""Return a polygon with m points that approximates the Bezier curve
specified by the control polygon P."""
assert len(P) > 1, m > 1
ret = np.zeros((m, 2));
for i in range(m):
ret[i] = de_casteljau(P, 0+i/(m-1));
return ret;
def add_control_point(P):
"""For the given Bezier curve control polygon P of length n, return a new
control polygon with n+1 points that describes the same curve."""
assert len(P) > 1
n = np.size(P, 0);
ret = np.zeros((n+1, 2));
ret[0][0] = P[0][0];
ret[0][1] = P[0][1];
ret[n][0] = P[n-1][0];
ret[n][1] = P[n-1][1];
for i in range(1, n):
a = i/n;
ret[i][0] = a*P[i-1][0] + (1-a)*P[i][0];
ret[i][1] = a*P[i-1][1] + (1-a)*P[i][1];
return ret;
def split_curve(P):
"""Split a Bezier curve, specified by a control polynomial P. Return a
tuple (L, R), where L and R are control polygons with the same
length as P, that describe the left and the right half of the original
curve, respectively."""
n = np.size(P, 0);
L = np.zeros((n, 2));
R = np.zeros((n, 2));
lastIndex = n-1;
for i in range(n-1):
L[i] = P[0];
R[n-i-1] = P[lastIndex];
P = de_casteljau_step(P, 1/2);
lastIndex -= 1;
L[n-1] = P[0];
R[0] = P[0];
return (L, R);
def bezier2(P, depth):
"""Return a polygon that approximates the Bezier curve specified by the
control polygon P by depth recursive subdivisions."""
if(depth == 0):
return P
else:
splitted = split_curve(P);
L = bezier2(splitted[0], depth-1);
R = bezier2(splitted[1], depth-1);
ret = np.zeros((2*np.size(L, 0)-1, 2));
for i in range(np.size(L, 0)):
ret[i] = L[i];
for j in range(1,np.size(R, 0)):
ret[np.size(L, 0)+j-1] = R[j];
return ret;
def de_casteljau_plot(P):
"""Draw all polygons in the de Casteljau pyramid of P for varying t."""
n = len(P)
t = 0.3
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
lines = ax.plot(P[:,0], P[:,1], 'o-')
Q = P.copy()
for i in range(n-1):
Q = de_casteljau_step(Q,t)
[line] = ax.plot(Q[:,0], Q[:,1], 'o-')
lines.append(line)
plt.grid(True)
def redraw(t):
Q = P.copy()
for i in range(n-1):
Q = de_casteljau_step(Q,t)
lines[i+1].set_xdata(Q[:,0])
lines[i+1].set_ydata(Q[:,1])
fig.subplots_adjust(left=0.25, bottom=0.25)
fig.canvas.draw_idle()
t_slider_ax = fig.add_axes([0.25, 0.1, 0.5, 0.03])
t_slider = Slider(t_slider_ax, 't', 0., 1., valinit=t)
t_slider.on_changed(redraw)
plt.show()
def bezier_plot(P):
"""Draw different bezier curve approximations for the given P."""
n = len(P)
depth = 1
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
B2 = bezier2(P.copy(), depth)
B1 = bezier1(P.copy(), len(B2))
[line0] = ax.plot( P[:,0], P[:,1], 'o-', label="P")
[line1] = ax.plot(B1[:,0], B1[:,1], 'o-', label="bezier1")
[line2] = ax.plot(B2[:,0], B2[:,1], 'o-', label="bezier2")
plt.legend(shadow=True)
plt.grid(True)
def redraw(depth):
depth = int(depth)
B2 = bezier2(P.copy(), depth)
line2.set_xdata(B2[:,0])
line2.set_ydata(B2[:,1])
B1 = bezier1(P.copy(), len(B2))
line1.set_xdata(B1[:,0])
line1.set_ydata(B1[:,1])
fig.subplots_adjust(left=0.25, bottom=0.25)
fig.canvas.draw_idle()
depth_slider_ax = fig.add_axes([0.25, 0.1, 0.5, 0.03])
depth_slider = Slider(depth_slider_ax, 'depth', 0, 7, valinit=depth)
depth_slider.on_changed(redraw)
plt.show()
def main():
P = np.array([[3., 2.], [2., 5.], [7., 6.], [8., 1.]])
#bezier2(P, 2);
de_casteljau_plot(P)
if __name__ == "__main__": main()