como desenhar 1 linha usando matemática simples?

Cambalinho

Power Member
eis o meu pseu-codigo:
1 - calculo a distancia da linha:
Código:
int LineDistance = sqrt( pow(X1-X0,2) + pow(Y1-Y0,2) );
'sqr()' é a raiz quadrada e 'pow()' é para o quadrado.
ou seja:
DistanciaDaRecta = RaizQuadrada(Quadrado(X1-X0) + Quadrado(Y1-Y0))
2 - calculo os passos de X e Y:
Código:
int XSteps =round( (X1 - X0)/LineDistance);
int YSteps = round((Y1 - Y0)/LineDistance);
PassosX = (X1-X0)/DistanciaDaLinha
e

PassosY = (Y1-Y0)/DistanciaDaLinha

estes calculos estão correctos?
eu calculo os passos para os usar num ciclo e desenhar a linha ponto a ponto...
PS: honestamente estou a rever alguma Matemática(e aprender mais) e tentar a utilizar, também, em Programação. eu já tenho funções para desenhar a linhas, mas gostava de entender como elas funcionam melhor ;)

a linha é desenhada se a linha for horizontal\vertical... mas a diagonal, nada é desenhado.
 
o código está correto... o que estava a esquecer era que tenho de usar cálculos float\decimais\virgula... e obter o X e Y integers\inteiros.
Código:
void DrawLine(HDC Destination, int X0, int Y0, int X1, int Y1, COLORREF LineColor = RGB(255,0,0))
{
    //Getting Line Distance(float resuults):
    float DX = X1 - X0;
    float DY = Y1 - Y0;
    //For 3D:
    //float DZ = Z1 - Z0;
    float LineDistance = sqrt(pow(DX,2) + pow(DY,2)); //for 3D add the pow(DZ,2) inside of sqrt()
    
    
    //Getting the Steps incrementation(float results):
    float XSteps =(float)DX/LineDistance;
    float YSteps =(float)DY/LineDistance;
    //For 3D:
    //float ZSteps = (float)DZ/LineDistance;
    
    //Draw Line using the Steps\ Incrementation:
    for(int i=0, X=X0, Y=Y0; X<X1 && Y <Y1; i++)
    {
        SetPixel(Destination,X,Y,LineColor);
        
        //Increment steps(integer results):
        X+=round(XSteps);
        Y+=round(YSteps);
        //For 3D:
        //Z+=round(ZSteps);
    }
}
repito: o que falhei no pseu-código foi não usar valores decimais(float) para os cálculos e depois os converter em inteiros(round())
muito obrigado
 

Kayvlim: por acaso eu já tinha entrado nesse link(por google), mas o erro que fiz(apesar de fazer com outros cálculos) está lá: não usa cálculos float e resultados inteiros usando o 'round'.
leitores: usar o GetPixel() é lento, deveríamos usar DIB's ou outro mais rápido... mas é o melhor de aprender ;)

 
boa consegui corrigir o código para desenhar 1 linha 3D...
este código usa o centro 0,0 do ecra.
Código:
void DrawLine(HDC Destination, int X0, int Y0, int X1, int Y1, COLORREF LineColor = RGB(255,0,0))
{
    //Getting Line Distance(float resuults):
    float DX = X1 - X0;
    float DY = Y1 - Y0;

    float LineDistance = sqrt(pow(DX,2) + pow(DY,2));


    //Getting the Steps incrementation(float results):
    float XSteps =(float)DX/LineDistance;
    float YSteps =(float)DY/LineDistance;

    //Draw Line using the Steps\ Incrementation:
    int X = X0;
    int Y = Y0;

    for(int i=0; i<LineDistance; i++)
    {

        SetPixel(Destination,X,Y,LineColor);

        //Increment steps(integer results):
        X+=round(XSteps);
        Y+=round(YSteps);
    }
}

void DrawLine3D(HDC Destination, int X0, int Y0, int Z0, int X1, int Y1, int Z1, COLORREF LineColor = RGB(255,0,0))
{
    //Avoiding division by zero:
    if(Z0==0) Z0=1;
    if(Z1==0) Z1=1;
    
    //Getting Line Distance(float results):
    float DX = X1 - X0;
    float DY = Y1 - Y0;
    float DZ = Z1 - Z0;
    float LineDistance = sqrt(pow(DX,2) + pow(DY,2) + pow(DZ,2));


    //Getting the Steps incrementation(float results):
    float XSteps = DX/LineDistance;
    float YSteps = DY/LineDistance;
    float ZSteps = DZ/LineDistance;

    //Draw Line using the Steps\ Incrementation:
    float X = X0;
    float Y = Y0;
    float Z = Z0;

    for(int i=0; i<LineDistance; i++)
    {
        //For every steps we calculate the perspective:
        float Perspective = 300/(300+Z);

        //The 3D to 2D convertion(i use 300 of eye distance, but we can change it):
        int PosX = round(X*Perspective);
        int PosY = round(Y*Perspective);

        //Draw the pixel:
        SetPixel(Destination,PosX,PosY,LineColor);

        //Increment steps(integer results):
        X+=XSteps;
        Y+=YSteps;
        Z+=ZSteps;
    }
}
usando o mesmo principio consegui criar a função para desenhar 1 linha normal e a 3D. No 3D temos de usar a perspetiva, porque o ecra usa X,Y e não X, Y, Z.
NUNCA ESQUECER:
1 - todos os cálculos são feitos com variáveis do tipo float;
2 - os resultados finais tem de ser inteiros usando a função round();
3 - no 3D temos de calcular a perspetiva usando a distancia do olho e a coordenada Z... estou sempre a calcular a perspetiva porque o Z está sempre a mudar ;)
para calcular o comprimento da linha, eu vi no livro de matemática... usando o comprimento de cada coordenada, podemos calcular o que podemos somar em cada coordenada. espero que este tópico ajude tanto quanto a mim. agora consigo criar 1 função para desenhar 1 linha sem problemas e calcular a perspetiva(converter o 3D para 2D).
penso que a espessura é desenhar várias linha lado a lado... e a forma como a desenhamos é usar passos: desenhar de 5 em 5 pontos... ou desenhar 5 pontos e deixar 3... além de mudar a cor. já podemos personalizar a linha como queremos.
o SetPixel() é muito lento, mas para testar serve. só não sei se pow(), sqrt(), round(), divisão e multiplicação estão a usar muito CPU.
muito obrigado a todos.
 
preciso de entender 1 coisa sobre o Z na linha: tenho de calcular a perspectiva em todos os pontos da linha ou basta só a Origem e Destino?
estou a tentar obter mais velocidade
 
Back
Topo