Disons que vous avez un plan à deux dimensions avec 2 points (appelés a et b) représentés par un entier x et un entier ay pour chaque point.
Comment pouvez-vous déterminer si un autre point c est sur le segment de droite défini par a et b?
J'utilise le plus python, mais des exemples dans n'importe quel langage seraient utiles.
Réponses:
Vérifiez si le produit croisé de (ba) et (ca) est 0, comme le dit Darius Bacon, vous indique si les points a, b et c sont alignés.
Mais, comme vous voulez savoir si c est compris entre a et b, vous devez également vérifier que le produit scalaire de (ba) et (ca) est positif et est inférieur au carré de la distance entre a et b.
En pseudocode non optimisé:
la source
-epsilon < crossproduct < epsilon and min(a.x, b.x) <= c.x <= max(a.x, b.x) and min(a.y, b.y) <= c.y <= max(a.y, b.y)
est-ce suffisant, n'est-ce pas?Voici comment je procéderais:
la source
-epsilon < (distance(a, c) + distance(c, b) - distance(a, b)) < epsilon
==
est une mauvaise chose pour les flotteurs dans la plupart des cas .math.isclose()
pourrait être utilisé à la place. Il n'ymath.isclose()
en avait pas en 2008 et j'ai donc fourni l'inégalité explicite avecepsilon
(abs_tol
enmath.isclose()
parlant).Vérifiez si le produit croisé de
b-a
etc-a
est0
: cela signifie que tous les points sont colinéaires. Si c'est le cas, vérifiez sic
les coordonnées de s sont comprises entrea
les s etb
les. Utilisez les coordonnées x ou y, tant quea
etb
sont séparés sur cet axe (ou ils sont identiques sur les deux).Cette réponse était un gâchis de trois mises à jour. Les informations intéressantes de leur part: le chapitre de Brian Hayes dans Beautiful Code couvre l'espace de conception d'une fonction de test de colinéarité - contexte utile. La réponse de Vincent a contribué à améliorer celle-ci. Et c'est Hayes qui a suggéré de tester une seule des coordonnées x ou y; à l'origine, le code avait
and
à la place deif a.x != b.x else
.la source
Voici une autre approche:
Le point C (x3, y3) se situera entre A et B si:
la source
La longueur du segment n'est pas importante, donc l'utilisation d'une racine carrée n'est pas nécessaire et doit être évitée car nous pourrions perdre une certaine précision.
Quelques exemples aléatoires d'utilisation:
la source
==
enis_between()
pouvait manquer (BTW il est un CrossProduct déguisé).is_between()
:a, b = self.a, self.b
Voici une manière différente de procéder, avec du code donné en C ++. Étant donné deux points, l1 et l2, il est trivial d'exprimer le segment de ligne entre eux comme
où 0 <= A <= 1. Ceci est connu comme la représentation vectorielle d'une ligne si cela vous intéresse plus que de l'utiliser pour ce problème. Nous pouvons séparer les composantes x et y de ceci, en donnant:
Prenez un point (x, y) et remplacez ses composantes x et y dans ces deux expressions pour résoudre A. Le point est sur la ligne si les solutions pour A dans les deux expressions sont égales et 0 <= A <= 1. Parce que la résolution de A nécessite une division, il existe des cas particuliers qui nécessitent une manipulation pour arrêter la division par zéro lorsque le segment de ligne est horizontal ou vertical. La solution finale est la suivante:
la source
En utilisant une approche plus géométrique, calculez les distances suivantes:
et testez si ac + bc est égal à ab :
C'est parce qu'il y a trois possibilités:
la source
Ok, beaucoup de mentions d'algèbre linéaire (produit croisé de vecteurs) et cela fonctionne dans un espace réel (c'est-à-dire à virgule continue ou flottante) mais la question précisait spécifiquement que les deux points étaient exprimés sous forme d' entiers et donc un produit croisé n'est pas le bon solution bien qu’elle puisse donner une solution approximative.
La bonne solution est d'utiliser l' algorithme de ligne de Bresenham entre les deux points et de voir si le troisième point est l'un des points de la ligne. Si les points sont suffisamment éloignés pour que le calcul de l'algorithme ne soit pas performant (et qu'il faudrait que ce soit vraiment grand pour que ce soit le cas), je suis sûr que vous pouvez fouiller et trouver des optimisations.
la source
Le produit scalaire entre (ca) et (ba) doit être égal au produit de leurs longueurs (cela signifie que les vecteurs (ca) et (ba) sont alignés et de même direction). De plus, la longueur de (ca) doit être inférieure ou égale à celle de (ba). Pseudocode:
la source
J'en avais besoin pour javascript à utiliser dans un canevas html5 pour détecter si le curseur de l'utilisateur était sur ou près d'une certaine ligne. J'ai donc modifié la réponse donnée par Darius Bacon en coffeescript:
la source
Vous pouvez utiliser le produit de coin et de point:
la source
Voici comment je l'ai fait à l'école. J'ai oublié pourquoi ce n'est pas une bonne idée.
ÉDITER:
@Darius Bacon: cite un livre "Beautiful Code" qui explique pourquoi le code ci-dessous n'est pas une bonne idée.
la source
Tout point sur le segment de droite ( a , b ) (où a et b sont des vecteurs) peut être exprimé comme une combinaison linéaire des deux vecteurs a et b :
En d'autres termes, si c se trouve sur le segment de droite ( a , b ):
En résolvant m , nous obtenons:
Donc, notre test devient (en Python):
la source
c # De http://www.faqs.org/faqs/graphics/algorithms-faq/ -> Sujet 1.02: Comment puis-je trouver la distance d'un point à une ligne?
la source
Voici un code Java qui a fonctionné pour moi:
la source
que diriez-vous simplement de vous assurer que la pente est la même et que le point est entre les autres?
points donnés (x1, y1) et (x2, y2) (avec x2> x1) et point candidat (a, b)
si (b-y1) / (a-x1) = (y2-y2) / (x2-x1) Et x1 <a <x2
Alors (a, b) doit être sur la ligne entre (x1, y1) et (x2, y2)
la source
Une réponse en C # utilisant une classe Vector2D
Notez que
est le produit scalaire du vecteur de segment via la surcharge d'opérateurs en C #
La clé est de profiter de la projection du point sur la ligne infinie et d'observer que la quantité scalaire de la projection nous dit trivialement si la projection est sur le segment ou non. Nous pouvons ajuster les bornes de la quantité scalaire pour utiliser une tolérance floue.
Si la projection est dans les limites, nous testons simplement si la distance entre le point et la projection est dans les limites.
L'avantage par rapport à l'approche multi-produits est que la tolérance a une valeur significative.
la source
Voici ma solution avec C # dans Unity.
la source
Version C # de la réponse de Jules:
la source
Vous pouvez le faire en résolvant l'équation de ligne pour ce segment de ligne avec les coordonnées du point, vous saurez si ce point est sur la ligne, puis en vérifiant les limites du segment pour savoir s'il est à l'intérieur ou à l'extérieur de celui-ci. Vous pouvez appliquer un certain seuil car il se trouve quelque part dans l'espace probablement défini par une valeur à virgule flottante et vous ne devez pas atteindre celui exact. Exemple en php
la source