obtenir plus proche point à la ligne
J'aimerais avoir un avant droite C# fonction permettant d'obtenir un point le plus proche (à partir d'un point P) un segment AB. Une fonction abstraite peut ressembler à ceci. J'ai recherche à travers ce qu'mais ne trouve pas utilisable (par moi) de la solution.
public Point getClosestPointFromLine(Point A, Point B, Point P);
- Qu'entendez-vous par "pour obtenir un point le plus proche (à partir d'un point P)"? Voulez-vous le point sur le segment de la ligne qui se trouve aussi près que possible de P?
- Connexes: la plus courte distance entre un point et un segment de ligne (Pas le même.)
- Semble être un point sur AB qui est sur la perpendiculaire en P sur AB.
- Comment vos données sont stockées, dans un graphique? base de données ? référence linéaire ?
- Je veux faire un point sur le segment de ligne AB, qui est aussi proche que possible du point d', P. je crois qu'il n'est pas lié à des données stockées, je suppose. J'ai vu que par rapport post, @Bill, mais je ne peux pas comprendre comment obtenir mon exigence d'elle.
- IL N'EST PAS DE DEVOIRS. C'est un programmeur de la question dont le calcul est mauvais.
- Notez que si l'objectif réel est de savoir si la distance du point à la ligne est inférieur/supérieur à un montant donné, il y a des binaires de recherche, des approches qui sera beaucoup plus rapide pour la plupart des cas, que la détermination absolue de point le plus proche sur la ligne, puis calculer sa distance à P.
Vous devez vous connecter pour publier un commentaire.
Voici Ruby déguisé en Pseudo-Code, en supposant
Point
objets ont chacun unx
ety
champ.Sinon:
De Ligne de Ligne de Intersection, sur Wikipédia. Tout d'abord, trouver Q, qui est un deuxième point qui est d'un pas de P dans la "bonne direction". Cela nous donne quatre points.
La mise en cache, de Sauter des étapes, etc. est possible, pour des raisons de performances.
getClosestPointFromLine()
devrait être:return Point.new (:x => ((A.x*B.y - A.y*B.x)*(P.x - Q.x) - (A.x-B.x)*(P.x*Q.y - P.y*Q.x)) / ((A.x - B.x)*(P.y-Q.y) - (A.y - B.y)*(P.x-Q.x)), :y => ((A.x*B.y - A.y*B.x)*(P.y - Q.y) - (A.y-B.y)*(P.x*Q.y - P.y*Q.x)) / ((A.x - B.x)*(P.y-Q.y) - (A.y - B.y)*(P.x-Q.x)) )
getClosestPointFromLine()
devrait être:return Point.new (:x => ((A.x*B.y - A.y*B.x)*(P.x - Q.x) - (A.x-B.x)*(P.x*Q.y - P.y*Q.x)) / ((A.x - B.x)*(P.y-Q.y) - (A.y - B.y)*(P.x-Q.x)), :y => ((A.x*B.y - A.y*B.x)*(P.y - Q.y) - (A.y-B.y)*(P.x*Q.y - P.y*Q.x)) / ((A.x - B.x)*(P.y-Q.y) - (A.y - B.y)*(P.x-Q.x)) )
Le problème peut être trouvée dans le dernier arc-boutée termes de l'x et de l'axe de la composante du nouveau point. Voir: Wikipédiasi quelqu'un est intéressé par un C# XNA fonctionnement basé sur la ci-dessus:
Votre point
X
) sera une combinaison linéaire de pointsA
etB
:Pour
X
être fait sur le segment de ligne, le paramètrek
doit être comprise entre 0 et 1 inclus. Vous pouvez calculer k comme suit:(où la période dénote le produit scalaire)
Ensuite, assurez-vous que le point est fait sur le segment de ligne:
La réponse de Justin L. est presque bien, mais il ne vérifie pas si la distance normalisée est inférieur à 0 ou supérieur à l'AB, l'amplitude du vecteur. Ensuite, il ne fonctionne pas bien lorsque le vecteur P proyection est en dehors des limites (à partir du segment AB).
Voici le corrigé de pseudo:
J'ai écrit cela il y a longtemps, il n'est pas très différent de ce que les autres ont dit, mais c'est un copier/coller de la solution en C# si vous avez une classe (ou structure) nommé
PointF
avec les membresX
etY
:Mise à jour: en Regardant les commentaires on dirait que j'ai adapté à C# à partir du même code source mentionnée dans la accepté de répondre.
if (t > 1) t = 1; if (t < 0) t = 0;
à assurez-vous que le point se trouve vraiment sur le segmentTrouver la pente a1 de l'AB en divisant l'axe de différence avec le x-différence; puis tracez une ligne perpendiculaire (avec une pente a2 = -1/a1, vous devez résoudre pour l'offset (b2) en posant P de coordonnées en y = a2*x + b2); ensuite, vous avez deux lignes (c'est à dire deux équations linéaires), et vous avez besoin pour résoudre l'intersection. Qui sera le plus proche de votre point.
Faire le droit de mathématiques, et la fonction va être assez trivial à écrire.
Pour développer un peu:
Espère que je n'ai pas loupé quelque part 🙂 mise à JOUR bien sûr je l'ai fait. Servir de moi pour ne pas travailler les choses sur le papier d'abord. Je mérite tous les downvote, mais je l'ai attendu quelqu'un pour me corriger. Fixe (je l'espère).
Flèches indiquent le chemin.
Mise à JOUR Ah, le coin des cas. Oui, certaines langues ne gère pas les infinités bien. J'ai dit que la solution était la langue-gratuit...
Vous pouvez vérifier les cas particuliers, ils sont assez facile. La première est lorsque le x différence est de 0. Cela signifie que la ligne est verticale, et le point le plus proche est sur une surface horizontale perpendiculaire. Ainsi,
x = Ax, y = Px
.La deuxième, c'est quand y de différence est de 0, et le contraire est vrai. Ainsi,
x = Px, y = Ay
Py
avecP.Y
, ajouter des déclarations appropriées et autres).Cette réponse est fondée sur les idées de la géométrie projective.
Calculer le produit vectoriel (Ax,Ay,1)×(Bx,By,1)=(u,v,w). Le vecteur résultant décrit la ligne reliant A et B: on a l'équation ux+vy+w=0. Mais vous pouvez aussi l'interpréter (u,v,0) comme un point infiniment loin de là, dans une direction perpendiculaire à cette ligne. Faire une autre croix produit, vous obtenez la ligne joignant hat point de P: (u,v,0)×(Px,Py,1). Et à l'intersection de cette ligne avec la ligne AB, vous faites un autre produit vectoriel: ((u,v,0)×(Px,Py,1))×(u,v,w). Le résultat sera un vecteur de coordonnées homogènes (x,y,z) à partir de laquelle vous pouvez lire les coordonnées de ce point le plus proche de (x/z,y/z).
Prendre le tout et vous obtenez la formule suivante:
À l'aide d'un système de calcul formel, vous pouvez obtenir les coordonnées suivantes:
Comme vous le remarquez, il y a beaucoup de termes qui reviennent. Inventer (assez bien arbitraire) de noms de ces, vous pouvez profiter du résultat final, écrit en pseudo-code:
Avantages de cette approche:
Le point le plus proche de
C
sera sur une ligne dont la pente est de l'inverse de AB et qui coupeP
. Cela sonne comme il pourrait être de devoirs, mais je vais vous donner quelques jolies de forts relents, dans l'ordre croissant de spoiler-niveau d'alerte:Il peut y avoir une seule ligne de ce type.
C'est un système de deux équations. Juste pour résoudre
x
ety
.Dessiner un segment de ligne entre
A
etB
; appel de cetteL
. L'équation pourL
esty = mx + b
, oùm
est le ratio de l'axe des coordonnées pour les abscisses. Pour résoudreb
en utilisant soitA
ouB
dans l'expression.Faire la même chose que ci-dessus, mais pour
CP
. Maintenant résoudre simultanément le système linéaire d'équations.Une recherche sur Google vous donnera une foule d'exemples à choisir.
Ici sont des méthodes d'extension qui devrait faire l'affaire:
Puis il suffit d'appeler:
Pour obtenir la distance du point "P" de la ligne |AB|. Il devrait être facile de modifier cela pour
PointF
.Trouver le point le plus proche puis c'est juste une question de recherche de la distance minimale.
LINQ
a des méthodes pour cela.Dans le cas où quelqu'un est à la recherche d'un moyen de le faire avec Java + LibGdx:
De l'algorithme serait assez facile:
vous avez 3 points - triangle. De là, vous devriez être en mesure de trouver AB, AC, BC.
Theck ceci:
http://www.topcoder.com/tc?d1=tutorials&d2=geometry1&module=Static#line_point_distance