[PYTHON] Ich möchte die Bezier-Kurve n-ter Ordnung an einem beliebigen Punkt teilen ~ Wiederholung und Matrix ~

Einführung

Unter bestimmten Umständen untersuchte ich die Teilung der Bezier-Kurve. Ich konnte nicht viele Websites finden, die erklären, wie die Bezier-Kurve ** $ n $ order ** geteilt wird.

Nun, da die Bezier-Kurve nur bis zur 4. Ordnung verwendet wird, spielt es keine Rolle, ob Sie die $ n $ -Ordnung nicht kennen. Ich wollte es wirklich ordentlich implementieren, also habe ich es untersucht, also werde ich es als Wissen belassen. Ich habe ein Implementierungsbeispiel in dem Artikel veröffentlicht, aber ich habe es auch auf GitHub veröffentlicht (siehe line_module.py).

Methode mit Wiederholung

Dies ist eine Methode namens De Casteljaus Algorithmus. Diese Methode verwendet die Wiederholung, um die Kontrollpunkte für die neue Bezier-Kurve nach der Division zu finden. Diese Methode ist ** einfach im Konzept und leicht zu implementieren **, hat jedoch den Nachteil, dass sie in eingebetteten Systemen mit einer kleinen Stapelgröße ** schwierig zu verwenden ist **. Nun, die Bezier-Kurve ist nur bis zur 4. Ordnung (weggelassen)

Algorithmus

Teilen wir als Beispiel die unten gezeigte Bezier-Kurve. Sei $ t $ die Mediatorvariable der Bezier-Kurve am Teilungspunkt und sei $ P_i $ der anfängliche Kontrollpunkt der Bezier-Kurve. 図0.png

** 1. Suchen Sie den Punkt, der zu $ t: 1-t $ wird, auf der Linie, die die Kontrollpunkte der Bezier-Kurve verbindet (Punkt $ Q $). ** ** ** 図1.png

** 2. Suchen Sie für die Verbindungslinie zwischen den erhaltenen Punkten den Punkt $ t: 1-t $ (Punkt $ R $). ** ** ** 図2.png

** 3. Wiederholen, bis es einen Punkt gibt (Punkt $ S $). ** ** ** 図3.png

** 4. An allen Punkten einschließlich der anfänglichen Kontrollpunkte sind die Punktmenge mit dem kleinsten Index und die Menge der Punkte mit dem größten Index die Kontrollpunkte nach der Division. ** ** ** 図4.png

Für den letzten Teil (Mindestindex) ist es einfacher zu verstehen, wenn Sie die folgende Baumstruktur schreiben. Die unten gezeigte Baumstruktur zeigt, aus welchem Liniensegment (welche zwei Punkte) ein neuer Punkt generiert wurde. 図5.png

Die äußersten Punkte dieser Baumstruktur, nämlich die Punkte $ \ {P_0, Q_0, R_0, S_0 \} $ und die Punkte $ \ {S_0, R_1, Q_2, P_3 \} $, werden zu neuen Bezier-Kurven. Ich werde. Sie können sehen, dass der Start- und Endpunkt der ursprünglichen Bezier-Kurve gemeinsam sind und dass der Punkt (Teilungspunkt $ S_0 $) in der Mediatorvariablen $ t $ der Startpunkt (Endpunkt) der neuen Bezier-Kurve ist. 図6.png

Programm

Ein Beispiel für die Implementierung eines Split-Programms mit Wiederholung ist unten dargestellt.

import numpy as np
from scipy.special import comb
import matplotlib.pyplot as plt

