

#include <stdio.h>

#include <grass/gstypes.h>
#include "gsget.h"
#include "rowcol.h"


#define FRINGE_FORE 0x000000
#define FRINGE_BACK 0xAAAAAA
#define FRINGE_WIDTH 2

/* Normals */
float Nnorth[] = { 0.0, 0.8, 0.6 };
float Nsouth[] = { 0.0, -0.8, 0.6 };
float Neast[] = { 0.8, 0.0, 0.6 };
float Nwest[] = { -0.8, 0.0, 0.6 };
float Ntop[] = { 0.0, 0.0, 1.0 };
float Nbottom[] = { 0.0, 0.0, -1.0 };

void
gsd_display_fringe (geosurf * surf, int where[4])
{

	/* TODO -- add elevation for bottom
	 *      -- add color option
	 *      -- add ruler grid lines
	 */

    float bot, xres, yres;   /* world size of view cell */
    int ycnt, xcnt;    /* number of view cells across */
    float xmax, ymax;

    xres =  surf->x_mod * surf->xres;
    yres =  surf->y_mod * surf->yres;

    xcnt = VCOLS(surf);
    ycnt = VROWS(surf);
    
    xmax = surf->xmax;
    ymax = surf->ymax;
    
    bot = surf->zmin - ((surf->zrange/4.) * surf->z_exag);
    
    gsd_linewidth(FRINGE_WIDTH);
    gsd_colormode(CM_COLOR);
    
    /* North fringe */
    if (where[0] || where[1]) {
    glNormal3fv(Nnorth);
    gsd_color_func(FRINGE_BACK);
    gsd_zwritemask(0x0);
    gsd_fringe_horiz_poly (bot, surf, 0, 0);
    gsd_color_func(FRINGE_FORE); /* WHITE */
    gsd_fringe_horiz_line (bot, surf, 0, 0);
    gsd_zwritemask(0xffffffff);
 /*   wmpack (0); ??? glColorMask */
    gsd_color_func(FRINGE_BACK);
    gsd_fringe_horiz_poly (bot, surf, 0, 0);
    }
    
    /* South fringe */
    if (where[2] || where[3]) {
    glNormal3fv(Nsouth);
    gsd_color_func(FRINGE_BACK);
    gsd_zwritemask(0x0); 
    gsd_fringe_horiz_poly (bot, surf, ycnt-2, 1);
    gsd_color_func(FRINGE_FORE); /* WHITE */
    gsd_fringe_horiz_line (bot, surf, ycnt-2, 1);
    gsd_zwritemask(0xffffffff); 
 /*   wmpack (0); ??? glColorMask */
    gsd_color_func(FRINGE_BACK);
    gsd_fringe_horiz_poly (bot, surf, ycnt-2, 1);
    }
    
    /* West fringe */
    if (where[0] || where[2]) {
    glNormal3fv(Nwest);
    gsd_color_func(FRINGE_BACK);
    gsd_zwritemask(0x0); 
    gsd_fringe_vert_poly (bot, surf, 0, 0);
    gsd_color_func(FRINGE_FORE);
    gsd_fringe_vert_line (bot, surf, 0, 0);
    gsd_zwritemask(0xffffffff); 
    gsd_color_func(FRINGE_BACK);
    gsd_fringe_vert_poly (bot, surf, 0, 0);
    }
        
    /* East fringe */
    if (where[1] || where[3]) {
    glNormal3fv(Neast);
    gsd_color_func(FRINGE_BACK);
    gsd_zwritemask(0x0); 
    gsd_fringe_vert_poly (bot, surf, xcnt-2, 1);
    gsd_color_func(FRINGE_FORE); 
    gsd_fringe_vert_line (bot, surf, xcnt-2, 1);
    gsd_zwritemask(0xffffffff); 
    gsd_color_func(FRINGE_BACK);
    gsd_fringe_vert_poly (bot, surf, xcnt-2, 1);
    }

return;
}

