[PYTHON] Ich möchte den Schnittpunkt einer Bezier-Kurve und einer geraden Linie finden (Bezier-Clipping-Methode)

Einführung

In meiner Nachwuchsforschung musste ich den Schnittpunkt der Bezier-Kurve und der Geraden finden. Ich habe bei der Recherche geholfen

"** Python ist eine starke Bibliothek oder ein kurzes Implementierungsbeispiel! Margin **: grin:"

Ich habe nachgedacht, aber ich konnte keinen Artikel finden, der ** auf einem Niveau geschrieben wurde, das ich verstehen konnte. Es bleibt keine andere Wahl, als sich auf die Bezier-Clipping-Methode zu konzentrieren, die relativ einfach zu sein scheint und einige PDF-Kommentare gefunden wurden. Ich habe das Papier gelesen, verstanden und umgesetzt, also werde ich dieses Wissen verlassen. Bitte beachten Sie, dass einige Ausdrücke im Artikel möglicherweise ungenau sind (und geben Sie mir bitte einige Korrekturen).

Der implementierte Code wird auf [GitHub] veröffentlicht (https://github.com/takkaO/Bezier_Clipping_Algorithm).

Was ist eine Bezier-Kurve?

Die Bezier-Kurve ist eine Art Darstellung einer Kurve. Es wird häufig verwendet, um Kurven auf einem Computer darzustellen, z. B. Umrissschriften und CG. Die Bezier-Kurve besteht neben den Start- und Endpunkten der Kurve aus mehreren Punkten, die als Kontrollpunkte bezeichnet werden. Im Folgenden wird auf die Kontrollpunkte einschließlich des Startpunkts und des Endpunkts Bezug genommen. Die Bezier-Kurve wird unter Verwendung der Mediatorvariablen $ t $$ (0 \ leq t \ leq 1) $ wie folgt ausgedrückt.

\begin{align}
P(t) &= \sum_{i=0}^{n} F_i B_{i}^{n}(t) \\
&= \sum_{i=0}^{n} F_i {n \choose i} t^i \left(1-t \right)^{n-i}
\end{align}

$ F_i $ ist der Kontrollpunkt und $ B_ {i} ^ {n} $ ist das Bernstein-Basispolynom. Außerdem steht $ {n \ select i} $ für eine Kombination. Der Weltstandard scheint diese Art des Schreibens zu sein, aber wenn Sie es so schreiben, wie Sie es in der japanischen High School gelernt haben, wird es wie folgt sein.

P(t) = \sum_{i=0}^{n} F_i ~~ {}_n \mathrm{C} {}_r ~~ t^i \left(1-t \right)^{n-i}

Da die Bezier-Kurve eine Menge von Punkten bei $ t $$ (0 \ leq t \ leq 1) $ ist, Je feiner die Schrittweite von $ t $ ist, desto glatter ist die Kurve. Das Folgende ist ein Beispiel für das Ändern der Schrittgröße. Die grauen $ \ times $ -Punkte stehen für Kontrollpunkte. ** $ (0 \ leq t \ leq 1) Wenn $ in 5 geteilt wird (wenn nur 5 Punkte berechnet werden). ** ** ** 1.png

** Wenn $ (0 \ leq t \ leq 1) $ in 10 geteilt wird (wenn nur 10 Punkte berechnet werden). ** ** ** 2.png

** $ (0 \ leq t \ leq 1) Wenn $ in 50 geteilt wird (wenn nur 50 Punkte berechnet werden). ** ** ** 3.png

** Wenn $ (0 \ leq t \ leq 1) $ in 100 geteilt wird (wenn nur 100 Punkte berechnet werden). ** ** ** 4.png

Bezier Clipping-Methode

Überblick

Die Bezier-Clipping-Methode ist eine Methode zum Ermitteln des Schnittpunkts einer Kurve und einer geraden Linie unter Verwendung der Eigenschaften der Bezier-Kurve. Vorgeschlagen von Nishida et al. Die Merkmale sind wie folgt (Teilauszug).

Es scheint, dass es auch auf Schnittpunkte zwischen Bezier-Kurven und Schnittpunkten im 3D-Raum angewendet werden kann. Dieses Mal beschränken wir uns auf Bezier-Kurven und gerade Linien.

Algorithmus

Der allgemeine Ablauf des Algorithmus ist wie folgt. ** 1. Konvertieren Sie die Bezier-Zielkurve in eine Bezier-Kurve, die den Abstand zur Geraden darstellt (konvertieren Sie von der $ xy $ -Ebene in die $ td $ -Ebene). ** ** ** 5-6.png ** 2. Finden Sie die konvexe Hülle des Kontrollpunkts der konvertierten Bezier-Kurve und finden Sie die Schnittpunkte $ t_ {min} und t_ {max} $ mit der $ t $ -Achse. ** ** ** 7.png

** 3. Teilen Sie die Bezier-Kurve durch die erhaltenen $ t_ {min} und t_ {max} $, um eine neue Bezier-Kurve zu erstellen. ** ** ** 8.png ** 4. Wiederholen Sie den Vorgang von 2-3, bis das Intervall $ [t_ {min}, ~ t_ {max}] $ ausreichend klein wird. ** ** ** 9.png ** 5. Das erhaltene $ t $ (roter Punkt in der obigen Abbildung) wird zur Mediatorvariablen $ t $ der ursprünglichen Bezier-Kurve am Schnittpunkt mit der geraden Linie. ** ** ** 10.png

Der Algorithmus selbst ist sehr einfach. Wahrscheinlich der Ort, an dem man stecken bleibt

Ich denke, das ist es, deshalb werde ich es im nächsten Abschnitt ausführlich erklären.

Bezier-Kurvenumwandlungsprozess

Es wird ein zweidimensionaler ebener Koordinatenraum angenommen. Die gerade Linie $ L $ im ebenen Raum kann ausgedrückt werden als: $ a, b, c $ sind Konstanten.

ax + by + c = 0

Der Abstand $ d $ zwischen einem beliebigen Punkt $ (x_1, y_1) $ im Koordinatenraum und der geraden Linie $ L $ kann wie folgt ausgedrückt werden.

d = \frac{ax_1+by_1+c}{\sqrt{a^2 + b^2}}

Hier kann der Punkt $ (x, y) $ auf der Bezier-Kurve wie folgt erhalten werden, wobei $ t $ als Mediatorvariable dient. $ (x_i, y_i) $ repräsentiert den Kontrollpunkt der Bezier-Kurve.

\begin{align}
x(t) &= \sum_{i=0}^{n} x_i B_i^n (t) \\
y(t) &= \sum_{i=0}^{n} y_i B_i^n (t)
\end{align}

Mit diesen kann der Abstand $ D $ zwischen der Geraden $ L $ und der Bezier-Kurve wie folgt ausgedrückt werden.

\begin{align}
D &= \frac{ax(t)+by(t)+c}{\sqrt{a^2+b^2}} \\ \\
  &= \frac{1}{\sqrt{a^2+b^2}}\left( a\sum_{i=0}^{n} x_i B_i^n (t) + b\sum_{i=0}^{n} y_i B_i^n (t) + c \right)
\end{align}

$ \ sum_ {i = 0} ^ {n} B_i ^ n (t) = 1 $, also

\begin{align}
D &= \frac{1}{\sqrt{a^2+b^2}}\left( a\sum_{i=0}^{n} x_i B_i^n (t) + b\sum_{i=0}^{n} y_i B_i^n (t) + c\sum_{i=0}^{n} B_i^n (t) \right) \\ \\
  &= \frac{1}{\sqrt{a^2+b^2}}\sum_{i=0}^{n} (ax_i+by_i+c) B_i^n (t) \\ \\
  &= \frac{1}{\sqrt{a^2+b^2}}\sum_{i=0}^{n} d_i B_i^n (t) 
\end{align}

Hier ist $ D $ eine rationale Bezier-Kurve, die aus Kontrollpunkten $ \ left (\ frac {i} {n}, d_i \ right) $ besteht. Außerdem ist $ D $ die Bezier-Kurve in der $ td $ -Ebene, dh die Bezier-Kurve im Ebenenraum mit der horizontalen Achse $ t $ und der vertikalen Achse $ d $. Die Tatsache, dass die konvertierte Bezier-Kurve $ D $ bei einigen $ t ~ (0 \ leq t \ leq 1) $ $ d = 0 $ annimmt, bedeutet dies Bei diesem $ t $ -Wert bedeutet dies, dass der Abstand zwischen der Bezier-Kurve und der Geraden in der $ xy $ -Ebene vor der Konvertierung Null ist. Daher kann die Mediatorvariable $ t $ am Schnittpunkt der Geraden und der Bezier-Kurve berechnet werden. Wenn Sie danach die Mediatorvariable $ t $ in der folgenden Gleichung an den Schnittpunkt setzen, finden Sie die Koordinaten des Schnittpunkts in der $ xy $ -Ebene.

\begin{align}
x(t) &= \sum_{i=0}^{n} x_i B_i^n (t) \\
y(t) &= \sum_{i=0}^{n} y_i B_i^n (t)
\end{align}

Verarbeitung bei mehreren Punkten

Der Vorgang ist einfach, wenn mehrere Kreuzungen vorhanden sind. Wenn es mehrere Schnittpunkte gibt, ist die Änderung zwischen $ t_ {min} $ und $ t_ {max} $ gering. Ein Beispiel ist in der folgenden Abbildung dargestellt. Der blaue Punkt in der Abbildung repräsentiert den vorherigen $ t_ {min}, t_ {max} $ Punkt.

Erstes Mal 1.png Zweites Mal 2.png Drittes Mal 3.png ** 4. ** 4.png

Ab dem dritten Mal können Sie sehen, dass sich die Positionen von $ t_ {min} und t_ {max} $ nicht geändert haben. Teilen Sie in diesem Fall die Kurve an einem geeigneten Punkt und wenden Sie die Bezier-Beschneidungsmethode erneut auf jede Bezier-Kurve an. Es schien den Punkt der Trennung nicht zu erwähnen. In meiner Implementierung versuche ich, es in der Mitte zu teilen.

abschließend

In diesem Artikel habe ich die Bezier-Clipping-Methode erklärt. Ich hatte große Probleme, den ersten Teil der Konvertierung zu verstehen. Ich hoffe, der Inhalt dieses Artikels wird jemandem nützlich sein.

Verweise

Recommended Posts

Ich möchte den Schnittpunkt einer Bezier-Kurve und einer geraden Linie finden (Bezier-Clipping-Methode)
Finden Sie den Schnittpunkt eines Kreises und einer geraden Linie (Sympymatrix)
Ich möchte die Frage nach der Methode "__init__" und dem Argument "self" der Python-Klasse klären.
Ich möchte die Natur von Python und Pip kennenlernen
Ich möchte den Namen der ausgeführten Funktion / Methode erhalten
Holz kratzen und essen - ich möchte ein gutes Restaurant finden! ~ (Arbeit)
Ich möchte ein Histogramm erstellen und die Normalverteilungskurve darauf überlagern. matplotlib edition
Ich möchte Tag-Informationen (Titel und Künstler) einer Musikdatei (flac, wav) extrahieren.
Ich möchte die Gefühle von Menschen analysieren, die sich treffen und zittern wollen
Python: Ich möchte die Verarbeitungszeit einer Funktion genau messen
Ich wollte mit der Bezier-Kurve spielen
Ich möchte leicht einen leckeren Laden finden
Ich möchte das Erscheinungsbild von zabbix anpassen
[LINE Messaging API] Ich möchte eine Nachricht vom Programm an alle LINE senden
Die Geschichte der IPv6-Adresse, die ich auf ein Minimum beschränken möchte
Ich möchte einen Lebenszyklus in der Aufgabendefinition von ECS festlegen
Ich möchte dem Anfang einer WAV-Datei 1 Sekunde lang Stille hinzufügen
Ich möchte eine Liste der WebDAV-Dateien im Modul Anfragen anzeigen
Ich möchte den Dateinamen, die Zeilennummer und den Funktionsnamen in Python 3.4 erhalten
Ich möchte ein beliebtes Paket auf PyPi finden
Ich möchte die Grundlagen von Bokeh vollständig verstehen
Ich möchte ein Paket von Php Redis installieren
Ich möchte die Sicherheit der SSH-Verbindung erhöhen
Ich habe versucht, das Update von "Werde ein Romanautor" mit "IFTTT" und "Werde ein Romanautor API" zu benachrichtigen.
Ich kann die Uhrenquelle tsc nicht finden! ?? Die Geschichte des Versuchs, einen Kernel-Patch zu schreiben
Ich möchte einen Screenshot der Site in Docker mit einer beliebigen Schriftart erstellen
Ich möchte die Bezier-Kurve n-ter Ordnung an einem beliebigen Punkt teilen ~ Wiederholung und Matrix ~
Ich habe versucht, die Entropie des Bildes mit Python zu finden
Ich möchte die von LINE an S3 gesendeten Fotos speichern
Ich habe versucht, mit TensorFlow den Durchschnitt mehrerer Spalten zu ermitteln
Ich möchte viele Prozesse von Python aus starten
Ich möchte nur die SudachiPy-Normalisierungsverarbeitung verwenden
Ich möchte Betriebsinformationen über die Yahoo-Route erhalten
Ich möchte die Authentizität eines Elements eines numpy-Arrays bestimmen
Ich möchte eine Nachricht von Python an LINE Bot senden
So ermitteln Sie den Skalierungskoeffizienten eines bipolaren Wavelets
Ich möchte eine wunderschön angepasste Wärmekarte der Korrelationsmatrix ausgeben. matplotlib edition
Ich möchte den EDINET-Code und die Wertpapiernummer zuordnen
Keras Ich möchte die Ausgabe einer beliebigen Ebene erhalten !!
Ich möchte die Legende der IT-Technologiewelt kennenlernen
Ich möchte vorerst eine Docker-Datei erstellen.
[Python] Ein Programm, um die Anzahl der Äpfel und Orangen zu ermitteln, die geerntet werden können
Ich möchte Informationen von fstab am ssh-Verbindungsziel abrufen und den Befehl ausführen
Eine Geschichte über das Schreiben von AWS Lambda und ein wenig Abhängigkeit von den Standardwerten von Python-Argumenten
Ich habe einen Linienbot erstellt, der das Geschlecht und das Alter einer Person anhand des Bildes errät
Ich habe versucht, den Unterschied zwischen A + = B und A = A + B in Python herauszufinden
[Twitter] Ich möchte die heruntergeladenen vergangenen Tweets (meines Kontos) in eine schöne CSV verwandeln
[Pytorch] Ich möchte die Trainingsparameter des Modells manuell zuweisen
Ich möchte automatisch hochwertige Teile aus den von mir aufgenommenen Videos finden
Ich habe eine Python-Bibliothek erstellt, um die API von LINE WORKS aufzurufen
Ich möchte die HTML-Version der OpenCV 3.1-Version "OpenCV-Python Tutorials" lesen
[Einführung in Python] Ich habe die Namenskonventionen von C # und Python verglichen.
[Einführung in StyleGAN] Ich habe mit "The Life of a Man" ♬ gespielt
Ich möchte den Anfang des nächsten Monats mit Python ausgeben
Ich möchte ein System erstellen, um zu verhindern, dass vergessen wird, den Schlüssel 1 festzuziehen