Come verificare se 4 punti formano un quadrato?


35

Supponiamo di avere 4 punti (sono bidimensionali), che sono diversi l'uno dall'altro, e voglio sapere se formano un quadrato. Come farlo? (lascia che il processo sia il più semplice possibile).


3
Presumo che avresti bisogno di tenere conto dei quadrati ruotati?
Martijn Pieters,

Hai informazioni sull'ordine dei punti? Vale a dire se due punti sono adiacenti o formano una diagonale? (queste informazioni possono essere utilizzate per semplificare il processo)
Daniel B,

1
@DanielB Nessun'altra informazione. Proprio come se avessi un libro bianco e ne disegnassi 4 punti a caso. Quindi voglio sapere se formano un quadrato.
MarshalSHI,

5
In particolare se i punti sono rappresentati come numeri in virgola mobile, è utile includere un senso di "tolleranza" in uno dei confronti suggeriti di seguito. Esatti controlli di uguaglianza possono fallire per i risultati delle operazioni in virgola mobile, anche quando noi umani li considereremmo "abbastanza vicini".
Stephan A. Terre,

Questo ha l'odore di una domanda a casa. Non che ci sia qualcosa di sbagliato in questo. : / whathaveyoutried.com
Jim G.

Risposte:


65

Supponendo che il tuo quadrato possa essere ruotato contro qualsiasi sistema di coordinate tu abbia in atto, non puoi fare affidamento sul fatto che ci sia una ripetizione dei valori X e Y nei tuoi quattro punti.

Quello che puoi fare è calcolare le distanze tra ciascuno dei quattro punti. Se ritieni che quanto segue sia vero, hai un quadrato:

  1. Ci sono due punti, diciamo A e C che sono distanza x l' uno dall'altro, e altri due punti, dicono B e D che sono anche distanza x l' uno dall'altro.

  2. Ogni punto {A, B, C, D} è uguale distanza dai due punti che non sono x di distanza. cioè: se A è x lontano da C, allora sarà z lontano sia da B che da D.

Per inciso, la distanza z dovrà essere SQRT (( x ^ 2) / 2), ma non è necessario confermarlo. Se le condizioni 1 e 2 sono vere, allora hai un quadrato. NOTA: alcune persone sono preoccupate per l'inefficienza della radice quadrata. Non ho detto che dovresti fare questo calcolo, ho solo detto che se lo facessi otterrai un risultato prevedibile!

Illustrazione delle regole quadrate

Il minimo indispensabile di lavoro che dovresti fare sarebbe scegliere un punto, dire A e calcolare la distanza da ciascuno degli altri tre punti. Se riesci a trovare che A è x da un punto e z da altri due punti, devi solo controllare gli altri due punti uno contro l'altro. Se sono anche x l' uno dall'altro, allora hai un quadrato. vale a dire:

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

Da AB = AD, controlla BD:

  • BD = x

Giusto per essere sicuri, è necessario controllare gli altri lati: BC e CD.

  • BC = z
  • CD = z

Poiché AC = BD e poiché AB = AD = BC = CD, questo è quindi un quadrato.

Lungo la strada, se trovi più di due distinte distanze dal bordo, la figura non può essere un quadrato, quindi puoi smettere di guardare.


Implementazione di esempio funzionante

Ho creato un esempio funzionante su jsfiddle (vedi qui ). Nella mia spiegazione dell'algoritmo, utilizzo i punti arbitrari A, B, C e D. Quei punti arbitrari si trovano in un certo ordine per il bene di percorrere l'esempio. L' algoritmo funziona anche se i punti sono in un ordine diverso, tuttavia l' esempio non funziona necessariamente se quei punti sono in un ordine diverso.


Grazie a: meshuai, Blrfl, MSalters e Bart van Ingen Schenau per commenti utili per migliorare questa risposta.


19
Puoi cortocircuitare questo processo e non preoccuparti di come ordinare i punti misurando la distanza tra loro e tenendo traccia del numero di distanze uniche che trovi. Una volta superati i due ( x e z di Joel ), la figura non è un quadrato.
Blrfl,

