Ir ao conteúdo
  • Cadastre-se

C++ como desenhar 1 linha usando o comprimento e angulo\radianos?


Cambalinho

Posts recomendados

eis a minha função atual para desenhar 1 linha com 1 comprimento e Radianos:

void DrawLineAngle(int X0, int Y0, float Radians, int Width)//Width é 100
{
    int X1 = X0 + cos(Radians)*Width;//200
    int Y1 = Y0 + sin(Radians)*Width;
    cout << "X1: " << X1<< "\n";
    int dx = abs(X1-X0);
    int dy = abs(Y1-Y0);
    double Steps;
    double x=X0;
    double y=Y0;
    HDC HDCConsole = GetWindowDC(GetConsoleWindow());
    HPEN LineColor = CreatePen(0,1,RGB(255,0,0));
    HPEN OldPen =(HPEN)SelectObject(HDCConsole,LineColor);

    const double INCREMENTO = 32.0;
    if (dx >dy)
        Steps = dx;
    else
        Steps = dy;
    double Xincrement = (dx / Steps) * INCREMENTO;
    double Yincrement = (dy / Steps) * INCREMENTO;
    cout << "Xincrement: " << Xincrement<< "\n";
    int v=0;
    for(v=0; v < Steps; v++)
    {
        x = x + Xincrement;
        y = y + Yincrement;
        cout << "X: " << x  << "  Y: " << y << "\n";
        if(x>=X1 or y>=Y1) break;//porque tenho de usar esse 'if', senão dá-me mais comprimento
    }

    cout << v<< "\n";
    MoveToEx(HDCConsole,X0,Y0,nullptr);
    LineTo(HDCConsole,X0+100,y);
    SelectObject(HDCConsole,OldPen);
    DeleteObject(LineColor);
}

e como a uso:

DrawLineAngle(100,100,0,100);

porque o ciclo 'for' é executado 1 única vez e o 'v' é zero?
deveria somar '32' no 'x' e 1 vez seria '132', ou seja inferior ao comprimento.... o que estou a fazer errado no código?

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Em 17/11/2023 às 14:54, Cambalinho disse:

porque o ciclo 'for' é executado 1 única vez e o 'v' é zero?

 

Bom, por que foi exatamente isso que você pediu pro programa executar. Ou seja, se Y0 + 0 for maior ou igual a Y0, o que é verdade (y=Y0 e Y1=Y0 se Radians=0), então o loop deve ser terminado.

 

Em 17/11/2023 às 14:54, Cambalinho disse:

deveria somar '32' no 'x' e 1 vez seria '132', ou seja inferior ao comprimento....

 

32 + 100 parece-me suficientemente maior que 100, supondo que você se refere a width como um comprimento.

 

Em 17/11/2023 às 14:54, Cambalinho disse:

o que estou a fazer errado no código?

 

Off-topic: Aparentemente, muitas coisas, mas o mais importante seria ter um pouco mais de cuidado na hora das operações aritméticas misturando int, float e double. Sempre converta tudo pra float ou double, dependendo do nível de precisão que deseja, antes das operações. O compilador tá realizando várias conversões implícitas e o código executado não é exatamente o código escrito. Portanto, ele é péssimo pra ler, pra debugar e provavelmente vai ter erros durante o runtime também.

  • Curtir 1
  • Amei 1
Link para o comentário
Compartilhar em outros sites

tem razão amigo... por isso alterei o código:

void DrawLineAngle(int X0, int Y0, float Radians, int Width)
{
    int X1 = X0 + cos(Radians)*Width;
    int Y1 = Y0 + sin(Radians)*Width;
    int dx = abs(X1-X0);
    int dy = abs(Y1-Y0);
    double Steps;
    double x=X0;
    double y=Y0;
    HDC HDCConsole = GetWindowDC(GetConsoleWindow());
    HPEN LineColor = CreatePen(0,1,RGB(255,0,0));
    HPEN OldPen =(HPEN)SelectObject(HDCConsole,LineColor);

    const double INCREMENTO = 32.0;
    if (dx >dy)
        Steps = dx;
    else
        Steps = dy;
    double Xincrement = (dx / Steps) * INCREMENTO;
    double Yincrement = (dy / Steps) * INCREMENTO;
    int v=0;

    while(x<=X1 and y<=Y1)
    {
        x = x + Xincrement;
        y = y + Yincrement;
        v++;
    };
    if(x>X1) x=X1;
    if(y>Y1) y=Y1;
    cout << "Steps: " << v << "\n";
    MoveToEx(HDCConsole,X0,Y0,nullptr);
    LineTo(HDCConsole,x,y);
    SelectObject(HDCConsole,OldPen);
    DeleteObject(LineColor);
}

agora funciona 😉

muito obrigado.

esta função pode ser usada ou atualizada para usar numa grelha com quadrados de 32 por 32?(mesmo que só passe 3 ou 4 pixels no mesmo quadrado)

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

sim... estou a tentar:

