Calcular el diagrama de Voronoi de una región dentro de una caja


8

Me enfrento a un problema de la siguiente manera: tengo una caja llena de puntos con una cierta distribución desconocida y me gustaría calcular su diagrama de Voronoï. El problema es que la cantidad de puntos es tan grande que puede ser imposible hacerlo para la distribución completa.

Por lo tanto, he planeado hacer eso solo para una región dentro de la caja, donde el número de puntos no era tan grande. Para hacerlo, necesito saber cómo calcular la región mínima que puede afectar al diagrama de Voronoi de cierta región más pequeña dentro de ese cuadro.

En otras palabras, me gustaría calcular el diagrama de Voronoï de los puntos dentro del cubo pequeño de la figura a continuación que se ajusta al diagrama de Voronoï que tendría los puntos de la caja llena almacenando el diagrama de Voronoï más pequeño posible en la memoria.

Explicación del problema.


3
He visto personas, especialmente en astrofísica, que calculan la teselación de grandes conjuntos de puntos. Vea el trabajo de Volker Springel. Por ejemplo, incluso hay un código fuente abierto aquí github.com/regonzar/paravt que puede serle útil. Ver también arxiv.org/abs/1601.06429
cfdlab

Todavía necesitaría alguna forma de hacerlo usando la estrategia del cubo pequeño, pero muchas gracias. Le echaré un vistazo.
ccorbella

1
Lo siento, tengo problemas para tratar de entender esta oración "Me gustaría calcular el diagrama de Voronoï de los puntos dentro del cubo pequeño de la figura a continuación que se ajusta al diagrama de Voronoï que tendría los puntos de la caja llena almacenando el diagrama de Voronoï más pequeño posible en la memoria ".
nicoguaro

Lo siento, solo quise decir que me gustaría calcular el diagrama de Voronoï del cubo pequeño, teniendo en cuenta que en esa región debería ser el mismo que el diagrama que obtendría si calculo usando todos los puntos de la caja. Para hacerlo, espero necesitar más puntos que los que están dentro de la caja (de lo contrario, no creo que pueda encajar con otro cubo si sigo la misma estrategia allí), pero me gustaría almacenar lo menos posible puntos.
ccorbella

@ccorbella No es una respuesta, pero ¿con qué herramienta proporcionaste esta bonita figura, por favor? Tal vez agregue en un subtítulo la herramienta.
Jan Hackenberg

Respuestas:


2

Para calcular el diagrama de Voronoi de grandes conjuntos de puntos (> 100 millones), puede usar el siguiente algoritmo:

1) create a kd-tree with all the points
2) for each point p [in parallel optionally]
     N = 10
     while not finished
       compute the N nearest neighbors of the point p
       compute the intersection of the N half-spaces defined by p 
       and the neighbors
       if there is a neighbor further away than 
         twice the radius of the ball centered on p and 
         bounding the intersection, finished = true
       N = N * 1.5
  // when exiting the loop, the computed intersection 
  // corresponds to the Voronoi cell of p, because no other bisector
  // can contribute to the Voronoi cell.

El algoritmo se explica con más detalles en mi artículo . Puede ser trivialmente paralelo (simplemente agregue "#pragma omp parallel for" antes del bucle principal), ya que no hay dependencia de datos. Está implementado en mi biblioteca de programación GEOGRAM C ++ (junto con un Kd-Tree eficiente en memoria que escala hasta más de 100 millones de puntos). Tenga en cuenta que en GEOGRAM también hay una implementación estándar paralela de Delaunay / Voronoi que funciona bien con hasta 100 millones de sitios.

Con respecto a la implementación paralela del algoritmo clásico (Boywer-Watson), la implementación de GEOGRAM se documenta aquí (ver también el archivo fuente c ++ asociado que tiene comentarios extensos). No tengo ningún artículo publicado al respecto, escribiré uno si el tiempo lo permite. La idea principal es usar spinlocks asociados con el tetraedro para garantizar que solo un hilo individual pueda modificar un tetraedro.


Antes que nada, gracias por tu respuesta. Lamento decirle que su artículo parece que ya no se carga (al menos la versión completa de la web que vincula). De todos modos, ¿podría explicarme cómo implementaría ese algoritmo de diagrama de Voronoi en paralelo?
ccorbella

Gracias por notificar eso, he arreglado el enlace (el nuevo enlace tiene el PDF, haga clic en el icono de PDF para obtenerlo). También he agregado una breve explicación / enlace a la implementación paralela de Delaunay.
BrunoLevy

Nota: funcionará bien siempre que los puntos estén distribuidos uniformemente (el rendimiento puede disminuir si tiene una alta variación de densidad de puntos).
BrunoLevy

2

