2012-03-25 6 views
8

questa è la mia prima domanda su questi forum:)HashCode per intero coordinate 3D ad alta coerenza spaziale

Sto scrivendo una classe di coordinate in Java per un sistema octree voxel spaziale. Queste coordinate non sono coordinate in virgola mobile, sono indici interi 4D nell'occhiello (3 dimensioni normali X, Y, Z e una avanti per profondità nell'albero). I primi 3 valori sono tutti in cortocircuito, l'ultima dimensione è un byte. In questo momento vengono utilizzati solo i primi 11 bit dei cortocircuiti e solo 3 bit del byte, ma ciò potrebbe essere soggetto a modifiche.

Ora sto cercando di scrivere una funzione di hash "buona" per questa classe. Il problema con cui sto lottando è che le coordinate saranno spesso utilizzate in situazioni coerenti altamente spaziali (spero che io stia usando la terminologia giusta lì). Quello che intendo è che spesso le coordinate di una coordinata vengono troncate insieme ai suoi vicini immediatamente adiacenti e altre coordinate vicine.

Esiste una pratica efficace per far sì che queste coordinate "vicine l'una all'altra" producano codici hash significativamente differenti?

risposta

2

"Significativamente diverso" dipende in realtà da ciò che si sta facendo con il codice hash in seguito. In alcuni casi sarà quindi soggetto a una scelta di bucket round robin prendendo lo hash % size dove size è la dimensione della mappa di hash che stai utilizzando, ad esempio. Ovviamente questo cambierà nel tempo. Mi piacerebbe di solito uso qualcosa di simile:

int hash = 23; 
hash = hash * 31 + x; 
hash = hash * 31 + y; 
hash = hash * 31 + z; 
hash = hash * 31 + depth; 
return hash; 

(. Questo è cribbed da Effective Java, in fondo) Ovviamente significa che (x1, y1, z1) e (x1 + 1, y1 - 31, z1) avrebbe lo stesso codice hash, ma se siete preoccupati per lo più molto vicino ai vicini non dovrebbe essere un problema.

MODIFICA: la risposta di mikera è probabile che funzioni meglio ma essere più complicato da codificare. Vorrei provare personalmente questo approccio molto semplice, e vedere se è abbastanza buono per i tuoi casi d'uso reali. Usa approcci progressivamente più efficaci ma complicati finché non trovi quello che è abbastanza buono.

+0

Ho eliminato la mia risposta simile perché sia ​​la risposta che la mia risposta non hanno una distribuzione molto buona per valori asimmetrici verso valori short più piccoli. Eseguendo un'analisi sulla funzione per gli ingressi x, y, z su 256 e la profondità su 16 mostra che il bit 24 è impostato con il doppio della frequenza dei bit 0..23 (che sono ben distribuiti), ei bit 25-31 non sono impostato a tutti, per qualsiasi combinazione di input. Sto eseguendo una simulazione all'intero intervallo di input 2^11 che l'OP descrive per curiosità, ma ci vorrà un po '. –

+0

@EricJ .: Ma non avremo davvero bisogno di una distribuzione uniforme qui, IMO - abbiamo solo bisogno di una piccola probabilità di collisione reale. Penso che la risposta di mikera sia probabilmente migliore comunque, ma lascerò tutto per il momento. –

+0

Con 25 bit usati e solo 10000 ingressi (piccoli per modello 3D) c'è una probabilità del 77% di almeno una collisione. Con 100.000 punti, almeno una collisione hash è praticamente garantita. Suppone che questa calcolatrice del problema del compleanno sia corretta http://lazycackle.com/Probability_of_repeated_event_online_calculator__birthday_problem_.html –

12

Sei fortunato: c'è un modo per ottenere codifiche di coordinate decenti con alta coerenza spaziale usando qualcosa chiamato Z-order curve.

Il trucco è di interlacciare i bit dei diversi componenti di coordinate. Quindi, se si dispone di 3 coordinate 8-bit come:

[XXXXXXXX, YYYYYYYY, ZZZZZZZZ] 

Quindi il valore codificato z-curva sarebbe un singolo valore a 24 bit:

XYZXYZXYZXYZXYZXYZXYZXYZ 

è possibile estendere a un maggior numero di bit o coordinate come richiesto.

Questa codifica funziona perché le coordinate che sono vicine nello spazio avranno differenze principalmente nei bit di ordine inferiore. Quindi, interlacciando le coordinate, si ottengono le differenze focalizzate nei bit di ordine inferiore del valore codificato.

Una proprietà molto interessante è che i bit inferiori descrivono le coordinate all'interno dei cubi dello spazio. Quindi la posizione dell'indirizzo a 3 bit più bassa con i cubi 2x2x2, la posizione dell'indirizzo a 6 bit più bassa all'interno dei cubi 4 * 4 * 4, la posizione a 9 bit più bassa all'interno dei cubi 8 * 8 * 8 ecc. Quindi questo è in realtà un sistema piuttosto ideale per indirizzare co -ordinati in un ottetto

+0

Questo è geniale. Grazie mille per avermi fatto conoscere questo e il link. Proverò a implementarlo il prima possibile. Grazie mille ancora. – Steven