libmonochrome/src/ML_filled_polygon.c

92 lines
2.4 KiB
C

/* ************************************************************************** */
/* */
/* ML_filled_polygon.c */
/* | Project : libmonochrome */
/* */
/* By: Pierre "PierrotLL" Le Gall <legallpierre89@gmail.com> */
/* Last updated: 2011/11/22 */
/* */
/* ************************************************************************** */
#include <monochrome/internals.h>
static int ML_filled_polygon_quicksord_partition(int *t, int p, int r)
{
int i, j, x, tmp;
j = p - 1;
x = t[r];
for(i=p ; i<r ; i++)
{
if(x > t[i])
{
j++;
tmp = t[j];
t[j] = t[i];
t[i] = tmp;
}
}
t[r] = t[j+1];
t[j+1] = x;
return j + 1;
}
static void ML_filled_polygon_quicksord(int* t, int p, int r)
{
int q;
if(p < r)
{
q = ML_filled_polygon_quicksord_partition(t, p, r);
ML_filled_polygon_quicksord(t, p, q-1);
ML_filled_polygon_quicksord(t, q+1, r);
}
}
void ML_filled_polygon(const int *x, const int *y, int nb_vertices, ML_Color color)
{
int i, j, dx, dy, ymin, ymax;
int *cut_in_line, nb_cut;
if(nb_vertices < 3) return;
cut_in_line = malloc(nb_vertices*sizeof(int));
if(!cut_in_line) return;
ymin = ymax = y[0];
for(i=1 ; i<nb_vertices ; i++)
{
if(y[i] < ymin) ymin = y[i];
if(y[i] > ymax) ymax = y[i];
}
for(i=ymin ; i<=ymax ; i++)
{
nb_cut = 0;
for(j=0 ; j<nb_vertices ; j++)
{
if((y[j]<=i && y[(j+1)%nb_vertices]>=i) || (y[j]>=i && y[(j+1)%nb_vertices]<=i))
{
dy = abs(y[j]-y[(j+1)%nb_vertices]);
if(dy)
{
dx = x[(j+1)%nb_vertices]-x[j];
cut_in_line[nb_cut] = x[j] + rnd(abs(i-y[j]+sgn(i-y[j])/2)*dx/dy);
nb_cut++;
}
}
}
ML_filled_polygon_quicksord(cut_in_line, 0, nb_cut-1);
j = 0;
while(j<nb_cut-2 && cut_in_line[j]==cut_in_line[j+1]) j++;
while(j < nb_cut)
{
if(j == nb_cut-1) ML_horizontal_line(i, cut_in_line[j-1]+1, cut_in_line[j], color);
else
{
dx = 1;
while(j+dx<nb_cut-1 && cut_in_line[j+dx]==cut_in_line[j+dx+1]) dx++;
ML_horizontal_line(i, cut_in_line[j], cut_in_line[j+dx], color);
j += dx;
}
j++;
}
}
free(cut_in_line);
}