class Bezier:
	def __init__(self, points):
		points = [np.array(e).flatten() for e in points]

		self._n = len(points)
		self._points = points

	@property
	def dims(self):
		return self._n - 1

	@property
	def points(self):
		return self._points

	@property
	def points4matplot(self):
		xs, ys = zip(*self.points)
		return xs, ys

	def _bernstein(self, n, i, t):
		return comb(n, i) * t**i * (1 - t)**(n-i)

	def bezier_point(self, t):
		p = np.zeros(2)
		for i, f in enumerate(self.points):
			p += self._bernstein(self.dims, i, t) * f
		return np.array(p).flatten()

	def _de_casteljau_algorithm(self, points, t):
		prev_p = None
		q = []
		for p in points:
			if not prev_p is None:
				## Split line into t:(1-t)
				q.append(np.array((1-t) * prev_p + t * p).flatten())
			prev_p = p
		if len(q) == 1:
			return [q]
		return [q] + self._de_casteljau_algorithm(q, t)

	def split_with_recursion(self, t):
		ret = [self.points] + self._de_casteljau_algorithm(self.points, t)
		lp = []
		rp = []
		for lst in ret:
			## Fetch min and max point
			lp.append(lst[0])
			rp.append(lst[-1])
		return Bezier(lp), Bezier(rp)	
			
	def plot(self, ax=None, with_ctrl_pt=True, bcolor="black", ccolor="gray", resolution=100):
		if ax is None:
			_, ax = plt.subplots()
		prev_point = None
		for t in np.linspace(0, 1, resolution):
			bp = self.bezier_point(t)
			if prev_point is None:
				prev_point = (bp[0], bp[1])
			xs, ys = zip(*(prev_point, (bp[0], bp[1])))
			ax.plot(xs, ys, '-', color=bcolor)
			prev_point = (bp[0], bp[1])

		if with_ctrl_pt:
			xs, ys = self.points4matplot
			ax.plot(xs, ys, 'x--', lw=2, color=ccolor, ms=10)
		return ax


def main():
	bezier = Bezier([(0.3, 1), (0.2, 3), (0.4, 4), (0.5, 0)])
	ax = bezier.plot()
	
	left_bezier, right_bezier = bezier.split_with_recursion(0.3)
	left_bezier.plot(ax, bcolor = "red")
	right_bezier.plot(ax, bcolor = "blue")

	plt.grid()
	plt.show()

if __name__ == "__main__":
	main()

Methode mit Matrix

Dies ist eine Methode, um mithilfe einer Matrix einen neuen Kontrollpunkt zu finden. Diese Methode ** spielt keine Rolle, wenn die Stapelgröße klein ist **, aber ** die Berechnung ist etwas kompliziert **. Nun, die Bezier-Kurve ist höchstens 4. Ordnung (weggelassen)

Darstellung der Bezier-Kurve in Form einer Matrix

Als ersten Schritt zur Erklärung des Algorithmus werde ich die Matrixdarstellung der Bezier-Kurve erläutern. Die Bezier-Kurve kann durch die folgende Gleichung ausgedrückt werden.

\begin{align}
F(t) &= \sum_{i=0}^{n} P_i~B_{i}^{n}(t)
\end{align}

$ P_i $ repräsentiert den Kontrollpunkt und $ B_ {i} ^ {n} (t) $ repräsentiert die Bernstein-Basisfunktion. $ n $ repräsentiert die Reihenfolge der Bezier-Kurve plus $ 1 $ (die Anzahl der $ = $ Kontrollpunkte). Dies kann in Form eines Matrizenprodukts wie folgt ausgedrückt werden.

\begin{align}
F(t) &= \sum_{i=0}^{n} P_i~B_{i}^{n}(t) \\
&= \left(
    \begin{array}{ccc}
        B_{0}^{n} & B_{1}^{n} & \dots & B_{n}^{n}
    \end{array} 
\right) 
\left( 
    \begin{array}{ccc}
        P_0 \\
        P_1 \\
        \vdots \\
        P_n
    \end{array}
\right)
\end{align}

Zusätzlich kann die Formel der Bezier-Kurve wie folgt ausgedrückt werden, indem sie für $ t $ organisiert wird. Hier repräsentiert $ a_n $ einen geeigneten Koeffizienten.

