
/****************************************************************************
 *
 * MODULE:       r.colors
 *
 * AUTHOR(S):    Michael Shapiro - CERL
 *               David Johnson
 *
 * PURPOSE:      Allows creation and/or modification of the color table 
 *               for a raster map layer.
 *
 * COPYRIGHT:    (C) 2006 by the GRASS Development Team
 *
 *               This program is free software under the GNU General Public
 *               License (>=v2). Read the file COPYING that comes with GRASS
 *               for details.
 *
 ***************************************************************************/

#include <math.h>
#include <stdlib.h>
#include "local_proto.h"

int get_stats(struct maps_info *input_maps, struct Cell_stats *statf)
{
    CELL *cell;
    int row, nrows, ncols;
    int fd;
    int i;

    Rast_init_cell_stats(statf);

    for (i = 0; i < input_maps->num; i++) {
	fd = Rast_open_old(input_maps->names[i], input_maps->mapsets[i]);

	cell = Rast_allocate_c_buf();
	nrows = Rast_window_rows();
	ncols = Rast_window_cols();

	G_verbose_message(_("(%i/%i) Reading raster map <%s>..."),
			i + 1, input_maps->num,
			G_fully_qualified_name(input_maps->names[i], input_maps->mapsets[i]));

	for (row = 0; row < nrows; row++) {
	    G_percent(row, nrows, 2);
	    Rast_get_c_row(fd, cell, row);
	    Rast_update_cell_stats(cell, ncols, statf);
	}
	G_percent(nrows, nrows, 2);
	Rast_close(fd);
	G_free(cell);
    }

    return 1;
}

void get_fp_stats(struct maps_info *input_maps,
        struct FP_stats *statf,
        DCELL min, DCELL max, int geometric, int geom_abs, int type)
{
    DCELL *dcell = NULL;
    int row, col, depth, nrows, ncols, ndepths = 1;
    int fd;
    int i;
    char *name;
    char *mapset;
    RASTER3D_Map *map3d = NULL;

    statf->geometric = geometric;
    statf->geom_abs = geom_abs;
    statf->flip = 0;

    if (statf->geometric) {
	if (min * max < 0)
	    G_fatal_error(_("Unable to use logarithmic scaling if range includes zero"));

	if (min < 0) {
	    statf->flip = 1;
	    min = -min;
	    max = -max;
	}
	min = log(min);
	max = log(max);
    }

    if (statf->geom_abs) {
	double a = log(fabs(min) + 1);
	double b = log(fabs(max) + 1);
	int has_zero = min * max < 0;

	min = a < b ? a : b;
	max = a > b ? a : b;
	if (has_zero)
	    min = 0;
    }

    statf->count = 1000;
    statf->min = min;
    statf->max = max;
    statf->stats = G_calloc(statf->count + 1, sizeof (unsigned long));
    statf->total = 0;

    /* Loop over all input maps */
    for(i = 0; i < input_maps->num; i++) {
	name = input_maps->names[i];
	mapset = input_maps->mapsets[i];

	fd = -1;
	if (type == RASTER_TYPE) {
	    fd = Rast_open_old(name, mapset);
	    dcell = Rast_allocate_d_buf();
	    nrows = Rast_window_rows();
	    ncols = Rast_window_cols();
	}
	else {
	    /* Initiate the default settings */
	    Rast3d_init_defaults();

	    map3d = Rast3d_open_cell_old(name, mapset, RASTER3D_DEFAULT_WINDOW,
			    RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);

	    if (map3d == NULL)
		Rast3d_fatal_error(_("Error opening 3d raster map"));

	    nrows = map3d->window.rows;
	    ncols = map3d->window.cols;
	    ndepths = map3d->window.depths;
	}

	G_verbose_message(_("(%i/%i) Reading map <%s>..."), i, input_maps->num,
			G_fully_qualified_name(name, mapset));

	for (depth = 0; depth < ndepths; depth++) {
	    for (row = 0; row < nrows; row++) {
		G_percent(row, nrows, 2);

		if (type == RASTER_TYPE)
		    Rast_get_d_row(fd, dcell, row);

		for (col = 0; col < ncols; col++) {
		    DCELL x;
		    int j;

		    if (type == RASTER_TYPE)
			x = dcell[col];
		    else
			x = Rast3d_get_double(map3d, col, row, depth);

		    if (Rast_is_d_null_value(&x))
			continue;

		    if (statf->flip)
			x = -x;
		    if (statf->geometric)
			x = log(x);
		    if (statf->geom_abs)
			x = log(fabs(x) + 1);

		    j = (int) floor(statf->count * (x - statf->min) / (statf->max - statf->min));
		    statf->stats[j]++;
		    statf->total++;
		}
	    }
	}

	G_percent(nrows, nrows, 2);

	if (type == RASTER_TYPE) {
	    Rast_close(fd);
	if(dcell)
	    G_free(dcell);
	}
	else {
	    Rast3d_close(map3d);
	    map3d = NULL;
	}
    }
}