3
Un'altra ottimizzazione sarebbe quella di confrontare le distanze al quadrato, anziché le distanze.
vaughandroid,

4
@Blrfl: il test non funziona. Lascia che ABCD sia un diamante con AB = BC = CD = DA = 1, anche AC = 1 (diagonale corta), quindi AD ~ 1.7 (diagonale lunga) / Hai solo due lunghezze x e z, ma la figura non è un quadrato .
MSalters il

2
@JoelBrown: è possibile creare una forma di trapezio con le diagonali AC = BD = x, i lati AB = BC = AD = z e l'ultimo lato CD = y! = Z.
Bart van Ingen Schenau,

2
Abbastanza giusto, nota comunque che OP ha detto esplicitamente 2 dimensioni.
Joel Brown,

24

Scegli tre dei quattro punti.

Scopri se si tratta di un triangolo isoscele destro verificando se uno dei tre vettori tra i punti è uguale a un altro ruotato di 90 gradi.

In tal caso, calcola il quarto punto per addizione vettoriale e confrontalo con il quarto punto dato.

Si noti che ciò non richiede costose radici quadrate, nemmeno la moltiplicazione.


Una delle due buone risposte. Non usare sqrtse non cruciale! Non è necessario degradare i calcoli dei numeri interi in FP ... per non parlare del peggioramento della precisione del calcolo FP.
K.Steff,

grazie. una buona.
MarshalSHI,

Questo è il modo giusto per farlo. La moltiplicazione non è effettivamente necessaria qui.
VIENI DAL

Come si fa a sapere se 2 vettori sono perpendicolari tra loro senza il loro punto prodotto che comporta la moltiplicazione?
Pavan Manjunath,

1
(x, y) ruotato di un angolo retto è (-y, x) o (y, -x), a seconda che ruotiate rispettivamente nella direzione positiva o negativa.
Starblue,

17

Penso che la soluzione più semplice sia la seguente:

  • Innanzitutto, calcola il centro dei 4 punti: center = (A + B + C + D)/4

  • Quindi calcola il vettore A - center. Lascia che siav := (x,y)

  • Lascia che v2il vettore sia vruotato di 90 gradi:v2 := (-y, x)

  • Ora gli altri punti dovrebbero essere center - v, center + v2e center - v2.

Il vantaggio di questa soluzione è che non è necessario utilizzare le radici quadrate.


2
Si. Questo è il più comprensibile e probabilmente anche il più facile da implementare.
Eric G,

Sembra l'uguaglianza vettoriale dei segmenti. Qualcuno può elaborare o dimostrare perché funziona?
vCillusion,

Fallisce specificamente per case (0,0), (2,1), (3, -1), (1, -2) - quadrato non allineato all'asse
vCillusion

1
Funziona per questo caso. Il punto centrale è (1,5, -0,5), il primo punto è (0, 0) e altri tre punti sono (1,5, -0,5) + (1,5, -0,5) = (3, -1); (1,5, -0,5) + (0,5, 1,5) = (2, 1) e (1,5, -0,5) - (0,5, 1,5) = (1, -2) che significa che è un quadrato. La prova è ... simmetria?
Aragaer,

1
La "soluzione della distanza" ha bisogno di radici quadrate, ma c'è la "soluzione della distanza quadrata", che non ha bisogno di nessuno. Il tuo potrebbe essere ancora più efficiente ...
Maaartinus,

5

Mi dispiace ma alcune risposte non si applicano.

Nel caso in cui misuri 3 bordi (diciamo AB, AC e AD) per scoprire che due hanno le stesse dimensioni (diciamo AC e AD) e uno è più grande (diciamo AB). Quindi si misura il CD per vedere se ha le stesse dimensioni di AB e si scopre che lo è. Invece di un quadrato, potresti avere l'immagine qui sotto, e questo lo rende una soluzione sbagliata.

Non un quadrato ...