\begin{align}
F(t) &= \sum_{i=0}^{n} P_i~B_{i}^{n}(t) \\
&= \left(
    \begin{array}{ccc}
        1 & t & t^2 & \dots & t^n
    \end{array} 
\right) 
\left( 
    \begin{array}{ccc}
        a_0 \\
        a_1 \\
        \vdots \\
        a_n
    \end{array}
\right)
\end{align}

Aus dem Obigen kann die folgende Gleichung abgeleitet werden.

\begin{align}
F(t) &= 
\left(
    \begin{array}{ccc}
        B_{0}^{n} & B_{1}^{n} & \dots & B_{n}^{n}
    \end{array} 
\right) 
\left( 
    \begin{array}{ccc}
        P_0 \\
        P_1 \\
        \vdots \\
        P_n
    \end{array}
\right)
=
\left(
    \begin{array}{ccc}
        1 & t & t^2 & \dots & t^n
    \end{array} 
\right) 
\left( 
    \begin{array}{ccc}
        a_0 \\
        a_1 \\
        \vdots \\
        a_n
    \end{array}
\right) \\ \\

F(t) &= BP = XA
\end{align}

Es ist ziemlich sauber. Hier wissen wir, dass $ A $ durch eine untere Dreiecksmatrix $ U_t $ und einen Kontrollpunkt $ P $ wie folgt ausgedrückt werden kann.

\begin{align}
A &= U_tP \\ \\
&= \left(
  \begin{array}{ccc}
    {n \choose 0} {n \choose 0} (-1)^0 & 0 & \cdots & 0 \\
    {n \choose 0} {n \choose 1} (-1)^1 & {n \choose 1} {n-1 \choose 0} (-1)^0 & \cdots & 0 \\
    \vdots & \vdots & \cdots & \vdots \\
    {n \choose 0} {n \choose n} (-1)^n & {n \choose 1} {n-1 \choose n-1} (-1)^{n-1} & \cdots & {n \choose n} {n-n \choose n-n} (-1)^{n-n} \\
  \end{array}
\right)
\left( 
    \begin{array}{ccc}
        P_0 \\
        P_1 \\
        \vdots \\
        P_n
    \end{array}
\right)
\end{align}

Daher kann schließlich die Bezier-Kurvengleichung unter Verwendung einer Matrix wie folgt ausgedrückt werden.

F(t) = BP = XU_tP

Algorithmus

Der Algorithmus für die Bezier-Kurventeilung unter Verwendung einer Matrix ist wie folgt.

** 1. Ordnen Sie die Bezier-Kurve für $ t $ an und drücken Sie sie in Form einer Matrix aus. ** ** **

\begin{align}
F(t) &= XU_tP \\
&= \left(
  \begin{array}{ccc}
    1 & t & t^2 & \dots & t^n
  \end{array}
\right)U_tP \\
\end{align}

** 2. Trennen Sie den Teilungspunkt $ z ~ (z \ in t) $. ** ** **

\begin{align}
F(t) &= \left(
  \begin{array}{ccc}
    1 & t & t^2 & \dots & t^n
  \end{array}
\right)U_tP \\ \\

&= \left(
  \begin{array}{ccc}
    1 & (z\cdot t) & (z\cdot t)^2 & \dots & (z\cdot t)^n
  \end{array}
\right)U_tP \\ \\

&= \left(
  \begin{array}{ccc}
    1 & t & t^2 & \dots & t^n
  \end{array}
\right)
\left(
  \begin{array}{ccc}
    1 &   &     &        & 0 \\
      & z &     &        &   \\
      &   & z^2 &        &   \\
      &   &     & \ddots &   \\
    0 &   &     &        &  z^n
  \end{array}
\right)U_tP

\end{align}

** 3. Transformieren Sie die Formel wie folgt, um $ Q $ zu finden. ** ** **

\begin{align}
F(t) &= \left(
  \begin{array}{ccc}
    1 & t & t^2 & \dots & t^n
  \end{array}
\right)
\left(
  \begin{array}{ccc}
    1 &   &     &        & 0 \\
      & z &     &        &   \\
      &   & z^2 &        &   \\
      &   &     & \ddots &   \\
    0 &   &     &        &  z^n
  \end{array}
\right)U_tP \\

