Sto cercando di trovare se un rettangolo interseca un poligono concavo. Questo algoritmo di realizzare questo?

voti
7

Sto cercando di trovare se un rettangolo interseca un poligono concavo. Ho trovato questo algoritmo:

double determinant(Vector2D vec1, Vector2D vec2){
    return vec1.x*vec2.y-vec1.y*vec2.x;
}

//one edge is a-b, the other is c-d
Vector2D edgeIntersection(Vector2D a, Vector2D b, Vector2D c, Vector2D d){
    double det=determinant(b-a,c-d);
    double t=determinant(c-a,c-d)/det;
    double u=determinant(b-a,c-a)/det;
    if ((t<0)||(u<0)||(t>1)||(u>1))return NO_INTERSECTION;
    return a*(1-t)+t*b;
}

Se eseguo questo 4 volte (Top a destra, dall'alto in basso a sinistra, in alto a destra in basso, in basso a destra) * (tutti i bordi della mia poligono) sarebbe questa maniera efficace e accurata dirmi se il rettangolo ha una parte o tutto il concava poligono all'interno? Se non ciò che sarebbe manca?

Grazie

È pubblicato 11/08/2010 alle 23:05
fonte dall'utente
In altre lingue...                            


3 risposte

voti
2

Credo che il seguente dovrebbe funzionare:

(1) for each e1 in rectangle_edges, e2 in polygon_edges
    (1.1) if edgeIntersection(e1,e2) != NO_INTERSECTION
        (1.1.1) return true
(2) if (max_polygon_x < max_rectangle_x) and (min_polygon_x > min_rectangle_x) and (max_polygon_y < max_rectangle_y) and (min_polygon_y > min_rectangle_y)
    (2.1) return true
(2) return false

Edit : Aggiunto il controllo per se il poligono è all'interno del rettangolo.

Risposto il 11/08/2010 a 23:12
fonte dall'utente

voti
13

Il codice tenta di trovare il punto di intersezione di due segmenti - AB e CD.

Ci sono molti modi diversi di spiegare come sta facendo, a seconda di come si interpretano queste operazioni.

Diciamo che il punto A ha coordinate (xa, ya), B - (xb, YB) e così via. Diciamo

dxAB = xb - xa
dyAB = yb - ya
dxCD = xd - xc
dyCD = yd - yc

Il seguente sistema di due equazioni lineari

| dxAB dxCD |   | t |   | xc-xa |
|           | * |   | = |       |
| dyAB dyCD |   | u |   | yc-ya |

se risolti per te u, vi darà la posizione proporzionale del punto di intersezione sulla linea AB (valore t) e sulla linea CD (valore u). Questi valori si trovano nella gamma di [0, 1]se il punto appartiene al segmento corrispondente e al di fuori di tale intervallo se il punto si trova all'esterno del segmento (sulla riga contenente il segmento).

Al fine di risolvere questo sistema di equazioni lineari possiamo utilizzare il noto regola di Cramer . Per questo avremo bisogno il determinante

| dxAB dxCD |
|           |
| dyAB dyCD |

che è esattamente determinant(b - a, c - d)dal codice. (In realtà, quello che ho qui è determinant(b - a, d - c), ma non è molto importante ai fini di questa spiegazione. Il codice che avete inviato per qualche ragione scambia C e D, vedi PS nota sotto).

E ci sarà anche bisogno determinante

| xc-xa dxCD |
|            |
| yc-ya dyCD |

che è esattamente determinant(c-a,c-d)dal codice, e determinante della

| dxAB xc-xa |
|            |
| dyAB yc-ya |

che è esattamente determinant(b-a,c-a).

Dividendo questi determinanti in conformità con la regola del Cramer ci darà i valori di te u, che è esattamente ciò che viene fatto nel codice che avete inviato.

Il codice procede poi per verificare i valori di te uper verificare se i segmenti effettivamente intersecano, cioè se sia te uappartengono [0, 1]gamma. E se lo fanno, si calcola il punto di intersezione effettivo valutando a*t+b*(1-t)(equivalentemente, potrebbe valutare c*u+d*(1-u)). (Di nuovo, vedi nota PS seguente).

PS Nel codice originale i punti D e C sono "scambiati" in un certo senso che il codice fa c - d, dove faccio d - cnella mia spiegazione. Ma questo non fa alcuna differenza per l'idea generale dell'algoritmo, fino a quando uno di attenti con i segni.

Questo scambio di punti C e D è anche il motivo per a*(1-t)+t*bespressione è usata nel valutare il punto di intersezione. Normalmente, come nella mia spiegazione, one'd si aspettano di vedere qualcosa di simile a*t+b*(1-t)c'è. (Ho i miei dubbi su questo però. Mi sarei aspettato di vedere a*t+b*(1-t)lì anche nella versione. Potrebbe essere un bug.)

PPS L'autore se il codice dimenticato di controllare det == 0(o molto vicino a 0), che avverrà nel caso in cui i segmenti sono paralleli.

Risposto il 11/08/2010 a 23:30
fonte dall'utente

voti
0

Per quanto posso dire, dopo una rapida occhiata, si cerca di determinare se 2 segmenti di linea si intersecano, e se lo fanno, quali sono le coordinate del punto di intersezione sono.

No, non è sufficiente per determinare se il rettangolo e poligono si intersecano, perché saresti ancora manca il caso in cui sia il poligono è completamente all'interno del rettangolo, o viceversa.

Risposto il 11/08/2010 a 23:56
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more