Teste confiável para interseção de duas curvas de Bezier

9

Como descobrir com segurança se duas curvas planares de Bezier se cruzam? Por "confiável", quero dizer que o teste responderá "sim" somente quando as curvas se cruzam e "não" somente quando elas não se cruzam. Não preciso saber em quais parâmetros o cruzamento foi encontrado. Eu também gostaria de usar números de ponto flutuante na implementação.

Encontrei várias respostas no StackOverflow que usam as caixas delimitadoras das curvas para o teste: não é isso que eu procuro, pois esse teste pode relatar interseção, mesmo que as curvas não se cruzem.

A coisa mais próxima que encontrei até agora é a " cunha delimitadora " de Sederberg e Meyers, mas "apenas" distingue entre no máximo uma e duas ou mais interseções, enquanto eu quero saber se existe no máximo zero e uma ou mais interseções.

Ecir Hana
fonte
Não tenho certeza de que exista como tal, determinar se existe ou não uma possibilidade de 0-1 ou 2 ou mais é bastante trivial, mas a formulação não torna realmente fácil garantir seu 0 ou 1 sem realmente verificar.
joojaa
Quais são os requisitos de tempo de execução? Uma solução que deveria ser capaz de produzir resultados bastante precisos seria aproximar as duas curvas por um grande número de segmentos retos curtos e, em seguida, cruzá-los de maneira pareada. Mas isso custa muito tempo e memória.
Dragonseel
@Dragonseel Bem, eu ficaria feliz em qualquer solução, realmente, mas desde que você perguntou O (1) seria bom. Mas aproximar as curvas com segmentos de linha leva aos mesmos problemas que o teste para delimitadora sobreposição caixa ...
Ecir Hana
Problema interessante. Acho que não há uma resposta fácil, mas gostaria de estar errado. Você tem um link para o artigo de Sederberg e Meyers?
precisa saber é o seguinte
@DanielMGessel Sim, veja a edição acima.
precisa saber é o seguinte

Respostas:

6

Uma maneira alternativa de formular o problema é definir uma função que dê a distância entre os pontos nas duas curvas, em função dos parâmetros das curvas. Em seguida, tente encontrar o mínimo global dessa função. Se as curvas se cruzarem, o mínimo será zero; caso contrário, o mínimo será uma distância positiva.

Para ser expressa, dado um par de curvas 2D definidos por , definir a distância ao quadrado como-c1,c2:[0,1]R2

f(u,v):[0,1]2R0|c2(v)c1(u)|2

f

Nathan Reed
fonte
[0,1]2R2
11
[0,1]R2
11
xyxciy
@ Nathan: Eu tinha considerado isso, mas, tendo passado muito tempo escrevendo código para encontrar mínimos em formatos de compressão de textura, tudo parecia um pouco hediondo.
Simon F
5

[Aviso: acho que o seguinte deve funcionar, mas não o codifiquei de fato]

Eu não conseguia pensar em um método "trivial" de produzir uma resposta sim / não, mas o seguinte seria uma abordagem razoável para uma solução prática para a pergunta.

Vamos assumir que nossas curvas são A (s) e B (t) com pontos de controle { A0, A1..An } e { B0, .. Bm }, respectivamente.

Parece-me que, dado um par de Beziers 2D para os quais desejamos determinar a interferência ou não, existem seis casos a serem considerados:

  1. Caso em que podemos "trivialmente" determinar que eles não se cruzam.

  2. Caso em que eles cruzam um número finito de vezes e podemos "facilmente" determinar se eles definitivamente cruzam pelo menos uma vez (mas na verdade não nos importamos onde essas interseções ocorrem)

  3. Um dos Beziers é degenerado, ou seja, um ponto (que ocorrerá se todos os pontos de controle forem idênticos). Podemos assumir que já lidamos com o caso em que ambos são pontos.

  4. Uma ou mais das curvas estão fechadas, por exemplo. A0 == An. Para simplificar a vida, subdividiremos essas curvas e começaremos novamente.

  5. Há um número infinito de pontos de interseção porque cada um é um subconjunto de um Bezier "pai" e eles se sobrepõem.

  6. Não temos certeza dos casos acima e precisamos de mais investigações

Por enquanto, ignoraremos 3 e 4, mas voltaremos a eles mais tarde.

Caso 1

Como você sugere na sua pergunta, se as respectivas caixas delimitadoras dos pontos de controle de A e B ) não se cruzam, as curvas não podem se cruzar. Obviamente, este é um teste rápido de rejeição, mas é excessivamente conservador. Como você provavelmente sabe, com uma curva de Bezier, o casco convexo de seus pontos de controle forma um limite (mais apertado) na curva. Assim, podemos usar a técnica do eixo de separação para decidir se os cascos de A e B não se cruzam. (por exemplo, como mostrado na Wikipedia :)

insira a descrição da imagem aqui

Caso 2

Se o teste do caso 1 falhar, você poderá verificar a existência "trivial" de uma interseção. Agora, provavelmente existem maneiras melhores de fazer isso, mas me ocorreu a seguinte abordagem, relativamente barata:

Considere apenas a curva A:

Limites de "linha gorda" de um Bezier

A0AnA0An¯A0An¯

Se fizermos o mesmo com a curva B, obtemos o seguinte caso (possível): insira a descrição da imagem aqui

A0AnB0Bm

Caso 6

A1,A2,B1,B2

(A1,B1),(A2,B1)...(A2,B2)

Caso 3 e 5

É aqui que se torna um pouco mais tedioso.

Se o "caso 3" passar no teste "caso 1", parece-me que você precisa resolver uma interseção real. Dado que existe um processo simples para mapear os N pontos de controle de um Bezier, A (s), para os pontos N-1 do Bezier, A '(s), representando sua primeira derivada então (desde que seja tomado cuidado Em situações relativamente raras, chamadas "degeneradas", onde a 1ª derivada chega a zero), a iteração de Newton (em uma dimensão) pode ser usada para encontrar possíveis soluções.
Observe também que, como os pontos de controle de A '(s) são limitados aos valores derivativos, existe o potencial de eliminar antecipadamente alguns casos.

O caso 5 parece relativamente improvável; talvez apenas após algumas recursões não exista uma prova conclusiva, alguém poderia tentar cada ponto final de A na curva B e vice-versa. Isso daria apenas uma prova de interseção - não uma prova de não interseção.

Simon F
fonte
Sim, mas estou pessoalmente mais interessado no caso em que Bm e / ou B0 estão dentro do volume de limite máximo e mínimo de A, mas não o perfuram, é necessário subdividir e, na pior das hipóteses, calcular a interseção ponto. Maneiras melhores seriam usar a caixa delimitadora mínima, também conhecida como aproximação de linha grossa.
Joojaa
Dado que, em todas as subdivisões binárias, a diferença entre a curva e o segmento que liga os pontos finais diminui por um fator razoável (e, no topo da minha cabeça, acho que pode ter sido 4x para quadráticos) certamente os limites estão indo convergir para uma fita "fina" rapidamente.
Simon F
Sim, mas o pior cenário é que o outro bezier começa no outro.
Joojaa
Você quer dizer, por exemplo, An == B0 . Você define isso como um cruzamento ou não?
Simon F
Não mais como B0 está Em algum lugar na curva. Ou até mesmo uma apenas minimamente cruzando
joojaa