#include "skeleton.h"

/* line primitives */
void setbox(line_ptr seg)
{
	int i,x,y;
	
	if((seg==NULL) || (seg->pts==NULL)) return;
	
	seg->box[0][0] = seg->pts->p[0][0];
	seg->box[0][1] = seg->pts->p[0][1];
	seg->box[1][0] = seg->pts->p[0][0];
	seg->box[1][1] = seg->pts->p[0][1];
	
	for(i=1;i<seg->number;i++)
	{
		x = seg->pts->p[i][0];
		y = seg->pts->p[i][1];
		
	        if(x<seg->box[0][0]) seg->box[0][0] = x;
        	if(x>seg->box[1][0]) seg->box[1][0] = x;
        	if(y<seg->box[0][1]) seg->box[0][1] = y;
        	if(y>seg->box[1][1]) seg->box[1][1] = y;
	}	
}

line_ptr addpoint(line_ptr seg,int x,int y)
{
    if(seg==NULL)
    {
        seg=(line_ptr)malloc(sizeof(struct line));
        seg->number = 1;
        seg->box[0][0] = x;
        seg->box[1][0] = x;
        seg->box[0][1] = y;
        seg->box[1][1] = y;
	seg->linec = 1;
	seg->fillc = 0;
        seg->pts=(struct pts *)malloc(sizeof(struct pts)*POINTS);
        seg->pts->p[0][0]=x;
        seg->pts->p[0][1]=y;
        seg->next = NULL;
    }
    else
    {
        if(x<seg->box[0][0]) seg->box[0][0] = x;
        if(x>seg->box[1][0]) seg->box[1][0] = x;
        if(y<seg->box[0][1]) seg->box[0][1] = y;
        if(y>seg->box[1][1]) seg->box[1][1] = y;

        if(seg->number%POINTS==0)
            seg->pts=(struct pts *)realloc((void *)seg->pts,
             sizeof(struct pts)*POINTS*(seg->number/POINTS+1),
	     sizeof(struct pts)*POINTS*(seg->number/POINTS));

        seg->pts->p[seg->number][0] = x;
        seg->pts->p[seg->number][1] = y;
        seg->number = seg->number + 1;
    }

    if(seg->number==1)			/* a single point is entered twice */
    {
        seg->pts->p[1][0]=x; 
        seg->pts->p[1][1]=y;
    }
    return(seg);
}

line_ptr appendpoint(line_ptr line,int x,int y)
{
    if(line==NULL) return(addpoint(NULL,x,y));

    while(line->next!=NULL)
        line=line->next;

    return(addpoint(line,x,y));
}

void insertpoint(line_ptr seg,int point,int x,int y)
{
    int xs,ys;

    if(seg==NULL) return;
    if(point>=seg->number) return((void)addpoint(seg,x,y));

    if(x<seg->box[0][0]) seg->box[0][0] = x;
    if(x>seg->box[1][0]) seg->box[1][0] = x;
    if(y<seg->box[0][1]) seg->box[0][1] = y;
    if(y>seg->box[1][1]) seg->box[1][1] = y;

    if(seg->number%POINTS==0)
        seg->pts=(struct pts *)realloc((void *)seg->pts,
         sizeof(struct pts)*POINTS*(seg->number/POINTS+1),
	 sizeof(struct pts)*POINTS*(seg->number/POINTS));

    for(;point<seg->number;point++)
    {
        xs = seg->pts->p[point][0];
        ys = seg->pts->p[point][1];
        seg->pts->p[point][0] = x;
        seg->pts->p[point][1] = y;
        x = xs;
        y = ys;
    }

    seg->pts->p[seg->number][0]=x;
    seg->pts->p[seg->number][1]=y;
    seg->number = seg->number + 1;
}

void deletepoint(line_ptr seg,int point)
{
    if(seg==NULL || point>=seg->number || seg->number==0) return;

    seg->number = seg->number-1;

    for(;point<seg->number;point++)
    {
        seg->pts->p[point][0] = seg->pts->p[point+1][0];
        seg->pts->p[point][1] = seg->pts->p[point+1][1];
    }

    if(seg->number%POINTS==0)
        if(seg->number!=0)
            seg->pts=(struct pts *)realloc((void *)seg->pts,
             sizeof(struct pts)*POINTS*(seg->number/POINTS),
	     sizeof(struct pts)*POINTS*(seg->number/POINTS+1));

    return;
}

void movepoint(line_ptr seg,int point,int x,int y)
{
    if(seg==NULL || point>=seg->number) return;

    seg->pts->p[point][0] = x;
    seg->pts->p[point][1] = y;

    if(x<seg->box[0][0]) seg->box[0][0] = x;
    if(x>seg->box[1][0]) seg->box[1][0] = x;
    if(y<seg->box[0][1]) seg->box[0][1] = y;
    if(y>seg->box[1][1]) seg->box[1][1] = y;

    return;
}

