¿Cómo puedo sumar y restar polígonos convexos?

12

Tengo dos polígonos convexos 2D superpuestos entre sí . Estoy buscando un algoritmo para restarlos y agregarlos . El resultado debe ser un único polígono cóncavo o (incluso mejor) un conjunto de los convexos más grandes que forman el resultado cóncavo (por ejemplo, triángulos).

ingrese la descripción de la imagen aquí

( Izquierda: los polígonos superpuestos iniciales. Medio: el polígono cóncavo resultante después de sumar. Derecha: un conjunto de polígonos convexos que forman el resultado cóncavo. Aquí sería mejor obtener polígonos convexos más grandes que un triángulo por razones de rendimiento. dos polígonos superpuestos conducirían a la misma imagen que a la izquierda pero con el área superpuesta que no forma parte del polígono resultante).

¿Cómo puedo hacer esto?

Sebastian Barth
fuente
¿Estamos hablando de 2D aquí? porque en 3D combinar polígonos no tiene mucho sentido.
concept3d
Sí, sry, ¡estoy hablando de 2D! Aunque no veo por qué no tiene menos sentido en 3D que en 2D.
Sebastian Barth
2
agregar dos polígonos en 3D, si son planos, no tiene mucho sentido a menos que estén en el mismo plano, si tienen volumen (sólidos), entonces es una historia diferente.
concept3d
Ok, lo tengo No estaba pensando en gráficos, sino en objetos de colisión. Gracias por la aclaración.
Sebastian Barth
Además, encuentre todos los puntos que se cruzan y agregue los vértices a un conjunto. El conjunto es importante para evitar la superposición. Luego, simplemente agregue todos los vértices de las otras dos formas en el conjunto. Este conjunto contiene todos los vértices de la forma aditiva.
Vaughan Hilts

Respuestas:

9

TL; DR Debe implementar operaciones booleanas utilizando árboles BSP.

Bueno, parece que estamos hablando de geometría sólida constructiva aquí. He implementado CSG a nivel comercial, así que sé una o dos cosas al respecto.

El artículo clásico sobre CSG se llama Combinar operaciones de conjuntos poliédricos de rendimientos de árboles BSP , para ser sincero, es demasiado para explicar aquí, pero hablando brevemente, el algoritmo trata con polígonos que se encuentran en el mismo plano que una partición de espacio binario, básicamente construyendo un árbol BSP de cada malla poligonal. El segundo paso es fusionar esos árboles BSP; simplemente toma un árbol e insértalo en el otro. Luego, el algoritmo procede a explicar cómo lidiar con cada nodo de hoja para dividir y restar los nodos, los nodos que no se necesitan en la forma final se eliminarán, otros recibirán el padre apropiado.

¡Pero espera! Ese documento básicamente habla de mallas poligonales y planos 3D, ¿NO?

El algoritmo puede generalizarse en cualquier dimensión, por lo que en su caso 2D es fácil usar segmentos de línea en lugar de planos como particiones binarias. Por lo tanto, cada polígono se convertirá en un árbol BSP que los dos se fusionarán. Finalmente atraviesas el árbol resultante para generar el polígono final,

Tenga en cuenta que este algoritmo y CSG en general no se ocupan de la representación y las caras de malla directamente y realmente no están listas para la representación, por lo que debe extraer las caras de los árboles BSP finales. También encuentro que el trazado de rayos es un enfoque más fácil para representar el resultado CSG, solo necesita los rayos para atravesar el árbol en lugar de extraer y dividir las caras (recuerde que solo tratamos con particiones binarias).

Respecto a la robustez numérica. Es bueno tener en cuenta que hay dos tipos de cálculos geométricos,

  • Los que se basan en la construcción, construye una forma basada en el resultado de una operación anterior. Por ejemplo y = sqrt(x)y luego usar yen una nueva operación. Esto se llama construcción; El problema es que los errores numéricos se acumularán rápidamente.
  • Alternativamente, hay operaciones que usan predicados en su lugar, esencialmente en lugar de usar construcción, simplemente pregunta si una condición es verdadera / falsa y usa el mismo valor en una operación diferente. Las pruebas clásicas incluyen incircle y la prueba de orientación; Esto también es sospechoso de errores numéricos, especialmente si usa precisión simple o doble, pero generalmente dará resultados mucho mejores. existen otras soluciones que varían en velocidad y precisión. Este es uno de los documentos recientes que evitan la construcción mediante el uso de una geometría basada en el plano para obtener resultados precisos. También citaré del artículo:

Sugihara e Iri [SI89] describieron por primera vez el concepto de representación basada en planos de mallas poligonales. Este tipo de representación proporciona una ventaja importante cuando se trata de tareas que implican cambiar la topología de sólidos representados por mallas como la evaluación de expresiones booleanas: no se debe construir nueva información de geometría primaria para obtener el poliedro resultante

ingrese la descripción de la imagen aquí

Y finalmente me gustaría agregar, si desea comenzar su implementación de BSP CSG, recomendaría comenzar con las preguntas frecuentes de BSP .

