Intersecciones y Ordenamiento

Anuncio
INTERSECCIONES
El cálculo de intersecciones en el espacio tiene varias finalidades en CG. La más simple es el clipping:
el recorte de los objetos entre los límites del volumen visual, renderizando sólo la fracción visible de la
escena. Las aplicaciones más complejas y masivas se dan al hacer ray-tracing y sus derivados, para
utilizar modelos de iluminación y sombreado más realistas, allí hay que calcular una miríada de
intersecciones entre rayos y objetos de la escena. También se utilizan para detección de colisiones en
simulaciones y juegos o detección de interferencias entre objetos de CAD. Las aplicaciones en
geometría computacional abarcan también los procesos de generación de mallas y la determinación de
isocurvas e isosuperficies para visualización de datos.
Veremos algunos ejemplos para mostrar los métodos básicos y alternativas. En la mayoría de los
libros, los planos y las rectas están definidas en forma vectorial o implícita, aquí utilizaremos también
el tratamiento paramétrico, que ya aprendimos a manejar para las curvas y superficies.
Se pretende que los algoritmos empleados sean rápidos, precisos y robustos. La falta de robustez
hace que los errores salten inmediatamente a la vista. Siempre es preferible sacrificar la precisión en
aras de la robustez: que el código entregue un resultado útil en cualquier caso, aún con un pequeño
margen de error. El usuario no se da cuenta si el punto de intersección debería estar un píxel más aquí
o allá, pero enseguida nota un píxel mal pintado o el ruido de colores del z-fighting; dando resultados
visualmente inaceptables; o peor, un “cuelgue” del programa.
El requerimiento de velocidad se vuelve obvio si se piensa que un procedimiento de ray-tracing, por
ejemplo, debe analizar intersecciones entre millones de rayos y miles de objetos. La primera respuesta
que hay que dar, y muy rápidamente, es si puede o no existir la intersección. Veremos las técnicas de
partición del espacio que nos permiten acelerar estas consultas y realizar descartes masivos muy
rápidamente. La velocidad de las placas gráficas se mide mediante la capacidad de procesar polígonos
rápidamente, el polygon throughput está en el orden de los 100 millones de polígonos por segundo.
Pertenencia y Distancia de Punto a Recta y Plano
La distancia entre dos objetos es la menor de entre las distancias de sus puntos. De un punto a un plano
o a una recta es la distancia al pie de la perpendicular del punto al plano o recta.
P
P
d
d
P┴
P1
P2
P┴
P0
P0
P1
P
P
d
P┴
P1
P0
d
P2
P┴
P0
P1
1/12
En el caso de la recta, definida por P0 y P1, notemos que el paralelogramo que subtienden los vectores
P1–P0 y P–P0 tiene altura d, que es la distancia buscada. El área del paralelogramo se calcula mediante
el producto vectorial. La distancia del punto a la recta (altura) se puede calcular mediante el área del
paralelogramo (base x altura) dividida por la longitud de la base, que es el módulo del vector P1–P0.
(P−P0)×(P1−P0)
(P1−P0)
d(P,{P0,P1}) =
= (P−P0) ×
||P1−P0||
||P1−P0||
En el caso del plano {P0, P1, P2} sucede lo mismo, pero con el paralelepípedo formado por los tres
vectores basados en P0 y cuyo volumen se calcula mediante el producto mixto. La distancia del punto
al plano (altura) será el volumen del paralelepípedo (área de la base x altura) dividido por el área de la
base que es el módulo del producto vectorial:
(P−P0)·(P1−P0)×(P2−P0)
(P1−P0)×(P2−P0)
d(P,{P0,P1,P2}) =
= (P−P0) ·
||(P1−P0)×(P2−P0)||
||(P1−P0)×(P2−P0)||
En ambos casos, si el resultado es nulo, el punto pertenece a la recta o al plano.
Una “distancia” es un real sin signo; por lo tanto las ecuaciones de arriba tienen datos demás. El
resultado de la primera ecuación es un vector; es normal al plano definido por la recta y el punto y su
módulo es la distancia buscada; la dirección del vector nos indica un punto de vista desde el cual el
punto está a la derecha de la recta en ese plano. Para la otra ecuación, la distancia calculada al plano es
un escalar con signo y el signo indica de qué lado del plano está el punto.
Los vectores que quedan a la derecha, divididos por sus módulos, son el versor tangente o dirección de
la recta y el versor normal al plano respectivamente.
(P1−P0)
(P1−P0)×(P2−P0)
t=
n=
||P1−P0||
||(P1−P0)×(P2−P0)||
El pie de la perpendicular o proyección se puede calcular del siguiente modo:
(P┴−P0) = [(P−P0)·t] t
(P┴−P0) = (P−P0) − [(P−P0)·n] n
Siendo t y n versores (módulo uno), la primera ecuación es simplemente la proyección de P sobre la
recta. En la segunda ecuación, al vector P−P0 se le quita la componente normal al plano: [(P−P0)·n] n
−que es la proyección sobre una recta perpendicular− quedando sólo la componente en el plano.
El cuadrado de la distancia se puede calcular también por medio de las proyecciones normales:
d2 = (P−P0)2 − [(P−P0)·t]2
d2 = [(P−P0)·n]2
En caso de que se desee calcular sólo la pertenencia o no al plano o recta, o de que lado está el punto,
no hacen falta los módulos ni las divisiones, los cuadrados y los numeradores se comparan con cero.
En general, hay que evitar raíces y divisiones para ganar en velocidad y robustez. Por ejemplo:
comparar distancias es lo mismo que comparar cuadrados y no implica extraer raíces.
Intersecciones de Líneas y Planos o Segmentos y Triángulos
Para calcular la intersección de dos segmentos hay que plantear la intersección de las rectas que los
soportan. Si cada recta se define como expansión afín de los dos puntos del segmento, su intersección
se calcula mediante la igualación del punto variable:
(1−α)P0+αP1 = (1−β)Q0+βQ1
Para dos rectas en el plano, son dos ecuaciones (x, y) con dos incógnitas (α, β). Si la matriz es singular
las entidades son paralelas o coincidentes. Si la intersección existe, los valores de los dos parámetros
nos indican si la intersección se produce dentro o fuera de cada segmento.
En el espacio son tres ecuaciones con dos incógnitas, cada par de ecuaciones nos da los parámetros en
la intersección vista desde el correspondiente plano coordenado, si la intersección existe coinciden las
tres proyecciones. Se pueden calcular α y β con las ecuaciones para x e y; luego, si existen y están
entre cero y uno, se verifica la ecuación para z. Este método es muy poco robusto pues depende de si
alguna de las rectas se ve de punta (se ve como un punto) en el plano xy (o en otros).
Un método más robusto y elegante (independiente del triedro de referencia) se basa en usar la
proyección sobre una normal a ambas rectas. En esa proyección, si existe, se mide la distancia entre las
rectas de soporte y, si es nula, luego se interpola el punto de intersección.
2/12
Los detalles son así:
n = (P1 – P0) × (Q1 – Q0) = ∆P × ∆Q
n
Q1
Si n = {0,0,0} las rectas son paralelas o coincidentes. En caso
contrario, se verifica si están alabeadas en el espacio:
Q0
2
2
d = ((Q0 – P0) · n) n/n = (∆0 · n) n/n
d
P
0
Ese vector tiene por módulo la distancia entre las rectas y es
perpendicular a las dos. Si es nulo, las rectas se cortan en el
espacio y hay que interpolar la intersección. Notar que no hizo
falta calcular una raíz cuadrada para el módulo de n, basta con
utilizar n2 = n·n y además, para saber si forman un plano, basta
verificar si ∆0· n se anula, sin dividir.
P0
Para interpolar I, usamos las áreas de los triángulos que se forman
∆P
I
con ∆Q fijo y los puntos de P (o viceversa). El área entre ∆Q y
∆0
P0, por ejemplo, es (P0−Q0)×∆Q/2 pero como necesitamos el
Q0
signo y vemos que da un vector en la dirección normal,
calculamos un valor proporcional (multiplicado por 2||n||) y con
signo: A(P0) = (P0−Q0)×∆Q⋅n. El cero interpolado es el área que corresponde al punto I:
A(I) − A(P0)
0 − (P0−Q0)×∆Q⋅n
(Q0−P0)×∆Q⋅n ∆0×∆Q⋅n
α = A(P ) − A(P ) =
=
=
.
(P1−Q0)×∆Q⋅n−(P0−Q0)×∆Q⋅n (P1−P0)×∆Q⋅n ∆P×∆Q⋅n
1
0
P1
Q1
∆Q
P1
∆0×∆Q⋅n
∆0×∆P⋅n
y, del mismo modo: β =
n2
n2
Solo resta verificar que α y β estén entre 0 y uno y calcular I = P0 + α ∆P.
Resumen de implementación:
a) ∆P, ∆Q, n = ∆P×∆Q. Si n≠{0,0,0} ⇒ b)
b) Si ∆0·n = 0 ⇒ c)
c) b = n×∆0, α’ = b·∆Q, β’ = b·∆P. Si {α’,β’} ∈ [0,n2]2 ⇒ d)
d) I = P0 + α’/n2 ∆P
α=
La intersección de un segmento (o rayo) y un triángulo en el
espacio es la situación más usual y, por suerte, es mucho más
sencilla; es un sistema de tres ecuaciones y tres incógnitas.
(1−α)P0+αP1 = (1−β−γ)Q0+βQ1+γQ2
Una matriz singular de coeficientes indica que las entidades son
paralelas o coincidentes y además los parámetros entre cero y
uno indican la pertenencia de la intersección al segmento y al
triángulo. Si se trata de una recta, α no importa; si se trata de un
rayo o semirrecta, α indica si la intersección está delante o
detrás del punto de partida P0 y además puede servir para
calcular la distancia al ojo (z-buffer).
Q2
P1
Q0
P0
Q1
La intersección de dos triángulos es un segmento en la recta de intersección de sus planos. En este caso
los parámetros son cuatro (dos de cada triangulo)
P0
y tenemos tres ecuaciones, por lo que el resultado
tiene un parámetro variable que define justamente
Q0
I
la recta de intersección. De todos modos, haremos
un análisis más sencillo, pero diferente.
np
Calculamos primero las normales como productos
nq
vectoriales de dos aristas en cada triángulo. Los
planos son paralelos o coincidentes si las normales
son paralelas. En caso contrario, la recta de
t
3/12
intersección pertenece a ambos planos y por lo tanto es perpendicular a ambas normales. La dirección
de la recta es: t = np×nq, pero para terminar de definir la posición de la recta en el espacio hace falta un
punto. En el plano definido por las dos normales, los triángulos se ven como segmentos y la recta se ve
como un punto I, que se puede calcular como la intersección de los segmentos, pero es más sencillo
considerar que I−P0 es perpendicular a np y que I−Q0 es perpendicular a nq, para calcular las
componentes en el plano:
I = δ np + ε nq
(I−P0 )·np = 0
⇒
δ np·np + ε np·nq = P0·np
⇒
δ np·nq + ε nq·nq = Q0·nq
(I−Q0)·nq = 0
Es un sistema de 2x2 del que se obtienen δ y ε y por lo tanto I y queda definida la recta.
Finalmente se intercepta la recta (I + α t) con las aristas ((1-β) Pi +β Pj) para definir la intersección de
los triángulos. Por cada β ∈ [0,1) obtenemos un valor de α y un punto. Si obtenemos dos puntos por
triángulo, ordenando los valores de α se averigua si la intersección existe y el segmento que la define.
Notar que β ∈ [0,1) , un intervalo semiabierto pues los vértices se cuentan sólo una vez. Hay que tener
cuidado con posibles errores de precisión: la recta no puede interceptar solamente una arista de un
triángulo a menos que coincida con la arista)
Cuando hay un mismo plano que intercepta (o
Qi (d’>0)
no) a muchos segmentos o triángulos o tetraedros
es mejor utilizar un algoritmo de level−sets. Se
calcula, para cada vértice una (pseudo)distancia
n
Iij
al plano {P0,n} y se buscar distancia 0 en las
aristas con extremos de distinto signo:
Qj (d’<0)
P0
d’i= |n|di = (Qi–P0)·n = Qi·n – P0·n
Notar que P0·n es constante.
Luego se interpola, buscando el valor 0, en cada
segmento o arista en la que cambie de signo entre
extremos:
d’i
0 − d’i
Iij = (1−α)Qi + αQj = Qi − d’ − d’ (Qj−Qi)
α = d’ − d’ ⇒
j
i
j
i
Circunferencias y Esferas
Aquí se presentan varios casos distintos. Podemos tratar de igual manera a la circunferencia en el
plano y a la esfera en el espacio; pero las circunferencias en el espacio (círculos o discos) se manejan
de un modo totalmente distinto. De la intersección general con discos, sólo diremos que hay que
calcular la intersección con el plano de soporte y verificar si es interior al círculo.
Para calcular la intersección entre una recta y una esfera (o circunferencia en el plano), se puede
plantear la ecuación de los puntos de la recta cuya distancia al centro sea igual al radio:
{C − [(1−α) P0 + α P1]}2 = r2 = [(C−P0) − α (P1−P0)]2
Poniendo el origen en P0 las ecuaciones se hacen más legibles. El resultado se traslada sumando P0.
(C − α P1)2 = r2 = C2 − 2αC·P1 + α2P12
⇒
P12 α2 − 2C·P1 α+ C2 − r2 =0
Dado que es una ecuación de segundo grado puede haber dos,
C┴ r’
una o ninguna solución. Para determinar el caso, hallamos el
2
n
discriminante y dividimos todo por P1 para ver que habrá
t
r
solución si:
P1
P0
∆ > 0 ⇒ C2 − (C·||P || )2 < r2 ⇒ C2 − (C·t)2 < r2
C
1
es decir, si la distancia del centro a la recta es
menor que el radio.
4/12
Un método alternativo, más sencillo y que sirve para todos los casos de circunferencias o esferas
contra rectas o planos consiste en calcular el pié de la perpendicular C⊥, verificar si esta dentro de la
esfera y luego calcular la intersección. Para hallar C⊥ utilizamos las ecuaciones deducidas antes para la
distancia del punto C a la recta o plano.
La misma figura muestra tres casos, que usan t o n:
a) Circunferencia y recta (P0,t) en el mismo plano.
b) Esfera y recta (P0,t) en el espacio, vemos el plano que forman la recta y el centro.
c) Esfera y plano (P0,n) en el espacio, vemos el plano de canto.
Todos esos casos se tratan igual por este método, como ya se explicó, se exceptúa sólo el caso del
disco contra una recta no coplanar.
Consideramos origen en P0 para simplificar. Se identifica primero el pié de la perpendicular desde el
centro a la recta o plano; como ya vimos, para la recta: C┴ = (C·t) t y para el plano: C┴ = C − (C·n) n.
Se compara luego el radio con la distancia entre C⊥ y C. Si hay intersección r’2 = r2 − (C┴ −C)2 define
la distancia a los dos puntos de intersección (C┴ ± r’ t) en la recta; o, si se trata de un plano contra una
esfera, r’ será el radio del disco de intersección, centrado en C┴ y en el mismo plano de normal n.
Nota: Usar como origen a P0 tiene sustento en que normalmente las rectas son rayos o semirrectas con
extremo en el punto de vista.
No podemos cubrir todos los casos y quedan varios que resultan útiles en CG, fundamentalmente las
intersecciones de rayos y planos con superficies paramétricas. Los métodos son siempre los mismos:
plantear de distintos modos las ecuaciones y elegir las simplificaciones y generalizaciones más
robustas. Como vimos, siempre hay que considerar si se trata de uno contra uno o de uno contra
muchos, en cuyo caso los métodos de optimización pueden obligar a usar técnicas distintas; por
ejemplo un rayo contra un triángulo o un rayo contra muchos triángulos o muchos rayos contra un
triángulo, en cada caso hay que analizar cual es la técnica más eficiente. Todos los casos de utilidad
están desarrollados e implementados en el libro de Buss: 3D Computer Graphics y con mucha mayor
extensión en el de Schneider y Eberly: Geometric Tools For Computer Graphic.
5/12
Optimización
La implementación de algoritmos geométricos debe hacerse con mucho cuidado para obtener las
prestaciones que se plantearon en la introducción de intersecciones. Primero se implementan las
ecuaciones tal como se deducen o se encuentran en la bibliografía, para verificar que el programa
funciona robustamente (siempre entrega un resultado útil) y con la precisión adecuada. Luego se puede
ajustar la eficiencia, sin perder los otros atributos, midiendo tiempos para miles o millones de
intersecciones, evitando utilizar algoritmos cuyo costo computacional en tiempo y memoria sea de
segundo orden o mayor en la cantidad de argumentos.
El mecanismo de optimización depende fuertemente del problema. El ejemplo mas importante de
intersecciones que se planteó aquí es el de rayo contra triángulo, puesto que la mayoría de los objetos
vienen dados mediante triangulaciones. En tal caso conviene averiguar en primer lugar si habrá
intersección, es decir si los parámetros correspondientes al triángulo estarán entre cero y uno. El
parámetro en el rayo se calcula solamente si se requiere la distancia al ojo (z-buffer) o, al menos,
averiguar si la intersección está delante del ojo. Por otro lado, también es muy frecuente el cálculo de
la intersección de un único plano con una gran cantidad de segmentos, por ejemplo cuando se corta un
objeto (sus aristas) mediante un plano para hacer clipping. En este caso se calcula el parámetro en el
segmento y solo cuando sepamos que habrá intersección; los parámetros en el plano no importan.
Las técnicas que veremos a continuación permiten el ordenamiento espacial y la simplificación de los
objetos para responder rápidamente a la pregunta: “¿puede haber intersección?”
Línea separadora y envoltorios
Dos objetos no se interceptan si sus proyecciones sobre alguna
línea no se solapan. Equivalentemente, si existe un plano que los
separe, dejando un objeto a cada lado.
Es muy sencillo proyectar muchos puntos en una línea, pero
encontrar una línea separadora puede ser más complicado e
ineficiente que calcular la intersección, por lo que se recurre a
proyecciones sencillas, por ejemplo las coordenadas (las líneas
son los ejes cartesianos); o la línea que une los centros.
Para los objetos complicados y los cóncavos se suele recurrir a envoltorios convexos simples. Separar
los envoltorios es más sencillo que separar los objetos. El análisis de intersecciones suele hacerse
primero con el envoltorio elegido, para luego analizar la intersección con el objeto.
CH
BS
AABB
OOBB
k−DOP
De izquierda a derecha, tenemos: el conocido convex−hull o mínimo envoltorio convexo; la esfera
envolvente o bounding−sphere o enveloping−sphere; el axis-aligned bounding−box o bounding−box a
secas, que podría traducirse como caja envolvente, es una caja ortogonal a los planos coordenados; el
oriented bounding−box o caja orientada, que puede estar definido por una dirección predefinida o por
los ejes principales del objeto (object−oriented bounding−box) y el k−discrete oriented polytope que
tiene k pares de direcciones de orientación. Todas tienen su extensión obvia a más de dos dimensiones.
El BB se calcula mediante los máximos y mínimos de cada coordenada. Los alineados (OBB y
k−DOP) con el máximo y mínimo calculado en un conjunto de direcciones (min_max(x·di)). La
mínima esfera, el menor OBB y el convex−hull son difíciles de calcular y requieren herramientas de
Geometría Computacional. Para juegos y Computación Gráfica en general, todos se pueden utilizar
aproximados y predefinidos al crear los objetos. El CH es especialmente útil cuando viene dado por
definición, por ejemplo en las curvas y superficies NURBS. La esfera provee la sencillez del cálculo
de sus intersecciones con otras o con rayos; es el envoltorio más sencillo y utilizado en juegos es la
6/12
esfera aproximada; ejemplos: La colisión o intersección entre dos objetos se descarta si los centros
están a mayor distancia que la suma de radios. La intersección de un objeto con un rayo se descarta si
el rayo dista del centro más que el radio.
Ordenamiento espacial
El análisis de intersecciones o de proximidad de puntos y objetos es esencialmente cuadrático: hay que
testear todos contra todos. Una rutina de orden cuadrático en el número de datos se puede hacer mucho
menos costosa si se subdivide el espacio en cajas (bins o buckets) que contienen unos pocos objetos y
se analiza el problema caja por caja. El paradigma de Divide and Conquer se basa en que la
∑pocos*pocos << todos*todos, normalmente ese principio se aplica recursivamente hasta el final (uno
contra uno) pero bien puede quedar en un estado intermedio de pocos contra pocos. El “mejor” método
para repartir objetos en cajas depende del problema; se pueden pre−ordenar los objetos, sus puntos o
sus envoltorios, dependiendo del problema en particular. El armado de las cajas se hace con estructuras
y algoritmos estándar y cada tipo de subdivisión está muy estudiado, solo se discute cual utilizar en
cada caso y ligeras variantes. Obviamente hay que considerar también el tiempo de división del
conjunto en cajas, el tiempo de armado de dicha estructura.
El ordenamiento más sencillo que puede pensarse es una simple subdivisión del espacio en cajas
idénticas. Normalmente entendemos por “espacio” el AABB del conjunto de objetos. Esta técnica
consiste en dividir cada coordenada en un número adecuado de partes. El principal problema aquí es la
gran cantidad de partes vacías; si la estructura queda muy desbalanceada (muy distinta cantidad por
celda) la reducción de tiempo no es muy grande. Una variante de éste método, que se utiliza en los
juegos en primera persona con recorridos por salas separadas, consiste en la obvia agrupación de
objetos en salas (más una relación de visibilidad a través de puertas y ventanas). Se denominan
métodos de cells and portals o celdas y portales.
Las mismas técnicas que se aprendieron para ordenamiento de números son generalizables para el
ordenamiento espacial, esa es casi una definición de Geometría Computacional (algoritmos y
estructuras de datos multidimensionales). En particular los árboles de divisiones recursivas reducen
mucho el costo algorítmico, en general a O(n log(n)) y la búsqueda de un elemento cercano es O(1).
Un primer refinamiento de la división en partes iguales consiste en subdividir recursivamente (cuatro
partes iguales en 2D u ocho en 3D) pero solo cuando la caja actual tiene más de determinada cantidad
de objetos o puntos. El método se denomina quadtree en 2D y octree en 3D.
Se puede utilizar una división más simple, que además puede extenderse mucho mejor a varias
dimensiones: el k-d tree, o árbol k-dimensional es una partición recursiva con un plano a la vez. Cada
plano puede partir a la mitad o por la mediana a la coordenada más larga de la celda o del BB de los
datos de la celda o simplemente ciclando (x, y, z, x, y, …) los planos cartesianos. Hay muchas
variantes, de acuerdo al método de selección y ubicación del plano de corte. Si los planos no están
alineados con los coordenados se denomina BSP-tree (binary space partition tree) y se utiliza con
mucha profusión en el ambiente de los desarrolladores de juegos.
División regular
Quadtree
k-d Tree
BSP Tree
7/12
Para el k-d-tree, se suelen ordenar los datos por coordenadas y partir con la mediana del conjunto de
cada celda. Esto produce árboles balanceados, es decir equilibrados en cantidad de elementos para
cada nivel de subdivisión, con ello se logran menos subdivisiones y menor profundidad total del árbol.
La selección del método y el balance costo/eficiencia dependen obviamente del problema particular.
Ejemplo: Algoritmo del Pintor mediante BSP-Tree. Se trata de realizar el renderizado en forma
ordenada desde el fondo hacia el frente, por ejemplo para objetos semitransparentes, aunque en general
se utiliza para determinar oclusión sin utilizar el z-buffer.
A
B
A
2
1
B
C
3
1
5
D
4
C
2
D
3
4
5
La explicación y el dibujo son bidimensionales, pero la técnica es exactamente igual en el espacio; el
divisor será un plano en lugar de una recta. No entraremos en los detalles complicadísimos de cómo
encontrar un divisor que no recorte objetos. En los juegos, esta construcción se hace en forma manual
para los objetos fijos, se hace una sola vez y se utiliza durante el desarrollo para el renderizado rápido.
A medida que se encuentra un divisor de los objetos restantes, éstos se asignan a cada lado del divisor,
construyendo un árbol de relaciones izquierda-derecha. Con el árbol construido (y probablemente
permanente) se indica, para cada divisor, de que lado está el observador. En la figura se indicó en rojo
la partición que contiene al observador en cada división. El orden de renderizado se obtiene
recorriendo el árbol en forma ordenada primero por donde no se encuentra el observador. La secuencia
de recorrido y renderizado es: A C 3 C D 4 D 5 D C A B 2 B 1 B A. Notar que el objeto 5 está más
cerca del ojo que el 2, pero aún así no puede ocluirlo, es decir que se recorren y renderizan primero, y
en forma completa, las ramas que no contienen al observador.
Ejemplo: Búsqueda del punto mas cercano con un k-d Tree.
En la figura el árbol parece estar construido utilizando los
puntos como divisores y admitiendo un solo punto interior en
cada hoja.
Por cada división del árbol se guardan: el BB, la coordenada
divisoria, el punto que la define, y un puntero a cada
subdivisión.
La búsqueda se realiza encontrando primero la hoja que
contiene al punto buscado. En cada rama se identifica de qué
lado de la subdivisión queda el punto y se pasa a la siguiente
hasta llegar a la hoja que lo contiene.
La hoja tiene un punto interior (o pocos), se busca el más
cercano y esa distancia define el radio de búsqueda posterior.
Ese radio define una circunferencia o, más sencillamente, un
cuadrado, que es su BB. Se busca, nuevamente en el árbol, en todas las hojas contenidas o que
interceptan a la circunferencia o su BB.
8/12
Diagrama de Voronoï y triangulación Delaunay
El diagrama de Voronoï es la última técnica de ordenamiento espacial que trataremos; pero le daremos
una atención más especial, debida a sus propiedades y múltiples aplicaciones.
En su forma más general consiste en dividir el espacio en celdas,
una para cada objeto; de modo que cada celda contiene los puntos
del espacio que están más cerca de su objeto que de cualquier otro.
Las múltiples variantes se deben al tipo de objetos y a la forma de
medir la distancia. Aquí estudiaremos sólo el diagrama de Voronoï
de puntos aislados y la distancia euclídea. El análisis lo haremos en
2D de un modo que permite analizar e implementar en 3D el mismo
procedimiento.
A los puntos dato (fijos) los llamaremos nodos, para diferenciarlos de los puntos comunes del espacio.
En la figura de arriba se muestra un conjunto de nodos y el diagrama de Voronoï. Todo el espacio se
divide en celdas convexas, cada una es el conjunto de puntos más cercanos a su nodo que a otro.
Para entender la geometría del problema tomamos un punto
cualquiera del plano y hacemos crecer una circunferencia centrada
en el punto. Si el punto está en el interior de alguna celda, la
circunferencia encuentra primero al correspondiente nodo, el más
cercano al punto. Si el punto está en una arista encuentra dos nodos
a la vez, la arista separa las dos celdas de los dos nodos equidistantes
del punto. Finalmente, si el punto es un vértice del diagrama, donde
se encuentran tres celdas, equidista de tres nodos a la vez.
Las aristas del diagrama de Voronoï separan dos celdas y equidistan de sus dos nodos. Forman parte de
la mediatriz de los dos nodos, que es la recta
que parte por la mitad y es perpendicular al
segmento que los une.
Los vértices, donde se juntan tres mediatrices,
son a su vez el centro de la circunferencia que
inscribe al triángulo formado por los tres
nodos. En 3D sucede lo mismo, las mediatrices
son planos y las circunferencias esferas.
El concepto y propiedad más importante es que un vértice del diagrama equidista de tres nodos y por
lo tanto es el centro de la circunferencia que inscribe al triángulo que forman. Lo mismo sucede en 3D
con esferas, cuatro nodos y el tetraedro que forman.
Los segmentos que unen a los nodos vecinos forman una triangulación. Aquí llamaremos triangulación
de un conjunto de nodos a una división de su convex-hull en triángulos
(o tetraedros en 3D, o símplices en general) de modo que:
1) Los nodos son vértices de los triángulos.
2) Dos triángulos comparten una arista completa o un nodo o nada
⇒ no hay uniones en T
3) Ningún triángulo tiene nodos en el interior.
⇒ Cada arista interior es compartida por dos triángulos.
⇒ No hay triángulos solapados
En la figura se puede notar que las celdas de nodos en el convex-hull son las únicas que tienen
extensión infinita. Esa característica se puede utilizar para determinar el CH del conjunto.
Dado el conjunto de nodos, hay muchas triangulaciones posibles. La triangulación que se obtiene
como “dual” del diagrama de Voronoï se llama Triangulación Delaunay.
Esa dualidad es un concepto extendido de la teoría de grafos. Cada vértice del diagrama es centro de la
circunferencia que equidista de los nodos y define el triángulo y se puede ver además la relación uno a
uno entre aristas (segmento - mediatriz) y entre celdas y nodos.
9/12
La siguiente tabla especifica en dos y tres dimensiones la dualidad de elementos.
Celda Voronoï
2D
Triángulo Delaunay
3D
Tetraedro Delaunay
Celda Voronoï
Celda
Arista
Vértice
Nodo
Arista
Triángulo
Celda
Arista
Cara
Nodo
Cara
Arista
Vértice
Tetraedro
Hay varios métodos propuestos y eficientes para construir un diagrama de Voronoï, o su equivalente
dual: la triangulación Delaunay. El método conceptualmente más sencillo aprovecha la característica
distintiva de la triangulación Delaunay: las circunferencias no contienen nodos en el interior.
La construcción se realiza agregando los nodos, de a uno, en una triangulación preexistente. Empieza
con un gran triángulo de nodos virtuales
(inexistentes) que envuelve a todo el conjunto.
Para cada nuevo nodo se buscan las
circunferencias que lo contienen, que deben ser
reemplazadas
por
otras
nuevas.
La
reconstrucción es local, se limita al entorno
natural (natural neighborhood) del nuevo nodo,
que es la unión de las circunferencias que lo
contienen. El conjunto de triángulos cuyas
circunferencias contienen al nuevo nodo forma
un polígono que envuelve al nodo y se
denomina “cavidad del nodo”, se reemplaza formando nuevos triángulos, cada uno con el nodo y una
arista exterior de la cavidad. En 3D la cavidad es un poliedro y el procedimiento es igual.
Cuando existen más de tres puntos “cocirculares” el diagrama de Voronoï tiene un vértice equidistante
de cuatro (o más) puntos. En tal caso, la triangulación genera problemas numéricos que se suelen
salvar perturbando la posición del nodo entrante, para restaurar la condición normal. En 3D el
problema es mucho mayor, porque la cocircularidad genera tetraedros aplastados conocidos como
slivers; hay una inmensa cantidad de técnicas publicadas para eliminarlos, pero es muy complicado.
El diagrama de Voronoï se obtiene naturalmente en procesos
de crecimiento que parten desde “semillas” fijas, Puede verse
en el caparazón de una tortuga, en el crecimiento de granos
apiñados o en el crecimiento de cristales en las aleaciones.
En la figura se muestra construido como una intersección de
conos vista desde arriba. Los conos simulan el crecimiento a
velocidad constante desde los nodos (crece el diámetro a
medida que aumenta la profundidad). Como método
constructivo es extremadamente ineficiente, pero para unos
pocos nodos, podemos visualizar el diagrama con unas pocas
líneas de código en OpenGL.
El diagrama de Voronoï y la triangulación Delaunay tienen propiedades muy fructíferas en
computación gráfica y geométrica, debido a que codifican naturalmente las relaciones de proximidad y
vecindad que, de otro modo, serían muy costosas de construir. Sobran ejemplos. Podemos averiguar en
forma muy eficiente cuales son los nodos cercanos a un determinado punto, averiguando a que
triángulo pertenece. Podemos planear el movimiento automático de un robot, esquivando objetos de la
escena, si lo obligamos a moverse por las líneas del diagrama de Voronoï. ¿Donde conviene poner una
nueva farmacia? En el diagrama de Voronoï de las farmacias existentes, elegimos el centro de la
circunferencia más grande, que es un vértice del diagrama.
10/12
Búsqueda lineal o linear walk
Para muchas operaciones de búsqueda de proximidad y en particular para la construcción incremental
del diagrama de Voronoï, se requiere saber a que esferas o círculos pertenece un punto (el nuevo nodo
a insertar) y podemos averiguarlo respondiendo a que tetraedro o triángulo pertenece. El proceso más
eficiente para hacerlo se denomina linear walk.
Tenemos una triangulación (no necesariamente Delaunay pero si convexa) de un conjunto de nodos y
queremos averiguar a que triángulo pertenece un punto del plano. El procedimiento consiste en partir
de un triángulo cualquiera y movernos por vecindades, de un modo recursivo que nos acerque cada vez
más al punto. Para ello debemos contar con una estructura de datos que identifique, para cada
triángulo, cuales son sus vecinos (por arista en 2D; por cara de tetraedros en 3D), ordenamos la lista de
modo que el vecino i-ésimo sea opuesto al i-esimo nodo del triángulo (i ∈ {0,1,2}). Podemos asignar
el puntero nulo al exterior del CH en las aristas de frontera.
1
α0 < 0
2
0
0 < α0 < 1
α0 > 1
1
2
0
Siguiendo la figura anterior, partimos del triángulo pintado y calculamos las coordenadas baricéntricas
en el punto. Sabemos que la línea del segmento opuesto a cada vértice separa el semiplano positivo del
negativo. La coordenada baricéntrica más negativa nos indica entonces a que vecino pasar.
Hay que aclarar que el nodo más cercano al punto no es necesariamente alguno de los nodos del
triángulo pero si debe estar entre los que definen las circunferencias que contienen al punto. Las
circunferencias se hallan buscando entre los vecinos de cada una hallada, empezando por el triángulo
que contiene al punto.
Cuando hay muchísimos triángulos, el proceso de búsqueda lineal se acelera si se precalcula una
estructura de ordenamiento espacial para el conjunto de nodos, puede ser un quadtree o un k-d-tree. Si
se colocan unos pocos nodos por celda terminal, basta incorporar el punto buscado en la estructura y
partir desde algún triángulo de un nodo de la misma celda terminal u hoja del árbol.
Otro mecanismo de aceleración se usa cuando se barren píxeles o vóxeles en imágenes o tomografías,
en tal caso conviene empezar la búsqueda por el triángulo que contenía al píxel anterior vecino. Muy
probablemente, el actual esté en el mismo y si no, en un vecino.
Cuando se posee cualquier tipo de polígonos o poliedros, no necesariamente simpliciales (triángulos o
tetraedros) el proceso de búsqueda se puede realizar también buscando una cara o lado que intercepte
el rayo que une un punto interior del polígono con el punto buscado. El ejemplo más común es ubicar
en que sala está el personaje móvil en un juego, o que sala señala el jugador con el cursor.
11/12
Circunferencia de tres puntos, esfera de cuatro…
En el proceso de armado del diagrama de Voronoï, se crean y destruyen esferas o circunferencias con
cada punto incorporado, por lo tanto el algoritmo utilizado para definirlas debe implementarse con la
mayor eficiencia y robustez posibles. El análisis siguiente es válido en cualquier cantidad de
dimensiones, pero fijemos ideas en 2D.
Queremos el centro C y radio r de la circunferencia definida por los tres
P1
puntos {P0, P1, P2}. La ecuación que los define plantea la distancia al
centro, común para todos los puntos:
r2 = (C−Pi)2 = C2 − 2 C·Pi + Pi2
En 2D son tres ecuaciones (i ∈ {0,1,2}) y tres incógnitas (Cx, Cy, r2),
C
P2
pero cuadráticas. Para librarnos de C2 ponemos el origen en P0, lo que
r
equivale a restar P0 a cada punto. La primera ecuación queda:
r2 = (C−P0) 2 = C2, (el modulo del vector r indicado en el dibujo)
P0
reemplazando r2 en las siguientes ecuaciones queda:
C2 = C2 − 2 C·Pi + Pi2 ⇒ 2 C·Pi = Pi2 (i ∈ {1,2})
De ese sistema lineal 2x2 (o dim x dim en más dimensiones) se calculan C y su módulo r, luego se
ubica C en el sistema original sumando P0.
El determinante de los coeficientes es un múltiplo del área del triángulo (volumen del tetraedro, etc.).
Si se buscan las coordenadas baricéntricas αi de C, se puede suponer origen en P0 y los dos Pi como la
base del sistema, queda:
2gjk αj Pik = 2gjk αj δik = 2gji αj = 2αj (Pi·Pj) = Pi2 (i,j,k ∈ {1,2})
Reordenando la ecuación original, en el sistema original:
Pi2 = 2 C·Pi + r2 − C2,
el primer miembro equivale a “subir” los puntos a un paraboloide de revolución en una dimensión más y
el segundo miembro es un plano de normal 2C y término independiente r2 − C2. La intersección de ambos, proyectada de
nuevo, es la circunferencia. Si P{x,y} representa cualquier punto del plano, w = P2 = x2 + y2 es un paraboloide en una
dimensión más. Toda la triangulación Delaunay coincide con la proyección del convex−hull del conjunto de puntos subidos
al paraboloide y de hecho esa lifting transformation se suele utilizar para construirla y, en general, es un mecanismo muy
utilizado para linearizar ecuaciones geométricas de segundo grado. Es parecido al tratamiento de linearización que provee
el espacio proyectivo. Por ejemplo, un punto está dentro de la circunferencia si su versión subida (lifted) al paraboloide está
debajo del plano, esto se reduce a calcular el signo del determinante (triple producto escalar) que define la distancia del
punto al plano. No hace falta calcular la circunferencia, el signo del determinante discrimina si el punto está dentro o fuera.
Néstor Calvo
Computación Grafica
FICH - UNL
12/12
Descargar