Quindi prova un'altra soluzione: misura tutte le distanze almeno una volta: AB, AC, AD, BC, BD, CD. Quindi scopri che 4 di questi sono uguali e anche gli altri 2 sono uguali tra loro. Ma potresti semplicemente avere una foto come di seguito:

E anche quello non è un quadrato ...

Quindi, quelle risposte non sono corrette, nonostante gli alti voti che hanno ricevuto.

Una possibile soluzione: se le due misure uguali non collegano lo stesso punto. Quindi: se AB e CD hanno la stessa lunghezza, tutte le altre combinazioni (AC, AD, BC, BD) sono uguali, hai un quadrato. Se hai lo stesso punto facendo la lunghezza maggiore (AB e AC sono le più grandi, e tutte le altre sono uguali), hai una delle immagini sopra.


no, il suo algoritmo diceva che i 2 bordi delle distanze x non condividono un punto. ma condividi semplicemente C. Quindi, supponi che AC sia x, quindi BD dovrebbe essere un altro x invece del tuo BC.
MarshalSHI,

3

Lascia che i quattro punti abbiano coordinate vettoriali a, b, c, d.

Quindi consente di chiamare le loro differenze w = (annuncio), x = (ba), y = (cb), z = (dc).

Quindi w è ortogonale a a se è possibile creare w da a con una rotazione di 90 gradi. Matematicamente la matrice di rotazione di 90 gradi nello spazio 2 è ((0, -1), (1, 0)). Pertanto, risulta la condizione se w sia ruotato di 90 gradi

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

Se questo vale, allora devi controllare che w == -y e x == -z, o

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

Se queste tre relazioni sono valide, a, b, c, d formano un quadrato orientato.


1
Penso che anche il rettangolo possa soddisfare le tue condizioni.
MarshalSHI,

No, la prima condizione non è soddisfatta da vettori ortogonali, ma non di uguale lunghezza.
Mark Salzer,

1
sì, mi manca solo il primo. Ma i 4 punti non sono ordinati. Quindi, abbiamo bisogno di più passaggi, credo, per confermare.
MarshalSHI,

Sì ... se non dovesse nascere un'idea più intelligente, bisognerebbe fare un ciclo. Penso che sia necessario un loop esterno per calcolare w, x, y, z da ogni possibile ordinamento di a, b, c, d e un loop interno per ogni possibile ordinamento della tupla w, x, y, z.
Mark Salzer,

2

Simile alla risposta di starblue

Scegli tre dei quattro punti.

Cerca tra loro un vertice ad angolo retto : controllando se il prodotto punto di uno dei due vettori è zero. Se non trovato, non un quadrato.

Controlla se anche i vertici adiacenti a questo angolo sono ad angolo retto. Altrimenti, non un quadrato.

Verifica se le diagonali sono perpendicolari : se il prodotto punto dei vettori tra il primo e il quarto vertice e gli altri due vertici (diagonali) è zero, allora è un quadrato.


Buona idea, ma è comunque necessario verificare che il 4o vertice sia alla giusta distanza dagli altri punti. Verifichi solo che si trova sulla diagonale.
Starblue,

@starblue Right! Altrimenti può formare un aquilone. Aggiornato.
Max

2

Penso che puoi farlo con semplice aggiunta e sottrazione e trovare min / max. Termini (corrisponde al diagramma di altre persone):

  • Punto con il valore y più alto => A
  • più alto x => B
  • minimo y => C
  • più basso x => D

Se 4 punti condividono solo 2 valori x e 2 valori y hai un quadrato di livello.

Altrimenti, hai un quadrato se i tuoi punti soddisfano quanto segue:

  • Ascia + Cx = Bx + Dx
  • Ay + Cy = By + Dy
  • Ay - Cy = Bx - Dx

Spiegazione: I segmenti di linea AC e BD devono incontrarsi ai loro punti medi. Pertanto (Ax + Cx) / 2 è il punto medio di AC e (Bx + Dx) / 2 è il punto medio di BD. Moltiplica ogni lato di questa equazione per 2 per ottenere la mia prima equazione. La seconda equazione è la stessa cosa per i valori Y. Le forme a diamante (romboidi) soddisferanno queste proprietà, quindi è necessario verificare di avere lati uguali - che la larghezza sia uguale all'altezza. Questa è la terza equazione.


