Come posso sapere se un oggetto si sta muovendo in senso orario o antiorario attorno a un percorso connesso?


19

Diciamo che abbiamo una forma frastagliata:

shape0

E due creature si muovono lungo il suo contorno.

Quindi levigiamo completamente la forma estraendo gli angoli.

Otteniamo questo:

liscio

È facile vedere ora che Orange si sta muovendo in senso orario e in senso antiorario verde. Come posso dire in quale direzione si stanno muovendo senza appianare la forma?

Nuova immagine

inserisci qui la descrizione dell'immagine


Ecco i miei 2 centesimi: i.imgur.com/zrBdw.png
Kendall Frey

Risposte:


27

Traccia una linea all'infinito e conta quante volte attraversi la forma (pari o dispari), senza contare il segmento in cui si trova la creatura. Quindi controlla se la creatura sta andando a sinistra oa destra di quella linea.

esempio

In questo esempio, attraversiamo la forma due volte (quindi anche) e andiamo a sinistra. Il risultato è immediato da questa tabella:

   # Crosses | even  | odd
  Direction  |       |
-------------+-------+------
    left     | CCW   |  CW
    right    |  CW   | CCW

In pseudocodice:

x, y = position of creature
vx, vy = direction of creature movement
crossings = 0
for each x1, y1, x2, y2 in shape segments:
    if (x1 < x and x <= x2) or (x2 < x and x <= x1):
        if y - y1 > (x - x1) * (y2 - y1) / (x2 - x1):
            ++crossings
if (crossings & 1) == (vx < 0):
    return CW
else
    return CCW

includi la creatura linea in movimento?
Ali1S232

@Gajoo: no, quindi il> invece di> = alla riga 6. Aggiungerò una nota a riguardo. Si noti che è possibile includere la riga e invertire semplicemente il contenuto della tabella.
sam hocevar,

1
Mi stavo inventando tra dare una risposta basata su questo metodo e la risposta che ho dato. Sono contento che qui abbiamo rappresentato entrambi gli approcci. Questo è concettualmente più semplice e molto elegante, ma richiede l'esecuzione di test di intersezione di segmenti di linea, che possono essere difficili da rendere robusti.
Trevor Powell,

@TrevorPowell True. Trovare il bordo più lontano potrebbe essere fonte di confusione. Ho controllato prima in base al vertice più distante del bordo e poi io tracciando una linea dal centro della forma e attraverso i centri dei due bordi (i due che condividono il vertice) e vedendo se una delle linee incrocia un altro bordo sulla strada per infinito dopo aver attraversato uno di questi bordi. Ha funzionato bene
Wolfdawn l'

5

Dipende dalle informazioni che hai a disposizione dalla struttura dei dati della tua forma, ma una creatura che si muove in senso antiorario lungo il contorno di una forma avrà sempre l'interno della forma alla sua destra, e una creatura che si muove in senso antiorario avrà l'interno della forma in è a sinistra.


Una soluzione molto più semplice, e anche il mio primo pensiero.
Amplifica il

come fai a sapere quale direzione è all'interno della forma? Voglio dire che spostarsi lungo un bordo all'interno della forma è alla tua sinistra o alla tua destra. come fai a sapere da che parte è?
Ali1S232,

Una soluzione molto elegante, ma non vera in generale. Immagina una ciambella, appiattita su un tavolo per creare una forma bidimensionale. Puoi camminare lungo il bordo di questa forma, mantenere l'interno della forma alla tua sinistra e fare un giro in senso orario o antiorario a seconda di dove hai iniziato.
Marcks Thomas,

