Reputation: 9
How can I find the area of a shape (triangle, quadrilateral and pentagon) drawn with BGI, whose coordinate points are given in C programming, by adding the unit squares inside the quadrilateral and through which the side lines pass?
I drew it in BGI with the coordinate points given in the figure, but I need to find its area by adding the unit squares within which the edge lines pass. I need this for a project.
void dortgen_alani(int sekil_ciz[][2])
{
int x[4], y[4];
for (int i = 0; i < 4; i++) {
x[i] = sekil_ciz[i][0];
y[i] = sekil_ciz[i][1];
putpixel(x[i], y[i], WHITE); // Noktaları işaretle
}
int toplamBirimKare = 0;
int minX = x[0], minY = y[0];
int maxX = x[0], maxY = y[0];
for (int i = 1; i < 4; i++) {
if (x[i] < minX) minX = x[i];
if (x[i] > maxX) maxX = x[i];
if (y[i] < minY) minY = y[i];
if (y[i] > maxY) maxY = y[i];
}
for (int i = minX; i < maxX; i++) {
for (int j = minY; j < maxY; j++) {
int icindeMi = 1;
for (int k = 0; k < 4; k++) {
int x1 = x[k];
int y1 = y[k];
int x2 = x[(k + 1) % 4];
int y2 = y[(k + 1) % 4];
int xMin = x1 < x2 ? x1 : x2;
int xMax = x1 > x2 ? x1 : x2;
int yMin = y1 < y2 ? y1 : y2;
int yMax = y1 > y2 ? y1 : y2;
if (i >= xMin && i < xMax && j >= yMin && j < yMax) {
if ((i - x1) * (y2 - y1) - (j - y1) * (x2 - x1) < 0) {
icindeMi = 0;
break;
}
}
}
if (icindeMi) {
putpixel(i, j, BLUE);
toplamBirimKare++;
}
}
}
printf("Dortgenin alani (birim karelerle): %d birim kare\n", toplamBirimKare / 100);
}
This code does not calculate correctly.
Upvotes: 0
Views: 263
Reputation: 1394
Find the area of a screen image/object by reading screen pixels of the object.
This is a solution for finding the area of specific geometric objects drawn on the screen in graphics mode. It reads screen pixels to discern exact location and general nature/shape of the object, and ultimately its area.
UPDATED VERSION:
Tested objects: triangle, rectangle, quadrilateral, pentagon, circle, and more. Test bed showing proof of concept with runnable code and numerous test cases is here.
Logic: Assume all the unpainted screen pixels are zero (ie: color black). We traverse the screen left to right and top to bottom examining every pixel to locate the image object and its interior. Expectation is that the image only exists as an outline (not filled), and is drawn with some non-zero pixel color.
From there, we use a common floodfill algorithm to fill the interior of the object with a specified color. At last, we analyze the screen summing all the painted pixels: this is the object's area.
This code is designed for Turbo C -- per OP's reference: "drawn in "BGI" (Borland Graphics Interface). However, the logic of the code is portable, so we only need to replace putpixel() and getpixel() with the applicable API to work on any platform.
putpixel() and getpixel() are both simulated -- using a virtual screen buffer -- in this example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TARGET_COLOR 0
#define FLOOD_COLOR 2
#define EDGE_COLOR 1
#define SCREEN_W 40
#define SCREEN_H 20
unsigned short screen[SCREEN_H][SCREEN_W];
/* This virtual screen has a 10x15 rectangle "drawn" in it.
** -- Do you see it? -- rectangle area should be 150.
*/
#define RECT_AREA 150
unsigned short screen_rect[SCREEN_H][SCREEN_W] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
/* Test bed versions of Turbo C's getpixel() and putpixel()
* Both use screen array as a virtual screen */
unsigned getpixel(int x, int y)
{
return screen[y][x];
}
void putpixel(int x, int y, int color)
{
screen[y][x] = color;
}
/*---------------------------------------------------------------------
disp_matrix() -- Helper function: display the image/matrix/table.
*---------------------------------------------------------------------*/
void disp_matrix(int wdth, int hgt)
{
int xxx,yyy;
for (yyy = 0; yyy < hgt; yyy++)
{
for (xxx = 0; xxx < wdth; xxx++)
{
int ch;
switch(getpixel(xxx,yyy))
{
case 0:
ch = ' ';
break;
case 1:
ch = '1';
break;
case FLOOD_COLOR:
ch = '2';
break;
default:
ch = getpixel(xxx,yyy)+'0';
break;
}
putchar(ch);
}
putchar('\n');
}
}
/*------------------------------------------------------------------
get_image_area()
Use after floodfill complete.
Count all non-zero pixels and return count.
*-----------------------------------------------------------------*/
int get_image_area(int wdth, int hgt)
{
int xxx,yyy,sum=0;
for (yyy = 0; yyy < hgt; yyy++)
{
for (xxx = 0; xxx < wdth; xxx++)
{
if(getpixel(xxx,yyy) != 0)
sum++;
}
}
return sum;
}
/*-------------------------------------------------------------------------------------
find_image_interior()
Given a rendered, non-filled screen image, span screen top to bottom.
For each screen pixel, scan north, south, east and west.
If an edge is found in each and every direction, return 1 (success) and provide
interior coordinate. Else return 0 (fail).
*-------------------------------------------------------------------------------------*/
int find_image_interior(int *px, int *py, int wdth, int hgt)
{
int xxx,yyy,x,y;
int east = 0, west = 0, north = 0, south = 0;
for(y=0; y<hgt; y++)
{
for(x=0; x<wdth; x++)
{
east = west = north = south = 0;
xxx = x,yyy =y;
while(!west && --xxx > -1 )
{
if( getpixel(xxx,yyy) == EDGE_COLOR)
{
west = 1; /* West search was a success. Market*/
}
}
xxx = x,yyy =y;
while(!east && ++xxx < wdth )
{
if( getpixel(xxx,yyy) == EDGE_COLOR)
{
east = 1; /* East search was a success. Market*/
}
}
xxx = x,yyy =y;
while(!north && --yyy > -1 )
{
if( getpixel(xxx,yyy) == EDGE_COLOR)
{
north = 1; /* North search was a success. Market*/
}
}
xxx = x,yyy =y;
while(!south && ++yyy < hgt)
{
if( getpixel(xxx,yyy) == EDGE_COLOR)
{
south = 1; /* North search was a success. Market*/
}
}
if((east+west+north+south) == 4)
{
printf("Image interior found at %d x %d\n", x, y);
*px = x;
*py = y;
return 1;
}
}
}
return 0;
}
/*-------------------------------------------------------------------------------
flood_fill()
The basic floodfill algo/code is thanks to user Malcolm McLean [here](https://stackoverflow.com/a/44086081/3130521)
and looks like this:
void floodfill(int **tab, int u, int v, int i int j)
{
if(tab[i][j] == u)
{
tab[i][j[ = v;
floodfill(tab, u, v, i+1, ,j);
floodfill(tab, u, v, i-1, j);
floodfill(tab, u, v, i, j -1);
floodfill(tab, u, v, i, j +1);
}
}
Adapted for this app to stay in screen bounds and image interior.
Returns: sum of updated pixels. (Unused)
*---------------------------------------------------------------------------------*/
int flood_fill(int start_x, int start_y, int wdth, int hgt)
{
int sum = 0;
/* Bounds check */
if (start_x > wdth-1 || start_x < 0 || start_y > hgt-1 || start_y < 0)
return sum;
/* If pixel not proper target color, exit */
if (getpixel(start_x,start_y) != TARGET_COLOR)
return sum;
/* Mark the image pixel with the floodfill char */
putpixel(start_x,start_y,FLOOD_COLOR);
sum = 1;
/* Basic floodfill algo -- recursive: check pixel above, below, left and rgt.
Added: what directions are legal? We want to stay within our image boundaries.
Examine Up, Down, Left, Right pixels for image edge.
If edge not found, proceed with recursive call:
*/
if(getpixel(start_x+1, start_y) != EDGE_COLOR)
sum += flood_fill(start_x+1, start_y, wdth, hgt);
if(getpixel(start_x-1,start_y) != EDGE_COLOR)
sum += flood_fill(start_x-1, start_y, wdth, hgt);
if(getpixel(start_x,start_y+1) != EDGE_COLOR)
sum += flood_fill(start_x, start_y+1, wdth, hgt);
if(getpixel(start_x, start_y-1) != EDGE_COLOR)
sum += flood_fill(start_x, start_y-1, wdth, hgt);
return sum;
}
int main()
{
int wdth = SCREEN_W, hgt = SCREEN_H;
int xxx, yyy, area;
/* Setup each test case by copying the image data to the virtual screen buffer*/
memcpy(screen, screen_rect, sizeof(screen));
disp_matrix(wdth, hgt); /* Display before floodfill() */
/* Normally in image floodfill, a user will use a pointing device to instruct the app
* where to begin the floodfil1. We don't have that luxury; we search: */
if(!find_image_interior(&xxx,&yyy, wdth, hgt) )
{
printf("Couldn't find image interior!\n");
return 0;
}
flood_fill(xxx, yyy, wdth, hgt); /* Do the floodfill beginning with coords provided by find */
area = get_image_area(wdth, hgt); /* Finally get the sum of all non-zero, painted pixels */
disp_matrix(wdth, hgt); /* Display after floodfill() */
/* Tell stats/image area */
printf("Rectangle area should be: %d. Computed area is: %d\n", RECT_AREA, area);
return 0;
}
Output:
1111111111
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1111111111
Image interior found at 16 x 2
1111111111
1222222221
1222222221
1222222221
1222222221
1222222221
1222222221
1222222221
1222222221
1222222221
1222222221
1222222221
1222222221
1222222221
1111111111
Rectangle area should be: 150. Computed area is: 150
Upvotes: 1