¿Cómo averiguar de manera confiable si dos curvas planas de Bezier se cruzan? Por "confiablemente" quiero decir que la prueba responderá "sí" solo cuando las curvas se crucen, y "no" solo cuando no se crucen. No necesito saber en qué parámetros se encontró la intersección. También me gustaría usar números de punto flotante en la implementación.
Encontré varias respuestas en StackOverflow que usan los cuadros delimitadores de las curvas para la prueba: esto no es lo que busco, ya que tal prueba puede informar la intersección, incluso si las curvas no se cruzan.
Lo más cercano que encontré hasta ahora es la " cuña delimitadora " de Sederberg y Meyers, pero "solo" distingue entre la intersección de uno o dos y más, mientras que quiero saber si hay cero. y una o más intersecciones.
fuente
Respuestas:
Una forma alternativa de formular el problema es definir una función que proporcione la distancia entre puntos en las dos curvas, en función de los parámetros de las curvas. Luego intente encontrar el mínimo global de esta función. Si las curvas se cruzan, el mínimo será cero; de lo contrario, el mínimo será una distancia positiva.
Para ser explícito, dado un par de curvas 2D definidas por , defina la distancia al cuadrado comoc1,c2:[0,1]→R2
Para curvas cúbicas, la función es entonces un polinomio de sexto grado en dos variables. Luego puede aplicar técnicas de optimización numérica como el método simplex o el descenso de gradiente conjugado . Desafortunadamente, la función puede tener varios mínimos locales (no es convexa), por lo que la optimización no es fácil. Puede que haya métodos de optimización más especializados disponibles para polinomios, pero esta no es un área de especialización para mí.f
fuente
[Descargo de responsabilidad: creo que lo siguiente debería funcionar, pero en realidad no lo he codificado yo mismo]
No podía pensar en un método "trivial" para producir una respuesta sí / no, pero lo siguiente sería un enfoque razonable para una solución práctica a la pregunta.
Supongamos que nuestras curvas son A (s) y B (t) con los puntos de control { A0, A1..An } y { B0, .. Bm } respectivamente.
Me parece que, dados un par de Béziers 2D para los que deseamos determinar si se cruzan o no, hay seis casos a considerar:
Caso en el que podemos determinar "trivialmente" que no se cruzan.
Caso en el que se cruzan un número finito de veces y podemos determinar "fácilmente" que definitivamente se cruzan al menos una vez (pero en realidad no nos importa dónde ocurren esas intersecciones)
Uno de los Beziers es degenerado, es decir, un punto (que ocurrirá si todos los puntos de control son idénticos). Podemos suponer que ya hemos manejado el caso donde ambos son puntos.
Una o más de las curvas están cerradas, por ejemplo. A0 == An. Para simplificar la vida, subdividiremos tales curvas y comenzaremos nuevamente.
Hay un número infinito de puntos de intersección porque cada uno es un subconjunto de un Bézier "padre" y se superponen.
No estamos seguros de los casos anteriores y necesitamos más investigación
Por el momento ignoraremos 3 y 4, pero volveremos a ellos más tarde.
Caso 1
Como insinúa en su pregunta, si los cuadros delimitadores respectivos de los puntos de control de A y B ), no se cruzan, entonces las curvas no pueden cruzarse. Obviamente, esta es una prueba de rechazo rápido, pero es demasiado conservadora. Como probablemente sepa, con una curva de Bezier, el casco convexo de sus puntos de control forma un límite (más apretado) en la curva. Por lo tanto, podemos usar la técnica de eje de separación para decidir si los cascos de A y B no se cruzan. (por ejemplo, como se muestra en Wikipedia :)
Caso 2
Si la prueba del caso 1 falla, puede verificar la existencia "trivial" de una intersección. Ahora hay probablemente mejores formas de hacer esto, pero se me ocurrió el siguiente enfoque, relativamente barato:
Considere solo la curva A:
Sabemos que la curva comienza en , termina en y se ubicará dentro del casco convexo. Para simplificar, calculemos la dirección del segmento de línea y los límites a cada lado (es decir, tome los productos de puntos de los puntos de control restantes contra la perpendicular a ).A n ¯ A 0 A n ¯ A 0 A nA0 An A0An¯¯¯¯¯¯¯¯¯¯¯¯ A0An¯¯¯¯¯¯¯¯¯¯¯¯
Si hacemos lo mismo con la curva B, obtenemos el siguiente (posible) caso:
Si encontramos que y están fuera de los límites opuestos de B y que y están fuera de los límites de A, entonces, por la continuidad de Béziers, debe haber al menos una intersección.A n B 0 B mA0 An B0 Bm
Caso 6
Si no podemos mostrar inmediatamente ninguno de los casos anteriores, divida cada uno de los Béziers en dos "mitades", es decir, . Esto es relativamente sencillo (dejado como un ejercicio para el lector) pero es particularmente trivial para Beziers cuadráticos :A1,A2,B1,B2
Compare recursivamente las 4 combinaciones: . Claramente, si todos pasan el caso 1, no hay intersección. Si alguno falla 1, continúe con el resto de las pruebas con ese subconjunto reducido.(A1,B1),(A2,B1)...(A2,B2)
Caso 3 y 5
Aquí es donde se vuelve un poco más tedioso.
Si el "caso 3" supera la prueba del "caso 1", me parece que necesita resolver una intersección real. Dado que hay un proceso simple para mapear los N puntos de control de un Bézier, A (s), a los puntos N-1 del Bézier, A '(s), que representa su primera derivada entonces (siempre que se tenga cuidado con el situaciones relativamente raras, llamadas "degeneradas", donde la primera derivada llega a cero), entonces la iteración de Newton (en una dimensión) podría usarse para encontrar soluciones potenciales.
Tenga en cuenta también que, dado que los puntos de control de A '(s) están vinculados a los valores derivados, existe la posibilidad de eliminar rápidamente algunos casos.
El caso 5 parece relativamente improbable, por lo que tal vez solo si después de algunas recursiones no hay pruebas concluyentes, se podría probar cada punto final de A contra la curva B y viceversa. Esto solo daría una prueba de intersección, no una prueba de no intersección.
fuente