&= X ~ Z U_t ~ P \\ \\
&= X ~ U_t U_t^{-1} Z U_t ~ P \\ \\
&= X ~ U_t Q ~P
\end{align}

Bei der obigen Berechnung wird die Position von $ U_t $ verschoben. Da $ U_t U_t ^ {-1} $ eine Einheitsmatrix ist, ändert sich das Berechnungsergebnis selbst nicht. $ Q = U_t ^ {-1} ZU_t $.

** 4. Berechnen Sie $ QP $, um den Kontrollpunkt der neuen Bezier-Kurve zu berechnen. ** ** **

\begin{align}
F(t) &= X ~ U_t Q ~P \\
&= X ~ U_t ~ P^{~\prime} 
\end{align}

Wenn $ P ^ {~ \ prime} = QP $ ist, hat dies die Form eines Ausdrucks, der die Bezier-Kurve darstellt. Daher ist $ P ^ {~ \ prime} $ der Kontrollpunkt der Bezier-Kurve nach der Division.


Durch das obige Verfahren konnten wir die ** geteilte linke Bezier-Kurve ** finden. Um die Bezier-Kurve auf der rechten Seite zu finden, trennen Sie $ z $ in Schritt 2 wie folgt. Finden Sie die richtige Matrix $ Q ^ {~ \ prime} $.

\begin{align}
F(t) &= \left(
  \begin{array}{ccc}
    1 & t & t^2 & \dots & t^n
  \end{array}
\right)U_tP \\ \\

&= \left(
  \begin{array}{ccc}
    1 & (z + (1-z)\cdot t) & (z + (1-z)\cdot t)^2 & \dots & (z + (1-z)\cdot t)^n
  \end{array}
\right)U_tP
\end{align}

Sie können jedoch $ Q ^ {~ \ prime} $ mithilfe des berechneten $ Q $ finden, ohne es direkt berechnen zu müssen. Speziell,

  1. Packen Sie die Elemente von $ Q $ rechts um $ 0 $.
  2. Drehen Sie die nach rechts gepackten Elemente der Matrix um.

Mach einfach die Operation. Da es schwierig ist, mathematische Formeln zu erklären, lesen Sie den Abschnitt des folgenden Berechnungsbeispiels.

Berechnungsbeispiel

Für diejenigen, die sagen: "$ n $ Ich verstehe nicht nur die nächste Geschichte!", Hier ist ein Beispiel für die Division durch Matrixberechnung. Diesmal als Beispiel P_0=(0, 1),~ P_1=(1, 4),~ P_2=(2, 0) Angenommen, Sie möchten eine quadratische Bezier-Kurve mit an der Position von $ t = 0,3 $ teilen. Es ist eine Kurve wie in der folgenden Abbildung gezeigt.

f1.png

Zunächst wird diese Bezier-Kurve in Form einer Matrix dargestellt und der Teilungspunkt $ z = 0,3 $ getrennt.

\begin{align}
F(t) &= XZU_tP \\
&=
\left( 
  \begin{array}{ccc}
     1 & t & t^2
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     0 & z & 0 \\
     0 & 0 & z^2
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     {2 \choose 0}{2 \choose 0}(-1)^0 & 0 & 0 \\
     {2 \choose 0}{2 \choose 1}(-1)^1 & {2 \choose 1}{1 \choose 0}(-1)^0 & 0 \\
     {2 \choose 0}{2 \choose 2}(-1)^2 & {2 \choose 1}{1 \choose 1}(-1)^1 & {2 \choose 2}{0 \choose 0}(-1)^0
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     P_0 \\
     P_1 \\
     P_2
  \end{array}
\right) \\ \\
&=
\left( 
  \begin{array}{ccc}
     1 & t & t^2
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     0 & 0.3 & 0 \\
     0 & 0 & 0.09
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     -2 & 2 & 0 \\
     1 & -2 & 1
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     P_0 \\
     P_1 \\
     P_2
  \end{array}
\right)

