J'ai besoin d'une fonction de base pour trouver la distance la plus courte entre un point et un segment de ligne. N'hésitez pas à rédiger la solution dans la langue de votre choix; Je peux le traduire dans ce que j'utilise (Javascript).
EDIT: Mon segment de ligne est défini par deux points d'extrémité. Mon segment de ligne AB
est donc défini 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)
. Mes compétences en géométrie sont rouillées, donc les exemples que j'ai vus prêtent à confusion, je suis désolé de l'admettre.
language-agnostic
geometry
distance
line-segment
Eli Courtwright
la source
la source
Réponses:
Eli, le code que vous avez choisi est incorrect. Un point proche de la ligne sur laquelle se trouve le segment mais éloigné d'une extrémité du segment serait incorrectement jugé près du segment.Mise à jour: La réponse incorrecte mentionnée n'est plus celle acceptée.Voici du code correct, en C ++. Il suppose un vecteur 2D de classe
class vec2 {float x,y;}
, essentiellement, avec des opérateurs pour ajouter, soustraire, mettre à l'échelle, etc., et une fonction de produit de distance et de point (c.x1 x2 + y1 y2
-à-d.).EDIT: J'avais besoin d'une implémentation Javascript, alors la voici, sans dépendances (ni commentaires, mais c'est un port direct de ce qui précède). Les points sont représentés comme des objets avec
x
et desy
attributs.EDIT 2: J'avais besoin d'une version Java, mais plus important, j'en avais besoin en 3D au lieu de 2D.
la source
p
sur une ligne est le point de la ligne le plus proche dep
. (Et une perpendiculaire à la ligne à la projection passer à traversp
.) Le nombret
est la distance le long du segment de ligne à partirv
dew
ce que la saillie diminue. Donc, sit
est 0, la projection tombe droit surv
; si c'est 1, c'est alluméw
; si c'est 0,5, par exemple, c'est à mi-chemin. Sit
est inférieur à 0 ou supérieur à 1, il tombe sur la ligne au-delà d'une extrémité ou de l'autre du segment. Dans ce cas, la distance au segment sera la distance à l'extrémité la plus proche.Voici le code complet le plus simple en Javascript.
x, y est votre point cible et x1, y1 à x2, y2 est votre segment de ligne.
MISE À JOUR: correction du problème de ligne de longueur 0 à partir des commentaires.
la source
Ceci est une implémentation faite pour les SEGMENTS DE LIGNE FINITE, pas des lignes infinies comme la plupart des autres fonctions ici semblent l'être (c'est pourquoi j'ai fait cela).
Mise en œuvre de la théorie par Paul Bourke .
Python:
AS3:
Java
la source
distAnother(0, 0, 4, 0, 2, 2)
donne 2,8284271247461903 (incorrect).distAnother(0., 0., 4., 0., 2., 2.)
donne 2.0 (correct). Veuillez en être conscient. Je pense que le code peut être amélioré pour avoir une conversion flottante quelque part.Dans mon propre fil de question, comment calculer la distance 2D la plus courte entre un point et un segment de ligne dans tous les cas en C, C # / .NET 2.0 ou Java? On m'a demandé de mettre une réponse C # ici quand j'en trouve une: la voici donc, modifiée à partir de http://www.topcoder.com/tc?d1=tutorials&d2=geometry1&module=Static :
Je suis @SO pour ne pas répondre mais poser des questions, donc j'espère que je n'obtiendrai pas des millions de votes négatifs pour certaines raisons, mais que je construis un critique. Je voulais juste (et j'ai été encouragé) partager les idées de quelqu'un d'autre car les solutions de ce fil sont soit avec un langage exotique (Fortran, Mathematica), soit marquées comme défectueuses par quelqu'un. Le seul utile (par Grumdrig) pour moi est écrit avec C ++ et personne ne l'a étiqueté défectueux. Mais il manque les méthodes (point etc.) qui sont appelées.
la source
En F #, la distance du point
c
au segment de ligne entrea
etb
est donnée par:Le vecteur
d
pointe dea
à leb
long du segment de ligne. Le produit scalaire ded/s
avecc-a
donne le paramètre du point d'approche le plus proche entre la ligne infinie et le pointc
. La fonctionmin
etmax
sont utilisées pour fixer ce paramètre à la plage de0..s
sorte que le point se situe entrea
etb
. Enfin, la longueur dea+p-c
est la distance duc
point le plus proche sur le segment de ligne.Exemple d'utilisation:
la source
(a + p - c).Length
lambda
etp
aslet lambda = (c - a) * d / (s * s)
etlet p = a + (lambda |> max 0.0 |> min 1.0) * d
, respectivement. Après cela, la fonction renvoie la distance correcte, par exemple pour le cas oùa = (0,1)
,b = (1,0)
etc = (1,1)
.Pour toute personne intéressée, voici une conversion triviale du code Javascript de Joshua en Objective-C:
J'avais besoin de cette solution pour travailler,
MKMapPoint
donc je la partagerai au cas où quelqu'un d'autre en aurait besoin. Juste quelques changements mineurs et cela retournera la distance en mètres:la source
Dans Mathematica
Il utilise une description paramétrique du segment et projette le point dans la ligne définie par le segment. Lorsque le paramètre passe de 0 à 1 dans le segment, si la projection est en dehors de ces limites, nous calculons la distance jusqu'au point de référence correspondant, au lieu de la droite normale au segment.
Résultat du tracé:
Tracez ces points plus près d'une distance de coupure :
Tracé de contour:
la source
Hé, je viens d'écrire ça hier. C'est dans Actionscript 3.0, qui est essentiellement Javascript, bien que vous n'ayez peut-être pas la même classe Point.
En outre, il y a une discussion assez complète et lisible du problème ici: notejot.com
la source
Pour les paresseux, voici mon port Objective-C de la solution de @ Grumdrig ci-dessus:
la source
return dist2(p, CGPointMake(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y)))
sqrtf(x) = x*x
.Impossible de résister au codage en python :)
Idem pour fortran :)
la source
Voici une orthographe plus complète de la solution de Grumdrig. Cette version renvoie également le point le plus proche lui-même.
la source
Solution à une ligne utilisant des arctangents:
L'idée est de déplacer A vers (0, 0) et de faire pivoter le triangle dans le sens des aiguilles d'une montre pour que C se trouve sur l'axe X, lorsque cela se produira, By sera la distance.
C #
Une ligne C # (à convertir en SQL)
la source
Considérez cette modification de la réponse de Grumdrig ci-dessus. Plusieurs fois, vous constaterez que l'imprécision en virgule flottante peut causer des problèmes. J'utilise des doubles dans la version ci-dessous, mais vous pouvez facilement passer aux flotteurs. La partie importante est qu'il utilise un epsilon pour gérer la "slop". De plus, vous voudrez souvent savoir OERE l'intersection s'est produite, ou si elle s'est produite. Si le t renvoyé est <0,0 ou> 1,0, aucune collision ne s'est produite. Cependant, même si aucune collision ne s'est produite, vous voudrez souvent savoir où se trouve le point le plus proche du segment à P, et donc j'utilise qx et qy pour retourner cet emplacement.
la source
Je suppose que vous voulez trouver le plus courtdistance entre le point et un segment de ligne; pour ce faire, vous devez trouver la ligne (ligne A) qui est perpendiculaire à votre segment de ligne (ligne B) qui passe par votre point, déterminer l'intersection entre cette ligne (ligne A) et votre ligne qui passe par votre segment de ligne (ligne B) ; si ce point est entre les deux points de votre segment de ligne, alors la distance est la distance entre votre point et le point que vous venez de trouver qui est l'intersection de la ligne A et de la ligne B; si le point n'est pas entre les deux points de votre segment de ligne, vous devez obtenir la distance entre votre point et le plus proche des deux extrémités du segment de ligne; cela peut être fait facilement en prenant la distance carrée (pour éviter une racine carrée) entre le point et les deux points du segment de ligne; selon ce qui est le plus proche, prenez la racine carrée de celle-ci.
la source
L'implémentation C ++ / JavaScript de Grumdrig m'a été très utile, j'ai donc fourni un port direct Python que j'utilise. Le code complet est ici .
la source
Code Matlab, avec "auto-test" intégré s'ils appellent la fonction sans argument:
la source
Et maintenant ma solution aussi ...... (Javascript)
C'est très rapide car j'essaye d'éviter toutes les fonctions Math.pow.
Comme vous pouvez le voir, à la fin de la fonction, j'ai la distance de la ligne.
le code provient de la lib http://www.draw2d.org/graphiti/jsdoc/#!/example
la source
codé en t-sql
le point est (@px, @py) et le segment de ligne s'étend de (@ax, @ay) à (@bx, @by)
la source
On dirait que presque tout le monde sur StackOverflow a contribué une réponse (23 réponses jusqu'à présent), alors voici ma contribution pour C #. Ceci est principalement basé sur la réponse de M. Katz, qui à son tour est basée sur la réponse de 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 méthode Sqrt () et la version normale. Mes tests indiquent que vous pouvez peut-être économiser environ 2,5%, mais je n'en suis même pas sûr - les variations au sein des différentes séries de tests étaient du même ordre de grandeur. J'ai également essayé de mesurer la version publiée par Matti (plus une optimisation évidente), et cette version semble être environ 4% plus lente que la version basée sur le code Katz / Grumdrig.
Edit: Par ailleurs, j'ai également essayé de mesurer une méthode qui trouve la distance à une ligne infinie (pas un segment de ligne) en utilisant un produit croisé (et un Sqrt ()), et c'est environ 32% plus rapide.
la source
Voici la version C ++ de devnullicus convertie en C #. Pour ma mise en œuvre, j'avais besoin de connaître le point d'intersection et j'ai trouvé sa solution pour bien fonctionner.
la source
Ici, il utilise Swift
la source
C #
Adapté de @Grumdrig
la source
Une solution 2D et 3D
Considérons un changement de base tel que le segment de ligne devienne
(0, 0, 0)-(d, 0, 0)
et le point(u, v, 0)
. La distance la plus courte se produit dans ce plan et est donnée par(la distance à l'un des points d'extrémité ou à la ligne de support, selon la projection sur la ligne. Le locus iso-distance est composé de deux demi-cercles et de deux segments de ligne.)
Dans l'expression ci-dessus, d est la longueur du segment AB, et u, v sont respectivement le produit scalaire et (module du) produit croisé de AB / d (vecteur unitaire dans la direction de AB) et AC. D'où vectorialement,
la source
voir la boîte à outils Matlab GEOMETRY sur le site Web suivant: http://people.sc.fsu.edu/~jburkardt/m_src/geometry/geometry.html
ctrl + f et tapez "segment" pour trouver les fonctions liées au segment de ligne. les fonctions "segment_point_dist_2d.m" et "segment_point_dist_3d.m" sont ce dont vous avez besoin.
Les codes GÉOMÉTRIE sont disponibles en version C et en version C ++ et en version FORTRAN77 et en version FORTRAN90 et en version MATLAB.
la source
Version AutoHotkeys basée sur le Javascript de Joshua:
la source
Je n'ai pas vu d'implémentation Java ici, j'ai donc traduit la fonction Javascript de la réponse acceptée au code Java:
la source
Version WPF:
la source
Voici le code que j'ai fini par écrire. Ce code suppose qu'un point est défini sous la forme de
{x:5, y:7}
. Notez que ce n'est pas le moyen le plus efficace, mais c'est le code le plus simple et le plus facile à comprendre que j'ai pu trouver.la source
La fonction ci-dessus ne fonctionne pas sur les lignes verticales. Voici une fonction qui fonctionne bien! Ligne avec les points p1, p2. et CheckPoint est p;
la source
Voici la même chose que la réponse C ++ mais portée sur pascal. L'ordre du paramètre point a changé pour s'adapter à mon code mais c'est la même chose.
la source