[PYTHON] Je veux trouver l'intersection d'une courbe de Bézier et d'une ligne droite (méthode de découpage de Bézier)

introduction

Dans mes recherches juniors, j'ai dû trouver l'intersection de la courbe de Bézier et de la ligne droite. J'aidais à la recherche

"** Python est une bibliothèque solide ou un exemple d'implémentation concis! Margin **: grin:"

Je réfléchissais, mais je n'ai pas trouvé d'article écrit ** à un niveau que je pouvais comprendre. Il n'y a pas d'autre choix que de se concentrer sur la méthode de découpage de Bézier, qui semble relativement facile et un PDF de commentaire a été trouvé. J'ai lu le document, je l'ai compris et mis en œuvre, alors je vais laisser cette connaissance. Veuillez noter que certaines expressions peuvent être inexactes dans l'article (et veuillez me donner quelques corrections).

Le code implémenté est publié sur GitHub.

Qu'est-ce qu'une courbe de Bézier?

La courbe de Bézier est un type de représentation d'une courbe. Il est souvent utilisé pour représenter des courbes sur un ordinateur telles que les polices vectorielles et CG. La courbe de Bézier se compose de plusieurs points appelés points de contrôle, en plus des points de début et de fin de la courbe. Ci-après, les points de contrôle comprenant le point de départ et le point final seront mentionnés. La courbe de Bézier est exprimée comme suit en utilisant la variable médiatrice $ t $$ (0 \ leq t \ leq 1) $.

\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 $ est le point de contrôle et $ B_ {i} ^ {n} $ est les polynômes de base de Bernstein. De plus, $ {n \ choose i} $ représente une combinaison. La norme mondiale semble être cette façon d'écrire, mais si vous l'écrivez comme vous l'avez appris au lycée japonais, ce sera comme suit.

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

Puisque la courbe de Bézier est un ensemble de points à $ t $$ (0 \ leq t \ leq 1) $, Plus la taille de pas de $ t $ est fine, plus la courbe est lisse. Voici un exemple de modification de la taille de pas. Les points gris $ \ times $ représentent les points de contrôle. ** $ (0 \ leq t \ leq 1) Lorsque $ est divisé en 5 (lorsque seulement 5 points sont calculés). ** ** 1.png

** Lorsque $ (0 \ leq t \ leq 1) $ est divisé en 10 (lorsque seulement 10 points sont calculés). ** ** 2.png

** Lorsque $ (0 \ leq t \ leq 1) $ est divisé en 50 (lorsque seulement 50 points sont calculés). ** ** 3.png

** Lorsque $ (0 \ leq t \ leq 1) $ est divisé en 100 (lorsque seulement 100 points sont calculés). ** ** 4.png

Méthode de découpage de Bézier

Aperçu

La méthode de découpage de Bézier est une méthode permettant de trouver l'intersection d'une courbe et d'une ligne droite en utilisant les propriétés de la courbe de Bézier. Proposé en 1990 par Nishida et al. Les caractéristiques sont les suivantes (extrait partiel).

--Toutes les solutions (intersections) dans la plage spécifiée peuvent être trouvées

Il semble qu'il puisse également s'appliquer aux intersections entre les courbes de Bézier et les intersections dans l'espace 3D. Cette fois, nous le limiterons aux courbes de Bézier et aux lignes droites.

algorithme

Le flux général de l'algorithme est le suivant. ** 1. Convertissez la courbe de Bézier cible en une courbe de Bézier qui représente la distance par rapport à la ligne droite (conversion du plan $ xy $ au plan $ td $). ** ** 5-6.png ** 2. Trouvez la coque convexe du point de contrôle de la courbe de Bézier convertie, et trouvez les intersections $ t_ {min} et t_ {max} $ avec l'axe $ t $. ** ** 7.png