\end{align}

Berechnen Sie nun $ Q = U_t ^ {-1} ZU_t $.

\begin{align}
Q &= U_t^{-1}ZU_t \\ \\
&=
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     1 & \frac{1}{2} & 0 \\
     1 & 1 & 1
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     0 & 0.3 & 0 \\
     0 & 0 & 0.09
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     -2 & 2 & 0 \\
     1 & -2 & 1
  \end{array}
\right) \\ \\
&=
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     0.7 & 0.3 & 0 \\
     0.49 & 0.42 & 0.09
  \end{array}
\right)
\end{align}

Transformieren Sie die Formel mit $ Q $ in eine Formel.

\begin{align}
F(t) &= XZU_tP \\
&= XU_tU_t^{-1}ZU_tP \\
&= XU_tQP \\
&=
\left( 
  \begin{array}{ccc}
     1 & t & t^2
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     -2 & 2 & 0 \\
     1 & -2 & 1
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     0.7 & 0.3 & 0 \\
     0.49 & 0.42 & 0.09
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     P_0 \\
     P_1 \\
     P_2
  \end{array}
\right)

\end{align}

Wenn Sie hier für $ QP $ rechnen,

\begin{align}
QP &=
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     0.7 & 0.3 & 0 \\
     0.49 & 0.42 & 0.09
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     P_0 \\
     P_1 \\
     P_2
  \end{array}
\right) \\ \\
&=
\left( 
  \begin{array}{ccc}
     P_0 \\
     0.7P_0 + 0.3P_1 \\
     0.49P_0 + 0.42P_1 + 0.09P_2
  \end{array}
\right) \\ \\
&= P^{~\prime} \\ \\
\end{align}
\begin{align}
P^{~\prime}_x &= 
\left( 
  \begin{array}{ccc}
     0 \\
     0.7\cdot 0 + 0.3 \cdot 1 \\
     0.49\cdot 0 + 0.42\cdot 1 + 0.09\cdot 2
  \end{array}
\right) 
=
\left( 
  \begin{array}{ccc}
     0 \\
     0.3 \\
     0.6
  \end{array}
\right)
\end{align}
\begin{align}
P^{~\prime}_y &= 
\left( 
  \begin{array}{ccc}
     1 \\
     0.7\cdot 1 + 0.3 \cdot 4 \\
     0.49\cdot 1 + 0.42\cdot 4 + 0.09\cdot 0
  \end{array}
\right) 
=
\left( 
  \begin{array}{ccc}
     1 \\
     1.9 \\
     2.17
  \end{array}
\right) \\
\end{align}

Und ** der Kontrollpunkt der geteilten linken Bezier-Kurve ** $P_0^{~\prime}=(0, 1),~ P_1^{~\prime}=(0.3, 1.9),~ P_2^{~\prime}=(0.6, 2.17)$ Es stellte sich heraus.

Als nächstes finden wir die Bezier-Kurve auf der rechten Seite. $ U_t ^ {-1} Z ^ {~ \ prime} U_t = Q ^ {~ \ prime} $ für die rechte Seite kann wie folgt unter Verwendung des berechneten $ Q $ berechnet werden.

** 1. Packen Sie das $ Q $ -Element rechts um $ 0 $. ** ** **

\begin{align}
Q &= 
\left( 
  \begin{array}{ccc}
     1 & 0 & 0 \\
     0.7 & 0.3 & 0 \\
     0.49 & 0.42 & 0.09
  \end{array}
\right) 
\Rightarrow
\left( 
  \begin{array}{ccc}
     0 & 0 & 1 \\
     0 & 0.7 & 0.3 \\
     0.49 & 0.42 & 0.09
  \end{array}
\right)

\end{align}

** 2. Drehen Sie die nach rechts gepackten Elemente der Matrix um. ** ** **

