Colisao de circulos

Pessoal, eu estou desenvolvendo um aplicativo aqui que preciso verificar se há colisão entre dois circulos.

Vamos aos detalhes:
Raio = 8
Diametro = 16
A verificação que estou fazendo é a seguinte:

[code] if (paths.euclideanDistance(pontoA, pontoB) <= diametro) {
//colidiu
}

public double euclideanDistance(Circle atual, Circle outra) {
	return Math.hypot(atual.getX() - outra.getX(), atual.getY() - outra.getY());
}

[/code]

Até ai tranquilo, mas quando eu dou o repaint ele mostra na tela os circulos um dentro do outro (encavalados), eu gostaria que mostrasse somente as bordas se encostando (mesmo o calculo afirmando que a distancia entre os centros é menor que o diametro, teria de mostrar as bolinhas somente encostando na borda um da outra).

Alguem tem uma ideia ?

Obrigadoo !

Você quer diminuir as bolinhas, é isso? Senão, se a distância entre os centros for menor que o diâmetro, elas fatalmente irão se encostar (você não pode ir contra as leis da geometria, que eu saiba, por melhor que seja seu advogado.

Podemos tentar assim:

public boolean collide(Circle atual, Circle outra){

    double distanciaX = outra.getX() - atual.getX(); // Calcula distancia entre o centro dos circulos
    double distanciaY = outra.getY() - atual.getY();
    double distancia = Math.sqrt( (distanciaX * distanciaX) - (distanciaY * distanciaY));
    double distanciaMinima = outra.getRaio() + atual.getRaio();

    return (distancia < distanciaMinima);

diego123321, isso que voce colocou é igual a hipotenusa (que eu ja coloquei ali).
entanglement, você sempre me ajuda aqui, vamos lá:
O que eu preciso é que quando a distancia de um centro da circunferencia até o outro centro seja < RAIO * 2 (as circunferencias tem o mesmo raio).
Melhor dizendo, como uma buferedImage comeca a rendenizar do canto superior esquerdo, fica assim:

O centro de cada circulo é (X + RAIO, Y + RAIO) para cada circunferencia.Os circuloes ficam andando pela tela em passos de 5 pixels mas se por acaso elas se chocarem a distancia entre os centros tem que ser <= diametro.

E quando ele faz o repaint pra mostrar as circunferencias, invez de aparecerem tipo, borda chocando com borda, aparece encavalada…

Eu sei que se a distancia for < diametro, elas se chocaram e na pratica vao ser pintadas uma encavalada na outra, o que eu queria é que não aparecessem encavaladas…

Será que fui claro ?! (espero que consigam entender)

Ah, entendi - se você tem dois círculos, e se a largura do “stroke” for não-nula, então fatalmente os círculos irão se interseccionar, é isso?

Na verdade, para desenhar um círculo do jeito que você quer, você provavelmente vai ter de levar em conta a largura do “stroke”, e reduzir o raio de sua circunferência de acordo, já que a circunferência ideal passa pelo meio do “stroke”.

Ahn, digamos que sim, da uma olhada no programa pra vc ver o que esta acontecendo.
(Ai vc entende o que eu digo que esta encavalando, quase não da pra perceber mas eu quero que não encavale).

https://docs.google.com/open?id=0B0tcetJ0NHPONF9WS3FDVlJJTEE

Ps: Use o Java mais atualizado possivel (Windows).

Pra usar vc precisa clicar em lugares diferentes da tela, ainda tem alguns bugs.

Então, entanglement, será que vc tem alguma idéia ai ?! rsrs

O proxy está bloqueando essa URL: https://docs.google.com/open?id=0B0tcetJ0NHPONF9WS3FDVlJJTEE

Tem como anexar a figura como “attachment” no seu post?

Opa,
Então, faz um tempo que num ‘brinco’ com geometria. Pensando nos pontos (X,Y) centrais de cada cículo. Assumindo que eles possuem o mesmo raio R.
Circulo1 possui centro no ponto (a,b)
Circulo2 possui centro no ponto (c,d)
Distancia entre os dois pontos centrais = RAIZQUADRADA[(a-c)²+(b-d)²]. (WIKIPEDIA)
SE DISTANCIA <= R*2 ENTÃO ‘estão em choque’.

Espero que ajude.

gmoenik, como eu ja expliquei isso, eu ja sei achar a distancia entre os pontos. Não é bem isso que eu preciso.

Vamos explicar melhor.

Um círculo, quando desenhado pelo Java2D, usa um “stroke” que é o traço deixado pelo pincel quando se desenha alguma coisa.
Ele pode ter uma largura de 1 pixel, ou pode ter uma largura maior que 1 pixel. (Ou seja, é uma circunferência com uma borda mais grosssa).
Se você estiver usando uma largura muito grande, pode ter o problema de quando dois círculos se tocam, seus “strokes” acabam se misturando.
Uma forma de você contornar esse problema é levar em conta a largura do “stroke”.

É esse seu problema? Como eu disse, eu não consigo ver sua figura no google.com.

entanglement , na vdd esse eh o programa rodando pra vc ter ideia do que eu to fazendo.

Cada bolinha é uma bufferedImage de 16x16 e tem um circulo desenhado de 16x16.

Obs: este programa é um simulador, estou fazendo pra depois implementar esta logica em outro software.

Você só quer reposicionar as bolinhas para que elas simplesmente se encostem?
E qual é o problema que você tem? Calcular nova posição da bolinha?

Por acaso as bolinhas se movem, ou você pode reposiciona-las para qualquer lado?
E se se movem, é uma só que se move, ou as duas?

Abaixo um procedimento relativamente genérico, considerando que as bolas se movem:
a) Calcule a distância entre os dois centros (isso você provavelmente já tem);
b) Subtraia a soma dos raios dessa distância. Essa é a distância que uma bolinha “penetrou” na outra;
c) Divida a distância pela soma das velocidades das bolinhas.
d) Inverta o vetor de direção da bolinha A, normalize-o e multiplique-o pela velocidade de A vezes o valor obtido no passo c)
e) Faça o mesmo para a bolinha B;
f) Some os vetores resultantes nas bolinhas.