Parece que los expertos no responden su pregunta, así que intentaré darle una idea. Pero antes de hacerlo, sugiero encarecidamente que busque en la literatura algunos métodos sofisticados que ya se han desarrollado. Sin embargo, sin garantizar que esta sea una sugerencia buena, rápida o eficiente, propongo la siguiente metodología. Tenga en cuenta que es posible que haya cometido algunos errores, por lo que no garantizo que todo sea completamente correcto, pero espero que la idea del método le brinde algún enfoque que lo ayude a resolver su problema.

Deje que sea ​​el conjunto de sus puntos en todo el cubo "grande". Arregle su cubo "pequeño" en algún lugar del cubo grande y deje que sea ​​el conjunto de puntos contenidos en , es decir, Inicialmente establezca .VCVCCVC=VC.VC=VC

Paso 1: generar el diagrama de Voronoi . Para cada punto denota por su celda Voronoi, que es un poliedro convexo en tres espacios. Además, denote con los vértices de la celda de Voronoi centrados en y con los vértices de todos los Voronoi células del diagrama de Voronoi .Vor(VC)vVCVor(v)W(v)vVCW(VC)=vVCW(v)Vor(VC)

Paso 2: Colorea todos los puntos de y todos los vértices de Voronoi blancos.VCW(VC)

Paso 3: Para cada vértice de Voronoi dibuje la esfera de Delaunay centrada en , es decir, la esfera con centro y radio la distancia entre y uno de los puntos de cuya celda Voronoi tiene como vértice (no importa qué punto, hay varios, pero el resultado es siempre el mismo).wW(VC)wwwVCw

Caso 3.1. Si la esfera de Delaunay de está contenida en el cubo , colorea negro.wCw

Caso 3.2. Si la esfera de Delaunay no está contenida en el cubo pero no contiene ningún punto de en su interior (abierto), colorea el punto negro.CVw

Caso 3.3. Si la esfera de Delaunay de contiene puntos de en su interior (abierto), (1) agregue los puntos de contenidos en el interior de la esfera al conjunto y (2) mantenga el color del punto blanco . wVVVCw

Paso 4: Para cada punto verifique si todos los vértices Voronoi de su celda Vornoi son negros. Si no todos son negros, mantenga el color de blanco. Si son negros, color negro.vVCW(v)vv

Paso 5: Verifique si todos los puntos del conjunto original son negros.VC

Caso 5.1. Si son todo negro, el Voronoi diagrama restringido al cubo es la porción local de la mundial Voronoi diagrama restringido a . Final.Vor(VC)CVor(V)C

Caso 5.2. Si hay vértices blancos en , entonces regrese al Paso 1. En el Paso 1, al generar el nuevo diagrama de Voronoi , uno mantiene las celdas de Voronoi alrededor de los puntos negros de igual, mantiene todo negro Voronoi vértices de y hace alteración solo en relación con los blancos. V o r ( V C ) V C W ( V C )VCVor(VC)VCW(VC)

Espero que esto ayude.


1

La forma más sencilla de hacerlo es rodear su caja interna con una caja más grande que contenga al menos todos los vecinos más cercanos de los puntos dentro de su caja interna. Tenga en cuenta que surgirá un problema cuando el cuadro interno esté cerca del borde del cuadro de datos que lo abarca: no tiene puntos externos.

Calcular un mosaico Voronoi / Delaunay puede ser más sutil de lo que piensas. Una de las cuestiones es cómo decidir con precisión si un punto está en un lado u otro de un plano / línea de teselación.

Existe la muy completa biblioteca C ++ "CGAL" para hacer esto en http://www.cgal.org/ . Mis colegas y yo hemos usado esto en varios artículos publicados en astrofísica: parece ser sólido como una roca para abordar todas las dificultades potenciales en la creación de estas teselaciones.


Muchas gracias por su respuesta. Entonces, mi pregunta debería reescribirse, si así lo desea, como "cómo encontrar los puntos vecinos más cercanos de los que están dentro del cubo haciendo el menor número de cálculos". Mi problema fue básicamente ese. ¿Conoces alguna forma de hacerlo?
ccorbella

¿Cómo se decide qué tan grande debe ser la caja exterior? Si no es lo suficientemente grande, es posible que no obtenga la restricción del diagrama completo en la caja pequeña original. Creo que la decisión correcta sobre un vértice de una celda voronoi del diagrama local es un vértice del diagrama global, es decir, un vértice que no será alterado por ningún recálculo futuro del diagrama voronoi local, se basa en si el interior de la correspondiente esfera delaunay contiene cualquier punto del conjunto total de puntos o no. Esta es exactamente la definición de una célula delaynay, que es dual a una célula voronoi.
Futurólogo el

@ConradCorbellaBagot Para el cálculo de los vecinos más cercanos en un gran conjunto de datos n-dim, existe un algoritmo muy eficiente . Tal vez quieras decir en qué estás realmente interesado.
Bort