void DrawRayLine(int X0, int Y0, float Radians, int Width,int Walls[10][10], int WallWidth, int WallHeight)
{
    int X1 = X0 + static_cast<int>(cos(Radians) * Width);
    int Y1 = Y0 + static_cast<int>(sin(Radians) * Width);

    int dx = abs(X1 - X0);
    int dy = abs(Y1 - Y0);

    double Steps;
    double x = X0;
    double y = Y0;

    // Calcular incrementos
    double INCREMENTO = 32.0;
    double Xincrement = INCREMENTO * cos(Radians);
    double Yincrement = INCREMENTO * sin(Radians);

    // Restante do código para desenhar o raio

    // Verificar se toca em uma parede

    bool hitsWall = false;
    while (x < X1 || y < Y1)
    {
         int currentX = static_cast<int>(x /32);
        int currentY = static_cast<int>(y /32);
        //cout << x << "\t" << y <<"\n";
        if (currentX >= 0 && currentX < WallWidth && currentY >= 0 && currentY < WallHeight)
        {
            if (Walls[currentX][currentY] != 0)
            {
                hitsWall = true;
                break;
            }
        }

        x += Xincrement;
        y += Yincrement;
    }
    HDC HDCConsole = GetWindowDC(GetConsoleWindow());
    HPEN LineColor = CreatePen(0,1,RGB(255,0,0));
    HPEN OldPen =(HPEN)SelectObject(HDCConsole,LineColor);
    MoveToEx(HDCConsole,X0,Y0,nullptr);
    LineTo(HDCConsole,x,y);
    SelectObject(HDCConsole,OldPen);
    DeleteObject(LineColor);
}

int main()
{
    int LevelMap[10][10]=
    {
        {1,1,1,1,1,1,1,1,1,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,1,1,1,1,1,1,1,1,1}
    };

    for(int X=0, Y=0;Y<10;)
    {
        HDC HDCConsole = GetWindowDC(GetConsoleWindow());
        Rectangle(HDCConsole,X*32,Y*32,X*32+31,Y*32+31);// ainda não comparo os valores para mudar a cor
        X++;
        if(X>=10)
        {
            X=0;
            Y++;
        }
    }
    DrawRayLine(3*32,3*32,25*3.14/180,200,LevelMap,10,10);
    cin.get();
    return 0;
}

este exemplo desenha a linha desejada, mas a linha termina no interior do quadrado e não no inicio do quadrado.... por usar o 32. e isso pode variar com o angulo.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

consegui melhores resultados:

double GetRadians(int Degrees)
{
    return (Degrees*M_PI/180);
}

void DrawRayLine(double X0, double Y0, double Radians, int Width,int Walls[10][10], int WallWidth, int WallHeight)
{
    double adjustedRadians = fmod(Radians, 2 * M_PI);

    double X1 = X0 + cos(adjustedRadians) * Width;
    double Y1 = Y0 + sin(adjustedRadians) * Width;

    if (X1 < X0)
    {
        double temp = X0;
        X0 = X1;
        X1 = temp;
    }

    double dx = abs(X1 - X0);
    double dy = abs(Y1 - Y0);

    double Steps;
    double x = X0;
    double y = Y0;
     if (dx >dy)
        Steps = dx;
    else
        Steps = dy;
    // Calcular incrementos
    double INCREMENTO = 5.0;
    double Xincrement =  (dx / Steps) * INCREMENTO;
    double Yincrement =  (dy / Steps) * INCREMENTO;

    // Restante do código para desenhar o raio

    // Verificar se toca em uma parede

    bool hitsWall = false;
    int S=0;
    while (x < X1 || y < Y1)
    {
        int currentX = static_cast<int>(x /32);
        int currentY = static_cast<int>(y /32);
        //cout << x << "\t" << y <<"\n";
        if (currentX >= 0 && currentX < WallWidth && currentY >= 0 && currentY < WallHeight)
        {
            if (Walls[currentY][currentX] != 0)
            {
                hitsWall = true;
                break;
            }
        }

        x += Xincrement;
        y += Yincrement;
        S++;
    }
    MessageBox (NULL,to_string(S).c_str(), "hello",MB_OK);
    HDC HDCConsole = GetWindowDC(GetConsoleWindow());
    HPEN LineColor = CreatePen(0,1,RGB(255,0,0));
    HPEN OldPen =(HPEN)SelectObject(HDCConsole,LineColor);
    MoveToEx(HDCConsole,X0,Y0,nullptr);
    LineTo(HDCConsole,x,y);
    SelectObject(HDCConsole,OldPen);
    DeleteObject(LineColor);
}

HDC HDCConsole = GetWindowDC(GetConsoleWindow());

int main()
{
    int LevelMap[10][10]=
    {
        {1,1,1,1,1,1,1,1,1,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,1,0,0,1},
        {1,0,0,0,0,1,0,0,0,1},
        {1,0,0,0,0,0,1,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,1},
        {1,1,1,1,1,1,1,1,1,1}
    };
    HBRUSH WhiteSquare=CreateSolidBrush(RGB(255,255,255));
    HBRUSH BlueSquare=CreateSolidBrush(RGB(0,0,255));
    HBRUSH OldBrush;
    for(int X=0, Y=0;Y<10;)
    {

        if(LevelMap[Y][X]==1) OldBrush=(HBRUSH)SelectObject(HDCConsole,BlueSquare);
        if(LevelMap[Y][X]!=1) OldBrush=(HBRUSH)SelectObject(HDCConsole,WhiteSquare);
        Rectangle(HDCConsole,X*32,Y*32,X*32+35,Y*32+35);
        X++;
        if(X>=10)
        {
            X=0;
            Y++;
        }
        SelectObject(HDCConsole,OldBrush);
    }
    DeleteObject(WhiteSquare);
    DeleteObject(BlueSquare);
    DrawRayLine(3.5*32,3.5*32,GetRadians(45),10000,LevelMap,10,10);
    cin.get();
    return 0;
}

noto 1 problema: se 45º é anti-horario porquê este resultado da linha vermelha?
image.thumb.png.22c883215a558b57b3e6e956064de5c1.png

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!