line_ptr copyline(line_ptr line)
{
    line_ptr newline,seg,last;

    newline = NULL;
    last = NULL;
    while(line!=NULL)
    {
        seg=(line_ptr)malloc(sizeof(struct line));
	memcpy((char *)seg,(char *)line,sizeof(struct line));
	if(seg->pts!=NULL)
	{
            seg->pts=(struct pts *)
	     malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
	    memcpy((char *)seg->pts,(char *)line->pts,
	     seg->number*sizeof(struct pts));
	}
        if(seg->number==1)
        {
		seg->pts->p[1][0] = seg->pts->p[0][0];
		seg->pts->p[1][1] = seg->pts->p[0][1];
        }
			
        if(newline==NULL)
            newline = seg;
        else
            last->next = seg;
        last = seg;
        line = line->next;
    }
    return(newline);
}

/*
line_ptr findpoint(line_ptr line,int x,int y,int *point)
{
    while(line!=NULL)
    {
        for(;*point<=line->number;(*point)++)
            if(x==line->pts->p[*point][0] && y==line->pts->p[*point][1])
                return(line);
        line = line->next;
        *point = 0;
    }
    return(NULL);
}
 */

/*
line_ptr findintersect(line_ptr line,int x,int y,int *point)
{
    int x1,y1,x2,y2;
    while(line!=NULL)
    {
        for(;*point<line->number-1;(*point)++)
        {
        x1 = line->pts->p[*point][0];
        y1 = line->pts->p[*point][1];
        x2 = line->pts->p[*point+1][0];
        y2 = line->pts->p[*point+1][1];

        if(x>=min(x1,x2) && x<=max(x1,x2) &&
           y>=min(y1,y2) && y<=max(y1,y2) &&
           abs((x1-x2)*(y-y1)-(x-x1)*(y1-y2))<
           min(abs(x1-x2),abs(y1-y2)) )
            return(line);
        }
        line = line->next;
        *point = 0;
    }
    return(NULL);
}
 */

line_ptr cutseg(line_ptr seg,int point)
{
    line_ptr newseg;

    if(point>=seg->number) return(NULL);

    newseg=(line_ptr)malloc(sizeof(struct line));
    memcpy((char *)newseg,(char *)seg,sizeof(struct line));
    newseg->next = NULL;

    newseg->number = seg->number-point;
    newseg->pts=(struct pts *)
     malloc(sizeof(struct pts)*POINTS*((newseg->number-1)/POINTS+1));
    memcpy((char *)newseg->pts,(char *)seg->pts->p[point],
     newseg->number*sizeof(struct pts));
    setbox(newseg);
    if(newseg->number==1)
    {
	newseg->pts->p[1][0] = seg->pts->p[0][0];
	newseg->pts->p[1][1] = seg->pts->p[0][1];
    }

    if(seg->number/POINTS != (point+1)/POINTS)
    	seg->pts=(struct pts *)realloc((void *)seg->pts,
    	 sizeof(struct pts)*POINTS*(point/POINTS+1),
	 sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
    seg->number = point + 1;
    setbox(seg);
    if(seg->number==1)
    {
	seg->pts->p[1][0] = seg->pts->p[0][0];
	seg->pts->p[1][1] = seg->pts->p[0][1];
    }

    return(newseg);
}

/*
line_ptr deleteseg(line_ptr seg)
{
    line_ptr next;
    if(seg==NULL) return(NULL);
    next = seg->next;
    free(seg->pts,sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
    free(seg,sizeof(struct line));
    return(next);
}
 */

/*
line_ptr cutline(line_ptr line,line_ptr seg)
{
    while(line!=NULL && line->next!=seg)
        line=line->next;
    if(line==NULL) return(NULL);
    line->next = NULL;
    return(seg);
}
 */
 
void deleteline(line_ptr line)
{
    line_ptr delete;

    while(line!=NULL)
    {
        delete = line;
        line = line->next;
        free(delete->pts,sizeof(struct pts)*POINTS*((delete->number-1)/POINTS+1));
        free(delete,sizeof(struct line));
    }
}

void appendline(line_ptr line,line_ptr append)
{
    if(line==NULL) return;
    while(line->next!=NULL)
        line=line->next;
    line->next = append;
}

/*
void scaleline(line_ptr line,int xfact,int yfact)
{
    int i;

    while(line!=NULL)
    {
        line->box[1][0] = (((line->box[1][0]-line->box[0][0])
         * xfact)>>8) + line->box[0][0];
        line->box[1][1] = (((line->box[1][1]-line->box[0][1])
         * yfact)>>8) + line->box[0][1];

        for(i=0;i<line->number;i++)
        {
            line->pts->p[i][0] = (((line->pts->p[i][0]-line->box[0][0])
             * xfact)>>8) + line->box[0][0];
            line->pts->p[i][1] = (((line->pts->p[i][1]-line->box[0][1])
             * yfact)>>8) + line->box[0][1];
        }
        line = line->next;
    }
}
 */
