9
votes

Lignes de dessin avec algorithme de ligne de Bresenham

Les devoirs graphiques de mon ordinateur sont d'implémenter des algorithmes OpenGL à l'aide de la capacité de dessiner des points.

Si évidemment, j'ai besoin d'obtenir Drawline () Code> Pour que je puisse tirer quelque chose d'autre. Drawline () Code> doit être effectué à l'aide d'entiers uniquement. Pas de point flottant. P>

C'est ce que j'ai appris. Fondamentalement, des lignes peuvent être divisées en 4 catégories différentes, raides positives, positives peu profondes, négatives escarpées et négatives peu profondes. C'est la photo que je suis censée dessiner: p>

résultat attendu p>

Et ceci est la photo mon programme dessine: p>

résultat réel p>

Les couleurs sont faites pour nous. Nous avons des sommets donnés et nous devons utiliser l'algorithme de ligne de Bresenham pour dessiner les lignes en fonction des points de début et de fin. P>

C'est ce que j'ai jusqu'à présent: P>

int dx = end.x - start.x;
int dy = end.y - start.y;

//initialize varibales
int d;
int dL;
int dU;

if (dy > 0){
        if (dy > dx){
                //+steep
                d = dy - 2*dx;
                dL = -2*dx;
                dU = 2*dy - 2*dx;

                for (int x = start.x, y = start.y; y <= end.y; y++){
                        Vertex v(x,y);
                        drawPoint(v);

                        if (d >= 1){
                                d += dL;
                        }else{
                                x++;
                                d += dU;
                        }
                }              
        } else {
                //+shallow
                d = 2*dy - dx;
                dL = 2*dy;
                dU = 2*dy - 2*dx;

                for (int x = start.x, y = start.y; x <= end.x; x++) {
                        Vertex v(x,y);
                        drawPoint(v);

                        // if choosing L, next y will stay the same, we only need
                        // to update d by dL
                        if (d <= 0) {
                                d += dL;
                        // otherwise choose U, y moves up 1
                        } else {
                                y++;
                                d += dU;
                        }
                }
        }
} else {
        if (-dy > dx){
                cout << "-steep\n";
                //-steep
                d = dy - 2*dx;
                //south
                dL = 2*dx;
                //southeast
                dU = 2*dy - 2*dx;

                for (int x = start.x, y = start.y; y >= end.y; --y){
                        Vertex v(x,y);
                        drawPoint(v);

                        //if choosing L, next x will stay the same, we only need
                        //to update d
                        if (d >= 1){
                                d -= dL;
                        } else {
                                x++;
                                d -= dU;
                        }
                }

        } else {
                cout << "-shallow\n";
                //-shallow
                d = 2*dy - dx;
                dL = 2*dy;
                dU = 2*dy - 2*dx;

                for (int x = start.x, y = start.y; x <= end.x; x++){
                        Vertex v(x,y);
                        drawPoint(v);

                        if (d >= 0){
                                d += dL;
                        } else {
                                --y;
                                d -= dU;
                        }
                }
        }
}


3 commentaires

Si vous regardez les deux images du paragraphe ci-dessus, mon code, le "2e quadrant" et le "4ème quadrant" ne sont pas corrects. Je mets ceux entre citations parce que le point (0,0) est dans le coin inférieur gauche de l'image. Fondamentalement, la première déclaration contient le code qui ne fonctionne pas correctement, -.


Exécutez votre code sur 2 exemples simples, celui qui fonctionne et celui qui ne le fait pas. Dites (0,0), (5, 5) et (0,5), (5,0), trace à la fois et voir étiez-ils divergent. Ce sera un exercice bien meilleur que d'avoir quelqu'un pour le faire pour vous.


Je l'ai fait et je ne peux toujours pas sembler comprendre comment résoudre le problème. Ce qui se passe, c'est la déclaration IF dans toutes les boucles, si (D> = 0) n'est pas basculé comme ça. Pour la ligne de (0,5) à (5,0), il devrait toujours soustraire à chaque fois de manière à ce que cela rend une ligne exactement à 45 degrés mais ce n'est pas le cas.


3 Réponses :


2
votes

Au cas où tout le monde se demandait quel était le problème, je ne sais toujours pas ce que c'était. Ce que j'ai fini par faire a été récupéré mon code de sorte que le -shallowallow et le même algorithme soit + peu profond et + raide, respectivement. Après avoir réglé les coordonnées X, Y (nier la coordonnée X ou Y), lorsque je suis allé les tracer, j'ai annulé ma négation d'origine afin qu'elle tracée au bon endroit.


1 commentaires

Je ne connais pas le langage C, mais certaines des valeurs fraktionnelles doivent-elles être converties en valeurs absolues?