\begin{align}
\left( 
  \begin{array}{ccc}
     0 & 0 & 1 \\
     0 & 0.7 & 0.3 \\
     0.49 & 0.42 & 0.09
  \end{array}
\right)
\Rightarrow
\left( 
  \begin{array}{ccc}
     0.49 & 0.42 & 0.09 \\
     0 & 0.7 & 0.3 \\
     0 & 0 & 1
  \end{array}
\right)
= Q^{~\prime}
\end{align}

Es ist einfach. Sie können das erhaltene $ Q ^ {~ \ prime} $ verwenden, um die ** geteilte rechte Bezier-Kurve ** zu finden.

\begin{align}
Q^{~\prime}P &=
\left( 
  \begin{array}{ccc}
     0.49 & 0.42 & 0.09 \\
     0 & 0.7 & 0.3 \\
     0 & 0 & 1
  \end{array}
\right)
\left( 
  \begin{array}{ccc}
     P_0 \\
     P_1 \\
     P_2
  \end{array}
\right) \\ \\
&=
\left( 
  \begin{array}{ccc}
     0.49P_0 + 0.42P_1 + 0.09P_2 \\
     0.7P_1 + 0.3P_2 \\
     P_2
  \end{array}
\right) \\ \\
&= P^{~\prime\prime} \\ \\
\end{align}
\begin{align}
P^{~\prime\prime}_x &= 
\left( 
  \begin{array}{ccc}
     0.49\cdot 0 + 0.42\cdot 1 + 0.09\cdot 2 \\
     0.7\cdot 1 + 0.3 \cdot 2 \\
     2
  \end{array}
\right) 
=
\left( 
  \begin{array}{ccc}
     0.6 \\
     1.3 \\
     2
  \end{array}
\right)
\end{align}
\begin{align}
P^{~\prime\prime}_y &= 
\left( 
  \begin{array}{ccc}
     0.49\cdot 1 + 0.42\cdot 4 + 0.09\cdot 0 \\
     0.7\cdot 4 + 0.3 \cdot 0 \\
     0
  \end{array}
\right) 
=
\left( 
  \begin{array}{ccc}
     2.17 \\
     2.8 \\
     0
  \end{array}
\right)
\end{align}

Nun der Kontrollpunkt der Bezier-Kurve auf der rechten Seite $P_0^{~\prime\prime}=(0.6, 2.17),~ P_1^{~\prime\prime}=(1.3, 2.8),~ P_2^{~\prime\prime}=(2, 0)$ Es stellte sich heraus.

Da $ P_0 = P_0 ^ {~ \ prime} $, $ P_2 ^ {~ \ prime} = P_0 ^ {~ \ prime \ prime} $, $ P_2 = P_2 ^ {~ \ prime \ prime} $ Es scheint, dass Sie es gut teilen können. Wenn Sie die erhaltene Bezier-Kurve auf der linken Seite und die Bezier-Kurve auf der rechten Seite zeichnen, entspricht dies der Abbildung unten. Sie können es gut teilen.

f2.png

Programm

Ein Beispiel für die Implementierung eines Teilungsprogramms unter Verwendung einer Matrix ist unten gezeigt.

import numpy as np
from scipy.special import comb
import matplotlib.pyplot as plt

