La plus courte distance entre un point et un segment de ligne
J'ai besoin d'une fonction de base pour trouver la plus courte distance entre un point et un segment de ligne. N'hésitez pas à écrire la solution dans la langue que vous voulez, je peux le traduire dans ce que je suis en utilisant (Javascript).
EDIT: Mon segment de ligne est définie par deux points de terminaison. Donc, mon segment de ligne AB
est définie par les deux points A (x1,y1)
et B (x2,y2)
. J'essaie de trouver la distance entre ce segment de ligne et un point C (x3,y3)
. Mon géométrie compétences sont rouillées, de sorte que les exemples que j'ai vu sont à confusion, je suis désolé de l'avouer.
- Je ne sais pas comment vous êtes représentant les lignes et les points, mais ici c'est toutes les mathématiques vous avez besoin pour commencer. Ne devrait pas être trop dur de comprendre ce que vous devez faire.
- Est la réponse à cette question peut être fixe ou changé ? Le courant n'est pas la question (segment), mais pour une ligne.
- que le lien est mort, mais j'ai trouvé une copie: paulbourke.net/geometry/pointline
- Dû chercher moi-même & suis tombé sur ce que Google -- si quelqu'un est à la recherche d'une mise en œuvre & pouvez aller avec Python, Galbées a cette. Vous êtes à la recherche pour le
LineString
classe pour le chemin d'accès. - que le lien est mort aussi, mais semblable ce lien fonctionne: paulbourke.net/geometry/pointlineplane
- Si quelqu'un est à la recherche de la distance entre un point et une ligne, pas un point et un SEGMENT de ligne, suivez ce lien: gist.github.com/rhyolight/2846020
- Le lien ci-dessus est mort. Voici le pseudo-code en c++ exemple, expliqué et dérivés comme détaillé comme un manuel, geomalgorithms.com/a02-_lines.html
- brilliant.org/wiki/...
Vous devez vous connecter pour publier un commentaire.
Eli, le code que vous avez installés sur est incorrect. Un point près de la ligne sur laquelle le segment se trouve, mais de loin l'une des extrémités du segment peut être mal jugé à proximité du segment.mise à Jour: La réponse incorrecte mentionné n'est plus accepté un.Voici quelques bon code en C++. Il suppose une classe de 2D-vecteur
class vec2 {float x,y;}
, essentiellement, avec des opérateurs pour ajouter, subract, échelle, etc, et à une distance et point en fonction du produit (c'est à direx1 x2 + y1 y2
).EDIT: j'avais besoin d'un Javascript de mise en œuvre, si elle est ici, sans dépendances (ou des commentaires, mais c'est un port direct de la ci-dessus). Les Points sont représentés comme des objets avec
x
ety
attributs.EDIT 2: j'ai besoin d'une version de Java, mais le plus important, j'ai besoin d'en 3d au lieu de 2d.
==
?p
sur une ligne du point sur la ligne la plus prochep
. (Et une perpendiculaire à la ligne à la projection sera de passer à traversp
.) Le nombret
est dans quelle mesure le long du segment de ligne dev
àw
que la projection des chutes. Donc, sit
est 0 la projection tombe à droite surv
; si c'est 1, c'est surw
; si elle est de 0,5, par exemple, il est à mi-chemin entre les deux. Sit
est inférieure à 0 ou supérieure à 1, il tombe sur la ligne après une extrémité ou l'autre du segment. Dans ce cas, la distance du segment sera la distance à la plus proche de la fin.p = (0.0001, 0.0)
,v = (0.0, 0.0)
,w = (0.004, 0.0)
, il retourne1.3552527156068805e-20
(voir jsfiddle: jsfiddle.net/qg0zerkc). Est-ce un virgule flottante problème de stabilité?projection
. Depuis la distance à partir dep
à la lignev,w
est égal àsqrt(|p-v|^2 - (|w-v|*t)^2)
. Donc les 2 dernières lignes de l'implémentation c++ peut être remplacé parreturn sqrt(length_squared(p, v) - l2 * (t * t));
t
, il n'y a pas besoin de calculer le reste de la formule, vous savez déjà que vous avez besoin de la distance entrep
etv
ouw
.Ici est la plus simple complet code en Javascript.
x, y est votre cible et x1, y1 et x2, y2 est votre segment de ligne.
Mise à JOUR: correction de longueur 0 problème de lignes de commentaires.
if (param > 1)
devrait êtreif(param>len_sq)
. Tout un?C'est une application faite pour les FINIS des SEGMENTS de LIGNE, pas à l'infini des lignes comme la plupart des autres fonctions semblent être (c'est pourquoi j'ai fait cela).
La mise en œuvre de la théorie de Paul Bourke.
Python:
AS3:
Java
distAnother(0, 0, 4, 0, 2, 2)
donne 2.8284271247461903 (incorrect).distAnother(0., 0., 4., 0., 2., 2.)
donne 2.0 (correct). S'il vous plaît être conscient de cela. Je pense que le code peut être amélioré pour avoir flotteur de conversion quelque part.Dans ma propre question thread comment calculer la plus courte 2D distance entre un point et un segment de ligne dans tous les cas en C, C# /.NET 2.0 ou Java? m'a demandé de mettre un C# réponse ici quand j'en trouve un: ici, c'est modifié à partir de http://www.topcoder.com/tc?d1=tutorials&d2=geometry1&module=Statique :
Je suis @SI ne pas répondre, mais de poser des questions donc j'espère que je ne reçois pas les millions de votes contre, pour certaines raisons, mais la construction de critique. Je voulais juste (et encouragé) à part de quelqu'un d'autre idées, car les solutions dans ce fil sont soit avec exotiques de la langue (Fortran, Mathematica) ou marqués comme défectueux par quelqu'un. La seule utile (par Grumdrig) pour moi, c'est écrit en C++ et personne n'a marqué défectueux. Mais il manque les méthodes (dot etc.) qui sont appelés.
En F#, la distance entre le point
c
pour le segment de ligne entrea
etb
est donnée par:Le vecteur
d
points dea
àb
le long du segment de ligne. Le produit scalaire ded/s
avecc-a
donne le paramètre du point de plus grande approche entre l'infini de la ligne et le pointc
. Lemin
etmax
fonction sont utilisées pour la fixation de ce paramètre pour la gamme0..s
de sorte que le point se trouve entrea
etb
. Enfin, la longueur dea+p-c
est la distance à partir dec
de point le plus proche sur le segment de ligne.Exemple d'utilisation:
(a + p - c).Length
lambda
etp
commelet lambda = (c - a) * d / (s * s)
etlet p = a + (lambda |> max 0.0 |> min 1.0) * d
, respectivement. Après que la fonction renvoie la distance correcte, par exemple, pour le cas oùa = (0,1)
,b = (1,0)
etc = (1,1)
.Dans Mathematica
Il utilise une représentation paramétrique de la description de l'activité et des projets le point dans la ligne définie par le segment. Comme le paramètre passe de 0 à 1 dans le segment, si la projection est en dehors de cette limite, nous calculons la distance correspondant à l'enpoint, au lieu de la ligne droite normale au segment.
Tracé résultat:
Parcelle de ces points plus proches que d'un distance limite:
Tracé De Contour:
Pour toute personne intéressée, voici une simple conversion de Josué du code Javascript à Objective-C:
J'avais besoin de cette solution fonctionne avec
MKMapPoint
donc je vais le partager au cas où quelqu'un d'autre en a besoin. Juste quelques changements mineurs et ce sera le retour de la distance en mètres :Hey, j'ai juste écrit ça hier. C'est dans Actionscript 3.0, qui est fondamentalement Javascript, bien que vous pourriez ne pas avoir la même classe Point.
Aussi, il est très complet et lisible de la discussion du problème ici: notejot.com
Pour les paresseux, voici mon Objective-C port de @Grumdrig la solution ci-dessus:
return dist2(p, CGPointMake(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y)))
sqrtf(x) = x*x
.N'a pas pu résister de codage en python 🙂
Idem pour le fortran 🙂
Ici est une information plus complète sur l'orthographe de Grumdrig de la solution. Cette version renvoie également le point le plus proche de lui-même.
Envisager cette modification à Grumdrig la réponse ci-dessus. Plusieurs fois, vous verrez que virgule flottante imprécision peut causer des problèmes. Je suis en utilisant un double dans la version ci-dessous, mais vous pouvez facilement changer de flotteurs. L'important, c'est qu'il utilise un epsilon pour gérer la "pâtée". En outre, vous aurez beaucoup de temps voulez savoir d'OÙ l'intersection est passé, ou si c'est arrivé à tous. Si le retour de t < 0.0 ou > 1.0, aucune collision s'est produite. Cependant, même si aucune collision s'est produite, de nombreuses fois, vous aurez envie de savoir où le point le plus proche sur le segment de P, et donc j'utilise qx et qy de retour cet emplacement.
Une solution en ligne à l'aide de arctangents:
L'idée est de déplacer Un à (0, 0) et faire pivoter le triangle des aiguilles d'une montre pour faire C laïcs sur l'axe X,
lorsque cela arrive, Par sera la distance.
C#
Une ligne de C# (être converti en SQL)
Je suis en supposant que vous voulez trouver le plus court distance entre le point et un segment de ligne; pour ce faire, vous avez besoin de trouver la ligne (lineA) qui est perpendiculaire à votre segment de ligne (lineB) qui passe au travers de votre point, déterminer l'intersection entre la ligne (lineA) et votre ligne qui va par le biais de votre segment de ligne (lineB); si ce point est entre les deux points de votre segment de ligne, ensuite, la distance est la distance entre le point et le point que vous venez de trouver qui est l'intersection de la lineA et lineB; si le point n'est pas entre les deux points de votre segment de ligne, vous avez besoin pour obtenir la distance entre le point et le plus proche des deux extrémités du segment de ligne, ce qui peut être fait facilement en prenant le carré de la distance (pour éviter une racine carrée) entre le point et les deux points du segment de ligne; celle qui est la plus proche, prendre la racine carrée de celle-là.
Grumdrig du C++/JavaScript mise en œuvre a été très utile pour moi, j'ai donc fourni un Python direct port que j'utilise. Le code complet est ici.
Code Matlab, avec "auto-test" si on appelle la fonction sans arguments:
Et maintenant ma solution......
(Javascript)
Il est très rapide, parce que j'essaie d'éviter toute Mathématiques.pow fonctions.
Comme vous pouvez le voir, à la fin de la fonction, j'ai la distance de la ligne.
code de la lib http://www.draw2d.org/graphiti/jsdoc/#!/exemple
codé en t-sql
le point est (@px, @py) et le segment de ligne s'exécute à partir de (@ax, @ay) à (@bx, @par)
Ressemble à peu près tous les autres sur StackOverflow a contribué d'une réponse (23 réponses), voici donc ma contribution pour C#. Cela est principalement basé sur la réponse de M. Katz, qui à son tour est basé sur la réponse par Grumdrig.
Et voici un petit programme de test.
Comme vous pouvez le voir, j'ai essayé de mesurer la différence entre l'utilisation de la version qui évite la Sqrt() la méthode et la version normale. Mes tests indiquent que vous pouvez peut-être économiser environ 2,5%, mais je ne suis même pas sûr de qui - les variations dans les différentes séries de tests ont été du même ordre de grandeur. J'ai aussi essayé de mesurer la version posté par Matti (en plus d'une optimisation évidente), et cette version semble être d'environ 4% plus lente que la version basée sur Katz/Grumdrig code.
Edit: d'ailleurs, j'ai aussi essayé de la mesure d'une méthode qui trouve la distance à une ligne infinie (pas un segment de ligne) à l'aide d'un produit croisé (et un Sqrt()), et il est d'environ 32% plus rapide.
Ici est devnullicus du C++ version convertie en C#. Pour mon application j'ai besoin de savoir le point d'intersection et a trouvé sa solution fonctionne bien.
Ici, c'est l'utilisation de Swift
voir le Matlab GÉOMÉTRIE de la boîte à outils sur le site web suivant:
http://people.sc.fsu.edu/~jburkardt/m_src/geometry/geometry.html
ctrl+f et tapez "segment" pour trouver segment de la ligne, des fonctions connexes. les fonctions "segment_point_dist_2d.m" et "segment_point_dist_3d.m" sont ce que vous avez besoin.
La GÉOMÉTRIE des codes sont disponibles dans une version en C et en C++ et une version FORTRAN77 et une version FORTRAN90 et une version MATLAB version.
AutoHotkeys version basée sur Joshua Javascript:
N'ai pas vu une implémentation de Java ici, j'ai donc traduit la fonction Javascript de la accepté de répondre à de code Java:
WPF version:
C#
Adapté de @Grumdrig
Voici le code que j'ai fini par écrire. Ce code suppose qu'un point est défini dans le formulaire de
{x:5, y:7}
. Notez que ce n'est pas l'absolu moyen le plus efficace, mais c'est le plus simple et le plus facile à comprendre le code que je pouvais venir.La fonction ci-dessus n'est pas de travailler sur des lignes verticales. Voici une fonction qui est fonctionne bien!
Ligne avec les points p1, p2. et de point de contrôle est p;
Ici est la même chose que le C++ répondre, mais porté à pascal. L'ordre du point de paramètre a changé pour l'adapter à mon code, mais c'est la même chose.
Un peu plus propre solution en JavaScript basé sur ce formule:
2D et 3D solution
Envisager un changement de base tels que le segment de ligne devient
(0, 0, 0)-(d, 0, 0)
et le point de(u, v, 0)
. La distance la plus courte se produit dans l'avion et est donné par(la distance à l'une des extrémités ou à l'appui de la ligne, selon la projection de la ligne. L'iso-distance lieu est formé de deux demi-cercles et deux segments de ligne.)
Dans l'expression ci-dessus, d est la longueur du segment AB et u, v sont respectivey le produit scalaire et (module de la) croix des produits de l'AB/d (vecteur unitaire dans la direction de AB) et (AC). Donc vectorially,
Cet algorithme est basé sur la recherche de l'intersection entre la ligne spécifiée et la orthogonale de la ligne, qui contient le point spécifié, et le calcul de sa distance. Dans le cas d'un segment de ligne, nous devons vérifier si l'intersection est entre les points du segment de ligne, si ce n'est pas le cas, alors la distance minimale entre le point et l'un des points de fin de la ligne. C'est un C# de mise en œuvre.
Python Numpy mise en œuvre pour la 2D coordonner tableau:
J'ai fait un interactive Desmos graphique pour montrer comment y parvenir:
https://www.desmos.com/calculator/kswrm8ddum
Le point rouge est Un, le point vert est B et le point C est le bleu.
Vous pouvez faire glisser les points dans le graphique pour voir les changements.
Sur la gauche, la valeur " s " est le paramètre de la ligne de segment (c'est à dire s = 0 signifie que le point A, et s = 1 signifie que le point B).
La valeur de " d " est la distance entre le troisième point de la droite passant par A et B.
EDIT:
Amusant petit aperçu: les coordonnées (s, d) est la coordonnée du troisième point C dans le système de coordonnées où AB est l'unité de l'axe des x, et l'unité de l'axe y est perpendiculaire à AB.
Matlab direct Grumdrig mise en œuvre
la accepté de répondre ne fonctionne pas
(par exemple, la distance entre 0,0 et (-10,2,10,2) doit être de 2).
voici le code qui fonctionne:
Si c'est une ligne infinie, pas un segment de ligne, la façon la plus simple est la suivante (en ruby), où mx + b est la ligne et (x1, y1) est le point connu
mx1
,b
oum
et votre solution n'est pas pour des segments de ligne.Viens de tomber sur ce et j'ai pensé ajouter un Lua mise en œuvre. Il suppose que les points sont donnés sous forme de tableaux {x=xVal, y=yVal} et la ligne ou un segment est donnée par un tableau contenant deux points (voir exemple ci-dessous):
Exemple d'utilisation:
Voulu faire cela en GLSL, mais il est préférable d'éviter toutes ces conditions, si possible. À l'aide de la pince() permet d'éviter la fin de deux-point de cas:
Si vous pouvez être sûr que A et B ne sont jamais très proches les uns des autres, ce qui peut être simplifié pour supprimer le si(). En fait, même si A et B sont le même, mon GPU donne toujours le bon résultat avec cette condition-la version gratuite (mais c'est à l'aide de pré-OpenGL 4.1 en ce qui GLSL division par zéro n'est pas défini):
Pour calculer la distance est trivial -- GLSL fournit une distance() fonction que vous pouvez utiliser sur ce point le plus proche et P.
Inspiré par Iñigo Quilez code pour une capsule fonction de distance
Même que cette réponse, sauf dans Visual Basic. Le rend utilisable comme une Fonction Définie par l'Utilisateur dans Microsoft Excel et VBA/macros.
La fonction renvoie la plus petite distance à partir du point (x,y) pour le segment défini par (x1,y1) et (x2,y2)
Lua:
Trouve la distance minimale entre un segment de ligne(pas l'ensemble de la ligne) et d'un point de
Cette réponse est fondée sur la accepté de répondre às'JavaScript solution.
Il est principalement formaté plus agréable, avec en plus des noms de fonction, et des cours plus courts syntaxe de la fonction parce que c'est dans l'ES6 + CoffeeScript.
Version JavaScript (ES6)
CoffeeScript version
dans la R
En javascript à l'aide de la Géométrie:
GLSL version:
Eigen C++ Version 3D segment de ligne et de point
Voici un autonome Delphi /Pascal version de la fonction sur la base de Joshua réponse ci-dessus. Utilise TPoint pour VCL des graphiques à l'écran, mais devrait être facile à ajuster, au besoin.
Ici est celui basé sur le vecteur de mathématiques; cette solution fonctionnera aussi pour les dimensions supérieures et également un rapport sur les interection point (sur le segment de ligne).
Résultat est
Le calcul est expliqué ici
https://brilliant.org/wiki/distance-between-point-and-line/