Calcular angulo entre dois pnotos

39 respostas
J
Pessoal, tenho um código que ao clicar na tela desenha um ponto e ao clicar pela segunda vez desenha outro ponto, ligando um ponto ao outro com uma linha, dizendo a distancia entre eles, o código está funcionando normal, só que eu gostaria de calcular o angulo entre os dois pontos e mostrar isso escrito na tela como é feita com a distancia, alguem poderia me ajudar com isso? O código é o seguinte:
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
#include <sstream>

using namespace std;

class Circulo {//classe circulo
public:
    int x;
    int y;
    int r;
};

float dist_eucl(int x1, int y1, int x2, int y2){//função para calculo de distancia euclidiana
    return sqrt((((x2 - x1)*(x2 - x1)) + ((y2 - y1)*(y2 - y1))));
}

int main()//inicio da mais
{
    sf::RenderWindow* app = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "Exercicio 2");
    int id_ponto = 0;
    Circulo* c1 = new Circulo;
    Circulo* c2 = new Circulo;
    sf::Shape p1;
    sf::Shape p2;
    int mouseX, mouseY;//posição do mouse na tela
    float raio = 1;

    //texto fixo
    sf::String* txttitulo;
    sf::String* txtpos1;
    sf::String* txtpos2;
    sf::String* txtdistancia;
    int xtxttitulo;
    int ytxttitulo;
    int xtxtpos1;
    int ytxtpos1;
    int xtxtpos2;
    int ytxtpos2;
    int xtxtdistancia;
    int ytxtdistancia;

    // texto variavel
    sf::String* txtpos11;
    sf::String* txtpos22;
    sf::String* txtdistancia1;
    int xtxtpos11;
    int ytxtpos11;
    int xtxtpos22;
    int ytxtpos22;
    int xtxtdistancia1;
    int ytxtdistancia1;
    string str1;
    string str2;
    string str3;

    bool abertura = true;

    while (app->IsOpened()) {

        xtxttitulo = 10;
        ytxttitulo = 10;
        xtxtpos1 = 10;
        ytxtpos1 = 40;
        xtxtpos2 = 10;
        ytxtpos2 = 60;
        xtxtdistancia = 10;
        ytxtdistancia = 80;
        xtxtpos11 = 120;
        ytxtpos11 = 40;
        xtxtpos22 = 120;
        ytxtpos22 = 60;
        xtxtdistancia1 = 120;
        ytxtdistancia1 = 80;


        sf::Font* fontTimes = new sf::Font();
        if (!fontTimes->LoadFromFile("times.ttf")) {
            std::cout << "ERRO FONTE" << std::endl;
        }
        txttitulo = new sf::String("Exercicio 2", *fontTimes, 20);
        txttitulo->SetColor(sf::Color(0, 0, 0));
        txttitulo->SetPosition(xtxttitulo, ytxttitulo);

        txtpos1 = new sf::String("Coordenadas P1:", *fontTimes, 15);
        txtpos1->SetColor(sf::Color(0, 0, 0));
        txtpos1->SetPosition(xtxtpos1, ytxtpos1);

        txtpos2 = new sf::String("Coordenadas P2:", *fontTimes, 15);
        txtpos2->SetColor(sf::Color(0, 0, 0));
        txtpos2->SetPosition(xtxtpos2, ytxtpos2);

        txtdistancia = new sf::String("Distância pontos:", *fontTimes, 15);
        txtdistancia->SetColor(sf::Color(0, 0, 0));
        txtdistancia->SetPosition(xtxtdistancia, ytxtdistancia);




        sf::Event* event = new sf::Event();
        while (app->GetEvent(*event)) {
            if (event->Type == sf::Event::Closed) {
                app->Close();
            }
        }
        if (app->GetInput().IsKeyDown(sf::Key::Escape)) {
            return EXIT_SUCCESS;
        }




        if (app->GetInput().IsMouseButtonDown(sf::Mouse::Left)) {

         mouseX = app->GetInput().GetMouseX();
         mouseY = app->GetInput().GetMouseY();


            if (id_ponto == 0) {
                id_ponto = 1;

                c1 -> x = mouseX;
                c1 -> y = mouseY;
                c1 -> r = raio;

                 p1  =  sf::Shape::Circle(c1->x, c1->y, c1->r, sf::Color(0, 0, 0), 1, sf::Color(0, 0, 0));
            }else if(id_ponto == 1){
                id_ponto = 2;
                c2 -> x = mouseX;
                c2 -> y = mouseY;
                c2 -> r = raio;

                p2  =  sf::Shape::Circle(c2->x, c2->y, c2->r, sf::Color(0, 0, 0), 1, sf::Color(0, 0, 0));

            }else if(id_ponto == 2){

                c1 -> x = c2->x;
                c1 -> y = c2->y;
                c1 -> r = c2->r;

                c2 -> x = mouseX;
                c2 -> y = mouseY;
                c2 -> r = raio;

                p1  =  sf::Shape::Circle(c1->x, c1->y, c1->r, sf::Color(0, 0, 0), 1, sf::Color(0, 0, 0));
                p2  =  sf::Shape::Circle(c2->x, c2->y, c2->r, sf::Color(0, 0, 0), 1, sf::Color(0, 0, 0));

            }

        }

        //Posição dos pontos
        stringstream x1;
        stringstream y1;
        stringstream x2;
        stringstream y2;

        if (id_ponto == 0){
            x1 << 0;
            y1 << 0;
            x2 << 0;
            y2 << 0;
        }else if (id_ponto == 1){
            x1 << c1->x;
            y1 << c1->y;
            x2 << 0;
            y2 << 0;
        }else{
            x1 << c1->x;
            y1 << c1->y;

            x2 << c2->x;
            y2 << c2->y;

        }
        str1 = "x: " + x1.str() + " - y: " + y1.str();
        txtpos11 = new sf::String(str1, *fontTimes, 15);
        txtpos11->SetColor(sf::Color(0, 0, 0));
        txtpos11->SetPosition(xtxtpos11, ytxtpos11);


        str2 = "x: " + x2.str() + " - y: " + y2.str();
        txtpos22 = new sf::String(str2, *fontTimes, 15);
        txtpos22->SetColor(sf::Color(0, 0, 0));
        txtpos22->SetPosition(xtxtpos22, ytxtpos22);

        stringstream distanciaFinal;

        app->Clear(sf::Color(255, 255, 255));
        app->Draw(*txttitulo);
        app->Draw(*txtpos1);
        app->Draw(*txtpos2);
        app->Draw(*txtdistancia);
        app->Draw(*txtpos11);
        app->Draw(*txtpos22);


        app->Draw(p1);
        app->Draw(p2);
        if (id_ponto > 1){
            sf::Shape reta = sf::Shape::Line(c1->x, c1->y, c2->x, c2->y, 1, sf::Color(0,0,0), 1, sf::Color(0, 0, 0));
            app->Draw(reta);
        distanciaFinal << dist_eucl(c1->x, c1->y, c2->x, c2->y);
        }else{
            distanciaFinal << 0;
        }


        str3 = distanciaFinal.str();
        txtdistancia1 = new sf::String(str3, *fontTimes, 15);
        txtdistancia1->SetColor(sf::Color(0, 0, 0));
        txtdistancia1->SetPosition(xtxtdistancia1, ytxtdistancia1);

        app->Draw(*txtdistancia1);

        sf::Sleep(0.1);

        app->Display();
    }
    return EXIT_SUCCESS;
}