Com esses procedimentos, elas irão somente se encostar. Cada bolinha vai voltar proporcionalmente a velocidade que se deslocou.

Se seu simulador precisa tratar as colisões, e talvez refletir o vetor de direção da bola, então, é melhor você estudar mais a fundo vetores e matemática.
Recomendo fortemente a leitura dos seguintes artigos:
http://www.pontov.com.br/site/arquitetura/54-matematica-e-fisica/132-o-uso-de-vetores-nos-jogos
http://www.pontov.com.br/site/arquitetura/54-matematica-e-fisica/332-vetores-guia-de-referencia

Veja um "pseudo-código" do algoritmo descrito acima (estou levando em consideração que você usa a biblioteca de vetores disponível no final do artigo):

[code]float distance = ballA.getPosition().subtract(ballB.getPosition()).size();
float penetration = (ballA.getRadius() + ballB.getRadius()) - distance;
if (penetration <= 0)
return; //Se < 0, não colidiu. Se = 0, está no local certo.

//A penetração média percorrida pelas duas bolas por unidade de tempo
//O resultado é invertido pois queremos que as bolas “voltem”
float distPerUnity = -penetration / (ballA.getSpeed() + ballB.getSpeed());

//Calcula a distância que cada bola percorreu, de acordo com sua velocidade
float offendingDistanceA = ballA.getSpeed() * distPerUnity;
float offendingDistanceB = ballB.getSpeed() * distPerUnity;

//Cria o vetor representando a direção inversa do deslocamento que estavam realizando.
Vector2D backVectorA = ballA.getDirection().normalize().multiplyMe(offendingDistanceA);
Vector2D backVectorB = ballB.getDirection().normalize().multiplyMe(offendingDistanceB);

//Soma esse vetor a posição atual da bola, fazendo com que ela volte e não esteja mais colidindo.
ballA.getPosition().addMe(backVectorA);
ballB.getPosition().addMe(backVectorB);
[/code]

Detalhe: Essa função faz a simplificação considerando que as bolas estão colidindo frontalmente. Para uma simulação simples, isso costuma a ser suficiente, até porque, estamos só resolvendo o encavalamento, e não calculando a força resultante em cada bolinha após a colisão. Se precisar de mais detalhes, recomendo que use uma engine de física. Ou então, prepare-se para sentar na cadeira e se aprofundar bem mais na teoria (você vai ter que saber sobre atrito, fricção, elasticidade e vai precisar saber decompor esses vetores adequadamente).

Coloquei uns comentários e corrigi uns detalhes no pseudo-código.
Não tive tempo de colocar o código no eclipse, simular as bolas e testar… então, talvez tenha algum errinho ali.

eu já fiz algo assim, e foi em uma applet, agora para achar onde é que guardei isto, fica dificil, pois salvei em algum dvd.

recomendo a leitura do livro
programação de games com java, de jonathan s. harbour.

ele trata de sprites e coisa e tal, e mostra um jogo asteroids.

me lembro que fiz a bolinha se mexer bem, com as setas do teclado, já na colisão tive alguns problemas, que acredito tenha resolvido.

em uma breve olhada no livro ele fala
em Rectangle.contains()
com java 2d.

enfim… são várias soluções, decerto.

ViniGodoy, obrigado pelas dicas, vou tentar implementar isto que você falou.

Você entendeu perfeitamente o que eu estava tentando explciar.

[quote=Vinicius Zibetti Resko]ViniGodoy, obrigado pelas dicas, vou tentar implementar isto que você falou.

Você entendeu perfeitamente o que eu estava tentando explciar.[/quote]

PS: Para evitar problemas como o que o entanglement teve (de não poder ver as imagens), use a opção de attachments, do próprio GUJ.
O botão está logo abaixo da área onde você escreve a mensagem, e ali você pode adicionar imagens e arquivos eu seu post mesmo.