• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Sign in to follow this  
Followers 0
Cybernavigator

[Resolvido] Ponto dentro de um circulo segmentado

8 posts in this topic

Boas, acho que aqui será o melhor sítio para colocar esta dúvida.

Eu tenho um circulo segmentado, e gostava de saber se um ponto está dentro ou fora desse circulo.

Para explicar melhor vou colocar imagens

capturadeecr20100616185.jpg

Isso é o que eu tenho, quando passo o rato na área do donut o que acontece é isto

capturadeecr20100616185.jpg

O segmento fica mais vermelho, mas a área de detecção é o que está a preto mais o que está a vermelho.

A forma como estou a detectar se o ponto está dentro dos limites é a seguinte:

SE ( (rato.x-centro-x)^2 + (rato.y-centro.y)^2 < raioMaior^2 ) ENTAO

                SE   ( (rato.x-centro-x)^2 + (rato.y-centro.y)^2 > raioMenor^2 )  ENTAO
                         APRESENTA("Dentro dos limites");
                FIM SE

FIM SE

Desta forma eu detecto se está entre o circulo de raio menor e o de raio maior.

Agora o problema está em detectar se está dentro do segmento vermelho. Alguém me sabe ajudar com isto?

Obrigado desde já.

0

Share this post


Link to post
Share on other sites

Se souberes a ordenada em que a área vermelha começa podes fazer mais uma verificação que vê se Y é maior que essa ordenada.

0

Share this post


Link to post
Share on other sites

Se souberes a ordenada em que a área vermelha começa podes fazer mais uma verificação que vê se Y é maior que essa ordenada.

Sim, eu sei onde ele começa, eu percebo o que queres dizer com detectar se está acima dos limites, mas eu queria generalizar a coisa.

Por exemplo, o segmento começa no angulo 0, mas pode começar a 45, acabar em 270, e por aí em diante. Essa solução não me dá grande resultado :S

THX.

0

Share this post


Link to post
Share on other sites

Se souberes a ordenada em que a área vermelha começa podes fazer mais uma verificação que vê se Y é maior que essa ordenada.

Não funciona para segmentos não horizontais.

Tudo depende de como conheces a área a vermelho, mas a forma mais fácil é guardando dois ângulos ao centro e calcular o ângulo ao centro do ponto que queres testar. Tem cuidado porque as contas são módulo 2 PI.

0

Share this post


Link to post
Share on other sites

A = vértice inferior esquerdo do lado esquerdo da parte vermelha

B = vértice inferior direito do lado direito da parte vermelha

Se o rato estiver à esquerda do centro, verificas se rato.y está por cima da recta definida pelo centro e pelo ponto A.

Se o rato estiver à direita do centro, verificas se rato.y está por cima da recta definida pelo centro e pelo ponto B.

As rectas podem ser escritas na forma y = mx + b, em que m é o declive e é a diferença em YY de dois pontos sobre a diferença em XX dos mesmos dois pontos.

m1 = (centro.y-A.y)/(centro.x-A.x)
b1 = centro.y - m1 * centro.x

m2 = (centro.y-B.y)/(centro.x-B.x)
b2 = centro.y - m2 * centro.x


SE ( (rato.x-centro-x)^2 + (rato.y-centro.y)^2 < raioMaior^2 ) ENTAO
                SE   ( (rato.x-centro-x)^2 + (rato.y-centro.y)^2 > raioMenor^2 )  ENTAO
                                SE ( rato.x < centro.x AND rato.y > m1 * rato.x + b1) ENTAO
                                                APRESENTA("Dentro dos limites");
                                FIM SE
                                SE ( rato.x > centro.x AND rato.y > m2 * rato.x + b2) ENTAO
                                                APRESENTA("Dentro dos limites");
                                FIM SE
                FIM SE
FIM SE

0

Share this post


Link to post
Share on other sites

A = vértice inferior esquerdo do lado esquerdo da parte vermelha

B = vértice inferior direito do lado direito da parte vermelha

Se o rato estiver à esquerda do centro, verificas se rato.y está por cima da recta definida pelo centro e pelo ponto A.

Se o rato estiver à direita do centro, verificas se rato.y está por cima da recta definida pelo centro e pelo ponto B.

As rectas podem ser escritas na forma y = mx + b, em que m é o declive e é a diferença em YY de dois pontos sobre a diferença em XX dos mesmos dois pontos.

m1 = (centro.y-A.y)/(centro.x-A.x)
b1 = centro.y - m1 * centro.x

m2 = (centro.y-B.y)/(centro.x-B.x)
b2 = centro.y - m2 * centro.x


SE ( (rato.x-centro-x)^2 + (rato.y-centro.y)^2 < raioMaior^2 ) ENTAO
                SE   ( (rato.x-centro-x)^2 + (rato.y-centro.y)^2 > raioMenor^2 )  ENTAO
                                SE ( rato.x < centro.x AND rato.y > m1 * rato.x + b1) ENTAO
                                                APRESENTA("Dentro dos limites");
                                FIM SE
                                SE ( rato.x > centro.x AND rato.y > m2 * rato.x + b2) ENTAO
                                                APRESENTA("Dentro dos limites");
                                FIM SE
                FIM SE
FIM SE

Awesome, agora vem outro problema que é detectar os Vértices mais acima ou mais em baixo.

Mas resolveu muito o problema, obrigadissimo.

0

Share this post


Link to post
Share on other sites

Bem, agora que vejo bem, não, não funciona lá muito bem, para o exemplo que eu dei funciona minimamente, para o caso de começar em 45º e acabar em 120º já não tem nada a ver.

apliquei da seguinte forma

NSRect rrect = [self bounds];
NSPoint center = {rrect.size.width/2, rrect.size.height/2};
int greaterRadius = (innerRadius > outerRadius) ? innerRadius : outerRadius;
int lesserRadius = (innerRadius < outerRadius) ? innerRadius : outerRadius;

NSPoint A = {center.x+cos(RADIANS_TO_DEGREES(startingAngle))*lesserRadius , 
	center.y+sin(RADIANS_TO_DEGREES(startingAngle))*lesserRadius};
NSPoint B = {center.x+cos(RADIANS_TO_DEGREES(endingAngle))*lesserRadius , 
	center.y+sin(RADIANS_TO_DEGREES(endingAngle))*lesserRadius};

int m1 = (center.y-A.y)/(center.x-A.x);
int b1 = center.y - m1 * center.x;

int m2 = (center.y-B.y)/(center.x-B.x);
int b2 = center.y - m2 * center.x;



if ((pow((mouse.x-center.x),2) + pow((mouse.y - center.y),2) < pow(greaterRadius,2)) && (pow((mouse.x-center.x),2) + pow((mouse.y - center.y),2) > pow(lesserRadius,2))){
	if (mouse.x < center.x && mouse.y > m1 * mouse.x + b1) {
		return 1;
	}
	if (mouse.x > center.x && mouse.y > m2 * mouse.y + b2) {
		return 1;
	}
}

return 0;

É a forma correcta para obter o A ou o B? A função RADIAN_TO_DEGREES faz exactamente o contrário :)

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0