class Bezier:
	def __init__(self, points):
		points = [np.array(e).flatten() for e in points]

		self._n = len(points)
		self._points = points

	@property
	def dims(self):
		return self._n - 1

	@property
	def points(self):
		return self._points

	@property
	def points4matplot(self):
		xs, ys = zip(*self.points)
		return xs, ys

	def _bernstein(self, n, i, t):
		return comb(n, i) * t**i * (1 - t)**(n-i)

	def bezier_point(self, t):
		p = np.zeros(2)
		for i, f in enumerate(self.points):
			p += self._bernstein(self.dims, i, t) * f
		return np.array(p).flatten()

	def split_with_matrix(self, t):
		M = self.create_Ut()
		iM = np.linalg.inv(M)

		Z = np.eye(self.dims + 1)
		for i in range(self.dims + 1):
			Z[i] = Z[i] * t ** i
		## Caluclate Q
		Q = iM @ Z @ M

		xs, ys = self.points4matplot
		X = np.array(xs)
		Y = np.array(ys)

		left_bezier = Bezier(list(zip(Q @ X, Q @ Y)))

		## Make Q'
		_Q = np.zeros((self.dims + 1, self.dims + 1))
		lst = []
		for i in reversed(range(self.dims + 1)):
			l = [-1] * i + list(range(self.dims + 1 - i))
			lst.append(l)
		for i, l in enumerate(lst):
			mtx = [Q[i][e] if not e == -1 else 0 for e in l]
			_Q[i] = np.array(mtx)
		_Q = np.flipud(_Q)

		right_bezier = Bezier(list(zip(_Q @ X, _Q @ Y)))

		return left_bezier, right_bezier

	def create_Ut(self, dims=None):
		if dims is None:
			dims = self.dims

		U = np.zeros([dims + 1, dims + 1])
		lmbd = lambda n, i, j: comb(n, j) * comb(n-j, i-j) * (-1)**(i - j)

		for i in range(dims + 1):
			lst = list(range(i+1)) + [-1]*(dims-i)
			elems = [lmbd(dims, i, j) if j >= 0 else 0.0 for j in lst]
			mtx = np.array(elems)
			U[i] = mtx
		return U
			
	def plot(self, ax=None, with_ctrl_pt=True, bcolor="black", ccolor="gray", resolution=100):
		if ax is None:
			_, ax = plt.subplots()
		prev_point = None
		for t in np.linspace(0, 1, resolution):
			bp = self.bezier_point(t)
			if prev_point is None:
				prev_point = (bp[0], bp[1])
			xs, ys = zip(*(prev_point, (bp[0], bp[1])))
			ax.plot(xs, ys, '-', color=bcolor)
			prev_point = (bp[0], bp[1])

		if with_ctrl_pt:
			xs, ys = self.points4matplot
			ax.plot(xs, ys, 'x--', lw=2, color=ccolor, ms=10)
		return ax


def main():
	bezier = Bezier([(0, 1), (1, 4), (2, 0)])
	ax = bezier.plot()
	
	left_bezier, right_bezier = bezier.split_with_matrix(0.3)
	left_bezier.plot(ax, bcolor = "red")
	right_bezier.plot(ax, bcolor = "blue")

	plt.grid()
	plt.show()

if __name__ == "__main__":
	main()

abschließend

In diesem Artikel habe ich die Division der Bezier-Kurve der Ordnung $ n $ vorgestellt. Es war vielleicht nicht sehr gut organisiert, aber bitte vergib mir. Ich hoffe, der Inhalt dieses Artikels wird jemandem nützlich sein.

Verweise

Recommended Posts

Ich möchte die Bezier-Kurve n-ter Ordnung an einem beliebigen Punkt teilen ~ Wiederholung und Matrix ~
Ich möchte den Schnittpunkt einer Bezier-Kurve und einer geraden Linie finden (Bezier-Clipping-Methode)
Ich möchte einen beliebigen Befehl im Befehlsverlauf von Shell belassen
Ich möchte ein Automatisierungsprogramm erstellen!
Ich möchte gleichzeitig einen Musik-Player erstellen und Musik ablegen
Ich möchte ein Element mit numpy in eine Datei schreiben und es überprüfen.
Ich möchte an eine Wiederholung denken können
Ich wollte mit der Bezier-Kurve spielen
Ich möchte OREMO mit setParam sein!
Ich möchte ein Bild mit Lollipop in WebP konvertieren
Ich möchte die Optimierung mit Python und CPlex behandeln
Ich möchte Android-Apps auf Android entwickeln (Debug)
Ich möchte das Produkt zu den niedrigsten Kosten veröffentlichen
Ich möchte die Effizienz mit Python auch in experimentellen Systemen verbessern (2) RS232C und pySerial
Ich möchte ein englisches Papier aus dem PDF-Format kopieren und in die Google-Übersetzung einfügen