2012-03-25 7 views
8

esta es mi primera pregunta en estos foros:)Hashcode de número entero coordenadas 3D con alta coherencia espacial

estoy escribiendo una clase de coordenadas en Java para un sistema octree voxel espacial. Estas coordenadas no son coordenadas de coma flotante, son índices enteros 4D en el octárbol (3 dimensiones normales X, Y, Z y a cuarta para profundizar en el árbol). Los primeros 3 valores son todos cortos, la última dimensión es un byte. En uso real en este momento, solo se usan los primeros 11 bits de los cortos y solo 3 bits del byte, pero esto podría estar sujeto a cambios.

Ahora estoy tratando de escribir una función de hash "buena" para esta clase. El problema con el que estoy luchando es que las coordenadas a menudo se usarán en situaciones coherentes altamente espaciales (espero estar usando la terminología correcta allí). Lo que quiero decir es que muchas veces una coordenada será hashed junto con sus vecinos inmediatamente adyacentes y otras coordenadas cercanas.

¿Existe una práctica efectiva para provocar que estas coordenadas "cercanas entre sí" produzcan códigos hash significativamente diferentes?

Respuesta

2

"Significativamente diferente" realmente depende de lo que esté haciendo con el código hash después. En algunos casos, estará sujeto a una selección de cubeta circular tomando el hash % size donde size tiene el tamaño del mapa hash que está utilizando, por ejemplo. Obviamente eso cambiará con el tiempo. Por lo general usaría algo como:

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

(. Esto se cribbed de Effective Java, básicamente) Obviamente esto significa que (x1, y1, z1) y (x1 + 1, y1 - 31, z1) tendría el mismo código hash, pero si usted está preocupado por su mayoría muy cerca de los vecinos no debería ser un problema.

EDITAR: la respuesta de mikera probablemente funcione mejor pero será más complicado de codificar. Yo personalmente probaría este enfoque muy simple primero, y ver si es suficientemente bueno para sus casos de uso reales. Use enfoques progresivamente más efectivos pero complicados hasta que encuentre uno que sea lo suficientemente bueno.

+0

He eliminado mi propia respuesta similar porque tanto su respuesta como mi respuesta no tienen una distribución muy buena para valores sesgados hacia valores cortos más pequeños. Al ejecutar un análisis de su función para las entradas x, y, z a 256 y la profundidad a 16, se muestra que el bit 24 está configurado con el doble de la frecuencia de los bits 0..23 (que están bien distribuidos), y los bits 25-31 no son configurado en absoluto, para cualquier combinación de entrada. Estoy ejecutando una simulación en el rango completo de entrada 2^11 que describe el OP por curiosidad, pero eso llevará un poco. –

+0

@EricJ .: Pero realmente no necesitaremos una distribución uniforme aquí, IMO: solo necesitamos una pequeña posibilidad de colisión real. Creo que la respuesta de mikera probablemente sea mejor, de todos modos, pero dejaré esto por el momento. –

+0

Con 25 bits usados ​​y solo 10000 entradas (pequeña para el modelo 3D), hay un 77% de probabilidad de al menos una colisión. Con 100.000 puntos, al menos una colisión hash está prácticamente asegurada. Asume que esta calculadora de problemas de cumpleaños es correcta http://lazycackle.com/Probability_of_repeated_event_online_calculator__birthday_problem_.html –

12

Estás de enhorabuena: hay una forma de obtener codificaciones de coordenadas decentes con una alta coherencia espacial usando algo llamado Z-order curve.

El truco es intercalar los bits de los diferentes componentes de coordenadas. Así que si usted tiene 3 8 bits coordenadas como:

[XXXXXXXX, YYYYYYYY, ZZZZZZZZ] 

A continuación, el valor codificado Z-curva sería un valor único de 24 bits:

XYZXYZXYZXYZXYZXYZXYZXYZ 

Se puede extender a un mayor número de bits o coordenadas según sea necesario.

Esta codificación funciona porque las coordenadas que están cerca en el espacio tendrán diferencias principalmente en los bits de orden inferior. Entonces al intercalar las coordenadas, obtienes las diferencias enfocadas en los bits de orden inferior del valor codificado.

Una propiedad extra interesante es que los bits inferiores describen coordenadas dentro de cubos de espacio. Así que la posición de dirección más baja de 3 bits con cubos 2x2x2, la posición más baja de dirección de 6 bits dentro de 4 * 4 * 4 cubos, la posición más baja de 9 bits dentro de 8 * 8 * 8 cubos, etc. Así que este es un sistema bastante ideal para direccionar -ordina dentro de un octree.

+0

Eso es ingenioso. Muchas gracias por informarme de esto y por el enlace. Trataré de implementar esto lo antes posible. Muchisímas gracias de nuevo. – Steven

Cuestiones relacionadas