void
gsd_fringe_horiz_poly (float bot, geosurf * surf, int row, int side)
{

int col;
int cnt;
float pt[4];
typbuff *buff;
long offset;
int xcnt, ycnt;

GS_set_draw(GSD_FRONT);
gsd_pushmatrix();
gsd_do_scale(1);
gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans);

gsd_bgnpolygon();

buff = gs_get_att_typbuff(surf, ATT_TOPO, 0);
xcnt = VCOLS(surf);

col = 0;
/* floor left */
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - ((row+side)*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

offset = (row*surf->y_mod*surf->cols) + (col*surf->x_mod);
GET_MAPATT(buff, offset, pt[Z]);
pt[Z] = pt[Z] * surf->z_exag;
gsd_vert_func(pt);

cnt = 1;
for (col = 0; col < xcnt-1; col++) 
{
	/* bottom right */
	pt[X] = col * (surf->x_mod *  surf->xres) ;
	pt[Y] = ((surf->rows - 1) * surf->yres) - ((row+side)*(surf->y_mod*surf->yres));
	offset = (row*surf->y_mod*surf->cols) + (col*surf->x_mod);
	GET_MAPATT(buff, offset, pt[Z]);
	pt[Z] = pt[Z] * surf->z_exag;
	gsd_vert_func(pt);
	cnt++;
}

col--;
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - ((row+side)*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

gsd_endpolygon();

GS_done_draw();
gsd_popmatrix();
gsd_flush();
    
return;
}


void
gsd_fringe_horiz_line (float bot, geosurf * surf, int row, int side)
{
int col;
int cnt;
float pt[4];
typbuff *buff;
long offset;
int xcnt, ycnt;

GS_set_draw(GSD_FRONT);
gsd_pushmatrix();
gsd_do_scale(1);
gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans);


buff = gs_get_att_typbuff(surf, ATT_TOPO, 0);
xcnt = VCOLS(surf);
gsd_bgnline();

col = 0;
/* floor left */
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - ((row+side)*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);


offset = (row*surf->y_mod*surf->cols) + (col*surf->x_mod) ;
GET_MAPATT(buff, offset, pt[Z]);
pt[Z] = pt[Z] * surf->z_exag;
gsd_vert_func(pt);

cnt = 1;
for (col = 0; col < xcnt-1; col++) 
{
	/* bottom right */
	pt[X] = col * (surf->x_mod *  surf->xres) ;
	pt[Y] = ((surf->rows - 1) * surf->yres) - ((row+side)*(surf->y_mod*surf->yres));
	offset = (row*surf->y_mod*surf->cols) + (col*surf->x_mod);
	GET_MAPATT(buff, offset, pt[Z]);
	pt[Z] = pt[Z] * surf->z_exag;
	gsd_vert_func(pt);
	cnt++;
}

col--;
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - ((row+side)*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

col = 0;
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - ((row+side)*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

gsd_endline();

    GS_done_draw();
    gsd_popmatrix();
    gsd_flush();
    
return;
}


void
gsd_fringe_vert_poly (float bot, geosurf * surf, int col, int side)
{

int row;
int cnt;
float pt[4];
typbuff *buff;
long offset;
int xcnt, ycnt;

GS_set_draw(GSD_FRONT);
gsd_pushmatrix();
gsd_do_scale(1);
gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans);

gsd_bgnpolygon();

buff = gs_get_att_typbuff(surf, ATT_TOPO, 0);
ycnt = VROWS(surf);

row = 0;
/* floor left */
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - (row*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

offset = (row*surf->y_mod*surf->cols) + (col*surf->x_mod);
GET_MAPATT(buff, offset, pt[Z]);
pt[Z] = pt[Z] * surf->z_exag;
gsd_vert_func(pt);

cnt = 1;
for (row = 0; row < ycnt-1; row++) 
{
	/* bottom right */
	pt[X] = col * (surf->x_mod *  surf->xres) ;
	pt[Y] = ((surf->rows - 1) * surf->yres) - (row*(surf->y_mod*surf->yres));
	offset = (row*surf->y_mod*surf->cols) + (col*surf->x_mod);
	GET_MAPATT(buff, offset, pt[Z]);
	pt[Z] = pt[Z] * surf->z_exag;
	gsd_vert_func(pt);
	cnt++;
}

row--;
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - (row*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

gsd_endpolygon();

GS_done_draw();
gsd_popmatrix();
gsd_flush();
    
return;
}


void
gsd_fringe_vert_line (float bot, geosurf * surf, int col, int side)
{
int row;
int cnt;
float pt[4];
typbuff *buff;
long offset;
int xcnt, ycnt;

GS_set_draw(GSD_FRONT);
gsd_pushmatrix();
gsd_do_scale(1);
gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans);


buff = gs_get_att_typbuff(surf, ATT_TOPO, 0);
ycnt = VROWS(surf);
gsd_bgnline();

row = 0;
/* floor left */
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - (row*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

offset = (row*surf->y_mod*surf->cols) + (col*surf->x_mod);
GET_MAPATT(buff, offset, pt[Z]);
pt[Z] = pt[Z] * surf->z_exag;
gsd_vert_func(pt);

cnt = 1;
for (row = 0; row < ycnt-1; row++) 
{
	/* bottom right */
	pt[X] = col * (surf->x_mod *  surf->xres) ;
	pt[Y] = ((surf->rows - 1) * surf->yres) - (row*(surf->y_mod*surf->yres));
	offset = (row*surf->y_mod*surf->cols) + (col*surf->x_mod);
	GET_MAPATT(buff, offset, pt[Z]);
	pt[Z] = pt[Z] * surf->z_exag;
	gsd_vert_func(pt);
	cnt++;
}

row--;
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - (row*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

row = 0;
pt[X] = col * (surf->x_mod *  surf->xres) ;
pt[Y] = ((surf->rows - 1) * surf->yres) - (row*(surf->y_mod*surf->yres));
pt[Z] = bot;
gsd_vert_func(pt);

gsd_endline();

    GS_done_draw();
    gsd_popmatrix();
    gsd_flush();
    
return;
}


















void
gsd_fringe_horiz_line2 (float bot, geosurf * surf, int row, int side)
{
int col;
int cnt;
float pt[4];
typbuff *buff;
long offset;
int xcnt, ycnt;

    GS_set_draw(GSD_FRONT);
    gsd_pushmatrix();
    gsd_do_scale(1);
    gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans);


buff = gs_get_att_typbuff(surf, ATT_TOPO, 0);
xcnt = VCOLS(surf);
gsd_bgnline();

col = 0;
/* floor left */
pt[X] = surf->xmin + (col*(surf->x_mod * surf->xres)) ;
pt[Y] = surf->ymax - ((row + side)*(surf->y_mod * surf->yres)) ;
pt[Z] = bot;
gsd_vert_func(pt);

offset = 0;
GET_MAPATT(buff, offset, pt[Z]);
pt[Z] = pt[Z] * surf->z_exag;
gsd_vert_func(pt);

cnt = 1;
for (col = 0; col < xcnt-1; col++) 
{
	/* bottom right */
	pt[X] = surf->xmin + (col*(surf->x_mod * surf->xres)) ;
	pt[Y] = surf->ymax - ((row + side)*(surf->y_mod * surf->yres)) ;
	offset = col * surf->x_mod;
	GET_MAPATT(buff, offset, pt[Z]);
	pt[Z] = pt[Z] * surf->z_exag;
	gsd_vert_func(pt);
	cnt++;
}

col--;
pt[X] = surf->xmin + (col*(surf->x_mod * surf->xres)) ;
pt[Y] = surf->ymax - ((row + side)*(surf->y_mod * surf->yres)) ;
pt[Z] = bot;
gsd_vert_func(pt);

gsd_endline();

    GS_done_draw();
    gsd_popmatrix();
    gsd_flush();
    
return;
}


