[GRASS-SVN] r39943 - grass-addons/grass7/raster/r.clump2

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Dec 8 04:57:20 EST 2009


Author: mmetz
Date: 2009-12-08 04:57:20 -0500 (Tue, 08 Dec 2009)
New Revision: 39943

Added:
   grass-addons/grass7/raster/r.clump2/Makefile
   grass-addons/grass7/raster/r.clump2/flag.c
   grass-addons/grass7/raster/r.clump2/flag.h
   grass-addons/grass7/raster/r.clump2/local_proto.h
   grass-addons/grass7/raster/r.clump2/main.c
   grass-addons/grass7/raster/r.clump2/pq.c
   grass-addons/grass7/raster/r.clump2/r.clump2.html
   grass-addons/grass7/raster/r.clump2/ramseg.c
   grass-addons/grass7/raster/r.clump2/ramseg.h
Log:
adding r.clump2

Added: grass-addons/grass7/raster/r.clump2/Makefile
===================================================================
--- grass-addons/grass7/raster/r.clump2/Makefile	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/Makefile	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.clump2
+
+LIBES = $(RASTERLIB) $(GISLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/raster/r.clump2/flag.c
===================================================================
--- grass-addons/grass7/raster/r.clump2/flag.c	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/flag.c	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,68 @@
+#include <grass/gis.h>
+#include "flag.h"
+
+FLAG *flag_create(int nrows, int ncols)
+{
+    unsigned char *temp;
+    FLAG *new_flag;
+    register int i;
+
+    new_flag = (FLAG *) G_malloc(sizeof(FLAG));
+    new_flag->nrows = nrows;
+    new_flag->ncols = ncols;
+    new_flag->leng = (ncols + 7) / 8;
+    new_flag->array =
+	(unsigned char **)G_malloc(nrows * sizeof(unsigned char *));
+
+    temp =
+	(unsigned char *)G_malloc(nrows * new_flag->leng *
+				  sizeof(unsigned char));
+
+    for (i = 0; i < nrows; i++) {
+	new_flag->array[i] = temp;
+	temp += new_flag->leng;
+    }
+
+    return (new_flag);
+}
+
+int flag_destroy(FLAG * flags)
+{
+    G_free(flags->array[0]);
+    G_free(flags->array);
+    G_free(flags);
+
+    return 0;
+}
+
+int flag_set(FLAG * flags, int row, int col)
+{
+    flags->array[row][col >> 3] |= (1 << (col & 7));
+
+    return 0;
+}
+
+int flag_unset(FLAG * flags, int row, int col)
+{
+    flags->array[row][col >> 3] &= ~(1 << (col & 7));
+
+    return 0;
+}
+
+int flag_get(FLAG * flags, int row, int col)
+{
+    return (flags->array[row][col >> 3] & (1 << (col & 7)));
+}
+
+int flag_clear_all(FLAG * flags)
+{
+    register int r, c;
+
+    for (r = 0; r < flags->nrows; r++) {
+	for (c = 0; c < flags->leng; c++) {
+	    flags->array[r][c] = 0;
+	}
+    }
+
+    return 0;
+}

Added: grass-addons/grass7/raster/r.clump2/flag.h
===================================================================
--- grass-addons/grass7/raster/r.clump2/flag.h	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/flag.h	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,66 @@
+#ifndef __FLAG_H__
+#define __FLAG_H__
+
+/* flag.[ch] is a set of routines which will set up an array of bits
+ ** that allow the programmer to "flag" cells in a raster map.
+ **
+ ** FLAG *
+ ** flag_create(nrows,ncols)
+ ** int nrows, ncols;
+ **     opens the structure flag.  
+ **     The flag structure will be a two dimensional array of bits the
+ **     size of nrows by ncols.  Will initalize flags to zero (unset).
+ **
+ ** flag_destroy(flags)
+ ** FLAG *flags;
+ **     closes flags and gives the memory back to the system.
+ **
+ ** flag_clear_all(flags)
+ ** FLAG *flags;
+ **     sets all values in flags to zero.
+ **
+ ** flag_unset(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ **     sets the value of (row, col) in flags to zero.
+ **
+ ** flag_set(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ **     will set the value of (row, col) in flags to one.
+ **
+ ** int
+ ** flag_get(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ **     returns the value in flags that is at (row, col).
+ **
+ ** idea by Michael Shapiro
+ ** code by Chuck Ehlschlaeger
+ ** April 03, 1989
+ */
+
+#define FLAG struct _flagsss_
+FLAG {
+    int nrows, ncols, leng;
+    unsigned char **array;
+};
+
+#define FLAG_UNSET(flags,row,col) \
+	(flags)->array[(row)][(col)>>3] &= ~(1<<((col) & 7))
+
+#define FLAG_SET(flags,row,col) \
+	(flags)->array[(row)][(col)>>3] |= (1<<((col) & 7))
+
+#define FLAG_GET(flags,row,col) \
+	(flags)->array[(row)][(col)>>3] & (1<<((col) & 7))
+
+/* flag.c */
+int flag_clear_all(FLAG *);
+FLAG *flag_create(int, int);
+int flag_destroy(FLAG *);
+int flag_get(FLAG *, int, int);
+int flag_set(FLAG *, int, int);
+int flag_unset(FLAG *, int, int);
+
+#endif /* __FLAG_H__ */

Added: grass-addons/grass7/raster/r.clump2/local_proto.h
===================================================================
--- grass-addons/grass7/raster/r.clump2/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/local_proto.h	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,37 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.clump
+ *
+ * AUTHOR(S):    Michael Shapiro - CERL
+ *
+ * PURPOSE:      Recategorizes data in a raster map layer by grouping cells
+ *               that form physically discrete areas into unique categories.
+ *
+ * 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.
+ *
+ ***************************************************************************/
+
+#ifndef __LOCAL_PROTO_H__
+#define __LOCAL_PROTO_H__
+
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include "flag.h"
+#include "ramseg.h"
+
+extern long pqsize;
+extern CELL *clump_id;
+
+/* pq.c */
+int init_pq(int);
+int free_pq(void);
+int add_pnt(long);
+long drop_pnt(void);
+
+
+#endif /* __LOCAL_PROTO_H__ */

Added: grass-addons/grass7/raster/r.clump2/main.c
===================================================================
--- grass-addons/grass7/raster/r.clump2/main.c	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/main.c	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,253 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.clump2
+ *
+ * AUTHOR(S):    Markus Metz
+ *
+ * PURPOSE:      Recategorizes data in a raster map layer by grouping cells
+ *		 that form physically discrete areas into unique categories.
+ *
+ * COPYRIGHT:    (C) 2009 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 <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include "local_proto.h"
+#include <grass/glocale.h>
+
+CELL *clump_id;
+long pqsize;
+
+int main(int argc, char *argv[])
+{
+    struct Colors colr;
+    struct Range range;
+    CELL min, max;
+    int in_fd, out_fd;
+    char title[512];
+    char name[GNAME_MAX];
+    struct GModule *module;
+    struct Option *opt_in;
+    struct Option *opt_out;
+    struct Option *opt_title;
+    struct Flag *sides_flag;
+    CELL clump_no, *out_buf;
+    struct Cell_head window, cellhd;
+    int nrows, ncols, r, c;
+    long ncells, counter;
+    void *in_ptr, *in_buf;
+    int map_type, in_size;
+    FLAG *inlist;
+    int ramseg;
+    long index, index_nbr;
+    int sides, s, r_nbr, c_nbr;
+    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
+    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
+
+    G_gisinit(argv[0]);
+
+    /* Define the different options */
+
+    module = G_define_module();
+    G_add_keyword(_("raster"));
+    G_add_keyword(_("statistics"));
+    G_add_keyword(_("reclass"));
+    module->description =
+	_("Recategorizes data in a raster map by grouping cells "
+	  "that form physically discrete areas into unique categories.");
+
+    opt_in = G_define_standard_option(G_OPT_R_INPUT);
+
+    opt_out = G_define_standard_option(G_OPT_R_OUTPUT);
+
+    opt_title = G_define_option();
+    opt_title->key = "title";
+    opt_title->type = TYPE_STRING;
+    opt_title->required = NO;
+    opt_title->description = _("Title");
+
+    sides_flag = G_define_flag();
+    sides_flag->key = 'e';
+    sides_flag->description = _("Ignore diagonal cells");
+
+
+    /* parse options */
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    in_fd = Rast_open_old(opt_in->answer, "");
+    if (in_fd < 0)
+	G_fatal_error(_("Unable to open raster map <%s>"), opt_in->answer);
+
+    out_fd = Rast_open_c_new(opt_out->answer);
+    if (out_fd < 0)
+	G_fatal_error(_("Unable to create raster map <%s>"), opt_out->answer);
+
+    if (sides_flag->answer)
+	sides = 4;
+    else
+	sides = 8;
+
+    /* some checks */
+    G_get_set_window(&window);
+    Rast_get_cellhd(opt_in->answer, "", &cellhd);
+
+    if (fabs(window.ew_res - cellhd.ew_res) > GRASS_EPSILON ||
+	fabs(window.ns_res - cellhd.ns_res) > GRASS_EPSILON) {
+	G_warning(_("Current region resolution and raster map resolution mismatch!"));
+	G_warning(_("Real clumps may not be presented"));
+	G_warning("ew diff %e", window.ew_res - cellhd.ew_res);
+	G_warning("ns diff %e", window.ns_res - cellhd.ns_res);
+    }
+
+    nrows = window.rows;
+    ncols = window.cols;
+
+    if ((double)nrows * ncols > LONG_MAX)
+	G_fatal_error(_("Current region is too large, can't process raster map <%s>"),
+		      opt_in->answer);
+
+    /* allocate space */
+    clump_id =
+	(CELL *) G_malloc(size_array(&ramseg, nrows, ncols) * sizeof(CELL));
+
+    /* read input */
+    map_type = Rast_get_map_type(in_fd);
+    in_size = Rast_cell_size(map_type);
+    in_buf = Rast_allocate_buf(map_type);
+
+    inlist = flag_create(nrows, ncols);
+
+    G_message(_("load input map ..."));
+    for (r = 0; r < nrows; r++) {
+	Rast_get_row(in_fd, in_buf, r, map_type);
+	in_ptr = in_buf;
+	G_percent(r, nrows, 2);
+	for (c = 0; c < ncols; c++) {
+	    index = SEG_INDEX(ramseg, r, c);
+	    if (Rast_is_null_value(in_ptr, map_type))
+		clump_id[index] = 0;
+	    else
+		clump_id[index] = 1;
+
+	    FLAG_UNSET(inlist, r, c);
+
+	    in_ptr = G_incr_void_ptr(in_ptr, in_size);
+	}
+    }
+    G_percent(nrows, nrows, 2);
+
+    Rast_close(in_fd);
+    G_free(in_buf);
+
+    /* determine clumps */
+    G_message(_("determine clumps ..."));
+
+    ncells = nrows * ncols;
+    counter = 1;
+
+    /* initialize priority queue */
+    init_pq(nrows * ncols * 0.02);
+
+    clump_no = 1;
+    index = SEG_INDEX(ramseg, 0, 0);
+    if (clump_id[index] != 0)
+	clump_id[index] = clump_no++;
+    add_pnt(index);
+    FLAG_SET(inlist, 0, 0);
+
+    while (pqsize > 0) {
+	int start_new = 1;
+
+	G_percent(counter++, ncells, 2);
+
+	index = drop_pnt();
+	seg_index_rc(ramseg, index, &r, &c);
+
+	for (s = 0; s < sides; s++) {
+	    r_nbr = r + nextdr[s];
+	    c_nbr = c + nextdc[s];
+	    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) {
+
+		if ((FLAG_GET(inlist, r_nbr, c_nbr)) == 0) {
+
+		    index_nbr = SEG_INDEX(ramseg, r_nbr, c_nbr);
+
+		    /* not in clump, start new clump */
+		    if (clump_id[index] == 0 && clump_id[index_nbr] != 0) {
+			/* skip other neighbors of same or other clump */
+			if (start_new) {
+			    clump_id[index_nbr] = clump_no++;
+			    add_pnt(index_nbr);
+			    FLAG_SET(inlist, r_nbr, c_nbr);
+			    start_new = 0;
+			}
+		    }
+		    else if (clump_id[index] == 0 && clump_id[index_nbr] == 0) {
+			add_pnt(index_nbr);
+			FLAG_SET(inlist, r_nbr, c_nbr);
+		    }
+		    else if (clump_id[index] != 0) {
+			if (clump_id[index_nbr] != 0)
+			    clump_id[index_nbr] = clump_id[index];
+
+			add_pnt(index_nbr);
+			FLAG_SET(inlist, r_nbr, c_nbr);
+		    }
+		}
+	    }
+	}
+    }
+    free_pq();
+
+    if (counter < ncells)
+	G_warning("missed some cells!");
+
+    flag_destroy(inlist);
+
+    /* write output */
+    G_message(_("write output map ..."));
+    out_buf = Rast_allocate_buf(CELL_TYPE);
+    for (r = 0; r < nrows; r++) {
+	G_percent(r, nrows, 2);
+	for (c = 0; c < ncols; c++) {
+	    index = SEG_INDEX(ramseg, r, c);
+	    if (clump_id[index] == 0)
+		Rast_set_c_null_value(&out_buf[c], 1);
+	    else
+		out_buf[c] = clump_id[index];
+
+	}
+	Rast_put_row(out_fd, out_buf, CELL_TYPE);
+    }
+    G_percent(nrows, nrows, 2);
+    G_free(out_buf);
+    Rast_close(out_fd);
+    G_free(clump_id);
+
+    G_debug(1, "Creating support files...");
+
+    /* build title */
+    if (opt_title->answer != NULL)
+	strcpy(title, opt_title->answer);
+    else
+	sprintf(title, "clump of <%s@%s>", name, G_mapset());
+
+    Rast_put_cell_title(opt_out->answer, title);
+    Rast_read_range(opt_out->answer, G_mapset(), &range);
+    Rast_get_range_min_max(&range, &min, &max);
+    Rast_make_random_colors(&colr, min, max);
+    Rast_write_colors(opt_out->answer, G_mapset(), &colr);
+
+    G_done_msg(_("%d clumps."), range.max);
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/raster/r.clump2/pq.c
===================================================================
--- grass-addons/grass7/raster/r.clump2/pq.c	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/pq.c	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,148 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.clump2
+ *
+ * AUTHOR(S):    Markus Metz
+ *
+ * PURPOSE:      Recategorizes data in a raster map layer by grouping cells
+ *		 that form physically discrete areas into unique categories.
+ *
+ * COPYRIGHT:    (C) 2009 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 <stdlib.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+#define GET_PARENT(c) (int) (((c) - 2) / 3 + 1)
+#define GET_CHILD(p) (int) (((p) * 3) - 1)
+
+static int heap_alloced = 0;
+static int heap_step;
+static long *heap_index;
+
+int init_pq(int step)
+{
+    pqsize = 0;
+    if (step < 100)
+	step = 100;
+
+    heap_alloced = heap_step = step;
+    heap_index = (long *)G_malloc(heap_alloced * sizeof(long));
+
+    return 0;
+}
+
+int free_pq(void)
+{
+    if (heap_alloced)
+	G_free(heap_index);
+
+    return 0;
+}
+
+long sift_up(long start, long child_pnt)
+{
+    register long parent, child;
+
+    child = start;
+
+    while (child > 1) {
+	parent = GET_PARENT(child);
+
+	/* child is larger */
+	if (clump_id[child_pnt] > clump_id[heap_index[parent]]) {
+	    /* push parent point down */
+	    heap_index[child] = heap_index[parent];
+	    child = parent;
+	}
+	else
+	    /* no more sifting up, found new slot for child */
+	    break;
+    }
+
+    /* put point in new slot */
+    if (child < start) {
+	heap_index[child] = child_pnt;
+    }
+
+    return child;
+}
+
+int add_pnt(long index)
+{
+    pqsize++;
+    if (pqsize >= heap_alloced) {
+	heap_alloced += heap_step;
+	heap_index =
+	    (long *)G_realloc((void *)heap_index,
+			      heap_alloced * sizeof(long));
+    }
+
+    heap_index[pqsize] = index;
+    sift_up(pqsize, index);
+
+    return 0;
+}
+
+long drop_pnt(void)
+{
+    register long parent, child, childr, i;
+    long next_index;
+
+    if (pqsize == 0)
+	return -1;
+
+    next_index = heap_index[1];
+
+    if (pqsize == 1) {
+	pqsize--;
+
+	heap_index[1] = -1;
+
+	return next_index;
+    }
+
+    /* start with root */
+    parent = 1;
+
+    /* sift down: move hole back towards bottom of heap */
+
+    while ((child = GET_CHILD(parent)) <= pqsize) {
+	if (child < pqsize) {
+	    childr = child + 1;
+	    i = child + 3;
+	    /* get largest child */
+	    while (childr < i && childr <= pqsize) {
+		if (clump_id[heap_index[childr]] >
+		    clump_id[heap_index[child]]) {
+		    child = childr;
+		}
+		childr++;
+	    }
+	}
+
+	/* move hole down */
+	heap_index[parent] = heap_index[child];
+	parent = child;
+    }
+
+    /* hole is in lowest layer, move to heap end */
+    if (parent < pqsize) {
+	heap_index[parent] = heap_index[pqsize];
+
+	/* sift up last swapped point, only necessary if hole moved to heap end */
+	sift_up(parent, heap_index[parent]);
+    }
+
+    /* the actual drop */
+    pqsize--;
+
+    return next_index;
+}

Added: grass-addons/grass7/raster/r.clump2/r.clump2.html
===================================================================
--- grass-addons/grass7/raster/r.clump2/r.clump2.html	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/r.clump2.html	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,48 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.clump2</em> finds all areas of contiguous cell category values in the
+input raster map layer <em>name.</em> It assigns a unique category value
+to each such area ("clump") in the resulting output raster map layer
+<em>name.</em> 
+
+<h4>Differences to r.clump</h4>
+
+Category distinctions in the input raster map layer are NOT preserved.
+This means that if distinct category values are adjacent, they will be
+clumped together if possible.
+<p>
+Contrary to r.clump, NULL cells are ignored and not clumped.
+<p>
+<em>r.clump2</em> also consideres diagonal cells. <em>r.clump2</em> can
+be forced to consider only edge cells with the <em>e</em> flag, diagonal
+cells are now ignored.
+<p>
+Linear elements (lines that are a single cell wide) are without the
+<em>e</em> flag always clumped together.
+<p> 
+
+
+<h2>NOTES</h2>
+
+A random color table and other support files are
+generated for the <em>output</em> raster map layer.
+
+<h2>SEE ALSO</h2>
+
+<em><a href="r.clump.html">r.clump</a></em><br>
+<em><a href="r.average.html">r.average</a></em><br>
+<em><a href="r.buffer.html">r.buffer</a></em><br>
+<em><a href="r.grow.html">r.grow</a></em><br>
+<em><a href="r.mapcalc.html">r.mapcalc</a></em><br>
+<em><a href="r.mfilter.html">r.mfilter</a></em><br>
+<em><a href="r.neighbors.html">r.neighbors</a></em><br>
+<em><a href="r.to.vect.html">r.to.vect</a></em><br>
+<em><a href="r.reclass.html">r.reclass</a></em><br>
+<em><a href="r.statistics.html">r.statistics</a></em><br>
+<em><a href="r.support.html">r.support</a></em>
+
+<h2>AUTHOR</h2>
+
+Markus Metz
+
+<p><i>Last changed: $Date: 2009-12-08 10:16:42 -0200 (Tue, 08 Dec 2009) $</i>

Added: grass-addons/grass7/raster/r.clump2/ramseg.c
===================================================================
--- grass-addons/grass7/raster/r.clump2/ramseg.c	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/ramseg.c	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include "ramseg.h"
+
+int size_array(int *ram_seg, int nrows, int ncols)
+{
+    int size, segs_in_col;
+
+    segs_in_col = ((nrows - 1) >> RAMSEGBITS) + 1;
+    *ram_seg = ((ncols - 1) >> RAMSEGBITS) + 1;
+    size = ((((nrows - 1) >> RAMSEGBITS) + 1) << RAMSEGBITS) *
+	((((ncols - 1) >> RAMSEGBITS) + 1) << RAMSEGBITS);
+    size -= ((segs_in_col << RAMSEGBITS) - nrows) << RAMSEGBITS;
+    size -= (*ram_seg << RAMSEGBITS) - ncols;
+    return (size);
+}
+
+/* get r, c from seg_index */
+int seg_index_rc(int ramseg, int seg_index, int *r, int *c)
+{
+    int seg_no, seg_remainder;
+
+    seg_no = seg_index >> DOUBLEBITS;
+    seg_remainder = seg_index - (seg_no << DOUBLEBITS);
+    *r = ((seg_no / ramseg) << RAMSEGBITS) + (seg_remainder >> RAMSEGBITS);
+    *c = ((seg_no - ((*r) >> RAMSEGBITS) * ramseg) << RAMSEGBITS) +
+	seg_remainder - (((*r) & SEGLENLESS) << RAMSEGBITS);
+    return seg_no;
+}

Added: grass-addons/grass7/raster/r.clump2/ramseg.h
===================================================================
--- grass-addons/grass7/raster/r.clump2/ramseg.h	                        (rev 0)
+++ grass-addons/grass7/raster/r.clump2/ramseg.h	2009-12-08 09:57:20 UTC (rev 39943)
@@ -0,0 +1,17 @@
+#ifndef __RAMSEG_H__
+#define __RAMSEG_H__
+
+
+#define RAMSEG		int
+#define RAMSEGBITS 	4
+#define DOUBLEBITS 	8	/* 2 * ramsegbits       */
+#define SEGLENLESS 	15	/* 2 ^ ramsegbits - 1   */
+
+#define SEG_INDEX(s,r,c) (int) \
+   (((((r) >> RAMSEGBITS) * (s) + ((c) >> RAMSEGBITS)) << DOUBLEBITS) \
+    + (((r) & SEGLENLESS) << RAMSEGBITS) + ((c) & SEGLENLESS))
+
+int size_array(int *, int, int);
+int seg_index_rc(int, int, int *, int *);
+
+#endif /* __RAMSEG_H__ */



More information about the grass-commit mailing list