Thread: drawing basic lines....

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    3

    Question drawing basic lines....

    hello,
    sorry to bother anyone but i am new to c programming and trying to write a code that draws basic lines of any gradient using arrays, but i can only getting straight lines as the gradient turns out to be 0.
    Any help offered would be duly appreciated.
    The code i wrote is:
    Code:
    #include<stdio.h>
    #include<math.h>
    
    
    #define WIDTH 256							//Defines the maxiximum width in image array
    #define HEIGHT 128							//Defines the maximum height in image array
    #define RED 0								//Defines the Red colour component
    #define GREEN 1								//Defines the Green colour component
    #define BLUE 2								//Defines the Blue colour component
    
    void main ()
    {
    int Red, Green, Blue;						//Colour components 
    int Y_start, Y_end, X_start, X_end;			//Declares position of line start and line end
    int x, y;									//Declares x and y variables
    int X2, X1, Y2, Y1;							//Maximum and minimum values of X and Y
    int image [WIDTH][HEIGHT][3];				//Declares the image array
    	
    	 
    int count= 1;								//declares count variable
    int a, b;									//loop control variable 
    int m;										//Gradient
    
    FILE *pfile;								//File pointer
    pfile = fopen("basic-lines.ppm", "w");
    
    
    
    
    for(x=0; x<256; x++)												//for loop which includes x variable ranging its max value
    {
    for(y=0; y<128; y++)												//for loop whiuch includes y variable ranging its max value
    {
    image [x][y][RED]=255;
    image [x][y][GREEN]=255;											// values needed to set the background colour of the area to white
    image [x][y][BLUE]=255;
    }
    }	
    
    
    
    printf("\nAll values entered should be between 0 and 255");
    printf("\n\nEnter values for the following colours to determine the colour of the line: ");
    
    
    do
    {
    printf("\n\nRED:\t");												
    scanf("%i", &Red);														
    if (Red < 0 || Red > 255)											
    printf("\n\aNumber is out of range, please enter another\a:");
    }
    while ((Red < 0) || (Red > 255));
    
    do
    {
    printf("\nGREEN:\t");												 					
    scanf("%i", &Green);															
    if (Green < 0 || Green > 255)										 					
    printf("\n\aNumber is out of range\a:");
    }
    while ((Green < 0) || (Green > 255));
    
    do
    {
    printf("\nBLUE:\t");																			
    scanf("%i", &Blue);													
    if (Blue < 0 || Blue > 255)											
    printf("\n\aNumber is out of range:");
    }
    while ((Blue < 0) || (Blue > 255));
    
    
    do
    {
    printf("\nPlease enter the X co-ordinate for the start of the line:  ");		
    scanf("%i", &X_start);														
    if(X_start > 256)															
    printf("\a\nCo-ordinate is out of range\a:");
    }
    while ((X_start > 256));
    
    
    do
    {
    printf("\nPlease enter the Y co-ordinate for the start of the line:  ");		
    scanf("%i", &Y_start);														
    if (Y_start > 128)															
    printf("\n\aCo-ordinate is out of range\a:");
    }
    while ((Y_start > 128));					
    
    
    
    do
    {
    printf("\nPlease enter the X co-ordinate for the end of the line:\t ");		
    scanf("%i", &X_end);														
    if (X_end > 256)																
    printf("\n\aCo-ordinate is out of range\a:");
    }
    while ((X_end > 256));
    
    
    do
    {
    printf("\nPlease enter the Y co-ordinate for the end of the line: ");		
    scanf("%i", &Y_end);														
    if (Y_end > 128)															
    printf("\n\aCo-ordinate is out of range\a:");
    }
    while ((Y_end > 128));
    
    
       
    
    
    
    
    
    if (X_start>X_end)			//If statement to check if x value for start of line is greater than end of line
    {
    X2=X_start;				//If so, X2 becomes X co-ordinate of start of line
    X1=X_end;				//X1 becomes X co-ordinate of end of line 
    }
    else
    { 
    X2=X_end;				//Otherwise X2 becomes X co-ordinate for end of line 
    X1=X_start;				//and X1 becomes X co-ordinate for the start of the line 
    }
    if (Y_start>Y_end)			 //if statement to check if Y value for start of line is greater than that for end of line
    {
    Y2=Y_start;				//If so, Y2 becomes Y co-ordinate of start of line
    Y1=Y_end;				//Y1 becomes X co-ordinate of end of line 
    }
    else
    { 
    Y2=Y_end;				//Otherwise Y2 becomes Y co-ordinate for end of line 
    Y1=Y_start;				//and Y1 becomes Y co-ordinate for the start of the line 
    }
    
    
    m= abs((Y_end-Y_start)/(X_end-X_start));   //Calculating the gradient 
    
    a=Y1;						//Equating 'a' variable to max Y value
    b=X2;						//Equating 'b' variable to min X value
    
    if ( m <=1)
    {
    printf("Gradient: %f \n", m);//Condition for if gradient is less than or equal to 1
    for (x=X1; x<=X2; x++)	// For when x variable = X1, less than or equal to X2, and incremented by 1
    {
    y=a;
    	
    if ((x>=0 && x<=255) && (y>=0 && y<=127)) 
    {
    image [x][y][RED]=Red;          
    image [x][y][GREEN]=Green;	//Defines array of red green and blue 
    image [x][y][BLUE]=Blue;
    }
    else
    {
    }
    }
    }
    else
    {
    m=1/m;
    printf("Gradient is: %i\n", m);
    for (y=Y1; y<=Y2; y++)				// For when y variable = Y1, less than or equal to Y2, and incremented by 1
    {
    	
    (float)b=(float)(b+m);
    x=b;
    if ((x>=0 && x<=255) && (y>=0 && y<=127))	
    {
    image [x][y][RED]=Red;
    image [x][y][GREEN]=Green;		 
    image [x][y][BLUE]=Blue;
    }
    else
    {
    }
    }
    }
    fprintf(pfile, "P3\n256 128\n255\n\n");   
    
    for(y=0; y<128; y++)
    {
    for(x=0; x<256; x++)
    {
    fprintf(pfile, "%d ", image [x][y][RED]);
    fprintf(pfile, "%d ", image [x][y][GREEN]);
    fprintf(pfile, "%d ", image [x][y][BLUE]);
    }
    }
    
    
    
    
    fclose(pfile);										
    scanf("%*s");										
    }
    the line is viewed using Xnview.

  2. #2
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    First off you want to learn how to indent your code, as its will be much easier for you and other people to see whats going on in your code.

    here:
    Code:
    m= abs((Y_end-Y_start)/(X_end-X_start));   //Calculating the gradient
    You want to be careful as if x_end == x_start you will end up with a divide by zero error.

    here:
    Code:
    printf("Gradient: &#37;f \n", m);//Condition for if gradient is less than or equal to 1
    you are printing m as if its a float when you have decalred it as an integer. I think you will need m to be a float, as integers can't hold fractions. For example here:
    Code:
    m=1/m;
    m will always end up being 0 (Edit: or 1). Dont know if that fixes yopur problem.

    Finally main should be declared as:
    Code:
    int main()
    and return 0 at the end
    Last edited by mike_g; 02-21-2008 at 05:17 AM.

  3. #3
    Registered User
    Join Date
    Feb 2008
    Posts
    3
    thank you very much,
    the gradient is been displayed now, but can't get it to draw sloping lines. It just draws straight vertical lines...Any help would be appreciated on making it to draw sloping line...

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    This is what your code would look like with indentation:
    Code:
    #include<stdio.h>
    #include<math.h>
    
    
    #define WIDTH 256							//Defines the maxiximum width in image array
    #define HEIGHT 128							//Defines the maximum height in image array
    #define RED 0								//Defines the Red colour component
    #define GREEN 1								//Defines the Green colour component
    #define BLUE 2								//Defines the Blue colour component
    
    int main () {
        int Red, Green, Blue;						//Colour components
        int Y_start, Y_end, X_start, X_end;			//Declares position of line start and line end
        int x, y;									//Declares x and y variables
        int X2, X1, Y2, Y1;							//Maximum and minimum values of X and Y
        int image [WIDTH][HEIGHT][3];				//Declares the image array
    
    
        int count= 1;								//declares count variable
        int a, b;									//loop control variable
        int m;										//Gradient
    
        FILE *pfile;								//File pointer
        pfile = fopen("basic-lines.ppm", "w");
    
        for (x=0; x<256; x++)												//for loop which includes x variable ranging its max value
        {
            for (y=0; y<128; y++)												//for loop whiuch includes y variable ranging its max value
            {
                image [x][y][RED]=255;
                image [x][y][GREEN]=255;											// values needed to set the background colour of the area to white
                image [x][y][BLUE]=255;
            }
        }
    
        printf("\nAll values entered should be between 0 and 255");
        printf("\n\nEnter values for the following colours to determine the colour of the line: ");
    
        do {
            printf("\n\nRED:\t");
            scanf("&#37;i", &Red);
            if (Red < 0 || Red > 255)
                printf("\n\aNumber is out of range, please enter another\a:");
        } while ((Red < 0) || (Red > 255));
    
        do {
            printf("\nGREEN:\t");
            scanf("%i", &Green);
            if (Green < 0 || Green > 255)
                printf("\n\aNumber is out of range\a:");
        } while ((Green < 0) || (Green > 255));
    
        do {
            printf("\nBLUE:\t");
            scanf("%i", &Blue);
            if (Blue < 0 || Blue > 255)
                printf("\n\aNumber is out of range:");
        } while ((Blue < 0) || (Blue > 255));
    
        do {
            printf("\nPlease enter the X co-ordinate for the start of the line:  ");
            scanf("%i", &X_start);
            if (X_start > 256)
                printf("\a\nCo-ordinate is out of range\a:");
        } while ((X_start > 256));
    
        do {
            printf("\nPlease enter the Y co-ordinate for the start of the line:  ");
            scanf("%i", &Y_start);
            if (Y_start > 128)
                printf("\n\aCo-ordinate is out of range\a:");
        } while ((Y_start > 128));
    
        do {
            printf("\nPlease enter the X co-ordinate for the end of the line:\t ");
            scanf("%i", &X_end);
            if (X_end > 256)
                printf("\n\aCo-ordinate is out of range\a:");
        } while ((X_end > 256));
    
        do {
            printf("\nPlease enter the Y co-ordinate for the end of the line: ");
            scanf("%i", &Y_end);
            if (Y_end > 128)
                printf("\n\aCo-ordinate is out of range\a:");
        } while ((Y_end > 128));
    
        if (X_start>X_end)			//If statement to check if x value for start of line is greater than end of line
        {
            X2=X_start;				//If so, X2 becomes X co-ordinate of start of line
            X1=X_end;				//X1 becomes X co-ordinate of end of line
        } else {
            X2=X_end;				//Otherwise X2 becomes X co-ordinate for end of line
            X1=X_start;				//and X1 becomes X co-ordinate for the start of the line
        }
        if (Y_start>Y_end)			 //if statement to check if Y value for start of line is greater than that for end of line
        {
            Y2=Y_start;				//If so, Y2 becomes Y co-ordinate of start of line
            Y1=Y_end;				//Y1 becomes X co-ordinate of end of line
        } else {
            Y2=Y_end;				//Otherwise Y2 becomes Y co-ordinate for end of line
            Y1=Y_start;				//and Y1 becomes Y co-ordinate for the start of the line
        }
    
        m= abs((Y_end-Y_start)/(X_end-X_start));   //Calculating the gradient
    
        a=Y1;						//Equating 'a' variable to max Y value
        b=X2;						//Equating 'b' variable to min X value
    
        if ( m <=1) {
            printf("Gradient: %f \n", m);//Condition for if gradient is less than or equal to 1
            for (x=X1; x<=X2; x++)	// For when x variable = X1, less than or equal to X2, and incremented by 1
            {
                y=a;
    
                if ((x>=0 && x<=255) && (y>=0 && y<=127)) {
                    image [x][y][RED]=Red;
                    image [x][y][GREEN]=Green;	//Defines array of red green and blue
                    image [x][y][BLUE]=Blue;
                } else {}
            }
        } else {
            m=1/m;
            printf("Gradient is: %i\n", m);
            for (y=Y1; y<=Y2; y++)				// For when y variable = Y1, less than or equal to Y2, and incremented by 1
            {
    
                (float)b=(float)(b+m);
                x=b;
                if ((x>=0 && x<=255) && (y>=0 && y<=127)) {
                    image [x][y][RED]=Red;
                    image [x][y][GREEN]=Green;
                    image [x][y][BLUE]=Blue;
                } else {}
            }
        }
        fprintf(pfile, "P3\n256 128\n255\n\n");
    
        for (y=0; y<128; y++) {
            for (x=0; x<256; x++) {
                fprintf(pfile, "%d ", image [x][y][RED]);
                fprintf(pfile, "%d ", image [x][y][GREEN]);
                fprintf(pfile, "%d ", image [x][y][BLUE]);
            }
        }
    
        fclose(pfile);
        scanf("%*s");
    }
    For one thing you really should read about functions, as there is very much redundant code in there (all the input loops could be handled by a single function.

    Now, to the gradient calculation. Are you sure that you need to use abs there? I'm not terribly strong in math, but I seem to remember that the sign of the gradient carries important information about the direction of the line.

    As for the output loops
    Code:
            for (x=X1; x<=X2; x++)	// For when x variable = X1, less than or equal to X2, and incremented by 1
            {
                y=a;
    
                if ((x>=0 && x<=255) && (y>=0 && y<=127)) {
                    image [x][y][RED]=Red;
                    image [x][y][GREEN]=Green;	//Defines array of red green and blue
                    image [x][y][BLUE]=Blue;
                } else {}
            }
    You are not changing y at all in this loops (or x in the following loop). Of course this can only produce horizontal/vertical lines. Did you mean to add gradient to y each time through the loop or something like that?
    Last edited by anon; 02-21-2008 at 08:30 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Yeah anon is right.

    'm' is your gradient, so 'a' needs to be incremented by 'm' each loop:
    Code:
            for (x=X1; x<=X2; x++)	// For when x variable = X1, less than or equal to X2, and incremented by 1
            {
                a+=m;
                y=a;
    
                if ((x>=0 && x<=255) && (y>=0 && y<=127)) {
                    image [x][y][RED]=Red;
                    image [x][y][GREEN]=Green;	//Defines array of red green and blue
                    image [x][y][BLUE]=Blue;
                } else {}
            }
    Also to invert m remeber to use:
    Code:
    m = 1.0 / m;
    for floating point maths.

    Another thing worth noting is that the variables a and b seem redundant, as you could just use y and x instead.

    Edit: again, like anon said, your lines wont be drawn correctly using an absolute value if the gradient is negative. For negative gradients you could have you could use a decrementing for loop.
    Last edited by mike_g; 02-21-2008 at 09:56 AM.

  6. #6
    Registered User
    Join Date
    Feb 2008
    Posts
    3

    Post lines..........

    thank you very much, i have changed the code now, but still getting vertical lines only...any codes welcomed.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    This is a simplified unoptimized version of Bresehnam's algorithm. Using slope will not yield the correct results because it does not operate on each pixel and leaves gaps. This algo will correctly draw a line from x1,y1 to x2,y2 and fill in all appropriate pixels.

    Code:
    void Line(int x1,int y1,int x2,int buffer_pitch,int y2,UINT color)
    {
      int diffx = x2-x1;
      int diffy = y2-y1;
      int xunit = 1;
      int yunit = buffer_pitch;
      int length = 0;
      unsigned int offset = y1 * buffer_pitch + x1;
      int eterm = 0;
      
      if (diffx < 0)
      {
         diffx = -diffx;
         xunit = -xunit;
      }
      if (diffy < 0)
      {
        diffy = -diffy;
        yunit = -yunit;
      }
    
      if (diffx < diffy)
      {
         length = diffx+1;
         for (int i = 0;i < length; ++i)
         {
            Buffer[offset] = color;
            offset += xunit;
            eterm += diffx;
            if (eterm > diffy)
            {
               eterm -= diffx;
               offset += yunit;
            }
          }
       }  
        else
       {
          length = diffy + 1;
          for (int i = 0;i < length; ++i)
          {
             Buffer[offset] = color;
             offset += yunit;
             eterm += diffy;
             if (eterm > 0)
             {
                eterm -= diffy;
                offset += xunit;
             }
          }
       }
    }
    If the code does not seem to draw lines correctly it is possible I mixed up the eterm's. In other words the eterm increment may be swapped so diffx's eterm should be swapped with diffy's. Check the internet for more info.

    Most libraries already have line drawing functions so I don't know why you would need this.

  8. #8
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Using slope will not yield the correct results because it does not operate on each pixel and leaves gaps.
    Not necessarily (if I understand you correctly here). As either the vertical or horizontal gradient is going to be >=-1 and <=1, by stepping along the shallowest gradient you wont end up missing pixels.

    I'm pretty sure that the OP's current problem (not drawing a slope) is coming from the fact that he/she is using integers for everything. One example is that the variables 'a' and 'b' would need to be floats to hold the fractions incremented by.
    Last edited by mike_g; 02-22-2008 at 04:19 AM.

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Not necessarily (if I understand you correctly here). As either the vertical or horizontal gradient is going to be >=-1 and <=1, by stepping along the shallowest gradient you wont end up missing pixels.
    The exact reason Bresehnam's even exists is because you cannot draw integral lines using slope alone. The algo was invented a long time ago and was meant to address this very problem. I believe early plotters used this algo to plot the lines on the paper.

    The algo stems from the fact that the guy had to draw lines on the computer but could not use floating point since it was not supported by the CPU at the time. He came up with an algorithm that used an error_term which allowed him to use integers yet still be able to draw lines of any slope.

  10. #10
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Sure, avoiding floats is better. I wrote my first line algo using floating point, but later switched to bresenham lines as they are faster. Same too with circles actually.

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    > Bresehnam's algorithm
    It's actually Bresenham.

    There's a nice tutorial about it at brackeen.com: http://brackeen.com/vga/shapes.html#2
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Line Counting
    By 00Sven in forum C Programming
    Replies: 26
    Last Post: 04-02-2006, 08:59 PM
  2. Finding number of lines of code
    By arron in forum Linux Programming
    Replies: 8
    Last Post: 01-06-2006, 05:35 AM
  3. what are your thoughts on visual basic?
    By orion- in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 09-22-2005, 04:28 AM
  4. visual basic vs C or C++
    By FOOTOO in forum Windows Programming
    Replies: 5
    Last Post: 02-06-2005, 08:41 PM