4
  1. Calcola il punto centrale della tua forma.
  2. Scegli il bordo più distante della tua forma dal centro.
    • (La selezione del bordo più distante assicura che non si inizi da una parte concava e invertita della forma, il che comporterebbe il recupero all'indietro della determinazione in senso orario / antiorario per l'intera forma)
  3. Determina quale direzione lungo quel bordo è in senso orario
    • (Una semplice implementazione di questo implicherebbe il confronto degli angoli dal centro della forma a ciascuna estremità del bordo selezionato. Il segno della differenza tra gli angoli indicherà il tuo senso orario rispetto a quello antiorario)
  4. Scorrere su tutti i bordi della forma, iniziando dal bordo selezionato nel passaggio 2, creando un elenco di bordi. Per ciascun bordo, conservare i suoi due vertici in senso orario.
    • (Se la forma non cambia nel tempo, è possibile memorizzare questo elenco di bordi per un uso successivo, quindi non è necessario eseguire i primi quattro passaggi ogni fotogramma)
    • (potresti già avere un elenco di bordi. In tal caso, puoi memorizzare questo ordine di vertici in senso orario in quello stesso elenco.)
  5. Per determinare se un'entità si sta muovendo in senso orario o antiorario:
    • Determina quale bordo si sta muovendo l'entità.
    • Fai un prodotto a punti della direzione di movimento dell'entità contro il vettore dai vertici di inizio-> fine in senso orario di quel bordo che hai determinato nel passaggio 4.
    • Se il risultato del prodotto punto è un valore maggiore di zero, l'entità si sta muovendo in senso orario. Meno di zero significa in senso antiorario.

Risposta molto intelligente
Wolfdawn,

Ho una piccola domanda? supponendo che i vertici nella sua forma siano numerati a partire dal punto più a sinistra CWW, in base alla tua risposta come posso sapere se lo spostamento da 6-> 7 o 9-> 10 (basato su zero) si sta muovendo in senso orario?
Ali1S232,

Inizi con il bordo più distante e scopri quale direzione è in senso orario su quel bordo. Diciamo che il bordo A è in senso orario dal vertice 'a' a 'b'. Quindi se passiamo al bordo B (che ha i vertici 'b' e 'c'), sappiamo che B è in senso orario da 'b' a 'c'. Allo stesso modo, il bordo C sarà in senso orario da 'c' a 'd'. Una volta che conosciamo la corretta direzione in senso orario da un bordo (passaggi 1-3), continuando in quella direzione in senso orario attorno ai bordi della forma, possiamo dedurre la corretta direzione "in senso orario" per ogni bordo, senza realmente guardare dove si trovano i suoi bordi, quindi la concavità è ok.
Trevor Powell,

come si può sapere se il bordo A è in senso orario da 'a' a 'b' o se è in senso orario da 'b' a 'a'? Penso che ti sia mancata quella parte.
Ali1S232

@Gajoo Questo è il punto tra parentesi del passaggio 3. Probabilmente non dovrebbe essere tra parentesi, poiché è davvero il passaggio critico dell'intero processo.
Trevor Powell,

2

Devi sapere in che modo è definito il poligono, in che modo i vertici lo circondano.

Se non lo sai, puoi risolverlo calcolando l'area del poligono:

float Polygon::area() {
    float result = 0.0f;

    for(int a = 0; a < vertexCount; a ++) {
        int b = (a+1) % vertexCount;
        result += vertices[a].x * vertices[b].y;
        result -= vertices[a].y * vertices[b].x;
    }

    return result * .5f;
}

Il segno del risultato (positivo o negativo) ti dirà se è in senso orario o antiorario. Devi provare questo per vedere in che direzione è per te perché dipende dal tuo sistema di coordinate.

Se la forma è in senso orario:

  • Una creatura che avanza attorno alla forma sta andando in senso orario , e
  • Una creatura che gira all'indietro attorno alla forma sta andando in senso antiorario .

Se la forma è in senso antiorario:

  • Una creatura che avanza attorno alla forma sta andando in senso antiorario , e
  • Una creatura che gira all'indietro attorno alla forma sta andando in senso orario .

0

Sembra che Trevor abbia già trattato questa domanda, ma ecco la mia soluzione:

  1. calcola l'area coperta dalla forma, ovvero

    area = 0
    foreach (edge in shape)
        area += edge.begin.x * edge.end.y - edge.begin.y * edge.end.x
  2. usando l'area calcolata come sopra puoi facilmente capire se la forma stessa è in senso orario o meno. è in senso orario solo se l'area è inferiore a zero.

  3. controlla se gli oggetti si stanno muovendo allo stesso modo dei vertici o nella direzione opposta.


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.