39 Respostas

E

Ângulo entre dois pontos? Você não precisa de 3 pontos pelo menos (nem que o terceiro ponto seja 0,0 ? )

J

Não sei, precisa de 3 pontos mesmo?

E

Você quer fazer um desenho dos pontos e do ângulo que você quer mostrar? Um desenho ajuda bastante a visualizar o que você quer. Pode pegar um pedaço de papel, fazer o desenho a lápis mesmo, e postar uma foto com seu celular, e deixar como um attachment na mensagem (infelizmente um monte de sites estão bloqueados aqui onde eu trabalho).

E

É que é o seguinte. Um ângulo é algo que existe entre dois segmentos de reta. Para determinar 2 segmentos de reta, é necessário ter 3 pontos pelo menos (sendo que um deles é o ponto onde esses segmentos se cruzam). E é por isso que você precisa de 3 pontos.

T

Sim angulos sao formados por triangulos, e ele possuem tres lados

J

Verdade, me equivoquei na pergunta, desculpem.

T

Até me expressei mal angulos sao formados por objetos de 3 ou mais lados

E

Estou imaginando que você queira, na verdade, determinar este ângulo aqui:


J

Isso, exatamente, o angulo com o solo.

E

Esse ângulo é trivial - você se lembra das aulas de trigonometria?

double x = x2 - x1;
double y = y2 - y1;
// Veja a documentação de Math.atan2: http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#atan2%28double,%20double%29
double theta = Math.atan2 (y, x); // em radianos - para o ângulo em graus, converta usando http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#toDegrees%28double%29
E

