2009-03-04 15 views
16

Sto cercando un buon algoritmo per trovare un rettangolo allineato agli assi all'interno di un poligono (non necessariamente convesso). Un rettangolo massimale sarebbe bello, ma non è necessario - qualsiasi algoritmo in grado di trovare un rettangolo "abbastanza buono" andrebbe bene.Trovare un rettangolo allineato agli assi all'interno di un poligono

Il poligono può anche presentare fori, ma qualsiasi suggerimento per algoritmi che funzionano solo per poligoni convessi o semplici potrebbe essere utile.

Nella mia implementazione, il test di intersezione dei lati è abbastanza economico, ma i test "punto in poligono" sono costosi, quindi idealmente dovrebbe essere ridotto al minimo.

+0

Considerate un test "Punto in poligono" pesante? Il più delle volte è solo un test "più grande di" e/o "meno di" di tutti i punti di cui è composto il poligono, e solo in alcuni casi un test di intersezione delle linee? O...? –

+0

Non sei sicuro di cosa intendi ... Sto usando il test di incrocio dispari per una semiretta (dopo aver controllato il rettangolo di delimitazione, ovviamente). Questo finisce per testare un sacco di lati, e se il poligono ha molti lati è piuttosto lento. –

+0

Coud si collega ad alcuni set di dati, questo suona come qualcosa che potrebbe essere divertente da provare. –

risposta

2

Solo per riferimento, finora tutto ciò che ho è forza bruta: crea una griglia, e per i punti sulla griglia, se sono all'interno del poligono, crea una serie di rettangoli espandendo ogni angolo o lato a turno fino a quando colpisce un lato Quindi scegli il più grande.

L'ottimizzazione più semplice (e molto efficace) consiste nel verificare se un punto di griglia si trova nel poligono dopo aver verificato che non è contenuto in uno dei rettangoli già costruiti, poiché il controllo del punto nel rettangolo è sfolgorante veloce.

Per ovvie ragioni, questo è abbastanza lento e impreciso, per non parlare poco elegante :)

+0

Appena fuori dalla mia testa, costruire orizzontale e linee verticali attraverso ogni vertice anziché una griglia uniforme. –

+0

... supponendo che il poli non abbia molti lati piccoli che si avvicinano alle curve. –

+0

Ho usato una variazione di questo con buoni risultati. Essenzialmente ho tagliato il poligono in 16 punti di prova (4 larghi e 4 alti in base alle dimensioni del rettangolo di delimitazione). Con un elenco di campioni molto limitato, ho solo dovuto espandere il mio rettangolo controllando se il nuovo punto produceva un rettangolo completamente all'interno della geometria. Ha funzionato molto bene per i miei scopi. –

3

Una soluzione è dividere il poligono concavo in segmenti convessi, quindi utilizzare il collegamento cobbal.

Dal momento che in realtà hai due diversi problemi fondamentali, hai considerato altre alternative al problema del hit test, ad esempio l'utilizzo di un albero BSP? Puoi accelerare ulteriormente posizionando una griglia sul poligono e costruendo un albero BSP per ogni quadrato della griglia. O un albero kd con al massimo un bordo in ogni foglia?

Edit: io ellaborate sul kd-tree (per noia, anche se potrebbe essere di qualche utilità a nessuno):

kd-alberi hanno le seguenti proprietà:

  1. Sono binari
  2. Ogni nodo non fogliare divide lo spazio lungo un piano perpendicolare a un asse, un lato per bambino. Per esempio. la radice divide lo spazio in x < x0 e x> = x0
  3. I livelli degli alberi, a turno, si dividono lungo diversi assi, ad es. livello 0 (root) divide perpendicolare a X, Livello 1 -> Y, ecc

Per utilizzare questo per il poligono hit rilevamento, costruire l'albero come segue:

  1. selezionamento un vertice per dividere lungo. (Preferibilmente da qualche parte vicino al centro per un albero equilibrato).
  2. Dividi altri vertici in due gruppi, uno per ciascun lato della divisione. Il vertice sopra non va in nessuno dei due set.
  3. Posizionare i bordi anche nei set. Qualsiasi arco che interseca la linea divisa va in entrambi i gruppi.
  4. Costruire i bambini in modo ricorsivo dai gruppi precedenti.

Se il vertice diviso viene scelto in modo appropriato, l'albero deve avere profondità vicino al log (N), dove N è il numero di vertici. Ogni nodo foglia avrà al massimo un bordo che lo attraversa. Per eseguire il rilevamento dei colpi:

  1. Trova la foglia in cui cade il punto.
  2. Se c'è un bordo nella foglia, confrontare il punto ad esso. In caso contrario, dovrebbe essere ovvio se il punto è all'interno o all'esterno (conservare queste informazioni in tali foglie quando si costruisce l'albero).
+0

State cercando di evitarlo ... conoscete una buona introduzione? Grazie :) –

+0

Non ne posso dare, ma puoi facilmente aggiungere un sacco di cose su Google e ciò che ho appena scritto dovrebbe dare un'idea generale. – TrayMan

0

E il ritaglio dell'orecchio? È possibile trovare il rettangolo allineato agli assi massimo in ciascun triangolo. Quindi potresti provare ad unire triangoli e ricalcolare i tuoi rettangoli.

Problemi correlati