Las teselaciones de Voronoi / Delaunay están bien definidas tanto en un conjunto de puntos infinitos como en un conjunto de puntos que está limitado, pero no en un subconjunto de puntos de un conjunto más grande. Para tales subconjuntos, debe tomar una decisión de compromiso arbitraria. En cosmología, donde tenemos una caja finita en un universo infinito, elegimos condiciones de contorno periódicas. Cuando hago análisis de imágenes en parte de una imagen, "visto" el límite con los primeros vecinos más cercanos de los puntos que definen el límite (hay complicaciones a considerar). Me parece que ir al próximo vecino más cercano tiene relativamente poca ganancia.
JonesTheAstronomer

Hay una presentación detallada de algo de esto en adsabs.harvard.edu/abs/2011MNRAS.416.2494P que se puede descargar libremente desde la revista y el arXiv. También tiene una discusión sobre la reconstrucción no lineal de Kriging de un campo de densidad utilizando estas teselaciones. La fuente de datos aquí es astronómica, pero la discusión es bastante genérica (para conjuntos de datos tridimensionales).
JonesTheAstronomer

1

Entiendo su pregunta como: Quiero dibujar el diagrama de Voronoi para un subconjunto de puntos de modo que sea el mismo que se obtiene al considerar el conjunto completo de puntos. Los diagramas de Voronoi se dibujan uniendo primero los puntos vecinos y luego dibujando un plano perpendicular a la línea en el punto medio. Haces esto para todos los vecinos más cercanos y tienes un diagrama de voronoi cerca de un punto. Haga esto para todos los puntos y tendrá un diagrama de voronoi para todos los puntos. Usted ve, los diagramas voronoi se definen localmente. No hay un segundo efecto de vecino más cercano o tercer vecino más cercano. Solo el primer efecto vecino más cercano. Entonces, todo lo que tiene que hacer para obtener un diagrama voronoi con un subconjunto de puntos es identificar los puntos en la subregión de interés, conectarlos con todos sus vecinos más cercanos respectivos, y dibuje un plano que pase por los puntos medios de este segmento de línea y perpendicular al segmento de línea. Este diagrama será el mismo para una región local, ya sea que considere una subregión o una región completa.


Dos preguntas. En primer lugar, "Hay un segundo efecto vecino más cercano o tercer vecino más cercano" debería ser "No hay ...", ¿verdad?
ccorbella

Si. Gracias por señalar eso. Actualizaré la respuesta. ¿Cuál es la segunda pregunta?
Kaustubh Kaluskar

Lo siento, estaba editando el comentario xDD Y el otro, sé que los diagramas de Voronoi se definen localmente (en otras condiciones, mi pregunta no tendría respuesta). Mi pregunta debe reescribirse, si así lo desea, como "cómo encontrar los puntos vecinos más cercanos de los que están dentro del cubo haciendo el menor número de cálculos". ¿Conoces alguna forma de hacerlo? De todos modos, muchas gracias por tu tiempo.
ccorbella

1
Yo uso la función knnsearch en MATLAB. Mi conjunto de datos típico es de alrededor de 1,5 millones de puntos y lo hago en mi computadora portátil. Desde el sitio web de Mathworks: 'IDX = knnsearch (X, Y) encuentra el vecino más cercano en X para cada punto en Y. IDX es un vector de columna con mis filas. Cada fila en IDX contiene el índice del vecino más cercano en X para la fila correspondiente en Y '. Aquí X sería su conjunto de datos completo e Y son puntos dentro del cubo.
Kaustubh Kaluskar

En primer lugar, muchas gracias una vez más. Voy a intentarlo con dificultad No estoy seguro si puedo ejecutar un algoritmo como un árbol kd en una cantidad tan grande de puntos, ya que dice que "Para grandes dimensiones (20 ya es grande) no espere que esto correr significativamente más rápido que la fuerza bruta. Las consultas de vecinos más cercanos de gran dimensión son un problema abierto sustancial en informática. "...
ccorbella

-2

Le sugiero que tenga un enfoque visual e intuitivo utilizando Grasshopper para Rhinoceros3D. Aunque Rhinoceros es un paquete CAD comercial y Grasshopper es un complemento para él, puede ejecutar complementos de forma gratuita sin limitaciones y realizar sus experimentos (Rhino3D sin licencia limita solo el almacenamiento de archivos de Rhino). Grasshopper incluye una gran cantidad de funciones matemáticas utilizadas en un lienzo, y los diagramas 3D Voronoi son una de ellas. un cubo Voronoi hecho con Grasshopper3D en Rhino3D


2
El enlace es interesante pero esto no responde la pregunta.
BrunoLevy

Eso no era lo que estaba pidiendo, pero gracias por la herramienta.
ccorbella
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.