Ah, esqueci que não é Java. De qualquer forma, existe um método em <math.h> chamado atan2, ele tem os mesmos parâmetros e é usado da mesma forma.

E

http://www.cplusplus.com/reference/clibrary/cmath/atan2/

E

Não recomendo usar aquele jeito “ingênuo” que se aprende em trigonometria (calcular atan (y / x) ) porque você precisa nesse caso levar em conta uma série de casos especiais (ficar somando ou subtraindo pi radianos, etc.). Acho mais fácil usar atan2, que já leva em conta esses casos especiais.

J

Obrigado, vou dar uma olhada nessa documentação da atan2
qualquer duvida eu posto aqui de novo.

J

Eu olhei a função atan2, mas não entendi direito, o que eu queria fazer era só mostrar o angulo em relação ao eixo x e o eixo y, se alguem puder me mostrar o do eixo x o do y eu faço de boa.

D

Uma dica, precisa refatorar seu código, tem muita repetição e sua função main está muito extensa, crie novas classes e funções menores, vai diminuir a repetição de código, facilitando modificações e leitura, mesmo que seja apenas para testes manuais, vale a pena.

E

Tio, nem precisa entender muito para que serve o atan2. Basta saber que a conta que mostrei em Java é, em C:

double x = x2 - x1;  
double y = y2 - y1;  
double theta = atan2 (y, x);

Não vi seu programa para saber como é que você pega os valores de x1, x2, y1 e y2 para passar para este trecho de código. Para passar o ângulo de radianos para graus, acho que você precisa só pegar aquele livro de matemática que está mofando na sua prateleira e ver como é que se faz a conta.

E

Além disso, você está com sérios problemas de matemática mesmo. Digamos que o ângulo theta que lhe passei seja 20 graus. O ângulo em relação ao eixo x é 20 graus e em relação ao eixo y - fala sério … -

D

P1(Ox, Oy) : primeiro ponto
P2(Ax, Ay) : segundo ponto

onde, explicitamente:
Ox : cordenada x do primeiro ponto
Oy : cordenada y do primeiro ponto
e
Ax : cordenada x do segundo ponto
Ay : cordenada y do segundo ponto

arco-tangente( (Ay-Oy) / (Ax- Ox) ) : angulo do eixo x ate a reta formada por P1 e P2.

arco-tangente( (Ax-Ox) / (Ay-Oy) ) : angulo do eixo y ate a reta formada por P1 e P2.

é a conta que o entanglement mostrou!

pra ajudar a entender os links



faça a conta primeiro e vai entender o porque.

E

De modo geral, duas ferramentas essenciais a qualquer pessoa que tente fazer algo que precise de um mínimo de geometria analítica (ou seja, gráficos e coordenadas):

a) Um livro de matemática que ensine um pouquinho de trigonometria

b) Lápis, papel e uma régua.

Pode também arranjar papel milimetrado e um transferidor, mas isso já é opcional. Agora, fazer tudo no teclado (e perguntar tudo aqui no Orkut, aham, no Facebook) já não funciona muito bem.

E

DavidUser:
P1(Ox, Oy) : primeiro ponto
P2(Ax, Ay) : segundo ponto

onde, explicitamente:
Ox : cordenada x do primeiro ponto
Oy : cordenada y do primeiro ponto
e
Ax : cordenada x do segundo ponto
Ay : cordenada y do segundo ponto

arco-tangente( Ay-Oy / Ax- Ox ) : angulo do eixo x ate a reta formada por P1 e P2.

arco-tangente( Ax-Ox / Ay-Oy ) : angulo do eixo y ate a reta formada por P1 e P2.

Eu disse que é o método “ingênuo” que se ensina em livros de matemática.
Na prática, em vez de fazer a divisão diretamente (o que dá problemas quando você tem um ângulo de 90 ou 270 graus - isso porque o denominador se torna zero), e ter de ficar corrigindo os ângulos somando ou subtraindo 180 graus, você usa o atan2, que já leva esses casos em conta.

D

legal isso entanglement!

V

Eu já recomendei, e volto a recomendar novamente:
http://www.pontov.com.br/site/arquitetura/54-matematica-e-fisica/132-o-uso-de-vetores-nos-jogos

Se estivesse usando a biblioteca, só faria:

J

aproveitando o topico sobre angulos,
usando o Graphics2D e rotate() como faço para rodar a uma imagem sem tirar ela do seu eixo original?
quando uso:

if (circle.contains(new Point(x2, y2))) {
  
            double x3 = x1- x2;
            double y3 = y2 - y1;

            double theta = Math.atan2(y3, x3);
            g.rotate(theta, x1, x2);
            g.drawImage(tower, x1, x2, this);
}