9
votes
/*BRESENHAAM ALGORITHM FOR LINE DRAWING*/
#include<iostream.h>
#include<graphics.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
#include<dos.h>
void bhm_line(int,int,int,int,int);
void main()
{
 int ghdriver=DETECT,ghmode,errorcode,x1,x2,y1,y2;
 initgraph(&ghdriver,&ghmode,"..\\bgi");
 errorcode = graphresult();
 if(errorcode !=grOk)
 {
  cout<<"Graphics error:%s\n"<<grapherrormsg(errorcode);
  cout<<"Press any key to halt:";
  getch();
  exit(1);
 }
 clrscr();
 cout<<"Enter the coordinates (x1,y1): ";
 cin>>x1>>y1;
 cout<<"Enter the coordinates (x2,y2): ";
 cin>>x2>>y2;
 bhm_line(x1,y1,x2,y2,1);
 getch();
}
void bhm_line(int x1,int y1,int x2,int y2,int c)
{
 int x,y,dx,dy,dx1,dy1,px,py,xe,ye,i;
 dx=x2-x1;
 dy=y2-y1;
 dx1=fabs(dx);
 dy1=fabs(dy);
 px=2*dy1-dx1;
 py=2*dx1-dy1;
 if(dy1<=dx1)
 {
  if(dx>=0)
  {
   x=x1;
   y=y1;
   xe=x2;
  }
  else
  {
   x=x2;
   y=y2;
   xe=x1;
  }
  putpixel(x,y,c);
  for(i=0;x<xe;i++)
  {
   x=x+1;
   if(px<0)
   {
    px=px+2*dy1;
   }
   else
   {
    if((dx<0 && dy<0) || (dx>0 && dy>0))
    {
     y=y+1;
    }
    else
    {
     y=y-1;
    }
    px=px+2*(dy1-dx1);
   }
   delay(0);
   putpixel(x,y,c);
  }
 }
 else
 {
  if(dy>=0)
  {
   x=x1;
   y=y1;
   ye=y2;
  }
  else
  {
   x=x2;
   y=y2;
   ye=y1;
  }
  putpixel(x,y,c);
  for(i=0;y<ye;i++)
  {
   y=y+1;
   if(py<=0)
   {
    py=py+2*dx1;
   }
   else
   {
    if((dx<0 && dy<0) || (dx>0 && dy>0))
    {
     x=x+1;
    }
    else
    {
     x=x-1;
    }
    py=py+2*(dx1-dy1);
   }
   delay(0);
   putpixel(x,y,c);
  }
 }
}

2 commentaires

Ceci est une réponse uniquement liée; Veuillez éditer votre réponse pour inclure le code actuel et non seulement le lien.


Quel est le "délai (0)" dans bhm_line ()?



3
votes

J'ai mis en place l'algorithme d'origine de Bresenham en C ++ et j'ai essayé d'optimiser autant que je pouvais (surtout en ce qui concerne l'élimination du si de la boucle intérieure).

Il tire dans un tampon linéaire au lieu d'une surface, et pour cette affaire , cette implémentation était presque aussi rapide que EFLA (algorithme de ligne extrêmement rapide) (peut-être 5% plus lent ). P>

void drawLine(Point2Di p0,  Point2Di p1)
{
    bool yLonger=false;
    int shortLen=p1.y-p0.y;
    int longLen=p1.x-p0.x;
    if (abs(shortLen)>abs(longLen)) {
        swap(shortLen, longLen);
        yLonger=true;
    }
    int decInc = longLen==0 ?  decInc=0 : ((shortLen << 16) / longLen);

    if (yLonger) {
        p0.y*=imageSide;
        p1.y*=imageSide;
        if (longLen>0)
            for (int j=0x8000+(p0.x<<16);p0.y<=p1.y;p0.y+=imageSide, j+=decInc)
                buffer[p0.y + (j >> 16)] = 255;  // or a call to your painting method
        else
            for (int j=0x8000+(p0.x<<16);p0.y>=p1.y;p0.y-=imageSide, j-=decInc)
                buffer[p0.y + (j >> 16)] = 255;  // or a call to your painting method
    }
    else
    {
        if (longLen>0)
            for (int j=0x8000+(p0.y<<16);p0.x<=p1.x;++p0.x, j+=decInc)
                buffer[(j >> 16) * imageSide + p0.x] = 255;  // or a call to your painting method
        else
            for (int j=0x8000+(p0.y<<16);p0.x>=p1.x;--p0.x, j-=decInc)
                buffer[(j >> 16) * imageSide + p0.x] = 255;  // or a call to your painting method
    }
}


0 commentaires