Como posso saber se um círculo e um retângulo se cruzam no espaço euclidiano 2D? (isto é, geometria 2D clássica)
192
Como posso saber se um círculo e um retângulo se cruzam no espaço euclidiano 2D? (isto é, geometria 2D clássica)
Respostas:
Existem apenas dois casos em que o círculo cruza com o retângulo:
Observe que isso não requer que o retângulo seja paralelo ao eixo.
(Uma maneira de ver isso: se nenhuma das arestas tem um ponto no círculo (se todas as arestas estiverem completamente "fora" do círculo)), a única maneira pela qual o círculo ainda pode cruzar o polígono é se ele estiver completamente dentro do círculo. polígono.)
Com essa visão, algo como o seguinte irá funcionar, onde o círculo tem centro
P
e raioR
, e o retângulo tem vérticesA
,B
,C
,D
nessa ordem (código não completa):Se você estiver escrevendo alguma geometria, provavelmente já possui as funções acima em sua biblioteca. Caso contrário,
pointInRectangle()
pode ser implementado de várias maneiras; qualquer ponto geral nos métodos de polígono funcionará, mas para um retângulo, você pode apenas verificar se isso funciona:E
intersectCircle()
é fácil de implementar também: uma maneira seria verificar se o pé da perpendicular deP
à linha está próximo o suficiente e entre os pontos de extremidade e, caso contrário, verifique os pontos de extremidade.O legal é que a mesma idéia funciona não apenas para retângulos, mas para a interseção de um círculo com qualquer polígono simples - nem precisa ser convexa!
fonte
Aqui está como eu faria isso:
Veja como funciona:
O primeiro par de linhas calcula os valores absolutos da diferença xey entre o centro do círculo e o centro do retângulo. Isso reduz os quatro quadrantes em um, para que os cálculos não precisem ser feitos quatro vezes. A imagem mostra a área em que o centro do círculo deve estar agora. Observe que apenas o quadrante único é mostrado. O retângulo é a área cinza e a borda vermelha descreve a área crítica, a exatamente um raio de distância das bordas do retângulo. O centro do círculo deve estar dentro dessa borda vermelha para que a interseção ocorra.
O segundo par de linhas elimina os casos fáceis em que o círculo está longe o suficiente do retângulo (em qualquer direção) para que nenhuma interseção seja possível. Isso corresponde à área verde na imagem.
O terceiro par de linhas lida com os casos fáceis em que o círculo está próximo o suficiente do retângulo (em qualquer direção) para garantir uma interseção. Isso corresponde às seções laranja e cinza da imagem. Observe que esta etapa deve ser executada após a etapa 2 para que a lógica faça sentido.
As linhas restantes calculam o caso difícil em que o círculo pode cruzar o canto do retângulo. Para resolver, calcule a distância do centro do círculo e do canto e verifique se a distância não é maior que o raio do círculo. Esse cálculo retorna falso para todos os círculos cujo centro está dentro da área sombreada em vermelho e retorna verdadeiro para todos os círculos cujo centro está dentro da área sombreada em branco.
fonte
;)
circleDistance_x = abs(circle.x - (rect.x-rect.w/2)); circleDistance_y = abs(circle.y - (rect.y-rect.h/2));
Aqui está outra solução bastante simples de implementar (e muito rápida também). Ele captura todas as interseções, inclusive quando a esfera entrou totalmente no retângulo.
Com qualquer biblioteca matemática decente, isso pode ser reduzido para 3 ou 4 linhas.
fonte
sua esfera e seu retângulo cruzam IIF,
a distância entre o centro do círculo e um vértice do seu ret é menor que o raio da sua esfera
OU
a distância entre o centro do círculo e uma aresta do seu ret é menor que o raio da sua esfera ( [ distância da linha do ponto ])
OU
o centro do círculo está dentro do retângulo
distância do ponto:
distância da linha do ponto:
circunferência do centro dentro
do retângulo : faça uma aproximação do eixo separador: se houver uma projeção em uma linha que separa o retângulo do ponto, eles não se cruzam
você projeta o ponto em linhas paralelas aos lados do seu ret e pode facilmente determinar se elas se cruzam. se eles não se cruzam nas 4 projeções, eles (o ponto e o retângulo) não podem se cruzar.
você só precisa do produto interno (x = [x1, x2], y = [y1, y2], x * y = x1 * y1 + x2 * y2)
seu teste ficaria assim:
isso não assume um retângulo alinhado ao eixo e é facilmente extensível para testar interseções entre conjuntos convexos.
fonte
Esta é a solução mais rápida:
Observe a ordem de execução e metade da largura / altura é pré-calculada. A quadratura também é feita "manualmente" para salvar alguns ciclos de relógio.
fonte
A solução mais simples que encontrei é bem direta.
Ele funciona encontrando o ponto no retângulo mais próximo do círculo e comparando a distância.
Você pode fazer tudo isso com algumas operações e até evitar a função sqrt.
E é isso! A solução acima assume uma origem no canto superior esquerdo do mundo, com o eixo x apontando para baixo.
Se você deseja uma solução para lidar com colisões entre um círculo e um retângulo em movimento, é muito mais complicado e abordado em outra resposta minha.
fonte
Na verdade, isso é muito mais simples. Você precisa apenas de duas coisas.
Primeiro, você precisa encontrar quatro ortogonais distâncias do centro do círculo para cada linha do retângulo. Em seguida, seu círculo não cruzará o retângulo se três deles forem maiores que o raio do círculo.
Segundo, você precisa encontrar a distância entre o centro do círculo e o centro do retângulo, para não circular dentro do retângulo se a distância for maior que a metade do comprimento diagonal do retângulo.
Boa sorte!
fonte
Aqui está o meu código C para resolver uma colisão entre uma esfera e uma caixa alinhada sem eixo. Ele conta com algumas das minhas próprias rotinas de biblioteca, mas pode ser útil para alguns. Estou usando em um jogo e funciona perfeitamente.
fonte
Para visualizar, pegue o teclado numérico do seu teclado. Se a tecla '5' representa seu retângulo, todas as teclas de 1 a 9 representam os 9 quadrantes de espaço divididos pelas linhas que compõem seu retângulo (com 5 sendo o interior).
1) Se o centro do círculo estiver no quadrante 5 (ou seja, dentro do retângulo), as duas formas se cruzam.
Com isso fora do caminho, existem dois casos possíveis: a) O círculo cruza com duas ou mais arestas vizinhas do retângulo. b) O círculo cruza com uma aresta do retângulo.
O primeiro caso é simples. Se o círculo cruzar com duas arestas vizinhas do retângulo, ele deverá conter o canto que liga essas duas arestas. (Esse ou seu centro está no quadrante 5, que já abordamos. Observe também que o caso em que o círculo se cruza com apenas duas arestas opostas do retângulo também é coberto.)
2) Se algum dos cantos A, B, C, D do retângulo estiver dentro do círculo, as duas formas se cruzam.
O segundo caso é mais complicado. Devemos notar que isso só pode acontecer quando o centro do círculo estiver em um dos quadrantes 2, 4, 6 ou 8. (De fato, se o centro estiver em qualquer um dos quadrantes 1, 3, 7, 8, o o canto correspondente será o ponto mais próximo a ele.)
Agora temos o caso de que o centro do círculo está em um dos quadrantes da "aresta" e só cruza com a aresta correspondente. Então, o ponto na aresta mais próximo do centro do círculo deve estar dentro do círculo.
3) Para cada linha AB, BC, CD, DA, construa as linhas perpendiculares p (AB, P), p (BC, P), p (CD, P), p (DA, P) através do centro do círculo P. Para cada linha perpendicular, se a interseção com a aresta original estiver dentro do círculo, as duas formas se cruzam.
Há um atalho para esta última etapa. Se o centro do círculo estiver no quadrante 8 e a aresta AB for a aresta superior, o ponto de interseção terá as coordenadas y de A e B e as coordenadas x do centro P.
Você pode construir as quatro interseções de linha e verificar se elas estão nas arestas correspondentes, ou descobrir em que quadrante P está e verificar a interseção correspondente. Ambos devem simplificar para a mesma equação booleana. Desconfie de que o passo 2 acima não excluiu P estar em um dos quadrantes de 'canto'; apenas procurou um cruzamento.
Edit: Como se vê, eu negligenciei o simples fato de que # 2 é uma sub-caixa de # 3 acima. Afinal, os cantos também são pontos nas bordas. Veja a resposta de @ ShreevatsaR abaixo para uma ótima explicação. Enquanto isso, esqueça o item 2 acima, a menos que você queira uma verificação rápida, mas redundante.
fonte
Esta função detecta colisões (interseções) entre Círculo e Retângulo. Ele funciona como o método e.James em sua resposta, mas este detecta colisões para todos os ângulos de retângulo (não apenas no canto superior direito).
NOTA:
aRect.origin.x e aRect.origin.y são coordenadas do ângulo inferior esquerdo do retângulo!
aCircle.x e aCircle.y são coordenadas do Circle Center!
fonte
Eu tenho um método que evita as pitágoras caras, se não for necessário - ou seja. quando delimitar caixas do retângulo e do círculo não se cruzam.
E funcionará também para não-euclidianos:
dLat=(lat-circleY); dLon=(lon-circleX); normed=dLat*dLat+dLon*dLon
. Obviamente, se você usar esse método normDist, precisará criar umnormedDist = dist*dist;
para o círculoVeja o código completo BBox e Circle do meu projeto GraphHopper .
fonte
Criei turma para trabalhar com formas espero que gostem
fonte
Aqui está o código modificado 100% funcionando:
Bassam Alugili
fonte
Aqui está um teste rápido de uma linha para isso:
Este é o caso alinhado ao eixo, onde
rect_halves
é um vetor positivo apontando do meio do retângulo para um canto. A expressão dentrolength()
é um vetor delta decenter
um ponto mais próximo no retângulo. Isso funciona em qualquer dimensão.fonte
É eficiente, porque:
fonte
funcionou para mim (só funciona quando o ângulo do retângulo é 180)
fonte
Melhorando um pouco a resposta do e.James:
Isso subtrai
rect.w / 2
erect.h / 2
uma vez em vez de até três vezes.fonte
Para aqueles que precisam calcular a colisão de Círculo / Retângulo nas coordenadas geográficas com SQL,
esta é minha implementação no oracle 11 do algoritmo sugerido e.James .
Na entrada, são necessárias coordenadas circulares, raio do círculo em km e duas coordenadas de vértices do retângulo:
fonte
Funciona, descobri isso há uma semana atrás e agora comecei a testá-lo.
fonte
fonte
Supondo que você tenha as quatro arestas do retângulo, verifique a distância entre as arestas e o centro do círculo, se for menor que o raio, as formas estão se cruzando.
fonte
Se o retângulo se cruzar com o círculo, um ou mais pontos de canto do retângulo devem estar dentro do círculo. Suponha que os quatro pontos de um retângulo sejam A, B, C, D. pelo menos um deles deve cruzar o círculo. portanto, se a distância de um ponto ao centro do círculo for menor que o raio do círculo, ele deve cruzar o círculo. Para obter a distância, você pode usar o teorema de Pitágoras,
Essa técnica tem alguns limites. Mas funcionará melhor para os desenvolvedores de jogos. especialmente detecção de colisão
É uma boa atualização para o algoritmo do Arvo
fonte