a imagem sai do eixo dela, queria apenas mudar o angulo da imagem em relação ao um ponto.

Grato.

V

Use metade do tamanho da imagem no segundo e terceiros parâmetros do método rotate.
Esses parâmetros indicam em que ponto da imagem será o pivot de rotação, considerando o canto superior esquerdo como 0,0.

J

ViniGodoy:
Use metade do tamanho da imagem no segundo e terceiros parâmetros do método rotate.
Esses parâmetros indicam em que ponto da imagem será o pivot de rotação, considerando o canto superior esquerdo como 0,0.

A imagem tem 32x32 pixels, ainda esta saindo do centro…

if (circle.contains(new Point(x2, y2))) {  
        
                double x3 = x1- x2;  
                double y3 = y2 - y1;  
      
                double theta = Math.atan2(y3, x3);  
                g.rotate(theta, 16, 16);  
                g.drawImage(tower, x1, x2, this);  
    }
J
JJjava:
ViniGodoy:
Use metade do tamanho da imagem no segundo e terceiros parâmetros do método rotate. Esses parâmetros indicam em que ponto da imagem será o pivot de rotação, considerando o canto superior esquerdo como 0,0.

A imagem tem 32x32 pixels, ainda esta saindo do centro...

if (circle.contains(new Point(x2, y2))) {  
        
                double x3 = x1- x2;  
                double y3 = y2 - y1;  
      
                double theta = Math.atan2(y3, x3);  
                g.rotate(theta, 16, 16);  
                g.drawImage(tower, x1, x2, this);  
    }
tentei tb o codigo abaixo e ainda sai do eixo :-(
if (circle.contains(new Point(x2, y2))) {  
        
                double x3 = x1- x2;  
                double y3 = y2 - y1;  
      
                double theta = Math.atan2(y3, x3);  
                g.rotate(theta, x1+16,x2+ 16);  
                g.drawImage(tower, x1, x2, this);  
    }
V

A sua imagem está desenhada no centro?

Outra coisa, o centro do objeto desenhado dentro da imagem, é o mesmo centro da imagem? Caso contrário, você tem que ver qual é o pixel do centro e indicar esse valor.

J

ViniGodoy:
A sua imagem está desenhada no centro?

Outra coisa, o centro do objeto desenhado dentro da imagem, é o mesmo centro da imagem? Caso contrário, você tem que ver qual é o pixel do centro e indicar esse valor.

não está no centro tela esta na posição (400,300) por exemplo

V

Onde foi que falei em tela?

Perguntei se o centro do desenho e o centro do arquivo de imagem coincidem.

Você tem que saber qual é o pixel do pivo de rotação. Abra sua imagem no paint, veja em torno de que pixel a figura deveria girar e coloque o valor desse pixel nos dois últimos parâmetros do método rotate.

J

Onde foi que falei em tela?

Perguntei se o centro do desenho e o centro do arquivo de imagem coincidem.

Você tem que saber qual é o pixel do pivo de rotação. Abra sua imagem no paint, veja em torno de que pixel a figura deveria girar e coloque o valor desse pixel nos dois últimos parâmetros do método rotate.

eu quero rodar no meio da imagem a imagem tem 32x32 pixels, o pixel do centro nao seria (16,16) ?

V

Poste sua imagem.

J

[img]

http://img.ragnabr-files.net/storage/box121/x53176towerq.png
[/img]

J

JJjava:
[img]

http://img.ragnabr-files.net/storage/box121/x53176towerq.png
[/img]

upei en outro lugar

http://www.imagemhost.net/fd.png

V

O pivo não seria no centro do retângulo da parte de cima ( ponto 16,8 )?

J

a “face” da “torre” seria a ponta do triangulo.
o minha intenção aqui é q face da da torre acompanhe o inimigo comforme ele passe

V

Nesse caso, a ponta do triângulo é o pivo. Coloque as coordenadas dela.

Imagine o pixel do pivo como um “pino” em torno do qual a imagem gira.

J

ViniGodoy:
Nesse caso, a ponta do triângulo é o pivo. Coloque as coordenadas dela.

Imagine o pixel do pivo como um “pino” em torno do qual a imagem gira.


uhum, let’s try…

J

ta um pouco estranho mas esta melhor q estava…
acho q o maior problema é a volta da torre para a posição original quando o imimigo sai do raio ela volta direto…

Criado 22 de novembro de 2012
Ultima resposta 15 de jan. de 2013
Respostas 39
Participantes 6