** 3. Divisez la courbe de Bézier par les $ t_ {min} et t_ {max} $ obtenus pour créer une nouvelle courbe de Bézier. ** ** 8.png ** 4. Répétez le processus 2-3 jusqu'à ce que l'intervalle $ [t_ {min}, ~ t_ {max}] $ devienne suffisamment petit. ** ** 9.png ** 5. Le $ t $ obtenu (point rouge dans la figure ci-dessus) devient la variable médiatrice $ t $ de la courbe de Bézier originale à l'intersection avec la ligne droite. ** ** 10.png

L'algorithme lui-même est très simple. Probablement l'endroit pour rester coincé

Je pense que c'est le cas, alors je vais l'expliquer en détail dans la section suivante.

Processus de conversion de la courbe de Bézier

Il suppose un espace de coordonnées plan bidimensionnel. La droite $ L $ dans l'espace plan peut être exprimée comme suit: $ a, b, c $ sont des constantes.

ax + by + c = 0

La distance $ d $ entre tout point $ (x_1, y_1) $ dans l'espace de coordonnées et la ligne droite $ L $ peut être exprimée comme suit.

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

Ici, le point $ (x, y) $ sur la courbe de Bézier peut être obtenu comme suit avec $ t $ comme variable intermédiaire. $ (x_i, y_i) $ représente le point de contrôle de la courbe de Bézier.

\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}

En utilisant ces derniers, la distance $ D $ entre la droite $ L $ et la courbe de Bézier peut être exprimée comme suit.

\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 $, donc

\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}

Ici, $ D $ est une courbe de Bézier rationnelle constituée de points de contrôle $ \ left (\ frac {i} {n}, d_i \ right) $. De plus, $ D $ est la courbe de Bézier dans le plan $ td $, c'est-à-dire la courbe de Bézier dans l'espace plan avec l'axe horizontal $ t $ et l'axe vertical $ d $. Le fait que la courbe de Bézier convertie $ D $ prenne $ d = 0 $ à quelque $ t ~ (0 \ leq t \ leq 1) $ signifie que À cette valeur $ t $, cela signifie que la distance entre la courbe de Bézier et la ligne droite dans le plan $ xy $ avant la conversion est nulle. Par conséquent, la variable médiatrice $ t $ à l'intersection de la droite et de la courbe de Bézier peut être calculée. Après cela, si vous placez la variable médiatrice $ t $ à l'intersection dans l'équation suivante, vous pouvez trouver les coordonnées de l'intersection dans le plan $ xy $.

\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}

Traitement lorsqu'il y a plusieurs points

Le processus est simple lorsqu'il y a plusieurs intersections. S'il y a plusieurs intersections, le changement entre $ t_ {min} $ et $ t_ {max} $ sera faible. Un exemple est illustré dans la figure ci-dessous. Le point bleu sur la figure représente le point $ t_ {min}, t_ {max} $ précédent.

Première fois 1.png Deuxième fois 2.png Troisième fois 3.png ** 4ème ** 4.png

A partir de la troisième fois, vous pouvez voir que les positions de $ t_ {min} et t_ {max} $ n'ont pas changé. Dans ce cas, divisez la courbe en un point approprié et appliquez à nouveau la méthode de découpage de Bézier à chaque courbe de Bézier. Il ne semblait pas mentionner le point de division. Dans ma mise en œuvre, j'essaye de le diviser au milieu.

en conclusion

Dans cet article, j'ai expliqué la méthode Bézier Clipping. J'ai eu beaucoup de mal à comprendre la première partie de la conversion. J'espère que le contenu de cet article sera utile à quelqu'un.

Les références

Recommended Posts