2

inserisci qui la descrizione dell'immagine

Ci sono alcune buone risposte qui, ma la domanda ha richiesto l'approccio più semplice. Ci ho pensato in fretta ed è così che lo farei.

Puoi stabilire se quattro punti rappresentano un quadrato (anche se ruotato), ma trova la media dei quattro punti.

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

Una volta ottenuta la media, la distanza tra ciascun punto e la media dovrebbe essere la stessa per tutti e quattro i punti.

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

MODIFICARE:

Errore mio. Ciò ti direbbe solo se i punti del modulo fossero su un cerchio. Se controlli anche la distanza tra i punti, allora deve essere un quadrato.

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"

Ciò presuppone che i punti A, B, C, D non attraversino (poiché in un ordine di avvolgimento valido).


1

questa non è una risposta secondo gli standard stabiliti, ma spero che questo aiuti:

[Copiato dal link sottostante in modo da non dover aprire il link] Python 76 caratteri

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

La funzione S prende un elenco di numeri complessi come input (A). Se conosciamo sia il centro che un angolo di un quadrato, possiamo ricostruire il quadrato ruotando l'angolo di 90.180 e 270 gradi attorno al punto centrale (c). Sul piano complesso la rotazione di 90 gradi attorno all'origine viene eseguita moltiplicando il punto per i. Se la nostra forma originale e il quadrato ricostruito hanno gli stessi punti, allora deve essere stato un quadrato.

Questo è stato preso da: Determina se 4 punti formano un quadrato

Se ti piace la risposta, dico, prenditi qualche momento per ringraziare la persona, o vota la sua risposta su quella pagina.


1
Puoi riassumere l'algoritmo qui. Stai collegando a un altro sito SE, il che è leggermente migliore rispetto a un altro sito, ma vogliamo che la risposta sia su questa pagina, dove viene posta la domanda. Ora le persone devono fare di nuovo clic per sapere quale potrebbe essere la risposta.
Martijn Pieters,

0

Idea di base (questo risponde alla domanda se stavo contribuendo con qualcosa di nuovo, che mi è stato chiesto dal bot quando ho cliccato per fornire una risposta):

  • un rombo con diagonali uguali è un quadrato.
  • "il più semplice possibile" comprende:
    • nessuna divisione,
    • nessuna radice quadrata,
    • nessuna ramificazione,
    • nessuna ricerca,
    • nessun controllo dell'angolo o acquisizione,
    • nessun vettore,
    • nessuna trasformazione,
    • nessun numero complesso,
    • nessuna funzione multilinea e
    • nessuna importazione di pacchetti speciali (usare solo roba integrata).
    • (E niente entantglements imperiali!)

La mia soluzione in R è presentata di seguito. Sto assumendo che ci siano esattamente quattro punti e che, per l'affermazione del problema, è già stato stabilito che i punti sono unici.

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

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

Guarda le opere di Norman Wildberger, in particolare i suoi video su YouTube ( Pesce reale, numeri reali, posti di lavoro reali e seguenti) e il suo libro Divine Proportions per una discussione sul "quadrance".

xysi riferisce ad un tipo di matrice di accettato da R plot, pointse linesfunzioni.

L'applicazione di as.data.frameè un trucco per convincere R a fare le cose per colonne.

La optional=Tclausola elimina comunque i nomi che non vengono utilizzati.

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

Questa è una funzione per calcolare i quadranti tra i punti specificati, dove coppie di punti sono specificate i2dall'argomento. Il i2simbolo si riferisce a una matrice di indice che ha una colonna per indice e 2 elementi per colonna (lo stesso tipo di matrice restituita dalla combnfunzione).

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

Il .whichè presentato come un argomento solo per esporla alla formalse tentare di comunicare ciò che sta succedendo.

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
}

Ho detto che "semplice" non includeva funzioni multilinea. Dovrai scusare questa funzione a due righe.

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

