Thread: PPM Vectors

  1. #1
    Registered User
    Join Date
    Sep 2012
    Location
    Clemson, SC USA
    Posts
    19

    PPM Vectors

    I'm having a rough time trying to make a PPM image of a triangle given three points. If I can get the points into vectors, I can just say that

    if (((x > AC) && (x < BC) && (x < AB)) && ((y > AB) && (y < AC) && (y < BC)))
    make_pixel(purple);
    else
    make_pixel(black);

    I understand how to get the slopes, but how can I form that into vectors? I've tried to get it into y=mx+b format... My three points are

    A (400,100)
    B (600,240)
    C (525,450)

    All in a 640 * 480W image.

    Really lost here...

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Is your array to hold the pixels, an array of structs with rows and columns, 640 rows x 480 columns, all able to hold a full pixel (red, green, and blue), so 3 chars?

  3. #3
    Registered User
    Join Date
    Sep 2012
    Location
    Clemson, SC USA
    Posts
    19
    Quote Originally Posted by Adak View Post
    Is your array to hold the pixels, an array of structs with rows and columns, 640 rows x 480 columns, all able to hold a full pixel (red, green, and blue), so 3 chars?
    I believe so, except 640 columns and 480 rows. The background is longer than it is tall.

    I meant a vector in the Geometric sense. Like a line segment. If I can print the line segments and just set a pixel 'i' to greater than, less than each vector then I can just use a for loop to fill in the triangle. Or at least, I think I can. My question is either how to (1) code line segments between each point or (2) how to draw a triangle. It isn't a right triangle, so that kinda complicates things.

    My dad emailed me something called the Barycentric Coordinate System, but the math is just beyond me.

    Barycentric coordinate system - Wikipedia, the free encyclopedia

    Barycentric Coordinates, Areal coordinates

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Since I did most of my beer drinking at home, your dad's Barycentric coordinate system, is well beyond me, also.

    I believe I could do it with an array, however. I've drawn triangles with PPM images before, but I just wrote them out from start to finish, directly to the file, which I don't think is workable in your case.

    Let me mess with that a bit.

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is what I came up with. This is my first time working with PPM files, using an array. Study it at your own risk!!

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define WIDTH  120
    #define HEIGHT 100
    
    typedef struct pixels {
       unsigned char r;
       unsigned char g;
       unsigned char b;
    }pxl;
    
    typedef struct points {
       int x;
       int y;
    }point;
    
    void triangles(pxl px[HEIGHT][WIDTH]);
    void output(pxl px[][WIDTH],FILE *fp); 
    
    int main(void) {
       pxl px[HEIGHT][WIDTH]={0};
       FILE *fp;   
       fp=fopen("out.ppm","wb");
       
       if(!fp) {
          printf("Error: file failed to open\n");
          return 0;
       }
      
       triangles(px);
       output(px,fp);
    
       system("out.ppm");
       return 0;
    }
    
    //puts the pixels into the array px[][]
    void triangles (pxl px[][WIDTH]) {
       int r1,c1,rm; //rm=right margin
       point A,B,C;      //where A,B,C are the corners of the triangle
       A.y=10;           // A|-----------B
       A.x=10;           //  |          /
       B.y=10;           //  |         / 
       B.x=60;           //  |        /
       C.y=80;           //  |       /
       C.x=10;           //  |      /
                         //  |     /
                         //  |    /
                         //  |   /
                         //  |  /
                         //  | /
                         //  |/
       rm=B.x;           //  C
       for(r1=A.y;r1<=C.y;r1++) {             
          
          for(c1=A.x;c1<=rm;c1++) {
             
             px[r1][c1].r=0;
             px[r1][c1].g=255;
             px[r1][c1].b=0;      
          }
          rm-=WIDTH/HEIGHT;   
    
       }
    }
    void output(pxl px[][WIDTH],FILE *fp) {
       int r,c;
       
       fprintf(fp,"P6\n%d %d %d\n", WIDTH, HEIGHT, 255); 
       
       for(r=0;r<HEIGHT;r++) {
          for(c=0;c<WIDTH;c++) {
             fprintf(fp, "%c%c%c",px[r][c].r,px[r][c].g,px[r][c].b);
          }
       }
       fclose(fp);
    }

  6. #6
    Registered User
    Join Date
    Sep 2012
    Location
    Clemson, SC USA
    Posts
    19
    Quote Originally Posted by Adak View Post
    This is what I came up with. This is my first time working with PPM files, using an array. Study it at your own risk!!

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define WIDTH  120
    #define HEIGHT 100
    
    typedef struct pixels {
       unsigned char r;
       unsigned char g;
       unsigned char b;
    }pxl;
    
    typedef struct points {
       int x;
       int y;
    }point;
    
    void triangles(pxl px[HEIGHT][WIDTH]);
    void output(pxl px[][WIDTH],FILE *fp); 
    
    int main(void) {
       pxl px[HEIGHT][WIDTH]={0};
       FILE *fp;   
       fp=fopen("out.ppm","wb");
       
       if(!fp) {
          printf("Error: file failed to open\n");
          return 0;
       }
      
       triangles(px);
       output(px,fp);
    
       system("out.ppm");
       return 0;
    }
    
    //puts the pixels into the array px[][]
    void triangles (pxl px[][WIDTH]) {
       int r1,c1,rm; //rm=right margin
       point A,B,C;      //where A,B,C are the corners of the triangle
       A.y=10;           // A|-----------B
       A.x=10;           //  |          /
       B.y=10;           //  |         / 
       B.x=60;           //  |        /
       C.y=80;           //  |       /
       C.x=10;           //  |      /
                         //  |     /
                         //  |    /
                         //  |   /
                         //  |  /
                         //  | /
                         //  |/
       rm=B.x;           //  C
       for(r1=A.y;r1<=C.y;r1++) {             
          
          for(c1=A.x;c1<=rm;c1++) {
             
             px[r1][c1].r=0;
             px[r1][c1].g=255;
             px[r1][c1].b=0;      
          }
          rm-=WIDTH/HEIGHT;   
    
       }
    }
    void output(pxl px[][WIDTH],FILE *fp) {
       int r,c;
       
       fprintf(fp,"P6\n%d %d %d\n", WIDTH, HEIGHT, 255); 
       
       for(r=0;r<HEIGHT;r++) {
          for(c=0;c<WIDTH;c++) {
             fprintf(fp, "%c%c%c",px[r][c].r,px[r][c].g,px[r][c].b);
          }
       }
       fclose(fp);
    }
    How do you compile that? I tried gcc triangle.c ; ./a.out > out.ppm gave me an error out.ppm not found...

    The way we compile PPM images is
    gcc *.c
    ./a.out > *.ppm (this is where you name it whatever you want.)
    display *.ppm

    This is for a class and I have classmates that frequent these forums, so I'll post my code tomorrow for a future reference for anyone. It's due midnight tonight.

    At this point I have it done, and it works, but I'm just curious how yours works.

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Don't redirect the output - the program makes it's own output file. Just display it. (In Windows you can call system(filename.ext), and if the ext has a program associated with it (in this case a view program [IrfanView], pops up and handles the actual display.)

    PPM Vectors-greentriangle-png

    The actual size of the pic is not known because the background is black in IrvanView, and I left the background in the ppm file black also, so they have no precise separation here.

  8. #8
    Registered User
    Join Date
    Jan 2013
    Posts
    106
    Nice

  9. #9
    Registered User
    Join Date
    Sep 2012
    Location
    Clemson, SC USA
    Posts
    19
    I'm using uBuntu instead of windows, that could be why it laughs at my './a.out' and calls me a retard...

  10. #10
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    The default output from the program IS out.ppm, so you could change that to "triangle.ppm" or some such.

    I like Ubuntu (although I have practiced imitating a cussing sailor's vocabulary with it a few times). I program on a Windows PC, however.

    The main difference between our programs is mine doesn't do the math yours does. Thank Gawd! :ROFL:

    It uses the A,B,&C x and y values so it only colors green pixels within the triangle. (not tested yet, but more or less).

    Thanks xArt.

  11. #11
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by Adak View Post
    The main difference between our programs is mine doesn't do the math yours does. Thank Gawd! :ROFL:
    But your program only works with triangles which have a rectangle between A and B and B must be right of A and C must be below A.
    [Edit]It doesn't work for the points in OP's post[/Edit]

    For a more general solution (i.e. no restrictions on the positions of A, B and C) you need the math (e.g. one of these two methods).

    Bye, Andreas
    Last edited by AndiPersti; 03-14-2013 at 12:21 PM.

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I found a way to work with area's, to test if a point was inside a triangle or not, so the triangle function became:

    Code:
    void triangles (pxl px[][WIDTH]) {
       int r,c,lox,hix,loy,hiy; 
       double areaABC,areaPTAB,areaPTBC,areaPTAC,areaPTotal;
    
       point A,B,C;       //where A,B,C are the corners of the triangle
       A.y=100;           
       A.x=400;           
       B.y=240;            
       B.x=600;           
       C.y=450;           
       C.x=525;           
                          
       lox=400;           
       hix=600;           
       loy=100;
       hiy=450;
       areaABC = abs((A.x*(B.y - C.y) + B.x*(C.y - A.y) + C.x*(A.y-B.y))/2.0);
    
       printf("areaABC: %.2f \n",areaABC); //getchar(); 
    
       for(r=hiy;r>=loy;r--) {             
          
          for(c=lox;c<=hix;c++) {
             areaPTAB= abs((A.x*(B.y-r) + B.x*(r-A.y) + c*(A.y-B.y))/2.0);
             areaPTBC= abs((B.x*(C.y-r) + C.x*(r-B.y) + c*(B.y-C.y))/2.0);
             areaPTAC= abs((A.x*(C.y-r) + C.x*(r-A.y) + c*(A.y-C.y))/2.0);
             areaPTotal=areaPTAB+areaPTBC+areaPTAC;
             //printf("areaPTAB: %.2f areaPTBC: %.2f  areaPTAC: %.2f\n",areaPTAB,areaPTBC,areaPTAC); 
             //printf("areaPTotal: %.2f\n",areaPTotal); //getchar();
             if(areaABC>areaPTotal-2.0 && areaABC<areaPTotal+2.0) { 
                px[r][c].r=0;
                px[r][c].g=255;
                px[r][c].b=0;      
             }
             
          }
       }
    }
    Which has a sloppy "fudge" factor necessary - I'm using some int's where I would need doubles in those expressions, apparently.

    Despite the arithmetic, it's not too slow.

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Ha! The bug was abs() -- the little devil!

    Code:
    //puts the pixels into the array px[][]
    void triangles (pxl px[][WIDTH]) {
       int r,c, lox,hix,loy,hiy; 
       double areaABC,areaPTAB,areaPTBC,areaPTAC,areaPTotal;
    
       point A,B,C;       //where A,B,C are the corners of the triangle
       A.y=100;           
       A.x=400;           
       B.y=240;            
       B.x=600;           
       C.y=450;           
       C.x=525;           
                          
       lox=400;           
       hix=600;           
       loy=100;
       hiy=450;
       areaABC = (A.x*(B.y - C.y) + B.x*(C.y - A.y) + C.x*(A.y-B.y))/2.0;
    
       printf("areaABC: %.2f \n",areaABC); //getchar(); 
    
       for(r=hiy;r>=loy;r--) {             
          
          for(c=lox;c<=hix;c++) {
             areaPTAB= (A.x*(B.y-r) + B.x*(r-A.y) + c*(A.y-B.y))/2.0;
             areaPTBC= (B.x*(C.y-r) + C.x*(r-B.y) + c*(B.y-C.y))/2.0;
             areaPTAC= (A.x*(C.y-r) + C.x*(r-A.y) + c*(A.y-C.y))/2.0;
    
             if(areaPTAB<0.000) areaPTAB*=-1;
             if(areaPTBC<0.000) areaPTBC*=-1;
             if(areaPTAC<0.000) areaPTAC*=-1;
    
             areaPTotal=areaPTAB+areaPTBC+areaPTAC;
             //printf("areaPTAB: %.2f areaPTBC: %.2f  areaPTAC: %.2f\n",areaPTAB,areaPTBC,areaPTAC); 
             //printf("areaPTotal: %.2f\n",areaPTotal); //getchar();
     
             if(areaABC==areaPTotal) {
                px[r][c].r=0;
                px[r][c].g=255;
                px[r][c].b=0;      
             }
             
          }
       }
    }

  14. #14
    Registered User
    Join Date
    Sep 2012
    Location
    Clemson, SC USA
    Posts
    19
    Okay so I'm doing this as a service to future people with problems coding a triangle in C.. Here is my full code for the program.

    I included a .h file for extra credit, I know it was useless in getting the triangle to print but it does make it a little easier to change the points around and see what happens.. There are two files, Shapes.c and Shapes.h

    Shapes.c:
    Code:
    /* ||__This is programming assignment 3__||
       ||__ Robert Harp CPSC 101 Section 1 __||
       ||__          **Shapes.c**          __||
       ||__********************************__||
       ||__        **Due 03.14.13**        __||
       ||__ This is a program that creates __||
       ||__   a PPM image containing an    __||
       ||__  circle and a purple triangle  __||
       ++====================================++ */
    
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #include<stdbool.h>
    #include "Shapes.h"
    
    void make_header(int, int);
    void make_image(int, int);
    void make_pixel(unsigned char, unsigned char, unsigned char);
    double area(int, int, int, int, int, int);
    bool is_inside(int, int, int, int, int, int, int, int);
    
    /*
     *
     */
    
    int main(void)
    {
        int height, width;
    
        height = 480;
        width = 640;
        
        make_header(width, height);
        make_image(width, height);
        fprintf(stderr, "creating an image with a width %d pixels by a height"
            " %d pixels\n", width, height);
    
    return (0);
    }
    
    /*
     * function to make a PPM header for the file
     */
    
    void make_header(int width, int height)
    {
        fprintf(stdout,"P6\n%d %d %d\n", width, height, 255);
    }
    
    /*
     * function to make the image and all of its shapes
     */
    
    void make_image(int width, int height)
    {
        int x, y; //values respective to each axis
    
        for(y = 1; y <= height; y++)
        {
            for(x = 1; x <= width; x++)
            { //if <circle>, else if <triangle>, else <background>
                if ((((x-CCX) * (x-CCX) + (y-CCY) * (y-CCY)) <= 5625))
                {    
                    make_pixel(255,125,1); //Orange circle
                }
                else
                {
                    if (is_inside(TAX, TAY, TBX, TBY, TCX, TCY, x, y))
                    {
                        make_pixel(148, 0, 212); // Purple triangle
                    }
                    else
                    {
                        make_pixel(0, 0, 0); //Black background
                    }
                }
            }
        }
    }
    
    /*
     * Function to print each individual pixel
     */
    
    void make_pixel(unsigned char r, unsigned char g, unsigned char b)
    {
        printf("%c%c%c", r, g, b);
    }
    
    /*
     * Function to find the area of each 
     */
    
    double area(int x1, int y1, int x2, int y2, int x3, int y3)
    {
        return abs((x1*(y2-y3) + x2*(y3-y1)+ x3*(y1-y2))/2.0);
    }
    
    /* 
     * A function to check whether point P(x, y) lies inside the triangle formed
     * by A(x1, y1), B(x2, y2) and C(x3, y3) 
     */
    
    bool is_inside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y)
    { 
        /* Calculate area of triangle ABC */
        double long A = area (x1, y1, x2, y2, x3, y3);
    
        /* Calculate area of triangle PBC */  
        double long A1 = area (x, y, x2, y2, x3, y3);
    
        /* Calculate area of triangle PAC */  
        double long A2 = area (x1, y1, x, y, x3, y3);
    
        /* Calculate area of triangle PAB */   
        double long A3 = area (x1, y1, x2, y2, x, y);
      
        /* Check if sum of A1, A2 and A3 is same as A */
    return (A >= A1 + A2 + A3);
    }
    /*
     * Coded by Robbo
     */

    And Shapes.h:
    Code:
    #define CCX 225
    #define CCY 175
    #define TAX 400
    #define TAY 100
    #define TBX 600
    #define TBY 240
    #define TCX 525
    #define TCY 450
    
    /*
     * To define my #define's
     * CCX, CCY - Circle Center X value, Y value, respectively
     * TAX, TAY - Triangle Point (A)'s X and Y values, respectively
     * TBX, TBY - Triangle Point (B)'s X and Y values, respectively
     * TCX, TCY - Triangle Point (C)'s X and Y values, respectively
     */
    You are welcome, world.

    Do note that in the last line of Shapes.c, the return value of "bool is_inside()" is >= to the sum of the areas. If you have it as ==, you will get a distorted triangle. <= doesn't print a triangle at all.

    So if you steal this from the geeksforgeeks.org page like I did, you HAVE to change the last line to >= from == to get a full triangle.

    Of course there are other ways to make a triangle, this is just an example to help with site traffic in the coming semesters of CPSC101 students at Clemson.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Vectors in vectors - pointers and iterators
    By fisherking in forum C++ Programming
    Replies: 8
    Last Post: 07-27-2010, 09:34 AM
  2. Vectors
    By naseerhaider in forum C++ Programming
    Replies: 11
    Last Post: 05-09-2008, 08:21 AM
  3. Vectors, Again
    By jrahhali in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 12-08-2005, 04:07 PM
  4. Vectors
    By Alastor in forum C Programming
    Replies: 9
    Last Post: 10-15-2005, 06:41 PM
  5. Vectors
    By Korn1699 in forum C++ Programming
    Replies: 5
    Last Post: 02-27-2004, 03:29 AM