Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
kurse:efcomputergrafik:kw3 [2020/01/08 15:49] Ivo Blöchliger [Variante mit variablen Interallen $[0,a_i]$ anstatt [0,1]] |
kurse:efcomputergrafik:kw3 [2020/03/04 09:21] (current) Ivo Blöchliger [Lineare Abschnitte mit bekannter Steigung] |
||
---|---|---|---|
Line 30: | Line 30: | ||
| $h_{1,0}$ | $-2t^3+3t^2$ | $t^2(3-2t)$ | $-12t+6$ | 6 | -6 | | | $h_{1,0}$ | $-2t^3+3t^2$ | $t^2(3-2t)$ | $-12t+6$ | 6 | -6 | | ||
| $h_{0,1}$ | $t^3-2t^2+t$ | $t(1-t)^2$ | $6t-4$ | -4 | 2 | | | $h_{0,1}$ | $t^3-2t^2+t$ | $t(1-t)^2$ | $6t-4$ | -4 | 2 | | ||
- | | $h_{1,1}$ | $t^3-t^2$ | $t^2(1-t)$ | $6t-2$ | -2 | 4 | | + | | $h_{1,1}$ | $t^3-t^2$ | $t^2(t-1)$ | $6t-2$ | -2 | 4 | |
Für allgemeine Funktionen ergibt sich die zweite Ableitung für $t=0$ und $t=1$: | Für allgemeine Funktionen ergibt sich die zweite Ableitung für $t=0$ und $t=1$: | ||
Line 92: | Line 92: | ||
\end{pmatrix} | \end{pmatrix} | ||
\] | \] | ||
+ | |||
+ | ====== Lineare Abschnitte mit bekannter Steigung ====== | ||
+ | Es ist wünschenswert, | ||
+ | |||
+ | \[ | ||
+ | \left(0 \ldots 0 \quad 1 \quad 0\ldots 0\right) \cdot \vec m = (0 \ldots 0 \quad -1 \quad 1 \quad 0 \ldots 0) \cdot \vec x | ||
+ | \] | ||
+ | mit $M_{i,i} = 1$ und $X_{i, | ||
+ | |||
In Python (hier Blender Code) sieht das dann z.B. wie folgt aus: | In Python (hier Blender Code) sieht das dann z.B. wie folgt aus: | ||
Line 97: | Line 106: | ||
import bpy | import bpy | ||
import numpy as np | import numpy as np | ||
+ | from mathutils import Vector | ||
+ | |||
+ | # Pfad heisst StartPath, gegebenenfalls anpassen oder auf aktive Auswahl anwenden | ||
+ | obj = bpy.data.objects[' | ||
+ | |||
+ | # Array für Kurvenpunkte | ||
+ | mypoints=[] | ||
+ | |||
+ | if obj.type == ' | ||
+ | for subcurve in obj.data.splines: | ||
+ | curvetype = subcurve.type | ||
+ | if curvetype == ' | ||
+ | for p in subcurve.points: | ||
+ | mypoints.append(p.co) | ||
+ | |||
+ | print(" | ||
+ | print(mypoints) | ||
+ | |||
+ | n=len(mypoints) | ||
+ | # Matrizen M*m = X*x | ||
- | n=5 | ||
M = np.zeros((n, | M = np.zeros((n, | ||
X = np.zeros((n, | X = np.zeros((n, | ||
- | x = np.array([0,4,1,3,1]) | + | x = np.zeros((n,3)) |
+ | #Matrizen zeilenweise befüllen | ||
for i in range(n): | for i in range(n): | ||
M[i][i] = 1 | M[i][i] = 1 | ||
M[i][(i+1)%n] = 4 | M[i][(i+1)%n] = 4 | ||
M[i][(i+2)%n] = 1 | M[i][(i+2)%n] = 1 | ||
- | X[i][i] = -3 | + | # etc. |
- | X[i][(i+2)%n] = 3 | + | |
| | ||
- | print(M) | + | |
- | print(X) | + | #print(M) |
- | print(x) | + | #print(X) |
- | x = np.dot(X, | + | m = np.linalg.solve(M,np.dot(X,x)) |
- | print(x) | + | |
- | m = np.linalg.solve(M, | + | |
print(m) | print(m) | ||
+ | print(x) | ||
+ | print(mypoints) | ||
+ | |||
+ | korrektur = 1.0 # | ||
+ | |||
+ | handle_right = m/ | ||
+ | handle_left = x-m/ | ||
+ | |||
+ | print(Vector(x[0])) | ||
+ | |||
+ | curvedata = bpy.data.curves.new(name=" | ||
+ | curvedata.dimensions = ' | ||
+ | |||
+ | objectdata = bpy.data.objects.new(" | ||
+ | objectdata.location = (0,0,0) | ||
+ | objectdata.data.bevel_depth = 0.03 | ||
+ | |||
+ | bpy.context.scene.collection.objects.link(objectdata) | ||
+ | # | ||
+ | # railsCol.objects.link(objectdata) | ||
+ | |||
+ | polyline = curvedata.splines.new(' | ||
+ | polyline.bezier_points.add(n-1) | ||
+ | polyline.use_cyclic_u = True | ||
+ | |||
+ | for i in range(n): | ||
+ | point = polyline.bezier_points[i] | ||
+ | point.co = Vector(x[i]) | ||
+ | point.handle_left = Vector(handle_left[i]) | ||
+ | point.handle_right = Vector(handle_right[i]) | ||
+ | # point.handle_left = Vector(x[i]) | ||
+ | # point.handle_right = Vector(x[i]) | ||
+ | point.handle_left_type = ' | ||
+ | point.handle_right_type = ' | ||
+ | |||
+ | |||
</ | </ | ||
Line 203: | Line 265: | ||
Zusammenfassen: | Zusammenfassen: | ||
$$ | $$ | ||
- | \frac{2}{a_i}m_i +m_{i+1} \cdot \left(\frac{4}{a_i}+\frac{4}{a_{i+1}} +\frac{2}{a_{i+1}}\cdot m_{i+2} = | + | \frac{2}{a_i}m_i +m_{i+1} \cdot \left(\frac{4}{a_i}+\frac{4}{a_{i+1}}\right) |
\frac{1}{a_{i+1}^2}(-6x_{i+1}+6x_{i+2}) - \frac{1}{a_i^2}(6x_i-6x_{i+1}) | \frac{1}{a_{i+1}^2}(-6x_{i+1}+6x_{i+2}) - \frac{1}{a_i^2}(6x_i-6x_{i+1}) | ||
$$ | $$ | ||
+ | |||
+ | ====== Simulation der Achterbahn ====== | ||
+ | Zu jedem Zeitpunkt $t$ ist die Position $\vec x(t)$ und die Geschwindigkeit $\vec v(t)$ gesucht auf der Achterbahn gesucht. | ||
+ | Der Betrag der Geschwindigkeit ergibt sich im einfachsten Fall mit dem Energieerhaltungssatz direkt aus der Höhe der Position (wenn man Reibung vernachlässigt). | ||
+ | |||
+ | Effektiv werden wir eine " | ||
+ | Daraus kann z.B. die entsprechende Strecke auf der Kurve vorwärts gegangen werden. Wir müssen also auf einer Bezierkurve eine gegebene Länge vorwärts gehen können. | ||
+ | |||
+ | Ansatz 1: Kleine Abstände von Punkten auf der Kurve aufsummieren: | ||
+ | |||
+ | Ansatz 2: Betrag der Geschwindigkeit integrieren: | ||
+ | |||
+ | Die Komponenten von $\vec v(t)$ sind Polynome 2. Grades, d.h. man integriert eine Wurzel aus einem Polynom 4. Grades. Keine Ahnung, ob man das noch explizit gebacken kriegt (maxima streikt schon in ganz einfachen Fällen). | ||
+ | |||
+ | Wir werden das darum nummerisch machen und eine nette Klasse Bezier programmieren, | ||
+ | |||
+ | Um die Schienen zu legen, müssen wir die effektive Beschleunigung kennen, damit die Schienen normal dazu gelegt werden können. Dazu brauchen wir die Normale zur Bahn. Die erhalten wir als Ableitung der normalisierten Geschwindigkeit. | ||
+ | |||
+ | ===== Nötige Methoden für die Bezier Klasse ===== | ||
+ | * x(t): Liefert die Position zum Parameter $t$. | ||
+ | * v(t): Liefert die Geschwindigkeit zum Parameter $t$ (exakt). | ||
+ | * len(tmin, tmax): Liefert die Länge der Kurve zwischen den Parametern tmin, tmax (angenähert). | ||
+ | * vnorm(t): Geschwindkeitsvektor mit Länge 1 zum Parameter $t$. | ||
+ | * adl(t): Die Ableitung von vnorm nach der **Länge** der Kurve | ||
+ | * | ||
+ | |||
+ | <code python bezier2.py> | ||
+ | # -*- coding: utf-8 -*- | ||
+ | |||
+ | # import importlib | ||
+ | # importlib.import_module(" | ||
+ | from vector import Vector | ||
+ | |||
+ | class Bezier: | ||
+ | | ||
+ | def __init__(self, | ||
+ | if len(pts)==4: | ||
+ | self.pts = [p.copy() for p in pts] | ||
+ | if len(pts)==3: | ||
+ | self.pts = [pts[0].copy(), | ||
+ | if len(pts)==2: | ||
+ | self.pts = [pts[0].copy(), | ||
+ | | ||
+ | # Punkt für Parameter t (in [0, | ||
+ | def x(self,t): | ||
+ | return (1.0-t)**3*self.pts[0]+\ | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | # Geschwindigkeit (dx/dt) in t-Parametrierung | ||
+ | def v(self,t): | ||
+ | return -3*(1.0-t)**2*self.pts[0]+\ | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | |||
+ | # Zeichnet den Spline | ||
+ | # Achtung: Funktioniert nur, wenn diese Datei ausgeführt wird... | ||
+ | def draw(self, steps=1000): | ||
+ | move(self.pts[0][0], | ||
+ | for i in range(1, | ||
+ | p = self.x(1.0*i/ | ||
+ | lineTo((p[0], | ||
+ | | ||
+ | |||
+ | if __name__== " | ||
+ | from gpanel import * | ||
+ | makeGPanel(Size(600, | ||
+ | window(0, 599, 0, 599) | ||
+ | b = Bezier([Vector([100, | ||
+ | b.draw() | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ |