web-dev-qa-db-fra.com

Comment vérifier si 4 points forment un carré?

Supposons que j'ai 4 points (ils sont à 2 dimensions), qui sont différents les uns des autres, et je veux savoir s'ils forment un carré. Comment faire? (que le processus soit aussi simple que possible.)

35
MarshalSHI

En supposant que votre carré puisse être tourné par rapport au système de coordonnées que vous avez en place, vous ne pouvez pas compter sur la répétition des valeurs X et Y dans vos quatre points.

Ce que vous pouvez faire, c'est calculer les distances entre chacun des quatre points. Si vous trouvez que ce qui suit est vrai, vous avez un carré:

  1. Il y a deux points, disons A et C qui sont la distance x l'un de l'autre, et deux autres points, disons B et D qui sont aussi la distance x de L'une et l'autre.

  2. Chaque point {A, B, C, D} est à égale distance des deux points qui ne sont pas x éloignés. Par exemple: si A est x loin de C, alors il sera z loin de B et D.

Par ailleurs, la distance z devra être SQRT (( x ^ 2)/2), mais vous n'avez pas besoin de le confirmer. Si les conditions 1 et 2 sont vraies, alors vous avez un carré.  REMARQUE: Certaines personnes s'inquiètent de l'inefficacité de la racine carrée. Je n'ai pas dit que vous devriez faire ce calcul, je viens de dire que si vous le faisiez, vous obtiendriez un résultat prévisible!

Illustration of Square Rules

Le strict minimum de travail que vous auriez à faire serait de choisir un point, disons A et de calculer la distance à chacun des trois autres points. Si vous pouvez trouver que A est x à partir d'un point et z à partir de deux autres points, alors il vous suffit de vérifier ces deux autres points l'un par rapport à l'autre. S'ils sont également x les uns des autres, alors vous avez un carré. c'est à dire.:

  • AB = z
  • AC = x
  • AD = z

Puisque AB = AD, vérifiez BD:

  • BD = x

Pour être sûr, vous devez vérifier les autres côtés: BC et CD.

  • BC = z
  • CD = z

Puisque AC = BD et puisque AB = AD = BC = CD, il s'agit donc d'un carré.

En cours de route, si vous trouvez plus de deux distances Edge distinctes, la figure ne peut pas être un carré, vous pouvez donc arrêter de regarder.


Exemple d'implémentation de travail

J'ai créé un exemple de travail sur jsfiddle (voir ici ). Dans mon explication de l'algorithme, j'utilise des points arbitraires A, B, C et D. Ces points arbitraires se trouvent être dans un certain ordre pour parcourir l'exemple. L'algorithme fonctionne même si les points sont dans un ordre différent, cependant, l'exemple ne fonctionne pas nécessairement si ces points sont dans un ordre différent.


Merci à: meshuai, Blrfl, MSalters et Bart van Ingen Schenau pour leurs commentaires utiles afin d'améliorer cette réponse.

65
Joel Brown

Choisissez trois des quatre points.

Déterminez s'il s'agit d'un triangle isocèle droit en vérifiant si l'un des trois vecteurs entre les points est égal à un autre tourné de 90 degrés.

Si c'est le cas, calculez le quatrième point par addition vectorielle et comparez-le au quatrième point donné.

Notez que cela ne nécessite pas de racines carrées coûteuses, pas même de multiplication.

24
starblue

Je pense que la solution la plus simple est la suivante:

  • Calculez d'abord le centre des 4 points: center = (A + B + C + D)/4

  • Calculez ensuite le vecteur A - center. Que ce soit v := (x,y)

  • Soit v2 Le vecteur v tourné de 90 degrés: v2 := (-y, x)

  • Maintenant, les autres points devraient être center - v, center + v2 Et center - v2.

L'avantage de cette solution est que vous n'avez pas du tout besoin d'utiliser des racines carrées.

17
Elian Ebbing

Je suis désolé mais certaines réponses ne s'appliquent pas.

Dans le cas où vous mesurez 3 bords (disons AB, AC et AD) pour trouver que deux ont la même taille (disons AC et AD) et un est plus grand (disons AB). Ensuite, vous mesureriez CD pour voir si elle est de la même taille que AB, et vous vous rendez compte qu'elle l'est. Au lieu d'un carré, vous pouvez avoir l'image ci-dessous, ce qui en fait une mauvaise solution.

Not a square...

Ensuite, vous essayez une autre solution: mesurez toutes les distances au moins une fois: AB, AC, AD, BC, BD, CD. Ensuite, vous trouvez que 4 d'entre eux sont égaux, et les 2 autres sont également égaux entre eux. Mais vous pourriez juste avoir une image comme ci-dessous:

And that's not a square, too...

Donc, ces réponses ne sont pas correctes, malgré les votes positifs élevés qu'ils ont reçus.

Une solution possible: si les deux mesures égales ne relient pas le même point. Donc: si AB et CD ont la même longueur, toutes les autres combinaisons (AC, AD, BC, BD) sont également égales, vous avez un carré. Si vous avez le même point faisant la plus grande longueur (AB et AC est le plus grand, et tous les autres sont égaux), vous avez l'une des images ci-dessus.

5
woliveirajr

Soit les quatre points des vecteurs de coordonnées a, b, c, d.

Appelons ensuite leurs différences w = (a-d), x = (b-a), y = (c-b), z = (d-c).

Ensuite, w est orthogonal à a si vous pouvez créer w à partir d'une rotation de 90 degrés. Mathématiquement, la matrice de rotation à 90 degrés dans 2 espaces est ((0, -1), (1, 0)). Ainsi, la condition que w soit une rotation de 90 degrés a entraîne

(w_1 == -x_2 et w_2 == x_1)

Si tel est le cas, vous devez vérifier que w == -y et x == -z, ou

((w_1 == -y_1 et w_2 == -y_2) et (x_1 == -z_1 et x_2 == -z_2))

Si ces trois relations se vérifient, a, b, c, d forment un carré orienté.

3
Mark Salzer

Je pense que vous pouvez le faire avec une simple addition et soustraction et en trouvant min/max. Termes (correspond au diagramme des autres):

  • Point avec la valeur y la plus élevée => A
  • le plus haut x => B
  • y le plus bas => C
  • le plus bas x => D

Si 4 points partagent seulement 2 valeurs x et 2 valeurs y, vous avez un carré de niveau.

Sinon, vous avez un carré si vos points satisfont aux critères suivants:

  • A.x + C.x = B.x + D.x
  • A.y + C.y = B.y + D.y
  • A.y - C.y = B.x - D.x

Explication: Les segments de ligne A-C et B-D doivent se rencontrer à leur milieu. Ainsi (A.x + C.x)/2 est le milieu de A-C et (B.x + D.x)/2 est le milieu de B-D. Multipliez chaque côté de cette équation par 2 pour obtenir ma première équation. La deuxième équation est la même chose pour les valeurs Y. Les losanges (rhomboïdes) satisferont ces propriétés, vous devez donc vérifier que vous avez des côtés égaux - que la largeur est la même que la hauteur. Voilà la troisième équation.

2
GlenPeterson

Similaire à la réponse de starblue

Choisissez trois des quatre points.

Recherchez un sommet à angle droit parmi eux: En vérifiant si le produit scalaire de deux des trois vecteurs est nul. S'il n'est pas trouvé, pas un carré.

Vérifiez si les sommets adjacents à cet angle sont également à angle droit. Sinon, pas un carré.

Vérifiez si les diagonales sont perpendiculaires: Si le produit scalaire des vecteurs entre le premier et le quatrième sommet et les deux autres sommets (diagonales) est nul, alors c'est un carré.

2
Max

enter image description here

Il y a de bonnes réponses ici, mais la question demandait l'approche la plus simple. J'y ai réfléchi rapidement et voici comment je le ferais.

Vous pouvez dire si quatre points représentent un carré (même s'il est tourné), mais trouver la moyenne des quatre points.

R = (A+B+C+D)/4

Une fois que vous avez la moyenne, la distance entre chaque point et la moyenne devrait être la même pour les quatre points.

if(dist(R,A) == dist(R,B) == dist(R,C) == dist(R,D) then
   print "Is Square"
else
   print "Is Not Square"

MODIFIER:

Mon erreur. Cela ne vous dirait que si les points du formulaire étaient sur un cercle. Si vous vérifiez également la distance entre les points, ce doit être un carré.

if(dist(R,A) == dist(R,B) == dist(R,C) == dist(R,D) AND
  (dist(A,B) == dist(B,C) == dist(C,D) == dist(A,D) then
   print "Is Square"
else
   print "Is Not Square"

Cela suppose que les points A, B, C, D ne se croisent pas (comme dans un ordre d'enroulement valide).

2
Reactgular

ce n'est pas une réponse selon les normes établies, mais j'espère que cela aide:

[Copié à partir du lien ci-dessous afin que vous n'ayez pas à ouvrir le lien] Python 76 caractères

def S(A):c=sum(A)/4.0;return set(A)==set((A[0]-c)*1j**i+c for i in range(4))

La fonction S prend une liste de nombres complexes comme entrée (A). Si nous connaissons à la fois le centre et un coin d'un carré, nous pouvons reconstruire le carré en tournant le coin de 90 180 et 270 degrés autour du point central (c). Sur le plan complexe, la rotation de 90 degrés autour de l'origine se fait en multipliant le point par i. Si notre forme d'origine et le carré reconstruit ont les mêmes points, cela doit être un carré.

Cela a été tiré de: Déterminez si 4 points forment un carré

Si vous aimez la réponse, je dis, prenez quelques instants pour remercier la personne ou votez pour sa réponse sur cette page.

1
bad_keypoints

Idée de base (cela répond à la question de savoir si je contribuais quelque chose de nouveau, qui a été posée par le bot lorsque j'ai cliqué pour fournir une réponse):

  • un losange avec des diagonales égales est un carré.
  • "aussi simple que possible" comprend:
    • pas de division,
    • pas de racines carrées,
    • pas de ramification,
    • pas de recherche,
    • pas de vérification d'angle ou de chasse,
    • pas de vecteurs,
    • pas de transformations,
    • pas de nombres complexes,
    • pas de fonctions multilignes, et
    • pas d'importation de packages spéciaux (utilisez uniquement des éléments intégrés).
    • (Et pas d'entantglements impériaux!)

Ma solution en R est présentée ci-dessous. Je suppose qu'il y a exactement quatre points et que, selon l'énoncé du problème, il a déjà été déterminé que les points sont uniques.

sumsq <- function(x) sum(x^2)

quadrances.xy <- function(xy) vapply(
    as.data.frame(t(diff(xy)), optional=T), sumsq, 1)

Voir les travaux de Norman Wildberger, en particulier ses vidéos YouTube ( Real fish, real numbers, real jobs et suiv.) Et son livre Divine Proportions pour une discussion sur "quadrance. "

xy fait référence à une sorte de matrice acceptée par les fonctions plot, points et lines de R.

L'application de as.data.frame Est une astuce pour amener R à faire les choses en colonnes.

La clause optional=T Élimine les noms, qui ne sont pas utilisés de toute façon.

quadrances.xy..i2. <- function(xy, i2) vapply(
    as.data.frame(i2, optional=T),
    function(k) quadrances.xy(m[k,]),
    1)

Il s'agit d'une fonction pour calculer les quadrances entre les points spécifiés, où les paires de points sont spécifiées par l'argument i2. Le symbole i2 Fait référence à une matrice d'index qui a une colonne par index, et 2 éléments par colonne (le même type de matrice retourné par la fonction combn).

quadrance.every.xy <- function(xy, .which=combn(nrow(xy), 2))
        quadrances.xy..i2.(xy, .which)

Le .which Est présenté comme un argument simplement pour l'exposer à formals et pour tenter de communiquer ce qui se passe.

is.square.xy <- function(xy) {
    qq <- sort(quadrance.every.xy(xy))
    all(qq[2:4] == qq[1]) && # ALL SIDES (SHORT QUADRANCES) EQUAL
    qq[5] == qq[6] # ALL DIAGONALS (LONG QUADRANCES) EQUAL
}

J'ai dit que "simple" ne comportait aucune fonction multiligne. Vous devrez excuser cette fonction à deux lignes.

xy <- t(matrix(c(3,0,  7,3,  4,7,  0,4), ncol=4))
xy
#      [,1] [,2]
# [1,]    3    0
# [2,]    7    3
# [3,]    4    7
# [4,]    0    4
is.square.xy(xy)
# [1] TRUE

Notez que les quatre premières fonctions sont utiles en elles-mêmes, à part la question sur les quatre points.

0
Ana Nimbus

Supposons quatre points A = (ax, ay), B = (bx, by), C = (cx, cy), D = (dx, dy), et ils forment les points d'un carré dans le sens inverse des aiguilles d'une montre. Nous déplaçons les points de sorte que A soit à (0, 0) en soustrayant ax de bx, cx et dx, et en soustrayant ay de by, cy et dy, en définissant ax = ay = 0.

Si les points sont exactement les coins d'un carré dans le sens inverse des aiguilles d'une montre, alors étant donné A et B, nous pouvons calculer où C et D sont: Nous devrions avoir (cx, cy) = (bx - par, bx + par) et (dx, dy) = (-by, bx). Nous calculons donc la distance au carré entre C et D et l'endroit où elles devraient être: errC = (cx - bx + by) ^ 2 + (cy - bx - by) ^ 2, et errD = (dx + by) ^ 2 + (dy - bx) ^ 2. Nous les ajoutons et les divisons par (bx ^ 2 + par ^ 2), donnant err = (errC + errD)/(bx ^ 2 + par ^ 2).

L'erreur de résultat serait 0 si un carré parfait, ou un petit nombre si presque un carré, et le nombre resterait inchangé, sauf pour les erreurs d'arrondi si nous traduisons, mettons à l'échelle ou tournons les points du carré. Nous pouvons donc utiliser err pour décider de la qualité d'un carré.

Mais nous ne connaissons pas l'ordre des points. B et D doivent être à la même distance de A; si nous multiplions cela par la racine carrée de 2, cela devrait être la distance de A à C. Nous utilisons cela pour déterminer quel point est C: Calculer distB = bx ^ 2 + par ^ 2, distD = dx ^ 2 + dy ^ 2. Si distD ≥ 1,5 distB, alors nous échangeons C et D; si distB ≥ 1,5 distD, alors nous échangeons C et B. Maintenant C a raison.

Nous pouvons également déterminer quels points sont B et D: si nous avons mal deviné lequel est B et lequel est D, alors notre calcul place D au mauvais endroit, exactement à l'opposé de l'endroit où il se trouve. Donc, si errD ≥ (bx ^ 2 + by ^ 2), alors nous échangeons B et D.

Cela arrangera correctement B, C et D si nous avons effectivement un carré ou du moins à peu près un carré. Mais si nous n'avons même pas un carré, nous savons que le calcul d'erreur à la fin le montrera.

Sommaire:

  1. Soustrayez ax de bx, cx, dx. Soustrayez ay de by, cy, dy.
  2. Soit distB = bx ^ 2 + par ^ 2, distD = dx ^ 2 + dy ^ 2.
  3. Si distD ≥ 1,5 * distB, échangez C et D et calculez à nouveau distD.
  4. Sinon, si distB ≥ 1,5 * distD, échangez B et C et calculez à nouveau distB.
  5. Soit errD = (dx + by) ^ 2 + (dy - bx) ^ 2.
  6. Si errD ≥ distB, puis permutez B et D, permutez distB et distD, calculez à nouveau errD.
  7. Soit errC = (cx - bx + by) ^ 2 + (cy - bx - by) ^ 2.
  8. Soit err = (errC + errD)/distB.
  9. Décidez si nous avons un carré ou presque un carré en fonction de la valeur de err.

Si nous connaissons l'ordre des points, cela peut évidemment être simplifié.

0
gnasher729