concepto3d
fuente
Genial, pero contra-intuitivo, considerando que un BSP de un polígono o poliedro convexo es una lista. Gran papel
3Dave
@DavidLively sí, pero puede convertirlo en un árbol equilibrado eligiendo el plano raíz para que no sea de las caras. En realidad, esto es parte del desafío del que no hablan
concept3d
Ah, eso tiene sentido. Una especie de BSP híbrido, entonces.
3Dave
@DavidLively también el BSP no es realmente fácil de renderizar, aunque la pregunta OP es un caso simple, en un caso más complejo con geometría de millones de polígonos, una vez que haya terminado la construcción del árbol, está lejos de terminar.
concept3d
@ concept3d Espero que esto no sea demasiado molesto ya que esta es una respuesta de 5 años, pero hay dos cosas que realmente no entiendo: cuando intento determinar si un punto se encuentra a la izquierda o derecha de un plano / línea, ¿no sería más fácil simplemente rotar todo de manera que el plano / línea corresponda a un plano / línea trivial y luego considerar las coordenadas del punto girado? ¿Qué tal usar el algoritmo Sutherland-Hodgman en lugar de árboles BSP? Suena bastante similar a este enfoque.
John P
1

Siguiendo tu ejemplo:

Elija un vértice inicial en el polígono A y luego comience a verificar si hay bordes de intersección en el sentido de las agujas del reloj (o en sentido contrario). Si no hay una intersección, agregue el vértice anterior a su polígono resultante. Si hay una intersección, agregue el punto en el que se intersectaron con su polígono resultante y luego comience a iterar sobre el polígono B, en el mismo orden de enrollamiento. Haga lo mismo, nuevamente cambiando al polígono A si ocurre una intersección.

Una vez que haya acumulado todos los vértices para el nuevo polígono, realice un algoritmo de triangulación en él. El método de recorte del oído es fácil de implementar, pero existen opciones más rápidas.

Importante: asegúrese de que el vértice en el que comienza no esté dentro del otro polígono (consulte este artículo para ver las pruebas de punto en polígonos).

Iterando sobre cada borde, para verificar una intersección sería un algoritmo O (n ^ 2). Puede acelerarlo buscando primero los vértices que están dentro del otro polígono, ya que los bordes vinculados a esos vértices serán los que se cruzan.

Culpa
fuente
0

Si desea un polígono cóncavo , simplemente elija el borde más cercano entre los dos polígonos de entrada y agregue dos bordes nuevos:

ingrese la descripción de la imagen aquí

Convexo se vuelve un poco más complicado:

ingrese la descripción de la imagen aquí

Un enfoque es iterativo porque agrega vértices desde el segundo polígono al primero, uno a la vez, evolucionando el primer polígono en un contenedor que lo abarca todo.

Básicamente:

  • Iterar a través de los vértices del segundo polígono.
  • Para cada vértice V, itera a través de los bordes del primer polígono:
  • Encuentre un "rango" de bordes que estén todos de cara al vértice
  • tome el par externo de vértices que definen ese rango y elimine todos los bordes en el rango que los conecta
  • Dibuja dos nuevos segmentos desde esos vértices exteriores hasta el nuevo vértice (desde el segundo polígono), asegurándote de que los nuevos bordes estén orientados en la dirección correcta.
  • Pase al siguiente vértice del segundo polígono.

Aquí hay un diagrama que ilustra el proceso para el primer vértice:

ingrese la descripción de la imagen aquí

Un método más rápido es encontrar la lista de bordes en cada polígono que no están frente al otro polígono, eliminar todo lo demás y conectar los puntos finales de las tiras de línea restantes entre sí.

Quizás alguien más pueda intervenir con algunos consejos de resta.

3Dave
fuente
Esto solo parece abordar la mitad del problema (además). También podría ser bueno señalar cómo funcionan los algoritmos o podría optimizarse si los polígonos se superponen.
El algoritmo ignora implícitamente los vértices que están "dentro" del polígono objetivo, lo que también compensa el problema en el que un borde del segundo polígono cruza el primero.
3Dave
Eso casi equivale a la fase de fusión (punto 4 del algoritmo de fusión del casco . En mi caso, no es una solución correcta encerrar más área después de combinar los polígonos. La solución correcta sería mantener ambos polígonos como están, ya que no son t superpuestas, ni tocar.
Sebastián Barth
@luftgewehrindianer Ah - Sí, eso hace una gran diferencia. Quizás entendí mal la pregunta. ¿Desea agregar los polígonos juntos, sin preocuparse de si el resultado es convexo o cóncavo? ¿O generar un conjunto convexo basado en la intersección? (Ignorando la resta por el momento.)
3Dave
@DavidLively Imagine dos polígonos convexos del mismo color y sin borde. Cuando se superponen, parece un nuevo polígono convexo o cóncavo. Intenta encontrar una triangulación de la forma combinada. No agregue área entre ambos polígonos.
danijar