Je veux trouver l'intersection d'une courbe de Bézier et d'une ligne droite (méthode de découpage de Bézier)
Trouver l'intersection d'un cercle et d'une droite (matrice sympy)
Je veux clarifier la question de la méthode "__init__" et de l'argument "self" de la classe Python.
Je veux connaître la nature de Python et pip
Je veux obtenir le nom de la fonction / méthode en cours d'exécution
Gratter et manger des bûches - je veux trouver un bon restaurant! ~ (Travail)
Je veux créer un histogramme et superposer la courbe de distribution normale dessus. édition matplotlib
Je souhaite extraire les informations d'étiquette (titre et artiste) d'un fichier de musique (flac, wav).
Je veux analyser les sentiments des gens qui veulent se rencontrer et trembler
Python: je souhaite mesurer proprement le temps de traitement d'une fonction
Je voulais jouer avec la courbe de Bézier
Je veux trouver facilement une délicieuse boutique
Je souhaite personnaliser l'apparence de zabbix
[LINE Messaging API] Je souhaite envoyer un message du programme à tout le monde LINE
L'histoire de l'adresse IPv6 que je souhaite conserver au minimum
Je souhaite définir un cycle de vie dans la définition de tâche d'ECS
Je veux ajouter du silence pendant 1 seconde au début d'un fichier wav
Je souhaite voir une liste de fichiers WebDAV dans le module Requêtes
Je veux obtenir le nom du fichier, le numéro de ligne et le nom de la fonction dans Python 3.4
Je veux trouver un package populaire sur PyPi
Je veux bien comprendre les bases de Bokeh
Je souhaite installer un package de Php Redis
Je souhaite augmenter la sécurité de la connexion SSH
J'ai essayé de notifier la mise à jour de "Devenir romancier" en utilisant "IFTTT" et "Devenir un romancier API"
Je ne trouve pas l'horloge tsc! ?? L'histoire d'essayer d'écrire un patch de noyau
Je souhaite prendre une capture d'écran du site sur Docker en utilisant n'importe quelle police
Je veux diviser la courbe de Bézier d'ordre n en tout point ~ Récurrence et matrice ~
J'ai essayé de trouver l'entropie de l'image avec python
Je souhaite enregistrer les photos envoyées par LINE vers S3
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow
Je veux démarrer beaucoup de processus à partir de python
Je souhaite utiliser uniquement le traitement de normalisation SudachiPy
Je veux obtenir des informations sur le fonctionnement de Yahoo Route
Je veux déterminer l'authenticité d'un élément du tableau numpy
Je souhaite envoyer un message de Python à LINE Bot
Comment trouver le coefficient de mise à l'échelle d'une ondelette bipolaire
Je souhaite produire une carte thermique magnifiquement personnalisée de la matrice de corrélation. édition matplotlib
Je souhaite mapper le code EDINET et le numéro de valeur
Keras Je veux obtenir la sortie de n'importe quelle couche !!
Je veux connaître la légende du monde des technologies informatiques
Je veux créer un Dockerfile pour le moment.
[Python] Un programme pour trouver le nombre de pommes et d'oranges qui peuvent être récoltées
Je veux obtenir des informations de fstab à la destination de la connexion ssh et exécuter la commande
Une histoire sur l'écriture d'AWS Lambda et de devenir un peu accro aux valeurs par défaut des arguments Python
J'ai créé un robot Line qui devine le sexe et l'âge d'une personne à partir de l'image
J'ai essayé de trouver la différence entre A + = B et A = A + B en Python, alors notez
[Twitter] Je veux faire des tweets téléchargés (de mon compte) dans un beau CSV
[Pytorch] Je souhaite attribuer manuellement les paramètres d'entraînement du modèle
Je veux trouver automatiquement des pièces de haute qualité à partir des vidéos que j'ai tournées
J'ai créé une bibliothèque Python pour appeler l'API de LINE WORKS
Je veux lire la version html de la version "OpenCV-Python Tutorials" OpenCV 3.1
[Introduction à Python] J'ai comparé les conventions de nommage de C # et Python.
[Introduction à StyleGAN] J'ai joué avec "The Life of a Man" ♬
Je veux sortir le début du mois prochain avec Python
Je veux créer un système pour éviter d'oublier de serrer la clé 1