//------------------------------------------------------------------- // hexagon.cpp // // This program tests a proposed algorithm for determining if a // point (x,y) lies inside a regular polygon centered at (0,0). // // programmer: ALLAN CRUSE // written on: 22 NOV 2003 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), write(), close() #include // for tcgetattr(), tcsetattr() #include // for mmap() #include // for iopl() #include // for cos(), sin() #define VRAM_BASE_ADDRESS 0xA0000000 #define VGA_MEMORY_LENGTH ( 4 << 20) #define PI (3.14159) #define MAXVERT 9 typedef float scalar_t; typedef struct { scalar_t x, y; } point_t; typedef struct { int numverts; point_t vert[ MAXVERT ]; } poly_t; int point_in_polygon( point_t p, poly_t poly ); unsigned char *vram = (unsigned char*)VRAM_BASE_ADDRESS; const int display_mode = 0x4101, hres = 640, vres = 480; void draw_rectangle( int x, int y, int h, int v, int color ) { int minx = x, miny = y, maxx = x+h-1, maxy = y+v-1; do { vram[ y*hres + x ] = color; ++x; } while ( x < maxx ); do { vram[ y*hres + x ] = color; ++y; } while ( y < maxy ); do { vram[ y*hres + x ] = color; --x; } while ( x > minx ); do { vram[ y*hres + x ] = color; --y; } while ( y > miny ); } int map_system_memory( int base, int size ) { int fd = open( "/dev/vram", O_RDWR ); if ( fd < 0 ) { perror( "/dev/vram" ); return -1; } int prot = PROT_READ | PROT_WRITE; int flag = MAP_FIXED | MAP_SHARED; void *mm = (void*)base; if ( mmap( mm, size, prot, flag, fd, 0 ) == MAP_FAILED ) { perror( "mmap" ); return -1; } close( fd ); } int main( int argc, char **argv ) { if ( iopl( 3 ) ) { perror( "iopl" ); exit(1); } system( "/sbin/insmod vram.o" ); map_system_memory( VRAM_BASE_ADDRESS, VGA_MEMORY_LENGTH ); struct termios otty; tcgetattr( 0, &otty ); struct termios tty = otty; tty.c_lflag &= ~( ICANON | ECHO | ISIG ); tty.c_cc[ VMIN ] = 1; tty.c_cc[ VTIME ] = 0; tcsetattr( 0, TCSAFLUSH, &tty ); char command[ 40 ]; sprintf( command, " clear ; mode3 %d ", display_mode ); system( command ); int color = 15; draw_rectangle( 0, 0, hres, vres, color ); getchar(); // construct a regular polygon with six sides int sides = 6; poly_t hexagon; scalar_t theta = 2*PI / sides; hexagon.numverts = sides; for (int i = 0; i <= sides; i++) { hexagon.vert[i].x = cos( i*theta ); hexagon.vert[i].y = sin( i*theta ); } // draw the regular polygon scalar_t transX = hres/2, transY = vres/2; scalar_t scaleX = 0.01, scaleY = -0.01; point_t origin; origin.x = transX, origin.y = transY; for (int v = 0; v < vres; v++) for (int h = 0; h < hres; h++) { point_t p; p.x = scaleX * ( h - transX ); p.y = scaleY * ( v - transY ); if ( point_in_polygon( p, hexagon ) ) vram[ v*hres + h ] = 2; } getchar(); system( " mode3 3 " ); tcsetattr( 0, TCSAFLUSH, &otty ); } void vector_fromto( point_t a, point_t b, point_t &c ) { c.x = b.x - a.x; c.y = b.y - a.y; } scalar_t det( point_t a, point_t b ) { return a.x * b.y - b.x * a.y; } int point_in_triangle( point_t o, point_t a, point_t b, point_t p ) { // returns 'true' if point p belongs to triangle oab point_t vector_oa, vector_ob, vector_op; vector_fromto( o, a, vector_oa ); vector_fromto( o, b, vector_ob ); vector_fromto( o, p, vector_op ); // verify that o, a, b are not collinear scalar_t den = det( vector_oa, vector_ob ); if ( den == 0.0 ) return 0; // compute coefficients: vector_op = c1*vector_oa + c2*vector_ob scalar_t c1 = det( vector_op, vector_ob )/ den; scalar_t c2 = det( vector_oa, vector_op )/ den; if (( c1 < 0.0 )||( c2 < 0.0 )) return 0; if ( c1 + c2 > 1.0 ) return 0; return 1; } int point_in_polygon( point_t p, poly_t poly ) { point_t o = poly.vert[0]; for (int i = 1; i < poly.numverts; i++) { point_t a = poly.vert[i]; point_t b = poly.vert[i+1]; if ( point_in_triangle( o, a, b, p ) ) return 1; } return 0; }