Si noti che le prime quattro funzioni sono utili di per sé, a parte la domanda sui quattro punti.


0

Assumi quattro punti A = (ax, ay), B = (bx, by), C = (cx, cy), D = (dx, dy) e formano i punti di un quadrato in ordine antiorario. Spostiamo i punti in modo che A sia a (0, 0) sottraendo ax da bx, cx e dx e sottraendo ay da da, cy e dy, impostando ax = ay = 0.

Se i punti sono esattamente gli angoli di un quadrato in ordine antiorario, quindi dati A e B, possiamo calcolare dove sono C e D: dovremmo avere (cx, cy) = (bx - by, bx + by) e (dx, dy) = (-by, bx). Quindi calcoliamo la distanza quadrata da dove si trovano C e D, dove dovrebbero essere: errC = (cx - bx + di) ^ 2 + (cy - bx - by) ^ 2, ed errD = (dx + by) ^ 2 + (dy - bx) ^ 2. Aggiungiamo questi e dividiamo per (bx ^ 2 + per ^ 2), dando err = (errC + errD) / (bx ^ 2 + per ^ 2).

Il risultato err sarebbe 0 se un quadrato perfetto, o un piccolo numero se quasi un quadrato, e il numero rimarrebbe invariato tranne gli errori di arrotondamento se traduciamo, ridimensioniamo o ruotiamo i punti del quadrato. Quindi possiamo usare err per decidere quanto è buono un quadrato.

Ma non conosciamo l'ordinamento dei punti. B e D dovrebbero essere alla stessa distanza da A; se moltiplichiamo questo per la radice quadrata di 2, quella dovrebbe essere la distanza da A a C. Usiamo questo per capire quale punto è C: Calcola distB = bx ^ 2 + per ^ 2, distD = dx ^ 2 + dy ^ 2. Se distD ≥ 1,5 distB, scambiamo C e D; se distB ≥ 1,5 distD scambiamo C e B. Ora C ha ragione.

Possiamo anche capire quali punti sono B e D: se abbiamo indovinato quale sia B e quale sia D, allora il nostro calcolo pone D nel posto completamente sbagliato, esattamente opposto a dove si trova. Quindi se errD ≥ (bx ^ 2 + per ^ 2), allora scambiamo B e D.

Questo sistemerà B, C e D correttamente se abbiamo davvero un quadrato o almeno approssimativamente un quadrato. Ma se non abbiamo nemmeno un quadrato, sappiamo che il calcolo dell'errore alla fine lo mostrerà.

Sommario:

  1. Sottrai l'ascia da bx, cx, dx. Sottrai ay da cy, dy.
  2. Lascia distB = bx ^ 2 + di ^ 2, distD = dx ^ 2 + dy ^ 2.
  3. Se distD ≥ 1,5 * distB, scambiare C e D e calcolare nuovamente distD.
  4. Altrimenti, se distB ≥ 1,5 * distD, scambiare B e C e calcolare nuovamente distB.
  5. Lascia che errD = (dx + by) ^ 2 + (dy - bx) ^ 2.
  6. Se errD ≥ distB quindi scambiare B e D, scambiare distB e distD, calcolare nuovamente errD.
  7. Sia errC = (cx - bx + di) ^ 2 + (cy - bx - di) ^ 2.
  8. Sia err = (errC + errD) / distB.
  9. Decidi se abbiamo un quadrato o quasi un quadrato a seconda del valore di err.

Se conosciamo l'ordine dei punti, questo può ovviamente essere semplificato.


-3

La soluzione è simile al pensiero mediatico.

Primo passo:

x = (A+B+C+D)/4
f=0
if(dist(x,A) == dist(x,B) == dist(x,C) == dist(x,D) 
   f=1
else
   f=0

Questa proprietà è seguita da quadrato perché è ciclico. ora un cerchio per seguire questa proprietà. quindi, ora basta controllare

if(A.B==B.C==C.D==D.A==0)
  f=1
else 
  f=0

if (f==1)
  square
else 
  not square

Qui AB significa punto prodotto di A e B

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.