[GRASS-SVN] r62436 - in grass/branches/releasebranch_7_0/lib: driver gpde ogsf

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Oct 28 06:32:07 PDT 2014


Author: martinl
Date: 2014-10-28 06:32:06 -0700 (Tue, 28 Oct 2014)
New Revision: 62436

Added:
   grass/branches/releasebranch_7_0/lib/driver/box.c
   grass/branches/releasebranch_7_0/lib/driver/color.c
   grass/branches/releasebranch_7_0/lib/driver/draw.c
   grass/branches/releasebranch_7_0/lib/driver/erase.c
   grass/branches/releasebranch_7_0/lib/driver/font.c
   grass/branches/releasebranch_7_0/lib/driver/get_t_box.c
   grass/branches/releasebranch_7_0/lib/driver/graph.c
   grass/branches/releasebranch_7_0/lib/driver/line_width.c
   grass/branches/releasebranch_7_0/lib/driver/move.c
   grass/branches/releasebranch_7_0/lib/driver/raster.c
   grass/branches/releasebranch_7_0/lib/driver/set_window.c
   grass/branches/releasebranch_7_0/lib/driver/text.c
   grass/branches/releasebranch_7_0/lib/driver/text_size.c
   grass/branches/releasebranch_7_0/lib/gpde/n_arrays.c
   grass/branches/releasebranch_7_0/lib/gpde/n_arrays_calc.c
   grass/branches/releasebranch_7_0/lib/gpde/n_arrays_io.c
   grass/branches/releasebranch_7_0/lib/gpde/n_geom.c
   grass/branches/releasebranch_7_0/lib/gpde/n_gradient.c
   grass/branches/releasebranch_7_0/lib/gpde/n_gradient_calc.c
   grass/branches/releasebranch_7_0/lib/gpde/n_gwflow.c
   grass/branches/releasebranch_7_0/lib/gpde/n_heatflow.c
   grass/branches/releasebranch_7_0/lib/gpde/n_les.c
   grass/branches/releasebranch_7_0/lib/gpde/n_les_assemble.c
   grass/branches/releasebranch_7_0/lib/gpde/n_parse_options.c
   grass/branches/releasebranch_7_0/lib/gpde/n_solute_transport.c
   grass/branches/releasebranch_7_0/lib/gpde/n_tools.c
   grass/branches/releasebranch_7_0/lib/gpde/n_upwind.c
   grass/branches/releasebranch_7_0/lib/ogsf/gk2.c
   grass/branches/releasebranch_7_0/lib/ogsf/gp2.c
   grass/branches/releasebranch_7_0/lib/ogsf/gp3.c
   grass/branches/releasebranch_7_0/lib/ogsf/gs2.c
   grass/branches/releasebranch_7_0/lib/ogsf/gs3.c
   grass/branches/releasebranch_7_0/lib/ogsf/gs_util.c
   grass/branches/releasebranch_7_0/lib/ogsf/gsx.c
   grass/branches/releasebranch_7_0/lib/ogsf/gv2.c
   grass/branches/releasebranch_7_0/lib/ogsf/gv3.c
   grass/branches/releasebranch_7_0/lib/ogsf/gvl2.c
   grass/branches/releasebranch_7_0/lib/ogsf/gvl3.c
Removed:
   grass/branches/releasebranch_7_0/lib/driver/Box.c
   grass/branches/releasebranch_7_0/lib/driver/Color.c
   grass/branches/releasebranch_7_0/lib/driver/Draw.c
   grass/branches/releasebranch_7_0/lib/driver/Erase.c
   grass/branches/releasebranch_7_0/lib/driver/Font.c
   grass/branches/releasebranch_7_0/lib/driver/Get_t_box.c
   grass/branches/releasebranch_7_0/lib/driver/Graph.c
   grass/branches/releasebranch_7_0/lib/driver/Line_width.c
   grass/branches/releasebranch_7_0/lib/driver/Move.c
   grass/branches/releasebranch_7_0/lib/driver/Raster.c
   grass/branches/releasebranch_7_0/lib/driver/Set_window.c
   grass/branches/releasebranch_7_0/lib/driver/Text.c
   grass/branches/releasebranch_7_0/lib/driver/Text_size.c
   grass/branches/releasebranch_7_0/lib/gpde/N_arrays.c
   grass/branches/releasebranch_7_0/lib/gpde/N_arrays_calc.c
   grass/branches/releasebranch_7_0/lib/gpde/N_arrays_io.c
   grass/branches/releasebranch_7_0/lib/gpde/N_geom.c
   grass/branches/releasebranch_7_0/lib/gpde/N_gradient.c
   grass/branches/releasebranch_7_0/lib/gpde/N_gradient_calc.c
   grass/branches/releasebranch_7_0/lib/gpde/N_gwflow.c
   grass/branches/releasebranch_7_0/lib/gpde/N_heatflow.c
   grass/branches/releasebranch_7_0/lib/gpde/N_les.c
   grass/branches/releasebranch_7_0/lib/gpde/N_les_assemble.c
   grass/branches/releasebranch_7_0/lib/gpde/N_parse_options.c
   grass/branches/releasebranch_7_0/lib/gpde/N_solute_transport.c
   grass/branches/releasebranch_7_0/lib/gpde/N_tools.c
   grass/branches/releasebranch_7_0/lib/gpde/N_upwind.c
   grass/branches/releasebranch_7_0/lib/ogsf/GK2.c
   grass/branches/releasebranch_7_0/lib/ogsf/GP2.c
   grass/branches/releasebranch_7_0/lib/ogsf/GS2.c
   grass/branches/releasebranch_7_0/lib/ogsf/GSX.c
   grass/branches/releasebranch_7_0/lib/ogsf/GS_util.c
   grass/branches/releasebranch_7_0/lib/ogsf/GV2.c
   grass/branches/releasebranch_7_0/lib/ogsf/GVL2.c
   grass/branches/releasebranch_7_0/lib/ogsf/Gp3.c
   grass/branches/releasebranch_7_0/lib/ogsf/Gs3.c
   grass/branches/releasebranch_7_0/lib/ogsf/Gv3.c
   grass/branches/releasebranch_7_0/lib/ogsf/Gvl3.c
Log:
lib: rename files to lowercase 


Deleted: grass/branches/releasebranch_7_0/lib/driver/Box.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Box.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Box.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,9 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Box_abs(double x1, double y1, double x2, double y2)
-{
-    if (driver->Box)
-	(*driver->Box)(x1, y1, x2, y2);
-}
-

Deleted: grass/branches/releasebranch_7_0/lib/driver/Color.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Color.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Color.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,20 +0,0 @@
-#include <grass/colors.h>
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Color_RGB(unsigned char r, unsigned char g, unsigned char b)
-{
-    if (driver->Color)
-	(*driver->Color)(r, g, b);
-}
-
-void COM_Standard_color(int number)
-{
-    struct color_rgb rgb;
-
-    if (number < 0 || number >= G_num_standard_colors())
-	return;
-
-    rgb = G_standard_color_rgb(number);
-    COM_Color_RGB(rgb.r, rgb.g, rgb.b);
-}

Deleted: grass/branches/releasebranch_7_0/lib/driver/Draw.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Draw.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Draw.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,52 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Bitmap(int ncols, int nrows, int threshold,
-		const unsigned char *buf)
-{
-    if (driver->Bitmap)
-	(*driver->Bitmap) (ncols, nrows, threshold, buf);
-}
-
-void COM_Begin(void)
-{
-    if (driver->Begin)
-	(*driver->Begin)();
-}
-
-void COM_Move(double x, double y)
-{
-    if (driver->Move)
-	(*driver->Move)(x, y);
-}
-
-void COM_Cont(double x, double y)
-{
-    if (driver->Cont)
-	(*driver->Cont)(x, y);
-}
-
-void COM_Close(void)
-{
-    if (driver->Close)
-	(*driver->Close)();
-}
-
-void COM_Stroke(void)
-{
-    if (driver->Stroke)
-	(*driver->Stroke)();
-}
-
-void COM_Fill(void)
-{
-    if (driver->Fill)
-	(*driver->Fill)();
-}
-
-void COM_Point(double x, double y)
-{
-    if (driver->Point)
-	(*driver->Point)(x, y);
-}
-

Deleted: grass/branches/releasebranch_7_0/lib/driver/Erase.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Erase.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Erase.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,8 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Erase(void)
-{
-    if (driver->Erase)
-	(*driver->Erase)();
-}

Deleted: grass/branches/releasebranch_7_0/lib/driver/Font.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Font.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Font.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,159 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-
-#include <grass/gis.h>
-#include "driver.h"
-#include "driverlib.h"
-
-static int font_type = GFONT_STROKE;
-static char *encoding;
-
-static void stroke_set(const char *filename)
-{
-    if (font_init(filename) == 0)
-	font_type = GFONT_STROKE;
-}
-
-static void freetype_set(const char *filename, int index)
-{
-    if (font_init_freetype(filename, index) == 0)
-	font_type = GFONT_FREETYPE;
-}
-
-static void driver_set(const char *name)
-{
-    (*driver->Set_font)(name);
-    font_type = GFONT_DRIVER;
-}
-
-int font_get_type(void)
-{
-    return font_type;
-}
-
-const char *font_get_encoding(void)
-{
-    if (!encoding)
-	encoding = G_store("ISO-8859-1");
-    return encoding;
-}
-
-static void font_list(char ***list, int *count, int verbose)
-{
-    char **fonts;
-    int num_fonts;
-    int i;
-
-    for (i = 0; ftcap[i].name; i++)
-	;
-    num_fonts = i;
-
-    fonts = G_malloc(num_fonts * sizeof(const char *));
-
-    for (i = 0; i < num_fonts; i++) {
-	struct GFONT_CAP *p = &ftcap[i];
-
-	if (verbose) {
-	    char buf[GPATH_MAX];
-
-	    sprintf(buf, "%s|%s|%d|%s|%d|%s|",
-		    p->name, p->longname, p->type,
-		    p->path, p->index, p->encoding);
-
-	    fonts[i] = G_store(buf);
-	}
-	else
-	    fonts[i] = G_store(p->name);
-    }
-
-    *list = fonts;
-    *count = num_fonts;
-}
-
-static void free_font_list(char **fonts, int count)
-{
-    int i;
-
-    for (i = 0; i < count; i++)
-	G_free(fonts[i]);
-
-    G_free(fonts);
-}
-
-void COM_Set_font(const char *name)
-{
-    int i;
-
-    if (G_is_absolute_path(name)) {
-	if (font_exists(name))
-	    freetype_set(name, 0);
-	return;
-    }
-
-    for (i = 0; ftcap[i].name; i++) {
-	struct GFONT_CAP *cap = &ftcap[i];
-
-	if (strcmp(name, cap->name) != 0)
-	    continue;
-
-	switch (cap->type) {
-	case GFONT_FREETYPE:
-	    freetype_set(cap->path, cap->index);
-	    COM_Set_encoding(cap->encoding);
-	    break;
-	case GFONT_STROKE:
-	    stroke_set(cap->name);
-	    break;
-	}
-	return;
-    }
-
-
-    if (driver->Font_info && driver->Set_font) {
-	char **list = NULL;
-	int count = 0;
-
-	(*driver->Font_info)(&list, &count);
-
-	for (i = 0; i < count; i++) {
-	    struct GFONT_CAP cap;
-
-	    if (!parse_fontcap_entry(&cap, list[i]))
-		continue;
-
-	    if (cap.type != GFONT_DRIVER || strcmp(name, cap.name) != 0)
-		continue;
-
-	    driver_set(cap.name);
-	    COM_Set_encoding(cap.encoding);
-	    break;
-	}
-
-	free_font_list(list, count);
-	return;
-    }
-
-    stroke_set("romans");
-}
-
-void COM_Set_encoding(const char *enc)
-{
-    if (encoding)
-	G_free(encoding);
-
-    encoding = G_store(enc);
-}
-
-void COM_Font_list(char ***list, int *count)
-{
-    font_list(list, count, 0);
-    if (driver->Font_list)
-	(*driver->Font_list)(list, count);
-}
-
-void COM_Font_info(char ***list, int *count)
-{
-    font_list(list, count, 1);
-    if (driver->Font_info)
-	(*driver->Font_info)(list, count);
-}

Deleted: grass/branches/releasebranch_7_0/lib/driver/Get_t_box.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Get_t_box.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Get_t_box.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,19 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Get_text_box(const char *text, double *t, double *b, double *l, double *r)
-{
-    switch (font_get_type()) {
-    case GFONT_STROKE:
-	get_text_ext(text, t, b, l, r);
-	break;
-    case GFONT_FREETYPE:
-	get_text_ext_freetype(text, t, b, l, r);
-	break;
-    case GFONT_DRIVER:
-	if (driver->Text_box)
-	    (*driver->Text_box)(text, t, b, l, r);
-	break;
-    }
-}
-

Deleted: grass/branches/releasebranch_7_0/lib/driver/Graph.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Graph.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Graph.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,15 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-int COM_Graph_set(void)
-{
-    if (driver->Graph_set)
-	return (*driver->Graph_set) ();
-    return 0;
-}
-
-void COM_Graph_close(void)
-{
-    if (driver->Graph_close)
-	(*driver->Graph_close) ();
-}

Deleted: grass/branches/releasebranch_7_0/lib/driver/Line_width.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Line_width.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Line_width.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,8 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Line_width(double width)
-{
-    if (driver->Line_width)
-	(*driver->Line_width) (width);
-}

Deleted: grass/branches/releasebranch_7_0/lib/driver/Move.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Move.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Move.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,9 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Pos_abs(double x, double y)
-{
-    cur_x = x;
-    cur_y = y;
-}
-

Deleted: grass/branches/releasebranch_7_0/lib/driver/Raster.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Raster.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Raster.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,33 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <grass/gis.h>
-#include "driver.h"
-#include "driverlib.h"
-
-/******************************************************************************
- * These routines support the drawing of multi-band images on the graphics
- * device.
- ******************************************************************************
- */
-
-void COM_begin_raster(int mask, int src[2][2], double dst[2][2])
-{
-    if (driver->Begin_raster)
-	(*driver->Begin_raster) (mask, src, dst);
-}
-
-int COM_raster(int n, int row,
-	       const unsigned char *red, const unsigned char *grn,
-	       const unsigned char *blu, const unsigned char *nul)
-{
-    if (driver->Raster)
-	return (*driver->Raster) (n, row, red, grn, blu, nul);
-
-    return -1;
-}
-
-void COM_end_raster(void)
-{
-    if (driver->End_raster)
-	(*driver->End_raster) ();
-}

Deleted: grass/branches/releasebranch_7_0/lib/driver/Set_window.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Set_window.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Set_window.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,25 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-static struct {
-    double t, b, l, r;
-} window;
-
-void COM_Set_window(double t, double b, double l, double r)
-{
-    window.t = t;
-    window.b = b;
-    window.l = l;
-    window.r = r;
-
-    if (driver->Set_window)
-	(*driver->Set_window) (t, b, l, r);
-}
-
-void COM_Get_window(double *t, double *b, double *l, double *r)
-{
-    *t = window.t;
-    *b = window.b;
-    *l = window.l;
-    *r = window.r;
-}

Deleted: grass/branches/releasebranch_7_0/lib/driver/Text.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Text.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Text.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,19 +0,0 @@
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Text(const char *text)
-{
-    switch (font_get_type()) {
-    case GFONT_STROKE:
-	soft_text(text);
-	break;
-    case GFONT_FREETYPE:
-	soft_text_freetype(text);
-	break;
-    case GFONT_DRIVER:
-	if (driver->Text)
-	    (*driver->Text)(text);
-	break;
-    }
-}
-

Deleted: grass/branches/releasebranch_7_0/lib/driver/Text_size.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/Text_size.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/driver/Text_size.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,18 +0,0 @@
-#include <math.h>
-#include "driver.h"
-#include "driverlib.h"
-
-void COM_Text_size(double x, double y)
-{
-    text_size_x = x;
-    text_size_y = y;
-    matrix_valid = 0;
-}
-
-void COM_Text_rotation(double val)
-{
-    text_rotation = val;
-    text_sinrot = sin(M_PI * text_rotation / 180.0);
-    text_cosrot = cos(M_PI * text_rotation / 180.0);
-    matrix_valid = 0;
-}

Copied: grass/branches/releasebranch_7_0/lib/driver/box.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Box.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/box.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/box.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,9 @@
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Box_abs(double x1, double y1, double x2, double y2)
+{
+    if (driver->Box)
+	(*driver->Box)(x1, y1, x2, y2);
+}
+

Copied: grass/branches/releasebranch_7_0/lib/driver/color.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Color.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/color.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/color.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,20 @@
+#include <grass/colors.h>
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Color_RGB(unsigned char r, unsigned char g, unsigned char b)
+{
+    if (driver->Color)
+	(*driver->Color)(r, g, b);
+}
+
+void COM_Standard_color(int number)
+{
+    struct color_rgb rgb;
+
+    if (number < 0 || number >= G_num_standard_colors())
+	return;
+
+    rgb = G_standard_color_rgb(number);
+    COM_Color_RGB(rgb.r, rgb.g, rgb.b);
+}

Copied: grass/branches/releasebranch_7_0/lib/driver/draw.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Draw.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/draw.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/draw.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,52 @@
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Bitmap(int ncols, int nrows, int threshold,
+		const unsigned char *buf)
+{
+    if (driver->Bitmap)
+	(*driver->Bitmap) (ncols, nrows, threshold, buf);
+}
+
+void COM_Begin(void)
+{
+    if (driver->Begin)
+	(*driver->Begin)();
+}
+
+void COM_Move(double x, double y)
+{
+    if (driver->Move)
+	(*driver->Move)(x, y);
+}
+
+void COM_Cont(double x, double y)
+{
+    if (driver->Cont)
+	(*driver->Cont)(x, y);
+}
+
+void COM_Close(void)
+{
+    if (driver->Close)
+	(*driver->Close)();
+}
+
+void COM_Stroke(void)
+{
+    if (driver->Stroke)
+	(*driver->Stroke)();
+}
+
+void COM_Fill(void)
+{
+    if (driver->Fill)
+	(*driver->Fill)();
+}
+
+void COM_Point(double x, double y)
+{
+    if (driver->Point)
+	(*driver->Point)(x, y);
+}
+

Copied: grass/branches/releasebranch_7_0/lib/driver/erase.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Erase.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/erase.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/erase.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,8 @@
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Erase(void)
+{
+    if (driver->Erase)
+	(*driver->Erase)();
+}

Copied: grass/branches/releasebranch_7_0/lib/driver/font.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Font.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/font.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/font.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <grass/gis.h>
+#include "driver.h"
+#include "driverlib.h"
+
+static int font_type = GFONT_STROKE;
+static char *encoding;
+
+static void stroke_set(const char *filename)
+{
+    if (font_init(filename) == 0)
+	font_type = GFONT_STROKE;
+}
+
+static void freetype_set(const char *filename, int index)
+{
+    if (font_init_freetype(filename, index) == 0)
+	font_type = GFONT_FREETYPE;
+}
+
+static void driver_set(const char *name)
+{
+    (*driver->Set_font)(name);
+    font_type = GFONT_DRIVER;
+}
+
+int font_get_type(void)
+{
+    return font_type;
+}
+
+const char *font_get_encoding(void)
+{
+    if (!encoding)
+	encoding = G_store("ISO-8859-1");
+    return encoding;
+}
+
+static void font_list(char ***list, int *count, int verbose)
+{
+    char **fonts;
+    int num_fonts;
+    int i;
+
+    for (i = 0; ftcap[i].name; i++)
+	;
+    num_fonts = i;
+
+    fonts = G_malloc(num_fonts * sizeof(const char *));
+
+    for (i = 0; i < num_fonts; i++) {
+	struct GFONT_CAP *p = &ftcap[i];
+
+	if (verbose) {
+	    char buf[GPATH_MAX];
+
+	    sprintf(buf, "%s|%s|%d|%s|%d|%s|",
+		    p->name, p->longname, p->type,
+		    p->path, p->index, p->encoding);
+
+	    fonts[i] = G_store(buf);
+	}
+	else
+	    fonts[i] = G_store(p->name);
+    }
+
+    *list = fonts;
+    *count = num_fonts;
+}
+
+static void free_font_list(char **fonts, int count)
+{
+    int i;
+
+    for (i = 0; i < count; i++)
+	G_free(fonts[i]);
+
+    G_free(fonts);
+}
+
+void COM_Set_font(const char *name)
+{
+    int i;
+
+    if (G_is_absolute_path(name)) {
+	if (font_exists(name))
+	    freetype_set(name, 0);
+	return;
+    }
+
+    for (i = 0; ftcap[i].name; i++) {
+	struct GFONT_CAP *cap = &ftcap[i];
+
+	if (strcmp(name, cap->name) != 0)
+	    continue;
+
+	switch (cap->type) {
+	case GFONT_FREETYPE:
+	    freetype_set(cap->path, cap->index);
+	    COM_Set_encoding(cap->encoding);
+	    break;
+	case GFONT_STROKE:
+	    stroke_set(cap->name);
+	    break;
+	}
+	return;
+    }
+
+
+    if (driver->Font_info && driver->Set_font) {
+	char **list = NULL;
+	int count = 0;
+
+	(*driver->Font_info)(&list, &count);
+
+	for (i = 0; i < count; i++) {
+	    struct GFONT_CAP cap;
+
+	    if (!parse_fontcap_entry(&cap, list[i]))
+		continue;
+
+	    if (cap.type != GFONT_DRIVER || strcmp(name, cap.name) != 0)
+		continue;
+
+	    driver_set(cap.name);
+	    COM_Set_encoding(cap.encoding);
+	    break;
+	}
+
+	free_font_list(list, count);
+	return;
+    }
+
+    stroke_set("romans");
+}
+
+void COM_Set_encoding(const char *enc)
+{
+    if (encoding)
+	G_free(encoding);
+
+    encoding = G_store(enc);
+}
+
+void COM_Font_list(char ***list, int *count)
+{
+    font_list(list, count, 0);
+    if (driver->Font_list)
+	(*driver->Font_list)(list, count);
+}
+
+void COM_Font_info(char ***list, int *count)
+{
+    font_list(list, count, 1);
+    if (driver->Font_info)
+	(*driver->Font_info)(list, count);
+}

Copied: grass/branches/releasebranch_7_0/lib/driver/get_t_box.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Get_t_box.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/get_t_box.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/get_t_box.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,19 @@
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Get_text_box(const char *text, double *t, double *b, double *l, double *r)
+{
+    switch (font_get_type()) {
+    case GFONT_STROKE:
+	get_text_ext(text, t, b, l, r);
+	break;
+    case GFONT_FREETYPE:
+	get_text_ext_freetype(text, t, b, l, r);
+	break;
+    case GFONT_DRIVER:
+	if (driver->Text_box)
+	    (*driver->Text_box)(text, t, b, l, r);
+	break;
+    }
+}
+

Copied: grass/branches/releasebranch_7_0/lib/driver/graph.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Graph.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/graph.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/graph.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,15 @@
+#include "driver.h"
+#include "driverlib.h"
+
+int COM_Graph_set(void)
+{
+    if (driver->Graph_set)
+	return (*driver->Graph_set) ();
+    return 0;
+}
+
+void COM_Graph_close(void)
+{
+    if (driver->Graph_close)
+	(*driver->Graph_close) ();
+}

Copied: grass/branches/releasebranch_7_0/lib/driver/line_width.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Line_width.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/line_width.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/line_width.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,8 @@
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Line_width(double width)
+{
+    if (driver->Line_width)
+	(*driver->Line_width) (width);
+}

Copied: grass/branches/releasebranch_7_0/lib/driver/move.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Move.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/move.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/move.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,9 @@
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Pos_abs(double x, double y)
+{
+    cur_x = x;
+    cur_y = y;
+}
+

Copied: grass/branches/releasebranch_7_0/lib/driver/raster.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Raster.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/raster.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/raster.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <grass/gis.h>
+#include "driver.h"
+#include "driverlib.h"
+
+/******************************************************************************
+ * These routines support the drawing of multi-band images on the graphics
+ * device.
+ ******************************************************************************
+ */
+
+void COM_begin_raster(int mask, int src[2][2], double dst[2][2])
+{
+    if (driver->Begin_raster)
+	(*driver->Begin_raster) (mask, src, dst);
+}
+
+int COM_raster(int n, int row,
+	       const unsigned char *red, const unsigned char *grn,
+	       const unsigned char *blu, const unsigned char *nul)
+{
+    if (driver->Raster)
+	return (*driver->Raster) (n, row, red, grn, blu, nul);
+
+    return -1;
+}
+
+void COM_end_raster(void)
+{
+    if (driver->End_raster)
+	(*driver->End_raster) ();
+}

Copied: grass/branches/releasebranch_7_0/lib/driver/set_window.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Set_window.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/set_window.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/set_window.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,25 @@
+#include "driver.h"
+#include "driverlib.h"
+
+static struct {
+    double t, b, l, r;
+} window;
+
+void COM_Set_window(double t, double b, double l, double r)
+{
+    window.t = t;
+    window.b = b;
+    window.l = l;
+    window.r = r;
+
+    if (driver->Set_window)
+	(*driver->Set_window) (t, b, l, r);
+}
+
+void COM_Get_window(double *t, double *b, double *l, double *r)
+{
+    *t = window.t;
+    *b = window.b;
+    *l = window.l;
+    *r = window.r;
+}

Copied: grass/branches/releasebranch_7_0/lib/driver/text.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Text.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/text.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/text.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,19 @@
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Text(const char *text)
+{
+    switch (font_get_type()) {
+    case GFONT_STROKE:
+	soft_text(text);
+	break;
+    case GFONT_FREETYPE:
+	soft_text_freetype(text);
+	break;
+    case GFONT_DRIVER:
+	if (driver->Text)
+	    (*driver->Text)(text);
+	break;
+    }
+}
+

Copied: grass/branches/releasebranch_7_0/lib/driver/text_size.c (from rev 62432, grass/branches/releasebranch_7_0/lib/driver/Text_size.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/driver/text_size.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/driver/text_size.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,18 @@
+#include <math.h>
+#include "driver.h"
+#include "driverlib.h"
+
+void COM_Text_size(double x, double y)
+{
+    text_size_x = x;
+    text_size_y = y;
+    matrix_valid = 0;
+}
+
+void COM_Text_rotation(double val)
+{
+    text_rotation = val;
+    text_sinrot = sin(M_PI * text_rotation / 180.0);
+    text_cosrot = cos(M_PI * text_rotation / 180.0);
+    matrix_valid = 0;
+}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_arrays.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_arrays.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_arrays.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,1244 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*
-* PURPOSE:     	Array managment functions
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-#include <grass/raster.h>
-#include <grass/glocale.h>
-
-
-/* ******************** 2D ARRAY FUNCTIONS *********************** */
-
-/*!
- * \brief Allocate memory for a N_array_2d data structure.
- *
- * This function allocates memory for an array of type N_array_2d
- * and returns the pointer to the new allocated memory.
- * <br><br>
- * The data type of this array is set by "type" and must be
- * CELL_TYPE, FCELL_TYPE or DCELL_TYPE accordingly to the raster map data types.
- * The offset sets the number of boundary cols and rows.
- * This option is useful to generate homogeneous Neumann boundary conditions around
- * an array or to establish overlapping boundaries. The array is initialized with 0 by default.
- * <br><br>
- * If the offset is greater then 0, negative indices are possible.
- * <br><br>
- *
- * The data structure of a array with 3 rows and cols and an offset of 1
- * will looks like this:
- * <br><br>
- *
- \verbatim
- 0 0 0 0 0
- 0 0 1 2 0
- 0 3 4 5 0
- 0 6 7 8 0
- 0 0 0 0 0
- \endverbatim
- *
- * 0 is the boundary.
- * <br><br>
- * Internal a one dimensional array is allocated to save memory and to speed up the memory access.
- * To access the one dimensional array with a two dimensional index use the provided
- * get and put functions. The internal representation of the above data will look like this:
- *
- \verbatim
- 0 0 0 0 0 0 0 1 2 0 0 3 4 5 0 0 6 7 8 0 0 0 0 0 0
- \endverbatim
- *
- * \param cols int
- * \param rows int
- * \param offset int
- * \param type int
- * \return N_array_2d *
- *
- * */
-N_array_2d *N_alloc_array_2d(int cols, int rows, int offset, int type)
-{
-    N_array_2d *data = NULL;
-
-    if (rows < 1 || cols < 1)
-	G_fatal_error("N_alloc_array_2d: cols and rows should be > 0");
-
-    if (type != CELL_TYPE && type != FCELL_TYPE && type != DCELL_TYPE)
-	G_fatal_error
-	    ("N_alloc_array_2d: Wrong data type, should be CELL_TYPE, FCELL_TYPE or DCELL_TYPE");
-
-    data = (N_array_2d *) G_calloc(1, sizeof(N_array_2d));
-
-    data->cols = cols;
-    data->rows = rows;
-    data->type = type;
-    data->offset = offset;
-    data->rows_intern = rows + 2 * offset;	/*offset position at booth sides */
-    data->cols_intern = cols + 2 * offset;	/*offset position at booth sides */
-    data->cell_array = NULL;
-    data->fcell_array = NULL;
-    data->dcell_array = NULL;
-
-    if (data->type == CELL_TYPE) {
-	data->cell_array =
-	    (CELL *) G_calloc((size_t) data->rows_intern * data->cols_intern,
-			      sizeof(CELL));
-	G_debug(3,
-		"N_alloc_array_2d: CELL array allocated rows_intern %i cols_intern %i offset %i",
-		data->rows_intern, data->cols_intern, data->offset = offset);
-    }
-    else if (data->type == FCELL_TYPE) {
-	data->fcell_array =
-	    (FCELL *) G_calloc((size_t) data->rows_intern * data->cols_intern,
-			       sizeof(FCELL));
-	G_debug(3,
-		"N_alloc_array_2d: FCELL array allocated rows_intern %i cols_intern %i offset %i",
-		data->rows_intern, data->cols_intern, data->offset = offset);
-
-    }
-    else if (data->type == DCELL_TYPE) {
-	data->dcell_array =
-	    (DCELL *) G_calloc((size_t) data->rows_intern * data->cols_intern,
-			       sizeof(DCELL));
-	G_debug(3,
-		"N_alloc_array_2d: DCELL array allocated rows_intern %i cols_intern %i offset %i",
-		data->rows_intern, data->cols_intern, data->offset = offset);
-    }
-
-    return data;
-}
-
-/*!
- * \brief Release the memory of a N_array_2d structure
- *
- * \param data N_array_2d *
- * \return void
- * */
-void N_free_array_2d(N_array_2d * data)
-{
-
-    if (data != NULL) {
-	G_debug(3, "N_free_array_2d: free N_array_2d");
-
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    G_free(data->cell_array);
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    G_free(data->fcell_array);
-
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    G_free(data->dcell_array);
-	}
-
-	G_free(data);
-	data = NULL;
-
-    }
-
-    return;
-}
-
-
-/*!
- * \brief Return the data type of the N_array_2d struct
- *
- * The data type can be CELL_TYPE, FCELL_TYPE or DCELL_TYPE accordingly to the raster map data types.
- *
- * \param array N_array_2d *
- * \return type int
- * */
-int N_get_array_2d_type(N_array_2d * array)
-{
-    return array->type;
-}
-
-/*!
- * \brief Write the value of the N_array_2d struct at position col, row to value
- *
- * The value must be of the same type as the array. Otherwise you will risk data losses.
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \param value void * - this variable contains the array value at col, row position
- * \return void
- * */
-
-void N_get_array_2d_value(N_array_2d * data, int col, int row, void *value)
-{
-
-    if (data->offset == 0) {
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    *((CELL *) value) =
-		data->cell_array[row * data->cols_intern + col];
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    *((FCELL *) value) =
-		data->fcell_array[row * data->cols_intern + col];
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    *((DCELL *) value) =
-		data->dcell_array[row * data->cols_intern + col];
-	}
-    }
-    else {
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    *((CELL *) value) =
-		data->cell_array[(row + data->offset) * data->cols_intern +
-				 col + data->offset];
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    *((FCELL *) value) =
-		data->fcell_array[(row + data->offset) * data->cols_intern +
-				  col + data->offset];
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    *((DCELL *) value) =
-		data->dcell_array[(row + data->offset) * data->cols_intern +
-				  col + data->offset];
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief Returns 1 if the value of N_array_2d struct at postion col, row
- * is of type null, otherwise 0
- *
- * This function checks automatically the type of the array and checks for the
- * data type null value.
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \return int - 1 = is null, 0 otherwise
- * */
-int N_is_array_2d_value_null(N_array_2d * data, int col, int row)
-{
-
-    if (data->offset == 0) {
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_2d_value_null: null value is of type CELL at pos [%i][%i]",
-		    col, row);
-	    return Rast_is_null_value((void *)
-				   &(data->
-				     cell_array[row * data->cols_intern +
-						col]), CELL_TYPE);
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_2d_value_null: null value is of type FCELL at pos [%i][%i]",
-		    col, row);
-	    return Rast_is_null_value((void *)
-				   &(data->
-				     fcell_array[row * data->cols_intern +
-						 col]), FCELL_TYPE);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_2d_value_null: null value is of type DCELL at pos [%i][%i]",
-		    col, row);
-	    return Rast_is_null_value((void *)
-				   &(data->
-				     dcell_array[row * data->cols_intern +
-						 col]), DCELL_TYPE);
-	}
-    }
-    else {
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_2d_value_null: null value is of type CELL at pos [%i][%i]",
-		    col, row);
-	    return Rast_is_null_value((void *)
-				   &(data->
-				     cell_array[(row +
-						 data->offset) *
-						data->cols_intern + col +
-						data->offset]), CELL_TYPE);
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_2d_value_null: null value is of type FCELL at pos [%i][%i]",
-		    col, row);
-	    return Rast_is_null_value((void *)
-				   &(data->
-				     fcell_array[(row +
-						  data->offset) *
-						 data->cols_intern + col +
-						 data->offset]), FCELL_TYPE);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_2d_value_null: null value is of type DCELL at pos [%i][%i]",
-		    col, row);
-	    return Rast_is_null_value((void *)
-				   &(data->
-				     dcell_array[(row +
-						  data->offset) *
-						 data->cols_intern + col +
-						 data->offset]), DCELL_TYPE);
-	}
-    }
-
-    return 0;
-}
-
-
-/*!
- * \brief Returns the value of type CELL at position col, row
- *
- * The data array can be of type CELL, FCELL or DCELL, the value will be casted to the CELL type.
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \return CELL
- *
- * */
-CELL N_get_array_2d_c_value(N_array_2d * data, int col, int row)
-{
-    CELL value = 0;
-    FCELL fvalue = 0.0;
-    DCELL dvalue = 0.0;
-
-    switch (data->type) {
-    case CELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&value);
-	return (CELL) value;
-    case FCELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&fvalue);
-	return (CELL) fvalue;
-    case DCELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&dvalue);
-	return (CELL) dvalue;
-    }
-
-    return value;
-}
-
-/*!
- * \brief Returns the value of type FCELL at position col, row
- *
- * The data array can be of type CELL, FCELL or DCELL, the value will be casted to the FCELL type.
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \return FCELL
-
- * */
-FCELL N_get_array_2d_f_value(N_array_2d * data, int col, int row)
-{
-    CELL value = 0;
-    FCELL fvalue = 0.0;
-    DCELL dvalue = 0.0;
-
-    switch (data->type) {
-    case CELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&value);
-	return (FCELL) value;
-    case FCELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&fvalue);
-	return (FCELL) fvalue;
-    case DCELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&dvalue);
-	return (FCELL) dvalue;
-    }
-
-    return fvalue;
-}
-
-/*!
- * \brief Returns the value of type DCELL at position col, row
- *
- * The data array can be of type CELL, FCELL or DCELL, the value will be casted to the DCELL type.
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \return DCELL
- *
- * */
-DCELL N_get_array_2d_d_value(N_array_2d * data, int col, int row)
-{
-    CELL value = 0;
-    FCELL fvalue = 0.0;
-    DCELL dvalue = 0.0;
-
-    switch (data->type) {
-    case CELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&value);
-	return (DCELL) value;
-    case FCELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&fvalue);
-	return (DCELL) fvalue;
-    case DCELL_TYPE:
-	N_get_array_2d_value(data, col, row, (void *)&dvalue);
-	return (DCELL) dvalue;
-    }
-
-    return dvalue;
-
-}
-
-/*!
- * \brief Writes a value to the N_array_2d struct at position col, row
- *
- * The value will be automatically cast to the array type.
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \param value char *
- * \return void
- * */
-void N_put_array_2d_value(N_array_2d * data, int col, int row, char *value)
-{
-
-    G_debug(6, "N_put_array_2d_value: put value to array");
-
-    if (data->offset == 0) {
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    data->cell_array[row * data->cols_intern + col] =
-		*((CELL *) value);
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    data->fcell_array[row * data->cols_intern + col] =
-		*((FCELL *) value);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    data->dcell_array[row * data->cols_intern + col] =
-		*((DCELL *) value);
-	}
-    }
-    else {
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    data->cell_array[(row + data->offset) * data->cols_intern + col +
-			     data->offset] = *((CELL *) value);
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    data->fcell_array[(row + data->offset) * data->cols_intern + col +
-			      data->offset] = *((FCELL *) value);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    data->dcell_array[(row + data->offset) * data->cols_intern + col +
-			      data->offset] = *((DCELL *) value);
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief Writes the null value to the N_array_2d struct at position col, row
- *
- * The null value will be automatically set to the array data type (CELL, FCELL or DCELL).
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \return void
- * */
-void N_put_array_2d_value_null(N_array_2d * data, int col, int row)
-{
-
-    G_debug(6,
-	    "N_put_array_2d_value_null: put null value to array pos [%i][%i]",
-	    col, row);
-
-    if (data->offset == 0) {
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    Rast_set_c_null_value((void *)
-			       &(data->
-				 cell_array[row * data->cols_intern + col]),
-			       1);
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    Rast_set_f_null_value((void *)
-			       &(data->
-				 fcell_array[row * data->cols_intern + col]),
-			       1);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    Rast_set_d_null_value((void *)
-			       &(data->
-				 dcell_array[row * data->cols_intern + col]),
-			       1);
-	}
-    }
-    else {
-	if (data->type == CELL_TYPE && data->cell_array != NULL) {
-	    Rast_set_c_null_value((void *)
-			       &(data->
-				 cell_array[(row +
-					     data->offset) *
-					    data->cols_intern + col +
-					    data->offset]), 1);
-	}
-	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    Rast_set_f_null_value((void *)
-			       &(data->
-				 fcell_array[(row +
-					      data->offset) *
-					     data->cols_intern + col +
-					     data->offset]), 1);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    Rast_set_d_null_value((void *)
-			       &(data->
-				 dcell_array[(row +
-					      data->offset) *
-					     data->cols_intern + col +
-					     data->offset]), 1);
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief Writes a CELL value to the N_array_2d struct at position col, row
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \param value CELL
- * \return void
- * */
-void N_put_array_2d_c_value(N_array_2d * data, int col, int row, CELL value)
-{
-    FCELL fvalue;
-    DCELL dvalue;
-
-    switch (data->type) {
-    case FCELL_TYPE:
-	fvalue = (FCELL) value;
-	N_put_array_2d_value(data, col, row, (char *)&fvalue);
-	return;
-    case DCELL_TYPE:
-	dvalue = (DCELL) value;
-	N_put_array_2d_value(data, col, row, (char *)&dvalue);
-	return;
-    }
-
-    N_put_array_2d_value(data, col, row, (char *)&value);
-
-    return;
-}
-
-/*!
- * \brief Writes a FCELL value to the N_array_2d struct at position col, row
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \param value FCELL
- * \return void
- * */
-void N_put_array_2d_f_value(N_array_2d * data, int col, int row, FCELL value)
-{
-    CELL cvalue;
-    DCELL dvalue;
-
-    switch (data->type) {
-    case CELL_TYPE:
-	cvalue = (CELL) value;
-	N_put_array_2d_value(data, col, row, (char *)&cvalue);
-	return;
-    case DCELL_TYPE:
-	dvalue = (DCELL) value;
-	N_put_array_2d_value(data, col, row, (char *)&dvalue);
-	return;
-    }
-
-    N_put_array_2d_value(data, col, row, (char *)&value);
-
-    return;
-}
-
-/*!
- * \brief Writes a DCELL value to the N_array_2d struct at position col, row
- *
- * \param data N_array_2d *
- * \param col int
- * \param row int
- * \param value DCELL
- * \return void
- * */
-void N_put_array_2d_d_value(N_array_2d * data, int col, int row, DCELL value)
-{
-    CELL cvalue;
-    FCELL fvalue;
-
-    switch (data->type) {
-    case CELL_TYPE:
-	cvalue = (CELL) value;
-	N_put_array_2d_value(data, col, row, (char *)&cvalue);
-	return;
-    case FCELL_TYPE:
-	fvalue = (FCELL) value;
-	N_put_array_2d_value(data, col, row, (char *)&fvalue);
-	return;
-    }
-
-    N_put_array_2d_value(data, col, row, (char *)&value);
-
-    return;
-}
-
-/*!
- * \brief This function writes the data info of the array data to stdout
- *
- * \param data N_array_2d *
- * \return void
- * */
-void N_print_array_2d_info(N_array_2d * data)
-{
-
-    fprintf(stdout, "N_array_2d \n");
-    fprintf(stdout, "Cols %i\n", data->cols);
-    fprintf(stdout, "Rows: %i\n", data->rows);
-    fprintf(stdout, "Array type: %i\n", data->type);
-    fprintf(stdout, "Offset: %i\n", data->offset);
-    fprintf(stdout, "Internal cols: %i\n", data->cols_intern);
-    fprintf(stdout, "Internal rows: %i\n", data->rows_intern);
-    fprintf(stdout, "CELL array pointer: %p\n", data->cell_array);
-    fprintf(stdout, "FCELL array pointer: %p\n", data->fcell_array);
-    fprintf(stdout, "DCELL array pointer: %p\n", data->dcell_array);
-
-
-    return;
-}
-
-/*!
- * \brief Write info and content of the N_array_2d struct to stdout
- *
- * Offsets are ignored
- *
- * \param data N_array_2d *
- * \return void
- * */
-void N_print_array_2d(N_array_2d * data)
-{
-    int i, j;
-
-    N_print_array_2d_info(data);
-
-    for (j = 0 - data->offset; j < data->rows + data->offset; j++) {
-	for (i = 0 - data->offset; i < data->cols + data->offset; i++) {
-	    if (data->type == CELL_TYPE)
-		fprintf(stdout, "%6d ", N_get_array_2d_c_value(data, i, j));
-	    else if (data->type == FCELL_TYPE)
-		fprintf(stdout, "%6.6f ", N_get_array_2d_f_value(data, i, j));
-	    else if (data->type == DCELL_TYPE)
-		printf("%6.6f ", N_get_array_2d_d_value(data, i, j));
-	}
-	fprintf(stdout, "\n");
-    }
-    fprintf(stdout, "\n");
-
-    return;
-}
-
-
-/* ******************** 3D ARRAY FUNCTIONS *********************** */
-
-/*!
- * \brief Allocate memory for a N_array_3d data structure.
- *
- * This functions allocates an array of type N_array_3d and returns a pointer
- * to the new allocated memory.
- * <br><br>
- * The data type of this array set by "type" must be
- * FCELL_TYPE or DCELL_TYPE accordingly to the raster3d map data types.
- * The offsets sets the number of boundary cols, rows and depths.
- * This option is useful to generate homogeneous Neumann boundary conditions around
- * an array or to establish overlapping boundaries. The arrays are initialized with 0 by default.
- * <br><br>
- * If the offset is greater then 0, negative indices are possible.
- * The data structure of a array with 3 depths, rows and cols and an offset of 1
- * will looks like this:
- *
- \verbatim
- 0  0  0  0  0
- 0  0  0  0  0
- 0  0  0  0  0
- 0  0  0  0  0
- 0  0  0  0  0
-
- 0  0  0  0  0
- 0  0  1  2  0
- 0  3  4  5  0
- 0  6  7  8  0
- 0  0  0  0  0
-
- 0  0  0  0  0
- 0  9 10 11  0
- 0 12 13 14  0
- 0 15 16 17  0
- 0  0  0  0  0
-
- 0  0  0  0  0
- 0 18 19 20  0
- 0 21 22 23  0
- 0 24 25 26  0
- 0  0  0  0  0
-
- 0  0  0  0  0
- 0  0  0  0  0
- 0  0  0  0  0
- 0  0  0  0  0
- 0  0  0  0  0
-
- \endverbatim
-
- The depth counts from the bottom to the top.
-
- * <br><br>
- * Internal a one dimensional array is allocated to speed up the memory access.
- * To access the dimensional array with a three dimensional indexing use the provided
- * get and put functions.
- *
- * \param cols int
- * \param rows int
- * \param depths int
- * \param offset int
- * \param type int
- * \return N_array_3d *
- *
- * */
-N_array_3d *N_alloc_array_3d(int cols, int rows, int depths, int offset,
-			     int type)
-{
-    N_array_3d *data = NULL;
-
-    if (rows < 1 || cols < 1 || depths < 1)
-	G_fatal_error
-	    ("N_alloc_array_3d: depths, cols and rows should be > 0");
-
-    if (type != DCELL_TYPE && type != FCELL_TYPE)
-	G_fatal_error
-	    ("N_alloc_array_3d: Wrong data type, should be FCELL_TYPE or DCELL_TYPE");
-
-    data = (N_array_3d *) G_calloc(1, sizeof(N_array_3d));
-
-    data->cols = cols;
-    data->rows = rows;
-    data->depths = depths;
-    data->type = type;
-    data->offset = offset;
-    data->rows_intern = rows + 2 * offset;
-    data->cols_intern = cols + 2 * offset;
-    data->depths_intern = depths + 2 * offset;
-    data->fcell_array = NULL;
-    data->dcell_array = NULL;
-
-    if (data->type == FCELL_TYPE) {
-	data->fcell_array =
-	    (float *)G_calloc((size_t) data->depths_intern * data->rows_intern *
-			      data->cols_intern, sizeof(float));
-	G_debug(3,
-		"N_alloc_array_3d: float array allocated rows_intern %i cols_intern %i depths_intern %i offset %i",
-		data->rows_intern, data->cols_intern, data->depths_intern,
-		data->offset = offset);
-    }
-    else if (data->type == DCELL_TYPE) {
-	data->dcell_array =
-	    (double *)G_calloc((size_t) data->depths_intern * data->rows_intern *
-			       data->cols_intern, sizeof(double));
-	G_debug(3,
-		"N_alloc_array_3d: double array allocated rows_intern %i cols_intern %i depths_intern %i offset %i",
-		data->rows_intern, data->cols_intern, data->depths_intern,
-		data->offset = offset);
-    }
-
-    return data;
-}
-
-/*!
- * \brief Release the memory of a N_array_3d
- *
- * \param data N_array_3d *
- * \return void
- * */
-void N_free_array_3d(N_array_3d * data)
-{
-
-    if (data != NULL) {
-	G_debug(3, "N_free_array_3d: free N_array_3d");
-
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    G_free(data->fcell_array);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    G_free(data->dcell_array);
-	}
-
-	G_free(data);
-	data = NULL;
-
-    }
-
-    return;
-}
-
-/*!
- * \brief Return the data type of the N_array_3d
- *
- * The data type can be FCELL_TYPE and DCELL_TYPE accordingly to the raster map data types.
- *
- * \param array N_array_3d *
- * \return type int -- FCELL_TYPE or DCELL_TYPE
- * */
-int N_get_array_3d_type(N_array_3d * array)
-{
-    return array->type;
-}
-
-
-/*!
- * \brief This function writes the value of N_array_3d data at position col, row, depth
- *        to the variable value
- *
- * The value must be from the same type as the array. Otherwise you will risk data losses.
- *
- * \param data N_array_3d *
- * \param col int
- * \param row int
- * \param depth int
- * \param value void *
- * \return void
- * */
-void
-N_get_array_3d_value(N_array_3d * data, int col, int row, int depth,
-		     void *value)
-{
-
-    if (data->offset == 0) {
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    *((float *)value) =
-		data->fcell_array[depth *
-				  (data->rows_intern * data->cols_intern) +
-				  row * data->cols_intern + col];
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    *((double *)value) =
-		data->dcell_array[depth *
-				  (data->rows_intern * data->cols_intern) +
-				  row * data->cols_intern + col];
-	}
-    }
-    else {
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    *((float *)value) =
-		data->fcell_array[(depth + data->offset) *
-				  (data->rows_intern * data->cols_intern) +
-				  (row + data->offset) * data->cols_intern +
-				  (col + data->offset)];
-
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    *((double *)value) =
-		data->dcell_array[(depth + data->offset) *
-				  (data->rows_intern * data->cols_intern) +
-				  (row + data->offset) * data->cols_intern +
-				  (col + data->offset)];
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief This function returns 1 if value of N_array_3d data at position col, row, depth
- * is of type null, otherwise 0
- *
- * This function checks automatically the type of the array and checks for the
- * data type null value.
- *
- * \param data N_array_3d *
- * \param col int
- * \param row int
- * \param depth int
- * \return void
- * */
-int N_is_array_3d_value_null(N_array_3d * data, int col, int row, int depth)
-{
-
-    if (data->offset == 0) {
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_3d_value_null: null value is of type DCELL_TYPE at pos [%i][%i][%i]",
-		    depth, row, col);
-	    return Rast3d_is_null_value_num((void *)
-				      &(data->
-					fcell_array[depth *
-						    (data->rows_intern *
-						     data->cols_intern) +
-						    row * data->cols_intern +
-						    col]), FCELL_TYPE);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_3d_value_null: null value is of type DCELL_TYPE at pos [%i][%i][%i]",
-		    depth, row, col);
-	    return Rast3d_is_null_value_num((void *)
-				      &(data->
-					dcell_array[depth *
-						    (data->rows_intern *
-						     data->cols_intern) +
-						    row * data->cols_intern +
-						    col]), DCELL_TYPE);
-	}
-    }
-    else {
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_3d_value_null: null value is of type DCELL_TYPE at pos [%i][%i][%i]",
-		    depth, row, col);
-	    return Rast3d_is_null_value_num((void *)
-				      &(data->
-					fcell_array[(depth +
-						     data->offset) *
-						    (data->rows_intern *
-						     data->cols_intern) +
-						    (row + data->offset)
-						    * data->cols_intern +
-						    (col + data->offset)]),
-				      FCELL_TYPE);
-
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    G_debug(6,
-		    "N_is_array_3d_value_null: null value is of type DCELL_TYPE at pos [%i][%i][%i]",
-		    depth, row, col);
-	    return Rast3d_is_null_value_num((void *)
-				      &(data->
-					dcell_array[(depth +
-						     data->offset) *
-						    (data->rows_intern *
-						     data->cols_intern) +
-						    (row +
-						     data->offset) *
-						    data->cols_intern + (col +
-									 data->
-									 offset)]),
-				      DCELL_TYPE);
-	}
-    }
-
-    return 0;
-}
-
-/*!
- * \brief This function returns the value of type float at position col, row, depth
- *
- * The data type can be FCELL_TYPE or DCELL_TYPE accordingly to the raster map data types.
- *
- * \param data N_array_3d *
- * \param col int
- * \param row int
- * \param depth int
- * \return float
- *
- * */
-float N_get_array_3d_f_value(N_array_3d * data, int col, int row, int depth)
-{
-    float fvalue = 0.0;
-    double dvalue = 0.0;
-
-    switch (data->type) {
-    case FCELL_TYPE:
-	N_get_array_3d_value(data, col, row, depth, (void *)&fvalue);
-	return (float)fvalue;
-    case DCELL_TYPE:
-	N_get_array_3d_value(data, col, row, depth, (void *)&dvalue);
-	return (float)dvalue;
-    }
-
-    return fvalue;
-}
-
-/*!
- * \brief This function returns the value of type float at position col, row, depth
- *
- * The data type can be FCELL_TYPE or DCELL_TYPE accordingly to the raster map data types.
- *
- * \param data N_array_3d *
- * \param col int
- * \param row int
- * \param depth int
- * \return double
- *
- * */
-double N_get_array_3d_d_value(N_array_3d * data, int col, int row, int depth)
-{
-    float fvalue = 0.0;
-    double dvalue = 0.0;
-
-    switch (data->type) {
-
-    case FCELL_TYPE:
-	N_get_array_3d_value(data, col, row, depth, (void *)&fvalue);
-	return (double)fvalue;
-    case DCELL_TYPE:
-	N_get_array_3d_value(data, col, row, depth, (void *)&dvalue);
-	return (double)dvalue;
-    }
-
-    return dvalue;
-}
-
-/*!
- * \brief This function writes a value to the N_array_3d data at position col, row, depth
- *
- * The value will be automatically cast to the array type.
- *
- * \param data N_array_3d *
- * \param col int
- * \param row int
- * \param depth int
- * \param value cahr *
- * \return void
- * */
-void
-N_put_array_3d_value(N_array_3d * data, int col, int row, int depth,
-		     char *value)
-{
-
-    G_debug(6, "N_put_array_3d_value: put value to array at pos [%i][%i][%i]",
-	    depth, row, col);
-
-    if (data->offset == 0) {
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    data->fcell_array[depth *
-			      (data->rows_intern * data->cols_intern) +
-			      row * data->cols_intern + col]
-		= *((float *)value);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-
-	    data->dcell_array[depth *
-			      (data->rows_intern * data->cols_intern) +
-			      row * data->cols_intern + col]
-		= *((double *)value);
-	}
-    }
-    else {
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    data->fcell_array[(depth + data->offset) *
-			      (data->rows_intern * data->cols_intern) + (row +
-									 data->
-									 offset)
-			      * data->cols_intern + (col + data->offset)] =
-		*((float *)value);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    data->dcell_array[(depth + data->offset) *
-			      (data->rows_intern * data->cols_intern) + (row +
-									 data->
-									 offset)
-			      * data->cols_intern + (col + data->offset)] =
-		*((double *)value);
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief This function writes a null value to the N_array_3d data at position col, row, depth
- *
- * The null value will be automatically set to the array type.
- *
- * \param data N_array_3d *
- * \param col int
- * \param row int
- * \param depth int
- * \return void
- * */
-void N_put_array_3d_value_null(N_array_3d * data, int col, int row, int depth)
-{
-
-    G_debug(6,
-	    "N_put_array_3d_value_null: put null value to array at pos [%i][%i][%i]",
-	    depth, row, col);
-
-    if (data->offset == 0) {
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    Rast3d_set_null_value((void *)
-			     &(data->
-			       fcell_array[depth *
-					   (data->rows_intern *
-					    data->cols_intern) +
-					   row * data->cols_intern + col]), 1,
-			     FCELL_TYPE);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    Rast3d_set_null_value((void *)
-			     &(data->
-			       dcell_array[depth *
-					   (data->rows_intern *
-					    data->cols_intern) +
-					   row * data->cols_intern + col]), 1,
-			     DCELL_TYPE);
-	}
-    }
-    else {
-	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
-	    Rast3d_set_null_value((void *)
-			     &(data->
-			       fcell_array[(depth +
-					    data->offset) *
-					   (data->rows_intern *
-					    data->cols_intern) + (row +
-								  data->
-								  offset) *
-					   data->cols_intern + (col +
-								data->
-								offset)]), 1,
-			     FCELL_TYPE);
-	}
-	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
-	    Rast3d_set_null_value((void *)
-			     &(data->
-			       dcell_array[(depth +
-					    data->offset) *
-					   (data->rows_intern *
-					    data->cols_intern) + (row +
-								  data->
-								  offset) *
-					   data->cols_intern + (col +
-								data->
-								offset)]), 1,
-			     DCELL_TYPE);
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief This function writes a float value to the N_array_3d data at position col, row, depth
- *
- * \param data N_array_3d *
- * \param col int
- * \param row int
- * \param depth int
- * \param value float
- * \return void
- * */
-void
-N_put_array_3d_f_value(N_array_3d * data, int col, int row, int depth,
-		       float value)
-{
-    double dval;
-
-    if (data->type == DCELL_TYPE) {
-	dval = (double)value;
-	N_put_array_3d_value(data, col, row, depth, (void *)&dval);
-    }
-    else {
-	N_put_array_3d_value(data, col, row, depth, (void *)&value);
-    }
-
-    return;
-}
-
-/*!
- * \brief Writes a double value to the N_array_3d struct at position col, row, depth
- *
- * \param data N_array_3d *
- * \param col int
- * \param row int
- * \param depth int
- * \param value double
- * \return void
- * */
-void
-N_put_array_3d_d_value(N_array_3d * data, int col, int row, int depth,
-		       double value)
-{
-    float fval;
-
-    if (data->type == FCELL_TYPE) {
-	fval = (double)value;
-	N_put_array_3d_value(data, col, row, depth, (void *)&fval);
-    }
-    else {
-	N_put_array_3d_value(data, col, row, depth, (void *)&value);
-    }
-
-    return;
-}
-
-/*!
- * \brief Write the info of the array to stdout
- *
- * \param data N_array_3d *
- * \return void
- * */
-void N_print_array_3d_info(N_array_3d * data)
-{
-
-    fprintf(stdout, "N_array_3d \n");
-    fprintf(stdout, "Cols %i\n", data->cols);
-    fprintf(stdout, "Rows: %i\n", data->rows);
-    fprintf(stdout, "Depths: %i\n", data->depths);
-    fprintf(stdout, "Array type: %i\n", data->type);
-    fprintf(stdout, "Offset: %i\n", data->offset);
-    fprintf(stdout, "Internal cols: %i\n", data->cols_intern);
-    fprintf(stdout, "Internal rows: %i\n", data->rows_intern);
-    fprintf(stdout, "Internal depths: %i\n", data->depths_intern);
-    fprintf(stdout, "FCELL array pointer: %p\n", data->fcell_array);
-    fprintf(stdout, "DCELL array pointer: %p\n", data->dcell_array);
-
-    return;
-}
-
-/*!
- * \brief Write info and content of the array data to stdout
- *
- * Offsets are ignored
- *
- * \param data N_array_2d *
- * \return void
- * */
-void N_print_array_3d(N_array_3d * data)
-{
-    int i, j, k;
-
-    N_print_array_3d_info(data);
-
-    for (k = 0; k < data->depths; k++) {
-	for (j = 0; j < data->rows; j++) {
-	    for (i = 0; i < data->cols; i++) {
-		if (data->type == FCELL_TYPE)
-		    printf("%6.6f ", N_get_array_3d_f_value(data, i, j, k));
-		else if (data->type == DCELL_TYPE)
-		    printf("%6.6f ", N_get_array_3d_d_value(data, i, j, k));
-	    }
-	    printf("\n");
-	}
-	printf("\n");
-    }
-    printf("\n");
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_arrays_calc.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_arrays_calc.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_arrays_calc.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,889 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:     	Higher level array managment functions 
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-#include <grass/raster.h>
-#include <grass/glocale.h>
-
-
-/* ******************** 2D ARRAY FUNCTIONS *********************** */
-
-/*!
- * \brief Copy the source N_array_2d struct to the target N_array_2d struct
- *
- * The arrays must have the same size and the same offset.
- *
- * The array types can be mixed, the values are automatically casted
- * and the null values are set accordingly.
- * <br><br>
- * If you copy a cell array into a dcell array, the values are casted to dcell and 
- * the null values are converted from cell-null to dcell-null
- * <br><br>
- * This function can be called in a parallel region defined with OpenMP.
- * The copy loop is parallelize with a openmp for pragma.
- *
- * \param source N_array_2d *
- * \param target N_array_2d *
- * \return void
- * */
-void N_copy_array_2d(N_array_2d * source, N_array_2d * target)
-{
-    int i;
-    int null = 0;
-
-#pragma omp single
-    {
-	if (source->cols_intern != target->cols_intern)
-	    G_fatal_error
-		("N_copy_array_2d: the arrays are not of equal size");
-
-	if (source->rows_intern != target->rows_intern)
-	    G_fatal_error
-		("N_copy_array_2d: the arrays are not of equal size");
-
-	G_debug(3,
-		"N_copy_array_2d: copy source array to target array size %i",
-		source->cols_intern * source->rows_intern);
-    }
-
-#pragma omp for
-    for (i = 0; i < source->cols_intern * source->rows_intern; i++) {
-	null = 0;
-	if (source->type == CELL_TYPE) {
-	    if (Rast_is_c_null_value((void *)&source->cell_array[i]))
-		null = 1;
-
-	    if (target->type == CELL_TYPE) {
-		target->cell_array[i] = source->cell_array[i];
-	    }
-	    if (target->type == FCELL_TYPE) {
-		if (null)
-		    Rast_set_f_null_value((void *)&(target->fcell_array[i]), 1);
-		else
-		    target->fcell_array[i] = (FCELL) source->cell_array[i];
-	    }
-	    if (target->type == DCELL_TYPE) {
-		if (null)
-		    Rast_set_d_null_value((void *)&(target->dcell_array[i]), 1);
-		else
-		    target->dcell_array[i] = (DCELL) source->cell_array[i];
-	    }
-
-	}
-	if (source->type == FCELL_TYPE) {
-	    if (Rast_is_f_null_value((void *)&source->fcell_array[i]))
-		null = 1;
-
-	    if (target->type == CELL_TYPE) {
-		if (null)
-		    Rast_set_c_null_value((void *)&(target->cell_array[i]), 1);
-		else
-		    target->cell_array[i] = (CELL) source->fcell_array[i];
-	    }
-	    if (target->type == FCELL_TYPE) {
-		target->fcell_array[i] = source->fcell_array[i];
-	    }
-	    if (target->type == DCELL_TYPE) {
-		if (null)
-		    Rast_set_d_null_value((void *)&(target->dcell_array[i]), 1);
-		else
-		    target->dcell_array[i] = (DCELL) source->fcell_array[i];
-	    }
-	}
-	if (source->type == DCELL_TYPE) {
-	    if (Rast_is_d_null_value((void *)&source->dcell_array[i]))
-		null = 1;
-
-	    if (target->type == CELL_TYPE) {
-		if (null)
-		    Rast_set_c_null_value((void *)&(target->cell_array[i]), 1);
-		else
-		    target->cell_array[i] = (CELL) source->dcell_array[i];
-	    }
-	    if (target->type == FCELL_TYPE) {
-		if (null)
-		    Rast_set_f_null_value((void *)&(target->fcell_array[i]), 1);
-		else
-		    target->fcell_array[i] = (FCELL) source->dcell_array[i];
-	    }
-	    if (target->type == DCELL_TYPE) {
-		target->dcell_array[i] = source->dcell_array[i];
-	    }
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief Calculate the norm of the two input arrays
- *
- * The norm can be of type N_MAXIMUM_NORM or N_EUKLID_NORM.
- * All arrays must have equal sizes and offsets.
- * The complete data array inclusively offsets is used for norm calucaltion.
- * Only non-null values are used to calcualte the norm.
- *
-
- * \param a N_array_2d *
- * \param b N_array_2d *
- * \param type the type of the norm -> N_MAXIMUM_NORM, N_EUKLID_NORM
- * \return double the calculated norm
- * */
-double N_norm_array_2d(N_array_2d * a, N_array_2d * b, int type)
-{
-    int i = 0;
-    double norm = 0.0, tmp = 0.0;
-    double v1 = 0.0, v2 = 0.0;
-
-    if (a->cols_intern != b->cols_intern)
-	G_fatal_error("N_norm_array_2d: the arrays are not of equal size");
-
-    if (a->rows_intern != b->rows_intern)
-	G_fatal_error("N_norm_array_2d: the arrays are not of equal size");
-
-    G_debug(3, "N_norm_array_2d: norm of a and b size %i",
-	    a->cols_intern * a->rows_intern);
-
-    for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
-	v1 = 0.0;
-	v2 = 0.0;
-
-	if (a->type == CELL_TYPE) {
-	    if (!Rast_is_f_null_value((void *)&(a->cell_array[i])))
-		v1 = (double)a->cell_array[i];
-	}
-	if (a->type == FCELL_TYPE) {
-	    if (!Rast_is_f_null_value((void *)&(a->fcell_array[i])))
-		v1 = (double)a->fcell_array[i];
-	}
-	if (a->type == DCELL_TYPE) {
-	    if (!Rast_is_f_null_value((void *)&(a->dcell_array[i])))
-		v1 = (double)a->dcell_array[i];
-	}
-	if (b->type == CELL_TYPE) {
-	    if (!Rast_is_f_null_value((void *)&(b->cell_array[i])))
-		v2 = (double)b->cell_array[i];
-	}
-	if (b->type == FCELL_TYPE) {
-	    if (!Rast_is_f_null_value((void *)&(b->fcell_array[i])))
-		v2 = (double)b->fcell_array[i];
-	}
-	if (b->type == DCELL_TYPE) {
-	    if (!Rast_is_f_null_value((void *)&(b->dcell_array[i])))
-		v2 = (double)b->dcell_array[i];
-	}
-
-	if (type == N_MAXIMUM_NORM) {
-	    tmp = fabs(v2 - v1);
-	    if ((tmp > norm))
-		norm = tmp;
-	}
-	if (type == N_EUKLID_NORM) {
-	    norm += fabs(v2 - v1);
-	}
-    }
-
-    return norm;
-}
-
-/*!
- * \brief Calculate basic statistics of the N_array_2d struct 
- *
- * Calculates the minimum, maximum, sum and the number of 
- * non null values. The array offset can be included in the calculation.
- *
- * \param a N_array_2d * - input array
- * \param min double* - variable to store the computed minimum
- * \param max double* - variable to store the computed maximum
- * \param sum double* - variable to store the computed sum
- * \param nonull int* - variable to store the number of non null values
- * \param withoffset - if 1 include offset values in statistic calculation, 0 otherwise 
- * \return void
- * */
-void N_calc_array_2d_stats(N_array_2d * a, double *min, double *max,
-			   double *sum, int *nonull, int withoffset)
-{
-    int i, j;
-    double val;
-
-    *sum = 0.0;
-    *nonull = 0;
-
-    if (withoffset == 1) {
-
-	*min =
-	    (double)N_get_array_2d_d_value(a, 0 - a->offset, 0 - a->offset);
-	*max =
-	    (double)N_get_array_2d_d_value(a, 0 - a->offset, 0 - a->offset);
-
-	for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
-	    for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
-		if (!N_is_array_2d_value_null(a, i, j)) {
-		    val = (double)N_get_array_2d_d_value(a, i, j);
-		    if (*min > val)
-			*min = val;
-		    if (*max < val)
-			*max = val;
-		    *sum += val;
-		    (*nonull)++;
-		}
-	    }
-	}
-    }
-    else {
-
-	*min = (double)N_get_array_2d_d_value(a, 0, 0);
-	*max = (double)N_get_array_2d_d_value(a, 0, 0);
-
-
-	for (j = 0; j < a->rows; j++) {
-	    for (i = 0; i < a->cols; i++) {
-		if (!N_is_array_2d_value_null(a, i, j)) {
-		    val = (double)N_get_array_2d_d_value(a, i, j);
-		    if (*min > val)
-			*min = val;
-		    if (*max < val)
-			*max = val;
-		    *sum += val;
-		    (*nonull)++;
-		}
-	    }
-	}
-    }
-
-    G_debug(3,
-	    "N_calc_array_2d_stats: compute array stats, min %g, max %g, sum %g, nonull %i",
-	    *min, *max, *sum, *nonull);
-    return;
-}
-
-
-/*!
- * \brief Perform calculations with two input arrays, 
- * the result is written to a third array.
- *
- * All arrays must have equal sizes and offsets.
- * The complete data array inclusively offsets is used for calucaltions.
- * Only non-null values are computed. If one array value is null, 
- * the result array value will be null too.
- * <br><br>
- * If a division with zero is detected, the resulting arrays 
- * value will set to null and not to NaN.
- * <br><br>
- * The result array is optional, if the result arrays points to NULL,
- * a new array will be allocated with the largest arrays data type
- * (CELL, FCELL or DCELL) used by the input arrays.
- * <br><br>
- * the array computations can be of the following forms:
- *
- * <ul>
- * <li>result = a + b -> N_ARRAY_SUM</li>
- * <li>result = a - b -> N_ARRAY_DIF</li>
- * <li>result = a * b -> N_ARRAY_MUL</li>
- * <li>result = a / b -> N_ARRAY_DIV</li>
- * </ul>
- *
- * \param a N_array_2d * - first input array
- * \param b N_array_2d * - second input array
- * \param result N_array_2d * - the optional result array
- * \param type  - the type of calculation
- * \return N_array_2d * - the pointer to the result array
- * */
-N_array_2d *N_math_array_2d(N_array_2d * a, N_array_2d * b,
-			    N_array_2d * result, int type)
-{
-    N_array_2d *c;
-    int i, j, setnull = 0;
-    double va = 0.0, vb = 0.0, vc = 0.0;	/*variables used for calculation */
-
-    /*Set the pointer */
-    c = result;
-
-#pragma omp single
-    {
-	/*Check the array sizes */
-	if (a->cols_intern != b->cols_intern)
-	    G_fatal_error
-		("N_math_array_2d: the arrays are not of equal size");
-	if (a->rows_intern != b->rows_intern)
-	    G_fatal_error
-		("N_math_array_2d: the arrays are not of equal size");
-	if (a->offset != b->offset)
-	    G_fatal_error
-		("N_math_array_2d: the arrays have different offsets");
-
-	G_debug(3, "N_math_array_2d: mathematical calculations, size: %i",
-		a->cols_intern * a->rows_intern);
-
-	/*if the result array is null, allocate a new one, use the 
-	 * largest data type of the input arrays*/
-	if (c == NULL) {
-	    if (a->type == DCELL_TYPE || b->type == DCELL_TYPE) {
-		c = N_alloc_array_2d(a->cols, a->rows, a->offset, DCELL_TYPE);
-		G_debug(3,
-			"N_math_array_2d: array of type DCELL_TYPE created");
-	    }
-	    else if (a->type == FCELL_TYPE || b->type == FCELL_TYPE) {
-		c = N_alloc_array_2d(a->cols, a->rows, a->offset, FCELL_TYPE);
-		G_debug(3,
-			"N_math_array_2d: array of type FCELL_TYPE created");
-	    }
-	    else {
-		c = N_alloc_array_2d(a->cols, a->rows, a->offset, CELL_TYPE);
-		G_debug(3,
-			"N_math_array_2d: array of type CELL_TYPE created");
-	    }
-	}
-	else {
-	    /*Check the array sizes */
-	    if (a->cols_intern != c->cols_intern)
-		G_fatal_error
-		    ("N_math_array_2d: the arrays are not of equal size");
-	    if (a->rows_intern != c->rows_intern)
-		G_fatal_error
-		    ("N_math_array_2d: the arrays are not of equal size");
-	    if (a->offset != c->offset)
-		G_fatal_error
-		    ("N_math_array_2d: the arrays have different offsets");
-	}
-    }
-
-#pragma omp for private(va, vb, vc, setnull)
-    for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
-	for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
-	    if (!N_is_array_2d_value_null(a, i, j) &&
-		!N_is_array_2d_value_null(b, i, j)) {
-		/*we always calulate internally with double values */
-		va = (double)N_get_array_2d_d_value(a, i, j);
-		vb = (double)N_get_array_2d_d_value(b, i, j);
-		vc = 0;
-		setnull = 0;
-
-		switch (type) {
-		case N_ARRAY_SUM:
-		    vc = va + vb;
-		    break;
-		case N_ARRAY_DIF:
-		    vc = va - vb;
-		    break;
-		case N_ARRAY_MUL:
-		    vc = va * vb;
-		    break;
-		case N_ARRAY_DIV:
-		    if (vb != 0)
-			vc = va / vb;
-		    else
-			setnull = 1;
-		    break;
-		}
-
-		if (c->type == CELL_TYPE) {
-		    if (setnull)
-			N_put_array_2d_value_null(c, i, j);
-		    else
-			N_put_array_2d_c_value(c, i, j, (CELL) vc);
-		}
-		if (c->type == FCELL_TYPE) {
-		    if (setnull)
-			N_put_array_2d_value_null(c, i, j);
-		    else
-			N_put_array_2d_f_value(c, i, j, (FCELL) vc);
-		}
-		if (c->type == DCELL_TYPE) {
-		    if (setnull)
-			N_put_array_2d_value_null(c, i, j);
-		    else
-			N_put_array_2d_d_value(c, i, j, (DCELL) vc);
-		}
-
-	    }
-	    else {
-		N_put_array_2d_value_null(c, i, j);
-	    }
-	}
-    }
-
-    return c;
-}
-
-/*!
- * \brief Convert all null values to zero values
- *
- * The complete data array inclusively offsets is used.
- * The array data types are automatically recognized.
- *
- * \param a N_array_2d *
- * \return int - number of replaced values
- * */
-int N_convert_array_2d_null_to_zero(N_array_2d * a)
-{
-    int i = 0, count = 0;
-
-    G_debug(3, "N_convert_array_2d_null_to_zero: convert array of size %i",
-	    a->cols_intern * a->rows_intern);
-
-    if (a->type == CELL_TYPE)
-	for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
-	    if (Rast_is_c_null_value((void *)&(a->cell_array[i]))) {
-		a->cell_array[i] = 0;
-		count++;
-	    }
-	}
-
-    if (a->type == FCELL_TYPE)
-	for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
-	    if (Rast_is_f_null_value((void *)&(a->fcell_array[i]))) {
-		a->fcell_array[i] = 0.0;
-		count++;
-	    }
-	}
-
-
-    if (a->type == DCELL_TYPE)
-	for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
-	    if (Rast_is_d_null_value((void *)&(a->dcell_array[i]))) {
-		a->dcell_array[i] = 0.0;
-		count++;
-	    }
-	}
-
-
-    if (a->type == CELL_TYPE)
-	G_debug(2,
-		"N_convert_array_2d_null_to_zero: %i values of type CELL_TYPE are converted",
-		count);
-    if (a->type == FCELL_TYPE)
-	G_debug(2,
-		"N_convert_array_2d_null_to_zero: %i valuess of type FCELL_TYPE are converted",
-		count);
-    if (a->type == DCELL_TYPE)
-	G_debug(2,
-		"N_convert_array_2d_null_to_zero: %i valuess of type DCELL_TYPE are converted",
-		count);
-
-    return count;
-}
-
-/* ******************** 3D ARRAY FUNCTIONS *********************** */
-
-/*!
- * \brief Copy the source N_array_3d struct to the target N_array_3d struct
- *
- * The arrays must have the same size and the same offset.
- *
- * The array data types can be mixed, the values are automatically casted
- * and the null values are set accordingly.
- *
- * If you copy a float array to a double array, the values are casted to DCELL and 
- * the null values are converted from FCELL-null to DCELL-null
- *
- * \param source N_array_3d *
- * \param target N_array_3d *
- * \return void
- * */
-void N_copy_array_3d(N_array_3d * source, N_array_3d * target)
-{
-    int i;
-    int null;
-
-    if (source->cols_intern != target->cols_intern)
-	G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
-
-    if (source->rows_intern != target->rows_intern)
-	G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
-
-    if (source->depths_intern != target->depths_intern)
-	G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
-
-
-    G_debug(3, "N_copy_array_3d: copy source array to target array size %i",
-	    source->cols_intern * source->rows_intern *
-	    source->depths_intern);
-
-    for (i = 0;
-	 i <
-	 source->cols_intern * source->rows_intern * source->depths_intern;
-	 i++) {
-	null = 0;
-	if (source->type == FCELL_TYPE) {
-	    if (Rast3d_is_null_value_num
-		((void *)&(source->fcell_array[i]), FCELL_TYPE))
-		null = 1;
-
-	    if (target->type == FCELL_TYPE) {
-		target->fcell_array[i] = source->fcell_array[i];
-	    }
-	    if (target->type == DCELL_TYPE) {
-		if (null)
-		    Rast3d_set_null_value((void *)&(target->dcell_array[i]), 1,
-				     DCELL_TYPE);
-		else
-		    target->dcell_array[i] = (double)source->fcell_array[i];
-	    }
-
-	}
-	if (source->type == DCELL_TYPE) {
-	    if (Rast3d_is_null_value_num
-		((void *)&(source->dcell_array[i]), DCELL_TYPE))
-		null = 1;
-
-	    if (target->type == FCELL_TYPE) {
-		if (null)
-		    Rast3d_set_null_value((void *)&(target->fcell_array[i]), 1,
-				     FCELL_TYPE);
-		else
-		    target->fcell_array[i] = (float)source->dcell_array[i];
-	    }
-	    if (target->type == DCELL_TYPE) {
-		target->dcell_array[i] = source->dcell_array[i];
-	    }
-	}
-    }
-
-    return;
-}
-
-
-/*!
- * \brief Calculate the norm of the two input arrays
- *
- * The norm can be of type N_MAXIMUM_NORM or N_EUKLID_NORM.
- * All arrays must have equal sizes and offsets.
- * The complete data array inclusively offsets is used for norm calucaltion.
- * Only non-null values are used to calcualte the norm.
- *
- * \param a N_array_3d *
- * \param b N_array_3d *
- * \param type the type of the norm -> N_MAXIMUM_NORM, N_EUKLID_NORM
- * \return double the calculated norm
- * */
-double N_norm_array_3d(N_array_3d * a, N_array_3d * b, int type)
-{
-    int i = 0;
-    double norm = 0.0, tmp = 0.0;
-    double v1 = 0.0, v2 = 0.0;
-
-    if (a->cols_intern != b->cols_intern)
-	G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
-
-    if (a->rows_intern != b->rows_intern)
-	G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
-
-    if (a->depths_intern != b->depths_intern)
-	G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
-
-    G_debug(3, "N_norm_array_3d: norm of a and b size %i",
-	    a->cols_intern * a->rows_intern * a->depths_intern);
-
-    for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern; i++) {
-	v1 = 0.0;
-	v2 = 0.0;
-
-	if (a->type == FCELL_TYPE) {
-	    if (!Rast3d_is_null_value_num((void *)&(a->fcell_array[i]), FCELL_TYPE))
-		v1 = (double)a->fcell_array[i];
-	}
-	if (a->type == DCELL_TYPE) {
-	    if (!Rast3d_is_null_value_num((void *)&(a->dcell_array[i]), DCELL_TYPE))
-		v1 = (double)a->dcell_array[i];
-	}
-	if (b->type == FCELL_TYPE) {
-	    if (!Rast3d_is_null_value_num((void *)&(b->fcell_array[i]), FCELL_TYPE))
-		v2 = (double)b->fcell_array[i];
-	}
-	if (b->type == DCELL_TYPE) {
-	    if (!Rast3d_is_null_value_num((void *)&(b->dcell_array[i]), DCELL_TYPE))
-		v2 = (double)b->dcell_array[i];
-	}
-
-	if (type == N_MAXIMUM_NORM) {
-	    tmp = fabs(v2 - v1);
-	    if ((tmp > norm))
-		norm = tmp;
-	}
-	if (type == N_EUKLID_NORM) {
-	    norm += fabs(v2 - v1);
-	}
-    }
-
-    return norm;
-}
-
-/*!
- * \brief Calculate basic statistics of the N_array_3d struct
- *
- * Calculates the minimum, maximum, sum and the number of 
- * non null values. The array offset can be included in the statistical calculation.
- *
- * \param a N_array_3d * - input array
- * \param min double* - variable to store the computed minimum
- * \param max double* - variable to store the computed maximum
- * \param sum double* - variable to store the computed sum
- * \param nonull int* - variable to store the number of non null values
- * \param withoffset - if 1 include offset values in statistic calculation, 0 otherwise 
- * \return void
- * */
-void N_calc_array_3d_stats(N_array_3d * a, double *min, double *max,
-			   double *sum, int *nonull, int withoffset)
-{
-    int i, j, k;
-    double val;
-
-    *sum = 0.0;
-    *nonull = 0;
-
-    if (withoffset == 1) {
-
-	*min =
-	    (double)N_get_array_3d_d_value(a, 0 - a->offset, 0 - a->offset,
-					   0 - a->offset);
-	*max =
-	    (double)N_get_array_3d_d_value(a, 0 - a->offset, 0 - a->offset,
-					   0 - a->offset);
-
-	for (k = 0 - a->offset; k < a->depths + a->offset; k++) {
-	    for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
-		for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
-		    if (!N_is_array_3d_value_null(a, i, j, k)) {
-			val = (double)N_get_array_3d_d_value(a, i, j, k);
-			if (*min > val)
-			    *min = val;
-			if (*max < val)
-			    *max = val;
-			*sum += val;
-			(*nonull)++;
-		    }
-		}
-	    }
-	}
-    }
-    else {
-
-	*min = (double)N_get_array_3d_d_value(a, 0, 0, 0);
-	*max = (double)N_get_array_3d_d_value(a, 0, 0, 0);
-
-	for (k = 0; k < a->depths; k++) {
-	    for (j = 0; j < a->rows; j++) {
-		for (i = 0; i < a->cols; i++) {
-		    if (!N_is_array_3d_value_null(a, i, j, k)) {
-			val = (double)N_get_array_3d_d_value(a, i, j, k);
-			if (*min > val)
-			    *min = val;
-			if (*max < val)
-			    *max = val;
-			*sum += val;
-			(*nonull)++;
-		    }
-		}
-	    }
-	}
-    }
-
-    G_debug(3,
-	    "N_calc_array_3d_stats: compute array stats, min %g, max %g, sum %g, nonull %i",
-	    *min, *max, *sum, *nonull);
-
-    return;
-}
-
-/*!
- * \brief Perform calculations with two input arrays, 
- * the result is written to a third array.
- *
- * All arrays must have equal sizes and offsets.
- * The complete data array inclusively offsets is used for calucaltions.
- * Only non-null values are used. If one array value is null, 
- * the result array value will be null too.
- * <br><br>
- *
- * If a division with zero is detected, the resulting arrays 
- * value will set to null and not to NaN.
- * <br><br>
- *
- * The result array is optional, if the result arrays points to NULL,
- * a new array will be allocated with the largest arrays data type
- * (FCELL_TYPE or DCELL_TYPE) used by the input arrays.
- * <br><br>
- *
- * the calculations are of the following form:
- *
- * <ul>
- * <li>result = a + b -> N_ARRAY_SUM</li>
- * <li>result = a - b -> N_ARRAY_DIF</li>
- * <li>result = a * b -> N_ARRAY_MUL</li>
- * <li>result = a / b -> N_ARRAY_DIV</li>
- * </ul>
- *
- * \param a N_array_3d * - first input array
- * \param b N_array_3d * - second input array
- * \param result N_array_3d * - the optional result array
- * \param type  - the type of calculation
- * \return N_array_3d * - the pointer to the result array
- * */
-N_array_3d *N_math_array_3d(N_array_3d * a, N_array_3d * b,
-			    N_array_3d * result, int type)
-{
-    N_array_3d *c;
-    int i, j, k, setnull = 0;
-    double va = 0.0, vb = 0.0, vc = 0.0;	/*variables used for calculation */
-
-    /*Set the pointer */
-    c = result;
-
-    /*Check the array sizes */
-    if (a->cols_intern != b->cols_intern)
-	G_fatal_error("N_math_array_3d: the arrays are not of equal size");
-    if (a->rows_intern != b->rows_intern)
-	G_fatal_error("N_math_array_3d: the arrays are not of equal size");
-    if (a->depths_intern != b->depths_intern)
-	G_fatal_error("N_math_array_3d: the arrays are not of equal size");
-    if (a->offset != b->offset)
-	G_fatal_error("N_math_array_3d: the arrays have different offsets");
-
-    G_debug(3, "N_math_array_3d: mathematical calculations, size: %i",
-	    a->cols_intern * a->rows_intern * a->depths_intern);
-
-    /*if the result array is null, allocate a new one, use the 
-     * largest data type of the input arrays*/
-    if (c == NULL) {
-	if (a->type == DCELL_TYPE || b->type == DCELL_TYPE) {
-	    c = N_alloc_array_3d(a->cols, a->rows, a->depths, a->offset,
-				 DCELL_TYPE);
-	    G_debug(3, "N_math_array_3d: array of type DCELL_TYPE created");
-	}
-	else {
-	    c = N_alloc_array_3d(a->cols, a->rows, a->depths, a->offset,
-				 FCELL_TYPE);
-	    G_debug(3, "N_math_array_3d: array of type FCELL_TYPE created");
-	}
-    }
-    else {
-	/*Check the array sizes */
-	if (a->cols_intern != c->cols_intern)
-	    G_fatal_error
-		("N_math_array_3d: the arrays are not of equal size");
-	if (a->rows_intern != c->rows_intern)
-	    G_fatal_error
-		("N_math_array_3d: the arrays are not of equal size");
-	if (a->depths_intern != c->depths_intern)
-	    G_fatal_error
-		("N_math_array_3d: the arrays are not of equal size");
-	if (a->offset != c->offset)
-	    G_fatal_error
-		("N_math_array_3d: the arrays have different offsets");
-    }
-
-    for (k = 0 - a->offset; k < a->depths + a->offset; k++) {
-	for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
-	    for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
-		if (!N_is_array_3d_value_null(a, i, j, k) &&
-		    !N_is_array_3d_value_null(a, i, j, k)) {
-		    /*we always calulate internally with double values */
-		    va = (double)N_get_array_3d_d_value(a, i, j, k);
-		    vb = (double)N_get_array_3d_d_value(b, i, j, k);
-		    vc = 0;
-		    setnull = 0;
-
-		    switch (type) {
-		    case N_ARRAY_SUM:
-			vc = va + vb;
-			break;
-		    case N_ARRAY_DIF:
-			vc = va - vb;
-			break;
-		    case N_ARRAY_MUL:
-			vc = va * vb;
-			break;
-		    case N_ARRAY_DIV:
-			if (vb != 0)
-			    vc = va / vb;
-			else
-			    setnull = 1;
-			break;
-		    }
-
-		    if (c->type == FCELL_TYPE) {
-			if (setnull)
-			    N_put_array_3d_value_null(c, i, j, k);
-			else
-			    N_put_array_3d_f_value(c, i, j, k, (float)vc);
-		    }
-		    if (c->type == DCELL_TYPE) {
-			if (setnull)
-			    N_put_array_3d_value_null(c, i, j, k);
-			else
-			    N_put_array_3d_d_value(c, i, j, k, vc);
-		    }
-		}
-		else {
-		    N_put_array_3d_value_null(c, i, j, k);
-		}
-	    }
-	}
-    }
-
-    return c;
-}
-
-/*!
- * \brief Convert all null values to zero values
- *
- * The complete data array inclusively offsets is used.
- *
- * \param a N_array_3d *
- * \return int - number of replaced null values
- * */
-int N_convert_array_3d_null_to_zero(N_array_3d * a)
-{
-    int i = 0, count = 0;
-
-    G_debug(3, "N_convert_array_3d_null_to_zero: convert array of size %i",
-	    a->cols_intern * a->rows_intern * a->depths_intern);
-
-    if (a->type == FCELL_TYPE)
-	for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern;
-	     i++) {
-	    if (Rast3d_is_null_value_num((void *)&(a->fcell_array[i]), FCELL_TYPE)) {
-		a->fcell_array[i] = 0.0;
-		count++;
-	    }
-	}
-
-    if (a->type == DCELL_TYPE)
-	for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern;
-	     i++) {
-	    if (Rast3d_is_null_value_num((void *)&(a->dcell_array[i]), DCELL_TYPE)) {
-		a->dcell_array[i] = 0.0;
-		count++;
-	    }
-	}
-
-
-    if (a->type == FCELL_TYPE)
-	G_debug(3,
-		"N_convert_array_3d_null_to_zero: %i values of type FCELL_TYPE are converted",
-		count);
-
-    if (a->type == DCELL_TYPE)
-	G_debug(3,
-		"N_convert_array_3d_null_to_zero: %i values of type DCELL_TYPE are converted",
-		count);
-
-    return count;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_arrays_io.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_arrays_io.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_arrays_io.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,467 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:     	IO array managment functions 
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-#include <grass/raster.h>
-#include <grass/glocale.h>
-
-
-/* ******************** 2D ARRAY FUNCTIONS *********************** */
-
-/*!
- * \brief Read a raster map into a N_array_2d structure
- *
- * The raster map will be opened in the current region settings.
- * If no N_array_2d structure is provided (NULL pointer), a new structure will be
- * allocated with the same data type as the raster map and the size of the current region. 
- * The array offset will be set to 0.
- * <br><br>
- * If a N_array_2d structure is provided, the values from the raster map are 
- * casted to the N_array_2d type. The array must have the same size 
- * as the current region. 
- * <br><br>
- * The new created or the provided array are returned.
- * If the reading of the raster map fails, G_fatal_error() will
- * be invoked.
- *
- * \param name * char - the name of an existing raster map
- * \param array * N_array_2d - an existing array or NULL
- * \return N_array_2d * - the existing or new allocated array
- * */
-N_array_2d *N_read_rast_to_array_2d(char *name, N_array_2d * array)
-{
-    int map;			/*The rastermap */
-    int x, y, cols, rows, type;
-    void *rast;
-    void *ptr;
-    struct Cell_head region;
-    N_array_2d *data = array;
-
-    /* Get the active region */
-    G_get_set_window(&region);
-
-    /*set the rows and cols */
-    rows = region.rows;
-    cols = region.cols;
-
-    /*open the raster map */
-    map = Rast_open_old(name, "");
-
-    type = Rast_get_map_type(map);
-
-    /*if the array is NULL create a new one with the data type of the raster map */
-    /*the offset is 0 by default */
-    if (data == NULL) {
-	if (type == DCELL_TYPE) {
-	    data = N_alloc_array_2d(cols, rows, 0, DCELL_TYPE);
-	}
-	if (type == FCELL_TYPE) {
-	    data = N_alloc_array_2d(cols, rows, 0, FCELL_TYPE);
-	}
-	if (type == CELL_TYPE) {
-	    data = N_alloc_array_2d(cols, rows, 0, CELL_TYPE);
-	}
-    }
-    else {
-	/*Check the array sizes */
-	if (data->cols != cols)
-	    G_fatal_error
-		("N_read_rast_to_array_2d: the data array size is different from the current region settings");
-	if (data->rows != rows)
-	    G_fatal_error
-		("N_read_rast_to_array_2d: the data array size is different from the current region settings");
-    }
-
-    rast = Rast_allocate_buf(type);
-
-    G_message(_("Reading raster map <%s> into memory"), name);
-
-    for (y = 0; y < rows; y++) {
-	G_percent(y, rows - 1, 10);
-
-	Rast_get_row(map, rast, y, type);
-
-	for (x = 0, ptr = rast; x < cols;
-	     x++, ptr = G_incr_void_ptr(ptr, Rast_cell_size(type))) {
-	    if (type == CELL_TYPE) {
-		if (Rast_is_c_null_value(ptr)) {
-		    N_put_array_2d_value_null(data, x, y);
-		}
-		else {
-		    if (data->type == CELL_TYPE)
-			N_put_array_2d_c_value(data, x, y,
-					       (CELL) * (CELL *) ptr);
-		    if (data->type == FCELL_TYPE)
-			N_put_array_2d_f_value(data, x, y,
-					       (FCELL) * (CELL *) ptr);
-		    if (data->type == DCELL_TYPE)
-			N_put_array_2d_d_value(data, x, y,
-					       (DCELL) * (CELL *) ptr);
-		}
-	    }
-	    if (type == FCELL_TYPE) {
-		if (Rast_is_f_null_value(ptr)) {
-		    N_put_array_2d_value_null(data, x, y);
-		}
-		else {
-		    if (data->type == CELL_TYPE)
-			N_put_array_2d_c_value(data, x, y,
-					       (CELL) * (FCELL *) ptr);
-		    if (data->type == FCELL_TYPE)
-			N_put_array_2d_f_value(data, x, y,
-					       (FCELL) * (FCELL *) ptr);
-		    if (data->type == DCELL_TYPE)
-			N_put_array_2d_d_value(data, x, y,
-					       (DCELL) * (FCELL *) ptr);
-		}
-	    }
-	    if (type == DCELL_TYPE) {
-		if (Rast_is_d_null_value(ptr)) {
-		    N_put_array_2d_value_null(data, x, y);
-		}
-		else {
-		    if (data->type == CELL_TYPE)
-			N_put_array_2d_c_value(data, x, y,
-					       (CELL) * (DCELL *) ptr);
-		    if (data->type == FCELL_TYPE)
-			N_put_array_2d_f_value(data, x, y,
-					       (FCELL) * (DCELL *) ptr);
-		    if (data->type == DCELL_TYPE)
-			N_put_array_2d_d_value(data, x, y,
-					       (DCELL) * (DCELL *) ptr);
-		}
-	    }
-	}
-    }
-
-    /* Close file */
-    Rast_close(map);
-
-    return data;
-}
-
-/*!
- * \brief Write a N_array_2d struct to a raster map
- *
- * A new raster map is created with the same type as the N_array_2d.
- * The current region is used to open the raster map.
- * The N_array_2d must have the same size as the current region.
- If the writing of the raster map fails, G_fatal_error() will
- * be invoked.
-
- * \param array N_array_2d * 
- * \param name char * - the name of the raster map
- * \return void
- *
- * */
-void N_write_array_2d_to_rast(N_array_2d * array, char *name)
-{
-    int map;			/*The rastermap */
-    int x, y, cols, rows, count, type;
-    CELL *rast = NULL;
-    FCELL *frast = NULL;
-    DCELL *drast = NULL;
-    struct Cell_head region;
-
-    if (!array)
-	G_fatal_error(_("N_array_2d * array is empty"));
-
-    /* Get the current region */
-    G_get_set_window(&region);
-
-    rows = region.rows;
-    cols = region.cols;
-    type = array->type;
-
-    /*Open the new map */
-    map = Rast_open_new(name, type);
-
-    if (type == CELL_TYPE)
-	rast = Rast_allocate_buf(type);
-    if (type == FCELL_TYPE)
-	frast = Rast_allocate_buf(type);
-    if (type == DCELL_TYPE)
-	drast = Rast_allocate_buf(type);
-
-    G_message(_("Write 2d array to raster map <%s>"), name);
-
-    count = 0;
-    for (y = 0; y < rows; y++) {
-	G_percent(y, rows - 1, 10);
-	for (x = 0; x < cols; x++) {
-	    if (type == CELL_TYPE)
-		rast[x] = N_get_array_2d_c_value(array, x, y);
-	    if (type == FCELL_TYPE)
-		frast[x] = N_get_array_2d_f_value(array, x, y);
-	    if (type == DCELL_TYPE)
-		drast[x] = N_get_array_2d_d_value(array, x, y);
-	}
-	if (type == CELL_TYPE)
-	    Rast_put_c_row(map, rast);
-	if (type == FCELL_TYPE)
-	    Rast_put_f_row(map, frast);
-	if (type == DCELL_TYPE)
-	    Rast_put_d_row(map, drast);
-    }
-
-    /* Close file */
-    Rast_close(map);
-}
-
-
-/* ******************** 3D ARRAY FUNCTIONS *********************** */
-
-/*!
- * \brief Read a volume map into a N_array_3d structure
- *
- * The volume map is opened in the current region settings.
- * If no N_array_3d structure is provided (NULL pointer), a new structure will be
- * allocated with the same data type as the volume map and the size of the current region. 
- * The array offset will be set to 0.
- * <br><br>
- *
- * If a N_array_3d structure is provided, the values from the volume map are 
- * casted to the N_array_3d type. The array must have the same size 
- * as the current region. 
- * <br><br>
- *
- * The new created or the provided array is returned.
- * If the reading of the volume map fails, Rast3d_fatal_error() will
- * be invoked.
- *
- * \param name * char - the name of an existing volume map
- * \param array * N_array_3d - an existing array or NULL
- * \param mask int - 0 = false, 1 = ture : if a mask is presenent, use it with the input volume map
- * \return N_array_3d * - the existing or new allocated array
- * */
-N_array_3d *N_read_rast3d_to_array_3d(char *name, N_array_3d * array,
-				      int mask)
-{
-    void *map = NULL;		/*The 3D Rastermap */
-    int changemask = 0;
-    int x, y, z, cols, rows, depths, type;
-    double d1 = 0, f1 = 0;
-    N_array_3d *data = array;
-    RASTER3D_Region region;
-
-
-    /*get the current region */
-    Rast3d_get_window(&region);
-
-    cols = region.cols;
-    rows = region.rows;
-    depths = region.depths;
-
-
-    if (NULL == G_find_raster3d(name, ""))
-	Rast3d_fatal_error(_("3D raster map <%s> not found"), name);
-
-    /*Open all maps with default region */
-    map =
-	Rast3d_open_cell_old(name, G_find_raster3d(name, ""), RASTER3D_DEFAULT_WINDOW,
-			RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
-
-    if (map == NULL)
-	Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), name);
-
-    type = Rast3d_tile_type_map(map);
-
-    /*if the array is NULL create a new one with the data type of the volume map */
-    /*the offset is 0 by default */
-    if (data == NULL) {
-	if (type == FCELL_TYPE) {
-	    data = N_alloc_array_3d(cols, rows, depths, 0, FCELL_TYPE);
-	}
-	if (type == DCELL_TYPE) {
-	    data = N_alloc_array_3d(cols, rows, depths, 0, DCELL_TYPE);
-	}
-    }
-    else {
-	/*Check the array sizes */
-	if (data->cols != cols)
-	    G_fatal_error
-		("N_read_rast_to_array_3d: the data array size is different from the current region settings");
-	if (data->rows != rows)
-	    G_fatal_error
-		("N_read_rast_to_array_3d: the data array size is different from the current region settings");
-	if (data->depths != depths)
-	    G_fatal_error
-		("N_read_rast_to_array_3d: the data array size is different from the current region settings");
-    }
-
-
-    G_message(_("Read g3d map <%s> into the memory"), name);
-
-    /*if requested set the Mask on */
-    if (mask) {
-	if (Rast3d_mask_file_exists()) {
-	    changemask = 0;
-	    if (Rast3d_mask_is_off(map)) {
-		Rast3d_mask_on(map);
-		changemask = 1;
-	    }
-	}
-    }
-
-    for (z = 0; z < depths; z++) {	/*From the bottom to the top */
-	G_percent(z, depths - 1, 10);
-	for (y = 0; y < rows; y++) {
-	    for (x = 0; x < cols; x++) {
-		if (type == FCELL_TYPE) {
-		    Rast3d_get_value(map, x, y, z, &f1, type);
-		    if (Rast_is_f_null_value((void *)&f1)) {
-			N_put_array_3d_value_null(data, x, y, z);
-		    }
-		    else {
-			if (data->type == FCELL_TYPE)
-			    N_put_array_3d_f_value(data, x, y, z, f1);
-			if (data->type == DCELL_TYPE)
-			    N_put_array_3d_d_value(data, x, y, z, (double)f1);
-		    }
-		}
-		else {
-		    Rast3d_get_value(map, x, y, z, &d1, type);
-		    if (Rast_is_d_null_value((void *)&d1)) {
-			N_put_array_3d_value_null(data, x, y, z);
-		    }
-		    else {
-			if (data->type == FCELL_TYPE)
-			    N_put_array_3d_f_value(data, x, y, z, (float)d1);
-			if (data->type == DCELL_TYPE)
-			    N_put_array_3d_d_value(data, x, y, z, d1);
-		    }
-
-		}
-	    }
-	}
-    }
-
-    /*We set the Mask off, if it was off before */
-    if (mask) {
-	if (Rast3d_mask_file_exists())
-	    if (Rast3d_mask_is_on(map) && changemask)
-		Rast3d_mask_off(map);
-    }
-
-    /* Close files and exit */
-    if (!Rast3d_close(map))
-	Rast3d_fatal_error(map, NULL, 0, _("Error closing g3d file"));
-
-    return data;
-}
-
-/*!
- * \brief Write a N_array_3d struct to a volume map
- *
- * A new volume map is created with the same type as the N_array_3d.
- * The current region is used to open the volume map.
- * The N_array_3d must have the same size as the current region.
- * If the writing of the volume map fails, Rast3d_fatal_error() will
- * be invoked.
- *
- *
- * \param array N_array_3d * 
- * \param name char * - the name of the volume map
- * \param mask int - 1 = use a 3d mask, 0 do not use a 3d mask
- * \return void
- *
- * */
-void N_write_array_3d_to_rast3d(N_array_3d * array, char *name, int mask)
-{
-    void *map = NULL;		/*The 3D Rastermap */
-    int changemask = 0;
-    int x, y, z, cols, rows, depths, count, type;
-    double d1 = 0.0, f1 = 0.0;
-    N_array_3d *data = array;
-    RASTER3D_Region region;
-
-    /*get the current region */
-    Rast3d_get_window(&region);
-
-    cols = region.cols;
-    rows = region.rows;
-    depths = region.depths;
-    type = data->type;
-
-    /*Check the array sizes */
-    if (data->cols != cols)
-	G_fatal_error
-	    ("N_write_array_3d_to_rast3d: the data array size is different from the current region settings");
-    if (data->rows != rows)
-	G_fatal_error
-	    ("N_write_array_3d_to_rast3d: the data array size is different from the current region settings");
-    if (data->depths != depths)
-	G_fatal_error
-	    ("N_write_array_3d_to_rast3d: the data array size is different from the current region settings");
-
-    /*Open the new map */
-    if (type == DCELL_TYPE)
-        map = Rast3d_open_new_opt_tile_size(name, RASTER3D_USE_CACHE_XY, &region, DCELL_TYPE, 32);
-    else if (type == FCELL_TYPE)
-        map = Rast3d_open_new_opt_tile_size(name, RASTER3D_USE_CACHE_XY, &region, FCELL_TYPE, 32);
-
-    if (map == NULL)
-	Rast3d_fatal_error(_("Error opening g3d map <%s>"), name);
-
-    G_message(_("Write 3d array to g3d map <%s>"), name);
-
-    /*if requested set the Mask on */
-    if (mask) {
-	if (Rast3d_mask_file_exists()) {
-	    changemask = 0;
-	    if (Rast3d_mask_is_off(map)) {
-		Rast3d_mask_on(map);
-		changemask = 1;
-	    }
-	}
-    }
-
-    count = 0;
-    for (z = 0; z < depths; z++) {	/*From the bottom to the top */
-	G_percent(z, depths - 1, 10);
-	for (y = 0; y < rows; y++) {
-	    for (x = 0; x < cols; x++) {
-		if (type == FCELL_TYPE) {
-		    f1 = N_get_array_3d_f_value(data, x, y, z);
-		    Rast3d_put_float(map, x, y, z, f1);
-		}
-		else if (type == DCELL_TYPE) {
-		    d1 = N_get_array_3d_d_value(data, x, y, z);
-		    Rast3d_put_double(map, x, y, z, d1);
-		}
-	    }
-	}
-    }
-
-    /*We set the Mask off, if it was off before */
-    if (mask) {
-	if (Rast3d_mask_file_exists())
-	    if (Rast3d_mask_is_on(map) && changemask)
-		Rast3d_mask_off(map);
-    }
-
-    /* Flush all tile */
-    if (!Rast3d_flush_all_tiles(map))
-	Rast3d_fatal_error("Error flushing tiles with Rast3d_flush_all_tiles");
-    /* Close files and exit */
-    if (!Rast3d_close(map))
-	Rast3d_fatal_error(map, NULL, 0, _("Error closing g3d file"));
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_geom.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_geom.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_geom.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,204 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:      part of the gpde library
-* 		allocation, destroing and initializing the geometric struct
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-
-/* *************************************************************** * 
- * *********** Konstruktor *************************************** * 
- * *************************************************************** */
-/*!
- * \brief Allocate the pde geometry data structure and return a pointer to the new allocated structure
- *
- * \return N_geom_data *
- * */
-N_geom_data *N_alloc_geom_data(void)
-{
-    N_geom_data *geom = (N_geom_data *) G_calloc(1, sizeof(N_geom_data));
-
-    geom->area = NULL;
-    geom->planimetric = 1;
-    geom->dim = 0;
-
-    return geom;
-}
-
-/* *************************************************************** * 
- * *********** Destruktor **************************************** * 
- * *************************************************************** */
-/*!
- * \brief Release memory of a pde geometry data structure
- *
- * \param  geom N_geom_data *
- * \return void
- * */
-void N_free_geom_data(N_geom_data * geom)
-{
-    if (geom->area != NULL)
-	G_free(geom->area);
-
-    G_free(geom);
-    return;
-}
-
-/* *************************************************************** * 
- * *************************************************************** * 
- * *************************************************************** */
-/*!
- * \brief Initiate a pde geometry data structure with a 3d region
- *
- * If the projection is not planimetric, a double array will be created based on the 
- * number of rows of the provided region
- *
- * \param region3d RASTER3D_Region *
- * \param geodata N_geom_data * - if a NULL pointer is given, a new structure will be allocatet and returned
- *
- * \return N_geom_data *
- * */
-N_geom_data *N_init_geom_data_3d(RASTER3D_Region * region3d, N_geom_data * geodata)
-{
-    N_geom_data *geom = geodata;
-    struct Cell_head region2d;
-
-#pragma omp critical
-    {
-
-	G_debug(2,
-		"N_init_geom_data_3d: initializing the geometry structure");
-
-	if (geom == NULL)
-	    geom = N_alloc_geom_data();
-
-	geom->dz = region3d->tb_res * G_database_units_to_meters_factor();	/*this function is not thread safe */
-	geom->depths = region3d->depths;
-	geom->dim = 3;
-
-	/*convert the 3d into a 2d region and begin the area calculation */
-	G_get_set_window(&region2d);	/*this function is not thread safe */
-	Rast3d_region_to_cell_head(region3d, &region2d);
-    }
-
-    return N_init_geom_data_2d(&region2d, geom);
-}
-
-
-/* *************************************************************** * 
- * *************************************************************** * 
- * *************************************************************** */
-/*!
- * \brief Initiate a pde geometry data structure with a 2d region
- *
- * If the projection is not planimetric, a double array will be created based on the 
- * number of rows of the provided region storing all computed areas for each row
- *
- * \param region sruct Cell_head *
- * \param geodata N_geom_data * - if a NULL pointer is given, a new structure will be allocatet and returned
- *
- * \return N_geom_data *
- * */
-N_geom_data *N_init_geom_data_2d(struct Cell_head * region,
-				 N_geom_data * geodata)
-{
-    N_geom_data *geom = geodata;
-    struct Cell_head backup;
-    double meters;
-    short ll = 0;
-    int i;
-
-
-    /*create an openmp lock to assure that only one thread at a time will access this function */
-#pragma omp critical
-    {
-	G_debug(2,
-		"N_init_geom_data_2d: initializing the geometry structure");
-
-	/*make a backup from this region */
-	G_get_set_window(&backup);	/*this function is not thread safe */
-	/*set the current region */
-	Rast_set_window(region);	/*this function is not thread safe */
-
-	if (geom == NULL)
-	    geom = N_alloc_geom_data();
-
-	meters = G_database_units_to_meters_factor();	/*this function is not thread safe */
-
-	/*set the dim to 2d if it was not initiated with 3, thats a bit ugly :( */
-	if (geom->dim != 3)
-	    geom->dim = 2;
-
-	geom->planimetric = 1;
-	geom->rows = region->rows;
-	geom->cols = region->cols;
-	geom->dx = region->ew_res * meters;
-	geom->dy = region->ns_res * meters;
-	geom->Az = geom->dy * geom->dx;	/*square meters in planimetric proj */
-	/*depths and dz are initialized with a 3d region */
-
-	/*Begin the area calculation */
-	ll = G_begin_cell_area_calculations();	/*this function is not thread safe */
-
-	/*if the projection is not planimetric, calc the area for each row */
-	if (ll == 2) {
-	    G_debug(2,
-		    "N_init_geom_data_2d: calculating the areas for non parametric projection");
-	    geom->planimetric = 0;
-
-	    if (geom->area != NULL)
-		G_free(geom->area);
-	    else
-		geom->area = G_calloc(geom->rows, sizeof(double));
-
-	    /*fill the area vector */
-	    for (i = 0; i < geom->rows; i++) {
-		geom->area[i] = G_area_of_cell_at_row(i);	/*square meters */
-	    }
-	}
-
-	/*restore the old region */
-	Rast_set_window(&backup);	/*this function is not thread safe */
-    }
-
-    return geom;
-}
-
-/* *************************************************************** * 
- * *************************************************************** * 
- * *************************************************************** */
-/*!
- * \brief Get the areay size in square meter of one cell (x*y) at row
- *
- * This function works for two and three dimensions
- *
- * \param geom N_geom_data *
- * \param row int
- * \return area double
- *
- * */
-double N_get_geom_data_area_of_cell(N_geom_data * geom, int row)
-{
-    if (geom->planimetric) {
-	G_debug(6, "N_get_geom_data_area_of_cell: %g", geom->Az);
-	return geom->Az;
-    }
-    else {
-	G_debug(6, "N_get_geom_data_area_of_cell: %g", geom->area[row]);
-	return geom->area[row];
-    }
-
-    return 0.0;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_gradient.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_gradient.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_gradient.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,1113 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:     	gradient management functions 
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-
-/*!
- * \brief Allocate a N_gradient_2d structure
- *
- * \return N_gradient_2d *
- *
- * */
-N_gradient_2d *N_alloc_gradient_2d(void)
-{
-    N_gradient_2d *grad;
-
-    grad = (N_gradient_2d *) G_calloc(1, sizeof(N_gradient_2d));
-
-    return grad;
-}
-
-/*!
- * \brief Free's a N_gradient_2d structure
- *
- * \return void
- *
- * */
-void N_free_gradient_2d(N_gradient_2d * grad)
-{
-    G_free(grad);
-    grad = NULL;
-
-    return;
-}
-
-/*!
- * \brief allocate and initialize a N_gradient_2d structure
- *
- * \param NC double - the gradient between northern and center cell
- * \param SC double - the gradient between southern and center cell
- * \param WC double - the gradient between western and center cell
- * \param EC double - the gradient between eastern and center cell
- * \return N_gradient_2d *
- *
- * */
-N_gradient_2d *N_create_gradient_2d(double NC, double SC, double WC,
-				    double EC)
-{
-    N_gradient_2d *grad;
-
-    G_debug(5, "N_create_gradient_2d: create N_gradient_2d");
-
-    grad = N_alloc_gradient_2d();
-
-    grad->NC = NC;
-    grad->SC = SC;
-    grad->WC = WC;
-    grad->EC = EC;
-
-    return grad;
-}
-
-/*!
- * \brief copy a N_gradient_2d structure
- *
- * \param source - the source N_gradient_2d struct
- * \param target - the target N_gradient_2d struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int N_copy_gradient_2d(N_gradient_2d * source, N_gradient_2d * target)
-{
-    G_debug(5, "N_copy_gradient_2d: copy N_gradient_2d");
-
-    if (!source || !target)
-	return 0;
-
-    target->NC = source->NC;
-    target->SC = source->SC;
-    target->WC = source->WC;
-    target->EC = source->EC;
-
-    return 1;
-}
-
-/*!
- * \brief Return a N_gradient_2d structure calculated from the input gradient field
- * at position [row][col]
- *
- *  This function returns the gradient of a cell at position [row][col] from the input gradient field.
- *  Returend is a new structure of type N_gradient_2d.
- *
- *  \param field N_gradient_field_2d * - A two dimensional gradient field
- *  \param gradient N_gradient_2d * - the gradient structure which should be filled with data, if a NULL pointer is given, a new structure will be created
- *  \param col int
- *  \param row int
- *  \return N_gradient_2d * - the new or filled gradient structure
- *  
- *
- * */
-N_gradient_2d *N_get_gradient_2d(N_gradient_field_2d * field,
-				 N_gradient_2d * gradient, int col, int row)
-{
-    double NC = 0, SC = 0, WC = 0, EC = 0;
-    N_gradient_2d *grad = gradient;
-
-
-    NC = N_get_array_2d_d_value(field->y_array, col, row);
-    SC = N_get_array_2d_d_value(field->y_array, col, row + 1);
-    WC = N_get_array_2d_d_value(field->x_array, col, row);
-    EC = N_get_array_2d_d_value(field->x_array, col + 1, row);
-
-    G_debug(5,
-	    "N_get_gradient_2d: calculate N_gradient_2d NC %g SC %g WC %g EC %g",
-	    NC, SC, WC, EC);
-
-    /*if gradient is a NULL pointer, create a new one */
-    if (!grad) {
-	grad = N_create_gradient_2d(NC, SC, WC, EC);
-    }
-    else {
-	grad->NC = NC;
-	grad->SC = SC;
-	grad->WC = WC;
-	grad->EC = EC;
-    }
-
-    return grad;
-}
-
-/*!
- * \brief Allocate a N_gradient_3d structure
- *
- * \return N_gradient_3d *
- *
- * */
-N_gradient_3d *N_alloc_gradient_3d(void)
-{
-    N_gradient_3d *grad;
-
-    grad = (N_gradient_3d *) G_calloc(1, sizeof(N_gradient_3d));
-
-    return grad;
-}
-
-/*!
- * \brief Free's a N_gradient_3d structure
- *
- * \return void
- *
- * */
-void N_free_gradient_3d(N_gradient_3d * grad)
-{
-    G_free(grad);
-    grad = NULL;
-
-    return;
-}
-
-
-/*!
- * \brief allocate and initialize a N_gradient_3d structure
- *
- * \param NC double - the gradient between northern and center cell
- * \param SC double - the gradient between southern and center cell
- * \param WC double - the gradient between western and center cell
- * \param EC double - the gradient between eastern and center cell
- * \param TC double - the gradient between top and center cell
- * \param BC double - the gradient between bottom and center cell
- * \return N_gradient_3d *
- *
- * */
-N_gradient_3d *N_create_gradient_3d(double NC, double SC, double WC,
-				    double EC, double TC, double BC)
-{
-    N_gradient_3d *grad;
-
-    G_debug(5, "N_create_gradient_3d: create N_gradient_3d");
-
-    grad = N_alloc_gradient_3d();
-
-    grad->NC = NC;
-    grad->SC = SC;
-    grad->WC = WC;
-    grad->EC = EC;
-    grad->TC = TC;
-    grad->BC = BC;
-
-    return grad;
-}
-
-/*!
- * \brief copy a N_gradient_3d structure
- *
- * \param source - the source N_gradient_3d struct
- * \param target - the target N_gradient_3d struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int N_copy_gradient_3d(N_gradient_3d * source, N_gradient_3d * target)
-{
-    G_debug(5, "N_copy_gradient_3d: copy N_gradient_3d");
-
-    if (!source || !target)
-	return 0;
-
-    target->NC = source->NC;
-    target->SC = source->SC;
-    target->WC = source->WC;
-    target->EC = source->EC;
-    target->TC = source->TC;
-    target->BC = source->BC;
-
-    return 1;
-}
-
-
-/*!
- * \brief Return a N_gradient_3d structure calculated from the input gradient field
- * at position [depth][row][col]
- *
- *  This function returns the gradient of a 3d cell at position [depth][row][col] from the input gradient field.
- *  Returned is a new structure of type N_gradient_3d.
- *
- *  \param field N_gradient_field_3d * - A three dimensional gradient field
- *  \param gradient N_gradient_3d * - an existing gradient structure or a NULL pointer, if a NULL pointer is providet a new structure will be returned
- *  \param col int
- *  \param row int
- *  \param depth int
- *  \return N_gradient_3d *
- *  
- *
- * */
-N_gradient_3d *N_get_gradient_3d(N_gradient_field_3d * field,
-				 N_gradient_3d * gradient, int col, int row,
-				 int depth)
-{
-    double NC, SC, WC, EC, TC, BC;
-    N_gradient_3d *grad = gradient;
-
-    NC = N_get_array_3d_d_value(field->y_array, col, row, depth);
-    SC = N_get_array_3d_d_value(field->y_array, col, row + 1, depth);
-    WC = N_get_array_3d_d_value(field->x_array, col, row, depth);
-    EC = N_get_array_3d_d_value(field->x_array, col + 1, row, depth);
-    BC = N_get_array_3d_d_value(field->z_array, col, row, depth);
-    TC = N_get_array_3d_d_value(field->z_array, col, row, depth + 1);
-
-    G_debug(6,
-	    "N_get_gradient_3d: calculate N_gradient_3d NC %g SC %g WC %g EC %g TC %g BC %g",
-	    NC, SC, WC, EC, TC, BC);
-
-    /*if gradient is a NULL pointer, create a new one */
-    if (!grad) {
-	grad = N_create_gradient_3d(NC, SC, WC, EC, TC, BC);
-    }
-    else {
-	grad->NC = NC;
-	grad->SC = SC;
-	grad->WC = WC;
-	grad->EC = EC;
-	grad->BC = BC;
-	grad->TC = TC;
-    }
-
-    return grad;
-}
-
-/*!
- * \brief Allocate a N_gradient_neighbours_x structure
- *
- * This structure contains all neighbour gradients in x direction of one cell  
- *
- * \return N_gradient_neighbours_x  *
- *
- * */
-N_gradient_neighbours_x *N_alloc_gradient_neighbours_x(void)
-{
-    N_gradient_neighbours_x *grad;
-
-    grad =
-	(N_gradient_neighbours_x *) G_calloc(1,
-					     sizeof(N_gradient_neighbours_x));
-
-    return grad;
-}
-
-/*!
- * \brief Free's a N_gradient_neighbours_x structure
- *
- * \return void
- *
- * */
-void N_free_gradient_neighbours_x(N_gradient_neighbours_x * grad)
-{
-    G_free(grad);
-    grad = NULL;
-
-    return;
-}
-
-
-/*!
- * \brief Allocate and initialize a N_gradient_neighbours_x structure
- *
- * \param NWN double - the gradient between north-west and northern cell
- * \param NEN double - the gradient between north-east and northern cell
- * \param WC double - the gradient between western and center cell
- * \param EC double - the gradient between eastern and center cell
- * \param SWS double - the gradient between south-west and southern cell
- * \param SES double - the gradient between south-east and southern cell
- * \return N_gradient_neighbours_x *
-
- *
- * */
-N_gradient_neighbours_x *N_create_gradient_neighbours_x(double NWN,
-							double NEN, double WC,
-							double EC, double SWS,
-							double SES)
-{
-    N_gradient_neighbours_x *grad;
-
-    G_debug(6,
-	    "N_create_gradient_neighbours_x: create N_gradient_neighbours_x");
-
-    grad = N_alloc_gradient_neighbours_x();
-
-    grad->NWN = NWN;
-    grad->NEN = NEN;
-    grad->WC = WC;
-    grad->EC = EC;
-    grad->SWS = SWS;
-    grad->SES = SES;
-
-    return grad;
-}
-
-/*!
- * \brief copy a N_gradient_neighbours_x structure
- *
- * \param source - the source N_gradient_neighbours_x struct
- * \param target - the target N_gradient_neighbours_x struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int
-N_copy_gradient_neighbours_x(N_gradient_neighbours_x * source,
-			     N_gradient_neighbours_x * target)
-{
-    G_debug(6, "N_copy_gradient_neighbours_x: copy N_gradient_neighbours_x");
-
-    if (!source || !target)
-	return 0;
-
-    target->NWN = source->NWN;
-    target->NEN = source->NEN;
-    target->WC = source->WC;
-    target->EC = source->EC;
-    target->SWS = source->SWS;
-    target->SES = source->SES;
-
-    return 1;
-}
-
-/*!
- * \brief Allocate a N_gradient_neighbours_y structure
- *
- * This structure contains all neighbour gradients in y direction of one cell  
- *
- * \return N_gradient_neighbours_y  *
- *
- * */
-N_gradient_neighbours_y *N_alloc_gradient_neighbours_y(void)
-{
-    N_gradient_neighbours_y *grad;
-
-    grad =
-	(N_gradient_neighbours_y *) G_calloc(1,
-					     sizeof(N_gradient_neighbours_y));
-
-    return grad;
-}
-
-/*!
- * \brief Free's a N_gradient_neighbours_y structure
- *
- * \return void
- *
- * */
-void N_free_gradient_neighbours_y(N_gradient_neighbours_y * grad)
-{
-    G_free(grad);
-    grad = NULL;
-
-    return;
-}
-
-/*!
- * \brief Allocate and initialize a N_gradient_neighbours_y structure
- *
- * \param NWW double - the gradient between north-west and western cell
- * \param NEE double - the gradient between north-east and eastern cell
- * \param NC double - the gradient between northern and center cell
- * \param SC double - the gradient between southern and center cell
- * \param SWW double - the gradient between south-west and western cell
- * \param SEE double - the gradient between south-east and eastern cell
- * \return N_gradient_neighbours_y *
-
- *
- * */
-N_gradient_neighbours_y *N_create_gradient_neighbours_y(double NWW,
-							double NEE, double NC,
-							double SC, double SWW,
-							double SEE)
-{
-    N_gradient_neighbours_y *grad;
-
-    G_debug(6,
-	    "N_create_gradient_neighbours_y: create N_gradient_neighbours_y");
-
-    grad = N_alloc_gradient_neighbours_y();
-
-    grad->NWW = NWW;
-    grad->NEE = NEE;
-    grad->NC = NC;
-    grad->SC = SC;
-    grad->SWW = SWW;
-    grad->SEE = SEE;
-
-    return grad;
-}
-
-/*!
- * \brief copy a N_gradient_neighbours_y structure
- *
- * \param source - the source N_gradient_neighbours_y struct
- * \param target - the target N_gradient_neighbours_y struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int
-N_copy_gradient_neighbours_y(N_gradient_neighbours_y * source,
-			     N_gradient_neighbours_y * target)
-{
-    G_debug(6, "N_copy_gradient_neighbours_y: copy N_gradient_neighbours_y");
-
-    if (!source || !target)
-	return 0;
-
-    target->NWW = source->NWW;
-    target->NEE = source->NEE;
-    target->NC = source->NC;
-    target->SC = source->SC;
-    target->SWW = source->SWW;
-    target->SEE = source->SEE;
-
-    return 1;
-}
-
-/*!
- * \brief Allocate a N_gradient_neighbours_z structure
- *
- * This structure contains all neighbour gradients in z direction of one cell  
- *
- * \return N_gradient_neighbours_z  *
- *
- * */
-N_gradient_neighbours_z *N_alloc_gradient_neighbours_z(void)
-{
-    N_gradient_neighbours_z *grad;
-
-    grad =
-	(N_gradient_neighbours_z *) G_calloc(1,
-					     sizeof(N_gradient_neighbours_z));
-
-    return grad;
-}
-
-/*!
- * \brief Free's a N_gradient_neighbours_z structure
- *
- * \return void
- *
- * */
-void N_free_gradient_neighbours_z(N_gradient_neighbours_z * grad)
-{
-    G_free(grad);
-    grad = NULL;
-
-    return;
-}
-
-/*!
- * \brief Allocate and initialize a N_gradient_neighbours_z structure
- *
- * \param NWZ double - the gradient between upper and lower north-western cells
- * \param NZ double - the gradient between upper and lower northern cells
- * \param NEZ double - the gradient between upper and lower north-eastern cells
- * \param WZ double - the gradient between upper and lower western cells
- * \param CZ double - the gradient between upper and lower center cells
- * \param EZ double - the gradient between upper and lower eastern cells
- * \param SWZ double - the gradient between upper and lower south-western cells
- * \param SZ double - the gradient between upper and lower southern cells
- * \param SEZ double - the gradient between upper and lower south-eastern cells
- * \return N_gradient_neighbours_z *
-
- *
- * */
-N_gradient_neighbours_z *N_create_gradient_neighbours_z(double NWZ, double NZ,
-							double NEZ, double WZ,
-							double CZ, double EZ,
-							double SWZ, double SZ,
-							double SEZ)
-{
-    N_gradient_neighbours_z *grad;
-
-    G_debug(6,
-	    "N_create_gradient_neighbours_z: create N_gradient_neighbours_z");
-
-    grad = N_alloc_gradient_neighbours_z();
-
-    grad->NWZ = NWZ;
-    grad->NZ = NZ;
-    grad->NEZ = NEZ;
-    grad->WZ = WZ;
-    grad->CZ = CZ;
-    grad->EZ = EZ;
-    grad->SWZ = SWZ;
-    grad->SZ = SZ;
-    grad->SEZ = SEZ;
-
-    return grad;
-}
-
-/*!
- * \brief copy a N_gradient_neighbours_z structure
- *
- * \param source - the source N_gradient_neighbours_z struct
- * \param target - the target N_gradient_neighbours_z struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int
-N_copy_gradient_neighbours_z(N_gradient_neighbours_z * source,
-			     N_gradient_neighbours_z * target)
-{
-    G_debug(6, "N_copy_gradient_neighbours_z: copy N_gradient_neighbours_z");
-
-    if (!source || !target)
-	return 0;
-
-    target->NWZ = source->NWZ;
-    target->NZ = source->NZ;
-    target->NEZ = source->NEZ;
-    target->WZ = source->WZ;
-    target->CZ = source->CZ;
-    target->EZ = source->EZ;
-    target->SWZ = source->SWZ;
-    target->SZ = source->SZ;
-    target->SEZ = source->SEZ;
-
-    return 1;
-}
-
-/*!
- * \brief Allocate a N_gradient_neighbours_2d structure
- *
- * This structure contains all neighbour gradients in all directions of one cell 
- * in a 2d raster layer
- *
- * \return N_gradient_neighbours_2d *
- *
- * */
-N_gradient_neighbours_2d *N_alloc_gradient_neighbours_2d(void)
-{
-    N_gradient_neighbours_2d *grad;
-
-    grad =
-	(N_gradient_neighbours_2d *) G_calloc(1,
-					      sizeof
-					      (N_gradient_neighbours_2d));
-
-    grad->x = N_alloc_gradient_neighbours_x();
-    grad->y = N_alloc_gradient_neighbours_y();
-
-    return grad;
-}
-
-/*!
- * \brief Free's a N_gradient_neighbours_2d structure
- *
- * \return void
- *
- * */
-void N_free_gradient_neighbours_2d(N_gradient_neighbours_2d * grad)
-{
-
-    N_free_gradient_neighbours_x(grad->x);
-    N_free_gradient_neighbours_y(grad->y);
-
-    G_free(grad);
-    grad = NULL;
-
-    return;
-}
-
-/*!
- * \brief Allocate and initialize a N_gradient_neighbours_2d structure
- *
- * The parameter N_gradient_neighbours x and y are copied into the new allocated structure 
- * and can be deleted after the initializing
- *
- * \return N_gradient_neighbours_2d * -- if failure NULL is returned
- *
- * */
-N_gradient_neighbours_2d
-    * N_create_gradient_neighbours_2d(N_gradient_neighbours_x * x,
-				      N_gradient_neighbours_y * y)
-{
-    N_gradient_neighbours_2d *grad;
-    int fail = 0;
-
-    G_debug(5,
-	    "N_create_gradient_neighbours_2d: create N_gradient_neighbours_2d");
-
-    grad = N_alloc_gradient_neighbours_2d();
-
-    if (!N_copy_gradient_neighbours_x(x, grad->x))
-	fail++;
-    if (!N_copy_gradient_neighbours_y(y, grad->y))
-	fail++;
-
-    if (fail > 0) {
-	N_free_gradient_neighbours_2d(grad);
-	grad = NULL;
-    }
-
-    return grad;
-}
-
-/*!
- * \brief copy a N_gradient_neighbours_2d structure
- *
- * \param source - the source N_gradient_neighbours_2d struct
- * \param target - the target N_gradient_neighbours_2d struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int
-N_copy_gradient_neighbours_2d(N_gradient_neighbours_2d * source,
-			      N_gradient_neighbours_2d * target)
-{
-    int fail = 0;
-
-    G_debug(5,
-	    "N_copy_gradient_neighbours_2d: copy N_gradient_neighbours_2d");
-
-    if (!source || !target)
-	return 0;
-
-    if (!(N_copy_gradient_neighbours_x(source->x, target->x)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_y(source->y, target->y)))
-	fail++;
-
-    if (fail > 0) {
-	return 0;
-    }
-
-    return 1;
-}
-
-/*!
- * \brief Return a N_gradient_neighbours_2d structure calculated from the input gradient field
- * at position [row][col]
- *
- *  This function returns the gradient neighbours in x and y dierection 
- *  of a cell at position [row][col] from the input gradient field.
- *  Returend is a pointer to a structure of type N_gradient_neighbours_2d.
- *
- *  \param field N_gradient_field_2d * - A two dimensional gradient field
- *  \param gradient N_gradient_neighbours_2d * - the gradient structure which should be filled with data, if a NULL pointer is given, a new structure will be created
- *  \param col int
- *  \param row int
- *  \return N_gradient_neighbours_2d * - the new or filled gradient structure
- *  
- *
- * */
-N_gradient_neighbours_2d *N_get_gradient_neighbours_2d(N_gradient_field_2d *
-						       field,
-						       N_gradient_neighbours_2d
-						       * gradient, int col,
-						       int row)
-{
-    double NWN, NEN, WC, EC, SWS, SES;
-    double NWW, NEE, NC, SC, SWW, SEE;
-    N_gradient_neighbours_2d *grad = NULL;
-    N_gradient_neighbours_x *grad_x = NULL;
-    N_gradient_neighbours_y *grad_y = NULL;
-
-
-    NWN = N_get_array_2d_d_value(field->x_array, col, row - 1);
-    NEN = N_get_array_2d_d_value(field->x_array, col + 1, row - 1);
-    WC = N_get_array_2d_d_value(field->x_array, col, row);
-    EC = N_get_array_2d_d_value(field->x_array, col + 1, row);
-    SWS = N_get_array_2d_d_value(field->x_array, col, row + 1);
-    SES = N_get_array_2d_d_value(field->x_array, col + 1, row + 1);
-
-    NWW = N_get_array_2d_d_value(field->y_array, col - 1, row);
-    NEE = N_get_array_2d_d_value(field->y_array, col + 1, row);
-    NC = N_get_array_2d_d_value(field->y_array, col, row);
-    SC = N_get_array_2d_d_value(field->y_array, col, row + 1);
-    SWW = N_get_array_2d_d_value(field->y_array, col - 1, row + 1);
-    SEE = N_get_array_2d_d_value(field->y_array, col + 1, row + 1);
-
-
-    grad_x = N_create_gradient_neighbours_x(NWN, NEN, WC, EC, SWS, SES);
-    grad_y = N_create_gradient_neighbours_y(NWW, NEE, NC, SC, SWW, SEE);
-
-    G_debug(5,
-	    "N_get_gradient_neighbours_2d: calculate N_gradient_neighbours_x NWN %g NEN %g WC %g EC %g SWS %g SES %g",
-	    NWN, NEN, WC, EC, SWS, SES);
-
-    G_debug(5,
-	    "N_get_gradient_neighbours_2d: calculate N_gradient_neighbours_y NWW %g NEE %g NC %g SC %g SWW %g SEE %g",
-	    NWW, NEE, NC, SC, SWW, SEE);
-
-
-    /*if gradient is a NULL pointer, create a new one */
-    if (!gradient) {
-	grad = N_create_gradient_neighbours_2d(grad_x, grad_y);
-	gradient = grad;
-    }
-    else {
-	grad = N_create_gradient_neighbours_2d(grad_x, grad_y);
-	N_copy_gradient_neighbours_2d(grad, gradient);
-	N_free_gradient_neighbours_2d(grad);
-    }
-
-    N_free_gradient_neighbours_x(grad_x);
-    N_free_gradient_neighbours_y(grad_y);
-
-    return gradient;
-}
-
-
-/*!
- * \brief Allocate a N_gradient_neighbours_3d structure
- *
- * This structure contains all neighbour gradients in all directions of one cell 
- * in a 3d raster layer
- *
- * \return N_gradient_neighbours_3d *
- *
- * */
-N_gradient_neighbours_3d *N_alloc_gradient_neighbours_3d(void)
-{
-    N_gradient_neighbours_3d *grad;
-
-    grad =
-	(N_gradient_neighbours_3d *) G_calloc(1,
-					      sizeof
-					      (N_gradient_neighbours_3d));
-
-    grad->xt = N_alloc_gradient_neighbours_x();
-    grad->xc = N_alloc_gradient_neighbours_x();
-    grad->xb = N_alloc_gradient_neighbours_x();
-    grad->yt = N_alloc_gradient_neighbours_y();
-    grad->yc = N_alloc_gradient_neighbours_y();
-    grad->yb = N_alloc_gradient_neighbours_y();
-    grad->zt = N_alloc_gradient_neighbours_z();
-    grad->zb = N_alloc_gradient_neighbours_z();
-
-    return grad;
-}
-
-/*!
- * \brief Free's a N_gradient_neighbours_3d structure
- *
- * \return void
- *
- * */
-void N_free_gradient_neighbours_3d(N_gradient_neighbours_3d * grad)
-{
-
-    N_free_gradient_neighbours_x(grad->xt);
-    N_free_gradient_neighbours_x(grad->xc);
-    N_free_gradient_neighbours_x(grad->xb);
-    N_free_gradient_neighbours_y(grad->yt);
-    N_free_gradient_neighbours_y(grad->yc);
-    N_free_gradient_neighbours_y(grad->yb);
-    N_free_gradient_neighbours_z(grad->zt);
-    N_free_gradient_neighbours_z(grad->zb);
-
-    G_free(grad);
-    grad = NULL;
-
-    return;
-}
-
-/*!
- * \brief Allocate and initialize a N_gradient_neighbours_3d structure
- *
- * The parameter N_gradient_neighbours x(tcb) and y(tcb) and z(tb) are copied into the new allocated structure 
- * and can be deleted after the initializing
- *
- * \return N_gradient_neighbours_3d * -- if failure NULL is returned
-
- *
- * */
-N_gradient_neighbours_3d
-    * N_create_gradient_neighbours_3d(N_gradient_neighbours_x * xt,
-				      N_gradient_neighbours_x * xc,
-				      N_gradient_neighbours_x * xb,
-				      N_gradient_neighbours_y * yt,
-				      N_gradient_neighbours_y * yc,
-				      N_gradient_neighbours_y * yb,
-				      N_gradient_neighbours_z * zt,
-				      N_gradient_neighbours_z * zb)
-{
-    N_gradient_neighbours_3d *grad;
-    int fail = 0;
-
-    G_debug(5,
-	    "N_create_gradient_neighbours_3d: create N_gradient_neighbours_3d");
-
-    grad = N_alloc_gradient_neighbours_3d();
-
-    if (!(N_copy_gradient_neighbours_x(xt, grad->xt)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_x(xc, grad->xc)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_x(xb, grad->xb)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_y(yt, grad->yt)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_y(yc, grad->yc)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_y(yb, grad->yb)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_z(zt, grad->zt)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_z(zb, grad->zb)))
-	fail++;
-
-    if (fail > 0) {
-	return NULL;
-    }
-
-    return grad;
-}
-
-/*!
- * \brief copy a N_gradient_neighbours_3d structure
- *
- * \param source - the source N_gradient_neighbours_3d struct
- * \param target - the target N_gradient_neighbours_3d struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int
-N_copy_gradient_neighbours_3d(N_gradient_neighbours_3d * source,
-			      N_gradient_neighbours_3d * target)
-{
-    int fail = 0;
-
-    G_debug(5,
-	    "N_copy_gradient_neighbours_3d: copy N_gradient_neighbours_3d");
-
-    if (!source || !target)
-	return 0;
-
-    if (!(N_copy_gradient_neighbours_x(source->xt, target->xt)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_x(source->xc, target->xc)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_x(source->xb, target->xb)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_y(source->yt, target->yt)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_y(source->yc, target->yc)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_y(source->yb, target->yb)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_z(source->zt, target->zt)))
-	fail++;
-    if (!(N_copy_gradient_neighbours_z(source->zb, target->zb)))
-	fail++;
-
-    if (fail > 0) {
-	return 0;
-    }
-
-    return 1;
-}
-
-/*!
- * \brief Allocate a N_gradient_field_2d
- *
- * The field arrays are of type DCELL. 
- *
- * \param rows - number of rows of the 2d array from which the gradient should be calculated
- * \param cols - number of cols of the 2d array from which the gradient should be calculated
- * \return N_gradient_field_2d *
- *
- * */
-N_gradient_field_2d *N_alloc_gradient_field_2d(int cols, int rows)
-{
-    N_gradient_field_2d *field;
-
-    G_debug(5,
-	    "N_alloc_gradient_field_2d: allocate a N_gradient_field_2d struct");
-
-    field = (N_gradient_field_2d *) G_calloc(1, sizeof(N_gradient_field_2d));
-
-    field->x_array = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    field->y_array = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-
-    field->cols = cols;
-    field->rows = rows;
-
-    return field;
-}
-
-/*!
- * \brief Free's a N_gradient_neighbours_2d structure
- *
- * \return void
- *
- * */
-void N_free_gradient_field_2d(N_gradient_field_2d * field)
-{
-
-    N_free_array_2d(field->x_array);
-    N_free_array_2d(field->y_array);
-
-    G_free(field);
-
-    field = NULL;
-
-    return;
-}
-
-/*!
- * \brief Copy N_gradient_field_2d structure from source to target
- *
- * \param source - the source N_gradient_field_2d struct
- * \param target - the target N_gradient_field_2d struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int
-N_copy_gradient_field_2d(N_gradient_field_2d * source,
-			 N_gradient_field_2d * target)
-{
-    G_debug(3, "N_copy_gradient_field_2d: copy N_gradient_field_2d");
-
-    if (!source || !target)
-	return 0;
-
-    N_copy_array_2d(source->x_array, target->x_array);
-    N_copy_array_2d(source->y_array, target->y_array);
-
-    return 1;
-}
-
-/*! \brief Print gradient field information to stdout
- *
- * \param field N_gradient_2d_field *
- * \return void
- *
- * */
-void N_print_gradient_field_2d_info(N_gradient_field_2d * field)
-{
-    fprintf(stdout, "N_gradient_field_2d \n");
-    fprintf(stdout, "Cols %i\n", field->cols);
-    fprintf(stdout, "Rows: %i\n", field->rows);
-    fprintf(stdout, "X array pointer: %p\n", field->x_array);
-    fprintf(stdout, "Y array pointer: %p\n", field->y_array);
-    fprintf(stdout, "Min %g\n", field->min);
-    fprintf(stdout, "Max %g\n", field->max);
-    fprintf(stdout, "Sum %g\n", field->sum);
-    fprintf(stdout, "Mean %g\n", field->mean);
-    fprintf(stdout, "Nonull %i\n", field->nonull);
-    fprintf(stdout, "X array info \n");
-    N_print_array_2d_info(field->x_array);
-    fprintf(stdout, "Y array info \n");
-    N_print_array_2d_info(field->y_array);
-
-    return;
-}
-
-
-/*!
- * \brief Allocate a N_gradient_field_3d
- *
- * The field arrays are always of type DCELL_TYPE. 
- *
- * \param cols - number of cols of the 3d array from which the gradient should be calculated
- * \param rows - number of rows of the 3d array from which the gradient should be calculated
- * \param depths - number of depths of the 3d array from which the gradient should be calculated
- * \return N_gradient_field_3d *
- *
- * */
-N_gradient_field_3d *N_alloc_gradient_field_3d(int cols, int rows, int depths)
-{
-    N_gradient_field_3d *field;
-
-    G_debug(5,
-	    "N_alloc_gradient_field_3d: allocate a N_gradient_field_3d struct");
-
-    field = (N_gradient_field_3d *) G_calloc(1, sizeof(N_gradient_field_3d));
-
-    field->x_array = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    field->y_array = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    field->z_array = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-
-    field->cols = cols;
-    field->rows = rows;
-    field->depths = depths;
-
-    return field;
-}
-
-
-/*!
- * \brief Free's a N_gradient_neighbours_3d structure
- *
- * \return void
- *
- * */
-void N_free_gradient_field_3d(N_gradient_field_3d * field)
-{
-
-    N_free_array_3d(field->x_array);
-    N_free_array_3d(field->y_array);
-    N_free_array_3d(field->z_array);
-
-    G_free(field);
-
-    field = NULL;
-
-    return;
-}
-
-
-/*!
- * \brief Copy N_gradient_field_3d structure from source to target
- *
- * \param source - the source N_gradient_field_3d struct
- * \param target - the target N_gradient_field_3d struct
- * \return int - 1 success, 0 failure while copying
- *
- * */
-int
-N_copy_gradient_field_3d(N_gradient_field_3d * source,
-			 N_gradient_field_3d * target)
-{
-    G_debug(3, "N_copy_gradient_field_3d: copy N_gradient_field_3d");
-
-    if (!source || !target)
-	return 0;
-
-    N_copy_array_3d(source->x_array, target->x_array);
-    N_copy_array_3d(source->y_array, target->y_array);
-    N_copy_array_3d(source->z_array, target->z_array);
-
-    return 1;
-}
-
-/*! \brief Print gradient field information to stdout
- *
- * \param field N_gradient_3d_field *
- * \return void
- *
- * */
-void N_print_gradient_field_3d_info(N_gradient_field_3d * field)
-{
-
-    fprintf(stdout, "N_gradient_field_3d \n");
-    fprintf(stdout, "Cols %i\n", field->cols);
-    fprintf(stdout, "Rows: %i\n", field->rows);
-    fprintf(stdout, "Depths %i\n", field->depths);
-    fprintf(stdout, "X array pointer: %p\n", field->x_array);
-    fprintf(stdout, "Y array pointer: %p\n", field->y_array);
-    fprintf(stdout, "Z array pointer: %p\n", field->z_array);
-    fprintf(stdout, "Min %g\n", field->min);
-    fprintf(stdout, "Max %g\n", field->max);
-    fprintf(stdout, "Sum %g\n", field->sum);
-    fprintf(stdout, "Mean %g\n", field->mean);
-    fprintf(stdout, "Nonull %i\n", field->nonull);
-    fprintf(stdout, "X array info \n");
-    N_print_array_3d_info(field->x_array);
-    fprintf(stdout, "Y array info \n");
-    N_print_array_3d_info(field->y_array);
-    fprintf(stdout, "Z array info \n");
-    N_print_array_3d_info(field->z_array);
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_gradient_calc.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_gradient_calc.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_gradient_calc.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,657 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:     	gradient management functions 
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-
-/*! \brief Calculate basic statistics of a gradient field
- *
- * The statistic is stored in the gradient field struct
- *
- * \param field N_gradient_2d_field *
- * \return void
- *
- * */
-void N_calc_gradient_field_2d_stats(N_gradient_field_2d * field)
-{
-    double minx, miny;
-    double maxx, maxy;
-    double sumx, sumy;
-    int nonullx, nonully;
-
-    G_debug(3,
-	    "N_calc_gradient_field_2d_stats: compute gradient field stats");
-
-    N_calc_array_2d_stats(field->x_array, &minx, &maxx, &sumx, &nonullx, 0);
-    N_calc_array_2d_stats(field->y_array, &miny, &maxy, &sumy, &nonully, 0);
-
-    if (minx < miny)
-	field->min = minx;
-    else
-	field->min = miny;
-
-    if (maxx > maxy)
-	field->max = maxx;
-    else
-	field->max = maxy;
-
-    field->sum = sumx + sumy;
-    field->nonull = nonullx + nonully;
-    field->mean = field->sum / (double)field->nonull;
-
-    return;
-}
-
-/*!
- * \brief This function computes the gradient based on the input N_array_2d pot
- * (potential), a weighting factor N_array_2d named weight and the distance between two cells 
- * saved in the N_geom_data struct.
- *
- * The gradient is calculated between cells for each cell and direction.
- * An existing gradient field can be filled with new data or, if a NULL pointer is
- * given, a new gradient field will be allocated with the appropriate size.
- *
- *
- \verbatim
- ______________ 
- |    |    |    |
- |    |    |    |
- |----|-NC-|----|
- |    |    |    |
- |   WC    EC   |
- |    |    |    |
- |----|-SC-|----|
- |    |    |    |
- |____|____|____|
-
-
- x - direction:
-
- r = 2 * weight[row][col]*weight[row][col + 1] / (weight[row][col]*weight[row][col + 1])
- EC = r * (pot[row][col] - pot[row][col + 1])/dx
-
- y - direction:
-
- r = 2 * weight[row][col]*weight[row + 1][col] / (weight[row][col]*weight[row + 1][col])
- SC = r * (pot[row][col] - pot[row + 1][col])/dy
-
- the values SC and EC are the values of the next row/col
-
-
- \endverbatim
- * \param pot N_array_2d * - the potential N_array_2d 
- * \param weight_x N_array_2d * - the weighting factor N_array_2d used to modify the gradient in x-direction
- * \param weight_y N_array_2d * - the weighting factor N_array_2d used to modify the gradient in y-direction
- * \param geom N_geom_data * - geometry data structure
- * \param gradfield N_gradient_field_2d * - a gradient field of the correct size, if a NULL pointer is provided this gradient field will be new allocated
- * \return N_gradient_field_2d * - the pointer to the computed gradient field
-
- *
- * */
-N_gradient_field_2d *N_compute_gradient_field_2d(N_array_2d * pot,
-						 N_array_2d * weight_x,
-						 N_array_2d * weight_y,
-						 N_geom_data * geom,
-						 N_gradient_field_2d *
-						 gradfield)
-{
-    int i, j;
-    int rows, cols;
-    double dx, dy, p1, p2, r1, r2, mean, grad, res;
-    N_gradient_field_2d *field = gradfield;
-
-
-    if (pot->cols != weight_x->cols || pot->cols != weight_y->cols)
-	G_fatal_error
-	    ("N_compute_gradient_field_2d: the arrays are not of equal size");
-
-    if (pot->rows != weight_x->rows || pot->rows != weight_y->rows)
-	G_fatal_error
-	    ("N_compute_gradient_field_2d: the arrays are not of equal size");
-
-    if (pot->cols != geom->cols || pot->rows != geom->rows)
-	G_fatal_error
-	    ("N_compute_gradient_field_2d: array sizes and geometry data are different");
-
-
-    G_debug(3, "N_compute_gradient_field_2d: compute gradient field");
-
-    rows = pot->rows;
-    cols = pot->cols;
-    dx = geom->dx;
-    dy = geom->dy;
-
-    if (field == NULL) {
-	field = N_alloc_gradient_field_2d(cols, rows);
-    }
-    else {
-	if (field->cols != geom->cols || field->rows != geom->rows)
-	    G_fatal_error
-		("N_compute_gradient_field_2d: gradient field sizes and geometry data are different");
-    }
-
-
-    for (j = 0; j < rows; j++)
-	for (i = 0; i < cols - 1; i++) {
-	    grad = 0;
-	    mean = 0;
-
-	    /* Only compute if the arrays are not null */
-	    if (!N_is_array_2d_value_null(pot, i, j) &&
-		!N_is_array_2d_value_null(pot, i + 1, j)) {
-		p1 = N_get_array_2d_d_value(pot, i, j);
-		p2 = N_get_array_2d_d_value(pot, i + 1, j);
-		grad = (p1 - p2) / dx;	/* gradient */
-	    }
-	    if (!N_is_array_2d_value_null(weight_x, i, j) &&
-		!N_is_array_2d_value_null(weight_x, i + 1, j)) {
-		r1 = N_get_array_2d_d_value(weight_x, i, j);
-		r2 = N_get_array_2d_d_value(weight_x, i + 1, j);
-		mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
-	    }
-
-	    res = mean * grad;
-
-	    N_put_array_2d_d_value(field->x_array, i + 1, j, res);
-
-	}
-
-    for (j = 0; j < rows - 1; j++)
-	for (i = 0; i < cols; i++) {
-	    grad = 0;
-	    mean = 0;
-
-	    /* Only compute if the arrays are not null */
-	    if (!N_is_array_2d_value_null(pot, i, j) &&
-		!N_is_array_2d_value_null(pot, i, j + 1)) {
-		p1 = N_get_array_2d_d_value(pot, i, j);
-		p2 = N_get_array_2d_d_value(pot, i, j + 1);
-		grad = (p1 - p2) / dy;	/* gradient */
-	    }
-	    if (!N_is_array_2d_value_null(weight_y, i, j) &&
-		!N_is_array_2d_value_null(weight_y, i, j + 1)) {
-		r1 = N_get_array_2d_d_value(weight_y, i, j);
-		r2 = N_get_array_2d_d_value(weight_y, i, j + 1);
-		mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
-	    }
-
-	    res = -1 * mean * grad;
-
-	    N_put_array_2d_d_value(field->y_array, i, j + 1, res);
-
-	}
-
-    /*Compute gradient field statistics */
-    N_calc_gradient_field_2d_stats(field);
-
-    return field;
-}
-
-/*! 
- * \brief Calculate the x and y vector components from a gradient field for each 
- * cell and stores them in the provided N_array_2d structures
- *
- * The arrays must have the same size as the gradient field.
-
- \verbatim
-
- Based on this storages scheme the gradient vector for each cell is 
- calculated and stored in the provided  N_array_2d structures
-
- ______________ 
- |    |    |    |
- |    |    |    |
- |----|-NC-|----|
- |    |    |    |
- |   WC    EC   |
- |    |    |    |
- |----|-SC-|----|
- |    |    |    |
- |____|____|____|
-
- x vector component:
-
- x = (WC + EC) / 2
-
- y vector component:
-
- y = (NC + SC) / 2
-
- \endverbatim
- *
- * \param field N_gradient_field_2d *
- * \param x_comp N_array_2d * - the array in which the x component will be written
- * \param y_comp N_array_2d * - the array in which the y component will be written
- *
- * \return void
- * */
-void
-N_compute_gradient_field_components_2d(N_gradient_field_2d * field,
-				       N_array_2d * x_comp,
-				       N_array_2d * y_comp)
-{
-    int i, j;
-
-    int rows, cols;
-
-    double vx, vy;
-
-    N_array_2d *x = x_comp;
-
-    N_array_2d *y = y_comp;
-
-    N_gradient_2d grad;
-
-
-    if (!x)
-	G_fatal_error("N_compute_gradient_components_2d: x array is empty");
-    if (!y)
-	G_fatal_error("N_compute_gradient_components_2d: y array is empty");
-
-    cols = field->x_array->cols;
-    rows = field->x_array->rows;
-
-    /*Check the array sizes */
-    if (x->cols != cols || x->rows != rows)
-	G_fatal_error
-	    ("N_compute_gradient_components_2d: the size of the x array doesn't fit the gradient field size");
-    if (y->cols != cols || y->rows != rows)
-	G_fatal_error
-	    ("N_compute_gradient_components_2d: the size of the y array doesn't fit the gradient field size");
-
-    for (j = 0; j < rows; j++)
-	for (i = 0; i < cols; i++) {
-	    N_get_gradient_2d(field, &grad, i, j);
-
-	    /* in case a gradient is zero, we expect a no flow boundary */
-	    if (grad.WC == 0.0 || grad.EC == 0.0)
-		vx = (grad.WC + grad.EC);
-	    else
-		vx = (grad.WC + grad.EC) / 2;
-	    if (grad.NC == 0.0 || grad.SC == 0.0)
-		vy = (grad.NC + grad.SC);
-	    else
-		vy = (grad.NC + grad.SC) / 2;
-
-	    N_put_array_2d_d_value(x, i, j, vx);
-	    N_put_array_2d_d_value(y, i, j, vy);
-	}
-
-    return;
-}
-
-/*! \brief Calculate basic statistics of a gradient field
- *
- * The statistic is stored in the gradient field struct
- *
- * \param field N_gradient_3d_field *
- * \return void
- *
- * */
-void N_calc_gradient_field_3d_stats(N_gradient_field_3d * field)
-{
-    double minx, miny, minz;
-
-    double maxx, maxy, maxz;
-
-    double sumx, sumy, sumz;
-
-    int nonullx, nonully, nonullz;
-
-    G_debug(3,
-	    "N_calc_gradient_field_3d_stats: compute gradient field stats");
-
-    N_calc_array_3d_stats(field->x_array, &minx, &maxx, &sumx, &nonullx, 0);
-    N_calc_array_3d_stats(field->y_array, &miny, &maxy, &sumy, &nonully, 0);
-    N_calc_array_3d_stats(field->z_array, &minz, &maxz, &sumz, &nonullz, 0);
-
-    if (minx <= minz && minx <= miny)
-	field->min = minx;
-    if (miny <= minz && miny <= minx)
-	field->min = miny;
-    if (minz <= minx && minz <= miny)
-	field->min = minz;
-
-    if (maxx >= maxz && maxx >= maxy)
-	field->max = maxx;
-    if (maxy >= maxz && maxy >= maxx)
-	field->max = maxy;
-    if (maxz >= maxx && maxz >= maxy)
-	field->max = maxz;
-
-    field->sum = sumx + sumy + sumz;
-    field->nonull = nonullx + nonully + nonullz;
-    field->mean = field->sum / (double)field->nonull;
-
-    return;
-}
-
-
-/*!
- * \brief This function computes the gradient based on the input N_array_3d pot
- * (that means potential), a weighting factor N_array_3d named weight and the distance between two cells 
- * saved in the N_geom_data struct.
- *
- * The gradient is calculated between cells for each cell and direction.
- * An existing gradient field can be filled with new data or, if a NULL pointer is
- * given, a new gradient field will be allocated with the appropriate size.
- *
- *
- *
- *
- \verbatim
-
- |  /
- TC NC
- |/
- --WC-----EC--
- /|
- SC BC
- /  |
-
- x - direction:
-
- r = 2 * weight_x[depth][row][col]*weight_x[depth][row][col + 1] / (weight_X[depth][row][col]*weight_x[depth][row][col + 1])
- EC = r * (pot[depth][row][col] - pot[depth][row][col + 1])/dx
-
- y - direction:
-
- r = 2 * weight_y[depth][row][col]*weight_y[depth][row + 1][col] / (weight_y[depth][row][col]*weight_y[depth][row + 1][col])
- SC = r * (pot[depth][row][col] - pot[depth][row + 1][col])/dy
-
- z - direction:
-
- r = 2 * weight_z[depth][row][col]*weight_z[depth + 1][row][col] / (weight_z[depth][row][col]*weight_z[depth + 1][row][col])
- TC = r * (pot[depth][row][col] - pot[depth + 1][row][col])/dy
-
- the values BC, NC, WC are the values of the next depth/row/col
-
-
- \endverbatim
- * \param pot N_array_3d * - the potential N_array_2d 
- * \param weight_x N_array_3d * - the weighting factor N_array_3d used to modify the gradient in x-direction
- * \param weight_y N_array_3d * - the weighting factor N_array_3d used to modify the gradient in y-direction
- * \param weight_z N_array_3d * - the weighting factor N_array_3d used to modify the gradient in z-direction
- * \param geom N_geom_data * - geometry data structure
- * \param gradfield N_gradient_field_3d * - a gradient field of the correct size, if a NULL pointer is provided this gradient field will be new allocated
- * \return N_gradient_field_3d * - the pointer to the computed gradient field
- *
- * */
-N_gradient_field_3d *N_compute_gradient_field_3d(N_array_3d * pot,
-						 N_array_3d * weight_x,
-						 N_array_3d * weight_y,
-						 N_array_3d * weight_z,
-						 N_geom_data * geom,
-						 N_gradient_field_3d *
-						 gradfield)
-{
-    int i, j, k;
-
-    int cols, rows, depths;
-
-    double dx, dy, dz, p1, p2, r1, r2, mean, grad, res;
-
-    N_gradient_field_3d *field = gradfield;
-
-
-    if (pot->cols != weight_x->cols || pot->cols != weight_y->cols ||
-	pot->cols != weight_z->cols)
-	G_fatal_error
-	    ("N_compute_gradient_field_3d: the arrays are not of equal size");
-
-    if (pot->rows != weight_x->rows || pot->rows != weight_y->rows ||
-	pot->rows != weight_z->rows)
-	G_fatal_error
-	    ("N_compute_gradient_field_3d: the arrays are not of equal size");
-
-    if (pot->depths != weight_x->depths || pot->depths != weight_y->depths ||
-	pot->depths != weight_z->depths)
-	G_fatal_error
-	    ("N_compute_gradient_field_3d: the arrays are not of equal size");
-
-    if (pot->cols != geom->cols || pot->rows != geom->rows ||
-	pot->depths != geom->depths)
-	G_fatal_error
-	    ("N_compute_gradient_field_3d: array sizes and geometry data are different");
-
-    G_debug(3, "N_compute_gradient_field_3d: compute gradient field");
-
-    cols = geom->cols;
-    rows = geom->rows;
-    depths = geom->depths;
-    dx = geom->dx;
-    dy = geom->dy;
-    dz = geom->dz;
-
-    if (gradfield == NULL) {
-	field = N_alloc_gradient_field_3d(cols, rows, depths);
-    }
-    else {
-	if (field->cols != geom->cols || field->rows != geom->rows ||
-	    field->depths != geom->depths)
-	    G_fatal_error
-		("N_compute_gradient_field_3d: gradient field sizes and geometry data are different");
-    }
-
-    for (k = 0; k < depths; k++)
-	for (j = 0; j < rows; j++)
-	    for (i = 0; i < cols - 1; i++) {
-		grad = 0;
-		mean = 0;
-
-		/*Only compute if the arrays are not null */
-		if (!N_is_array_3d_value_null(pot, i, j, k) &&
-		    !N_is_array_3d_value_null(pot, i + 1, j, k)) {
-		    p1 = N_get_array_3d_d_value(pot, i, j, k);
-		    p2 = N_get_array_3d_d_value(pot, i + 1, j, k);
-		    grad = (p1 - p2) / dx;	/* gradient */
-		}
-		if (!N_is_array_3d_value_null(weight_x, i, j, k) &&
-		    !N_is_array_3d_value_null(weight_x, i + 1, j, k)) {
-		    r1 = N_get_array_3d_d_value(weight_x, i, j, k);
-		    r2 = N_get_array_3d_d_value(weight_x, i + 1, j, k);
-		    mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
-		}
-
-		res = mean * grad;
-
-		G_debug(6,
-			"N_compute_gradient_field_3d: X-direction insert value %6.5g at %i %i %i ",
-			res, k, j, i + 1);
-
-		N_put_array_3d_d_value(field->x_array, i + 1, j, k, res);
-
-	    }
-
-    for (k = 0; k < depths; k++)
-	for (j = 0; j < rows - 1; j++)
-	    for (i = 0; i < cols; i++) {
-		grad = 0;
-		mean = 0;
-
-		/* Only compute if the arrays are not null */
-		if (!N_is_array_3d_value_null(pot, i, j, k) &&
-		    !N_is_array_3d_value_null(pot, i, j + 1, k)) {
-		    p1 = N_get_array_3d_d_value(pot, i, j, k);
-		    p2 = N_get_array_3d_d_value(pot, i, j + 1, k);
-		    grad = (p1 - p2) / dy;	/* gradient */
-		}
-		if (!N_is_array_3d_value_null(weight_y, i, j, k) &&
-		    !N_is_array_3d_value_null(weight_y, i, j + 1, k)) {
-		    r1 = N_get_array_3d_d_value(weight_y, i, j, k);
-		    r2 = N_get_array_3d_d_value(weight_y, i, j + 1, k);
-		    mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
-		}
-
-		res = -1 * mean * grad;	/*invert the direction, because we count from north to south,
-					 * but the gradient is defined in y direction */
-
-		G_debug(6,
-			"N_compute_gradient_field_3d: Y-direction insert value %6.5g at %i %i %i ",
-			res, k, j + 1, i);
-
-		N_put_array_3d_d_value(field->y_array, i, j + 1, k, res);
-
-	    }
-
-    for (k = 0; k < depths - 1; k++)
-	for (j = 0; j < rows; j++)
-	    for (i = 0; i < cols; i++) {
-		grad = 0;
-		mean = 0;
-
-		/* Only compute if the arrays are not null */
-		if (!N_is_array_3d_value_null(pot, i, j, k) &&
-		    !N_is_array_3d_value_null(pot, i, j, k + 1)) {
-		    p1 = N_get_array_3d_d_value(pot, i, j, k);
-		    p2 = N_get_array_3d_d_value(pot, i, j, k + 1);
-		    grad = (p1 - p2) / dz;	/* gradient */
-		}
-		if (!N_is_array_3d_value_null(weight_z, i, j, k) &&
-		    !N_is_array_3d_value_null(weight_z, i, j, k + 1)) {
-		    r1 = N_get_array_3d_d_value(weight_z, i, j, k);
-		    r2 = N_get_array_3d_d_value(weight_z, i, j, k + 1);
-		    mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
-		}
-
-		res = mean * grad;
-
-		G_debug(6,
-			"N_compute_gradient_field_3d: Z-direction insert value %6.5g at %i %i %i ",
-			res, k + 1, j, i);
-
-		N_put_array_3d_d_value(field->z_array, i, j, k + 1, res);
-
-	    }
-
-    /*Compute gradient field statistics */
-    N_calc_gradient_field_3d_stats(field);
-
-    return field;
-}
-
-/*! 
- * \brief Calculate the x, y and z vector components from a gradient field for each cell 
- *  and store them in the provided N_array_3d structures
- *
- * The arrays must have the same size as the gradient field.
- *
- \verbatim
-
- Based on this storages scheme the gradient vector for each cell is 
- calculated and stored in the provided  N_array_3d structures
-
-
- |  /
- TC NC
- |/
- --WC-----EC--
- /|
- SC BC
- /  |
-
-
- x vector component:
-
- x = (WC + EC) / 2
-
- y vector component:
-
- y = (NC + SC) / 2
-
- z vector component:
-
- z = (TC + BC) / 2
-
- \endverbatim
-
- * \param field N_gradient_field_3d *
- * \param x_comp N_array_3d * - the array in which the x component will be written
- * \param y_comp N_array_3d * - the array in which the y component will be written
- * \param z_comp N_array_3d * - the array in which the z component will be written
- *
- * \return void
- * */
-void
-N_compute_gradient_field_components_3d(N_gradient_field_3d * field,
-				       N_array_3d * x_comp,
-				       N_array_3d * y_comp,
-				       N_array_3d * z_comp)
-{
-    int i, j, k;
-
-    int rows, cols, depths;
-
-    double vx, vy, vz;
-
-    N_array_3d *x = x_comp;
-
-    N_array_3d *y = y_comp;
-
-    N_array_3d *z = z_comp;
-
-    N_gradient_3d grad;
-
-
-    if (!x)
-	G_fatal_error("N_compute_gradient_components_3d: x array is empty");
-    if (!y)
-	G_fatal_error("N_compute_gradient_components_3d: y array is empty");
-    if (!z)
-	G_fatal_error("N_compute_gradient_components_3d: z array is empty");
-
-    cols = field->x_array->cols;
-    rows = field->x_array->rows;
-    depths = field->x_array->depths;
-
-    /*Check the array sizes */
-    if (x->cols != cols || x->rows != rows || x->depths != depths)
-	G_fatal_error
-	    ("N_compute_gradient_components_3d: the size of the x array doesn't fit the gradient field size");
-    if (y->cols != cols || y->rows != rows || y->depths != depths)
-	G_fatal_error
-	    ("N_compute_gradient_components_3d: the size of the y array doesn't fit the gradient field size");
-    if (z->cols != cols || z->rows != rows || z->depths != depths)
-	G_fatal_error
-	    ("N_compute_gradient_components_3d: the size of the z array doesn't fit the gradient field size");
-
-    for (k = 0; k < depths; k++)
-	for (j = 0; j < rows; j++)
-	    for (i = 0; i < cols; i++) {
-		N_get_gradient_3d(field, &grad, i, j, k);
-		/* in case a gradient is zero, we expect a no flow boundary */
-		if (grad.WC == 0.0 || grad.EC == 0.0)
-		    vx = (grad.WC + grad.EC);
-		else
-		    vx = (grad.WC + grad.EC) / 2;
-		if (grad.NC == 0.0 || grad.SC == 0.0)
-		    vy = (grad.NC + grad.SC);
-		else
-		    vy = (grad.NC + grad.SC) / 2;
-		if (grad.TC == 0.0 || grad.BC == 0.0)
-		    vz = (grad.TC + grad.BC);
-		else
-		    vz = (grad.TC + grad.BC) / 2;
-
-		N_put_array_3d_d_value(x, i, j, k, vx);
-		N_put_array_3d_d_value(y, i, j, k, vy);
-		N_put_array_3d_d_value(z, i, j, k, vz);
-	    }
-
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_gwflow.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_gwflow.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_gwflow.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,720 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:      groundwater flow in porous media 
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_gwflow.h>
-
-/* *************************************************************** */
-/* ***************** N_gwflow_data3d ***************************** */
-/* *************************************************************** */
-/*!
- * \brief Alllocate memory for the groundwater calculation data structure in 3 dimensions
- *
- * The groundwater calculation data structure will be allocated including
- * all appendant 3d and 2d arrays. The offset for the 3d arrays is one
- * to establish homogeneous Neumann boundary conditions at the calculation area border.
- * This data structure is used to create a linear equation system based on the computation of
- * groundwater flow in porous media with the finite volume method.
- *
- * \param cols   int
- * \param rows   int
- * \param depths int
- * \return N_gwflow_data3d *
- * */
-N_gwflow_data3d *N_alloc_gwflow_data3d(int cols, int rows, int depths,
-				       int river, int drain)
-{
-    N_gwflow_data3d *data;
-
-    data = (N_gwflow_data3d *) G_calloc(1, sizeof(N_gwflow_data3d));
-
-    data->phead = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->phead_start = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->status = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->hc_x = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->hc_y = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->hc_z = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->q = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->s = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->nf = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->r = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-
-    if (river) {
-	data->river_head =
-	    N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-	data->river_leak =
-	    N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-	data->river_bed = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    }
-    else {
-	data->river_head = NULL;
-	data->river_leak = NULL;
-	data->river_bed = NULL;
-    }
-
-    if (drain) {
-	data->drain_leak =
-	    N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-	data->drain_bed = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    }
-    else {
-	data->drain_leak = NULL;
-	data->drain_bed = NULL;
-    }
-
-    return data;
-}
-
-/* *************************************************************** */
-/* ********************* N_free_gwflow_data3d ******************** */
-/* *************************************************************** */
-/*!
- * \brief Release the memory of the groundwater flow data structure in three dimensions
- *
- * \param data N_gwflow_data3d *
- * \return void *
- * */
-
-void N_free_gwflow_data3d(N_gwflow_data3d * data)
-{
-    if (data->phead)
-	N_free_array_3d(data->phead);
-    if (data->phead_start)
-	N_free_array_3d(data->phead_start);
-    if (data->status)
-	N_free_array_3d(data->status);
-    if (data->hc_x)
-	N_free_array_3d(data->hc_x);
-    if (data->hc_y)
-	N_free_array_3d(data->hc_y);
-    if (data->hc_z)
-	N_free_array_3d(data->hc_z);
-    if (data->q)
-	N_free_array_3d(data->q);
-    if (data->s)
-	N_free_array_3d(data->s);
-    if (data->nf)
-	N_free_array_3d(data->nf);
-    if (data->r)
-	N_free_array_2d(data->r);
-    if (data->river_head)
-	N_free_array_3d(data->river_head);
-    if (data->river_leak)
-	N_free_array_3d(data->river_leak);
-    if (data->river_bed)
-	N_free_array_3d(data->river_bed);
-    if (data->drain_leak)
-	N_free_array_3d(data->drain_leak);
-    if (data->drain_bed)
-	N_free_array_3d(data->drain_bed);
-
-    G_free(data);
-
-    data = NULL;
-
-    return;
-}
-
-/* *************************************************************** */
-/* ******************** N_alloc_gwflow_data2d ******************** */
-/* *************************************************************** */
-/*!
- * \brief Alllocate memory for the groundwater calculation data structure in 2 dimensions
- * 
- * The groundwater calculation data structure will be allocated including
- * all appendant 2d arrays. The offset for the 3d arrays is one
- * to establish homogeneous Neumann boundary conditions at the calculation area border.
- * This data structure is used to create a linear equation system based on the computation of
- * groundwater flow in porous media with the finite volume method.
- *
- * \param cols int
- * \param rows int
- * \return N_gwflow_data2d *
- * */
-N_gwflow_data2d *N_alloc_gwflow_data2d(int cols, int rows, int river,
-				       int drain)
-{
-    N_gwflow_data2d *data;
-
-    data = (N_gwflow_data2d *) G_calloc(1, sizeof(N_gwflow_data2d));
-
-    data->phead = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->phead_start = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->status = N_alloc_array_2d(cols, rows, 1, CELL_TYPE);
-    data->hc_x = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->hc_y = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->q = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->s = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->nf = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->r = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->top = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->bottom = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-
-    if (river) {
-	data->river_head = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-	data->river_leak = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-	data->river_bed = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    }
-    else {
-	data->river_head = NULL;
-	data->river_leak = NULL;
-	data->river_bed = NULL;
-    }
-
-    if (drain) {
-	data->drain_leak = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-	data->drain_bed = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    }
-    else {
-	data->drain_leak = NULL;
-	data->drain_bed = NULL;
-    }
-
-
-    return data;
-}
-
-/* *************************************************************** */
-/* ****************** N_free_gwflow_data2d *********************** */
-/* *************************************************************** */
-/*!
- * \brief Release the memory of the groundwater flow data structure in two dimensions
- *
- * \param data N_gwflow_data2d *
- * \return void
- * */
-void N_free_gwflow_data2d(N_gwflow_data2d * data)
-{
-    if (data->phead)
-	N_free_array_2d(data->phead);
-    if (data->phead_start)
-	N_free_array_2d(data->phead_start);
-    if (data->status)
-	N_free_array_2d(data->status);
-    if (data->hc_x)
-	N_free_array_2d(data->hc_x);
-    if (data->hc_y)
-	N_free_array_2d(data->hc_y);
-    if (data->q)
-	N_free_array_2d(data->q);
-    if (data->s)
-	N_free_array_2d(data->s);
-    if (data->nf)
-	N_free_array_2d(data->nf);
-    if (data->r)
-	N_free_array_2d(data->r);
-    if (data->top)
-	N_free_array_2d(data->top);
-    if (data->bottom)
-	N_free_array_2d(data->bottom);
-    if (data->river_head)
-	N_free_array_2d(data->river_head);
-    if (data->river_leak)
-	N_free_array_2d(data->river_leak);
-    if (data->river_bed)
-	N_free_array_2d(data->river_bed);
-    if (data->drain_leak)
-	N_free_array_2d(data->drain_leak);
-    if (data->drain_bed)
-	N_free_array_2d(data->drain_bed);
-
-    G_free(data);
-
-    data = NULL;;
-
-    return;
-}
-
-/* *************************************************************** */
-/* ***************** N_callback_gwflow_3d ************************ */
-/* *************************************************************** */
-/*!
- * \brief This callback function creates the mass balance of a 7 point star
- *
- * The mass balance is based on the common groundwater flow equation:
- *
- * \f[Ss \frac{\partial h}{\partial t} = \nabla {\bf K} \nabla h + q \f]
- *
- * This equation is discretizised with the finite volume method in three dimensions.
- *
- *
- * \param gwdata N_gwflow_data3d *
- * \param geom N_geom_data *
- * \param col   int
- * \param row   int
- * \param depth int
- * \return N_data_star *
- *
- * */
-N_data_star *N_callback_gwflow_3d(void *gwdata, N_geom_data * geom, int col,
-				  int row, int depth)
-{
-    double hc_e = 0, hc_w = 0, hc_n = 0, hc_s = 0, hc_t = 0, hc_b = 0;
-    double dx, dy, dz, Ax, Ay, Az;
-    double hc_x, hc_y, hc_z;
-    double hc_xw, hc_yn, hc_zt;
-    double hc_xe, hc_ys, hc_zb;
-    double hc_start;
-    double Ss, r, nf, q;
-    double C, W, E, N, S, T, B, V;
-    N_data_star *mat_pos;
-    N_gwflow_data3d *data;
-
-    /*cast the void pointer to the right data structure */
-    data = (N_gwflow_data3d *) gwdata;
-
-    dx = geom->dx;
-    dy = geom->dy;
-    dz = geom->dz;
-    Az = N_get_geom_data_area_of_cell(geom, row);
-    Ay = geom->dx * geom->dz;
-    Ax = geom->dz * geom->dy;
-
-    /*read the data from the arrays */
-    hc_start = N_get_array_3d_d_value(data->phead_start, col, row, depth);
-
-    hc_x = N_get_array_3d_d_value(data->hc_x, col, row, depth);
-    hc_y = N_get_array_3d_d_value(data->hc_y, col, row, depth);
-    hc_z = N_get_array_3d_d_value(data->hc_z, col, row, depth);
-
-    hc_xw = N_get_array_3d_d_value(data->hc_x, col - 1, row, depth);
-    hc_xe = N_get_array_3d_d_value(data->hc_x, col + 1, row, depth);
-    hc_yn = N_get_array_3d_d_value(data->hc_y, col, row - 1, depth);
-    hc_ys = N_get_array_3d_d_value(data->hc_y, col, row + 1, depth);
-    hc_zt = N_get_array_3d_d_value(data->hc_z, col, row, depth + 1);
-    hc_zb = N_get_array_3d_d_value(data->hc_z, col, row, depth - 1);
-
-    hc_w = N_calc_harmonic_mean(hc_xw, hc_x);
-    hc_e = N_calc_harmonic_mean(hc_xe, hc_x);
-    hc_n = N_calc_harmonic_mean(hc_yn, hc_y);
-    hc_s = N_calc_harmonic_mean(hc_ys, hc_y);
-    hc_t = N_calc_harmonic_mean(hc_zt, hc_z);
-    hc_b = N_calc_harmonic_mean(hc_zb, hc_z);
-
-    /*inner sources */
-    q = N_get_array_3d_d_value(data->q, col, row, depth);
-    /*storativity */
-    Ss = N_get_array_3d_d_value(data->s, col, row, depth);
-    /*porosity */
-    nf = N_get_array_3d_d_value(data->nf, col, row, depth);
-
-    /*mass balance center cell to western cell */
-    W = -1 * Ax * hc_w / dx;
-    /*mass balance center cell to eastern cell */
-    E = -1 * Ax * hc_e / dx;
-    /*mass balance center cell to northern cell */
-    N = -1 * Ay * hc_n / dy;
-    /*mass balance center cell to southern cell */
-    S = -1 * Ay * hc_s / dy;
-    /*mass balance center cell to top cell */
-    T = -1 * Az * hc_t / dz;
-    /*mass balance center cell to bottom cell */
-    B = -1 * Az * hc_b / dz;
-
-    /*storativity */
-    Ss = Az * dz * Ss;
-
-    /*the diagonal entry of the matrix */
-    C = -1 * (W + E + N + S + T + B - Ss / data->dt * Az);
-
-    /*the entry in the right side b of Ax = b */
-    V = (q + hc_start * Ss / data->dt * Az);
-
-    /*only the top cells will have recharge */
-    if (depth == geom->depths - 2) {
-	r = N_get_array_2d_d_value(data->r, col, row);
-	V += r * Az;
-    }
-
-    G_debug(5, "N_callback_gwflow_3d: called [%i][%i][%i]", depth, col, row);
-
-    /*create the 7 point star entries */
-    mat_pos = N_create_7star(C, W, E, N, S, T, B, V);
-
-    return mat_pos;
-}
-
-
-/* *************************************************************** */
-/* ****************** N_gwflow_3d_calc_water_budget ************** */
-/* *************************************************************** */
-/*!
- * \brief This function computes the water budget of the entire groundwater
- *
- * The water budget is calculated for each active and dirichlet cell from
- * its surrounding neighbours. This is based on the 7 star mass balance computation
- * of N_callback_gwflow_3d and the gradient of the water heights in the cells.
- * The sum of the water budget of each active/dirichlet cell must be near zero
- * due the effect of numerical inaccuracy of cpu's.
- *
- * \param gwdata N_gwflow_data3d *
- * \param geom N_geom_data *
- * \param budget N_array_3d
- * \return void
- *
- * */
-void
-N_gwflow_3d_calc_water_budget(N_gwflow_data3d * data, N_geom_data * geom, N_array_3d * budget)
-{
-    int z, y, x, stat;
-    double h, hc;
-    double val;
-    double sum;
-    N_data_star *dstar;
-
-    int rows = data->status->rows;
-    int cols = data->status->cols;
-    int depths = data->status->depths;
-    sum = 0;
-
-    for (z = 0; z < depths; z++) {
-        for (y = 0; y < rows; y++) {
-            G_percent(y, rows - 1, 10);
-            for (x = 0; x < cols; x++) {
-                stat = (int)N_get_array_3d_d_value(data->status, x, y, z);
-
-                val = 0.0;
-
-                if (stat != N_CELL_INACTIVE ) {	/*all active/dirichlet cells */
-
-                    /* Compute the flow parameter */
-                    dstar = N_callback_gwflow_3d(data, geom, x, y, z);
-                    /* Compute the gradient in each direction pointing from the center */
-                    hc = N_get_array_3d_d_value(data->phead, x, y, z);
-
-                    if((int)N_get_array_3d_d_value(data->status, x + 1, y    , z) != N_CELL_INACTIVE) {
-                        h = N_get_array_3d_d_value(data->phead,  x + 1, y    , z);
-                        val += dstar->E * (hc - h);
-                    }
-                    if((int)N_get_array_3d_d_value(data->status, x - 1, y    , z) != N_CELL_INACTIVE) {
-                        h = N_get_array_3d_d_value(data->phead,  x - 1, y    , z);
-                        val += dstar->W * (hc - h);
-                    }
-                    if((int)N_get_array_3d_d_value(data->status, x    , y + 1, z) != N_CELL_INACTIVE) {
-                        h = N_get_array_3d_d_value(data->phead,  x    , y + 1, z);
-                        val += dstar->S * (hc - h);
-                    }
-                    if((int)N_get_array_3d_d_value(data->status, x    , y - 1, z) != N_CELL_INACTIVE) {
-                        h = N_get_array_3d_d_value(data->phead,  x    , y - 1, z);
-                        val += dstar->N * (hc - h);
-                    }
-                    if((int)N_get_array_3d_d_value(data->status, x    , y    , z + 1) != N_CELL_INACTIVE) {
-                        h = N_get_array_3d_d_value(data->phead,  x    , y    , z + 1);
-                        val += dstar->T * (hc - h);
-                    }
-                    if((int)N_get_array_3d_d_value(data->status, x    , y    , z - 1) != N_CELL_INACTIVE) {
-                        h = N_get_array_3d_d_value(data->phead,  x    , y    , z - 1);
-                        val += dstar->B * (hc - h);
-                    }
-                    sum += val;
-
-                    G_free(dstar);
-                }
-                else {
-                    Rast_set_null_value(&val, 1, DCELL_TYPE);
-                }
-                N_put_array_3d_d_value(budget, x, y, z, val);
-            }
-        }
-    }
-
-    if(fabs(sum) < 0.0000000001)
-        G_message(_("The total sum of the water budget: %g\n"), sum);
-    else
-        G_warning(_("The total sum of the water budget is significant larger then 0: %g\n"), sum);
-
-    return;
-}
-
-
-
-/* *************************************************************** */
-/* ****************** N_callback_gwflow_2d *********************** */
-/* *************************************************************** */
-/*!
- * \brief This callback function creates the mass balance of a 5 point star
- *
- * The mass balance is based on the common groundwater flow equation:
- *
- * \f[Ss \frac{\partial h}{\partial t} = \nabla {\bf K} \nabla h + q \f]
- *
- * This equation is discretizised with the finite volume method in two dimensions.
- *
- * \param gwdata N_gwflow_data2d *
- * \param geom N_geom_data *
- * \param col int
- * \param row int
- * \return N_data_star *
- *
- * */
-N_data_star *N_callback_gwflow_2d(void *gwdata, N_geom_data * geom, int col,
-				  int row)
-{
-    double T_e = 0, T_w = 0, T_n = 0, T_s = 0;
-    double z_e = 0, z_w = 0, z_n = 0, z_s = 0;
-    double dx, dy, Az;
-    double hc_x, hc_y;
-    double z, top;
-    double hc_xw, hc_yn;
-    double z_xw, z_yn;
-    double hc_xe, hc_ys;
-    double z_xe, z_ys;
-    double hc, hc_start;
-    double Ss, r, q;
-    double C, W, E, N, S, V;
-    N_gwflow_data2d *data;
-    N_data_star *mat_pos;
-    double river_vect = 0;	/*entry in vector */
-    double river_mat = 0;	/*entry in matrix */
-    double drain_vect = 0;	/*entry in vector */
-    double drain_mat = 0;	/*entry in matrix */
-
-    /*cast the void pointer to the right data structure */
-    data = (N_gwflow_data2d *) gwdata;
-
-    dx = geom->dx;
-    dy = geom->dy;
-    Az = N_get_geom_data_area_of_cell(geom, row);
-
-    /*read the data from the arrays */
-    hc_start = N_get_array_2d_d_value(data->phead_start, col, row);
-    hc = N_get_array_2d_d_value(data->phead, col, row);
-    top = N_get_array_2d_d_value(data->top, col, row);
-
-    /* Inner sources */
-    q = N_get_array_2d_d_value(data->q, col, row);
-
-    /* storativity or porosity of current cell face [-]*/
-    Ss = N_get_array_2d_d_value(data->s, col, row);
-    /* recharge */
-    r = N_get_array_2d_d_value(data->r, col, row) * Az;
-
-
-    if (hc > top) {		/*If the aquifer is confined */
-	z = N_get_array_2d_d_value(data->top, col,
-				   row) -
-	    N_get_array_2d_d_value(data->bottom, col, row);
-	z_xw =
-	    N_get_array_2d_d_value(data->top, col - 1,
-				   row) -
-	    N_get_array_2d_d_value(data->bottom, col - 1, row);
-	z_xe =
-	    N_get_array_2d_d_value(data->top, col + 1,
-				   row) -
-	    N_get_array_2d_d_value(data->bottom, col + 1, row);
-	z_yn =
-	    N_get_array_2d_d_value(data->top, col,
-				   row - 1) -
-	    N_get_array_2d_d_value(data->bottom, col, row - 1);
-	z_ys =
-	    N_get_array_2d_d_value(data->top, col,
-				   row + 1) -
-	    N_get_array_2d_d_value(data->bottom, col, row + 1);
-    }
-    else {			/* the aquifer is unconfined */
-
-	/* If the aquifer is unconfied use an explicite scheme to solve
-	 * the nonlinear equation. We use the phead from the first iteration */
-	z = N_get_array_2d_d_value(data->phead, col, row) -
-	    N_get_array_2d_d_value(data->bottom, col, row);
-	z_xw = N_get_array_2d_d_value(data->phead, col - 1, row) -
-	    N_get_array_2d_d_value(data->bottom, col - 1, row);
-	z_xe = N_get_array_2d_d_value(data->phead, col + 1, row) -
-	    N_get_array_2d_d_value(data->bottom, col + 1, row);
-	z_yn = N_get_array_2d_d_value(data->phead, col, row - 1) -
-	    N_get_array_2d_d_value(data->bottom, col, row - 1);
-	z_ys = N_get_array_2d_d_value(data->phead, col, row + 1) -
-	    N_get_array_2d_d_value(data->bottom, col, row + 1);
-    }
-
-    /*geometrical mean of cell height */
-    if (z_w > 0 || z_w < 0 || z_w == 0)
-	z_w = N_calc_arith_mean(z_xw, z);
-    else
-	z_w = z;
-    if (z_e > 0 || z_e < 0 || z_e == 0)
-	z_e = N_calc_arith_mean(z_xe, z);
-    else
-	z_e = z;
-    if (z_n > 0 || z_n < 0 || z_n == 0)
-	z_n = N_calc_arith_mean(z_yn, z);
-    else
-	z_n = z;
-    if (z_s > 0 || z_s < 0 || z_s == 0)
-	z_s = N_calc_arith_mean(z_ys, z);
-    else
-	z_s = z;
-
-    /*get the surrounding permeabilities */
-    hc_x = N_get_array_2d_d_value(data->hc_x, col, row);
-    hc_y = N_get_array_2d_d_value(data->hc_y, col, row);
-    hc_xw = N_get_array_2d_d_value(data->hc_x, col - 1, row);
-    hc_xe = N_get_array_2d_d_value(data->hc_x, col + 1, row);
-    hc_yn = N_get_array_2d_d_value(data->hc_y, col, row - 1);
-    hc_ys = N_get_array_2d_d_value(data->hc_y, col, row + 1);
-
-    /* calculate the transmissivities */
-    T_w = N_calc_harmonic_mean(hc_xw, hc_x) * z_w;
-    T_e = N_calc_harmonic_mean(hc_xe, hc_x) * z_e;
-    T_n = N_calc_harmonic_mean(hc_yn, hc_y) * z_n;
-    T_s = N_calc_harmonic_mean(hc_ys, hc_y) * z_s;
-
-    /* Compute the river leakage, this is an explicit method
-     * Influent and effluent flow is computed.
-     */
-    if (data->river_leak &&
-	(N_get_array_2d_d_value(data->river_leak, col, row) != 0) &&
-            N_get_array_2d_d_value(data->river_bed, col, row) <= top) {
-        /* Groundwater surface is above the river bed*/
-	if (hc > N_get_array_2d_d_value(data->river_bed, col, row)) {
-	    river_vect = N_get_array_2d_d_value(data->river_head, col, row) *
-		N_get_array_2d_d_value(data->river_leak, col, row);
-	    river_mat = N_get_array_2d_d_value(data->river_leak, col, row);
-	} /* Groundwater surface is below the river bed */
-	else if (hc < N_get_array_2d_d_value(data->river_bed, col, row)) {
-	    river_vect = (N_get_array_2d_d_value(data->river_head, col, row) -
-			  N_get_array_2d_d_value(data->river_bed, col, row))
-		* N_get_array_2d_d_value(data->river_leak, col, row);
-	    river_mat = 0;
-	}
-    }
-
-    /* compute the drainage, this is an explicit method
-     * Drainage is only enabled, if the drain bed is lower the groundwater surface
-     */
-    if (data->drain_leak &&
-	(N_get_array_2d_d_value(data->drain_leak, col, row) != 0) &&
-            N_get_array_2d_d_value(data->drain_bed, col, row) <= top) {
-	if (hc > N_get_array_2d_d_value(data->drain_bed, col, row)) {
-	    drain_vect = N_get_array_2d_d_value(data->drain_bed, col, row) *
-		N_get_array_2d_d_value(data->drain_leak, col, row);
-	    drain_mat = N_get_array_2d_d_value(data->drain_leak, col, row);
-	}
-	else if (hc <= N_get_array_2d_d_value(data->drain_bed, col, row)) {
-	    drain_vect = 0;
-	    drain_mat = 0;
-	}
-    }
-
-    /*mass balance center cell to western cell */
-    W = -1 * T_w * dy / dx;
-    /*mass balance center cell to eastern cell */
-    E = -1 * T_e * dy / dx;
-    /*mass balance center cell to northern cell */
-    N = -1 * T_n * dx / dy;
-    /*mass balance center cell to southern cell */
-    S = -1 * T_s * dx / dy;
-
-    /*the diagonal entry of the matrix */
-    C = -1 * (W + E + N + S -  Az *Ss / data->dt - river_mat * Az -
-	      drain_mat * Az);
-
-    /*the entry in the right side b of Ax = b */
-    V = (q + hc_start * Az * Ss / data->dt) + r + river_vect * Az +
-	drain_vect * Az;
-
-    G_debug(5, "N_callback_gwflow_2d: called [%i][%i]", row, col);
-
-    /*create the 5 point star entries */
-    mat_pos = N_create_5star(C, W, E, N, S, V);
-
-    return mat_pos;
-}
-
-
-
-/* *************************************************************** */
-/* ****************** N_gwflow_2d_calc_water_budget ************** */
-/* *************************************************************** */
-/*!
- * \brief This function computes the water budget of the entire groundwater
- *
- * The water budget is calculated for each active and dirichlet cell from
- * its surrounding neighbours. This is based on the 5 star mass balance computation
- * of N_callback_gwflow_2d and the gradient of the water heights in the cells.
- * The sum of the water budget of each active/dirichlet cell must be near zero
- * due the effect of numerical inaccuracy of cpu's.
- *
- * \param gwdata N_gwflow_data2d *
- * \param geom N_geom_data *
- * \param budget N_array_2d
- * \return void
- *
- * */
-void
-N_gwflow_2d_calc_water_budget(N_gwflow_data2d * data, N_geom_data * geom, N_array_2d * budget)
-{
-    int y, x, stat;
-    double h, hc;
-    double val;
-    double sum;
-    N_data_star *dstar;
-
-    int rows = data->status->rows;
-    int cols = data->status->cols;
-
-    sum = 0;
-
-    for (y = 0; y < rows; y++) {
-	G_percent(y, rows - 1, 10);
-	for (x = 0; x < cols; x++) {
-	    stat = N_get_array_2d_c_value(data->status, x, y);
-
-            val = 0.0;
-
-	    if (stat != N_CELL_INACTIVE ) {	/*all active/dirichlet cells */
-
-                /* Compute the flow parameter */
-                dstar = N_callback_gwflow_2d(data, geom, x, y);
-                /* Compute the gradient in each direction pointing from the center */
-                hc = N_get_array_2d_d_value(data->phead, x, y);
-
-                if((int)N_get_array_2d_d_value(data->status, x + 1, y    ) != N_CELL_INACTIVE) {
-                    h = N_get_array_2d_d_value(data->phead,  x + 1, y);
-                    val += dstar->E * (hc - h);
-                }
-                if((int)N_get_array_2d_d_value(data->status, x - 1, y    ) != N_CELL_INACTIVE) {
-                    h = N_get_array_2d_d_value(data->phead,  x - 1, y);
-                    val += dstar->W * (hc - h);
-                }
-                if((int)N_get_array_2d_d_value(data->status, x    , y + 1) != N_CELL_INACTIVE) {
-                    h = N_get_array_2d_d_value(data->phead,  x    , y + 1);
-                    val += dstar->S * (hc - h);
-                }
-                if((int)N_get_array_2d_d_value(data->status, x    , y - 1) != N_CELL_INACTIVE) {
-                    h = N_get_array_2d_d_value(data->phead,  x    , y - 1);
-                    val += dstar->N * (hc - h);
-                }
-
-                sum += val;
-
-                G_free(dstar);
-	    }
-	    else {
-		Rast_set_null_value(&val, 1, DCELL_TYPE);
-	    }
-	    N_put_array_2d_d_value(budget, x, y, val);
-	}
-    }
-
-    if(fabs(sum) < 0.0000000001)
-        G_message(_("The total sum of the water budget: %g\n"), sum);
-    else
-        G_warning(_("The total sum of the water budget is significant larger then 0: %g\n"), sum);
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_heatflow.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_heatflow.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_heatflow.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,19 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:      Calculation of heatflow
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_les.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_les.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_les.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,335 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:      functions to manage linear equation systems
-* 		part of the gpde library
-*               
-* COPYRIGHT:    (C) 2000 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/N_pde.h>
-#include <grass/gmath.h>
-
-
-/*!
- * \brief Allocate memory for a (not) quadratic linear equation system which includes the Matrix A, vector x and vector b
- *
- * This function calls #N_alloc_les_param
- *
- * \param cols int
- * \param rows int
- * \param type int
- * \return N_les *
- *
- * */
-N_les *N_alloc_nquad_les(int cols, int rows, int type)
-{
-    return N_alloc_les_param(cols, rows, type, 2);
-}
-
-/*!
- * \brief Allocate memory for a (not) quadratic linear equation system which includes the Matrix A and vector x
- *
- * This function calls #N_alloc_les_param
- *
- * \param cols int
- * \param rows int
- * \param type int
- * \return N_les *
- *
- * */
-N_les *N_alloc_nquad_les_Ax(int cols, int rows, int type)
-{
-    return N_alloc_les_param(cols, rows, type, 1);
-}
-
-/*!
- * \brief Allocate memory for a (not) quadratic linear equation system which includes the Matrix A
- *
- * This function calls #N_alloc_les_param
- *
- * \param cols int
- * \param rows int
- * \param type int
- * \return N_les *
- *
- * */
-N_les *N_alloc_nquad_les_A(int cols, int rows, int type)
-{
-    return N_alloc_les_param(cols, rows, type, 0);
-}
-
-/*!
- * \brief Allocate memory for a (not) quadratic linear equation system which includes the Matrix A, vector x and vector b
- *
- * This function calls #N_alloc_les_param
- *
- * \param cols int
- * \param rows int
- * \param type int
- * \return N_les *
- *
- * */
-N_les *N_alloc_nquad_les_Ax_b(int cols, int rows, int type)
-{
-    return N_alloc_les_param(cols, rows, type, 2);
-}
-
-
-
-/*!
- * \brief Allocate memory for a quadratic linear equation system which includes the Matrix A, vector x and vector b
- *
- * This function calls #N_alloc_les_param
- *
- * \param rows int
- * \param type int
- * \return N_les *
- *
- * */
-N_les *N_alloc_les(int rows, int type)
-{
-    return N_alloc_les_param(rows, rows, type, 2);
-}
-
-/*!
- * \brief Allocate memory for a quadratic linear equation system which includes the Matrix A and vector x
- *
- * This function calls #N_alloc_les_param
- *
- * \param rows int
- * \param type int
- * \return N_les *
- *
- * */
-N_les *N_alloc_les_Ax(int rows, int type)
-{
-    return N_alloc_les_param(rows, rows, type, 1);
-}
-
-/*!
- * \brief Allocate memory for a quadratic linear equation system which includes the Matrix A
- *
- * This function calls #N_alloc_les_param
- *
- * \param rows int
- * \param type int
- * \return N_les *
- *
- * */
-N_les *N_alloc_les_A(int rows, int type)
-{
-    return N_alloc_les_param(rows, rows, type, 0);
-}
-
-/*!
- * \brief Allocate memory for a quadratic linear equation system which includes the Matrix A, vector x and vector b
- *
- * This function calls #N_alloc_les_param
- *
- * \param rows int
- * \param type int
- * \return N_les *
- *
- * */
-N_les *N_alloc_les_Ax_b(int rows, int type)
-{
-    return N_alloc_les_param(rows, rows, type, 2);
-}
-
-
-/*!
- * \brief Allocate memory for a quadratic or not quadratic linear equation system
- *
- * The type of the linear equation system must be N_NORMAL_LES for
- * a regular quadratic matrix or N_SPARSE_LES for a sparse matrix
- *
- * <p>
- * In case of N_NORMAL_LES
- * 
- * A quadratic matrix of size rows*rows*sizeof(double) will allocated
- *
- * <p>
- * In case of N_SPARSE_LES
- *
- * a vector of size row will be allocated, ready to hold additional allocated sparse vectors.
- * each sparse vector may have a different size.
- *
- * Parameter parts defines which parts of the les should be allocated.
- * The number of columns and rows defines if the matrix is quadratic.
- *
- * \param cols int
- * \param rows int
- * \param type int
- * \param parts int -- 2 = A, x and b; 1 = A and x; 0 = A allocated
- * \return N_les *
- *
- * */
-N_les *N_alloc_les_param(int cols, int rows, int type, int parts)
-{
-    N_les *les;
-
-    int i;
-
-    if (type == N_SPARSE_LES)
-	G_debug(2,
-		"Allocate memory for a sparse linear equation system with %i rows\n",
-		rows);
-    else
-	G_debug(2,
-		"Allocate memory for a regular linear equation system with %i rows\n",
-		rows);
-
-    les = (N_les *) G_calloc(1, sizeof(N_les));
-
-    if (parts > 0) {
-	les->x = (double *)G_calloc(cols, sizeof(double));
-	for (i = 0; i < cols; i++)
-	    les->x[i] = 0.0;
-    }
-
-
-    if (parts > 1) {
-	les->b = (double *)G_calloc(cols, sizeof(double));
-	for (i = 0; i < cols; i++)
-	    les->b[i] = 0.0;
-    }
-
-    les->A = NULL;
-    les->Asp = NULL;
-    les->rows = rows;
-    les->cols = cols;
-    if (rows == cols)
-	les->quad = 1;
-    else
-	les->quad = 0;
-
-    if (type == N_SPARSE_LES) {
-	les->Asp = G_math_alloc_spmatrix(rows);
-	les->type = N_SPARSE_LES;
-    }
-    else {
-	les->A = G_alloc_matrix(rows, cols);
-	les->type = N_NORMAL_LES;
-    }
-
-    return les;
-}
-
-/*!
- *
- * \brief prints the linear equation system to stdout
- *
- * <p>
- * Format:
- * A*x = b
- *
- * <p>
- * Example
- \verbatim
-
- 2 1 1 1 * 2 = 0.1
- 1 2 0 0 * 3 = 0.2
- 1 0 2 0 * 3 = 0.2
- 1 0 0 2 * 2 = 0.1
-
- \endverbatim
- *
- * \param les N_les * 
- * \return void
- *  
- * */
-void N_print_les(N_les * les)
-{
-    int i, j, k, out;
-
-
-    if (les->type == N_SPARSE_LES) {
-	for (i = 0; i < les->rows; i++) {
-	    for (j = 0; j < les->cols; j++) {
-		out = 0;
-		for (k = 0; k < les->Asp[i]->cols; k++) {
-		    if (les->Asp[i]->index[k] == j) {
-			fprintf(stdout, "%4.5f ", les->Asp[i]->values[k]);
-			out = 1;
-		    }
-		}
-		if (!out)
-		    fprintf(stdout, "%4.5f ", 0.0);
-	    }
-	    if (les->x)
-		fprintf(stdout, "  *  %4.5f", les->x[i]);
-	    if (les->b)
-		fprintf(stdout, " =  %4.5f ", les->b[i]);
-
-	    fprintf(stdout, "\n");
-	}
-    }
-    else {
-
-	for (i = 0; i < les->rows; i++) {
-	    for (j = 0; j < les->cols; j++) {
-		fprintf(stdout, "%4.5f ", les->A[i][j]);
-	    }
-	    if (les->x)
-		fprintf(stdout, "  *  %4.5f", les->x[i]);
-	    if (les->b)
-		fprintf(stdout, " =  %4.5f ", les->b[i]);
-
-	    fprintf(stdout, "\n");
-	}
-
-    }
-    return;
-}
-
-/*!
- * \brief Release the memory of the linear equation system
- *
- * \param les N_les *            
- * \return void
- *
- * */
-
-void N_free_les(N_les * les)
-{
-    if (les->type == N_SPARSE_LES)
-	G_debug(2, "Releasing memory of a sparse linear equation system\n");
-    else
-	G_debug(2, "Releasing memory of a regular linear equation system\n");
-
-    if (les) {
-
-	if (les->x)
-	    G_free(les->x);
-	if (les->b)
-	    G_free(les->b);
-
-	if (les->type == N_SPARSE_LES) {
-
-	    if (les->Asp) {
-		G_math_free_spmatrix(les->Asp, les->rows);
-	    }
-	}
-	else {
-
-	    if (les->A) {
-		G_free_matrix(les->A);
-	    }
-	}
-
-	free(les);
-    }
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_les_assemble.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_les_assemble.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_les_assemble.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,1397 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:      functions to assemble a linear equation system
-* 		part of the gpde library
-*               
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-
-/* local protos */
-static int make_les_entry_2d(int i, int j, int offset_i, int offset_j,
-			     int count, int pos, N_les * les,
-			     G_math_spvector * spvect,
-			     N_array_2d * cell_count, N_array_2d * status,
-			     N_array_2d * start_val, double entry,
-			     int cell_type);
-
-static int make_les_entry_3d(int i, int j, int k, int offset_i, int offset_j,
-			     int offset_k, int count, int pos, N_les * les,
-			     G_math_spvector * spvect,
-			     N_array_3d * cell_count, N_array_3d * status,
-			     N_array_3d * start_val, double entry,
-			     int cell_type);
-
-/* *************************************************************** * 
- * ********************** N_alloc_5star ************************** * 
- * *************************************************************** */
-/*!
- * \brief allocate a 5 point star data structure
- *
- * \return N_data_star *
- * */
-N_data_star *N_alloc_5star(void)
-{
-    N_data_star *star = (N_data_star *) G_calloc(1, sizeof(N_data_star));
-
-    star->type = N_5_POINT_STAR;
-    star->count = 5;
-    return star;
-}
-
-/* *************************************************************** * 
- * ********************* N_alloc_7star *************************** * 
- * *************************************************************** */
-/*!
- * \brief allocate a 7 point star data structure
- *
- * \return N_data_star *
- * */
-N_data_star *N_alloc_7star(void)
-{
-    N_data_star *star = (N_data_star *) G_calloc(1, sizeof(N_data_star));
-
-    star->type = N_7_POINT_STAR;
-    star->count = 7;
-    return star;
-}
-
-/* *************************************************************** * 
- * ********************* N_alloc_9star *************************** * 
- * *************************************************************** */
-/*!
- * \brief allocate a 9 point star data structure
- *
- * \return N_data_star *
- *
- * \attention The 9 point start is not yet implemented in the matrix assembling function
- *
- * */
-N_data_star *N_alloc_9star(void)
-{
-    N_data_star *star = (N_data_star *) G_calloc(1, sizeof(N_data_star));
-
-    star->type = N_9_POINT_STAR;
-    star->count = 9;
-    return star;
-}
-
-/* *************************************************************** * 
- * ********************* N_alloc_27star ************************** * 
- * *************************************************************** */
-/*!
- * \brief allocate a 27 point star data structure
- *
- * \return N_data_star *
- *
- * \attention The 27 point start is not yet implemented in the matrix assembling function
- *
- * */
-N_data_star *N_alloc_27star(void)
-{
-    N_data_star *star = (N_data_star *) G_calloc(1, sizeof(N_data_star));
-
-    star->type = N_27_POINT_STAR;
-    star->count = 27;
-    return star;
-}
-
-/* *************************************************************** * 
- * ********************** N_create_5star ************************* * 
- * *************************************************************** */
-/*!
- * \brief allocate and initialize a 5 point star data structure
- *
- * \param C double
- * \param W double
- * \param E double
- * \param N double
- * \param S double
- * \param V double
- * \return N_data_star *
- * */
-N_data_star *N_create_5star(double C, double W, double E, double N,
-			    double S, double V)
-{
-    N_data_star *star = N_alloc_5star();
-
-    star->C = C;
-    star->W = W;
-    star->E = E;
-    star->N = N;
-    star->S = S;
-
-    star->V = V;
-
-    G_debug(5, "N_create_5star:  w %g e %g n %g s %g c %g v %g\n", star->W,
-	    star->E, star->N, star->S, star->C, star->V);
-
-    return star;
-}
-
-/* *************************************************************** * 
- * ************************* N_create_7star ********************** * 
- * *************************************************************** */
-/*!
- * \brief allocate and initialize a 7 point star data structure
- *
- * \param C double
- * \param W double
- * \param E double
- * \param N double
- * \param S double
- * \param T double
- * \param B double
- * \param V double
- * \return N_data_star *
- * */
-N_data_star *N_create_7star(double C, double W, double E, double N,
-			    double S, double T, double B, double V)
-{
-    N_data_star *star = N_alloc_7star();
-
-    star->C = C;
-    star->W = W;
-    star->E = E;
-    star->N = N;
-    star->S = S;
-
-    star->T = T;
-    star->B = B;
-
-    star->V = V;
-
-    G_debug(5, "N_create_7star:  w %g e %g n %g s %g t %g b %g c %g v %g\n",
-	    star->W, star->E, star->N, star->S, star->T, star->B, star->C,
-	    star->V);
-
-    return star;
-}
-
-/* *************************************************************** * 
- * ************************ N_create_9star *********************** * 
- * *************************************************************** */
-/*!
- * \brief allocate and initialize a 9 point star data structure
- *
- * \param C  double
- * \param W  double
- * \param E  double
- * \param N  double
- * \param S  double
- * \param NW double
- * \param SW double
- * \param NE double
- * \param SE double
- * \param V  double
- * \return N_data_star *
- * */
-N_data_star *N_create_9star(double C, double W, double E, double N,
-			    double S, double NW, double SW, double NE,
-			    double SE, double V)
-{
-    N_data_star *star = N_alloc_9star();
-
-    star->C = C;
-    star->W = W;
-    star->E = E;
-    star->N = N;
-    star->S = S;
-
-    star->NW = NW;
-    star->SW = SW;
-    star->NE = NE;
-    star->SE = SE;
-
-    star->V = V;
-
-    G_debug(5,
-	    "N_create_9star:  w %g e %g n %g s %g nw %g sw %g ne %g se %g c %g v %g\n",
-	    star->W, star->E, star->N, star->S, star->NW, star->SW, star->NE,
-	    star->SE, star->C, star->V);
-
-    return star;
-}
-
-/* *************************************************************** * 
- * ************************ N_create_27star *********************** * 
- * *************************************************************** */
-/*!
- * \brief allocate and initialize a 27 point star data structure
- *
- * \param C  double
- * \param W  double
- * \param E  double
- * \param N  double
- * \param S  double
- * \param NW double
- * \param SW double
- * \param NE double
- * \param SE double
- * \param T  double
- * \param W_T  double
- * \param E_T  double
- * \param N_T  double
- * \param S_T  double
- * \param NW_T double
- * \param SW_T double
- * \param NE_T double
- * \param SE_T double
- * \param B  double
- * \param W_B  double
- * \param E_B  double
- * \param N_B  double
- * \param S_B  double
- * \param NW_B double
- * \param SW_B double
- * \param NE_B double
- * \param SE_B double
- * \param V  double
- * \return N_data_star *
- * */
-N_data_star *N_create_27star(double C, double W, double E, double N, double S,
-			     double NW, double SW, double NE, double SE,
-			     double T, double W_T, double E_T, double N_T,
-			     double S_T, double NW_T, double SW_T,
-			     double NE_T, double SE_T, double B, double W_B,
-			     double E_B, double N_B, double S_B, double NW_B,
-			     double SW_B, double NE_B, double SE_B, double V)
-{
-    N_data_star *star = N_alloc_27star();
-
-    star->C = C;
-    star->W = W;
-    star->E = E;
-    star->N = N;
-    star->S = S;
-
-    star->NW = NW;
-    star->SW = SW;
-    star->NE = NE;
-    star->SE = SE;
-
-    star->T = T;
-    star->W_T = W_T;
-    star->E_T = E_T;
-    star->N_T = N_T;
-    star->S_T = S_T;
-
-    star->NW_T = NW_T;
-    star->SW_T = SW_T;
-    star->NE_T = NE_T;
-    star->SE_T = SE_T;
-
-    star->B = B;
-    star->W_B = W_B;
-    star->E_B = E_B;
-    star->N_B = N_B;
-    star->S_B = S_B;
-
-    star->NW_B = NW_B;
-    star->SW_B = SW_B;
-    star->NE_B = NE_B;
-    star->SE_B = SE_B;
-
-    star->V = V;
-
-    G_debug(5,
-	    "N_create_27star:  w %g e %g n %g s %g nw %g sw %g ne %g se %g c %g v %g\n",
-	    star->W, star->E, star->N, star->S, star->NW, star->SW, star->NE,
-	    star->SE, star->C, star->V);
-
-    G_debug(5,
-	    "N_create_27star:  w_t %g e_t %g n_t %g s_t %g nw_t %g sw_t %g ne_t %g se_t %g t %g \n",
-	    star->W_T, star->E_T, star->N_T, star->S_T, star->NW_T,
-	    star->SW_T, star->NE_T, star->SE_T, star->T);
-
-    G_debug(5,
-	    "N_create_27star:  w_b %g e_b %g n_b %g s_b %g nw_b %g sw_b %g ne_b %g se_B %g b %g\n",
-	    star->W_B, star->E_B, star->N_B, star->S_B, star->NW_B,
-	    star->SW_B, star->NE_B, star->SE_B, star->B);
-
-
-
-    return star;
-}
-
-
-/* *************************************************************** * 
- * ****************** N_set_les_callback_3d_func ***************** * 
- * *************************************************************** */
-/*!
- * \brief Set the callback function which is called while assembling the les in 3d
- *
- * \param data N_les_callback_3d *
- * \param callback_func_3d N_data_star *
- * \return void
- * */
-void
-N_set_les_callback_3d_func(N_les_callback_3d * data,
-			   N_data_star * (*callback_func_3d) ())
-{
-    data->callback = callback_func_3d;
-}
-
-/* *************************************************************** * 
- * *************** N_set_les_callback_2d_func ******************** * 
- * *************************************************************** */
-/*!
- * \brief Set the callback function which is called while assembling the les in 2d
- *
- * \param data N_les_callback_2d *
- * \param callback_func_2d N_data_star * 
- * \return void
- * */
-void
-N_set_les_callback_2d_func(N_les_callback_2d * data,
-			   N_data_star * (*callback_func_2d) ())
-{
-    data->callback = callback_func_2d;
-}
-
-/* *************************************************************** * 
- * ************** N_alloc_les_callback_3d ************************ * 
- * *************************************************************** */
-/*!
- * \brief Allocate the structure holding the callback function
- *
- * A template callback is set. Use N_set_les_callback_3d_func
- * to set up a specific function.
- *
- * \return N_les_callback_3d *
- * */
-N_les_callback_3d *N_alloc_les_callback_3d(void)
-{
-    N_les_callback_3d *call;
-
-    call = (N_les_callback_3d *) G_calloc(1, sizeof(N_les_callback_3d *));
-    call->callback = N_callback_template_3d;
-
-    return call;
-}
-
-/* *************************************************************** * 
- * *************** N_alloc_les_callback_2d *********************** * 
- * *************************************************************** */
-/*!
- * \brief Allocate the structure holding the callback function
- *
- * A template callback is set. Use N_set_les_callback_2d_func
- * to set up a specific function.
- *
- * \return N_les_callback_2d *
- * */
-N_les_callback_2d *N_alloc_les_callback_2d(void)
-{
-    N_les_callback_2d *call;
-
-    call = (N_les_callback_2d *) G_calloc(1, sizeof(N_les_callback_2d *));
-    call->callback = N_callback_template_2d;
-
-    return call;
-}
-
-/* *************************************************************** * 
- * ******************** N_callback_template_3d ******************* * 
- * *************************************************************** */
-/*!
- * \brief A callback template creates a 7 point star structure
- *
- * This is a template callback for mass balance calculation with 7 point stars
- * based on 3d data (g3d).
- *
- * \param data void *
- * \param geom N_geom_data *
- * \param depth int
- * \param row   int
- * \param col   int
- * \return N_data_star *
- *
- * */
-N_data_star *N_callback_template_3d(void *data, N_geom_data * geom, int col,
-				    int row, int depth)
-{
-    N_data_star *star = N_alloc_7star();
-
-    star->E = 1 / geom->dx;
-    star->W = 1 / geom->dx;
-    star->N = 1 / geom->dy;
-    star->S = 1 / geom->dy;
-    star->T = 1 / geom->dz;
-    star->B = 1 / geom->dz;
-    star->C = -1 * (2 / geom->dx + 2 / geom->dy + 2 / geom->dz);
-    star->V = -1;
-
-    G_debug(5,
-	    "N_callback_template_3d:  w %g e %g n %g s %g t %g b %g c %g v %g\n",
-	    star->W, star->E, star->N, star->S, star->T, star->B, star->C,
-	    star->V);
-
-
-    return star;
-}
-
-/* *************************************************************** * 
- * ********************* N_callback_template_2d ****************** * 
- * *************************************************************** */
-/*!
- * \brief A callback template creates a 9 point star structure
- *
- * This is a template callback for mass balance calculation with 9 point stars
- * based on 2d data (raster).
- *
- * \param data void *
- * \param geom N_geom_data *
- * \param row int
- * \param col int
- * \return N_data_star *
- *
- * */
-N_data_star *N_callback_template_2d(void *data, N_geom_data * geom, int col,
-				    int row)
-{
-    N_data_star *star = N_alloc_9star();
-
-    star->E = 1 / geom->dx;
-    star->NE = 1 / sqrt(geom->dx * geom->dx + geom->dy * geom->dy);
-    star->SE = 1 / sqrt(geom->dx * geom->dx + geom->dy * geom->dy);
-    star->W = 1 / geom->dx;
-    star->NW = 1 / sqrt(geom->dx * geom->dx + geom->dy * geom->dy);
-    star->SW = 1 / sqrt(geom->dx * geom->dx + geom->dy * geom->dy);
-    star->N = 1 / geom->dy;
-    star->S = 1 / geom->dy;
-    star->C =
-	-1 * (star->E + star->NE + star->SE + star->W + star->NW + star->SW +
-	      star->N + star->S);
-    star->V = 0;
-
-    return star;
-}
-
-/* *************************************************************** * 
- * ******************** N_assemble_les_2d ************************ * 
- * *************************************************************** */
-/*!
- * \brief Assemble a linear equation system (les) based on 2d location data (raster) and active cells
- *
- * This function calls #N_assemble_les_2d_param
- *
- */
-N_les *N_assemble_les_2d(int les_type, N_geom_data * geom,
-			 N_array_2d * status, N_array_2d * start_val,
-			 void *data, N_les_callback_2d * call)
-{
-    return N_assemble_les_2d_param(les_type, geom, status, start_val, data,
-				   call, N_CELL_ACTIVE);
-}
-
-/*!
- * \brief Assemble a linear equation system (les) based on 2d location data (raster) and active cells
- *
- * This function calls #N_assemble_les_2d_param
- *
- */
-N_les *N_assemble_les_2d_active(int les_type, N_geom_data * geom,
-				N_array_2d * status, N_array_2d * start_val,
-				void *data, N_les_callback_2d * call)
-{
-    return N_assemble_les_2d_param(les_type, geom, status, start_val, data,
-				   call, N_CELL_ACTIVE);
-}
-
-/*!
- * \brief Assemble a linear equation system (les) based on 2d location data (raster) and active and dirichlet cells
- *
- * This function calls #N_assemble_les_2d_param
- *
- */
-N_les *N_assemble_les_2d_dirichlet(int les_type, N_geom_data * geom,
-				   N_array_2d * status,
-				   N_array_2d * start_val, void *data,
-				   N_les_callback_2d * call)
-{
-    return N_assemble_les_2d_param(les_type, geom, status, start_val, data,
-				   call, N_CELL_DIRICHLET);
-}
-
-/*!
- * \brief Assemble a linear equation system (les) based on 2d location data  (raster)
- *
- * 
- * The linear equation system type can be set to N_NORMAL_LES to create a regular
- * matrix, or to N_SPARSE_LES to create a sparse matrix. This function returns
- * a new created linear equation system which can be solved with 
- * linear equation solvers. An 2d array with start values and an 2d status array
- * must be provided as well as the location geometry and a void pointer to data 
- * passed to the callback which creates the les row entries. This callback
- * must be defined in the N_les_callback_2d strcuture.
- *
- * The creation of the les is parallelized with OpenMP. 
- * If you implement new callbacks, please make sure that the 
- * function calls are thread safe.
- *
- *
- * the les can be created in two ways, with dirichlet and similar cells and without them,
- * to spare some memory. If the les is created with dirichlet cell, the dirichlet boundary condition
- * must be added.
- *
- * \param les_type int
- * \param geom      N_geom_data*
- * \param status    N_array_2d *
- * \param start_val N_array_2d *
- * \param data void *
- * \param cell_type int  -- les assemble based on N_CELL_ACTIVE or N_CELL_DIRICHLET
- * \param call N_les_callback_2d *
- * \return N_les *
- * */
-N_les *N_assemble_les_2d_param(int les_type, N_geom_data * geom,
-			       N_array_2d * status, N_array_2d * start_val,
-			       void *data, N_les_callback_2d * call,
-			       int cell_type)
-{
-    int i, j, count = 0, pos = 0;
-    int cell_type_count = 0;
-    int **index_ij;
-    N_array_2d *cell_count;
-    N_les *les = NULL;
-
-    G_debug(2,
-	    "N_assemble_les_2d: starting to assemble the linear equation system");
-
-    /* At first count the number of valid cells and save 
-     * each number in a new 2d array. Those numbers are used 
-     * to create the linear equation system.
-     * */
-
-    cell_count = N_alloc_array_2d(geom->cols, geom->rows, 1, CELL_TYPE);
-
-    /* include dirichlet cells in the les */
-    if (cell_type == N_CELL_DIRICHLET) {
-	for (j = 0; j < geom->rows; j++) {
-	    for (i = 0; i < geom->cols; i++) {
-		/*use all non-inactive cells for les creation */
-		if (N_CELL_INACTIVE < N_get_array_2d_c_value(status, i, j) &&
-		    N_get_array_2d_c_value(status, i, j) < N_MAX_CELL_STATE)
-		    cell_type_count++;
-	    }
-	}
-    }
-    /*use only active cell in the les */
-    if (cell_type == N_CELL_ACTIVE) {
-	for (j = 0; j < geom->rows; j++) {
-	    for (i = 0; i < geom->cols; i++) {
-		/*count only active cells */
-		if (N_CELL_ACTIVE == N_get_array_2d_d_value(status, i, j))
-		    cell_type_count++;
-	    }
-	}
-    }
-
-    G_debug(2, "N_assemble_les_2d: number of used cells %i\n",
-	    cell_type_count);
-
-    if (cell_type_count == 0)
-	G_fatal_error
-	    ("Not enough cells [%i] to create the linear equation system. Check the cell status. Only active cells (value = 1) are used to create the equation system.",
-	     cell_type_count);
-
-    /* Then allocate the memory for the linear equation system (les). 
-     * Only valid cells are used to create the les. */
-    index_ij = (int **)G_calloc(cell_type_count, sizeof(int *));
-    for (i = 0; i < cell_type_count; i++)
-	index_ij[i] = (int *)G_calloc(2, sizeof(int));
-
-    les = N_alloc_les_Ax_b(cell_type_count, les_type);
-
-    count = 0;
-
-    /*count the number of cells which should be used to create the linear equation system */
-    /*save the i and j indices and create a ordered numbering */
-    for (j = 0; j < geom->rows; j++) {
-	for (i = 0; i < geom->cols; i++) {
-	    /*count every non-inactive cell */
-	    if (cell_type == N_CELL_DIRICHLET) {
-		if (N_CELL_INACTIVE < N_get_array_2d_c_value(status, i, j) &&
-		    N_get_array_2d_c_value(status, i, j) < N_MAX_CELL_STATE) {
-		    N_put_array_2d_c_value(cell_count, i, j, count);
-		    index_ij[count][0] = i;
-		    index_ij[count][1] = j;
-		    count++;
-		    G_debug(5,
-			    "N_assemble_les_2d: non-inactive cells count %i at pos x[%i] y[%i]\n",
-			    count, i, j);
-		}
-		/*count every active cell */
-	    }
-	    else if (N_CELL_ACTIVE == N_get_array_2d_c_value(status, i, j)) {
-		N_put_array_2d_c_value(cell_count, i, j, count);
-		index_ij[count][0] = i;
-		index_ij[count][1] = j;
-		count++;
-		G_debug(5,
-			"N_assemble_les_2d: active cells count %i at pos x[%i] y[%i]\n",
-			count, i, j);
-	    }
-	}
-    }
-
-    G_debug(2, "N_assemble_les_2d: starting the parallel assemble loop");
-
-    /* Assemble the matrix in parallel */
-#pragma omp parallel for private(i, j, pos, count) schedule(static)
-    for (count = 0; count < cell_type_count; count++) {
-	i = index_ij[count][0];
-	j = index_ij[count][1];
-
-	/*create the entries for the */
-	N_data_star *items = call->callback(data, geom, i, j);
-
-	/* we need a sparse vector pointer anytime */
-	G_math_spvector *spvect = NULL;
-
-	/*allocate a sprase vector */
-	if (les_type == N_SPARSE_LES) {
-	    spvect = G_math_alloc_spvector(items->count);
-	}
-	/* initial conditions */
-	les->x[count] = N_get_array_2d_d_value(start_val, i, j);
-
-	/* the entry in the vector b */
-	les->b[count] = items->V;
-
-	/* pos describes the position in the sparse vector.
-	 * the first entry is always the diagonal entry of the matrix*/
-	pos = 0;
-
-	if (les_type == N_SPARSE_LES) {
-	    spvect->index[pos] = count;
-	    spvect->values[pos] = items->C;
-	}
-	else {
-	    les->A[count][count] = items->C;
-	}
-	/* western neighbour, entry is col - 1 */
-	if (i > 0) {
-	    pos = make_les_entry_2d(i, j, -1, 0, count, pos, les, spvect,
-				    cell_count, status, start_val, items->W,
-				    cell_type);
-	}
-	/* eastern neighbour, entry col + 1 */
-	if (i < geom->cols - 1) {
-	    pos = make_les_entry_2d(i, j, 1, 0, count, pos, les, spvect,
-				    cell_count, status, start_val, items->E,
-				    cell_type);
-	}
-	/* northern neighbour, entry row - 1 */
-	if (j > 0) {
-	    pos =
-		make_les_entry_2d(i, j, 0, -1, count, pos, les, spvect,
-				  cell_count, status, start_val, items->N,
-				  cell_type);
-	}
-	/* southern neighbour, entry row + 1 */
-	if (j < geom->rows - 1) {
-	    pos = make_les_entry_2d(i, j, 0, 1, count, pos, les, spvect,
-				    cell_count, status, start_val, items->S,
-				    cell_type);
-	}
-	/*in case of a nine point star, we have additional entries */
-	if (items->type == N_9_POINT_STAR) {
-	    /* north-western neighbour, entry is col - 1 row - 1 */
-	    if (i > 0 && j > 0) {
-		pos = make_les_entry_2d(i, j, -1, -1, count, pos, les, spvect,
-					cell_count, status, start_val,
-					items->NW, cell_type);
-	    }
-	    /* north-eastern neighbour, entry col + 1 row - 1 */
-	    if (i < geom->cols - 1 && j > 0) {
-		pos = make_les_entry_2d(i, j, 1, -1, count, pos, les, spvect,
-					cell_count, status, start_val,
-					items->NE, cell_type);
-	    }
-	    /* south-western neighbour, entry is col - 1 row + 1 */
-	    if (i > 0 && j < geom->rows - 1) {
-		pos = make_les_entry_2d(i, j, -1, 1, count, pos, les, spvect,
-					cell_count, status, start_val,
-					items->SW, cell_type);
-	    }
-	    /* south-eastern neighbour, entry col + 1 row + 1 */
-	    if (i < geom->cols - 1 && j < geom->rows - 1) {
-		pos = make_les_entry_2d(i, j, 1, 1, count, pos, les, spvect,
-					cell_count, status, start_val,
-					items->SE, cell_type);
-	    }
-	}
-
-	/*How many entries in the les */
-	if (les->type == N_SPARSE_LES) {
-	    spvect->cols = pos + 1;
-	    G_math_add_spvector(les->Asp, spvect, count);
-	}
-
-	if (items)
-	    G_free(items);
-    }
-
-    /*release memory */
-    N_free_array_2d(cell_count);
-
-    for (i = 0; i < cell_type_count; i++)
-	G_free(index_ij[i]);
-
-    G_free(index_ij);
-
-    return les;
-}
-
-/*!
- * \brief Integrate Dirichlet or Transmission boundary conditions into the les (2s)
- *
- * Dirichlet and Transmission boundary conditions will be integrated into
- * the provided linear equation system. This is meaningfull if
- * the les was created with #N_assemble_les_2d_dirichlet, because in
- * this case Dirichlet boundary conditions are not automatically included.
- *
- * The provided les will be modified:
- *
- * Ax = b will be splitted into Ax_u + Ax_d = b
- *
- * x_u - the unknowns
- * x_d - the Dirichlet cells
- *
- * Ax_u = b -Ax_d will be computed. Then the matrix A will be modified to
- *
- * | A_u  0 | x_u
- * |  0   I | x_d
- *
- * \param les N_les* -- the linear equation system
- * \param geom N_geom_data* -- geometrical data information
- * \param status N_array_2d* -- the status array containing the cell types
- * \param start_val N_array_2d* -- an array with start values
- * \return int -- 1 = success, 0 = failure
- * */
-int N_les_integrate_dirichlet_2d(N_les * les, N_geom_data * geom,
-				 N_array_2d * status, N_array_2d * start_val)
-{
-    int rows, cols;
-    int count = 0;
-    int i, j, x, y, stat;
-    double *dvect1;
-    double *dvect2;
-
-    G_debug(2,
-	    "N_les_integrate_dirichlet_2d: integrating the dirichlet boundary condition");
-
-    rows = geom->rows;
-    cols = geom->cols;
-
-    /*we nned to additional vectors */
-    dvect1 = (double *)G_calloc(les->cols, sizeof(double));
-    dvect2 = (double *)G_calloc(les->cols, sizeof(double));
-
-    /*fill the first one with the x vector data of Dirichlet cells */
-    count = 0;
-    for (y = 0; y < rows; y++) {
-	for (x = 0; x < cols; x++) {
-	    stat = N_get_array_2d_c_value(status, x, y);
-	    if (stat > N_CELL_ACTIVE && stat < N_MAX_CELL_STATE) {
-		dvect1[count] = N_get_array_2d_d_value(start_val, x, y);
-		count++;
-	    }
-	    else if (stat == N_CELL_ACTIVE) {
-		dvect1[count] = 0.0;
-		count++;
-	    }
-	}
-    }
-
-#pragma omp parallel default(shared)
-    {
-	/*perform the matrix vector product and */
-	if (les->type == N_SPARSE_LES)
-	    G_math_Ax_sparse(les->Asp, dvect1, dvect2, les->rows);
-	else
-	    G_math_d_Ax(les->A, dvect1, dvect2, les->rows, les->cols);
-#pragma omp for schedule (static) private(i)
-	for (i = 0; i < les->cols; i++)
-	    les->b[i] = les->b[i] - dvect2[i];
-    }
-
-    /*now set the Dirichlet cell rows and cols to zero and the 
-     * diagonal entry to 1*/
-    count = 0;
-    for (y = 0; y < rows; y++) {
-	for (x = 0; x < cols; x++) {
-	    stat = N_get_array_2d_c_value(status, x, y);
-	    if (stat > N_CELL_ACTIVE && stat < N_MAX_CELL_STATE) {
-		if (les->type == N_SPARSE_LES) {
-		    /*set the rows to zero */
-		    for (i = 0; i < les->Asp[count]->cols; i++)
-			les->Asp[count]->values[i] = 0.0;
-		    /*set the cols to zero */
-		    for (i = 0; i < les->rows; i++) {
-			for (j = 0; j < les->Asp[i]->cols; j++) {
-			    if (les->Asp[i]->index[j] == count)
-				les->Asp[i]->values[j] = 0.0;
-			}
-		    }
-
-		    /*entry on the diagonal */
-		    les->Asp[count]->values[0] = 1.0;
-
-		}
-		else {
-		    /*set the rows to zero */
-		    for (i = 0; i < les->cols; i++)
-			les->A[count][i] = 0.0;
-		    /*set the cols to zero */
-		    for (i = 0; i < les->rows; i++)
-			les->A[i][count] = 0.0;
-
-		    /*entry on the diagonal */
-		    les->A[count][count] = 1.0;
-		}
-	    }
-	    if (stat >= N_CELL_ACTIVE)
-		count++;
-	}
-    }
-
-    return 0;
-
-}
-
-/* **************************************************************** */
-/* **** make an entry in the les (2d) ***************************** */
-/* **************************************************************** */
-int make_les_entry_2d(int i, int j, int offset_i, int offset_j, int count,
-		      int pos, N_les * les, G_math_spvector * spvect,
-		      N_array_2d * cell_count, N_array_2d * status,
-		      N_array_2d * start_val, double entry, int cell_type)
-{
-    int K;
-    int di = offset_i;
-    int dj = offset_j;
-
-    K = N_get_array_2d_c_value(cell_count, i + di, j + dj) -
-	N_get_array_2d_c_value(cell_count, i, j);
-
-    /* active cells build the linear equation system */
-    if (cell_type == N_CELL_ACTIVE) {
-	/* dirichlet or transmission cells must be handled like this */
-	if (N_get_array_2d_c_value(status, i + di, j + dj) > N_CELL_ACTIVE &&
-	    N_get_array_2d_c_value(status, i + di, j + dj) < N_MAX_CELL_STATE)
-	    les->b[count] -=
-		N_get_array_2d_d_value(start_val, i + di, j + dj) * entry;
-	else if (N_get_array_2d_c_value(status, i + di, j + dj) ==
-		 N_CELL_ACTIVE) {
-	    if ((count + K) >= 0 && (count + K) < les->cols) {
-		G_debug(5,
-			" make_les_entry_2d: (N_CELL_ACTIVE) create matrix entry at row[%i] col[%i] value %g\n",
-			count, count + K, entry);
-		pos++;
-		if (les->type == N_SPARSE_LES) {
-		    spvect->index[pos] = count + K;
-		    spvect->values[pos] = entry;
-		}
-		else {
-		    les->A[count][count + K] = entry;
-		}
-	    }
-	}
-    }				/* if dirichlet cells should be used then check for all valid cell neighbours */
-    else if (cell_type == N_CELL_DIRICHLET) {
-	/* all valid cells */
-	if (N_get_array_2d_c_value(status, i + di, j + dj) > N_CELL_INACTIVE
-	    && N_get_array_2d_c_value(status, i + di,
-				      j + dj) < N_MAX_CELL_STATE) {
-	    if ((count + K) >= 0 && (count + K) < les->cols) {
-		G_debug(5,
-			" make_les_entry_2d: (N_CELL_DIRICHLET) create matrix entry at row[%i] col[%i] value %g\n",
-			count, count + K, entry);
-		pos++;
-		if (les->type == N_SPARSE_LES) {
-		    spvect->index[pos] = count + K;
-		    spvect->values[pos] = entry;
-		}
-		else {
-		    les->A[count][count + K] = entry;
-		}
-	    }
-	}
-    }
-
-    return pos;
-}
-
-
-/* *************************************************************** * 
- * ******************** N_assemble_les_3d ************************ * 
- * *************************************************************** */
-/*!
- * \brief Assemble a linear equation system (les) based on 3d location data (g3d) active cells
- *
- * This function calls #N_assemble_les_3d_param
- * */
-N_les *N_assemble_les_3d(int les_type, N_geom_data * geom,
-			 N_array_3d * status, N_array_3d * start_val,
-			 void *data, N_les_callback_3d * call)
-{
-    return N_assemble_les_3d_param(les_type, geom, status, start_val, data,
-				   call, N_CELL_ACTIVE);
-}
-
-/*!
- * \brief Assemble a linear equation system (les) based on 3d location data (g3d) active cells
- *
- * This function calls #N_assemble_les_3d_param
- * */
-N_les *N_assemble_les_3d_active(int les_type, N_geom_data * geom,
-				N_array_3d * status, N_array_3d * start_val,
-				void *data, N_les_callback_3d * call)
-{
-    return N_assemble_les_3d_param(les_type, geom, status, start_val, data,
-				   call, N_CELL_ACTIVE);
-}
-
-/*!
- * \brief Assemble a linear equation system (les) based on 3d location data (g3d) active and dirichlet cells
- *
- * This function calls #N_assemble_les_3d_param
- * */
-N_les *N_assemble_les_3d_dirichlet(int les_type, N_geom_data * geom,
-				   N_array_3d * status,
-				   N_array_3d * start_val, void *data,
-				   N_les_callback_3d * call)
-{
-    return N_assemble_les_3d_param(les_type, geom, status, start_val, data,
-				   call, N_CELL_DIRICHLET);
-}
-
-/*!
- * \brief Assemble a linear equation system (les) based on 3d location data (g3d)
- *
- * The linear equation system type can be set to N_NORMAL_LES to create a regular
- * matrix, or to N_SPARSE_LES to create a sparse matrix. This function returns
- * a new created linear equation system which can be solved with 
- * linear equation solvers. An 3d array with start values and an 3d status array
- * must be provided as well as the location geometry and a void pointer to data 
- * passed to the callback which creates the les row entries. This callback
- * must be defined in the N_les_callback_3d structure.
- * 
- * The creation of the les is parallelized with OpenMP. 
- * If you implement new callbacks, please make sure that the 
- * function calls are thread safe.
- *
- * the les can be created in two ways, with dirichlet and similar cells and without them,
- * to spare some memory. If the les is created with dirichlet cell, the dirichlet boundary condition
- * must be added.
- *
- * \param les_type int
- * \param geom      N_geom_data*
- * \param status    N_array_3d *
- * \param start_val N_array_3d *
- * \param data void *
- * \param call N_les_callback_3d *
- * \param cell_type int  -- les assemble based on N_CELL_ACTIVE or N_CELL_DIRICHLET
- * \return N_les *
- * */
-N_les *N_assemble_les_3d_param(int les_type, N_geom_data * geom,
-			       N_array_3d * status, N_array_3d * start_val,
-			       void *data, N_les_callback_3d * call,
-			       int cell_type)
-{
-    int i, j, k, count = 0, pos = 0;
-    int cell_type_count = 0;
-    N_array_3d *cell_count;
-    N_les *les = NULL;
-    int **index_ij;
-
-    G_debug(2,
-	    "N_assemble_les_3d: starting to assemble the linear equation system");
-
-    cell_count =
-	N_alloc_array_3d(geom->cols, geom->rows, geom->depths, 1, DCELL_TYPE);
-
-    /* First count the number of valid cells and save  
-     * each number in a new 3d array. Those numbers are used 
-     * to create the linear equation system.*/
-
-    if (cell_type == N_CELL_DIRICHLET) {
-	/* include dirichlet cells in the les */
-	for (k = 0; k < geom->depths; k++) {
-	    for (j = 0; j < geom->rows; j++) {
-		for (i = 0; i < geom->cols; i++) {
-		    /*use all non-inactive cells for les creation */
-		    if (N_CELL_INACTIVE <
-			(int)N_get_array_3d_d_value(status, i, j, k) &&
-			(int)N_get_array_3d_d_value(status, i, j,
-						    k) < N_MAX_CELL_STATE)
-			cell_type_count++;
-		}
-	    }
-	}
-    }
-    else {
-	/*use only active cell in the les */
-	for (k = 0; k < geom->depths; k++) {
-	    for (j = 0; j < geom->rows; j++) {
-		for (i = 0; i < geom->cols; i++) {
-		    /*count only active cells */
-		    if (N_CELL_ACTIVE
-			== (int)N_get_array_3d_d_value(status, i, j, k))
-			cell_type_count++;
-
-		}
-	    }
-	}
-    }
-
-    G_debug(2,
-	    "N_assemble_les_3d: number of  used cells %i\n", cell_type_count);
-
-    if (cell_type_count == 0.0)
-	G_fatal_error
-	    ("Not enough active cells [%i] to create the linear equation system. Check the cell status. Only active cells (value = 1) are used to create the equation system.",
-	     cell_type_count);
-
-    /* allocate the memory for the linear equation system (les). 
-     * Only valid cells are used to create the les. */
-    les = N_alloc_les_Ax_b(cell_type_count, les_type);
-
-    index_ij = (int **)G_calloc(cell_type_count, sizeof(int *));
-    for (i = 0; i < cell_type_count; i++)
-	index_ij[i] = (int *)G_calloc(3, sizeof(int));
-
-    count = 0;
-    /*count the number of cells which should be used to create the linear equation system */
-    /*save the k, i and j indices and create a ordered numbering */
-    for (k = 0; k < geom->depths; k++) {
-	for (j = 0; j < geom->rows; j++) {
-	    for (i = 0; i < geom->cols; i++) {
-		if (cell_type == N_CELL_DIRICHLET) {
-		    if (N_CELL_INACTIVE <
-			(int)N_get_array_3d_d_value(status, i, j, k) &&
-			(int)N_get_array_3d_d_value(status, i, j,
-						    k) < N_MAX_CELL_STATE) {
-			N_put_array_3d_d_value(cell_count, i, j, k, count);
-			index_ij[count][0] = i;
-			index_ij[count][1] = j;
-			index_ij[count][2] = k;
-			count++;
-			G_debug(5,
-				"N_assemble_les_3d: non-inactive cells count %i at pos x[%i] y[%i] z[%i]\n",
-				count, i, j, k);
-		    }
-		}
-		else if (N_CELL_ACTIVE ==
-			 (int)N_get_array_3d_d_value(status, i, j, k)) {
-		    N_put_array_3d_d_value(cell_count, i, j, k, count);
-		    index_ij[count][0] = i;
-		    index_ij[count][1] = j;
-		    index_ij[count][2] = k;
-		    count++;
-		    G_debug(5,
-			    "N_assemble_les_3d: active cells count %i at pos x[%i] y[%i] z[%i]\n",
-			    count, i, j, k);
-		}
-	    }
-	}
-    }
-
-    G_debug(2, "N_assemble_les_3d: starting the parallel assemble loop");
-
-#pragma omp parallel for private(i, j, k, pos, count) schedule(static)
-    for (count = 0; count < cell_type_count; count++) {
-	i = index_ij[count][0];
-	j = index_ij[count][1];
-	k = index_ij[count][2];
-
-	/*create the entries for the */
-	N_data_star *items = call->callback(data, geom, i, j, k);
-
-	G_math_spvector *spvect = NULL;
-
-	/*allocate a sprase vector */
-	if (les_type == N_SPARSE_LES)
-	    spvect = G_math_alloc_spvector(items->count);
-	/* initial conditions */
-
-	les->x[count] = N_get_array_3d_d_value(start_val, i, j, k);
-
-	/* the entry in the vector b */
-	les->b[count] = items->V;
-
-	/* pos describes the position in the sparse vector.
-	 * the first entry is always the diagonal entry of the matrix*/
-	pos = 0;
-
-	if (les_type == N_SPARSE_LES) {
-	    spvect->index[pos] = count;
-	    spvect->values[pos] = items->C;
-	}
-	else {
-	    les->A[count][count] = items->C;
-	}
-	/* western neighbour, entry is col - 1 */
-	if (i > 0) {
-	    pos =
-		make_les_entry_3d(i, j, k, -1, 0, 0, count, pos, les, spvect,
-				  cell_count, status, start_val, items->W,
-				  cell_type);
-	}
-	/* eastern neighbour, entry col + 1 */
-	if (i < geom->cols - 1) {
-	    pos = make_les_entry_3d(i, j, k, 1, 0, 0, count, pos, les, spvect,
-				    cell_count, status, start_val, items->E,
-				    cell_type);
-	}
-	/* northern neighbour, entry row -1 */
-	if (j > 0) {
-	    pos =
-		make_les_entry_3d(i, j, k, 0, -1, 0, count, pos, les, spvect,
-				  cell_count, status, start_val, items->N,
-				  cell_type);
-	}
-	/* southern neighbour, entry row +1 */
-	if (j < geom->rows - 1) {
-	    pos = make_les_entry_3d(i, j, k, 0, 1, 0, count, pos, les, spvect,
-				    cell_count, status, start_val, items->S,
-				    cell_type);
-	}
-	/*only for a 7 star entry needed */
-	if (items->type == N_7_POINT_STAR || items->type == N_27_POINT_STAR) {
-	    /* the upper cell (top), entry depth + 1 */
-	    if (k < geom->depths - 1) {
-		pos =
-		    make_les_entry_3d(i, j, k, 0, 0, 1, count, pos, les,
-				      spvect, cell_count, status, start_val,
-				      items->T, cell_type);
-	    }
-	    /* the lower cell (bottom), entry depth - 1 */
-	    if (k > 0) {
-		pos =
-		    make_les_entry_3d(i, j, k, 0, 0, -1, count, pos, les,
-				      spvect, cell_count, status, start_val,
-				      items->B, cell_type);
-	    }
-	}
-
-	/*How many entries in the les */
-	if (les->type == N_SPARSE_LES) {
-	    spvect->cols = pos + 1;
-	    G_math_add_spvector(les->Asp, spvect, count);
-	}
-
-	if (items)
-	    G_free(items);
-    }
-
-    N_free_array_3d(cell_count);
-
-    for (i = 0; i < cell_type_count; i++)
-	G_free(index_ij[i]);
-
-    G_free(index_ij);
-
-    return les;
-}
-
-/*!
- * \brief Integrate Dirichlet or Transmission boundary conditions into the les (3d)
- *
- * Dirichlet and Transmission boundary conditions will be integrated into
- * the provided linear equation system. This is meaningfull if
- * the les was created with #N_assemble_les_2d_dirichlet, because in
- * this case Dirichlet boundary conditions are not automatically included.
- *
- * The provided les will be modified:
- *
- * Ax = b will be splitted into Ax_u + Ax_d = b
- *
- * x_u - the unknowns
- * x_d - the Dirichlet cells
- *
- * Ax_u = b -Ax_d will be computed. Then the matrix A will be modified to
- *
- * | A_u  0 | x_u
- * |  0   I | x_d
- *
- * \param les N_les* -- the linear equation system
- * \param geom N_geom_data* -- geometrical data information
- * \param status N_array_2d* -- the status array containing the cell types
- * \param start_val N_array_2d* -- an array with start values
- * \return int -- 1 = success, 0 = failure
- * */
-int N_les_integrate_dirichlet_3d(N_les * les, N_geom_data * geom,
-				 N_array_3d * status, N_array_3d * start_val)
-{
-    int rows, cols, depths;
-    int count = 0;
-    int i, j, x, y, z, stat;
-    double *dvect1;
-    double *dvect2;
-
-    G_debug(2,
-	    "N_les_integrate_dirichlet_3d: integrating the dirichlet boundary condition");
-
-    rows = geom->rows;
-    cols = geom->cols;
-    depths = geom->depths;
-
-    /*we nned to additional vectors */
-    dvect1 = (double *)G_calloc(les->cols, sizeof(double));
-    dvect2 = (double *)G_calloc(les->cols, sizeof(double));
-
-    /*fill the first one with the x vector data of Dirichlet cells */
-    count = 0;
-    for (z = 0; z < depths; z++) {
-	for (y = 0; y < rows; y++) {
-	    for (x = 0; x < cols; x++) {
-		stat = (int)N_get_array_3d_d_value(status, x, y, z);
-		if (stat > N_CELL_ACTIVE && stat < N_MAX_CELL_STATE) {
-		    dvect1[count] =
-			N_get_array_3d_d_value(start_val, x, y, z);
-		    count++;
-		}
-		else if (stat == N_CELL_ACTIVE) {
-		    dvect1[count] = 0.0;
-		    count++;
-		}
-	    }
-	}
-    }
-
-#pragma omp parallel default(shared)
-    {
-	/*perform the matrix vector product and */
-	if (les->type == N_SPARSE_LES)
-	    G_math_Ax_sparse(les->Asp, dvect1, dvect2, les->rows);
-	else
-	    G_math_d_Ax(les->A, dvect1, dvect2, les->rows, les->cols);
-#pragma omp for schedule (static) private(i)
-	for (i = 0; i < les->cols; i++)
-	    les->b[i] = les->b[i] - dvect2[i];
-    }
-
-    /*now set the Dirichlet cell rows and cols to zero and the 
-     * diagonal entry to 1*/
-    count = 0;
-    for (z = 0; z < depths; z++) {
-	for (y = 0; y < rows; y++) {
-	    for (x = 0; x < cols; x++) {
-		stat = (int)N_get_array_3d_d_value(status, x, y, z);
-		if (stat > N_CELL_ACTIVE && stat < N_MAX_CELL_STATE) {
-		    if (les->type == N_SPARSE_LES) {
-			/*set the rows to zero */
-			for (i = 0; i < les->Asp[count]->cols; i++)
-			    les->Asp[count]->values[i] = 0.0;
-			/*set the cols to zero */
-			for (i = 0; i < les->rows; i++) {
-			    for (j = 0; j < les->Asp[i]->cols; j++) {
-				if (les->Asp[i]->index[j] == count)
-				    les->Asp[i]->values[j] = 0.0;
-			    }
-			}
-
-			/*entry on the diagonal */
-			les->Asp[count]->values[0] = 1.0;
-
-		    }
-		    else {
-			/*set the rows to zero */
-			for (i = 0; i < les->cols; i++)
-			    les->A[count][i] = 0.0;
-			/*set the cols to zero */
-			for (i = 0; i < les->rows; i++)
-			    les->A[i][count] = 0.0;
-
-			/*entry on the diagonal */
-			les->A[count][count] = 1.0;
-		    }
-		}
-		count++;
-	    }
-	}
-    }
-
-    return 0;
-
-}
-
-/* **************************************************************** */
-/* **** make an entry in the les (3d) ***************************** */
-/* **************************************************************** */
-int make_les_entry_3d(int i, int j, int k, int offset_i, int offset_j,
-		      int offset_k, int count, int pos, N_les * les,
-		      G_math_spvector * spvect, N_array_3d * cell_count,
-		      N_array_3d * status, N_array_3d * start_val,
-		      double entry, int cell_type)
-{
-    int K;
-    int di = offset_i;
-    int dj = offset_j;
-    int dk = offset_k;
-
-    K = (int)N_get_array_3d_d_value(cell_count, i + di, j + dj, k + dk) -
-	(int)N_get_array_3d_d_value(cell_count, i, j, k);
-
-    if (cell_type == N_CELL_ACTIVE) {
-	if ((int)N_get_array_3d_d_value(status, i + di, j + dj, k + dk) >
-	    N_CELL_ACTIVE &&
-	    (int)N_get_array_3d_d_value(status, i + di, j + dj,
-					k + dk) < N_MAX_CELL_STATE)
-	    les->b[count] -=
-		N_get_array_3d_d_value(start_val, i + di, j + dj,
-				       k + dk) * entry;
-	else if ((int)N_get_array_3d_d_value(status, i + di, j + dj, k + dk)
-		 == N_CELL_ACTIVE) {
-	    if ((count + K) >= 0 && (count + K) < les->cols) {
-		G_debug(5,
-			" make_les_entry_3d: (N_CELL_ACTIVE) create matrix entry at row[%i] col[%i] value %g\n",
-			count, count + K, entry);
-		pos++;
-		if (les->type == N_SPARSE_LES) {
-		    spvect->index[pos] = count + K;
-		    spvect->values[pos] = entry;
-		}
-		else {
-		    les->A[count][count + K] = entry;
-		}
-	    }
-	}
-    }
-    else if (cell_type == N_CELL_DIRICHLET) {
-	if ((int)N_get_array_3d_d_value(status, i + di, j + dj, k + dk)
-	    != N_CELL_INACTIVE) {
-	    if ((count + K) >= 0 && (count + K) < les->cols) {
-		G_debug(5,
-			" make_les_entry_3d: (N_CELL_DIRICHLET) create matrix entry at row[%i] col[%i] value %g\n",
-			count, count + K, entry);
-		pos++;
-		if (les->type == N_SPARSE_LES) {
-		    spvect->index[pos] = count + K;
-		    spvect->values[pos] = entry;
-		}
-		else {
-		    les->A[count][count + K] = entry;
-		}
-	    }
-	}
-    }
-
-    return pos;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_parse_options.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_parse_options.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_parse_options.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,111 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:      standard parser option for the numerical pde library
-*
-* COPYRIGHT:    (C) 2000 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <grass/glocale.h>
-#include <grass/N_pde.h>
-
-/*!
- * \brief Create standardised Option structure related to the gpde library.
- *
- * This function will create a standardised Option structure
- * defined by parameter opt. A list of valid parameters can be found in N_pde.h.
- * It allocates memory for the Option structure and returns a pointer to
- * this memory (of <i>type struct Option *</i>).<br>
- *
- * If an invalid parameter was specified an empty Option structure will
- * be returned (not NULL).
- *
- * This function is related to the gpde library, general standard options can be 
- * found in lib/gis/parser.c. These options are set with G_define_standard_option ();
- *
- * \param[in] opt Type of Option struct to create
- * \return Option * Pointer to an Option struct
- *
- * */
-struct Option *N_define_standard_option(int opt)
-{
-    struct Option *Opt;
-
-    Opt = G_define_option();
-
-    switch (opt) {
-	/*solver for symmetric, positive definite linear equation systems */
-    case N_OPT_SOLVER_SYMM:
-	Opt->key = "solver";
-	Opt->type = TYPE_STRING;
-	Opt->required = NO;
-	Opt->key_desc = "name";
-	Opt->answer = "cg";
-	Opt->options = "gauss,lu,cholesky,jacobi,sor,cg,bicgstab,pcg";
-        Opt->guisection = "Solver";
-	Opt->description =
-	    ("The type of solver which should solve the symmetric linear equation system");
-	break;
-	/*solver for unsymmetric linear equation systems */
-    case N_OPT_SOLVER_UNSYMM:
-	Opt->key = "solver";
-	Opt->type = TYPE_STRING;
-	Opt->required = NO;
-	Opt->key_desc = "name";
-	Opt->answer = "bicgstab";
-	Opt->options = "gauss,lu,jacobi,sor,bicgstab";
-        Opt->guisection = "Solver";
-	Opt->description =
-	    ("The type of solver which should solve the linear equation system");
-	break;
-    case N_OPT_MAX_ITERATIONS:
-	Opt->key = "maxit";
-	Opt->type = TYPE_INTEGER;
-	Opt->required = NO;
-	Opt->answer = "10000";
-        Opt->guisection = "Solver";
-	Opt->description =
-	    ("Maximum number of iteration used to solve the linear equation system");
-	break;
-    case N_OPT_ITERATION_ERROR:
-	Opt->key = "error";
-	Opt->type = TYPE_DOUBLE;
-	Opt->required = NO;
-	Opt->answer = "0.000001";
-        Opt->guisection = "Solver";
-	Opt->description =
-	    ("Error break criteria for iterative solver");
-	break;
-    case N_OPT_SOR_VALUE:
-	Opt->key = "relax";
-	Opt->type = TYPE_DOUBLE;
-	Opt->required = NO;
-	Opt->answer = "1";
-        Opt->guisection = "Solver";
-	Opt->description =
-	    ("The relaxation parameter used by the jacobi and sor solver for speedup or stabilizing");
-	break;
-    case N_OPT_CALC_TIME:
-	Opt->key = "dt";
-	Opt->type = TYPE_DOUBLE;
-	Opt->required = YES;
-	Opt->answer = "86400";
-        Opt->guisection = "Solver";
-	Opt->description = _("The calculation time in seconds");
-	break;
-    }
-
-    return Opt;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_solute_transport.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_solute_transport.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_solute_transport.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,772 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:      solute transport in porous media
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2007 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 <grass/N_solute_transport.h>
-
-/* ************************************************************************* *
- * ************************************************************************* *
- * ************************************************************************* */
-/*! \brief This is just a placeholder
- *
- * */
-N_data_star *N_callback_solute_transport_3d(void *solutedata,
-					    N_geom_data * geom, int col,
-					    int row, int depth)
-{
-    double Df_e = 0, Df_w = 0, Df_n = 0, Df_s = 0, Df_t = 0, Df_b = 0;
-    double dx, dy, dz, Az;
-    double diff_x, diff_y, diff_z;
-    double diff_xw, diff_yn;
-    double diff_xe, diff_ys;
-    double diff_zt, diff_zb;
-    double cin = 0, cg, cg_start;
-    double R, nf, cs, q;
-    double C, W, E, N, S, T, B, V;
-    double vw = 0, ve = 0, vn = 0, vs = 0, vt = 0, vb = 0;
-    double Ds_w = 0, Ds_e = 0, Ds_n = 0, Ds_s = 0, Ds_t = 0, Ds_b = 0;
-    double Dw = 0, De = 0, Dn = 0, Ds = 0, Dt = 0, Db = 0;
-    double rw = 0.5, re = 0.5, rn = 0.5, rs = 0.5, rt = 0.5, rb = 0.5;
-
-    N_solute_transport_data3d *data = NULL;
-    N_data_star *mat_pos;
-    N_gradient_3d grad;
-
-    /*cast the void pointer to the right data structure */
-    data = (N_solute_transport_data3d *) solutedata;
-
-    N_get_gradient_3d(data->grad, &grad, col, row, depth);
-
-    dx = geom->dx;
-    dy = geom->dy;
-    dz = geom->dz;
-    Az = N_get_geom_data_area_of_cell(geom, row);
-
-    /*read the data from the arrays */
-    cg_start = N_get_array_3d_d_value(data->c_start, col, row, depth);
-    cg = N_get_array_3d_d_value(data->c, col, row, depth);
-
-    /*get the surrounding diffusion tensor entries */
-    diff_x = N_get_array_3d_d_value(data->diff_x, col, row, depth);
-    diff_y = N_get_array_3d_d_value(data->diff_y, col, row, depth);
-    diff_z = N_get_array_3d_d_value(data->diff_z, col, row, depth);
-    diff_xw = N_get_array_3d_d_value(data->diff_x, col - 1, row, depth);
-    diff_xe = N_get_array_3d_d_value(data->diff_x, col + 1, row, depth);
-    diff_yn = N_get_array_3d_d_value(data->diff_y, col, row - 1, depth);
-    diff_ys = N_get_array_3d_d_value(data->diff_y, col, row + 1, depth);
-    diff_zt = N_get_array_3d_d_value(data->diff_z, col, row, depth + 1);
-    diff_zb = N_get_array_3d_d_value(data->diff_z, col, row, depth - 1);
-
-    /* calculate the diffusion on the cell borders using the harmonical mean */
-    Df_w = N_calc_harmonic_mean(diff_xw, diff_x);
-    Df_e = N_calc_harmonic_mean(diff_xe, diff_x);
-    Df_n = N_calc_harmonic_mean(diff_yn, diff_y);
-    Df_s = N_calc_harmonic_mean(diff_ys, diff_y);
-    Df_t = N_calc_harmonic_mean(diff_zt, diff_z);
-    Df_b = N_calc_harmonic_mean(diff_zb, diff_z);
-
-    /* calculate the dispersion */
-    /*todo */
-
-    /* calculate the velocity parts  with full upwinding scheme */
-    vw = grad.WC;
-    ve = grad.EC;
-    vn = grad.NC;
-    vs = grad.SC;
-    vt = grad.TC;
-    vb = grad.BC;
-
-    /* put the diffusion and dispersion together */
-    Dw = ((Df_w + Ds_w)) / dx;
-    De = ((Df_e + Ds_e)) / dx;
-    Dn = ((Df_n + Ds_n)) / dy;
-    Ds = ((Df_s + Ds_s)) / dy;
-    Dt = ((Df_t + Ds_t)) / dz;
-    Db = ((Df_b + Ds_b)) / dz;
-
-    rw = N_exp_upwinding(-1 * vw, dx, Dw);
-    re = N_exp_upwinding(ve, dx, De);
-    rs = N_exp_upwinding(-1 * vs, dy, Ds);
-    rn = N_exp_upwinding(vn, dy, Dn);
-    rb = N_exp_upwinding(-1 * vb, dz, Dn);
-    rt = N_exp_upwinding(vt, dz, Dn);
-
-    /*mass balance center cell to western cell */
-    W = -1 * (Dw) * dy * dz - vw * (1 - rw) * dy * dz;
-    /*mass balance center cell to eastern cell */
-    E = -1 * (De) * dy * dz + ve * (1 - re) * dy * dz;
-    /*mass balance center cell to southern cell */
-    S = -1 * (Ds) * dx * dz - vs * (1 - rs) * dx * dz;
-    /*mass balance center cell to northern cell */
-    N = -1 * (Dn) * dx * dz + vn * (1 - rn) * dx * dz;
-    /*mass balance center cell to bottom cell */
-    B = -1 * (Db) * Az - vb * (1 - rb) * Az;
-    /*mass balance center cell to top cell */
-    T = -1 * (Dt) * Az + vt * (1 - rt) * Az;
-
-    /* Retardation */
-    R = N_get_array_3d_d_value(data->R, col, row, depth);
-    /* Inner sources */
-    cs = N_get_array_3d_d_value(data->cs, col, row, depth);
-    /* effective porosity */
-    nf = N_get_array_3d_d_value(data->nf, col, row, depth);
-    /* groundwater sources and sinks */
-    q = N_get_array_3d_d_value(data->q, col, row, depth);
-    /* concentration of influent water */
-    cin = N_get_array_3d_d_value(data->cin, col, row, depth);
-
-    /*the diagonal entry of the matrix */
-    C = ((Dw - vw) * dy * dz +
-	 (De + ve) * dy * dz +
-	 (Ds - vs) * dx * dz +
-	 (Dn + vn) * dx * dz +
-	 (Db - vb) * Az + (Dt + vt) * Az + Az * dz * R / data->dt - q / nf);
-
-    /*the entry in the right side b of Ax = b */
-    V = (cs + cg_start * Az * dz * R / data->dt - q / nf * cin);
-
-    /*
-     * printf("nf %g\n", nf);
-     * printf("q %g\n", q);
-     * printf("cs %g\n", cs);
-     * printf("cin %g\n", cin);
-     * printf("cg %g\n", cg);
-     * printf("cg_start %g\n", cg_start);
-     * printf("Az %g\n", Az);
-     * printf("z %g\n", z);
-     * printf("R %g\n", R);
-     * printf("dt %g\n", data->dt);
-     */
-    G_debug(6, "N_callback_solute_transport_3d: called [%i][%i][%i]", row,
-	    col, depth);
-
-    /*create the 7 point star entries */
-    mat_pos = N_create_7star(C, W, E, N, S, T, B, V);
-
-    return mat_pos;
-}
-
-/* ************************************************************************* *
- * ************************************************************************* *
- * ************************************************************************* */
-/*!
- * \brief This callback function creates the mass balance of a 5 point star
- *
- * The mass balance is based on the common solute transport equation:
- *
- * \f[\frac{\partial c_g}{\partial t} R = \nabla \cdot ({\bf D} \nabla c_g - {\bf u} c_g) + \sigma + \frac{q}{n_f}(c_g - c_in) \f]
- *
- * This equation is discretizised with the finite volume method in two dimensions.
- *
- *
- * \param solutedata  * N_solute_transport_data2d - a void pointer to the data structure
- * \param geom N_geom_data *
- * \param col   int
- * \param row   int
- * \return N_data_star * - a five point data star
- *
- * */
-N_data_star *N_callback_solute_transport_2d(void *solutedata,
-					    N_geom_data * geom, int col,
-					    int row)
-{
-    double Df_e = 0, Df_w = 0, Df_n = 0, Df_s = 0;
-    double z_e = 0, z_w = 0, z_n = 0, z_s = 0;
-    double dx, dy, Az;
-    double diff_x, diff_y;
-    double disp_x, disp_y;
-    double z;
-    double diff_xw, diff_yn;
-    double disp_xw, disp_yn;
-    double z_xw, z_yn;
-    double diff_xe, diff_ys;
-    double disp_xe, disp_ys;
-    double z_xe, z_ys;
-    double cin = 0, cg, cg_start;
-    double R, nf, cs, q;
-    double C, W, E, N, S, V, NE, NW, SW, SE;
-    double vw = 0, ve = 0, vn = 0, vs = 0;
-    double Ds_w = 0, Ds_e = 0, Ds_n = 0, Ds_s = 0;
-    double Dw = 0, De = 0, Dn = 0, Ds = 0;
-    double rw = 0.5, re = 0.5, rn = 0.5, rs = 0.5;
-
-    N_solute_transport_data2d *data = NULL;
-    N_data_star *mat_pos;
-    N_gradient_2d grad;
-
-    /*cast the void pointer to the right data structure */
-    data = (N_solute_transport_data2d *) solutedata;
-
-    N_get_gradient_2d(data->grad, &grad, col, row);
-
-    dx = geom->dx;
-    dy = geom->dy;
-    Az = N_get_geom_data_area_of_cell(geom, row);
-
-    /*read the data from the arrays */
-    cg_start = N_get_array_2d_d_value(data->c_start, col, row);
-    cg = N_get_array_2d_d_value(data->c, col, row);
-
-    /* calculate the cell height */
-    z = N_get_array_2d_d_value(data->top, col,
-			       row) -
-	N_get_array_2d_d_value(data->bottom, col, row);
-    z_xw =
-	N_get_array_2d_d_value(data->top, col - 1,
-			       row) -
-	N_get_array_2d_d_value(data->bottom, col - 1, row);
-    z_xe =
-	N_get_array_2d_d_value(data->top, col + 1,
-			       row) -
-	N_get_array_2d_d_value(data->bottom, col + 1, row);
-    z_yn =
-	N_get_array_2d_d_value(data->top, col,
-			       row - 1) -
-	N_get_array_2d_d_value(data->bottom, col, row - 1);
-    z_ys =
-	N_get_array_2d_d_value(data->top, col,
-			       row + 1) -
-	N_get_array_2d_d_value(data->bottom, col, row + 1);
-
-    /*geometrical mean of cell height */
-    z_w = N_calc_geom_mean(z_xw, z);
-    z_e = N_calc_geom_mean(z_xe, z);
-    z_n = N_calc_geom_mean(z_yn, z);
-    z_s = N_calc_geom_mean(z_ys, z);
-
-    /*get the surrounding diffusion tensor entries */
-    diff_x = N_get_array_2d_d_value(data->diff_x, col, row);
-    diff_y = N_get_array_2d_d_value(data->diff_y, col, row);
-    diff_xw = N_get_array_2d_d_value(data->diff_x, col - 1, row);
-    diff_xe = N_get_array_2d_d_value(data->diff_x, col + 1, row);
-    diff_yn = N_get_array_2d_d_value(data->diff_y, col, row - 1);
-    diff_ys = N_get_array_2d_d_value(data->diff_y, col, row + 1);
-
-    /* calculate the diffusion at the cell borders using the harmonical mean */
-    Df_w = N_calc_harmonic_mean(diff_xw, diff_x);
-    Df_e = N_calc_harmonic_mean(diff_xe, diff_x);
-    Df_n = N_calc_harmonic_mean(diff_yn, diff_y);
-    Df_s = N_calc_harmonic_mean(diff_ys, diff_y);
-
-    /* calculate the dispersion */
-    /*get the surrounding dispersion tensor entries */
-    disp_x = N_get_array_2d_d_value(data->disp_xx, col, row);
-    disp_y = N_get_array_2d_d_value(data->disp_yy, col, row);
-    if (N_get_array_2d_d_value(data->status, col - 1, row) ==
-	N_CELL_TRANSMISSION) {
-	disp_xw = disp_x;
-    }
-    else {
-	disp_xw = N_get_array_2d_d_value(data->disp_xx, col - 1, row);
-    }
-    if (N_get_array_2d_d_value(data->status, col + 1, row) ==
-	N_CELL_TRANSMISSION) {
-	disp_xe = disp_x;
-    }
-    else {
-	disp_xe = N_get_array_2d_d_value(data->disp_xx, col + 1, row);
-    }
-    if (N_get_array_2d_d_value(data->status, col, row - 1) ==
-	N_CELL_TRANSMISSION) {
-	disp_yn = disp_y;
-    }
-    else {
-	disp_yn = N_get_array_2d_d_value(data->disp_yy, col, row - 1);
-    }
-    if (N_get_array_2d_d_value(data->status, col, row + 1) ==
-	N_CELL_TRANSMISSION) {
-	disp_ys = disp_y;
-    }
-    else {
-	disp_ys = N_get_array_2d_d_value(data->disp_yy, col, row + 1);
-    }
-
-    /* calculate the dispersion at the cell borders using the harmonical mean */
-    Ds_w = N_calc_harmonic_mean(disp_xw, disp_x);
-    Ds_e = N_calc_harmonic_mean(disp_xe, disp_x);
-    Ds_n = N_calc_harmonic_mean(disp_yn, disp_y);
-    Ds_s = N_calc_harmonic_mean(disp_ys, disp_y);
-
-    /* put the diffusion and dispersion together */
-    Dw = ((Df_w + Ds_w)) / dx;
-    De = ((Df_e + Ds_e)) / dx;
-    Ds = ((Df_s + Ds_s)) / dy;
-    Dn = ((Df_n + Ds_n)) / dy;
-
-    vw = -1.0 * grad.WC;
-    ve = grad.EC;
-    vs = -1.0 * grad.SC;
-    vn = grad.NC;
-
-    if (data->stab == N_UPWIND_FULL) {
-	rw = N_full_upwinding(vw, dx, Dw);
-	re = N_full_upwinding(ve, dx, De);
-	rs = N_full_upwinding(vs, dy, Ds);
-	rn = N_full_upwinding(vn, dy, Dn);
-    }
-    else if (data->stab == N_UPWIND_EXP) {
-	rw = N_exp_upwinding(vw, dx, Dw);
-	re = N_exp_upwinding(ve, dx, De);
-	rs = N_exp_upwinding(vs, dy, Ds);
-	rn = N_exp_upwinding(vn, dy, Dn);
-    }
-
-    /*mass balance center cell to western cell */
-    W = -1 * (Dw) * dy * z_w + vw * (1 - rw) * dy * z_w;
-    /*mass balance center cell to eastern cell */
-    E = -1 * (De) * dy * z_e + ve * (1 - re) * dy * z_e;
-    /*mass balance center cell to southern cell */
-    S = -1 * (Ds) * dx * z_s + vs * (1 - rs) * dx * z_s;
-    /*mass balance center cell to northern cell */
-    N = -1 * (Dn) * dx * z_n + vn * (1 - rn) * dx * z_n;
-
-    NW = 0.0;
-    SW = 0.0;
-    NE = 0.0;
-    SE = 0.0;
-
-    /* Retardation */
-    R = N_get_array_2d_d_value(data->R, col, row);
-    /* Inner sources */
-    cs = N_get_array_2d_d_value(data->cs, col, row);
-    /* effective porosity */
-    nf = N_get_array_2d_d_value(data->nf, col, row);
-    /* groundwater sources and sinks */
-    q = N_get_array_2d_d_value(data->q, col, row);
-    /* concentration of influent water */
-    cin = N_get_array_2d_d_value(data->cin, col, row);
-
-    /*the diagonal entry of the matrix */
-    C = (Dw + vw * rw) * dy * z_w +
-	(De + ve * re) * dy * z_e +
-	(Ds + vs * rs) * dx * z_s +
-	(Dn + vn * rn) * dx * z_n + Az * z * R / data->dt - q / nf;
-
-    /*the entry in the right side b of Ax = b */
-    V = (cs + cg_start * Az * z * R / data->dt + q / nf * cin);
-
-    /*
-       fprintf(stderr, "nf %g\n", nf);
-       fprintf(stderr, "q %g\n", q);
-       fprintf(stderr, "cs %g\n", cs);
-       fprintf(stderr, "cin %g\n", cin);
-       fprintf(stderr, "cg %g\n", cg);
-       fprintf(stderr, "cg_start %g\n", cg_start);
-       fprintf(stderr, "Az %g\n", Az);
-       fprintf(stderr, "z %g\n", z);
-       fprintf(stderr, "R %g\n", R);
-       fprintf(stderr, "dt %g\n", data->dt);
-     */
-
-    G_debug(6, "N_callback_solute_transport_2d: called [%i][%i]", row, col);
-
-    /*create the 9 point star entries */
-    mat_pos = N_create_9star(C, W, E, N, S, NW, SW, NE, SE, V);
-
-    return mat_pos;
-}
-
-/* ************************************************************************* *
- * ************************************************************************* *
- * ************************************************************************* */
-/*!
- * \brief Alllocate memory for the solute transport data structure in three dimensions
- *
- * The solute transport data structure will be allocated including
- * all appendant 3d arrays. The offset for the 3d arrays is one
- * to establish homogeneous Neumann boundary conditions at the calculation area border.
- * This data structure is used to create a linear equation system based on the computation of
- * solute transport in porous media with the finite volume method.
- *
- * \param cols   int
- * \param rows   int
- * \param depths int
- * \return N_solute_transport_data3d *
- * */
-
-N_solute_transport_data3d *N_alloc_solute_transport_data3d(int cols, int rows,
-							   int depths)
-{
-    N_solute_transport_data3d *data = NULL;
-
-    data =
-	(N_solute_transport_data3d *) G_calloc(1,
-					       sizeof
-					       (N_solute_transport_data3d));
-
-    data->c = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->c_start = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->status = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->diff_x = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->diff_y = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->diff_z = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->q = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->cs = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->R = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->nf = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->cin = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-
-    /*Allocate the dispersivity tensor */
-    data->disp_xx = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->disp_yy = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->disp_zz = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->disp_xy = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->disp_xz = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-    data->disp_yz = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
-
-
-    data->grad = N_alloc_gradient_field_3d(cols, rows, depths);
-    data->stab = N_UPWIND_EXP;
-
-    return data;
-}
-
-/* ************************************************************************* *
- * ************************************************************************* *
- * ************************************************************************* */
-/*!
- * \brief Alllocate memory for the solute transport data structure in two dimensions
- *
- * The solute transport data structure will be allocated including
- * all appendant 2d arrays. The offset for the 2d arrays is one
- * to establish homogeneous Neumann boundary conditions at the calculation area border.
- * This data structure is used to create a linear equation system based on the computation of
- * solute transport in porous media with the finite volume method.
- *
- * \param cols   int
- * \param rows   int
- * \return N_solute_transport_data2d *
- * */
-
-
-N_solute_transport_data2d *N_alloc_solute_transport_data2d(int cols, int rows)
-{
-    N_solute_transport_data2d *data = NULL;
-
-    data =
-	(N_solute_transport_data2d *) G_calloc(1,
-					       sizeof
-					       (N_solute_transport_data2d));
-
-    data->c = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->c_start = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->status = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->diff_x = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->diff_y = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->q = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->cs = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->R = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->nf = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->cin = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->top = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->bottom = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-
-    /*Allocate the dispersivity tensor */
-    data->disp_xx = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->disp_yy = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-    data->disp_xy = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
-
-    data->grad = N_alloc_gradient_field_2d(cols, rows);
-    data->stab = N_UPWIND_EXP;
-
-    return data;
-}
-
-/* ************************************************************************* *
- * ************************************************************************* *
- * ************************************************************************* */
-/*!
- * \brief Release the memory of the solute transport data structure in three dimensions
- *
- * \param data N_solute_transport_data2d *
- * \return void *
- * */
-void N_free_solute_transport_data3d(N_solute_transport_data3d * data)
-{
-    N_free_array_3d(data->c);
-    N_free_array_3d(data->c_start);
-    N_free_array_3d(data->status);
-    N_free_array_3d(data->diff_x);
-    N_free_array_3d(data->diff_y);
-    N_free_array_3d(data->diff_z);
-    N_free_array_3d(data->q);
-    N_free_array_3d(data->cs);
-    N_free_array_3d(data->R);
-    N_free_array_3d(data->nf);
-    N_free_array_3d(data->cin);
-
-    N_free_array_3d(data->disp_xx);
-    N_free_array_3d(data->disp_yy);
-    N_free_array_3d(data->disp_zz);
-    N_free_array_3d(data->disp_xy);
-    N_free_array_3d(data->disp_xz);
-    N_free_array_3d(data->disp_yz);
-
-    G_free(data);
-
-    data = NULL;
-
-    return;
-}
-
-/* ************************************************************************* *
- * ************************************************************************* *
- * ************************************************************************* */
-/*!
- * \brief Release the memory of the solute transport data structure in two dimensions
- *
- * \param data N_solute_transport_data2d *
- * \return void *
- * */
-void N_free_solute_transport_data2d(N_solute_transport_data2d * data)
-{
-    N_free_array_2d(data->c);
-    N_free_array_2d(data->c_start);
-    N_free_array_2d(data->status);
-    N_free_array_2d(data->diff_x);
-    N_free_array_2d(data->diff_y);
-    N_free_array_2d(data->q);
-    N_free_array_2d(data->cs);
-    N_free_array_2d(data->R);
-    N_free_array_2d(data->nf);
-    N_free_array_2d(data->cin);
-    N_free_array_2d(data->top);
-    N_free_array_2d(data->bottom);
-
-    N_free_array_2d(data->disp_xx);
-    N_free_array_2d(data->disp_yy);
-    N_free_array_2d(data->disp_xy);
-
-    G_free(data);
-
-    data = NULL;
-
-    return;
-}
-
-/*!
- * \brief Compute the transmission boundary condition in 2d
- *
- * This function calculates the transmission boundary condition
- * for each cell with status N_CELL_TRANSMISSION. The surrounding
- * gradient field is used to verfiy the flow direction. If a flow
- * goes into a cell, the concentration (data->c) from the neighbour cell is
- * added to the transmission cell. If the flow from several neighbour 
- * cells goes into the cell, the concentration mean is calculated.
- * 
- * The new concentrations are written into the data->c_start array,
- * so they can be handled by the matrix assembling function.
- *
- * \param data N_solute_transport_data2d *
- * \return void *
- * */
-void N_calc_solute_transport_transmission_2d(N_solute_transport_data2d * data)
-{
-    int i, j, count = 1;
-    int cols, rows;
-    double c;
-    N_gradient_2d grad;
-
-    cols = data->grad->cols;
-    rows = data->grad->rows;
-
-    G_debug(2,
-	    "N_calc_solute_transport_transmission_2d: calculating transmission boundary");
-
-    for (j = 0; j < rows; j++) {
-	for (i = 0; i < cols; i++) {
-	    if (N_get_array_2d_d_value(data->status, i, j) ==
-		N_CELL_TRANSMISSION) {
-		count = 0;
-		/*get the gradient neighbours */
-		N_get_gradient_2d(data->grad, &grad, i, j);
-		c = 0;
-		/*
-		   c = N_get_array_2d_d_value(data->c_start, i, j);
-		   if(c > 0)
-		   count++;
-		 */
-
-		if (grad.WC > 0 &&
-		    !N_is_array_2d_value_null(data->c, i - 1, j)) {
-		    c += N_get_array_2d_d_value(data->c, i - 1, j);
-		    count++;
-		}
-		if (grad.EC < 0 &&
-		    !N_is_array_2d_value_null(data->c, i + 1, j)) {
-		    c += N_get_array_2d_d_value(data->c, i + 1, j);
-		    count++;
-		}
-		if (grad.NC < 0 &&
-		    !N_is_array_2d_value_null(data->c, i, j - 1)) {
-		    c += N_get_array_2d_d_value(data->c, i, j - 1);
-		    count++;
-		}
-		if (grad.SC > 0 &&
-		    !N_is_array_2d_value_null(data->c, i, j + 1)) {
-		    c += N_get_array_2d_d_value(data->c, i, j + 1);
-		    count++;
-		}
-		if (count != 0)
-		    c = c / (double)count;
-		/*make sure it is not NAN */
-		if (c > 0 || c == 0 || c < 0)
-		    N_put_array_2d_d_value(data->c_start, i, j, c);
-	    }
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief Compute the dispersivity tensor based on the solute transport data in 2d
- *
- * The dispersivity tensor is stored in the data structure.
- * To compute the dispersivity tensor, the dispersivity lentghs and the gradient field
- * must be present.
- *
- * This is just a simple tensor computation which should be extended.
- *
- * \todo Change the tensor calculation to a mor realistic algorithm 
- *
- * \param data N_solute_transport_data2d *
- * \return void *
- * */
-void N_calc_solute_transport_disptensor_2d(N_solute_transport_data2d * data)
-{
-    int i, j;
-    int cols, rows;
-    double vx, vy, vv;
-    double disp_xx, disp_yy, disp_xy;
-    N_gradient_2d grad;
-
-    cols = data->grad->cols;
-    rows = data->grad->rows;
-
-    G_debug(2,
-	    "N_calc_solute_transport_disptensor_2d: calculating the dispersivity tensor");
-
-    for (j = 0; j < rows; j++) {
-	for (i = 0; i < cols; i++) {
-
-	    disp_xx = 0;
-	    disp_yy = 0;
-	    disp_xy = 0;
-
-	    /*get the gradient neighbours */
-	    N_get_gradient_2d(data->grad, &grad, i, j);
-	    vx = (grad.WC + grad.EC) / 2;
-	    vy = (grad.NC + grad.SC) / 2;
-	    vv = sqrt(vx * vx + vy * vy);
-
-	    if (vv != 0) {
-		disp_xx = data->al * vx * vx / vv + data->at * vy * vy / vv;
-		disp_yy = data->at * vx * vx / vv + data->al * vy * vy / vv;
-		disp_xy = (data->al - data->at) * vx * vy / vv;
-	    }
-
-	    G_debug(5,
-		    "N_calc_solute_transport_disptensor_2d: [%i][%i] disp_xx %g disp_yy %g disp_xy %g",
-		    i, j, disp_xx, disp_yy, disp_xy);
-	    N_put_array_2d_d_value(data->disp_xx, i, j, disp_xx);
-	    N_put_array_2d_d_value(data->disp_yy, i, j, disp_yy);
-	    N_put_array_2d_d_value(data->disp_xy, i, j, disp_xy);
-	}
-    }
-
-    return;
-}
-
-/*!
- * \brief Compute the dispersivity tensor based on the solute transport data in 3d
- *
- * The dispersivity tensor is stored in the data structure.
- * To compute the dispersivity tensor, the dispersivity lentghs and the gradient field
- * must be present.
- * 
- * This is just a simple tensor computation which should be extended.
- *
- * \todo Change the tensor calculation to a mor realistic algorithm 
- *
- * \param data N_solute_transport_data3d *
- * \return void *
- * */
-void N_calc_solute_transport_disptensor_3d(N_solute_transport_data3d * data)
-{
-    int i, j, k;
-    int cols, rows, depths;
-    double vx, vy, vz, vv;
-    double disp_xx, disp_yy, disp_zz, disp_xy, disp_xz, disp_yz;
-    N_gradient_3d grad;
-
-    cols = data->grad->cols;
-    rows = data->grad->rows;
-    depths = data->grad->depths;
-
-    G_debug(2,
-	    "N_calc_solute_transport_disptensor_3d: calculating the dispersivity tensor");
-
-    for (k = 0; k < depths; k++) {
-	for (j = 0; j < rows; j++) {
-	    for (i = 0; i < cols; i++) {
-		disp_xx = 0;
-		disp_yy = 0;
-		disp_zz = 0;
-		disp_xy = 0;
-		disp_xz = 0;
-		disp_yz = 0;
-
-		/*get the gradient neighbours */
-		N_get_gradient_3d(data->grad, &grad, i, j, k);
-		vx = (grad.WC + grad.EC) / 2;
-		vy = (grad.NC + grad.SC) / 2;
-		vz = (grad.BC + grad.TC) / 2;
-		vv = sqrt(vx * vx + vy * vy + vz * vz);
-
-		if (vv != 0) {
-		    disp_xx =
-			data->al * vx * vx / vv + data->at * vy * vy / vv +
-			data->at * vz * vz / vv;
-		    disp_yy =
-			data->at * vx * vx / vv + data->al * vy * vy / vv +
-			data->at * vz * vz / vv;
-		    disp_zz =
-			data->at * vx * vx / vv + data->at * vy * vy / vv +
-			data->al * vz * vz / vv;
-		    disp_xy = (data->al - data->at) * vx * vy / vv;
-		    disp_xz = (data->al - data->at) * vx * vz / vv;
-		    disp_yz = (data->al - data->at) * vy * vz / vv;
-		}
-
-		G_debug(5,
-			"N_calc_solute_transport_disptensor_3d: [%i][%i][%i] disp_xx %g disp_yy %g disp_zz %g  disp_xy %g disp_xz %g disp_yz %g ",
-			i, j, k, disp_xx, disp_yy, disp_zz, disp_xy, disp_xz,
-			disp_yz);
-		N_put_array_3d_d_value(data->disp_xx, i, j, k, disp_xx);
-		N_put_array_3d_d_value(data->disp_yy, i, j, k, disp_yy);
-		N_put_array_3d_d_value(data->disp_zz, i, j, k, disp_zz);
-		N_put_array_3d_d_value(data->disp_xy, i, j, k, disp_xy);
-		N_put_array_3d_d_value(data->disp_xz, i, j, k, disp_xz);
-		N_put_array_3d_d_value(data->disp_yz, i, j, k, disp_yz);
-	    }
-	}
-    }
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_tools.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_tools.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_tools.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,200 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:     	Array managment functions 
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-#include <grass/glocale.h>
-
-
-/*!
- * \brief Calculate the arithmetic mean of values a and b
- *
- * mean = (a+b)/2
- *
- * \param a double
- * \param b double
- * \return val double
- * */
-double N_calc_arith_mean(double a, double b)
-{
-    double val = 0;
-
-    val = (a + b) / 2.0;
-
-    return val;
-}
-
-/*!
- * \brief Calculate the arithmetic mean of the values in vector a
- * of size n
- *
- * n = [0 ... size[
- * mean =  (a[0] + a[1] + ... + a[n])/size
- *
- * \param a double * -- the value vector 
- * \param size int -- the size of the vector a
- * \return val double
- * */
-double N_calc_arith_mean_n(double *a, int size)
-{
-    double val = 0.0;
-    int i;
-
-    for (i = 0; i < size; i++)
-	val += a[i];
-
-    val = (val / (double)size);
-
-    return val;
-}
-
-
-/*!
- * \brief Calculate the geometrical mean of values a and b
- *
- * mean = sqrt(a*b)
- *
- * \param a double
- * \param b double
- * \return val double
- * */
-double N_calc_geom_mean(double a, double b)
-{
-    double val = 0;
-
-    val = sqrt(a * b);
-
-    return val;
-}
-
-/*!
- * \brief Calculate the geometrical mean of the values in vector a
- * of size n
- *
- * n = [0 ... size[
- * mean =  pow((a[0] * a[1] * ... * a[n]), 1.0/size)
- *
- * \param a double * -- the value vector 
- * \param size int -- the size of the vector a
- * \return val double
- * */
-double N_calc_geom_mean_n(double *a, int size)
-{
-    double val = 1;
-    int i;
-
-    for (i = 0; i < size; i++)
-	val *= a[i];
-
-    val = (double)pow((long double)val, (long double)1.0 / (long double)size);
-
-    return val;
-}
-
-
-/*!
- * \brief Calculate the harmonical mean of values a and b
- *
- * mean = 2*(a*b)/(a + b)
- *
- * \param a double
- * \param b double
- * \return val double -- if (a + b) == 0, a 0 is returned
- * */
-double N_calc_harmonic_mean(double a, double b)
-{
-    double val = 0.0;
-
-    if ((a + b) != 0)
-	val = 2.0 * (a * b) / (a + b);
-
-    return val;
-}
-
-/*!
- * \brief Calculate the harmonical mean of the values in vector a
- * of size n
- *
- * n = [0 ... size[
- * mean = 1/(1/size *(1/a[0] + 1/a[1] + ... + 1/a[n]))
- * 
- * \param a double * -- the value vector 
- * \param size int -- the size of the vector a
- * \return val double -- if one division with 0 is detected, 0 will be returned
- * */
-double N_calc_harmonic_mean_n(double *a, int size)
-{
-    double val = 0;
-    int i;
-
-    for (i = 0; i < size; i++)
-	if (a[i] != 0.0)
-	    val += 1.0 / a[i];
-	else
-	    return 0.0;
-
-    if (val == 0.0)
-	return 0.0;
-    else
-	val = 1.0 / (1.0 / (double)size * val);
-
-    return val;
-}
-
-
-/*!
- * \brief Calculate the quadratic mean of values a and b
- *
- * mean = sqrt((a*a + b*b)/2)
- *
- * \param a double
- * \param b double
- * \return val double 
- * */
-double N_calc_quad_mean(double a, double b)
-{
-    double val = 0.0;
-
-    val = sqrt((a * a + b * b) / 2.0);
-
-    return val;
-}
-
-/*!
- * \brief Calculate the quadratic mean of the values in vector a
- * of size n
- *
- * n = [0 ... size[
- * mean = sqrt((a[0]*a[0] + a[1]*a[1] + ... + a[n]*a[n])/size)
- * 
- * \param a double * -- the value vector 
- * \param size int -- the size of the vector a
- * \return val double 
- * */
-double N_calc_quad_mean_n(double *a, int size)
-{
-    double val = 0;
-    int i;
-
-    for (i = 0; i < size; i++)
-	val += a[i] * a[i];
-
-    val = sqrt(val / (double)size);
-
-    return val;
-}

Deleted: grass/branches/releasebranch_7_0/lib/gpde/N_upwind.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/N_upwind.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/gpde/N_upwind.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,77 +0,0 @@
-
-/*****************************************************************************
-*
-* MODULE:       Grass PDE Numerical Library
-* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
-* 		soerengebbert <at> gmx <dot> de
-*               
-* PURPOSE:      upwinding stabilization algorithms
-* 		part of the gpde library
-*
-* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
-
-
-/*! \brief full upwinding stabilization algorithm
- *
- * The arguments are values to compute the local peclet number
- *
- * \param sprod double -- the scalar produkt between the velocity vector and the normal vector between two points
- * \param distance double -- distance between two points
- * \param D double -- diffusion/dispersion tensor part between two points
- *
- * \return the weighting factor
- * */
-double N_full_upwinding(double sprod, double distance, double D)
-{
-    double z;
-
-    if (D == 0)
-	return 0.5;
-
-    /*compute the local peclet number */
-    z = sprod * distance / D;
-
-    if (z > 0)
-	return 1;
-    if (z == 0)
-	return 0.5;
-    if (z < 0)
-	return 0;
-
-    return 0;
-}
-
-/*! \brief exponential upwinding stabilization algorithm
- *
- * The arguments are values to compute the local peclet number
- *
- * \param sprod double -- the scalar produkt between the velocity vector and the normal vector between two points
- * \param distance double -- distance between two points
- * \param D double -- diffusion/dispersion tensor part between two points
- *
- * \return the weighting factor
- * */
-double N_exp_upwinding(double sprod, double distance, double D)
-{
-    double z;
-
-    if (D == 0)
-	return 0.5;
-
-    /*compute the local peclet number */
-    z = sprod * distance / D;
-
-    if (z != 0)
-	return (1 - (1 / z) * (1 - (z / (exp(z) - 1))));
-
-    return 0.5;
-}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_arrays.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_arrays.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_arrays.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_arrays.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,1244 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*
+* PURPOSE:     	Array managment functions
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+
+/* ******************** 2D ARRAY FUNCTIONS *********************** */
+
+/*!
+ * \brief Allocate memory for a N_array_2d data structure.
+ *
+ * This function allocates memory for an array of type N_array_2d
+ * and returns the pointer to the new allocated memory.
+ * <br><br>
+ * The data type of this array is set by "type" and must be
+ * CELL_TYPE, FCELL_TYPE or DCELL_TYPE accordingly to the raster map data types.
+ * The offset sets the number of boundary cols and rows.
+ * This option is useful to generate homogeneous Neumann boundary conditions around
+ * an array or to establish overlapping boundaries. The array is initialized with 0 by default.
+ * <br><br>
+ * If the offset is greater then 0, negative indices are possible.
+ * <br><br>
+ *
+ * The data structure of a array with 3 rows and cols and an offset of 1
+ * will looks like this:
+ * <br><br>
+ *
+ \verbatim
+ 0 0 0 0 0
+ 0 0 1 2 0
+ 0 3 4 5 0
+ 0 6 7 8 0
+ 0 0 0 0 0
+ \endverbatim
+ *
+ * 0 is the boundary.
+ * <br><br>
+ * Internal a one dimensional array is allocated to save memory and to speed up the memory access.
+ * To access the one dimensional array with a two dimensional index use the provided
+ * get and put functions. The internal representation of the above data will look like this:
+ *
+ \verbatim
+ 0 0 0 0 0 0 0 1 2 0 0 3 4 5 0 0 6 7 8 0 0 0 0 0 0
+ \endverbatim
+ *
+ * \param cols int
+ * \param rows int
+ * \param offset int
+ * \param type int
+ * \return N_array_2d *
+ *
+ * */
+N_array_2d *N_alloc_array_2d(int cols, int rows, int offset, int type)
+{
+    N_array_2d *data = NULL;
+
+    if (rows < 1 || cols < 1)
+	G_fatal_error("N_alloc_array_2d: cols and rows should be > 0");
+
+    if (type != CELL_TYPE && type != FCELL_TYPE && type != DCELL_TYPE)
+	G_fatal_error
+	    ("N_alloc_array_2d: Wrong data type, should be CELL_TYPE, FCELL_TYPE or DCELL_TYPE");
+
+    data = (N_array_2d *) G_calloc(1, sizeof(N_array_2d));
+
+    data->cols = cols;
+    data->rows = rows;
+    data->type = type;
+    data->offset = offset;
+    data->rows_intern = rows + 2 * offset;	/*offset position at booth sides */
+    data->cols_intern = cols + 2 * offset;	/*offset position at booth sides */
+    data->cell_array = NULL;
+    data->fcell_array = NULL;
+    data->dcell_array = NULL;
+
+    if (data->type == CELL_TYPE) {
+	data->cell_array =
+	    (CELL *) G_calloc((size_t) data->rows_intern * data->cols_intern,
+			      sizeof(CELL));
+	G_debug(3,
+		"N_alloc_array_2d: CELL array allocated rows_intern %i cols_intern %i offset %i",
+		data->rows_intern, data->cols_intern, data->offset = offset);
+    }
+    else if (data->type == FCELL_TYPE) {
+	data->fcell_array =
+	    (FCELL *) G_calloc((size_t) data->rows_intern * data->cols_intern,
+			       sizeof(FCELL));
+	G_debug(3,
+		"N_alloc_array_2d: FCELL array allocated rows_intern %i cols_intern %i offset %i",
+		data->rows_intern, data->cols_intern, data->offset = offset);
+
+    }
+    else if (data->type == DCELL_TYPE) {
+	data->dcell_array =
+	    (DCELL *) G_calloc((size_t) data->rows_intern * data->cols_intern,
+			       sizeof(DCELL));
+	G_debug(3,
+		"N_alloc_array_2d: DCELL array allocated rows_intern %i cols_intern %i offset %i",
+		data->rows_intern, data->cols_intern, data->offset = offset);
+    }
+
+    return data;
+}
+
+/*!
+ * \brief Release the memory of a N_array_2d structure
+ *
+ * \param data N_array_2d *
+ * \return void
+ * */
+void N_free_array_2d(N_array_2d * data)
+{
+
+    if (data != NULL) {
+	G_debug(3, "N_free_array_2d: free N_array_2d");
+
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    G_free(data->cell_array);
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    G_free(data->fcell_array);
+
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    G_free(data->dcell_array);
+	}
+
+	G_free(data);
+	data = NULL;
+
+    }
+
+    return;
+}
+
+
+/*!
+ * \brief Return the data type of the N_array_2d struct
+ *
+ * The data type can be CELL_TYPE, FCELL_TYPE or DCELL_TYPE accordingly to the raster map data types.
+ *
+ * \param array N_array_2d *
+ * \return type int
+ * */
+int N_get_array_2d_type(N_array_2d * array)
+{
+    return array->type;
+}
+
+/*!
+ * \brief Write the value of the N_array_2d struct at position col, row to value
+ *
+ * The value must be of the same type as the array. Otherwise you will risk data losses.
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \param value void * - this variable contains the array value at col, row position
+ * \return void
+ * */
+
+void N_get_array_2d_value(N_array_2d * data, int col, int row, void *value)
+{
+
+    if (data->offset == 0) {
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    *((CELL *) value) =
+		data->cell_array[row * data->cols_intern + col];
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    *((FCELL *) value) =
+		data->fcell_array[row * data->cols_intern + col];
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    *((DCELL *) value) =
+		data->dcell_array[row * data->cols_intern + col];
+	}
+    }
+    else {
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    *((CELL *) value) =
+		data->cell_array[(row + data->offset) * data->cols_intern +
+				 col + data->offset];
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    *((FCELL *) value) =
+		data->fcell_array[(row + data->offset) * data->cols_intern +
+				  col + data->offset];
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    *((DCELL *) value) =
+		data->dcell_array[(row + data->offset) * data->cols_intern +
+				  col + data->offset];
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief Returns 1 if the value of N_array_2d struct at postion col, row
+ * is of type null, otherwise 0
+ *
+ * This function checks automatically the type of the array and checks for the
+ * data type null value.
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \return int - 1 = is null, 0 otherwise
+ * */
+int N_is_array_2d_value_null(N_array_2d * data, int col, int row)
+{
+
+    if (data->offset == 0) {
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_2d_value_null: null value is of type CELL at pos [%i][%i]",
+		    col, row);
+	    return Rast_is_null_value((void *)
+				   &(data->
+				     cell_array[row * data->cols_intern +
+						col]), CELL_TYPE);
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_2d_value_null: null value is of type FCELL at pos [%i][%i]",
+		    col, row);
+	    return Rast_is_null_value((void *)
+				   &(data->
+				     fcell_array[row * data->cols_intern +
+						 col]), FCELL_TYPE);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_2d_value_null: null value is of type DCELL at pos [%i][%i]",
+		    col, row);
+	    return Rast_is_null_value((void *)
+				   &(data->
+				     dcell_array[row * data->cols_intern +
+						 col]), DCELL_TYPE);
+	}
+    }
+    else {
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_2d_value_null: null value is of type CELL at pos [%i][%i]",
+		    col, row);
+	    return Rast_is_null_value((void *)
+				   &(data->
+				     cell_array[(row +
+						 data->offset) *
+						data->cols_intern + col +
+						data->offset]), CELL_TYPE);
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_2d_value_null: null value is of type FCELL at pos [%i][%i]",
+		    col, row);
+	    return Rast_is_null_value((void *)
+				   &(data->
+				     fcell_array[(row +
+						  data->offset) *
+						 data->cols_intern + col +
+						 data->offset]), FCELL_TYPE);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_2d_value_null: null value is of type DCELL at pos [%i][%i]",
+		    col, row);
+	    return Rast_is_null_value((void *)
+				   &(data->
+				     dcell_array[(row +
+						  data->offset) *
+						 data->cols_intern + col +
+						 data->offset]), DCELL_TYPE);
+	}
+    }
+
+    return 0;
+}
+
+
+/*!
+ * \brief Returns the value of type CELL at position col, row
+ *
+ * The data array can be of type CELL, FCELL or DCELL, the value will be casted to the CELL type.
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \return CELL
+ *
+ * */
+CELL N_get_array_2d_c_value(N_array_2d * data, int col, int row)
+{
+    CELL value = 0;
+    FCELL fvalue = 0.0;
+    DCELL dvalue = 0.0;
+
+    switch (data->type) {
+    case CELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&value);
+	return (CELL) value;
+    case FCELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&fvalue);
+	return (CELL) fvalue;
+    case DCELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&dvalue);
+	return (CELL) dvalue;
+    }
+
+    return value;
+}
+
+/*!
+ * \brief Returns the value of type FCELL at position col, row
+ *
+ * The data array can be of type CELL, FCELL or DCELL, the value will be casted to the FCELL type.
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \return FCELL
+
+ * */
+FCELL N_get_array_2d_f_value(N_array_2d * data, int col, int row)
+{
+    CELL value = 0;
+    FCELL fvalue = 0.0;
+    DCELL dvalue = 0.0;
+
+    switch (data->type) {
+    case CELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&value);
+	return (FCELL) value;
+    case FCELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&fvalue);
+	return (FCELL) fvalue;
+    case DCELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&dvalue);
+	return (FCELL) dvalue;
+    }
+
+    return fvalue;
+}
+
+/*!
+ * \brief Returns the value of type DCELL at position col, row
+ *
+ * The data array can be of type CELL, FCELL or DCELL, the value will be casted to the DCELL type.
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \return DCELL
+ *
+ * */
+DCELL N_get_array_2d_d_value(N_array_2d * data, int col, int row)
+{
+    CELL value = 0;
+    FCELL fvalue = 0.0;
+    DCELL dvalue = 0.0;
+
+    switch (data->type) {
+    case CELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&value);
+	return (DCELL) value;
+    case FCELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&fvalue);
+	return (DCELL) fvalue;
+    case DCELL_TYPE:
+	N_get_array_2d_value(data, col, row, (void *)&dvalue);
+	return (DCELL) dvalue;
+    }
+
+    return dvalue;
+
+}
+
+/*!
+ * \brief Writes a value to the N_array_2d struct at position col, row
+ *
+ * The value will be automatically cast to the array type.
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \param value char *
+ * \return void
+ * */
+void N_put_array_2d_value(N_array_2d * data, int col, int row, char *value)
+{
+
+    G_debug(6, "N_put_array_2d_value: put value to array");
+
+    if (data->offset == 0) {
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    data->cell_array[row * data->cols_intern + col] =
+		*((CELL *) value);
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    data->fcell_array[row * data->cols_intern + col] =
+		*((FCELL *) value);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    data->dcell_array[row * data->cols_intern + col] =
+		*((DCELL *) value);
+	}
+    }
+    else {
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    data->cell_array[(row + data->offset) * data->cols_intern + col +
+			     data->offset] = *((CELL *) value);
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    data->fcell_array[(row + data->offset) * data->cols_intern + col +
+			      data->offset] = *((FCELL *) value);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    data->dcell_array[(row + data->offset) * data->cols_intern + col +
+			      data->offset] = *((DCELL *) value);
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief Writes the null value to the N_array_2d struct at position col, row
+ *
+ * The null value will be automatically set to the array data type (CELL, FCELL or DCELL).
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \return void
+ * */
+void N_put_array_2d_value_null(N_array_2d * data, int col, int row)
+{
+
+    G_debug(6,
+	    "N_put_array_2d_value_null: put null value to array pos [%i][%i]",
+	    col, row);
+
+    if (data->offset == 0) {
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    Rast_set_c_null_value((void *)
+			       &(data->
+				 cell_array[row * data->cols_intern + col]),
+			       1);
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    Rast_set_f_null_value((void *)
+			       &(data->
+				 fcell_array[row * data->cols_intern + col]),
+			       1);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    Rast_set_d_null_value((void *)
+			       &(data->
+				 dcell_array[row * data->cols_intern + col]),
+			       1);
+	}
+    }
+    else {
+	if (data->type == CELL_TYPE && data->cell_array != NULL) {
+	    Rast_set_c_null_value((void *)
+			       &(data->
+				 cell_array[(row +
+					     data->offset) *
+					    data->cols_intern + col +
+					    data->offset]), 1);
+	}
+	else if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    Rast_set_f_null_value((void *)
+			       &(data->
+				 fcell_array[(row +
+					      data->offset) *
+					     data->cols_intern + col +
+					     data->offset]), 1);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    Rast_set_d_null_value((void *)
+			       &(data->
+				 dcell_array[(row +
+					      data->offset) *
+					     data->cols_intern + col +
+					     data->offset]), 1);
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief Writes a CELL value to the N_array_2d struct at position col, row
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \param value CELL
+ * \return void
+ * */
+void N_put_array_2d_c_value(N_array_2d * data, int col, int row, CELL value)
+{
+    FCELL fvalue;
+    DCELL dvalue;
+
+    switch (data->type) {
+    case FCELL_TYPE:
+	fvalue = (FCELL) value;
+	N_put_array_2d_value(data, col, row, (char *)&fvalue);
+	return;
+    case DCELL_TYPE:
+	dvalue = (DCELL) value;
+	N_put_array_2d_value(data, col, row, (char *)&dvalue);
+	return;
+    }
+
+    N_put_array_2d_value(data, col, row, (char *)&value);
+
+    return;
+}
+
+/*!
+ * \brief Writes a FCELL value to the N_array_2d struct at position col, row
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \param value FCELL
+ * \return void
+ * */
+void N_put_array_2d_f_value(N_array_2d * data, int col, int row, FCELL value)
+{
+    CELL cvalue;
+    DCELL dvalue;
+
+    switch (data->type) {
+    case CELL_TYPE:
+	cvalue = (CELL) value;
+	N_put_array_2d_value(data, col, row, (char *)&cvalue);
+	return;
+    case DCELL_TYPE:
+	dvalue = (DCELL) value;
+	N_put_array_2d_value(data, col, row, (char *)&dvalue);
+	return;
+    }
+
+    N_put_array_2d_value(data, col, row, (char *)&value);
+
+    return;
+}
+
+/*!
+ * \brief Writes a DCELL value to the N_array_2d struct at position col, row
+ *
+ * \param data N_array_2d *
+ * \param col int
+ * \param row int
+ * \param value DCELL
+ * \return void
+ * */
+void N_put_array_2d_d_value(N_array_2d * data, int col, int row, DCELL value)
+{
+    CELL cvalue;
+    FCELL fvalue;
+
+    switch (data->type) {
+    case CELL_TYPE:
+	cvalue = (CELL) value;
+	N_put_array_2d_value(data, col, row, (char *)&cvalue);
+	return;
+    case FCELL_TYPE:
+	fvalue = (FCELL) value;
+	N_put_array_2d_value(data, col, row, (char *)&fvalue);
+	return;
+    }
+
+    N_put_array_2d_value(data, col, row, (char *)&value);
+
+    return;
+}
+
+/*!
+ * \brief This function writes the data info of the array data to stdout
+ *
+ * \param data N_array_2d *
+ * \return void
+ * */
+void N_print_array_2d_info(N_array_2d * data)
+{
+
+    fprintf(stdout, "N_array_2d \n");
+    fprintf(stdout, "Cols %i\n", data->cols);
+    fprintf(stdout, "Rows: %i\n", data->rows);
+    fprintf(stdout, "Array type: %i\n", data->type);
+    fprintf(stdout, "Offset: %i\n", data->offset);
+    fprintf(stdout, "Internal cols: %i\n", data->cols_intern);
+    fprintf(stdout, "Internal rows: %i\n", data->rows_intern);
+    fprintf(stdout, "CELL array pointer: %p\n", data->cell_array);
+    fprintf(stdout, "FCELL array pointer: %p\n", data->fcell_array);
+    fprintf(stdout, "DCELL array pointer: %p\n", data->dcell_array);
+
+
+    return;
+}
+
+/*!
+ * \brief Write info and content of the N_array_2d struct to stdout
+ *
+ * Offsets are ignored
+ *
+ * \param data N_array_2d *
+ * \return void
+ * */
+void N_print_array_2d(N_array_2d * data)
+{
+    int i, j;
+
+    N_print_array_2d_info(data);
+
+    for (j = 0 - data->offset; j < data->rows + data->offset; j++) {
+	for (i = 0 - data->offset; i < data->cols + data->offset; i++) {
+	    if (data->type == CELL_TYPE)
+		fprintf(stdout, "%6d ", N_get_array_2d_c_value(data, i, j));
+	    else if (data->type == FCELL_TYPE)
+		fprintf(stdout, "%6.6f ", N_get_array_2d_f_value(data, i, j));
+	    else if (data->type == DCELL_TYPE)
+		printf("%6.6f ", N_get_array_2d_d_value(data, i, j));
+	}
+	fprintf(stdout, "\n");
+    }
+    fprintf(stdout, "\n");
+
+    return;
+}
+
+
+/* ******************** 3D ARRAY FUNCTIONS *********************** */
+
+/*!
+ * \brief Allocate memory for a N_array_3d data structure.
+ *
+ * This functions allocates an array of type N_array_3d and returns a pointer
+ * to the new allocated memory.
+ * <br><br>
+ * The data type of this array set by "type" must be
+ * FCELL_TYPE or DCELL_TYPE accordingly to the raster3d map data types.
+ * The offsets sets the number of boundary cols, rows and depths.
+ * This option is useful to generate homogeneous Neumann boundary conditions around
+ * an array or to establish overlapping boundaries. The arrays are initialized with 0 by default.
+ * <br><br>
+ * If the offset is greater then 0, negative indices are possible.
+ * The data structure of a array with 3 depths, rows and cols and an offset of 1
+ * will looks like this:
+ *
+ \verbatim
+ 0  0  0  0  0
+ 0  0  0  0  0
+ 0  0  0  0  0
+ 0  0  0  0  0
+ 0  0  0  0  0
+
+ 0  0  0  0  0
+ 0  0  1  2  0
+ 0  3  4  5  0
+ 0  6  7  8  0
+ 0  0  0  0  0
+
+ 0  0  0  0  0
+ 0  9 10 11  0
+ 0 12 13 14  0
+ 0 15 16 17  0
+ 0  0  0  0  0
+
+ 0  0  0  0  0
+ 0 18 19 20  0
+ 0 21 22 23  0
+ 0 24 25 26  0
+ 0  0  0  0  0
+
+ 0  0  0  0  0
+ 0  0  0  0  0
+ 0  0  0  0  0
+ 0  0  0  0  0
+ 0  0  0  0  0
+
+ \endverbatim
+
+ The depth counts from the bottom to the top.
+
+ * <br><br>
+ * Internal a one dimensional array is allocated to speed up the memory access.
+ * To access the dimensional array with a three dimensional indexing use the provided
+ * get and put functions.
+ *
+ * \param cols int
+ * \param rows int
+ * \param depths int
+ * \param offset int
+ * \param type int
+ * \return N_array_3d *
+ *
+ * */
+N_array_3d *N_alloc_array_3d(int cols, int rows, int depths, int offset,
+			     int type)
+{
+    N_array_3d *data = NULL;
+
+    if (rows < 1 || cols < 1 || depths < 1)
+	G_fatal_error
+	    ("N_alloc_array_3d: depths, cols and rows should be > 0");
+
+    if (type != DCELL_TYPE && type != FCELL_TYPE)
+	G_fatal_error
+	    ("N_alloc_array_3d: Wrong data type, should be FCELL_TYPE or DCELL_TYPE");
+
+    data = (N_array_3d *) G_calloc(1, sizeof(N_array_3d));
+
+    data->cols = cols;
+    data->rows = rows;
+    data->depths = depths;
+    data->type = type;
+    data->offset = offset;
+    data->rows_intern = rows + 2 * offset;
+    data->cols_intern = cols + 2 * offset;
+    data->depths_intern = depths + 2 * offset;
+    data->fcell_array = NULL;
+    data->dcell_array = NULL;
+
+    if (data->type == FCELL_TYPE) {
+	data->fcell_array =
+	    (float *)G_calloc((size_t) data->depths_intern * data->rows_intern *
+			      data->cols_intern, sizeof(float));
+	G_debug(3,
+		"N_alloc_array_3d: float array allocated rows_intern %i cols_intern %i depths_intern %i offset %i",
+		data->rows_intern, data->cols_intern, data->depths_intern,
+		data->offset = offset);
+    }
+    else if (data->type == DCELL_TYPE) {
+	data->dcell_array =
+	    (double *)G_calloc((size_t) data->depths_intern * data->rows_intern *
+			       data->cols_intern, sizeof(double));
+	G_debug(3,
+		"N_alloc_array_3d: double array allocated rows_intern %i cols_intern %i depths_intern %i offset %i",
+		data->rows_intern, data->cols_intern, data->depths_intern,
+		data->offset = offset);
+    }
+
+    return data;
+}
+
+/*!
+ * \brief Release the memory of a N_array_3d
+ *
+ * \param data N_array_3d *
+ * \return void
+ * */
+void N_free_array_3d(N_array_3d * data)
+{
+
+    if (data != NULL) {
+	G_debug(3, "N_free_array_3d: free N_array_3d");
+
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    G_free(data->fcell_array);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    G_free(data->dcell_array);
+	}
+
+	G_free(data);
+	data = NULL;
+
+    }
+
+    return;
+}
+
+/*!
+ * \brief Return the data type of the N_array_3d
+ *
+ * The data type can be FCELL_TYPE and DCELL_TYPE accordingly to the raster map data types.
+ *
+ * \param array N_array_3d *
+ * \return type int -- FCELL_TYPE or DCELL_TYPE
+ * */
+int N_get_array_3d_type(N_array_3d * array)
+{
+    return array->type;
+}
+
+
+/*!
+ * \brief This function writes the value of N_array_3d data at position col, row, depth
+ *        to the variable value
+ *
+ * The value must be from the same type as the array. Otherwise you will risk data losses.
+ *
+ * \param data N_array_3d *
+ * \param col int
+ * \param row int
+ * \param depth int
+ * \param value void *
+ * \return void
+ * */
+void
+N_get_array_3d_value(N_array_3d * data, int col, int row, int depth,
+		     void *value)
+{
+
+    if (data->offset == 0) {
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    *((float *)value) =
+		data->fcell_array[depth *
+				  (data->rows_intern * data->cols_intern) +
+				  row * data->cols_intern + col];
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    *((double *)value) =
+		data->dcell_array[depth *
+				  (data->rows_intern * data->cols_intern) +
+				  row * data->cols_intern + col];
+	}
+    }
+    else {
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    *((float *)value) =
+		data->fcell_array[(depth + data->offset) *
+				  (data->rows_intern * data->cols_intern) +
+				  (row + data->offset) * data->cols_intern +
+				  (col + data->offset)];
+
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    *((double *)value) =
+		data->dcell_array[(depth + data->offset) *
+				  (data->rows_intern * data->cols_intern) +
+				  (row + data->offset) * data->cols_intern +
+				  (col + data->offset)];
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief This function returns 1 if value of N_array_3d data at position col, row, depth
+ * is of type null, otherwise 0
+ *
+ * This function checks automatically the type of the array and checks for the
+ * data type null value.
+ *
+ * \param data N_array_3d *
+ * \param col int
+ * \param row int
+ * \param depth int
+ * \return void
+ * */
+int N_is_array_3d_value_null(N_array_3d * data, int col, int row, int depth)
+{
+
+    if (data->offset == 0) {
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_3d_value_null: null value is of type DCELL_TYPE at pos [%i][%i][%i]",
+		    depth, row, col);
+	    return Rast3d_is_null_value_num((void *)
+				      &(data->
+					fcell_array[depth *
+						    (data->rows_intern *
+						     data->cols_intern) +
+						    row * data->cols_intern +
+						    col]), FCELL_TYPE);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_3d_value_null: null value is of type DCELL_TYPE at pos [%i][%i][%i]",
+		    depth, row, col);
+	    return Rast3d_is_null_value_num((void *)
+				      &(data->
+					dcell_array[depth *
+						    (data->rows_intern *
+						     data->cols_intern) +
+						    row * data->cols_intern +
+						    col]), DCELL_TYPE);
+	}
+    }
+    else {
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_3d_value_null: null value is of type DCELL_TYPE at pos [%i][%i][%i]",
+		    depth, row, col);
+	    return Rast3d_is_null_value_num((void *)
+				      &(data->
+					fcell_array[(depth +
+						     data->offset) *
+						    (data->rows_intern *
+						     data->cols_intern) +
+						    (row + data->offset)
+						    * data->cols_intern +
+						    (col + data->offset)]),
+				      FCELL_TYPE);
+
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    G_debug(6,
+		    "N_is_array_3d_value_null: null value is of type DCELL_TYPE at pos [%i][%i][%i]",
+		    depth, row, col);
+	    return Rast3d_is_null_value_num((void *)
+				      &(data->
+					dcell_array[(depth +
+						     data->offset) *
+						    (data->rows_intern *
+						     data->cols_intern) +
+						    (row +
+						     data->offset) *
+						    data->cols_intern + (col +
+									 data->
+									 offset)]),
+				      DCELL_TYPE);
+	}
+    }
+
+    return 0;
+}
+
+/*!
+ * \brief This function returns the value of type float at position col, row, depth
+ *
+ * The data type can be FCELL_TYPE or DCELL_TYPE accordingly to the raster map data types.
+ *
+ * \param data N_array_3d *
+ * \param col int
+ * \param row int
+ * \param depth int
+ * \return float
+ *
+ * */
+float N_get_array_3d_f_value(N_array_3d * data, int col, int row, int depth)
+{
+    float fvalue = 0.0;
+    double dvalue = 0.0;
+
+    switch (data->type) {
+    case FCELL_TYPE:
+	N_get_array_3d_value(data, col, row, depth, (void *)&fvalue);
+	return (float)fvalue;
+    case DCELL_TYPE:
+	N_get_array_3d_value(data, col, row, depth, (void *)&dvalue);
+	return (float)dvalue;
+    }
+
+    return fvalue;
+}
+
+/*!
+ * \brief This function returns the value of type float at position col, row, depth
+ *
+ * The data type can be FCELL_TYPE or DCELL_TYPE accordingly to the raster map data types.
+ *
+ * \param data N_array_3d *
+ * \param col int
+ * \param row int
+ * \param depth int
+ * \return double
+ *
+ * */
+double N_get_array_3d_d_value(N_array_3d * data, int col, int row, int depth)
+{
+    float fvalue = 0.0;
+    double dvalue = 0.0;
+
+    switch (data->type) {
+
+    case FCELL_TYPE:
+	N_get_array_3d_value(data, col, row, depth, (void *)&fvalue);
+	return (double)fvalue;
+    case DCELL_TYPE:
+	N_get_array_3d_value(data, col, row, depth, (void *)&dvalue);
+	return (double)dvalue;
+    }
+
+    return dvalue;
+}
+
+/*!
+ * \brief This function writes a value to the N_array_3d data at position col, row, depth
+ *
+ * The value will be automatically cast to the array type.
+ *
+ * \param data N_array_3d *
+ * \param col int
+ * \param row int
+ * \param depth int
+ * \param value cahr *
+ * \return void
+ * */
+void
+N_put_array_3d_value(N_array_3d * data, int col, int row, int depth,
+		     char *value)
+{
+
+    G_debug(6, "N_put_array_3d_value: put value to array at pos [%i][%i][%i]",
+	    depth, row, col);
+
+    if (data->offset == 0) {
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    data->fcell_array[depth *
+			      (data->rows_intern * data->cols_intern) +
+			      row * data->cols_intern + col]
+		= *((float *)value);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+
+	    data->dcell_array[depth *
+			      (data->rows_intern * data->cols_intern) +
+			      row * data->cols_intern + col]
+		= *((double *)value);
+	}
+    }
+    else {
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    data->fcell_array[(depth + data->offset) *
+			      (data->rows_intern * data->cols_intern) + (row +
+									 data->
+									 offset)
+			      * data->cols_intern + (col + data->offset)] =
+		*((float *)value);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    data->dcell_array[(depth + data->offset) *
+			      (data->rows_intern * data->cols_intern) + (row +
+									 data->
+									 offset)
+			      * data->cols_intern + (col + data->offset)] =
+		*((double *)value);
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief This function writes a null value to the N_array_3d data at position col, row, depth
+ *
+ * The null value will be automatically set to the array type.
+ *
+ * \param data N_array_3d *
+ * \param col int
+ * \param row int
+ * \param depth int
+ * \return void
+ * */
+void N_put_array_3d_value_null(N_array_3d * data, int col, int row, int depth)
+{
+
+    G_debug(6,
+	    "N_put_array_3d_value_null: put null value to array at pos [%i][%i][%i]",
+	    depth, row, col);
+
+    if (data->offset == 0) {
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    Rast3d_set_null_value((void *)
+			     &(data->
+			       fcell_array[depth *
+					   (data->rows_intern *
+					    data->cols_intern) +
+					   row * data->cols_intern + col]), 1,
+			     FCELL_TYPE);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    Rast3d_set_null_value((void *)
+			     &(data->
+			       dcell_array[depth *
+					   (data->rows_intern *
+					    data->cols_intern) +
+					   row * data->cols_intern + col]), 1,
+			     DCELL_TYPE);
+	}
+    }
+    else {
+	if (data->type == FCELL_TYPE && data->fcell_array != NULL) {
+	    Rast3d_set_null_value((void *)
+			     &(data->
+			       fcell_array[(depth +
+					    data->offset) *
+					   (data->rows_intern *
+					    data->cols_intern) + (row +
+								  data->
+								  offset) *
+					   data->cols_intern + (col +
+								data->
+								offset)]), 1,
+			     FCELL_TYPE);
+	}
+	else if (data->type == DCELL_TYPE && data->dcell_array != NULL) {
+	    Rast3d_set_null_value((void *)
+			     &(data->
+			       dcell_array[(depth +
+					    data->offset) *
+					   (data->rows_intern *
+					    data->cols_intern) + (row +
+								  data->
+								  offset) *
+					   data->cols_intern + (col +
+								data->
+								offset)]), 1,
+			     DCELL_TYPE);
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief This function writes a float value to the N_array_3d data at position col, row, depth
+ *
+ * \param data N_array_3d *
+ * \param col int
+ * \param row int
+ * \param depth int
+ * \param value float
+ * \return void
+ * */
+void
+N_put_array_3d_f_value(N_array_3d * data, int col, int row, int depth,
+		       float value)
+{
+    double dval;
+
+    if (data->type == DCELL_TYPE) {
+	dval = (double)value;
+	N_put_array_3d_value(data, col, row, depth, (void *)&dval);
+    }
+    else {
+	N_put_array_3d_value(data, col, row, depth, (void *)&value);
+    }
+
+    return;
+}
+
+/*!
+ * \brief Writes a double value to the N_array_3d struct at position col, row, depth
+ *
+ * \param data N_array_3d *
+ * \param col int
+ * \param row int
+ * \param depth int
+ * \param value double
+ * \return void
+ * */
+void
+N_put_array_3d_d_value(N_array_3d * data, int col, int row, int depth,
+		       double value)
+{
+    float fval;
+
+    if (data->type == FCELL_TYPE) {
+	fval = (double)value;
+	N_put_array_3d_value(data, col, row, depth, (void *)&fval);
+    }
+    else {
+	N_put_array_3d_value(data, col, row, depth, (void *)&value);
+    }
+
+    return;
+}
+
+/*!
+ * \brief Write the info of the array to stdout
+ *
+ * \param data N_array_3d *
+ * \return void
+ * */
+void N_print_array_3d_info(N_array_3d * data)
+{
+
+    fprintf(stdout, "N_array_3d \n");
+    fprintf(stdout, "Cols %i\n", data->cols);
+    fprintf(stdout, "Rows: %i\n", data->rows);
+    fprintf(stdout, "Depths: %i\n", data->depths);
+    fprintf(stdout, "Array type: %i\n", data->type);
+    fprintf(stdout, "Offset: %i\n", data->offset);
+    fprintf(stdout, "Internal cols: %i\n", data->cols_intern);
+    fprintf(stdout, "Internal rows: %i\n", data->rows_intern);
+    fprintf(stdout, "Internal depths: %i\n", data->depths_intern);
+    fprintf(stdout, "FCELL array pointer: %p\n", data->fcell_array);
+    fprintf(stdout, "DCELL array pointer: %p\n", data->dcell_array);
+
+    return;
+}
+
+/*!
+ * \brief Write info and content of the array data to stdout
+ *
+ * Offsets are ignored
+ *
+ * \param data N_array_2d *
+ * \return void
+ * */
+void N_print_array_3d(N_array_3d * data)
+{
+    int i, j, k;
+
+    N_print_array_3d_info(data);
+
+    for (k = 0; k < data->depths; k++) {
+	for (j = 0; j < data->rows; j++) {
+	    for (i = 0; i < data->cols; i++) {
+		if (data->type == FCELL_TYPE)
+		    printf("%6.6f ", N_get_array_3d_f_value(data, i, j, k));
+		else if (data->type == DCELL_TYPE)
+		    printf("%6.6f ", N_get_array_3d_d_value(data, i, j, k));
+	    }
+	    printf("\n");
+	}
+	printf("\n");
+    }
+    printf("\n");
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_arrays_calc.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_arrays_calc.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_arrays_calc.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_arrays_calc.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,889 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:     	Higher level array managment functions 
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+
+/* ******************** 2D ARRAY FUNCTIONS *********************** */
+
+/*!
+ * \brief Copy the source N_array_2d struct to the target N_array_2d struct
+ *
+ * The arrays must have the same size and the same offset.
+ *
+ * The array types can be mixed, the values are automatically casted
+ * and the null values are set accordingly.
+ * <br><br>
+ * If you copy a cell array into a dcell array, the values are casted to dcell and 
+ * the null values are converted from cell-null to dcell-null
+ * <br><br>
+ * This function can be called in a parallel region defined with OpenMP.
+ * The copy loop is parallelize with a openmp for pragma.
+ *
+ * \param source N_array_2d *
+ * \param target N_array_2d *
+ * \return void
+ * */
+void N_copy_array_2d(N_array_2d * source, N_array_2d * target)
+{
+    int i;
+    int null = 0;
+
+#pragma omp single
+    {
+	if (source->cols_intern != target->cols_intern)
+	    G_fatal_error
+		("N_copy_array_2d: the arrays are not of equal size");
+
+	if (source->rows_intern != target->rows_intern)
+	    G_fatal_error
+		("N_copy_array_2d: the arrays are not of equal size");
+
+	G_debug(3,
+		"N_copy_array_2d: copy source array to target array size %i",
+		source->cols_intern * source->rows_intern);
+    }
+
+#pragma omp for
+    for (i = 0; i < source->cols_intern * source->rows_intern; i++) {
+	null = 0;
+	if (source->type == CELL_TYPE) {
+	    if (Rast_is_c_null_value((void *)&source->cell_array[i]))
+		null = 1;
+
+	    if (target->type == CELL_TYPE) {
+		target->cell_array[i] = source->cell_array[i];
+	    }
+	    if (target->type == FCELL_TYPE) {
+		if (null)
+		    Rast_set_f_null_value((void *)&(target->fcell_array[i]), 1);
+		else
+		    target->fcell_array[i] = (FCELL) source->cell_array[i];
+	    }
+	    if (target->type == DCELL_TYPE) {
+		if (null)
+		    Rast_set_d_null_value((void *)&(target->dcell_array[i]), 1);
+		else
+		    target->dcell_array[i] = (DCELL) source->cell_array[i];
+	    }
+
+	}
+	if (source->type == FCELL_TYPE) {
+	    if (Rast_is_f_null_value((void *)&source->fcell_array[i]))
+		null = 1;
+
+	    if (target->type == CELL_TYPE) {
+		if (null)
+		    Rast_set_c_null_value((void *)&(target->cell_array[i]), 1);
+		else
+		    target->cell_array[i] = (CELL) source->fcell_array[i];
+	    }
+	    if (target->type == FCELL_TYPE) {
+		target->fcell_array[i] = source->fcell_array[i];
+	    }
+	    if (target->type == DCELL_TYPE) {
+		if (null)
+		    Rast_set_d_null_value((void *)&(target->dcell_array[i]), 1);
+		else
+		    target->dcell_array[i] = (DCELL) source->fcell_array[i];
+	    }
+	}
+	if (source->type == DCELL_TYPE) {
+	    if (Rast_is_d_null_value((void *)&source->dcell_array[i]))
+		null = 1;
+
+	    if (target->type == CELL_TYPE) {
+		if (null)
+		    Rast_set_c_null_value((void *)&(target->cell_array[i]), 1);
+		else
+		    target->cell_array[i] = (CELL) source->dcell_array[i];
+	    }
+	    if (target->type == FCELL_TYPE) {
+		if (null)
+		    Rast_set_f_null_value((void *)&(target->fcell_array[i]), 1);
+		else
+		    target->fcell_array[i] = (FCELL) source->dcell_array[i];
+	    }
+	    if (target->type == DCELL_TYPE) {
+		target->dcell_array[i] = source->dcell_array[i];
+	    }
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief Calculate the norm of the two input arrays
+ *
+ * The norm can be of type N_MAXIMUM_NORM or N_EUKLID_NORM.
+ * All arrays must have equal sizes and offsets.
+ * The complete data array inclusively offsets is used for norm calucaltion.
+ * Only non-null values are used to calcualte the norm.
+ *
+
+ * \param a N_array_2d *
+ * \param b N_array_2d *
+ * \param type the type of the norm -> N_MAXIMUM_NORM, N_EUKLID_NORM
+ * \return double the calculated norm
+ * */
+double N_norm_array_2d(N_array_2d * a, N_array_2d * b, int type)
+{
+    int i = 0;
+    double norm = 0.0, tmp = 0.0;
+    double v1 = 0.0, v2 = 0.0;
+
+    if (a->cols_intern != b->cols_intern)
+	G_fatal_error("N_norm_array_2d: the arrays are not of equal size");
+
+    if (a->rows_intern != b->rows_intern)
+	G_fatal_error("N_norm_array_2d: the arrays are not of equal size");
+
+    G_debug(3, "N_norm_array_2d: norm of a and b size %i",
+	    a->cols_intern * a->rows_intern);
+
+    for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
+	v1 = 0.0;
+	v2 = 0.0;
+
+	if (a->type == CELL_TYPE) {
+	    if (!Rast_is_f_null_value((void *)&(a->cell_array[i])))
+		v1 = (double)a->cell_array[i];
+	}
+	if (a->type == FCELL_TYPE) {
+	    if (!Rast_is_f_null_value((void *)&(a->fcell_array[i])))
+		v1 = (double)a->fcell_array[i];
+	}
+	if (a->type == DCELL_TYPE) {
+	    if (!Rast_is_f_null_value((void *)&(a->dcell_array[i])))
+		v1 = (double)a->dcell_array[i];
+	}
+	if (b->type == CELL_TYPE) {
+	    if (!Rast_is_f_null_value((void *)&(b->cell_array[i])))
+		v2 = (double)b->cell_array[i];
+	}
+	if (b->type == FCELL_TYPE) {
+	    if (!Rast_is_f_null_value((void *)&(b->fcell_array[i])))
+		v2 = (double)b->fcell_array[i];
+	}
+	if (b->type == DCELL_TYPE) {
+	    if (!Rast_is_f_null_value((void *)&(b->dcell_array[i])))
+		v2 = (double)b->dcell_array[i];
+	}
+
+	if (type == N_MAXIMUM_NORM) {
+	    tmp = fabs(v2 - v1);
+	    if ((tmp > norm))
+		norm = tmp;
+	}
+	if (type == N_EUKLID_NORM) {
+	    norm += fabs(v2 - v1);
+	}
+    }
+
+    return norm;
+}
+
+/*!
+ * \brief Calculate basic statistics of the N_array_2d struct 
+ *
+ * Calculates the minimum, maximum, sum and the number of 
+ * non null values. The array offset can be included in the calculation.
+ *
+ * \param a N_array_2d * - input array
+ * \param min double* - variable to store the computed minimum
+ * \param max double* - variable to store the computed maximum
+ * \param sum double* - variable to store the computed sum
+ * \param nonull int* - variable to store the number of non null values
+ * \param withoffset - if 1 include offset values in statistic calculation, 0 otherwise 
+ * \return void
+ * */
+void N_calc_array_2d_stats(N_array_2d * a, double *min, double *max,
+			   double *sum, int *nonull, int withoffset)
+{
+    int i, j;
+    double val;
+
+    *sum = 0.0;
+    *nonull = 0;
+
+    if (withoffset == 1) {
+
+	*min =
+	    (double)N_get_array_2d_d_value(a, 0 - a->offset, 0 - a->offset);
+	*max =
+	    (double)N_get_array_2d_d_value(a, 0 - a->offset, 0 - a->offset);
+
+	for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
+	    for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
+		if (!N_is_array_2d_value_null(a, i, j)) {
+		    val = (double)N_get_array_2d_d_value(a, i, j);
+		    if (*min > val)
+			*min = val;
+		    if (*max < val)
+			*max = val;
+		    *sum += val;
+		    (*nonull)++;
+		}
+	    }
+	}
+    }
+    else {
+
+	*min = (double)N_get_array_2d_d_value(a, 0, 0);
+	*max = (double)N_get_array_2d_d_value(a, 0, 0);
+
+
+	for (j = 0; j < a->rows; j++) {
+	    for (i = 0; i < a->cols; i++) {
+		if (!N_is_array_2d_value_null(a, i, j)) {
+		    val = (double)N_get_array_2d_d_value(a, i, j);
+		    if (*min > val)
+			*min = val;
+		    if (*max < val)
+			*max = val;
+		    *sum += val;
+		    (*nonull)++;
+		}
+	    }
+	}
+    }
+
+    G_debug(3,
+	    "N_calc_array_2d_stats: compute array stats, min %g, max %g, sum %g, nonull %i",
+	    *min, *max, *sum, *nonull);
+    return;
+}
+
+
+/*!
+ * \brief Perform calculations with two input arrays, 
+ * the result is written to a third array.
+ *
+ * All arrays must have equal sizes and offsets.
+ * The complete data array inclusively offsets is used for calucaltions.
+ * Only non-null values are computed. If one array value is null, 
+ * the result array value will be null too.
+ * <br><br>
+ * If a division with zero is detected, the resulting arrays 
+ * value will set to null and not to NaN.
+ * <br><br>
+ * The result array is optional, if the result arrays points to NULL,
+ * a new array will be allocated with the largest arrays data type
+ * (CELL, FCELL or DCELL) used by the input arrays.
+ * <br><br>
+ * the array computations can be of the following forms:
+ *
+ * <ul>
+ * <li>result = a + b -> N_ARRAY_SUM</li>
+ * <li>result = a - b -> N_ARRAY_DIF</li>
+ * <li>result = a * b -> N_ARRAY_MUL</li>
+ * <li>result = a / b -> N_ARRAY_DIV</li>
+ * </ul>
+ *
+ * \param a N_array_2d * - first input array
+ * \param b N_array_2d * - second input array
+ * \param result N_array_2d * - the optional result array
+ * \param type  - the type of calculation
+ * \return N_array_2d * - the pointer to the result array
+ * */
+N_array_2d *N_math_array_2d(N_array_2d * a, N_array_2d * b,
+			    N_array_2d * result, int type)
+{
+    N_array_2d *c;
+    int i, j, setnull = 0;
+    double va = 0.0, vb = 0.0, vc = 0.0;	/*variables used for calculation */
+
+    /*Set the pointer */
+    c = result;
+
+#pragma omp single
+    {
+	/*Check the array sizes */
+	if (a->cols_intern != b->cols_intern)
+	    G_fatal_error
+		("N_math_array_2d: the arrays are not of equal size");
+	if (a->rows_intern != b->rows_intern)
+	    G_fatal_error
+		("N_math_array_2d: the arrays are not of equal size");
+	if (a->offset != b->offset)
+	    G_fatal_error
+		("N_math_array_2d: the arrays have different offsets");
+
+	G_debug(3, "N_math_array_2d: mathematical calculations, size: %i",
+		a->cols_intern * a->rows_intern);
+
+	/*if the result array is null, allocate a new one, use the 
+	 * largest data type of the input arrays*/
+	if (c == NULL) {
+	    if (a->type == DCELL_TYPE || b->type == DCELL_TYPE) {
+		c = N_alloc_array_2d(a->cols, a->rows, a->offset, DCELL_TYPE);
+		G_debug(3,
+			"N_math_array_2d: array of type DCELL_TYPE created");
+	    }
+	    else if (a->type == FCELL_TYPE || b->type == FCELL_TYPE) {
+		c = N_alloc_array_2d(a->cols, a->rows, a->offset, FCELL_TYPE);
+		G_debug(3,
+			"N_math_array_2d: array of type FCELL_TYPE created");
+	    }
+	    else {
+		c = N_alloc_array_2d(a->cols, a->rows, a->offset, CELL_TYPE);
+		G_debug(3,
+			"N_math_array_2d: array of type CELL_TYPE created");
+	    }
+	}
+	else {
+	    /*Check the array sizes */
+	    if (a->cols_intern != c->cols_intern)
+		G_fatal_error
+		    ("N_math_array_2d: the arrays are not of equal size");
+	    if (a->rows_intern != c->rows_intern)
+		G_fatal_error
+		    ("N_math_array_2d: the arrays are not of equal size");
+	    if (a->offset != c->offset)
+		G_fatal_error
+		    ("N_math_array_2d: the arrays have different offsets");
+	}
+    }
+
+#pragma omp for private(va, vb, vc, setnull)
+    for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
+	for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
+	    if (!N_is_array_2d_value_null(a, i, j) &&
+		!N_is_array_2d_value_null(b, i, j)) {
+		/*we always calulate internally with double values */
+		va = (double)N_get_array_2d_d_value(a, i, j);
+		vb = (double)N_get_array_2d_d_value(b, i, j);
+		vc = 0;
+		setnull = 0;
+
+		switch (type) {
+		case N_ARRAY_SUM:
+		    vc = va + vb;
+		    break;
+		case N_ARRAY_DIF:
+		    vc = va - vb;
+		    break;
+		case N_ARRAY_MUL:
+		    vc = va * vb;
+		    break;
+		case N_ARRAY_DIV:
+		    if (vb != 0)
+			vc = va / vb;
+		    else
+			setnull = 1;
+		    break;
+		}
+
+		if (c->type == CELL_TYPE) {
+		    if (setnull)
+			N_put_array_2d_value_null(c, i, j);
+		    else
+			N_put_array_2d_c_value(c, i, j, (CELL) vc);
+		}
+		if (c->type == FCELL_TYPE) {
+		    if (setnull)
+			N_put_array_2d_value_null(c, i, j);
+		    else
+			N_put_array_2d_f_value(c, i, j, (FCELL) vc);
+		}
+		if (c->type == DCELL_TYPE) {
+		    if (setnull)
+			N_put_array_2d_value_null(c, i, j);
+		    else
+			N_put_array_2d_d_value(c, i, j, (DCELL) vc);
+		}
+
+	    }
+	    else {
+		N_put_array_2d_value_null(c, i, j);
+	    }
+	}
+    }
+
+    return c;
+}
+
+/*!
+ * \brief Convert all null values to zero values
+ *
+ * The complete data array inclusively offsets is used.
+ * The array data types are automatically recognized.
+ *
+ * \param a N_array_2d *
+ * \return int - number of replaced values
+ * */
+int N_convert_array_2d_null_to_zero(N_array_2d * a)
+{
+    int i = 0, count = 0;
+
+    G_debug(3, "N_convert_array_2d_null_to_zero: convert array of size %i",
+	    a->cols_intern * a->rows_intern);
+
+    if (a->type == CELL_TYPE)
+	for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
+	    if (Rast_is_c_null_value((void *)&(a->cell_array[i]))) {
+		a->cell_array[i] = 0;
+		count++;
+	    }
+	}
+
+    if (a->type == FCELL_TYPE)
+	for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
+	    if (Rast_is_f_null_value((void *)&(a->fcell_array[i]))) {
+		a->fcell_array[i] = 0.0;
+		count++;
+	    }
+	}
+
+
+    if (a->type == DCELL_TYPE)
+	for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
+	    if (Rast_is_d_null_value((void *)&(a->dcell_array[i]))) {
+		a->dcell_array[i] = 0.0;
+		count++;
+	    }
+	}
+
+
+    if (a->type == CELL_TYPE)
+	G_debug(2,
+		"N_convert_array_2d_null_to_zero: %i values of type CELL_TYPE are converted",
+		count);
+    if (a->type == FCELL_TYPE)
+	G_debug(2,
+		"N_convert_array_2d_null_to_zero: %i valuess of type FCELL_TYPE are converted",
+		count);
+    if (a->type == DCELL_TYPE)
+	G_debug(2,
+		"N_convert_array_2d_null_to_zero: %i valuess of type DCELL_TYPE are converted",
+		count);
+
+    return count;
+}
+
+/* ******************** 3D ARRAY FUNCTIONS *********************** */
+
+/*!
+ * \brief Copy the source N_array_3d struct to the target N_array_3d struct
+ *
+ * The arrays must have the same size and the same offset.
+ *
+ * The array data types can be mixed, the values are automatically casted
+ * and the null values are set accordingly.
+ *
+ * If you copy a float array to a double array, the values are casted to DCELL and 
+ * the null values are converted from FCELL-null to DCELL-null
+ *
+ * \param source N_array_3d *
+ * \param target N_array_3d *
+ * \return void
+ * */
+void N_copy_array_3d(N_array_3d * source, N_array_3d * target)
+{
+    int i;
+    int null;
+
+    if (source->cols_intern != target->cols_intern)
+	G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
+
+    if (source->rows_intern != target->rows_intern)
+	G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
+
+    if (source->depths_intern != target->depths_intern)
+	G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
+
+
+    G_debug(3, "N_copy_array_3d: copy source array to target array size %i",
+	    source->cols_intern * source->rows_intern *
+	    source->depths_intern);
+
+    for (i = 0;
+	 i <
+	 source->cols_intern * source->rows_intern * source->depths_intern;
+	 i++) {
+	null = 0;
+	if (source->type == FCELL_TYPE) {
+	    if (Rast3d_is_null_value_num
+		((void *)&(source->fcell_array[i]), FCELL_TYPE))
+		null = 1;
+
+	    if (target->type == FCELL_TYPE) {
+		target->fcell_array[i] = source->fcell_array[i];
+	    }
+	    if (target->type == DCELL_TYPE) {
+		if (null)
+		    Rast3d_set_null_value((void *)&(target->dcell_array[i]), 1,
+				     DCELL_TYPE);
+		else
+		    target->dcell_array[i] = (double)source->fcell_array[i];
+	    }
+
+	}
+	if (source->type == DCELL_TYPE) {
+	    if (Rast3d_is_null_value_num
+		((void *)&(source->dcell_array[i]), DCELL_TYPE))
+		null = 1;
+
+	    if (target->type == FCELL_TYPE) {
+		if (null)
+		    Rast3d_set_null_value((void *)&(target->fcell_array[i]), 1,
+				     FCELL_TYPE);
+		else
+		    target->fcell_array[i] = (float)source->dcell_array[i];
+	    }
+	    if (target->type == DCELL_TYPE) {
+		target->dcell_array[i] = source->dcell_array[i];
+	    }
+	}
+    }
+
+    return;
+}
+
+
+/*!
+ * \brief Calculate the norm of the two input arrays
+ *
+ * The norm can be of type N_MAXIMUM_NORM or N_EUKLID_NORM.
+ * All arrays must have equal sizes and offsets.
+ * The complete data array inclusively offsets is used for norm calucaltion.
+ * Only non-null values are used to calcualte the norm.
+ *
+ * \param a N_array_3d *
+ * \param b N_array_3d *
+ * \param type the type of the norm -> N_MAXIMUM_NORM, N_EUKLID_NORM
+ * \return double the calculated norm
+ * */
+double N_norm_array_3d(N_array_3d * a, N_array_3d * b, int type)
+{
+    int i = 0;
+    double norm = 0.0, tmp = 0.0;
+    double v1 = 0.0, v2 = 0.0;
+
+    if (a->cols_intern != b->cols_intern)
+	G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
+
+    if (a->rows_intern != b->rows_intern)
+	G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
+
+    if (a->depths_intern != b->depths_intern)
+	G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
+
+    G_debug(3, "N_norm_array_3d: norm of a and b size %i",
+	    a->cols_intern * a->rows_intern * a->depths_intern);
+
+    for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern; i++) {
+	v1 = 0.0;
+	v2 = 0.0;
+
+	if (a->type == FCELL_TYPE) {
+	    if (!Rast3d_is_null_value_num((void *)&(a->fcell_array[i]), FCELL_TYPE))
+		v1 = (double)a->fcell_array[i];
+	}
+	if (a->type == DCELL_TYPE) {
+	    if (!Rast3d_is_null_value_num((void *)&(a->dcell_array[i]), DCELL_TYPE))
+		v1 = (double)a->dcell_array[i];
+	}
+	if (b->type == FCELL_TYPE) {
+	    if (!Rast3d_is_null_value_num((void *)&(b->fcell_array[i]), FCELL_TYPE))
+		v2 = (double)b->fcell_array[i];
+	}
+	if (b->type == DCELL_TYPE) {
+	    if (!Rast3d_is_null_value_num((void *)&(b->dcell_array[i]), DCELL_TYPE))
+		v2 = (double)b->dcell_array[i];
+	}
+
+	if (type == N_MAXIMUM_NORM) {
+	    tmp = fabs(v2 - v1);
+	    if ((tmp > norm))
+		norm = tmp;
+	}
+	if (type == N_EUKLID_NORM) {
+	    norm += fabs(v2 - v1);
+	}
+    }
+
+    return norm;
+}
+
+/*!
+ * \brief Calculate basic statistics of the N_array_3d struct
+ *
+ * Calculates the minimum, maximum, sum and the number of 
+ * non null values. The array offset can be included in the statistical calculation.
+ *
+ * \param a N_array_3d * - input array
+ * \param min double* - variable to store the computed minimum
+ * \param max double* - variable to store the computed maximum
+ * \param sum double* - variable to store the computed sum
+ * \param nonull int* - variable to store the number of non null values
+ * \param withoffset - if 1 include offset values in statistic calculation, 0 otherwise 
+ * \return void
+ * */
+void N_calc_array_3d_stats(N_array_3d * a, double *min, double *max,
+			   double *sum, int *nonull, int withoffset)
+{
+    int i, j, k;
+    double val;
+
+    *sum = 0.0;
+    *nonull = 0;
+
+    if (withoffset == 1) {
+
+	*min =
+	    (double)N_get_array_3d_d_value(a, 0 - a->offset, 0 - a->offset,
+					   0 - a->offset);
+	*max =
+	    (double)N_get_array_3d_d_value(a, 0 - a->offset, 0 - a->offset,
+					   0 - a->offset);
+
+	for (k = 0 - a->offset; k < a->depths + a->offset; k++) {
+	    for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
+		for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
+		    if (!N_is_array_3d_value_null(a, i, j, k)) {
+			val = (double)N_get_array_3d_d_value(a, i, j, k);
+			if (*min > val)
+			    *min = val;
+			if (*max < val)
+			    *max = val;
+			*sum += val;
+			(*nonull)++;
+		    }
+		}
+	    }
+	}
+    }
+    else {
+
+	*min = (double)N_get_array_3d_d_value(a, 0, 0, 0);
+	*max = (double)N_get_array_3d_d_value(a, 0, 0, 0);
+
+	for (k = 0; k < a->depths; k++) {
+	    for (j = 0; j < a->rows; j++) {
+		for (i = 0; i < a->cols; i++) {
+		    if (!N_is_array_3d_value_null(a, i, j, k)) {
+			val = (double)N_get_array_3d_d_value(a, i, j, k);
+			if (*min > val)
+			    *min = val;
+			if (*max < val)
+			    *max = val;
+			*sum += val;
+			(*nonull)++;
+		    }
+		}
+	    }
+	}
+    }
+
+    G_debug(3,
+	    "N_calc_array_3d_stats: compute array stats, min %g, max %g, sum %g, nonull %i",
+	    *min, *max, *sum, *nonull);
+
+    return;
+}
+
+/*!
+ * \brief Perform calculations with two input arrays, 
+ * the result is written to a third array.
+ *
+ * All arrays must have equal sizes and offsets.
+ * The complete data array inclusively offsets is used for calucaltions.
+ * Only non-null values are used. If one array value is null, 
+ * the result array value will be null too.
+ * <br><br>
+ *
+ * If a division with zero is detected, the resulting arrays 
+ * value will set to null and not to NaN.
+ * <br><br>
+ *
+ * The result array is optional, if the result arrays points to NULL,
+ * a new array will be allocated with the largest arrays data type
+ * (FCELL_TYPE or DCELL_TYPE) used by the input arrays.
+ * <br><br>
+ *
+ * the calculations are of the following form:
+ *
+ * <ul>
+ * <li>result = a + b -> N_ARRAY_SUM</li>
+ * <li>result = a - b -> N_ARRAY_DIF</li>
+ * <li>result = a * b -> N_ARRAY_MUL</li>
+ * <li>result = a / b -> N_ARRAY_DIV</li>
+ * </ul>
+ *
+ * \param a N_array_3d * - first input array
+ * \param b N_array_3d * - second input array
+ * \param result N_array_3d * - the optional result array
+ * \param type  - the type of calculation
+ * \return N_array_3d * - the pointer to the result array
+ * */
+N_array_3d *N_math_array_3d(N_array_3d * a, N_array_3d * b,
+			    N_array_3d * result, int type)
+{
+    N_array_3d *c;
+    int i, j, k, setnull = 0;
+    double va = 0.0, vb = 0.0, vc = 0.0;	/*variables used for calculation */
+
+    /*Set the pointer */
+    c = result;
+
+    /*Check the array sizes */
+    if (a->cols_intern != b->cols_intern)
+	G_fatal_error("N_math_array_3d: the arrays are not of equal size");
+    if (a->rows_intern != b->rows_intern)
+	G_fatal_error("N_math_array_3d: the arrays are not of equal size");
+    if (a->depths_intern != b->depths_intern)
+	G_fatal_error("N_math_array_3d: the arrays are not of equal size");
+    if (a->offset != b->offset)
+	G_fatal_error("N_math_array_3d: the arrays have different offsets");
+
+    G_debug(3, "N_math_array_3d: mathematical calculations, size: %i",
+	    a->cols_intern * a->rows_intern * a->depths_intern);
+
+    /*if the result array is null, allocate a new one, use the 
+     * largest data type of the input arrays*/
+    if (c == NULL) {
+	if (a->type == DCELL_TYPE || b->type == DCELL_TYPE) {
+	    c = N_alloc_array_3d(a->cols, a->rows, a->depths, a->offset,
+				 DCELL_TYPE);
+	    G_debug(3, "N_math_array_3d: array of type DCELL_TYPE created");
+	}
+	else {
+	    c = N_alloc_array_3d(a->cols, a->rows, a->depths, a->offset,
+				 FCELL_TYPE);
+	    G_debug(3, "N_math_array_3d: array of type FCELL_TYPE created");
+	}
+    }
+    else {
+	/*Check the array sizes */
+	if (a->cols_intern != c->cols_intern)
+	    G_fatal_error
+		("N_math_array_3d: the arrays are not of equal size");
+	if (a->rows_intern != c->rows_intern)
+	    G_fatal_error
+		("N_math_array_3d: the arrays are not of equal size");
+	if (a->depths_intern != c->depths_intern)
+	    G_fatal_error
+		("N_math_array_3d: the arrays are not of equal size");
+	if (a->offset != c->offset)
+	    G_fatal_error
+		("N_math_array_3d: the arrays have different offsets");
+    }
+
+    for (k = 0 - a->offset; k < a->depths + a->offset; k++) {
+	for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
+	    for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
+		if (!N_is_array_3d_value_null(a, i, j, k) &&
+		    !N_is_array_3d_value_null(a, i, j, k)) {
+		    /*we always calulate internally with double values */
+		    va = (double)N_get_array_3d_d_value(a, i, j, k);
+		    vb = (double)N_get_array_3d_d_value(b, i, j, k);
+		    vc = 0;
+		    setnull = 0;
+
+		    switch (type) {
+		    case N_ARRAY_SUM:
+			vc = va + vb;
+			break;
+		    case N_ARRAY_DIF:
+			vc = va - vb;
+			break;
+		    case N_ARRAY_MUL:
+			vc = va * vb;
+			break;
+		    case N_ARRAY_DIV:
+			if (vb != 0)
+			    vc = va / vb;
+			else
+			    setnull = 1;
+			break;
+		    }
+
+		    if (c->type == FCELL_TYPE) {
+			if (setnull)
+			    N_put_array_3d_value_null(c, i, j, k);
+			else
+			    N_put_array_3d_f_value(c, i, j, k, (float)vc);
+		    }
+		    if (c->type == DCELL_TYPE) {
+			if (setnull)
+			    N_put_array_3d_value_null(c, i, j, k);
+			else
+			    N_put_array_3d_d_value(c, i, j, k, vc);
+		    }
+		}
+		else {
+		    N_put_array_3d_value_null(c, i, j, k);
+		}
+	    }
+	}
+    }
+
+    return c;
+}
+
+/*!
+ * \brief Convert all null values to zero values
+ *
+ * The complete data array inclusively offsets is used.
+ *
+ * \param a N_array_3d *
+ * \return int - number of replaced null values
+ * */
+int N_convert_array_3d_null_to_zero(N_array_3d * a)
+{
+    int i = 0, count = 0;
+
+    G_debug(3, "N_convert_array_3d_null_to_zero: convert array of size %i",
+	    a->cols_intern * a->rows_intern * a->depths_intern);
+
+    if (a->type == FCELL_TYPE)
+	for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern;
+	     i++) {
+	    if (Rast3d_is_null_value_num((void *)&(a->fcell_array[i]), FCELL_TYPE)) {
+		a->fcell_array[i] = 0.0;
+		count++;
+	    }
+	}
+
+    if (a->type == DCELL_TYPE)
+	for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern;
+	     i++) {
+	    if (Rast3d_is_null_value_num((void *)&(a->dcell_array[i]), DCELL_TYPE)) {
+		a->dcell_array[i] = 0.0;
+		count++;
+	    }
+	}
+
+
+    if (a->type == FCELL_TYPE)
+	G_debug(3,
+		"N_convert_array_3d_null_to_zero: %i values of type FCELL_TYPE are converted",
+		count);
+
+    if (a->type == DCELL_TYPE)
+	G_debug(3,
+		"N_convert_array_3d_null_to_zero: %i values of type DCELL_TYPE are converted",
+		count);
+
+    return count;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_arrays_io.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_arrays_io.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_arrays_io.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_arrays_io.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,467 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:     	IO array managment functions 
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+
+/* ******************** 2D ARRAY FUNCTIONS *********************** */
+
+/*!
+ * \brief Read a raster map into a N_array_2d structure
+ *
+ * The raster map will be opened in the current region settings.
+ * If no N_array_2d structure is provided (NULL pointer), a new structure will be
+ * allocated with the same data type as the raster map and the size of the current region. 
+ * The array offset will be set to 0.
+ * <br><br>
+ * If a N_array_2d structure is provided, the values from the raster map are 
+ * casted to the N_array_2d type. The array must have the same size 
+ * as the current region. 
+ * <br><br>
+ * The new created or the provided array are returned.
+ * If the reading of the raster map fails, G_fatal_error() will
+ * be invoked.
+ *
+ * \param name * char - the name of an existing raster map
+ * \param array * N_array_2d - an existing array or NULL
+ * \return N_array_2d * - the existing or new allocated array
+ * */
+N_array_2d *N_read_rast_to_array_2d(char *name, N_array_2d * array)
+{
+    int map;			/*The rastermap */
+    int x, y, cols, rows, type;
+    void *rast;
+    void *ptr;
+    struct Cell_head region;
+    N_array_2d *data = array;
+
+    /* Get the active region */
+    G_get_set_window(&region);
+
+    /*set the rows and cols */
+    rows = region.rows;
+    cols = region.cols;
+
+    /*open the raster map */
+    map = Rast_open_old(name, "");
+
+    type = Rast_get_map_type(map);
+
+    /*if the array is NULL create a new one with the data type of the raster map */
+    /*the offset is 0 by default */
+    if (data == NULL) {
+	if (type == DCELL_TYPE) {
+	    data = N_alloc_array_2d(cols, rows, 0, DCELL_TYPE);
+	}
+	if (type == FCELL_TYPE) {
+	    data = N_alloc_array_2d(cols, rows, 0, FCELL_TYPE);
+	}
+	if (type == CELL_TYPE) {
+	    data = N_alloc_array_2d(cols, rows, 0, CELL_TYPE);
+	}
+    }
+    else {
+	/*Check the array sizes */
+	if (data->cols != cols)
+	    G_fatal_error
+		("N_read_rast_to_array_2d: the data array size is different from the current region settings");
+	if (data->rows != rows)
+	    G_fatal_error
+		("N_read_rast_to_array_2d: the data array size is different from the current region settings");
+    }
+
+    rast = Rast_allocate_buf(type);
+
+    G_message(_("Reading raster map <%s> into memory"), name);
+
+    for (y = 0; y < rows; y++) {
+	G_percent(y, rows - 1, 10);
+
+	Rast_get_row(map, rast, y, type);
+
+	for (x = 0, ptr = rast; x < cols;
+	     x++, ptr = G_incr_void_ptr(ptr, Rast_cell_size(type))) {
+	    if (type == CELL_TYPE) {
+		if (Rast_is_c_null_value(ptr)) {
+		    N_put_array_2d_value_null(data, x, y);
+		}
+		else {
+		    if (data->type == CELL_TYPE)
+			N_put_array_2d_c_value(data, x, y,
+					       (CELL) * (CELL *) ptr);
+		    if (data->type == FCELL_TYPE)
+			N_put_array_2d_f_value(data, x, y,
+					       (FCELL) * (CELL *) ptr);
+		    if (data->type == DCELL_TYPE)
+			N_put_array_2d_d_value(data, x, y,
+					       (DCELL) * (CELL *) ptr);
+		}
+	    }
+	    if (type == FCELL_TYPE) {
+		if (Rast_is_f_null_value(ptr)) {
+		    N_put_array_2d_value_null(data, x, y);
+		}
+		else {
+		    if (data->type == CELL_TYPE)
+			N_put_array_2d_c_value(data, x, y,
+					       (CELL) * (FCELL *) ptr);
+		    if (data->type == FCELL_TYPE)
+			N_put_array_2d_f_value(data, x, y,
+					       (FCELL) * (FCELL *) ptr);
+		    if (data->type == DCELL_TYPE)
+			N_put_array_2d_d_value(data, x, y,
+					       (DCELL) * (FCELL *) ptr);
+		}
+	    }
+	    if (type == DCELL_TYPE) {
+		if (Rast_is_d_null_value(ptr)) {
+		    N_put_array_2d_value_null(data, x, y);
+		}
+		else {
+		    if (data->type == CELL_TYPE)
+			N_put_array_2d_c_value(data, x, y,
+					       (CELL) * (DCELL *) ptr);
+		    if (data->type == FCELL_TYPE)
+			N_put_array_2d_f_value(data, x, y,
+					       (FCELL) * (DCELL *) ptr);
+		    if (data->type == DCELL_TYPE)
+			N_put_array_2d_d_value(data, x, y,
+					       (DCELL) * (DCELL *) ptr);
+		}
+	    }
+	}
+    }
+
+    /* Close file */
+    Rast_close(map);
+
+    return data;
+}
+
+/*!
+ * \brief Write a N_array_2d struct to a raster map
+ *
+ * A new raster map is created with the same type as the N_array_2d.
+ * The current region is used to open the raster map.
+ * The N_array_2d must have the same size as the current region.
+ If the writing of the raster map fails, G_fatal_error() will
+ * be invoked.
+
+ * \param array N_array_2d * 
+ * \param name char * - the name of the raster map
+ * \return void
+ *
+ * */
+void N_write_array_2d_to_rast(N_array_2d * array, char *name)
+{
+    int map;			/*The rastermap */
+    int x, y, cols, rows, count, type;
+    CELL *rast = NULL;
+    FCELL *frast = NULL;
+    DCELL *drast = NULL;
+    struct Cell_head region;
+
+    if (!array)
+	G_fatal_error(_("N_array_2d * array is empty"));
+
+    /* Get the current region */
+    G_get_set_window(&region);
+
+    rows = region.rows;
+    cols = region.cols;
+    type = array->type;
+
+    /*Open the new map */
+    map = Rast_open_new(name, type);
+
+    if (type == CELL_TYPE)
+	rast = Rast_allocate_buf(type);
+    if (type == FCELL_TYPE)
+	frast = Rast_allocate_buf(type);
+    if (type == DCELL_TYPE)
+	drast = Rast_allocate_buf(type);
+
+    G_message(_("Write 2d array to raster map <%s>"), name);
+
+    count = 0;
+    for (y = 0; y < rows; y++) {
+	G_percent(y, rows - 1, 10);
+	for (x = 0; x < cols; x++) {
+	    if (type == CELL_TYPE)
+		rast[x] = N_get_array_2d_c_value(array, x, y);
+	    if (type == FCELL_TYPE)
+		frast[x] = N_get_array_2d_f_value(array, x, y);
+	    if (type == DCELL_TYPE)
+		drast[x] = N_get_array_2d_d_value(array, x, y);
+	}
+	if (type == CELL_TYPE)
+	    Rast_put_c_row(map, rast);
+	if (type == FCELL_TYPE)
+	    Rast_put_f_row(map, frast);
+	if (type == DCELL_TYPE)
+	    Rast_put_d_row(map, drast);
+    }
+
+    /* Close file */
+    Rast_close(map);
+}
+
+
+/* ******************** 3D ARRAY FUNCTIONS *********************** */
+
+/*!
+ * \brief Read a volume map into a N_array_3d structure
+ *
+ * The volume map is opened in the current region settings.
+ * If no N_array_3d structure is provided (NULL pointer), a new structure will be
+ * allocated with the same data type as the volume map and the size of the current region. 
+ * The array offset will be set to 0.
+ * <br><br>
+ *
+ * If a N_array_3d structure is provided, the values from the volume map are 
+ * casted to the N_array_3d type. The array must have the same size 
+ * as the current region. 
+ * <br><br>
+ *
+ * The new created or the provided array is returned.
+ * If the reading of the volume map fails, Rast3d_fatal_error() will
+ * be invoked.
+ *
+ * \param name * char - the name of an existing volume map
+ * \param array * N_array_3d - an existing array or NULL
+ * \param mask int - 0 = false, 1 = ture : if a mask is presenent, use it with the input volume map
+ * \return N_array_3d * - the existing or new allocated array
+ * */
+N_array_3d *N_read_rast3d_to_array_3d(char *name, N_array_3d * array,
+				      int mask)
+{
+    void *map = NULL;		/*The 3D Rastermap */
+    int changemask = 0;
+    int x, y, z, cols, rows, depths, type;
+    double d1 = 0, f1 = 0;
+    N_array_3d *data = array;
+    RASTER3D_Region region;
+
+
+    /*get the current region */
+    Rast3d_get_window(&region);
+
+    cols = region.cols;
+    rows = region.rows;
+    depths = region.depths;
+
+
+    if (NULL == G_find_raster3d(name, ""))
+	Rast3d_fatal_error(_("3D raster map <%s> not found"), name);
+
+    /*Open all maps with default region */
+    map =
+	Rast3d_open_cell_old(name, G_find_raster3d(name, ""), RASTER3D_DEFAULT_WINDOW,
+			RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
+
+    if (map == NULL)
+	Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), name);
+
+    type = Rast3d_tile_type_map(map);
+
+    /*if the array is NULL create a new one with the data type of the volume map */
+    /*the offset is 0 by default */
+    if (data == NULL) {
+	if (type == FCELL_TYPE) {
+	    data = N_alloc_array_3d(cols, rows, depths, 0, FCELL_TYPE);
+	}
+	if (type == DCELL_TYPE) {
+	    data = N_alloc_array_3d(cols, rows, depths, 0, DCELL_TYPE);
+	}
+    }
+    else {
+	/*Check the array sizes */
+	if (data->cols != cols)
+	    G_fatal_error
+		("N_read_rast_to_array_3d: the data array size is different from the current region settings");
+	if (data->rows != rows)
+	    G_fatal_error
+		("N_read_rast_to_array_3d: the data array size is different from the current region settings");
+	if (data->depths != depths)
+	    G_fatal_error
+		("N_read_rast_to_array_3d: the data array size is different from the current region settings");
+    }
+
+
+    G_message(_("Read g3d map <%s> into the memory"), name);
+
+    /*if requested set the Mask on */
+    if (mask) {
+	if (Rast3d_mask_file_exists()) {
+	    changemask = 0;
+	    if (Rast3d_mask_is_off(map)) {
+		Rast3d_mask_on(map);
+		changemask = 1;
+	    }
+	}
+    }
+
+    for (z = 0; z < depths; z++) {	/*From the bottom to the top */
+	G_percent(z, depths - 1, 10);
+	for (y = 0; y < rows; y++) {
+	    for (x = 0; x < cols; x++) {
+		if (type == FCELL_TYPE) {
+		    Rast3d_get_value(map, x, y, z, &f1, type);
+		    if (Rast_is_f_null_value((void *)&f1)) {
+			N_put_array_3d_value_null(data, x, y, z);
+		    }
+		    else {
+			if (data->type == FCELL_TYPE)
+			    N_put_array_3d_f_value(data, x, y, z, f1);
+			if (data->type == DCELL_TYPE)
+			    N_put_array_3d_d_value(data, x, y, z, (double)f1);
+		    }
+		}
+		else {
+		    Rast3d_get_value(map, x, y, z, &d1, type);
+		    if (Rast_is_d_null_value((void *)&d1)) {
+			N_put_array_3d_value_null(data, x, y, z);
+		    }
+		    else {
+			if (data->type == FCELL_TYPE)
+			    N_put_array_3d_f_value(data, x, y, z, (float)d1);
+			if (data->type == DCELL_TYPE)
+			    N_put_array_3d_d_value(data, x, y, z, d1);
+		    }
+
+		}
+	    }
+	}
+    }
+
+    /*We set the Mask off, if it was off before */
+    if (mask) {
+	if (Rast3d_mask_file_exists())
+	    if (Rast3d_mask_is_on(map) && changemask)
+		Rast3d_mask_off(map);
+    }
+
+    /* Close files and exit */
+    if (!Rast3d_close(map))
+	Rast3d_fatal_error(map, NULL, 0, _("Error closing g3d file"));
+
+    return data;
+}
+
+/*!
+ * \brief Write a N_array_3d struct to a volume map
+ *
+ * A new volume map is created with the same type as the N_array_3d.
+ * The current region is used to open the volume map.
+ * The N_array_3d must have the same size as the current region.
+ * If the writing of the volume map fails, Rast3d_fatal_error() will
+ * be invoked.
+ *
+ *
+ * \param array N_array_3d * 
+ * \param name char * - the name of the volume map
+ * \param mask int - 1 = use a 3d mask, 0 do not use a 3d mask
+ * \return void
+ *
+ * */
+void N_write_array_3d_to_rast3d(N_array_3d * array, char *name, int mask)
+{
+    void *map = NULL;		/*The 3D Rastermap */
+    int changemask = 0;
+    int x, y, z, cols, rows, depths, count, type;
+    double d1 = 0.0, f1 = 0.0;
+    N_array_3d *data = array;
+    RASTER3D_Region region;
+
+    /*get the current region */
+    Rast3d_get_window(&region);
+
+    cols = region.cols;
+    rows = region.rows;
+    depths = region.depths;
+    type = data->type;
+
+    /*Check the array sizes */
+    if (data->cols != cols)
+	G_fatal_error
+	    ("N_write_array_3d_to_rast3d: the data array size is different from the current region settings");
+    if (data->rows != rows)
+	G_fatal_error
+	    ("N_write_array_3d_to_rast3d: the data array size is different from the current region settings");
+    if (data->depths != depths)
+	G_fatal_error
+	    ("N_write_array_3d_to_rast3d: the data array size is different from the current region settings");
+
+    /*Open the new map */
+    if (type == DCELL_TYPE)
+        map = Rast3d_open_new_opt_tile_size(name, RASTER3D_USE_CACHE_XY, &region, DCELL_TYPE, 32);
+    else if (type == FCELL_TYPE)
+        map = Rast3d_open_new_opt_tile_size(name, RASTER3D_USE_CACHE_XY, &region, FCELL_TYPE, 32);
+
+    if (map == NULL)
+	Rast3d_fatal_error(_("Error opening g3d map <%s>"), name);
+
+    G_message(_("Write 3d array to g3d map <%s>"), name);
+
+    /*if requested set the Mask on */
+    if (mask) {
+	if (Rast3d_mask_file_exists()) {
+	    changemask = 0;
+	    if (Rast3d_mask_is_off(map)) {
+		Rast3d_mask_on(map);
+		changemask = 1;
+	    }
+	}
+    }
+
+    count = 0;
+    for (z = 0; z < depths; z++) {	/*From the bottom to the top */
+	G_percent(z, depths - 1, 10);
+	for (y = 0; y < rows; y++) {
+	    for (x = 0; x < cols; x++) {
+		if (type == FCELL_TYPE) {
+		    f1 = N_get_array_3d_f_value(data, x, y, z);
+		    Rast3d_put_float(map, x, y, z, f1);
+		}
+		else if (type == DCELL_TYPE) {
+		    d1 = N_get_array_3d_d_value(data, x, y, z);
+		    Rast3d_put_double(map, x, y, z, d1);
+		}
+	    }
+	}
+    }
+
+    /*We set the Mask off, if it was off before */
+    if (mask) {
+	if (Rast3d_mask_file_exists())
+	    if (Rast3d_mask_is_on(map) && changemask)
+		Rast3d_mask_off(map);
+    }
+
+    /* Flush all tile */
+    if (!Rast3d_flush_all_tiles(map))
+	Rast3d_fatal_error("Error flushing tiles with Rast3d_flush_all_tiles");
+    /* Close files and exit */
+    if (!Rast3d_close(map))
+	Rast3d_fatal_error(map, NULL, 0, _("Error closing g3d file"));
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_geom.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_geom.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_geom.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_geom.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,204 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:      part of the gpde library
+* 		allocation, destroing and initializing the geometric struct
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+
+/* *************************************************************** * 
+ * *********** Konstruktor *************************************** * 
+ * *************************************************************** */
+/*!
+ * \brief Allocate the pde geometry data structure and return a pointer to the new allocated structure
+ *
+ * \return N_geom_data *
+ * */
+N_geom_data *N_alloc_geom_data(void)
+{
+    N_geom_data *geom = (N_geom_data *) G_calloc(1, sizeof(N_geom_data));
+
+    geom->area = NULL;
+    geom->planimetric = 1;
+    geom->dim = 0;
+
+    return geom;
+}
+
+/* *************************************************************** * 
+ * *********** Destruktor **************************************** * 
+ * *************************************************************** */
+/*!
+ * \brief Release memory of a pde geometry data structure
+ *
+ * \param  geom N_geom_data *
+ * \return void
+ * */
+void N_free_geom_data(N_geom_data * geom)
+{
+    if (geom->area != NULL)
+	G_free(geom->area);
+
+    G_free(geom);
+    return;
+}
+
+/* *************************************************************** * 
+ * *************************************************************** * 
+ * *************************************************************** */
+/*!
+ * \brief Initiate a pde geometry data structure with a 3d region
+ *
+ * If the projection is not planimetric, a double array will be created based on the 
+ * number of rows of the provided region
+ *
+ * \param region3d RASTER3D_Region *
+ * \param geodata N_geom_data * - if a NULL pointer is given, a new structure will be allocatet and returned
+ *
+ * \return N_geom_data *
+ * */
+N_geom_data *N_init_geom_data_3d(RASTER3D_Region * region3d, N_geom_data * geodata)
+{
+    N_geom_data *geom = geodata;
+    struct Cell_head region2d;
+
+#pragma omp critical
+    {
+
+	G_debug(2,
+		"N_init_geom_data_3d: initializing the geometry structure");
+
+	if (geom == NULL)
+	    geom = N_alloc_geom_data();
+
+	geom->dz = region3d->tb_res * G_database_units_to_meters_factor();	/*this function is not thread safe */
+	geom->depths = region3d->depths;
+	geom->dim = 3;
+
+	/*convert the 3d into a 2d region and begin the area calculation */
+	G_get_set_window(&region2d);	/*this function is not thread safe */
+	Rast3d_region_to_cell_head(region3d, &region2d);
+    }
+
+    return N_init_geom_data_2d(&region2d, geom);
+}
+
+
+/* *************************************************************** * 
+ * *************************************************************** * 
+ * *************************************************************** */
+/*!
+ * \brief Initiate a pde geometry data structure with a 2d region
+ *
+ * If the projection is not planimetric, a double array will be created based on the 
+ * number of rows of the provided region storing all computed areas for each row
+ *
+ * \param region sruct Cell_head *
+ * \param geodata N_geom_data * - if a NULL pointer is given, a new structure will be allocatet and returned
+ *
+ * \return N_geom_data *
+ * */
+N_geom_data *N_init_geom_data_2d(struct Cell_head * region,
+				 N_geom_data * geodata)
+{
+    N_geom_data *geom = geodata;
+    struct Cell_head backup;
+    double meters;
+    short ll = 0;
+    int i;
+
+
+    /*create an openmp lock to assure that only one thread at a time will access this function */
+#pragma omp critical
+    {
+	G_debug(2,
+		"N_init_geom_data_2d: initializing the geometry structure");
+
+	/*make a backup from this region */
+	G_get_set_window(&backup);	/*this function is not thread safe */
+	/*set the current region */
+	Rast_set_window(region);	/*this function is not thread safe */
+
+	if (geom == NULL)
+	    geom = N_alloc_geom_data();
+
+	meters = G_database_units_to_meters_factor();	/*this function is not thread safe */
+
+	/*set the dim to 2d if it was not initiated with 3, thats a bit ugly :( */
+	if (geom->dim != 3)
+	    geom->dim = 2;
+
+	geom->planimetric = 1;
+	geom->rows = region->rows;
+	geom->cols = region->cols;
+	geom->dx = region->ew_res * meters;
+	geom->dy = region->ns_res * meters;
+	geom->Az = geom->dy * geom->dx;	/*square meters in planimetric proj */
+	/*depths and dz are initialized with a 3d region */
+
+	/*Begin the area calculation */
+	ll = G_begin_cell_area_calculations();	/*this function is not thread safe */
+
+	/*if the projection is not planimetric, calc the area for each row */
+	if (ll == 2) {
+	    G_debug(2,
+		    "N_init_geom_data_2d: calculating the areas for non parametric projection");
+	    geom->planimetric = 0;
+
+	    if (geom->area != NULL)
+		G_free(geom->area);
+	    else
+		geom->area = G_calloc(geom->rows, sizeof(double));
+
+	    /*fill the area vector */
+	    for (i = 0; i < geom->rows; i++) {
+		geom->area[i] = G_area_of_cell_at_row(i);	/*square meters */
+	    }
+	}
+
+	/*restore the old region */
+	Rast_set_window(&backup);	/*this function is not thread safe */
+    }
+
+    return geom;
+}
+
+/* *************************************************************** * 
+ * *************************************************************** * 
+ * *************************************************************** */
+/*!
+ * \brief Get the areay size in square meter of one cell (x*y) at row
+ *
+ * This function works for two and three dimensions
+ *
+ * \param geom N_geom_data *
+ * \param row int
+ * \return area double
+ *
+ * */
+double N_get_geom_data_area_of_cell(N_geom_data * geom, int row)
+{
+    if (geom->planimetric) {
+	G_debug(6, "N_get_geom_data_area_of_cell: %g", geom->Az);
+	return geom->Az;
+    }
+    else {
+	G_debug(6, "N_get_geom_data_area_of_cell: %g", geom->area[row]);
+	return geom->area[row];
+    }
+
+    return 0.0;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_gradient.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_gradient.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_gradient.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_gradient.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,1113 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:     	gradient management functions 
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+
+/*!
+ * \brief Allocate a N_gradient_2d structure
+ *
+ * \return N_gradient_2d *
+ *
+ * */
+N_gradient_2d *N_alloc_gradient_2d(void)
+{
+    N_gradient_2d *grad;
+
+    grad = (N_gradient_2d *) G_calloc(1, sizeof(N_gradient_2d));
+
+    return grad;
+}
+
+/*!
+ * \brief Free's a N_gradient_2d structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_2d(N_gradient_2d * grad)
+{
+    G_free(grad);
+    grad = NULL;
+
+    return;
+}
+
+/*!
+ * \brief allocate and initialize a N_gradient_2d structure
+ *
+ * \param NC double - the gradient between northern and center cell
+ * \param SC double - the gradient between southern and center cell
+ * \param WC double - the gradient between western and center cell
+ * \param EC double - the gradient between eastern and center cell
+ * \return N_gradient_2d *
+ *
+ * */
+N_gradient_2d *N_create_gradient_2d(double NC, double SC, double WC,
+				    double EC)
+{
+    N_gradient_2d *grad;
+
+    G_debug(5, "N_create_gradient_2d: create N_gradient_2d");
+
+    grad = N_alloc_gradient_2d();
+
+    grad->NC = NC;
+    grad->SC = SC;
+    grad->WC = WC;
+    grad->EC = EC;
+
+    return grad;
+}
+
+/*!
+ * \brief copy a N_gradient_2d structure
+ *
+ * \param source - the source N_gradient_2d struct
+ * \param target - the target N_gradient_2d struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int N_copy_gradient_2d(N_gradient_2d * source, N_gradient_2d * target)
+{
+    G_debug(5, "N_copy_gradient_2d: copy N_gradient_2d");
+
+    if (!source || !target)
+	return 0;
+
+    target->NC = source->NC;
+    target->SC = source->SC;
+    target->WC = source->WC;
+    target->EC = source->EC;
+
+    return 1;
+}
+
+/*!
+ * \brief Return a N_gradient_2d structure calculated from the input gradient field
+ * at position [row][col]
+ *
+ *  This function returns the gradient of a cell at position [row][col] from the input gradient field.
+ *  Returend is a new structure of type N_gradient_2d.
+ *
+ *  \param field N_gradient_field_2d * - A two dimensional gradient field
+ *  \param gradient N_gradient_2d * - the gradient structure which should be filled with data, if a NULL pointer is given, a new structure will be created
+ *  \param col int
+ *  \param row int
+ *  \return N_gradient_2d * - the new or filled gradient structure
+ *  
+ *
+ * */
+N_gradient_2d *N_get_gradient_2d(N_gradient_field_2d * field,
+				 N_gradient_2d * gradient, int col, int row)
+{
+    double NC = 0, SC = 0, WC = 0, EC = 0;
+    N_gradient_2d *grad = gradient;
+
+
+    NC = N_get_array_2d_d_value(field->y_array, col, row);
+    SC = N_get_array_2d_d_value(field->y_array, col, row + 1);
+    WC = N_get_array_2d_d_value(field->x_array, col, row);
+    EC = N_get_array_2d_d_value(field->x_array, col + 1, row);
+
+    G_debug(5,
+	    "N_get_gradient_2d: calculate N_gradient_2d NC %g SC %g WC %g EC %g",
+	    NC, SC, WC, EC);
+
+    /*if gradient is a NULL pointer, create a new one */
+    if (!grad) {
+	grad = N_create_gradient_2d(NC, SC, WC, EC);
+    }
+    else {
+	grad->NC = NC;
+	grad->SC = SC;
+	grad->WC = WC;
+	grad->EC = EC;
+    }
+
+    return grad;
+}
+
+/*!
+ * \brief Allocate a N_gradient_3d structure
+ *
+ * \return N_gradient_3d *
+ *
+ * */
+N_gradient_3d *N_alloc_gradient_3d(void)
+{
+    N_gradient_3d *grad;
+
+    grad = (N_gradient_3d *) G_calloc(1, sizeof(N_gradient_3d));
+
+    return grad;
+}
+
+/*!
+ * \brief Free's a N_gradient_3d structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_3d(N_gradient_3d * grad)
+{
+    G_free(grad);
+    grad = NULL;
+
+    return;
+}
+
+
+/*!
+ * \brief allocate and initialize a N_gradient_3d structure
+ *
+ * \param NC double - the gradient between northern and center cell
+ * \param SC double - the gradient between southern and center cell
+ * \param WC double - the gradient between western and center cell
+ * \param EC double - the gradient between eastern and center cell
+ * \param TC double - the gradient between top and center cell
+ * \param BC double - the gradient between bottom and center cell
+ * \return N_gradient_3d *
+ *
+ * */
+N_gradient_3d *N_create_gradient_3d(double NC, double SC, double WC,
+				    double EC, double TC, double BC)
+{
+    N_gradient_3d *grad;
+
+    G_debug(5, "N_create_gradient_3d: create N_gradient_3d");
+
+    grad = N_alloc_gradient_3d();
+
+    grad->NC = NC;
+    grad->SC = SC;
+    grad->WC = WC;
+    grad->EC = EC;
+    grad->TC = TC;
+    grad->BC = BC;
+
+    return grad;
+}
+
+/*!
+ * \brief copy a N_gradient_3d structure
+ *
+ * \param source - the source N_gradient_3d struct
+ * \param target - the target N_gradient_3d struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int N_copy_gradient_3d(N_gradient_3d * source, N_gradient_3d * target)
+{
+    G_debug(5, "N_copy_gradient_3d: copy N_gradient_3d");
+
+    if (!source || !target)
+	return 0;
+
+    target->NC = source->NC;
+    target->SC = source->SC;
+    target->WC = source->WC;
+    target->EC = source->EC;
+    target->TC = source->TC;
+    target->BC = source->BC;
+
+    return 1;
+}
+
+
+/*!
+ * \brief Return a N_gradient_3d structure calculated from the input gradient field
+ * at position [depth][row][col]
+ *
+ *  This function returns the gradient of a 3d cell at position [depth][row][col] from the input gradient field.
+ *  Returned is a new structure of type N_gradient_3d.
+ *
+ *  \param field N_gradient_field_3d * - A three dimensional gradient field
+ *  \param gradient N_gradient_3d * - an existing gradient structure or a NULL pointer, if a NULL pointer is providet a new structure will be returned
+ *  \param col int
+ *  \param row int
+ *  \param depth int
+ *  \return N_gradient_3d *
+ *  
+ *
+ * */
+N_gradient_3d *N_get_gradient_3d(N_gradient_field_3d * field,
+				 N_gradient_3d * gradient, int col, int row,
+				 int depth)
+{
+    double NC, SC, WC, EC, TC, BC;
+    N_gradient_3d *grad = gradient;
+
+    NC = N_get_array_3d_d_value(field->y_array, col, row, depth);
+    SC = N_get_array_3d_d_value(field->y_array, col, row + 1, depth);
+    WC = N_get_array_3d_d_value(field->x_array, col, row, depth);
+    EC = N_get_array_3d_d_value(field->x_array, col + 1, row, depth);
+    BC = N_get_array_3d_d_value(field->z_array, col, row, depth);
+    TC = N_get_array_3d_d_value(field->z_array, col, row, depth + 1);
+
+    G_debug(6,
+	    "N_get_gradient_3d: calculate N_gradient_3d NC %g SC %g WC %g EC %g TC %g BC %g",
+	    NC, SC, WC, EC, TC, BC);
+
+    /*if gradient is a NULL pointer, create a new one */
+    if (!grad) {
+	grad = N_create_gradient_3d(NC, SC, WC, EC, TC, BC);
+    }
+    else {
+	grad->NC = NC;
+	grad->SC = SC;
+	grad->WC = WC;
+	grad->EC = EC;
+	grad->BC = BC;
+	grad->TC = TC;
+    }
+
+    return grad;
+}
+
+/*!
+ * \brief Allocate a N_gradient_neighbours_x structure
+ *
+ * This structure contains all neighbour gradients in x direction of one cell  
+ *
+ * \return N_gradient_neighbours_x  *
+ *
+ * */
+N_gradient_neighbours_x *N_alloc_gradient_neighbours_x(void)
+{
+    N_gradient_neighbours_x *grad;
+
+    grad =
+	(N_gradient_neighbours_x *) G_calloc(1,
+					     sizeof(N_gradient_neighbours_x));
+
+    return grad;
+}
+
+/*!
+ * \brief Free's a N_gradient_neighbours_x structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_neighbours_x(N_gradient_neighbours_x * grad)
+{
+    G_free(grad);
+    grad = NULL;
+
+    return;
+}
+
+
+/*!
+ * \brief Allocate and initialize a N_gradient_neighbours_x structure
+ *
+ * \param NWN double - the gradient between north-west and northern cell
+ * \param NEN double - the gradient between north-east and northern cell
+ * \param WC double - the gradient between western and center cell
+ * \param EC double - the gradient between eastern and center cell
+ * \param SWS double - the gradient between south-west and southern cell
+ * \param SES double - the gradient between south-east and southern cell
+ * \return N_gradient_neighbours_x *
+
+ *
+ * */
+N_gradient_neighbours_x *N_create_gradient_neighbours_x(double NWN,
+							double NEN, double WC,
+							double EC, double SWS,
+							double SES)
+{
+    N_gradient_neighbours_x *grad;
+
+    G_debug(6,
+	    "N_create_gradient_neighbours_x: create N_gradient_neighbours_x");
+
+    grad = N_alloc_gradient_neighbours_x();
+
+    grad->NWN = NWN;
+    grad->NEN = NEN;
+    grad->WC = WC;
+    grad->EC = EC;
+    grad->SWS = SWS;
+    grad->SES = SES;
+
+    return grad;
+}
+
+/*!
+ * \brief copy a N_gradient_neighbours_x structure
+ *
+ * \param source - the source N_gradient_neighbours_x struct
+ * \param target - the target N_gradient_neighbours_x struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int
+N_copy_gradient_neighbours_x(N_gradient_neighbours_x * source,
+			     N_gradient_neighbours_x * target)
+{
+    G_debug(6, "N_copy_gradient_neighbours_x: copy N_gradient_neighbours_x");
+
+    if (!source || !target)
+	return 0;
+
+    target->NWN = source->NWN;
+    target->NEN = source->NEN;
+    target->WC = source->WC;
+    target->EC = source->EC;
+    target->SWS = source->SWS;
+    target->SES = source->SES;
+
+    return 1;
+}
+
+/*!
+ * \brief Allocate a N_gradient_neighbours_y structure
+ *
+ * This structure contains all neighbour gradients in y direction of one cell  
+ *
+ * \return N_gradient_neighbours_y  *
+ *
+ * */
+N_gradient_neighbours_y *N_alloc_gradient_neighbours_y(void)
+{
+    N_gradient_neighbours_y *grad;
+
+    grad =
+	(N_gradient_neighbours_y *) G_calloc(1,
+					     sizeof(N_gradient_neighbours_y));
+
+    return grad;
+}
+
+/*!
+ * \brief Free's a N_gradient_neighbours_y structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_neighbours_y(N_gradient_neighbours_y * grad)
+{
+    G_free(grad);
+    grad = NULL;
+
+    return;
+}
+
+/*!
+ * \brief Allocate and initialize a N_gradient_neighbours_y structure
+ *
+ * \param NWW double - the gradient between north-west and western cell
+ * \param NEE double - the gradient between north-east and eastern cell
+ * \param NC double - the gradient between northern and center cell
+ * \param SC double - the gradient between southern and center cell
+ * \param SWW double - the gradient between south-west and western cell
+ * \param SEE double - the gradient between south-east and eastern cell
+ * \return N_gradient_neighbours_y *
+
+ *
+ * */
+N_gradient_neighbours_y *N_create_gradient_neighbours_y(double NWW,
+							double NEE, double NC,
+							double SC, double SWW,
+							double SEE)
+{
+    N_gradient_neighbours_y *grad;
+
+    G_debug(6,
+	    "N_create_gradient_neighbours_y: create N_gradient_neighbours_y");
+
+    grad = N_alloc_gradient_neighbours_y();
+
+    grad->NWW = NWW;
+    grad->NEE = NEE;
+    grad->NC = NC;
+    grad->SC = SC;
+    grad->SWW = SWW;
+    grad->SEE = SEE;
+
+    return grad;
+}
+
+/*!
+ * \brief copy a N_gradient_neighbours_y structure
+ *
+ * \param source - the source N_gradient_neighbours_y struct
+ * \param target - the target N_gradient_neighbours_y struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int
+N_copy_gradient_neighbours_y(N_gradient_neighbours_y * source,
+			     N_gradient_neighbours_y * target)
+{
+    G_debug(6, "N_copy_gradient_neighbours_y: copy N_gradient_neighbours_y");
+
+    if (!source || !target)
+	return 0;
+
+    target->NWW = source->NWW;
+    target->NEE = source->NEE;
+    target->NC = source->NC;
+    target->SC = source->SC;
+    target->SWW = source->SWW;
+    target->SEE = source->SEE;
+
+    return 1;
+}
+
+/*!
+ * \brief Allocate a N_gradient_neighbours_z structure
+ *
+ * This structure contains all neighbour gradients in z direction of one cell  
+ *
+ * \return N_gradient_neighbours_z  *
+ *
+ * */
+N_gradient_neighbours_z *N_alloc_gradient_neighbours_z(void)
+{
+    N_gradient_neighbours_z *grad;
+
+    grad =
+	(N_gradient_neighbours_z *) G_calloc(1,
+					     sizeof(N_gradient_neighbours_z));
+
+    return grad;
+}
+
+/*!
+ * \brief Free's a N_gradient_neighbours_z structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_neighbours_z(N_gradient_neighbours_z * grad)
+{
+    G_free(grad);
+    grad = NULL;
+
+    return;
+}
+
+/*!
+ * \brief Allocate and initialize a N_gradient_neighbours_z structure
+ *
+ * \param NWZ double - the gradient between upper and lower north-western cells
+ * \param NZ double - the gradient between upper and lower northern cells
+ * \param NEZ double - the gradient between upper and lower north-eastern cells
+ * \param WZ double - the gradient between upper and lower western cells
+ * \param CZ double - the gradient between upper and lower center cells
+ * \param EZ double - the gradient between upper and lower eastern cells
+ * \param SWZ double - the gradient between upper and lower south-western cells
+ * \param SZ double - the gradient between upper and lower southern cells
+ * \param SEZ double - the gradient between upper and lower south-eastern cells
+ * \return N_gradient_neighbours_z *
+
+ *
+ * */
+N_gradient_neighbours_z *N_create_gradient_neighbours_z(double NWZ, double NZ,
+							double NEZ, double WZ,
+							double CZ, double EZ,
+							double SWZ, double SZ,
+							double SEZ)
+{
+    N_gradient_neighbours_z *grad;
+
+    G_debug(6,
+	    "N_create_gradient_neighbours_z: create N_gradient_neighbours_z");
+
+    grad = N_alloc_gradient_neighbours_z();
+
+    grad->NWZ = NWZ;
+    grad->NZ = NZ;
+    grad->NEZ = NEZ;
+    grad->WZ = WZ;
+    grad->CZ = CZ;
+    grad->EZ = EZ;
+    grad->SWZ = SWZ;
+    grad->SZ = SZ;
+    grad->SEZ = SEZ;
+
+    return grad;
+}
+
+/*!
+ * \brief copy a N_gradient_neighbours_z structure
+ *
+ * \param source - the source N_gradient_neighbours_z struct
+ * \param target - the target N_gradient_neighbours_z struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int
+N_copy_gradient_neighbours_z(N_gradient_neighbours_z * source,
+			     N_gradient_neighbours_z * target)
+{
+    G_debug(6, "N_copy_gradient_neighbours_z: copy N_gradient_neighbours_z");
+
+    if (!source || !target)
+	return 0;
+
+    target->NWZ = source->NWZ;
+    target->NZ = source->NZ;
+    target->NEZ = source->NEZ;
+    target->WZ = source->WZ;
+    target->CZ = source->CZ;
+    target->EZ = source->EZ;
+    target->SWZ = source->SWZ;
+    target->SZ = source->SZ;
+    target->SEZ = source->SEZ;
+
+    return 1;
+}
+
+/*!
+ * \brief Allocate a N_gradient_neighbours_2d structure
+ *
+ * This structure contains all neighbour gradients in all directions of one cell 
+ * in a 2d raster layer
+ *
+ * \return N_gradient_neighbours_2d *
+ *
+ * */
+N_gradient_neighbours_2d *N_alloc_gradient_neighbours_2d(void)
+{
+    N_gradient_neighbours_2d *grad;
+
+    grad =
+	(N_gradient_neighbours_2d *) G_calloc(1,
+					      sizeof
+					      (N_gradient_neighbours_2d));
+
+    grad->x = N_alloc_gradient_neighbours_x();
+    grad->y = N_alloc_gradient_neighbours_y();
+
+    return grad;
+}
+
+/*!
+ * \brief Free's a N_gradient_neighbours_2d structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_neighbours_2d(N_gradient_neighbours_2d * grad)
+{
+
+    N_free_gradient_neighbours_x(grad->x);
+    N_free_gradient_neighbours_y(grad->y);
+
+    G_free(grad);
+    grad = NULL;
+
+    return;
+}
+
+/*!
+ * \brief Allocate and initialize a N_gradient_neighbours_2d structure
+ *
+ * The parameter N_gradient_neighbours x and y are copied into the new allocated structure 
+ * and can be deleted after the initializing
+ *
+ * \return N_gradient_neighbours_2d * -- if failure NULL is returned
+ *
+ * */
+N_gradient_neighbours_2d
+    * N_create_gradient_neighbours_2d(N_gradient_neighbours_x * x,
+				      N_gradient_neighbours_y * y)
+{
+    N_gradient_neighbours_2d *grad;
+    int fail = 0;
+
+    G_debug(5,
+	    "N_create_gradient_neighbours_2d: create N_gradient_neighbours_2d");
+
+    grad = N_alloc_gradient_neighbours_2d();
+
+    if (!N_copy_gradient_neighbours_x(x, grad->x))
+	fail++;
+    if (!N_copy_gradient_neighbours_y(y, grad->y))
+	fail++;
+
+    if (fail > 0) {
+	N_free_gradient_neighbours_2d(grad);
+	grad = NULL;
+    }
+
+    return grad;
+}
+
+/*!
+ * \brief copy a N_gradient_neighbours_2d structure
+ *
+ * \param source - the source N_gradient_neighbours_2d struct
+ * \param target - the target N_gradient_neighbours_2d struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int
+N_copy_gradient_neighbours_2d(N_gradient_neighbours_2d * source,
+			      N_gradient_neighbours_2d * target)
+{
+    int fail = 0;
+
+    G_debug(5,
+	    "N_copy_gradient_neighbours_2d: copy N_gradient_neighbours_2d");
+
+    if (!source || !target)
+	return 0;
+
+    if (!(N_copy_gradient_neighbours_x(source->x, target->x)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_y(source->y, target->y)))
+	fail++;
+
+    if (fail > 0) {
+	return 0;
+    }
+
+    return 1;
+}
+
+/*!
+ * \brief Return a N_gradient_neighbours_2d structure calculated from the input gradient field
+ * at position [row][col]
+ *
+ *  This function returns the gradient neighbours in x and y dierection 
+ *  of a cell at position [row][col] from the input gradient field.
+ *  Returend is a pointer to a structure of type N_gradient_neighbours_2d.
+ *
+ *  \param field N_gradient_field_2d * - A two dimensional gradient field
+ *  \param gradient N_gradient_neighbours_2d * - the gradient structure which should be filled with data, if a NULL pointer is given, a new structure will be created
+ *  \param col int
+ *  \param row int
+ *  \return N_gradient_neighbours_2d * - the new or filled gradient structure
+ *  
+ *
+ * */
+N_gradient_neighbours_2d *N_get_gradient_neighbours_2d(N_gradient_field_2d *
+						       field,
+						       N_gradient_neighbours_2d
+						       * gradient, int col,
+						       int row)
+{
+    double NWN, NEN, WC, EC, SWS, SES;
+    double NWW, NEE, NC, SC, SWW, SEE;
+    N_gradient_neighbours_2d *grad = NULL;
+    N_gradient_neighbours_x *grad_x = NULL;
+    N_gradient_neighbours_y *grad_y = NULL;
+
+
+    NWN = N_get_array_2d_d_value(field->x_array, col, row - 1);
+    NEN = N_get_array_2d_d_value(field->x_array, col + 1, row - 1);
+    WC = N_get_array_2d_d_value(field->x_array, col, row);
+    EC = N_get_array_2d_d_value(field->x_array, col + 1, row);
+    SWS = N_get_array_2d_d_value(field->x_array, col, row + 1);
+    SES = N_get_array_2d_d_value(field->x_array, col + 1, row + 1);
+
+    NWW = N_get_array_2d_d_value(field->y_array, col - 1, row);
+    NEE = N_get_array_2d_d_value(field->y_array, col + 1, row);
+    NC = N_get_array_2d_d_value(field->y_array, col, row);
+    SC = N_get_array_2d_d_value(field->y_array, col, row + 1);
+    SWW = N_get_array_2d_d_value(field->y_array, col - 1, row + 1);
+    SEE = N_get_array_2d_d_value(field->y_array, col + 1, row + 1);
+
+
+    grad_x = N_create_gradient_neighbours_x(NWN, NEN, WC, EC, SWS, SES);
+    grad_y = N_create_gradient_neighbours_y(NWW, NEE, NC, SC, SWW, SEE);
+
+    G_debug(5,
+	    "N_get_gradient_neighbours_2d: calculate N_gradient_neighbours_x NWN %g NEN %g WC %g EC %g SWS %g SES %g",
+	    NWN, NEN, WC, EC, SWS, SES);
+
+    G_debug(5,
+	    "N_get_gradient_neighbours_2d: calculate N_gradient_neighbours_y NWW %g NEE %g NC %g SC %g SWW %g SEE %g",
+	    NWW, NEE, NC, SC, SWW, SEE);
+
+
+    /*if gradient is a NULL pointer, create a new one */
+    if (!gradient) {
+	grad = N_create_gradient_neighbours_2d(grad_x, grad_y);
+	gradient = grad;
+    }
+    else {
+	grad = N_create_gradient_neighbours_2d(grad_x, grad_y);
+	N_copy_gradient_neighbours_2d(grad, gradient);
+	N_free_gradient_neighbours_2d(grad);
+    }
+
+    N_free_gradient_neighbours_x(grad_x);
+    N_free_gradient_neighbours_y(grad_y);
+
+    return gradient;
+}
+
+
+/*!
+ * \brief Allocate a N_gradient_neighbours_3d structure
+ *
+ * This structure contains all neighbour gradients in all directions of one cell 
+ * in a 3d raster layer
+ *
+ * \return N_gradient_neighbours_3d *
+ *
+ * */
+N_gradient_neighbours_3d *N_alloc_gradient_neighbours_3d(void)
+{
+    N_gradient_neighbours_3d *grad;
+
+    grad =
+	(N_gradient_neighbours_3d *) G_calloc(1,
+					      sizeof
+					      (N_gradient_neighbours_3d));
+
+    grad->xt = N_alloc_gradient_neighbours_x();
+    grad->xc = N_alloc_gradient_neighbours_x();
+    grad->xb = N_alloc_gradient_neighbours_x();
+    grad->yt = N_alloc_gradient_neighbours_y();
+    grad->yc = N_alloc_gradient_neighbours_y();
+    grad->yb = N_alloc_gradient_neighbours_y();
+    grad->zt = N_alloc_gradient_neighbours_z();
+    grad->zb = N_alloc_gradient_neighbours_z();
+
+    return grad;
+}
+
+/*!
+ * \brief Free's a N_gradient_neighbours_3d structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_neighbours_3d(N_gradient_neighbours_3d * grad)
+{
+
+    N_free_gradient_neighbours_x(grad->xt);
+    N_free_gradient_neighbours_x(grad->xc);
+    N_free_gradient_neighbours_x(grad->xb);
+    N_free_gradient_neighbours_y(grad->yt);
+    N_free_gradient_neighbours_y(grad->yc);
+    N_free_gradient_neighbours_y(grad->yb);
+    N_free_gradient_neighbours_z(grad->zt);
+    N_free_gradient_neighbours_z(grad->zb);
+
+    G_free(grad);
+    grad = NULL;
+
+    return;
+}
+
+/*!
+ * \brief Allocate and initialize a N_gradient_neighbours_3d structure
+ *
+ * The parameter N_gradient_neighbours x(tcb) and y(tcb) and z(tb) are copied into the new allocated structure 
+ * and can be deleted after the initializing
+ *
+ * \return N_gradient_neighbours_3d * -- if failure NULL is returned
+
+ *
+ * */
+N_gradient_neighbours_3d
+    * N_create_gradient_neighbours_3d(N_gradient_neighbours_x * xt,
+				      N_gradient_neighbours_x * xc,
+				      N_gradient_neighbours_x * xb,
+				      N_gradient_neighbours_y * yt,
+				      N_gradient_neighbours_y * yc,
+				      N_gradient_neighbours_y * yb,
+				      N_gradient_neighbours_z * zt,
+				      N_gradient_neighbours_z * zb)
+{
+    N_gradient_neighbours_3d *grad;
+    int fail = 0;
+
+    G_debug(5,
+	    "N_create_gradient_neighbours_3d: create N_gradient_neighbours_3d");
+
+    grad = N_alloc_gradient_neighbours_3d();
+
+    if (!(N_copy_gradient_neighbours_x(xt, grad->xt)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_x(xc, grad->xc)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_x(xb, grad->xb)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_y(yt, grad->yt)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_y(yc, grad->yc)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_y(yb, grad->yb)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_z(zt, grad->zt)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_z(zb, grad->zb)))
+	fail++;
+
+    if (fail > 0) {
+	return NULL;
+    }
+
+    return grad;
+}
+
+/*!
+ * \brief copy a N_gradient_neighbours_3d structure
+ *
+ * \param source - the source N_gradient_neighbours_3d struct
+ * \param target - the target N_gradient_neighbours_3d struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int
+N_copy_gradient_neighbours_3d(N_gradient_neighbours_3d * source,
+			      N_gradient_neighbours_3d * target)
+{
+    int fail = 0;
+
+    G_debug(5,
+	    "N_copy_gradient_neighbours_3d: copy N_gradient_neighbours_3d");
+
+    if (!source || !target)
+	return 0;
+
+    if (!(N_copy_gradient_neighbours_x(source->xt, target->xt)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_x(source->xc, target->xc)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_x(source->xb, target->xb)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_y(source->yt, target->yt)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_y(source->yc, target->yc)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_y(source->yb, target->yb)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_z(source->zt, target->zt)))
+	fail++;
+    if (!(N_copy_gradient_neighbours_z(source->zb, target->zb)))
+	fail++;
+
+    if (fail > 0) {
+	return 0;
+    }
+
+    return 1;
+}
+
+/*!
+ * \brief Allocate a N_gradient_field_2d
+ *
+ * The field arrays are of type DCELL. 
+ *
+ * \param rows - number of rows of the 2d array from which the gradient should be calculated
+ * \param cols - number of cols of the 2d array from which the gradient should be calculated
+ * \return N_gradient_field_2d *
+ *
+ * */
+N_gradient_field_2d *N_alloc_gradient_field_2d(int cols, int rows)
+{
+    N_gradient_field_2d *field;
+
+    G_debug(5,
+	    "N_alloc_gradient_field_2d: allocate a N_gradient_field_2d struct");
+
+    field = (N_gradient_field_2d *) G_calloc(1, sizeof(N_gradient_field_2d));
+
+    field->x_array = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    field->y_array = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+
+    field->cols = cols;
+    field->rows = rows;
+
+    return field;
+}
+
+/*!
+ * \brief Free's a N_gradient_neighbours_2d structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_field_2d(N_gradient_field_2d * field)
+{
+
+    N_free_array_2d(field->x_array);
+    N_free_array_2d(field->y_array);
+
+    G_free(field);
+
+    field = NULL;
+
+    return;
+}
+
+/*!
+ * \brief Copy N_gradient_field_2d structure from source to target
+ *
+ * \param source - the source N_gradient_field_2d struct
+ * \param target - the target N_gradient_field_2d struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int
+N_copy_gradient_field_2d(N_gradient_field_2d * source,
+			 N_gradient_field_2d * target)
+{
+    G_debug(3, "N_copy_gradient_field_2d: copy N_gradient_field_2d");
+
+    if (!source || !target)
+	return 0;
+
+    N_copy_array_2d(source->x_array, target->x_array);
+    N_copy_array_2d(source->y_array, target->y_array);
+
+    return 1;
+}
+
+/*! \brief Print gradient field information to stdout
+ *
+ * \param field N_gradient_2d_field *
+ * \return void
+ *
+ * */
+void N_print_gradient_field_2d_info(N_gradient_field_2d * field)
+{
+    fprintf(stdout, "N_gradient_field_2d \n");
+    fprintf(stdout, "Cols %i\n", field->cols);
+    fprintf(stdout, "Rows: %i\n", field->rows);
+    fprintf(stdout, "X array pointer: %p\n", field->x_array);
+    fprintf(stdout, "Y array pointer: %p\n", field->y_array);
+    fprintf(stdout, "Min %g\n", field->min);
+    fprintf(stdout, "Max %g\n", field->max);
+    fprintf(stdout, "Sum %g\n", field->sum);
+    fprintf(stdout, "Mean %g\n", field->mean);
+    fprintf(stdout, "Nonull %i\n", field->nonull);
+    fprintf(stdout, "X array info \n");
+    N_print_array_2d_info(field->x_array);
+    fprintf(stdout, "Y array info \n");
+    N_print_array_2d_info(field->y_array);
+
+    return;
+}
+
+
+/*!
+ * \brief Allocate a N_gradient_field_3d
+ *
+ * The field arrays are always of type DCELL_TYPE. 
+ *
+ * \param cols - number of cols of the 3d array from which the gradient should be calculated
+ * \param rows - number of rows of the 3d array from which the gradient should be calculated
+ * \param depths - number of depths of the 3d array from which the gradient should be calculated
+ * \return N_gradient_field_3d *
+ *
+ * */
+N_gradient_field_3d *N_alloc_gradient_field_3d(int cols, int rows, int depths)
+{
+    N_gradient_field_3d *field;
+
+    G_debug(5,
+	    "N_alloc_gradient_field_3d: allocate a N_gradient_field_3d struct");
+
+    field = (N_gradient_field_3d *) G_calloc(1, sizeof(N_gradient_field_3d));
+
+    field->x_array = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    field->y_array = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    field->z_array = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+
+    field->cols = cols;
+    field->rows = rows;
+    field->depths = depths;
+
+    return field;
+}
+
+
+/*!
+ * \brief Free's a N_gradient_neighbours_3d structure
+ *
+ * \return void
+ *
+ * */
+void N_free_gradient_field_3d(N_gradient_field_3d * field)
+{
+
+    N_free_array_3d(field->x_array);
+    N_free_array_3d(field->y_array);
+    N_free_array_3d(field->z_array);
+
+    G_free(field);
+
+    field = NULL;
+
+    return;
+}
+
+
+/*!
+ * \brief Copy N_gradient_field_3d structure from source to target
+ *
+ * \param source - the source N_gradient_field_3d struct
+ * \param target - the target N_gradient_field_3d struct
+ * \return int - 1 success, 0 failure while copying
+ *
+ * */
+int
+N_copy_gradient_field_3d(N_gradient_field_3d * source,
+			 N_gradient_field_3d * target)
+{
+    G_debug(3, "N_copy_gradient_field_3d: copy N_gradient_field_3d");
+
+    if (!source || !target)
+	return 0;
+
+    N_copy_array_3d(source->x_array, target->x_array);
+    N_copy_array_3d(source->y_array, target->y_array);
+    N_copy_array_3d(source->z_array, target->z_array);
+
+    return 1;
+}
+
+/*! \brief Print gradient field information to stdout
+ *
+ * \param field N_gradient_3d_field *
+ * \return void
+ *
+ * */
+void N_print_gradient_field_3d_info(N_gradient_field_3d * field)
+{
+
+    fprintf(stdout, "N_gradient_field_3d \n");
+    fprintf(stdout, "Cols %i\n", field->cols);
+    fprintf(stdout, "Rows: %i\n", field->rows);
+    fprintf(stdout, "Depths %i\n", field->depths);
+    fprintf(stdout, "X array pointer: %p\n", field->x_array);
+    fprintf(stdout, "Y array pointer: %p\n", field->y_array);
+    fprintf(stdout, "Z array pointer: %p\n", field->z_array);
+    fprintf(stdout, "Min %g\n", field->min);
+    fprintf(stdout, "Max %g\n", field->max);
+    fprintf(stdout, "Sum %g\n", field->sum);
+    fprintf(stdout, "Mean %g\n", field->mean);
+    fprintf(stdout, "Nonull %i\n", field->nonull);
+    fprintf(stdout, "X array info \n");
+    N_print_array_3d_info(field->x_array);
+    fprintf(stdout, "Y array info \n");
+    N_print_array_3d_info(field->y_array);
+    fprintf(stdout, "Z array info \n");
+    N_print_array_3d_info(field->z_array);
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_gradient_calc.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_gradient_calc.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_gradient_calc.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_gradient_calc.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,657 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:     	gradient management functions 
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+
+/*! \brief Calculate basic statistics of a gradient field
+ *
+ * The statistic is stored in the gradient field struct
+ *
+ * \param field N_gradient_2d_field *
+ * \return void
+ *
+ * */
+void N_calc_gradient_field_2d_stats(N_gradient_field_2d * field)
+{
+    double minx, miny;
+    double maxx, maxy;
+    double sumx, sumy;
+    int nonullx, nonully;
+
+    G_debug(3,
+	    "N_calc_gradient_field_2d_stats: compute gradient field stats");
+
+    N_calc_array_2d_stats(field->x_array, &minx, &maxx, &sumx, &nonullx, 0);
+    N_calc_array_2d_stats(field->y_array, &miny, &maxy, &sumy, &nonully, 0);
+
+    if (minx < miny)
+	field->min = minx;
+    else
+	field->min = miny;
+
+    if (maxx > maxy)
+	field->max = maxx;
+    else
+	field->max = maxy;
+
+    field->sum = sumx + sumy;
+    field->nonull = nonullx + nonully;
+    field->mean = field->sum / (double)field->nonull;
+
+    return;
+}
+
+/*!
+ * \brief This function computes the gradient based on the input N_array_2d pot
+ * (potential), a weighting factor N_array_2d named weight and the distance between two cells 
+ * saved in the N_geom_data struct.
+ *
+ * The gradient is calculated between cells for each cell and direction.
+ * An existing gradient field can be filled with new data or, if a NULL pointer is
+ * given, a new gradient field will be allocated with the appropriate size.
+ *
+ *
+ \verbatim
+ ______________ 
+ |    |    |    |
+ |    |    |    |
+ |----|-NC-|----|
+ |    |    |    |
+ |   WC    EC   |
+ |    |    |    |
+ |----|-SC-|----|
+ |    |    |    |
+ |____|____|____|
+
+
+ x - direction:
+
+ r = 2 * weight[row][col]*weight[row][col + 1] / (weight[row][col]*weight[row][col + 1])
+ EC = r * (pot[row][col] - pot[row][col + 1])/dx
+
+ y - direction:
+
+ r = 2 * weight[row][col]*weight[row + 1][col] / (weight[row][col]*weight[row + 1][col])
+ SC = r * (pot[row][col] - pot[row + 1][col])/dy
+
+ the values SC and EC are the values of the next row/col
+
+
+ \endverbatim
+ * \param pot N_array_2d * - the potential N_array_2d 
+ * \param weight_x N_array_2d * - the weighting factor N_array_2d used to modify the gradient in x-direction
+ * \param weight_y N_array_2d * - the weighting factor N_array_2d used to modify the gradient in y-direction
+ * \param geom N_geom_data * - geometry data structure
+ * \param gradfield N_gradient_field_2d * - a gradient field of the correct size, if a NULL pointer is provided this gradient field will be new allocated
+ * \return N_gradient_field_2d * - the pointer to the computed gradient field
+
+ *
+ * */
+N_gradient_field_2d *N_compute_gradient_field_2d(N_array_2d * pot,
+						 N_array_2d * weight_x,
+						 N_array_2d * weight_y,
+						 N_geom_data * geom,
+						 N_gradient_field_2d *
+						 gradfield)
+{
+    int i, j;
+    int rows, cols;
+    double dx, dy, p1, p2, r1, r2, mean, grad, res;
+    N_gradient_field_2d *field = gradfield;
+
+
+    if (pot->cols != weight_x->cols || pot->cols != weight_y->cols)
+	G_fatal_error
+	    ("N_compute_gradient_field_2d: the arrays are not of equal size");
+
+    if (pot->rows != weight_x->rows || pot->rows != weight_y->rows)
+	G_fatal_error
+	    ("N_compute_gradient_field_2d: the arrays are not of equal size");
+
+    if (pot->cols != geom->cols || pot->rows != geom->rows)
+	G_fatal_error
+	    ("N_compute_gradient_field_2d: array sizes and geometry data are different");
+
+
+    G_debug(3, "N_compute_gradient_field_2d: compute gradient field");
+
+    rows = pot->rows;
+    cols = pot->cols;
+    dx = geom->dx;
+    dy = geom->dy;
+
+    if (field == NULL) {
+	field = N_alloc_gradient_field_2d(cols, rows);
+    }
+    else {
+	if (field->cols != geom->cols || field->rows != geom->rows)
+	    G_fatal_error
+		("N_compute_gradient_field_2d: gradient field sizes and geometry data are different");
+    }
+
+
+    for (j = 0; j < rows; j++)
+	for (i = 0; i < cols - 1; i++) {
+	    grad = 0;
+	    mean = 0;
+
+	    /* Only compute if the arrays are not null */
+	    if (!N_is_array_2d_value_null(pot, i, j) &&
+		!N_is_array_2d_value_null(pot, i + 1, j)) {
+		p1 = N_get_array_2d_d_value(pot, i, j);
+		p2 = N_get_array_2d_d_value(pot, i + 1, j);
+		grad = (p1 - p2) / dx;	/* gradient */
+	    }
+	    if (!N_is_array_2d_value_null(weight_x, i, j) &&
+		!N_is_array_2d_value_null(weight_x, i + 1, j)) {
+		r1 = N_get_array_2d_d_value(weight_x, i, j);
+		r2 = N_get_array_2d_d_value(weight_x, i + 1, j);
+		mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
+	    }
+
+	    res = mean * grad;
+
+	    N_put_array_2d_d_value(field->x_array, i + 1, j, res);
+
+	}
+
+    for (j = 0; j < rows - 1; j++)
+	for (i = 0; i < cols; i++) {
+	    grad = 0;
+	    mean = 0;
+
+	    /* Only compute if the arrays are not null */
+	    if (!N_is_array_2d_value_null(pot, i, j) &&
+		!N_is_array_2d_value_null(pot, i, j + 1)) {
+		p1 = N_get_array_2d_d_value(pot, i, j);
+		p2 = N_get_array_2d_d_value(pot, i, j + 1);
+		grad = (p1 - p2) / dy;	/* gradient */
+	    }
+	    if (!N_is_array_2d_value_null(weight_y, i, j) &&
+		!N_is_array_2d_value_null(weight_y, i, j + 1)) {
+		r1 = N_get_array_2d_d_value(weight_y, i, j);
+		r2 = N_get_array_2d_d_value(weight_y, i, j + 1);
+		mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
+	    }
+
+	    res = -1 * mean * grad;
+
+	    N_put_array_2d_d_value(field->y_array, i, j + 1, res);
+
+	}
+
+    /*Compute gradient field statistics */
+    N_calc_gradient_field_2d_stats(field);
+
+    return field;
+}
+
+/*! 
+ * \brief Calculate the x and y vector components from a gradient field for each 
+ * cell and stores them in the provided N_array_2d structures
+ *
+ * The arrays must have the same size as the gradient field.
+
+ \verbatim
+
+ Based on this storages scheme the gradient vector for each cell is 
+ calculated and stored in the provided  N_array_2d structures
+
+ ______________ 
+ |    |    |    |
+ |    |    |    |
+ |----|-NC-|----|
+ |    |    |    |
+ |   WC    EC   |
+ |    |    |    |
+ |----|-SC-|----|
+ |    |    |    |
+ |____|____|____|
+
+ x vector component:
+
+ x = (WC + EC) / 2
+
+ y vector component:
+
+ y = (NC + SC) / 2
+
+ \endverbatim
+ *
+ * \param field N_gradient_field_2d *
+ * \param x_comp N_array_2d * - the array in which the x component will be written
+ * \param y_comp N_array_2d * - the array in which the y component will be written
+ *
+ * \return void
+ * */
+void
+N_compute_gradient_field_components_2d(N_gradient_field_2d * field,
+				       N_array_2d * x_comp,
+				       N_array_2d * y_comp)
+{
+    int i, j;
+
+    int rows, cols;
+
+    double vx, vy;
+
+    N_array_2d *x = x_comp;
+
+    N_array_2d *y = y_comp;
+
+    N_gradient_2d grad;
+
+
+    if (!x)
+	G_fatal_error("N_compute_gradient_components_2d: x array is empty");
+    if (!y)
+	G_fatal_error("N_compute_gradient_components_2d: y array is empty");
+
+    cols = field->x_array->cols;
+    rows = field->x_array->rows;
+
+    /*Check the array sizes */
+    if (x->cols != cols || x->rows != rows)
+	G_fatal_error
+	    ("N_compute_gradient_components_2d: the size of the x array doesn't fit the gradient field size");
+    if (y->cols != cols || y->rows != rows)
+	G_fatal_error
+	    ("N_compute_gradient_components_2d: the size of the y array doesn't fit the gradient field size");
+
+    for (j = 0; j < rows; j++)
+	for (i = 0; i < cols; i++) {
+	    N_get_gradient_2d(field, &grad, i, j);
+
+	    /* in case a gradient is zero, we expect a no flow boundary */
+	    if (grad.WC == 0.0 || grad.EC == 0.0)
+		vx = (grad.WC + grad.EC);
+	    else
+		vx = (grad.WC + grad.EC) / 2;
+	    if (grad.NC == 0.0 || grad.SC == 0.0)
+		vy = (grad.NC + grad.SC);
+	    else
+		vy = (grad.NC + grad.SC) / 2;
+
+	    N_put_array_2d_d_value(x, i, j, vx);
+	    N_put_array_2d_d_value(y, i, j, vy);
+	}
+
+    return;
+}
+
+/*! \brief Calculate basic statistics of a gradient field
+ *
+ * The statistic is stored in the gradient field struct
+ *
+ * \param field N_gradient_3d_field *
+ * \return void
+ *
+ * */
+void N_calc_gradient_field_3d_stats(N_gradient_field_3d * field)
+{
+    double minx, miny, minz;
+
+    double maxx, maxy, maxz;
+
+    double sumx, sumy, sumz;
+
+    int nonullx, nonully, nonullz;
+
+    G_debug(3,
+	    "N_calc_gradient_field_3d_stats: compute gradient field stats");
+
+    N_calc_array_3d_stats(field->x_array, &minx, &maxx, &sumx, &nonullx, 0);
+    N_calc_array_3d_stats(field->y_array, &miny, &maxy, &sumy, &nonully, 0);
+    N_calc_array_3d_stats(field->z_array, &minz, &maxz, &sumz, &nonullz, 0);
+
+    if (minx <= minz && minx <= miny)
+	field->min = minx;
+    if (miny <= minz && miny <= minx)
+	field->min = miny;
+    if (minz <= minx && minz <= miny)
+	field->min = minz;
+
+    if (maxx >= maxz && maxx >= maxy)
+	field->max = maxx;
+    if (maxy >= maxz && maxy >= maxx)
+	field->max = maxy;
+    if (maxz >= maxx && maxz >= maxy)
+	field->max = maxz;
+
+    field->sum = sumx + sumy + sumz;
+    field->nonull = nonullx + nonully + nonullz;
+    field->mean = field->sum / (double)field->nonull;
+
+    return;
+}
+
+
+/*!
+ * \brief This function computes the gradient based on the input N_array_3d pot
+ * (that means potential), a weighting factor N_array_3d named weight and the distance between two cells 
+ * saved in the N_geom_data struct.
+ *
+ * The gradient is calculated between cells for each cell and direction.
+ * An existing gradient field can be filled with new data or, if a NULL pointer is
+ * given, a new gradient field will be allocated with the appropriate size.
+ *
+ *
+ *
+ *
+ \verbatim
+
+ |  /
+ TC NC
+ |/
+ --WC-----EC--
+ /|
+ SC BC
+ /  |
+
+ x - direction:
+
+ r = 2 * weight_x[depth][row][col]*weight_x[depth][row][col + 1] / (weight_X[depth][row][col]*weight_x[depth][row][col + 1])
+ EC = r * (pot[depth][row][col] - pot[depth][row][col + 1])/dx
+
+ y - direction:
+
+ r = 2 * weight_y[depth][row][col]*weight_y[depth][row + 1][col] / (weight_y[depth][row][col]*weight_y[depth][row + 1][col])
+ SC = r * (pot[depth][row][col] - pot[depth][row + 1][col])/dy
+
+ z - direction:
+
+ r = 2 * weight_z[depth][row][col]*weight_z[depth + 1][row][col] / (weight_z[depth][row][col]*weight_z[depth + 1][row][col])
+ TC = r * (pot[depth][row][col] - pot[depth + 1][row][col])/dy
+
+ the values BC, NC, WC are the values of the next depth/row/col
+
+
+ \endverbatim
+ * \param pot N_array_3d * - the potential N_array_2d 
+ * \param weight_x N_array_3d * - the weighting factor N_array_3d used to modify the gradient in x-direction
+ * \param weight_y N_array_3d * - the weighting factor N_array_3d used to modify the gradient in y-direction
+ * \param weight_z N_array_3d * - the weighting factor N_array_3d used to modify the gradient in z-direction
+ * \param geom N_geom_data * - geometry data structure
+ * \param gradfield N_gradient_field_3d * - a gradient field of the correct size, if a NULL pointer is provided this gradient field will be new allocated
+ * \return N_gradient_field_3d * - the pointer to the computed gradient field
+ *
+ * */
+N_gradient_field_3d *N_compute_gradient_field_3d(N_array_3d * pot,
+						 N_array_3d * weight_x,
+						 N_array_3d * weight_y,
+						 N_array_3d * weight_z,
+						 N_geom_data * geom,
+						 N_gradient_field_3d *
+						 gradfield)
+{
+    int i, j, k;
+
+    int cols, rows, depths;
+
+    double dx, dy, dz, p1, p2, r1, r2, mean, grad, res;
+
+    N_gradient_field_3d *field = gradfield;
+
+
+    if (pot->cols != weight_x->cols || pot->cols != weight_y->cols ||
+	pot->cols != weight_z->cols)
+	G_fatal_error
+	    ("N_compute_gradient_field_3d: the arrays are not of equal size");
+
+    if (pot->rows != weight_x->rows || pot->rows != weight_y->rows ||
+	pot->rows != weight_z->rows)
+	G_fatal_error
+	    ("N_compute_gradient_field_3d: the arrays are not of equal size");
+
+    if (pot->depths != weight_x->depths || pot->depths != weight_y->depths ||
+	pot->depths != weight_z->depths)
+	G_fatal_error
+	    ("N_compute_gradient_field_3d: the arrays are not of equal size");
+
+    if (pot->cols != geom->cols || pot->rows != geom->rows ||
+	pot->depths != geom->depths)
+	G_fatal_error
+	    ("N_compute_gradient_field_3d: array sizes and geometry data are different");
+
+    G_debug(3, "N_compute_gradient_field_3d: compute gradient field");
+
+    cols = geom->cols;
+    rows = geom->rows;
+    depths = geom->depths;
+    dx = geom->dx;
+    dy = geom->dy;
+    dz = geom->dz;
+
+    if (gradfield == NULL) {
+	field = N_alloc_gradient_field_3d(cols, rows, depths);
+    }
+    else {
+	if (field->cols != geom->cols || field->rows != geom->rows ||
+	    field->depths != geom->depths)
+	    G_fatal_error
+		("N_compute_gradient_field_3d: gradient field sizes and geometry data are different");
+    }
+
+    for (k = 0; k < depths; k++)
+	for (j = 0; j < rows; j++)
+	    for (i = 0; i < cols - 1; i++) {
+		grad = 0;
+		mean = 0;
+
+		/*Only compute if the arrays are not null */
+		if (!N_is_array_3d_value_null(pot, i, j, k) &&
+		    !N_is_array_3d_value_null(pot, i + 1, j, k)) {
+		    p1 = N_get_array_3d_d_value(pot, i, j, k);
+		    p2 = N_get_array_3d_d_value(pot, i + 1, j, k);
+		    grad = (p1 - p2) / dx;	/* gradient */
+		}
+		if (!N_is_array_3d_value_null(weight_x, i, j, k) &&
+		    !N_is_array_3d_value_null(weight_x, i + 1, j, k)) {
+		    r1 = N_get_array_3d_d_value(weight_x, i, j, k);
+		    r2 = N_get_array_3d_d_value(weight_x, i + 1, j, k);
+		    mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
+		}
+
+		res = mean * grad;
+
+		G_debug(6,
+			"N_compute_gradient_field_3d: X-direction insert value %6.5g at %i %i %i ",
+			res, k, j, i + 1);
+
+		N_put_array_3d_d_value(field->x_array, i + 1, j, k, res);
+
+	    }
+
+    for (k = 0; k < depths; k++)
+	for (j = 0; j < rows - 1; j++)
+	    for (i = 0; i < cols; i++) {
+		grad = 0;
+		mean = 0;
+
+		/* Only compute if the arrays are not null */
+		if (!N_is_array_3d_value_null(pot, i, j, k) &&
+		    !N_is_array_3d_value_null(pot, i, j + 1, k)) {
+		    p1 = N_get_array_3d_d_value(pot, i, j, k);
+		    p2 = N_get_array_3d_d_value(pot, i, j + 1, k);
+		    grad = (p1 - p2) / dy;	/* gradient */
+		}
+		if (!N_is_array_3d_value_null(weight_y, i, j, k) &&
+		    !N_is_array_3d_value_null(weight_y, i, j + 1, k)) {
+		    r1 = N_get_array_3d_d_value(weight_y, i, j, k);
+		    r2 = N_get_array_3d_d_value(weight_y, i, j + 1, k);
+		    mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
+		}
+
+		res = -1 * mean * grad;	/*invert the direction, because we count from north to south,
+					 * but the gradient is defined in y direction */
+
+		G_debug(6,
+			"N_compute_gradient_field_3d: Y-direction insert value %6.5g at %i %i %i ",
+			res, k, j + 1, i);
+
+		N_put_array_3d_d_value(field->y_array, i, j + 1, k, res);
+
+	    }
+
+    for (k = 0; k < depths - 1; k++)
+	for (j = 0; j < rows; j++)
+	    for (i = 0; i < cols; i++) {
+		grad = 0;
+		mean = 0;
+
+		/* Only compute if the arrays are not null */
+		if (!N_is_array_3d_value_null(pot, i, j, k) &&
+		    !N_is_array_3d_value_null(pot, i, j, k + 1)) {
+		    p1 = N_get_array_3d_d_value(pot, i, j, k);
+		    p2 = N_get_array_3d_d_value(pot, i, j, k + 1);
+		    grad = (p1 - p2) / dz;	/* gradient */
+		}
+		if (!N_is_array_3d_value_null(weight_z, i, j, k) &&
+		    !N_is_array_3d_value_null(weight_z, i, j, k + 1)) {
+		    r1 = N_get_array_3d_d_value(weight_z, i, j, k);
+		    r2 = N_get_array_3d_d_value(weight_z, i, j, k + 1);
+		    mean = N_calc_harmonic_mean(r1, r2);	/*harmonical mean */
+		}
+
+		res = mean * grad;
+
+		G_debug(6,
+			"N_compute_gradient_field_3d: Z-direction insert value %6.5g at %i %i %i ",
+			res, k + 1, j, i);
+
+		N_put_array_3d_d_value(field->z_array, i, j, k + 1, res);
+
+	    }
+
+    /*Compute gradient field statistics */
+    N_calc_gradient_field_3d_stats(field);
+
+    return field;
+}
+
+/*! 
+ * \brief Calculate the x, y and z vector components from a gradient field for each cell 
+ *  and store them in the provided N_array_3d structures
+ *
+ * The arrays must have the same size as the gradient field.
+ *
+ \verbatim
+
+ Based on this storages scheme the gradient vector for each cell is 
+ calculated and stored in the provided  N_array_3d structures
+
+
+ |  /
+ TC NC
+ |/
+ --WC-----EC--
+ /|
+ SC BC
+ /  |
+
+
+ x vector component:
+
+ x = (WC + EC) / 2
+
+ y vector component:
+
+ y = (NC + SC) / 2
+
+ z vector component:
+
+ z = (TC + BC) / 2
+
+ \endverbatim
+
+ * \param field N_gradient_field_3d *
+ * \param x_comp N_array_3d * - the array in which the x component will be written
+ * \param y_comp N_array_3d * - the array in which the y component will be written
+ * \param z_comp N_array_3d * - the array in which the z component will be written
+ *
+ * \return void
+ * */
+void
+N_compute_gradient_field_components_3d(N_gradient_field_3d * field,
+				       N_array_3d * x_comp,
+				       N_array_3d * y_comp,
+				       N_array_3d * z_comp)
+{
+    int i, j, k;
+
+    int rows, cols, depths;
+
+    double vx, vy, vz;
+
+    N_array_3d *x = x_comp;
+
+    N_array_3d *y = y_comp;
+
+    N_array_3d *z = z_comp;
+
+    N_gradient_3d grad;
+
+
+    if (!x)
+	G_fatal_error("N_compute_gradient_components_3d: x array is empty");
+    if (!y)
+	G_fatal_error("N_compute_gradient_components_3d: y array is empty");
+    if (!z)
+	G_fatal_error("N_compute_gradient_components_3d: z array is empty");
+
+    cols = field->x_array->cols;
+    rows = field->x_array->rows;
+    depths = field->x_array->depths;
+
+    /*Check the array sizes */
+    if (x->cols != cols || x->rows != rows || x->depths != depths)
+	G_fatal_error
+	    ("N_compute_gradient_components_3d: the size of the x array doesn't fit the gradient field size");
+    if (y->cols != cols || y->rows != rows || y->depths != depths)
+	G_fatal_error
+	    ("N_compute_gradient_components_3d: the size of the y array doesn't fit the gradient field size");
+    if (z->cols != cols || z->rows != rows || z->depths != depths)
+	G_fatal_error
+	    ("N_compute_gradient_components_3d: the size of the z array doesn't fit the gradient field size");
+
+    for (k = 0; k < depths; k++)
+	for (j = 0; j < rows; j++)
+	    for (i = 0; i < cols; i++) {
+		N_get_gradient_3d(field, &grad, i, j, k);
+		/* in case a gradient is zero, we expect a no flow boundary */
+		if (grad.WC == 0.0 || grad.EC == 0.0)
+		    vx = (grad.WC + grad.EC);
+		else
+		    vx = (grad.WC + grad.EC) / 2;
+		if (grad.NC == 0.0 || grad.SC == 0.0)
+		    vy = (grad.NC + grad.SC);
+		else
+		    vy = (grad.NC + grad.SC) / 2;
+		if (grad.TC == 0.0 || grad.BC == 0.0)
+		    vz = (grad.TC + grad.BC);
+		else
+		    vz = (grad.TC + grad.BC) / 2;
+
+		N_put_array_3d_d_value(x, i, j, k, vx);
+		N_put_array_3d_d_value(y, i, j, k, vy);
+		N_put_array_3d_d_value(z, i, j, k, vz);
+	    }
+
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_gwflow.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_gwflow.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_gwflow.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_gwflow.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,720 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:      groundwater flow in porous media 
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_gwflow.h>
+
+/* *************************************************************** */
+/* ***************** N_gwflow_data3d ***************************** */
+/* *************************************************************** */
+/*!
+ * \brief Alllocate memory for the groundwater calculation data structure in 3 dimensions
+ *
+ * The groundwater calculation data structure will be allocated including
+ * all appendant 3d and 2d arrays. The offset for the 3d arrays is one
+ * to establish homogeneous Neumann boundary conditions at the calculation area border.
+ * This data structure is used to create a linear equation system based on the computation of
+ * groundwater flow in porous media with the finite volume method.
+ *
+ * \param cols   int
+ * \param rows   int
+ * \param depths int
+ * \return N_gwflow_data3d *
+ * */
+N_gwflow_data3d *N_alloc_gwflow_data3d(int cols, int rows, int depths,
+				       int river, int drain)
+{
+    N_gwflow_data3d *data;
+
+    data = (N_gwflow_data3d *) G_calloc(1, sizeof(N_gwflow_data3d));
+
+    data->phead = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->phead_start = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->status = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->hc_x = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->hc_y = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->hc_z = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->q = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->s = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->nf = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->r = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+
+    if (river) {
+	data->river_head =
+	    N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+	data->river_leak =
+	    N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+	data->river_bed = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    }
+    else {
+	data->river_head = NULL;
+	data->river_leak = NULL;
+	data->river_bed = NULL;
+    }
+
+    if (drain) {
+	data->drain_leak =
+	    N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+	data->drain_bed = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    }
+    else {
+	data->drain_leak = NULL;
+	data->drain_bed = NULL;
+    }
+
+    return data;
+}
+
+/* *************************************************************** */
+/* ********************* N_free_gwflow_data3d ******************** */
+/* *************************************************************** */
+/*!
+ * \brief Release the memory of the groundwater flow data structure in three dimensions
+ *
+ * \param data N_gwflow_data3d *
+ * \return void *
+ * */
+
+void N_free_gwflow_data3d(N_gwflow_data3d * data)
+{
+    if (data->phead)
+	N_free_array_3d(data->phead);
+    if (data->phead_start)
+	N_free_array_3d(data->phead_start);
+    if (data->status)
+	N_free_array_3d(data->status);
+    if (data->hc_x)
+	N_free_array_3d(data->hc_x);
+    if (data->hc_y)
+	N_free_array_3d(data->hc_y);
+    if (data->hc_z)
+	N_free_array_3d(data->hc_z);
+    if (data->q)
+	N_free_array_3d(data->q);
+    if (data->s)
+	N_free_array_3d(data->s);
+    if (data->nf)
+	N_free_array_3d(data->nf);
+    if (data->r)
+	N_free_array_2d(data->r);
+    if (data->river_head)
+	N_free_array_3d(data->river_head);
+    if (data->river_leak)
+	N_free_array_3d(data->river_leak);
+    if (data->river_bed)
+	N_free_array_3d(data->river_bed);
+    if (data->drain_leak)
+	N_free_array_3d(data->drain_leak);
+    if (data->drain_bed)
+	N_free_array_3d(data->drain_bed);
+
+    G_free(data);
+
+    data = NULL;
+
+    return;
+}
+
+/* *************************************************************** */
+/* ******************** N_alloc_gwflow_data2d ******************** */
+/* *************************************************************** */
+/*!
+ * \brief Alllocate memory for the groundwater calculation data structure in 2 dimensions
+ * 
+ * The groundwater calculation data structure will be allocated including
+ * all appendant 2d arrays. The offset for the 3d arrays is one
+ * to establish homogeneous Neumann boundary conditions at the calculation area border.
+ * This data structure is used to create a linear equation system based on the computation of
+ * groundwater flow in porous media with the finite volume method.
+ *
+ * \param cols int
+ * \param rows int
+ * \return N_gwflow_data2d *
+ * */
+N_gwflow_data2d *N_alloc_gwflow_data2d(int cols, int rows, int river,
+				       int drain)
+{
+    N_gwflow_data2d *data;
+
+    data = (N_gwflow_data2d *) G_calloc(1, sizeof(N_gwflow_data2d));
+
+    data->phead = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->phead_start = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->status = N_alloc_array_2d(cols, rows, 1, CELL_TYPE);
+    data->hc_x = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->hc_y = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->q = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->s = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->nf = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->r = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->top = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->bottom = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+
+    if (river) {
+	data->river_head = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+	data->river_leak = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+	data->river_bed = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    }
+    else {
+	data->river_head = NULL;
+	data->river_leak = NULL;
+	data->river_bed = NULL;
+    }
+
+    if (drain) {
+	data->drain_leak = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+	data->drain_bed = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    }
+    else {
+	data->drain_leak = NULL;
+	data->drain_bed = NULL;
+    }
+
+
+    return data;
+}
+
+/* *************************************************************** */
+/* ****************** N_free_gwflow_data2d *********************** */
+/* *************************************************************** */
+/*!
+ * \brief Release the memory of the groundwater flow data structure in two dimensions
+ *
+ * \param data N_gwflow_data2d *
+ * \return void
+ * */
+void N_free_gwflow_data2d(N_gwflow_data2d * data)
+{
+    if (data->phead)
+	N_free_array_2d(data->phead);
+    if (data->phead_start)
+	N_free_array_2d(data->phead_start);
+    if (data->status)
+	N_free_array_2d(data->status);
+    if (data->hc_x)
+	N_free_array_2d(data->hc_x);
+    if (data->hc_y)
+	N_free_array_2d(data->hc_y);
+    if (data->q)
+	N_free_array_2d(data->q);
+    if (data->s)
+	N_free_array_2d(data->s);
+    if (data->nf)
+	N_free_array_2d(data->nf);
+    if (data->r)
+	N_free_array_2d(data->r);
+    if (data->top)
+	N_free_array_2d(data->top);
+    if (data->bottom)
+	N_free_array_2d(data->bottom);
+    if (data->river_head)
+	N_free_array_2d(data->river_head);
+    if (data->river_leak)
+	N_free_array_2d(data->river_leak);
+    if (data->river_bed)
+	N_free_array_2d(data->river_bed);
+    if (data->drain_leak)
+	N_free_array_2d(data->drain_leak);
+    if (data->drain_bed)
+	N_free_array_2d(data->drain_bed);
+
+    G_free(data);
+
+    data = NULL;;
+
+    return;
+}
+
+/* *************************************************************** */
+/* ***************** N_callback_gwflow_3d ************************ */
+/* *************************************************************** */
+/*!
+ * \brief This callback function creates the mass balance of a 7 point star
+ *
+ * The mass balance is based on the common groundwater flow equation:
+ *
+ * \f[Ss \frac{\partial h}{\partial t} = \nabla {\bf K} \nabla h + q \f]
+ *
+ * This equation is discretizised with the finite volume method in three dimensions.
+ *
+ *
+ * \param gwdata N_gwflow_data3d *
+ * \param geom N_geom_data *
+ * \param col   int
+ * \param row   int
+ * \param depth int
+ * \return N_data_star *
+ *
+ * */
+N_data_star *N_callback_gwflow_3d(void *gwdata, N_geom_data * geom, int col,
+				  int row, int depth)
+{
+    double hc_e = 0, hc_w = 0, hc_n = 0, hc_s = 0, hc_t = 0, hc_b = 0;
+    double dx, dy, dz, Ax, Ay, Az;
+    double hc_x, hc_y, hc_z;
+    double hc_xw, hc_yn, hc_zt;
+    double hc_xe, hc_ys, hc_zb;
+    double hc_start;
+    double Ss, r, nf, q;
+    double C, W, E, N, S, T, B, V;
+    N_data_star *mat_pos;
+    N_gwflow_data3d *data;
+
+    /*cast the void pointer to the right data structure */
+    data = (N_gwflow_data3d *) gwdata;
+
+    dx = geom->dx;
+    dy = geom->dy;
+    dz = geom->dz;
+    Az = N_get_geom_data_area_of_cell(geom, row);
+    Ay = geom->dx * geom->dz;
+    Ax = geom->dz * geom->dy;
+
+    /*read the data from the arrays */
+    hc_start = N_get_array_3d_d_value(data->phead_start, col, row, depth);
+
+    hc_x = N_get_array_3d_d_value(data->hc_x, col, row, depth);
+    hc_y = N_get_array_3d_d_value(data->hc_y, col, row, depth);
+    hc_z = N_get_array_3d_d_value(data->hc_z, col, row, depth);
+
+    hc_xw = N_get_array_3d_d_value(data->hc_x, col - 1, row, depth);
+    hc_xe = N_get_array_3d_d_value(data->hc_x, col + 1, row, depth);
+    hc_yn = N_get_array_3d_d_value(data->hc_y, col, row - 1, depth);
+    hc_ys = N_get_array_3d_d_value(data->hc_y, col, row + 1, depth);
+    hc_zt = N_get_array_3d_d_value(data->hc_z, col, row, depth + 1);
+    hc_zb = N_get_array_3d_d_value(data->hc_z, col, row, depth - 1);
+
+    hc_w = N_calc_harmonic_mean(hc_xw, hc_x);
+    hc_e = N_calc_harmonic_mean(hc_xe, hc_x);
+    hc_n = N_calc_harmonic_mean(hc_yn, hc_y);
+    hc_s = N_calc_harmonic_mean(hc_ys, hc_y);
+    hc_t = N_calc_harmonic_mean(hc_zt, hc_z);
+    hc_b = N_calc_harmonic_mean(hc_zb, hc_z);
+
+    /*inner sources */
+    q = N_get_array_3d_d_value(data->q, col, row, depth);
+    /*storativity */
+    Ss = N_get_array_3d_d_value(data->s, col, row, depth);
+    /*porosity */
+    nf = N_get_array_3d_d_value(data->nf, col, row, depth);
+
+    /*mass balance center cell to western cell */
+    W = -1 * Ax * hc_w / dx;
+    /*mass balance center cell to eastern cell */
+    E = -1 * Ax * hc_e / dx;
+    /*mass balance center cell to northern cell */
+    N = -1 * Ay * hc_n / dy;
+    /*mass balance center cell to southern cell */
+    S = -1 * Ay * hc_s / dy;
+    /*mass balance center cell to top cell */
+    T = -1 * Az * hc_t / dz;
+    /*mass balance center cell to bottom cell */
+    B = -1 * Az * hc_b / dz;
+
+    /*storativity */
+    Ss = Az * dz * Ss;
+
+    /*the diagonal entry of the matrix */
+    C = -1 * (W + E + N + S + T + B - Ss / data->dt * Az);
+
+    /*the entry in the right side b of Ax = b */
+    V = (q + hc_start * Ss / data->dt * Az);
+
+    /*only the top cells will have recharge */
+    if (depth == geom->depths - 2) {
+	r = N_get_array_2d_d_value(data->r, col, row);
+	V += r * Az;
+    }
+
+    G_debug(5, "N_callback_gwflow_3d: called [%i][%i][%i]", depth, col, row);
+
+    /*create the 7 point star entries */
+    mat_pos = N_create_7star(C, W, E, N, S, T, B, V);
+
+    return mat_pos;
+}
+
+
+/* *************************************************************** */
+/* ****************** N_gwflow_3d_calc_water_budget ************** */
+/* *************************************************************** */
+/*!
+ * \brief This function computes the water budget of the entire groundwater
+ *
+ * The water budget is calculated for each active and dirichlet cell from
+ * its surrounding neighbours. This is based on the 7 star mass balance computation
+ * of N_callback_gwflow_3d and the gradient of the water heights in the cells.
+ * The sum of the water budget of each active/dirichlet cell must be near zero
+ * due the effect of numerical inaccuracy of cpu's.
+ *
+ * \param gwdata N_gwflow_data3d *
+ * \param geom N_geom_data *
+ * \param budget N_array_3d
+ * \return void
+ *
+ * */
+void
+N_gwflow_3d_calc_water_budget(N_gwflow_data3d * data, N_geom_data * geom, N_array_3d * budget)
+{
+    int z, y, x, stat;
+    double h, hc;
+    double val;
+    double sum;
+    N_data_star *dstar;
+
+    int rows = data->status->rows;
+    int cols = data->status->cols;
+    int depths = data->status->depths;
+    sum = 0;
+
+    for (z = 0; z < depths; z++) {
+        for (y = 0; y < rows; y++) {
+            G_percent(y, rows - 1, 10);
+            for (x = 0; x < cols; x++) {
+                stat = (int)N_get_array_3d_d_value(data->status, x, y, z);
+
+                val = 0.0;
+
+                if (stat != N_CELL_INACTIVE ) {	/*all active/dirichlet cells */
+
+                    /* Compute the flow parameter */
+                    dstar = N_callback_gwflow_3d(data, geom, x, y, z);
+                    /* Compute the gradient in each direction pointing from the center */
+                    hc = N_get_array_3d_d_value(data->phead, x, y, z);
+
+                    if((int)N_get_array_3d_d_value(data->status, x + 1, y    , z) != N_CELL_INACTIVE) {
+                        h = N_get_array_3d_d_value(data->phead,  x + 1, y    , z);
+                        val += dstar->E * (hc - h);
+                    }
+                    if((int)N_get_array_3d_d_value(data->status, x - 1, y    , z) != N_CELL_INACTIVE) {
+                        h = N_get_array_3d_d_value(data->phead,  x - 1, y    , z);
+                        val += dstar->W * (hc - h);
+                    }
+                    if((int)N_get_array_3d_d_value(data->status, x    , y + 1, z) != N_CELL_INACTIVE) {
+                        h = N_get_array_3d_d_value(data->phead,  x    , y + 1, z);
+                        val += dstar->S * (hc - h);
+                    }
+                    if((int)N_get_array_3d_d_value(data->status, x    , y - 1, z) != N_CELL_INACTIVE) {
+                        h = N_get_array_3d_d_value(data->phead,  x    , y - 1, z);
+                        val += dstar->N * (hc - h);
+                    }
+                    if((int)N_get_array_3d_d_value(data->status, x    , y    , z + 1) != N_CELL_INACTIVE) {
+                        h = N_get_array_3d_d_value(data->phead,  x    , y    , z + 1);
+                        val += dstar->T * (hc - h);
+                    }
+                    if((int)N_get_array_3d_d_value(data->status, x    , y    , z - 1) != N_CELL_INACTIVE) {
+                        h = N_get_array_3d_d_value(data->phead,  x    , y    , z - 1);
+                        val += dstar->B * (hc - h);
+                    }
+                    sum += val;
+
+                    G_free(dstar);
+                }
+                else {
+                    Rast_set_null_value(&val, 1, DCELL_TYPE);
+                }
+                N_put_array_3d_d_value(budget, x, y, z, val);
+            }
+        }
+    }
+
+    if(fabs(sum) < 0.0000000001)
+        G_message(_("The total sum of the water budget: %g\n"), sum);
+    else
+        G_warning(_("The total sum of the water budget is significant larger then 0: %g\n"), sum);
+
+    return;
+}
+
+
+
+/* *************************************************************** */
+/* ****************** N_callback_gwflow_2d *********************** */
+/* *************************************************************** */
+/*!
+ * \brief This callback function creates the mass balance of a 5 point star
+ *
+ * The mass balance is based on the common groundwater flow equation:
+ *
+ * \f[Ss \frac{\partial h}{\partial t} = \nabla {\bf K} \nabla h + q \f]
+ *
+ * This equation is discretizised with the finite volume method in two dimensions.
+ *
+ * \param gwdata N_gwflow_data2d *
+ * \param geom N_geom_data *
+ * \param col int
+ * \param row int
+ * \return N_data_star *
+ *
+ * */
+N_data_star *N_callback_gwflow_2d(void *gwdata, N_geom_data * geom, int col,
+				  int row)
+{
+    double T_e = 0, T_w = 0, T_n = 0, T_s = 0;
+    double z_e = 0, z_w = 0, z_n = 0, z_s = 0;
+    double dx, dy, Az;
+    double hc_x, hc_y;
+    double z, top;
+    double hc_xw, hc_yn;
+    double z_xw, z_yn;
+    double hc_xe, hc_ys;
+    double z_xe, z_ys;
+    double hc, hc_start;
+    double Ss, r, q;
+    double C, W, E, N, S, V;
+    N_gwflow_data2d *data;
+    N_data_star *mat_pos;
+    double river_vect = 0;	/*entry in vector */
+    double river_mat = 0;	/*entry in matrix */
+    double drain_vect = 0;	/*entry in vector */
+    double drain_mat = 0;	/*entry in matrix */
+
+    /*cast the void pointer to the right data structure */
+    data = (N_gwflow_data2d *) gwdata;
+
+    dx = geom->dx;
+    dy = geom->dy;
+    Az = N_get_geom_data_area_of_cell(geom, row);
+
+    /*read the data from the arrays */
+    hc_start = N_get_array_2d_d_value(data->phead_start, col, row);
+    hc = N_get_array_2d_d_value(data->phead, col, row);
+    top = N_get_array_2d_d_value(data->top, col, row);
+
+    /* Inner sources */
+    q = N_get_array_2d_d_value(data->q, col, row);
+
+    /* storativity or porosity of current cell face [-]*/
+    Ss = N_get_array_2d_d_value(data->s, col, row);
+    /* recharge */
+    r = N_get_array_2d_d_value(data->r, col, row) * Az;
+
+
+    if (hc > top) {		/*If the aquifer is confined */
+	z = N_get_array_2d_d_value(data->top, col,
+				   row) -
+	    N_get_array_2d_d_value(data->bottom, col, row);
+	z_xw =
+	    N_get_array_2d_d_value(data->top, col - 1,
+				   row) -
+	    N_get_array_2d_d_value(data->bottom, col - 1, row);
+	z_xe =
+	    N_get_array_2d_d_value(data->top, col + 1,
+				   row) -
+	    N_get_array_2d_d_value(data->bottom, col + 1, row);
+	z_yn =
+	    N_get_array_2d_d_value(data->top, col,
+				   row - 1) -
+	    N_get_array_2d_d_value(data->bottom, col, row - 1);
+	z_ys =
+	    N_get_array_2d_d_value(data->top, col,
+				   row + 1) -
+	    N_get_array_2d_d_value(data->bottom, col, row + 1);
+    }
+    else {			/* the aquifer is unconfined */
+
+	/* If the aquifer is unconfied use an explicite scheme to solve
+	 * the nonlinear equation. We use the phead from the first iteration */
+	z = N_get_array_2d_d_value(data->phead, col, row) -
+	    N_get_array_2d_d_value(data->bottom, col, row);
+	z_xw = N_get_array_2d_d_value(data->phead, col - 1, row) -
+	    N_get_array_2d_d_value(data->bottom, col - 1, row);
+	z_xe = N_get_array_2d_d_value(data->phead, col + 1, row) -
+	    N_get_array_2d_d_value(data->bottom, col + 1, row);
+	z_yn = N_get_array_2d_d_value(data->phead, col, row - 1) -
+	    N_get_array_2d_d_value(data->bottom, col, row - 1);
+	z_ys = N_get_array_2d_d_value(data->phead, col, row + 1) -
+	    N_get_array_2d_d_value(data->bottom, col, row + 1);
+    }
+
+    /*geometrical mean of cell height */
+    if (z_w > 0 || z_w < 0 || z_w == 0)
+	z_w = N_calc_arith_mean(z_xw, z);
+    else
+	z_w = z;
+    if (z_e > 0 || z_e < 0 || z_e == 0)
+	z_e = N_calc_arith_mean(z_xe, z);
+    else
+	z_e = z;
+    if (z_n > 0 || z_n < 0 || z_n == 0)
+	z_n = N_calc_arith_mean(z_yn, z);
+    else
+	z_n = z;
+    if (z_s > 0 || z_s < 0 || z_s == 0)
+	z_s = N_calc_arith_mean(z_ys, z);
+    else
+	z_s = z;
+
+    /*get the surrounding permeabilities */
+    hc_x = N_get_array_2d_d_value(data->hc_x, col, row);
+    hc_y = N_get_array_2d_d_value(data->hc_y, col, row);
+    hc_xw = N_get_array_2d_d_value(data->hc_x, col - 1, row);
+    hc_xe = N_get_array_2d_d_value(data->hc_x, col + 1, row);
+    hc_yn = N_get_array_2d_d_value(data->hc_y, col, row - 1);
+    hc_ys = N_get_array_2d_d_value(data->hc_y, col, row + 1);
+
+    /* calculate the transmissivities */
+    T_w = N_calc_harmonic_mean(hc_xw, hc_x) * z_w;
+    T_e = N_calc_harmonic_mean(hc_xe, hc_x) * z_e;
+    T_n = N_calc_harmonic_mean(hc_yn, hc_y) * z_n;
+    T_s = N_calc_harmonic_mean(hc_ys, hc_y) * z_s;
+
+    /* Compute the river leakage, this is an explicit method
+     * Influent and effluent flow is computed.
+     */
+    if (data->river_leak &&
+	(N_get_array_2d_d_value(data->river_leak, col, row) != 0) &&
+            N_get_array_2d_d_value(data->river_bed, col, row) <= top) {
+        /* Groundwater surface is above the river bed*/
+	if (hc > N_get_array_2d_d_value(data->river_bed, col, row)) {
+	    river_vect = N_get_array_2d_d_value(data->river_head, col, row) *
+		N_get_array_2d_d_value(data->river_leak, col, row);
+	    river_mat = N_get_array_2d_d_value(data->river_leak, col, row);
+	} /* Groundwater surface is below the river bed */
+	else if (hc < N_get_array_2d_d_value(data->river_bed, col, row)) {
+	    river_vect = (N_get_array_2d_d_value(data->river_head, col, row) -
+			  N_get_array_2d_d_value(data->river_bed, col, row))
+		* N_get_array_2d_d_value(data->river_leak, col, row);
+	    river_mat = 0;
+	}
+    }
+
+    /* compute the drainage, this is an explicit method
+     * Drainage is only enabled, if the drain bed is lower the groundwater surface
+     */
+    if (data->drain_leak &&
+	(N_get_array_2d_d_value(data->drain_leak, col, row) != 0) &&
+            N_get_array_2d_d_value(data->drain_bed, col, row) <= top) {
+	if (hc > N_get_array_2d_d_value(data->drain_bed, col, row)) {
+	    drain_vect = N_get_array_2d_d_value(data->drain_bed, col, row) *
+		N_get_array_2d_d_value(data->drain_leak, col, row);
+	    drain_mat = N_get_array_2d_d_value(data->drain_leak, col, row);
+	}
+	else if (hc <= N_get_array_2d_d_value(data->drain_bed, col, row)) {
+	    drain_vect = 0;
+	    drain_mat = 0;
+	}
+    }
+
+    /*mass balance center cell to western cell */
+    W = -1 * T_w * dy / dx;
+    /*mass balance center cell to eastern cell */
+    E = -1 * T_e * dy / dx;
+    /*mass balance center cell to northern cell */
+    N = -1 * T_n * dx / dy;
+    /*mass balance center cell to southern cell */
+    S = -1 * T_s * dx / dy;
+
+    /*the diagonal entry of the matrix */
+    C = -1 * (W + E + N + S -  Az *Ss / data->dt - river_mat * Az -
+	      drain_mat * Az);
+
+    /*the entry in the right side b of Ax = b */
+    V = (q + hc_start * Az * Ss / data->dt) + r + river_vect * Az +
+	drain_vect * Az;
+
+    G_debug(5, "N_callback_gwflow_2d: called [%i][%i]", row, col);
+
+    /*create the 5 point star entries */
+    mat_pos = N_create_5star(C, W, E, N, S, V);
+
+    return mat_pos;
+}
+
+
+
+/* *************************************************************** */
+/* ****************** N_gwflow_2d_calc_water_budget ************** */
+/* *************************************************************** */
+/*!
+ * \brief This function computes the water budget of the entire groundwater
+ *
+ * The water budget is calculated for each active and dirichlet cell from
+ * its surrounding neighbours. This is based on the 5 star mass balance computation
+ * of N_callback_gwflow_2d and the gradient of the water heights in the cells.
+ * The sum of the water budget of each active/dirichlet cell must be near zero
+ * due the effect of numerical inaccuracy of cpu's.
+ *
+ * \param gwdata N_gwflow_data2d *
+ * \param geom N_geom_data *
+ * \param budget N_array_2d
+ * \return void
+ *
+ * */
+void
+N_gwflow_2d_calc_water_budget(N_gwflow_data2d * data, N_geom_data * geom, N_array_2d * budget)
+{
+    int y, x, stat;
+    double h, hc;
+    double val;
+    double sum;
+    N_data_star *dstar;
+
+    int rows = data->status->rows;
+    int cols = data->status->cols;
+
+    sum = 0;
+
+    for (y = 0; y < rows; y++) {
+	G_percent(y, rows - 1, 10);
+	for (x = 0; x < cols; x++) {
+	    stat = N_get_array_2d_c_value(data->status, x, y);
+
+            val = 0.0;
+
+	    if (stat != N_CELL_INACTIVE ) {	/*all active/dirichlet cells */
+
+                /* Compute the flow parameter */
+                dstar = N_callback_gwflow_2d(data, geom, x, y);
+                /* Compute the gradient in each direction pointing from the center */
+                hc = N_get_array_2d_d_value(data->phead, x, y);
+
+                if((int)N_get_array_2d_d_value(data->status, x + 1, y    ) != N_CELL_INACTIVE) {
+                    h = N_get_array_2d_d_value(data->phead,  x + 1, y);
+                    val += dstar->E * (hc - h);
+                }
+                if((int)N_get_array_2d_d_value(data->status, x - 1, y    ) != N_CELL_INACTIVE) {
+                    h = N_get_array_2d_d_value(data->phead,  x - 1, y);
+                    val += dstar->W * (hc - h);
+                }
+                if((int)N_get_array_2d_d_value(data->status, x    , y + 1) != N_CELL_INACTIVE) {
+                    h = N_get_array_2d_d_value(data->phead,  x    , y + 1);
+                    val += dstar->S * (hc - h);
+                }
+                if((int)N_get_array_2d_d_value(data->status, x    , y - 1) != N_CELL_INACTIVE) {
+                    h = N_get_array_2d_d_value(data->phead,  x    , y - 1);
+                    val += dstar->N * (hc - h);
+                }
+
+                sum += val;
+
+                G_free(dstar);
+	    }
+	    else {
+		Rast_set_null_value(&val, 1, DCELL_TYPE);
+	    }
+	    N_put_array_2d_d_value(budget, x, y, val);
+	}
+    }
+
+    if(fabs(sum) < 0.0000000001)
+        G_message(_("The total sum of the water budget: %g\n"), sum);
+    else
+        G_warning(_("The total sum of the water budget is significant larger then 0: %g\n"), sum);
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_heatflow.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_heatflow.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_heatflow.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_heatflow.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,19 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:      Calculation of heatflow
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_les.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_les.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_les.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_les.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,335 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:      functions to manage linear equation systems
+* 		part of the gpde library
+*               
+* COPYRIGHT:    (C) 2000 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/N_pde.h>
+#include <grass/gmath.h>
+
+
+/*!
+ * \brief Allocate memory for a (not) quadratic linear equation system which includes the Matrix A, vector x and vector b
+ *
+ * This function calls #N_alloc_les_param
+ *
+ * \param cols int
+ * \param rows int
+ * \param type int
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_nquad_les(int cols, int rows, int type)
+{
+    return N_alloc_les_param(cols, rows, type, 2);
+}
+
+/*!
+ * \brief Allocate memory for a (not) quadratic linear equation system which includes the Matrix A and vector x
+ *
+ * This function calls #N_alloc_les_param
+ *
+ * \param cols int
+ * \param rows int
+ * \param type int
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_nquad_les_Ax(int cols, int rows, int type)
+{
+    return N_alloc_les_param(cols, rows, type, 1);
+}
+
+/*!
+ * \brief Allocate memory for a (not) quadratic linear equation system which includes the Matrix A
+ *
+ * This function calls #N_alloc_les_param
+ *
+ * \param cols int
+ * \param rows int
+ * \param type int
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_nquad_les_A(int cols, int rows, int type)
+{
+    return N_alloc_les_param(cols, rows, type, 0);
+}
+
+/*!
+ * \brief Allocate memory for a (not) quadratic linear equation system which includes the Matrix A, vector x and vector b
+ *
+ * This function calls #N_alloc_les_param
+ *
+ * \param cols int
+ * \param rows int
+ * \param type int
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_nquad_les_Ax_b(int cols, int rows, int type)
+{
+    return N_alloc_les_param(cols, rows, type, 2);
+}
+
+
+
+/*!
+ * \brief Allocate memory for a quadratic linear equation system which includes the Matrix A, vector x and vector b
+ *
+ * This function calls #N_alloc_les_param
+ *
+ * \param rows int
+ * \param type int
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_les(int rows, int type)
+{
+    return N_alloc_les_param(rows, rows, type, 2);
+}
+
+/*!
+ * \brief Allocate memory for a quadratic linear equation system which includes the Matrix A and vector x
+ *
+ * This function calls #N_alloc_les_param
+ *
+ * \param rows int
+ * \param type int
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_les_Ax(int rows, int type)
+{
+    return N_alloc_les_param(rows, rows, type, 1);
+}
+
+/*!
+ * \brief Allocate memory for a quadratic linear equation system which includes the Matrix A
+ *
+ * This function calls #N_alloc_les_param
+ *
+ * \param rows int
+ * \param type int
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_les_A(int rows, int type)
+{
+    return N_alloc_les_param(rows, rows, type, 0);
+}
+
+/*!
+ * \brief Allocate memory for a quadratic linear equation system which includes the Matrix A, vector x and vector b
+ *
+ * This function calls #N_alloc_les_param
+ *
+ * \param rows int
+ * \param type int
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_les_Ax_b(int rows, int type)
+{
+    return N_alloc_les_param(rows, rows, type, 2);
+}
+
+
+/*!
+ * \brief Allocate memory for a quadratic or not quadratic linear equation system
+ *
+ * The type of the linear equation system must be N_NORMAL_LES for
+ * a regular quadratic matrix or N_SPARSE_LES for a sparse matrix
+ *
+ * <p>
+ * In case of N_NORMAL_LES
+ * 
+ * A quadratic matrix of size rows*rows*sizeof(double) will allocated
+ *
+ * <p>
+ * In case of N_SPARSE_LES
+ *
+ * a vector of size row will be allocated, ready to hold additional allocated sparse vectors.
+ * each sparse vector may have a different size.
+ *
+ * Parameter parts defines which parts of the les should be allocated.
+ * The number of columns and rows defines if the matrix is quadratic.
+ *
+ * \param cols int
+ * \param rows int
+ * \param type int
+ * \param parts int -- 2 = A, x and b; 1 = A and x; 0 = A allocated
+ * \return N_les *
+ *
+ * */
+N_les *N_alloc_les_param(int cols, int rows, int type, int parts)
+{
+    N_les *les;
+
+    int i;
+
+    if (type == N_SPARSE_LES)
+	G_debug(2,
+		"Allocate memory for a sparse linear equation system with %i rows\n",
+		rows);
+    else
+	G_debug(2,
+		"Allocate memory for a regular linear equation system with %i rows\n",
+		rows);
+
+    les = (N_les *) G_calloc(1, sizeof(N_les));
+
+    if (parts > 0) {
+	les->x = (double *)G_calloc(cols, sizeof(double));
+	for (i = 0; i < cols; i++)
+	    les->x[i] = 0.0;
+    }
+
+
+    if (parts > 1) {
+	les->b = (double *)G_calloc(cols, sizeof(double));
+	for (i = 0; i < cols; i++)
+	    les->b[i] = 0.0;
+    }
+
+    les->A = NULL;
+    les->Asp = NULL;
+    les->rows = rows;
+    les->cols = cols;
+    if (rows == cols)
+	les->quad = 1;
+    else
+	les->quad = 0;
+
+    if (type == N_SPARSE_LES) {
+	les->Asp = G_math_alloc_spmatrix(rows);
+	les->type = N_SPARSE_LES;
+    }
+    else {
+	les->A = G_alloc_matrix(rows, cols);
+	les->type = N_NORMAL_LES;
+    }
+
+    return les;
+}
+
+/*!
+ *
+ * \brief prints the linear equation system to stdout
+ *
+ * <p>
+ * Format:
+ * A*x = b
+ *
+ * <p>
+ * Example
+ \verbatim
+
+ 2 1 1 1 * 2 = 0.1
+ 1 2 0 0 * 3 = 0.2
+ 1 0 2 0 * 3 = 0.2
+ 1 0 0 2 * 2 = 0.1
+
+ \endverbatim
+ *
+ * \param les N_les * 
+ * \return void
+ *  
+ * */
+void N_print_les(N_les * les)
+{
+    int i, j, k, out;
+
+
+    if (les->type == N_SPARSE_LES) {
+	for (i = 0; i < les->rows; i++) {
+	    for (j = 0; j < les->cols; j++) {
+		out = 0;
+		for (k = 0; k < les->Asp[i]->cols; k++) {
+		    if (les->Asp[i]->index[k] == j) {
+			fprintf(stdout, "%4.5f ", les->Asp[i]->values[k]);
+			out = 1;
+		    }
+		}
+		if (!out)
+		    fprintf(stdout, "%4.5f ", 0.0);
+	    }
+	    if (les->x)
+		fprintf(stdout, "  *  %4.5f", les->x[i]);
+	    if (les->b)
+		fprintf(stdout, " =  %4.5f ", les->b[i]);
+
+	    fprintf(stdout, "\n");
+	}
+    }
+    else {
+
+	for (i = 0; i < les->rows; i++) {
+	    for (j = 0; j < les->cols; j++) {
+		fprintf(stdout, "%4.5f ", les->A[i][j]);
+	    }
+	    if (les->x)
+		fprintf(stdout, "  *  %4.5f", les->x[i]);
+	    if (les->b)
+		fprintf(stdout, " =  %4.5f ", les->b[i]);
+
+	    fprintf(stdout, "\n");
+	}
+
+    }
+    return;
+}
+
+/*!
+ * \brief Release the memory of the linear equation system
+ *
+ * \param les N_les *            
+ * \return void
+ *
+ * */
+
+void N_free_les(N_les * les)
+{
+    if (les->type == N_SPARSE_LES)
+	G_debug(2, "Releasing memory of a sparse linear equation system\n");
+    else
+	G_debug(2, "Releasing memory of a regular linear equation system\n");
+
+    if (les) {
+
+	if (les->x)
+	    G_free(les->x);
+	if (les->b)
+	    G_free(les->b);
+
+	if (les->type == N_SPARSE_LES) {
+
+	    if (les->Asp) {
+		G_math_free_spmatrix(les->Asp, les->rows);
+	    }
+	}
+	else {
+
+	    if (les->A) {
+		G_free_matrix(les->A);
+	    }
+	}
+
+	free(les);
+    }
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_les_assemble.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_les_assemble.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_les_assemble.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_les_assemble.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,1397 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:      functions to assemble a linear equation system
+* 		part of the gpde library
+*               
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+
+/* local protos */
+static int make_les_entry_2d(int i, int j, int offset_i, int offset_j,
+			     int count, int pos, N_les * les,
+			     G_math_spvector * spvect,
+			     N_array_2d * cell_count, N_array_2d * status,
+			     N_array_2d * start_val, double entry,
+			     int cell_type);
+
+static int make_les_entry_3d(int i, int j, int k, int offset_i, int offset_j,
+			     int offset_k, int count, int pos, N_les * les,
+			     G_math_spvector * spvect,
+			     N_array_3d * cell_count, N_array_3d * status,
+			     N_array_3d * start_val, double entry,
+			     int cell_type);
+
+/* *************************************************************** * 
+ * ********************** N_alloc_5star ************************** * 
+ * *************************************************************** */
+/*!
+ * \brief allocate a 5 point star data structure
+ *
+ * \return N_data_star *
+ * */
+N_data_star *N_alloc_5star(void)
+{
+    N_data_star *star = (N_data_star *) G_calloc(1, sizeof(N_data_star));
+
+    star->type = N_5_POINT_STAR;
+    star->count = 5;
+    return star;
+}
+
+/* *************************************************************** * 
+ * ********************* N_alloc_7star *************************** * 
+ * *************************************************************** */
+/*!
+ * \brief allocate a 7 point star data structure
+ *
+ * \return N_data_star *
+ * */
+N_data_star *N_alloc_7star(void)
+{
+    N_data_star *star = (N_data_star *) G_calloc(1, sizeof(N_data_star));
+
+    star->type = N_7_POINT_STAR;
+    star->count = 7;
+    return star;
+}
+
+/* *************************************************************** * 
+ * ********************* N_alloc_9star *************************** * 
+ * *************************************************************** */
+/*!
+ * \brief allocate a 9 point star data structure
+ *
+ * \return N_data_star *
+ *
+ * \attention The 9 point start is not yet implemented in the matrix assembling function
+ *
+ * */
+N_data_star *N_alloc_9star(void)
+{
+    N_data_star *star = (N_data_star *) G_calloc(1, sizeof(N_data_star));
+
+    star->type = N_9_POINT_STAR;
+    star->count = 9;
+    return star;
+}
+
+/* *************************************************************** * 
+ * ********************* N_alloc_27star ************************** * 
+ * *************************************************************** */
+/*!
+ * \brief allocate a 27 point star data structure
+ *
+ * \return N_data_star *
+ *
+ * \attention The 27 point start is not yet implemented in the matrix assembling function
+ *
+ * */
+N_data_star *N_alloc_27star(void)
+{
+    N_data_star *star = (N_data_star *) G_calloc(1, sizeof(N_data_star));
+
+    star->type = N_27_POINT_STAR;
+    star->count = 27;
+    return star;
+}
+
+/* *************************************************************** * 
+ * ********************** N_create_5star ************************* * 
+ * *************************************************************** */
+/*!
+ * \brief allocate and initialize a 5 point star data structure
+ *
+ * \param C double
+ * \param W double
+ * \param E double
+ * \param N double
+ * \param S double
+ * \param V double
+ * \return N_data_star *
+ * */
+N_data_star *N_create_5star(double C, double W, double E, double N,
+			    double S, double V)
+{
+    N_data_star *star = N_alloc_5star();
+
+    star->C = C;
+    star->W = W;
+    star->E = E;
+    star->N = N;
+    star->S = S;
+
+    star->V = V;
+
+    G_debug(5, "N_create_5star:  w %g e %g n %g s %g c %g v %g\n", star->W,
+	    star->E, star->N, star->S, star->C, star->V);
+
+    return star;
+}
+
+/* *************************************************************** * 
+ * ************************* N_create_7star ********************** * 
+ * *************************************************************** */
+/*!
+ * \brief allocate and initialize a 7 point star data structure
+ *
+ * \param C double
+ * \param W double
+ * \param E double
+ * \param N double
+ * \param S double
+ * \param T double
+ * \param B double
+ * \param V double
+ * \return N_data_star *
+ * */
+N_data_star *N_create_7star(double C, double W, double E, double N,
+			    double S, double T, double B, double V)
+{
+    N_data_star *star = N_alloc_7star();
+
+    star->C = C;
+    star->W = W;
+    star->E = E;
+    star->N = N;
+    star->S = S;
+
+    star->T = T;
+    star->B = B;
+
+    star->V = V;
+
+    G_debug(5, "N_create_7star:  w %g e %g n %g s %g t %g b %g c %g v %g\n",
+	    star->W, star->E, star->N, star->S, star->T, star->B, star->C,
+	    star->V);
+
+    return star;
+}
+
+/* *************************************************************** * 
+ * ************************ N_create_9star *********************** * 
+ * *************************************************************** */
+/*!
+ * \brief allocate and initialize a 9 point star data structure
+ *
+ * \param C  double
+ * \param W  double
+ * \param E  double
+ * \param N  double
+ * \param S  double
+ * \param NW double
+ * \param SW double
+ * \param NE double
+ * \param SE double
+ * \param V  double
+ * \return N_data_star *
+ * */
+N_data_star *N_create_9star(double C, double W, double E, double N,
+			    double S, double NW, double SW, double NE,
+			    double SE, double V)
+{
+    N_data_star *star = N_alloc_9star();
+
+    star->C = C;
+    star->W = W;
+    star->E = E;
+    star->N = N;
+    star->S = S;
+
+    star->NW = NW;
+    star->SW = SW;
+    star->NE = NE;
+    star->SE = SE;
+
+    star->V = V;
+
+    G_debug(5,
+	    "N_create_9star:  w %g e %g n %g s %g nw %g sw %g ne %g se %g c %g v %g\n",
+	    star->W, star->E, star->N, star->S, star->NW, star->SW, star->NE,
+	    star->SE, star->C, star->V);
+
+    return star;
+}
+
+/* *************************************************************** * 
+ * ************************ N_create_27star *********************** * 
+ * *************************************************************** */
+/*!
+ * \brief allocate and initialize a 27 point star data structure
+ *
+ * \param C  double
+ * \param W  double
+ * \param E  double
+ * \param N  double
+ * \param S  double
+ * \param NW double
+ * \param SW double
+ * \param NE double
+ * \param SE double
+ * \param T  double
+ * \param W_T  double
+ * \param E_T  double
+ * \param N_T  double
+ * \param S_T  double
+ * \param NW_T double
+ * \param SW_T double
+ * \param NE_T double
+ * \param SE_T double
+ * \param B  double
+ * \param W_B  double
+ * \param E_B  double
+ * \param N_B  double
+ * \param S_B  double
+ * \param NW_B double
+ * \param SW_B double
+ * \param NE_B double
+ * \param SE_B double
+ * \param V  double
+ * \return N_data_star *
+ * */
+N_data_star *N_create_27star(double C, double W, double E, double N, double S,
+			     double NW, double SW, double NE, double SE,
+			     double T, double W_T, double E_T, double N_T,
+			     double S_T, double NW_T, double SW_T,
+			     double NE_T, double SE_T, double B, double W_B,
+			     double E_B, double N_B, double S_B, double NW_B,
+			     double SW_B, double NE_B, double SE_B, double V)
+{
+    N_data_star *star = N_alloc_27star();
+
+    star->C = C;
+    star->W = W;
+    star->E = E;
+    star->N = N;
+    star->S = S;
+
+    star->NW = NW;
+    star->SW = SW;
+    star->NE = NE;
+    star->SE = SE;
+
+    star->T = T;
+    star->W_T = W_T;
+    star->E_T = E_T;
+    star->N_T = N_T;
+    star->S_T = S_T;
+
+    star->NW_T = NW_T;
+    star->SW_T = SW_T;
+    star->NE_T = NE_T;
+    star->SE_T = SE_T;
+
+    star->B = B;
+    star->W_B = W_B;
+    star->E_B = E_B;
+    star->N_B = N_B;
+    star->S_B = S_B;
+
+    star->NW_B = NW_B;
+    star->SW_B = SW_B;
+    star->NE_B = NE_B;
+    star->SE_B = SE_B;
+
+    star->V = V;
+
+    G_debug(5,
+	    "N_create_27star:  w %g e %g n %g s %g nw %g sw %g ne %g se %g c %g v %g\n",
+	    star->W, star->E, star->N, star->S, star->NW, star->SW, star->NE,
+	    star->SE, star->C, star->V);
+
+    G_debug(5,
+	    "N_create_27star:  w_t %g e_t %g n_t %g s_t %g nw_t %g sw_t %g ne_t %g se_t %g t %g \n",
+	    star->W_T, star->E_T, star->N_T, star->S_T, star->NW_T,
+	    star->SW_T, star->NE_T, star->SE_T, star->T);
+
+    G_debug(5,
+	    "N_create_27star:  w_b %g e_b %g n_b %g s_b %g nw_b %g sw_b %g ne_b %g se_B %g b %g\n",
+	    star->W_B, star->E_B, star->N_B, star->S_B, star->NW_B,
+	    star->SW_B, star->NE_B, star->SE_B, star->B);
+
+
+
+    return star;
+}
+
+
+/* *************************************************************** * 
+ * ****************** N_set_les_callback_3d_func ***************** * 
+ * *************************************************************** */
+/*!
+ * \brief Set the callback function which is called while assembling the les in 3d
+ *
+ * \param data N_les_callback_3d *
+ * \param callback_func_3d N_data_star *
+ * \return void
+ * */
+void
+N_set_les_callback_3d_func(N_les_callback_3d * data,
+			   N_data_star * (*callback_func_3d) ())
+{
+    data->callback = callback_func_3d;
+}
+
+/* *************************************************************** * 
+ * *************** N_set_les_callback_2d_func ******************** * 
+ * *************************************************************** */
+/*!
+ * \brief Set the callback function which is called while assembling the les in 2d
+ *
+ * \param data N_les_callback_2d *
+ * \param callback_func_2d N_data_star * 
+ * \return void
+ * */
+void
+N_set_les_callback_2d_func(N_les_callback_2d * data,
+			   N_data_star * (*callback_func_2d) ())
+{
+    data->callback = callback_func_2d;
+}
+
+/* *************************************************************** * 
+ * ************** N_alloc_les_callback_3d ************************ * 
+ * *************************************************************** */
+/*!
+ * \brief Allocate the structure holding the callback function
+ *
+ * A template callback is set. Use N_set_les_callback_3d_func
+ * to set up a specific function.
+ *
+ * \return N_les_callback_3d *
+ * */
+N_les_callback_3d *N_alloc_les_callback_3d(void)
+{
+    N_les_callback_3d *call;
+
+    call = (N_les_callback_3d *) G_calloc(1, sizeof(N_les_callback_3d *));
+    call->callback = N_callback_template_3d;
+
+    return call;
+}
+
+/* *************************************************************** * 
+ * *************** N_alloc_les_callback_2d *********************** * 
+ * *************************************************************** */
+/*!
+ * \brief Allocate the structure holding the callback function
+ *
+ * A template callback is set. Use N_set_les_callback_2d_func
+ * to set up a specific function.
+ *
+ * \return N_les_callback_2d *
+ * */
+N_les_callback_2d *N_alloc_les_callback_2d(void)
+{
+    N_les_callback_2d *call;
+
+    call = (N_les_callback_2d *) G_calloc(1, sizeof(N_les_callback_2d *));
+    call->callback = N_callback_template_2d;
+
+    return call;
+}
+
+/* *************************************************************** * 
+ * ******************** N_callback_template_3d ******************* * 
+ * *************************************************************** */
+/*!
+ * \brief A callback template creates a 7 point star structure
+ *
+ * This is a template callback for mass balance calculation with 7 point stars
+ * based on 3d data (g3d).
+ *
+ * \param data void *
+ * \param geom N_geom_data *
+ * \param depth int
+ * \param row   int
+ * \param col   int
+ * \return N_data_star *
+ *
+ * */
+N_data_star *N_callback_template_3d(void *data, N_geom_data * geom, int col,
+				    int row, int depth)
+{
+    N_data_star *star = N_alloc_7star();
+
+    star->E = 1 / geom->dx;
+    star->W = 1 / geom->dx;
+    star->N = 1 / geom->dy;
+    star->S = 1 / geom->dy;
+    star->T = 1 / geom->dz;
+    star->B = 1 / geom->dz;
+    star->C = -1 * (2 / geom->dx + 2 / geom->dy + 2 / geom->dz);
+    star->V = -1;
+
+    G_debug(5,
+	    "N_callback_template_3d:  w %g e %g n %g s %g t %g b %g c %g v %g\n",
+	    star->W, star->E, star->N, star->S, star->T, star->B, star->C,
+	    star->V);
+
+
+    return star;
+}
+
+/* *************************************************************** * 
+ * ********************* N_callback_template_2d ****************** * 
+ * *************************************************************** */
+/*!
+ * \brief A callback template creates a 9 point star structure
+ *
+ * This is a template callback for mass balance calculation with 9 point stars
+ * based on 2d data (raster).
+ *
+ * \param data void *
+ * \param geom N_geom_data *
+ * \param row int
+ * \param col int
+ * \return N_data_star *
+ *
+ * */
+N_data_star *N_callback_template_2d(void *data, N_geom_data * geom, int col,
+				    int row)
+{
+    N_data_star *star = N_alloc_9star();
+
+    star->E = 1 / geom->dx;
+    star->NE = 1 / sqrt(geom->dx * geom->dx + geom->dy * geom->dy);
+    star->SE = 1 / sqrt(geom->dx * geom->dx + geom->dy * geom->dy);
+    star->W = 1 / geom->dx;
+    star->NW = 1 / sqrt(geom->dx * geom->dx + geom->dy * geom->dy);
+    star->SW = 1 / sqrt(geom->dx * geom->dx + geom->dy * geom->dy);
+    star->N = 1 / geom->dy;
+    star->S = 1 / geom->dy;
+    star->C =
+	-1 * (star->E + star->NE + star->SE + star->W + star->NW + star->SW +
+	      star->N + star->S);
+    star->V = 0;
+
+    return star;
+}
+
+/* *************************************************************** * 
+ * ******************** N_assemble_les_2d ************************ * 
+ * *************************************************************** */
+/*!
+ * \brief Assemble a linear equation system (les) based on 2d location data (raster) and active cells
+ *
+ * This function calls #N_assemble_les_2d_param
+ *
+ */
+N_les *N_assemble_les_2d(int les_type, N_geom_data * geom,
+			 N_array_2d * status, N_array_2d * start_val,
+			 void *data, N_les_callback_2d * call)
+{
+    return N_assemble_les_2d_param(les_type, geom, status, start_val, data,
+				   call, N_CELL_ACTIVE);
+}
+
+/*!
+ * \brief Assemble a linear equation system (les) based on 2d location data (raster) and active cells
+ *
+ * This function calls #N_assemble_les_2d_param
+ *
+ */
+N_les *N_assemble_les_2d_active(int les_type, N_geom_data * geom,
+				N_array_2d * status, N_array_2d * start_val,
+				void *data, N_les_callback_2d * call)
+{
+    return N_assemble_les_2d_param(les_type, geom, status, start_val, data,
+				   call, N_CELL_ACTIVE);
+}
+
+/*!
+ * \brief Assemble a linear equation system (les) based on 2d location data (raster) and active and dirichlet cells
+ *
+ * This function calls #N_assemble_les_2d_param
+ *
+ */
+N_les *N_assemble_les_2d_dirichlet(int les_type, N_geom_data * geom,
+				   N_array_2d * status,
+				   N_array_2d * start_val, void *data,
+				   N_les_callback_2d * call)
+{
+    return N_assemble_les_2d_param(les_type, geom, status, start_val, data,
+				   call, N_CELL_DIRICHLET);
+}
+
+/*!
+ * \brief Assemble a linear equation system (les) based on 2d location data  (raster)
+ *
+ * 
+ * The linear equation system type can be set to N_NORMAL_LES to create a regular
+ * matrix, or to N_SPARSE_LES to create a sparse matrix. This function returns
+ * a new created linear equation system which can be solved with 
+ * linear equation solvers. An 2d array with start values and an 2d status array
+ * must be provided as well as the location geometry and a void pointer to data 
+ * passed to the callback which creates the les row entries. This callback
+ * must be defined in the N_les_callback_2d strcuture.
+ *
+ * The creation of the les is parallelized with OpenMP. 
+ * If you implement new callbacks, please make sure that the 
+ * function calls are thread safe.
+ *
+ *
+ * the les can be created in two ways, with dirichlet and similar cells and without them,
+ * to spare some memory. If the les is created with dirichlet cell, the dirichlet boundary condition
+ * must be added.
+ *
+ * \param les_type int
+ * \param geom      N_geom_data*
+ * \param status    N_array_2d *
+ * \param start_val N_array_2d *
+ * \param data void *
+ * \param cell_type int  -- les assemble based on N_CELL_ACTIVE or N_CELL_DIRICHLET
+ * \param call N_les_callback_2d *
+ * \return N_les *
+ * */
+N_les *N_assemble_les_2d_param(int les_type, N_geom_data * geom,
+			       N_array_2d * status, N_array_2d * start_val,
+			       void *data, N_les_callback_2d * call,
+			       int cell_type)
+{
+    int i, j, count = 0, pos = 0;
+    int cell_type_count = 0;
+    int **index_ij;
+    N_array_2d *cell_count;
+    N_les *les = NULL;
+
+    G_debug(2,
+	    "N_assemble_les_2d: starting to assemble the linear equation system");
+
+    /* At first count the number of valid cells and save 
+     * each number in a new 2d array. Those numbers are used 
+     * to create the linear equation system.
+     * */
+
+    cell_count = N_alloc_array_2d(geom->cols, geom->rows, 1, CELL_TYPE);
+
+    /* include dirichlet cells in the les */
+    if (cell_type == N_CELL_DIRICHLET) {
+	for (j = 0; j < geom->rows; j++) {
+	    for (i = 0; i < geom->cols; i++) {
+		/*use all non-inactive cells for les creation */
+		if (N_CELL_INACTIVE < N_get_array_2d_c_value(status, i, j) &&
+		    N_get_array_2d_c_value(status, i, j) < N_MAX_CELL_STATE)
+		    cell_type_count++;
+	    }
+	}
+    }
+    /*use only active cell in the les */
+    if (cell_type == N_CELL_ACTIVE) {
+	for (j = 0; j < geom->rows; j++) {
+	    for (i = 0; i < geom->cols; i++) {
+		/*count only active cells */
+		if (N_CELL_ACTIVE == N_get_array_2d_d_value(status, i, j))
+		    cell_type_count++;
+	    }
+	}
+    }
+
+    G_debug(2, "N_assemble_les_2d: number of used cells %i\n",
+	    cell_type_count);
+
+    if (cell_type_count == 0)
+	G_fatal_error
+	    ("Not enough cells [%i] to create the linear equation system. Check the cell status. Only active cells (value = 1) are used to create the equation system.",
+	     cell_type_count);
+
+    /* Then allocate the memory for the linear equation system (les). 
+     * Only valid cells are used to create the les. */
+    index_ij = (int **)G_calloc(cell_type_count, sizeof(int *));
+    for (i = 0; i < cell_type_count; i++)
+	index_ij[i] = (int *)G_calloc(2, sizeof(int));
+
+    les = N_alloc_les_Ax_b(cell_type_count, les_type);
+
+    count = 0;
+
+    /*count the number of cells which should be used to create the linear equation system */
+    /*save the i and j indices and create a ordered numbering */
+    for (j = 0; j < geom->rows; j++) {
+	for (i = 0; i < geom->cols; i++) {
+	    /*count every non-inactive cell */
+	    if (cell_type == N_CELL_DIRICHLET) {
+		if (N_CELL_INACTIVE < N_get_array_2d_c_value(status, i, j) &&
+		    N_get_array_2d_c_value(status, i, j) < N_MAX_CELL_STATE) {
+		    N_put_array_2d_c_value(cell_count, i, j, count);
+		    index_ij[count][0] = i;
+		    index_ij[count][1] = j;
+		    count++;
+		    G_debug(5,
+			    "N_assemble_les_2d: non-inactive cells count %i at pos x[%i] y[%i]\n",
+			    count, i, j);
+		}
+		/*count every active cell */
+	    }
+	    else if (N_CELL_ACTIVE == N_get_array_2d_c_value(status, i, j)) {
+		N_put_array_2d_c_value(cell_count, i, j, count);
+		index_ij[count][0] = i;
+		index_ij[count][1] = j;
+		count++;
+		G_debug(5,
+			"N_assemble_les_2d: active cells count %i at pos x[%i] y[%i]\n",
+			count, i, j);
+	    }
+	}
+    }
+
+    G_debug(2, "N_assemble_les_2d: starting the parallel assemble loop");
+
+    /* Assemble the matrix in parallel */
+#pragma omp parallel for private(i, j, pos, count) schedule(static)
+    for (count = 0; count < cell_type_count; count++) {
+	i = index_ij[count][0];
+	j = index_ij[count][1];
+
+	/*create the entries for the */
+	N_data_star *items = call->callback(data, geom, i, j);
+
+	/* we need a sparse vector pointer anytime */
+	G_math_spvector *spvect = NULL;
+
+	/*allocate a sprase vector */
+	if (les_type == N_SPARSE_LES) {
+	    spvect = G_math_alloc_spvector(items->count);
+	}
+	/* initial conditions */
+	les->x[count] = N_get_array_2d_d_value(start_val, i, j);
+
+	/* the entry in the vector b */
+	les->b[count] = items->V;
+
+	/* pos describes the position in the sparse vector.
+	 * the first entry is always the diagonal entry of the matrix*/
+	pos = 0;
+
+	if (les_type == N_SPARSE_LES) {
+	    spvect->index[pos] = count;
+	    spvect->values[pos] = items->C;
+	}
+	else {
+	    les->A[count][count] = items->C;
+	}
+	/* western neighbour, entry is col - 1 */
+	if (i > 0) {
+	    pos = make_les_entry_2d(i, j, -1, 0, count, pos, les, spvect,
+				    cell_count, status, start_val, items->W,
+				    cell_type);
+	}
+	/* eastern neighbour, entry col + 1 */
+	if (i < geom->cols - 1) {
+	    pos = make_les_entry_2d(i, j, 1, 0, count, pos, les, spvect,
+				    cell_count, status, start_val, items->E,
+				    cell_type);
+	}
+	/* northern neighbour, entry row - 1 */
+	if (j > 0) {
+	    pos =
+		make_les_entry_2d(i, j, 0, -1, count, pos, les, spvect,
+				  cell_count, status, start_val, items->N,
+				  cell_type);
+	}
+	/* southern neighbour, entry row + 1 */
+	if (j < geom->rows - 1) {
+	    pos = make_les_entry_2d(i, j, 0, 1, count, pos, les, spvect,
+				    cell_count, status, start_val, items->S,
+				    cell_type);
+	}
+	/*in case of a nine point star, we have additional entries */
+	if (items->type == N_9_POINT_STAR) {
+	    /* north-western neighbour, entry is col - 1 row - 1 */
+	    if (i > 0 && j > 0) {
+		pos = make_les_entry_2d(i, j, -1, -1, count, pos, les, spvect,
+					cell_count, status, start_val,
+					items->NW, cell_type);
+	    }
+	    /* north-eastern neighbour, entry col + 1 row - 1 */
+	    if (i < geom->cols - 1 && j > 0) {
+		pos = make_les_entry_2d(i, j, 1, -1, count, pos, les, spvect,
+					cell_count, status, start_val,
+					items->NE, cell_type);
+	    }
+	    /* south-western neighbour, entry is col - 1 row + 1 */
+	    if (i > 0 && j < geom->rows - 1) {
+		pos = make_les_entry_2d(i, j, -1, 1, count, pos, les, spvect,
+					cell_count, status, start_val,
+					items->SW, cell_type);
+	    }
+	    /* south-eastern neighbour, entry col + 1 row + 1 */
+	    if (i < geom->cols - 1 && j < geom->rows - 1) {
+		pos = make_les_entry_2d(i, j, 1, 1, count, pos, les, spvect,
+					cell_count, status, start_val,
+					items->SE, cell_type);
+	    }
+	}
+
+	/*How many entries in the les */
+	if (les->type == N_SPARSE_LES) {
+	    spvect->cols = pos + 1;
+	    G_math_add_spvector(les->Asp, spvect, count);
+	}
+
+	if (items)
+	    G_free(items);
+    }
+
+    /*release memory */
+    N_free_array_2d(cell_count);
+
+    for (i = 0; i < cell_type_count; i++)
+	G_free(index_ij[i]);
+
+    G_free(index_ij);
+
+    return les;
+}
+
+/*!
+ * \brief Integrate Dirichlet or Transmission boundary conditions into the les (2s)
+ *
+ * Dirichlet and Transmission boundary conditions will be integrated into
+ * the provided linear equation system. This is meaningfull if
+ * the les was created with #N_assemble_les_2d_dirichlet, because in
+ * this case Dirichlet boundary conditions are not automatically included.
+ *
+ * The provided les will be modified:
+ *
+ * Ax = b will be splitted into Ax_u + Ax_d = b
+ *
+ * x_u - the unknowns
+ * x_d - the Dirichlet cells
+ *
+ * Ax_u = b -Ax_d will be computed. Then the matrix A will be modified to
+ *
+ * | A_u  0 | x_u
+ * |  0   I | x_d
+ *
+ * \param les N_les* -- the linear equation system
+ * \param geom N_geom_data* -- geometrical data information
+ * \param status N_array_2d* -- the status array containing the cell types
+ * \param start_val N_array_2d* -- an array with start values
+ * \return int -- 1 = success, 0 = failure
+ * */
+int N_les_integrate_dirichlet_2d(N_les * les, N_geom_data * geom,
+				 N_array_2d * status, N_array_2d * start_val)
+{
+    int rows, cols;
+    int count = 0;
+    int i, j, x, y, stat;
+    double *dvect1;
+    double *dvect2;
+
+    G_debug(2,
+	    "N_les_integrate_dirichlet_2d: integrating the dirichlet boundary condition");
+
+    rows = geom->rows;
+    cols = geom->cols;
+
+    /*we nned to additional vectors */
+    dvect1 = (double *)G_calloc(les->cols, sizeof(double));
+    dvect2 = (double *)G_calloc(les->cols, sizeof(double));
+
+    /*fill the first one with the x vector data of Dirichlet cells */
+    count = 0;
+    for (y = 0; y < rows; y++) {
+	for (x = 0; x < cols; x++) {
+	    stat = N_get_array_2d_c_value(status, x, y);
+	    if (stat > N_CELL_ACTIVE && stat < N_MAX_CELL_STATE) {
+		dvect1[count] = N_get_array_2d_d_value(start_val, x, y);
+		count++;
+	    }
+	    else if (stat == N_CELL_ACTIVE) {
+		dvect1[count] = 0.0;
+		count++;
+	    }
+	}
+    }
+
+#pragma omp parallel default(shared)
+    {
+	/*perform the matrix vector product and */
+	if (les->type == N_SPARSE_LES)
+	    G_math_Ax_sparse(les->Asp, dvect1, dvect2, les->rows);
+	else
+	    G_math_d_Ax(les->A, dvect1, dvect2, les->rows, les->cols);
+#pragma omp for schedule (static) private(i)
+	for (i = 0; i < les->cols; i++)
+	    les->b[i] = les->b[i] - dvect2[i];
+    }
+
+    /*now set the Dirichlet cell rows and cols to zero and the 
+     * diagonal entry to 1*/
+    count = 0;
+    for (y = 0; y < rows; y++) {
+	for (x = 0; x < cols; x++) {
+	    stat = N_get_array_2d_c_value(status, x, y);
+	    if (stat > N_CELL_ACTIVE && stat < N_MAX_CELL_STATE) {
+		if (les->type == N_SPARSE_LES) {
+		    /*set the rows to zero */
+		    for (i = 0; i < les->Asp[count]->cols; i++)
+			les->Asp[count]->values[i] = 0.0;
+		    /*set the cols to zero */
+		    for (i = 0; i < les->rows; i++) {
+			for (j = 0; j < les->Asp[i]->cols; j++) {
+			    if (les->Asp[i]->index[j] == count)
+				les->Asp[i]->values[j] = 0.0;
+			}
+		    }
+
+		    /*entry on the diagonal */
+		    les->Asp[count]->values[0] = 1.0;
+
+		}
+		else {
+		    /*set the rows to zero */
+		    for (i = 0; i < les->cols; i++)
+			les->A[count][i] = 0.0;
+		    /*set the cols to zero */
+		    for (i = 0; i < les->rows; i++)
+			les->A[i][count] = 0.0;
+
+		    /*entry on the diagonal */
+		    les->A[count][count] = 1.0;
+		}
+	    }
+	    if (stat >= N_CELL_ACTIVE)
+		count++;
+	}
+    }
+
+    return 0;
+
+}
+
+/* **************************************************************** */
+/* **** make an entry in the les (2d) ***************************** */
+/* **************************************************************** */
+int make_les_entry_2d(int i, int j, int offset_i, int offset_j, int count,
+		      int pos, N_les * les, G_math_spvector * spvect,
+		      N_array_2d * cell_count, N_array_2d * status,
+		      N_array_2d * start_val, double entry, int cell_type)
+{
+    int K;
+    int di = offset_i;
+    int dj = offset_j;
+
+    K = N_get_array_2d_c_value(cell_count, i + di, j + dj) -
+	N_get_array_2d_c_value(cell_count, i, j);
+
+    /* active cells build the linear equation system */
+    if (cell_type == N_CELL_ACTIVE) {
+	/* dirichlet or transmission cells must be handled like this */
+	if (N_get_array_2d_c_value(status, i + di, j + dj) > N_CELL_ACTIVE &&
+	    N_get_array_2d_c_value(status, i + di, j + dj) < N_MAX_CELL_STATE)
+	    les->b[count] -=
+		N_get_array_2d_d_value(start_val, i + di, j + dj) * entry;
+	else if (N_get_array_2d_c_value(status, i + di, j + dj) ==
+		 N_CELL_ACTIVE) {
+	    if ((count + K) >= 0 && (count + K) < les->cols) {
+		G_debug(5,
+			" make_les_entry_2d: (N_CELL_ACTIVE) create matrix entry at row[%i] col[%i] value %g\n",
+			count, count + K, entry);
+		pos++;
+		if (les->type == N_SPARSE_LES) {
+		    spvect->index[pos] = count + K;
+		    spvect->values[pos] = entry;
+		}
+		else {
+		    les->A[count][count + K] = entry;
+		}
+	    }
+	}
+    }				/* if dirichlet cells should be used then check for all valid cell neighbours */
+    else if (cell_type == N_CELL_DIRICHLET) {
+	/* all valid cells */
+	if (N_get_array_2d_c_value(status, i + di, j + dj) > N_CELL_INACTIVE
+	    && N_get_array_2d_c_value(status, i + di,
+				      j + dj) < N_MAX_CELL_STATE) {
+	    if ((count + K) >= 0 && (count + K) < les->cols) {
+		G_debug(5,
+			" make_les_entry_2d: (N_CELL_DIRICHLET) create matrix entry at row[%i] col[%i] value %g\n",
+			count, count + K, entry);
+		pos++;
+		if (les->type == N_SPARSE_LES) {
+		    spvect->index[pos] = count + K;
+		    spvect->values[pos] = entry;
+		}
+		else {
+		    les->A[count][count + K] = entry;
+		}
+	    }
+	}
+    }
+
+    return pos;
+}
+
+
+/* *************************************************************** * 
+ * ******************** N_assemble_les_3d ************************ * 
+ * *************************************************************** */
+/*!
+ * \brief Assemble a linear equation system (les) based on 3d location data (g3d) active cells
+ *
+ * This function calls #N_assemble_les_3d_param
+ * */
+N_les *N_assemble_les_3d(int les_type, N_geom_data * geom,
+			 N_array_3d * status, N_array_3d * start_val,
+			 void *data, N_les_callback_3d * call)
+{
+    return N_assemble_les_3d_param(les_type, geom, status, start_val, data,
+				   call, N_CELL_ACTIVE);
+}
+
+/*!
+ * \brief Assemble a linear equation system (les) based on 3d location data (g3d) active cells
+ *
+ * This function calls #N_assemble_les_3d_param
+ * */
+N_les *N_assemble_les_3d_active(int les_type, N_geom_data * geom,
+				N_array_3d * status, N_array_3d * start_val,
+				void *data, N_les_callback_3d * call)
+{
+    return N_assemble_les_3d_param(les_type, geom, status, start_val, data,
+				   call, N_CELL_ACTIVE);
+}
+
+/*!
+ * \brief Assemble a linear equation system (les) based on 3d location data (g3d) active and dirichlet cells
+ *
+ * This function calls #N_assemble_les_3d_param
+ * */
+N_les *N_assemble_les_3d_dirichlet(int les_type, N_geom_data * geom,
+				   N_array_3d * status,
+				   N_array_3d * start_val, void *data,
+				   N_les_callback_3d * call)
+{
+    return N_assemble_les_3d_param(les_type, geom, status, start_val, data,
+				   call, N_CELL_DIRICHLET);
+}
+
+/*!
+ * \brief Assemble a linear equation system (les) based on 3d location data (g3d)
+ *
+ * The linear equation system type can be set to N_NORMAL_LES to create a regular
+ * matrix, or to N_SPARSE_LES to create a sparse matrix. This function returns
+ * a new created linear equation system which can be solved with 
+ * linear equation solvers. An 3d array with start values and an 3d status array
+ * must be provided as well as the location geometry and a void pointer to data 
+ * passed to the callback which creates the les row entries. This callback
+ * must be defined in the N_les_callback_3d structure.
+ * 
+ * The creation of the les is parallelized with OpenMP. 
+ * If you implement new callbacks, please make sure that the 
+ * function calls are thread safe.
+ *
+ * the les can be created in two ways, with dirichlet and similar cells and without them,
+ * to spare some memory. If the les is created with dirichlet cell, the dirichlet boundary condition
+ * must be added.
+ *
+ * \param les_type int
+ * \param geom      N_geom_data*
+ * \param status    N_array_3d *
+ * \param start_val N_array_3d *
+ * \param data void *
+ * \param call N_les_callback_3d *
+ * \param cell_type int  -- les assemble based on N_CELL_ACTIVE or N_CELL_DIRICHLET
+ * \return N_les *
+ * */
+N_les *N_assemble_les_3d_param(int les_type, N_geom_data * geom,
+			       N_array_3d * status, N_array_3d * start_val,
+			       void *data, N_les_callback_3d * call,
+			       int cell_type)
+{
+    int i, j, k, count = 0, pos = 0;
+    int cell_type_count = 0;
+    N_array_3d *cell_count;
+    N_les *les = NULL;
+    int **index_ij;
+
+    G_debug(2,
+	    "N_assemble_les_3d: starting to assemble the linear equation system");
+
+    cell_count =
+	N_alloc_array_3d(geom->cols, geom->rows, geom->depths, 1, DCELL_TYPE);
+
+    /* First count the number of valid cells and save  
+     * each number in a new 3d array. Those numbers are used 
+     * to create the linear equation system.*/
+
+    if (cell_type == N_CELL_DIRICHLET) {
+	/* include dirichlet cells in the les */
+	for (k = 0; k < geom->depths; k++) {
+	    for (j = 0; j < geom->rows; j++) {
+		for (i = 0; i < geom->cols; i++) {
+		    /*use all non-inactive cells for les creation */
+		    if (N_CELL_INACTIVE <
+			(int)N_get_array_3d_d_value(status, i, j, k) &&
+			(int)N_get_array_3d_d_value(status, i, j,
+						    k) < N_MAX_CELL_STATE)
+			cell_type_count++;
+		}
+	    }
+	}
+    }
+    else {
+	/*use only active cell in the les */
+	for (k = 0; k < geom->depths; k++) {
+	    for (j = 0; j < geom->rows; j++) {
+		for (i = 0; i < geom->cols; i++) {
+		    /*count only active cells */
+		    if (N_CELL_ACTIVE
+			== (int)N_get_array_3d_d_value(status, i, j, k))
+			cell_type_count++;
+
+		}
+	    }
+	}
+    }
+
+    G_debug(2,
+	    "N_assemble_les_3d: number of  used cells %i\n", cell_type_count);
+
+    if (cell_type_count == 0.0)
+	G_fatal_error
+	    ("Not enough active cells [%i] to create the linear equation system. Check the cell status. Only active cells (value = 1) are used to create the equation system.",
+	     cell_type_count);
+
+    /* allocate the memory for the linear equation system (les). 
+     * Only valid cells are used to create the les. */
+    les = N_alloc_les_Ax_b(cell_type_count, les_type);
+
+    index_ij = (int **)G_calloc(cell_type_count, sizeof(int *));
+    for (i = 0; i < cell_type_count; i++)
+	index_ij[i] = (int *)G_calloc(3, sizeof(int));
+
+    count = 0;
+    /*count the number of cells which should be used to create the linear equation system */
+    /*save the k, i and j indices and create a ordered numbering */
+    for (k = 0; k < geom->depths; k++) {
+	for (j = 0; j < geom->rows; j++) {
+	    for (i = 0; i < geom->cols; i++) {
+		if (cell_type == N_CELL_DIRICHLET) {
+		    if (N_CELL_INACTIVE <
+			(int)N_get_array_3d_d_value(status, i, j, k) &&
+			(int)N_get_array_3d_d_value(status, i, j,
+						    k) < N_MAX_CELL_STATE) {
+			N_put_array_3d_d_value(cell_count, i, j, k, count);
+			index_ij[count][0] = i;
+			index_ij[count][1] = j;
+			index_ij[count][2] = k;
+			count++;
+			G_debug(5,
+				"N_assemble_les_3d: non-inactive cells count %i at pos x[%i] y[%i] z[%i]\n",
+				count, i, j, k);
+		    }
+		}
+		else if (N_CELL_ACTIVE ==
+			 (int)N_get_array_3d_d_value(status, i, j, k)) {
+		    N_put_array_3d_d_value(cell_count, i, j, k, count);
+		    index_ij[count][0] = i;
+		    index_ij[count][1] = j;
+		    index_ij[count][2] = k;
+		    count++;
+		    G_debug(5,
+			    "N_assemble_les_3d: active cells count %i at pos x[%i] y[%i] z[%i]\n",
+			    count, i, j, k);
+		}
+	    }
+	}
+    }
+
+    G_debug(2, "N_assemble_les_3d: starting the parallel assemble loop");
+
+#pragma omp parallel for private(i, j, k, pos, count) schedule(static)
+    for (count = 0; count < cell_type_count; count++) {
+	i = index_ij[count][0];
+	j = index_ij[count][1];
+	k = index_ij[count][2];
+
+	/*create the entries for the */
+	N_data_star *items = call->callback(data, geom, i, j, k);
+
+	G_math_spvector *spvect = NULL;
+
+	/*allocate a sprase vector */
+	if (les_type == N_SPARSE_LES)
+	    spvect = G_math_alloc_spvector(items->count);
+	/* initial conditions */
+
+	les->x[count] = N_get_array_3d_d_value(start_val, i, j, k);
+
+	/* the entry in the vector b */
+	les->b[count] = items->V;
+
+	/* pos describes the position in the sparse vector.
+	 * the first entry is always the diagonal entry of the matrix*/
+	pos = 0;
+
+	if (les_type == N_SPARSE_LES) {
+	    spvect->index[pos] = count;
+	    spvect->values[pos] = items->C;
+	}
+	else {
+	    les->A[count][count] = items->C;
+	}
+	/* western neighbour, entry is col - 1 */
+	if (i > 0) {
+	    pos =
+		make_les_entry_3d(i, j, k, -1, 0, 0, count, pos, les, spvect,
+				  cell_count, status, start_val, items->W,
+				  cell_type);
+	}
+	/* eastern neighbour, entry col + 1 */
+	if (i < geom->cols - 1) {
+	    pos = make_les_entry_3d(i, j, k, 1, 0, 0, count, pos, les, spvect,
+				    cell_count, status, start_val, items->E,
+				    cell_type);
+	}
+	/* northern neighbour, entry row -1 */
+	if (j > 0) {
+	    pos =
+		make_les_entry_3d(i, j, k, 0, -1, 0, count, pos, les, spvect,
+				  cell_count, status, start_val, items->N,
+				  cell_type);
+	}
+	/* southern neighbour, entry row +1 */
+	if (j < geom->rows - 1) {
+	    pos = make_les_entry_3d(i, j, k, 0, 1, 0, count, pos, les, spvect,
+				    cell_count, status, start_val, items->S,
+				    cell_type);
+	}
+	/*only for a 7 star entry needed */
+	if (items->type == N_7_POINT_STAR || items->type == N_27_POINT_STAR) {
+	    /* the upper cell (top), entry depth + 1 */
+	    if (k < geom->depths - 1) {
+		pos =
+		    make_les_entry_3d(i, j, k, 0, 0, 1, count, pos, les,
+				      spvect, cell_count, status, start_val,
+				      items->T, cell_type);
+	    }
+	    /* the lower cell (bottom), entry depth - 1 */
+	    if (k > 0) {
+		pos =
+		    make_les_entry_3d(i, j, k, 0, 0, -1, count, pos, les,
+				      spvect, cell_count, status, start_val,
+				      items->B, cell_type);
+	    }
+	}
+
+	/*How many entries in the les */
+	if (les->type == N_SPARSE_LES) {
+	    spvect->cols = pos + 1;
+	    G_math_add_spvector(les->Asp, spvect, count);
+	}
+
+	if (items)
+	    G_free(items);
+    }
+
+    N_free_array_3d(cell_count);
+
+    for (i = 0; i < cell_type_count; i++)
+	G_free(index_ij[i]);
+
+    G_free(index_ij);
+
+    return les;
+}
+
+/*!
+ * \brief Integrate Dirichlet or Transmission boundary conditions into the les (3d)
+ *
+ * Dirichlet and Transmission boundary conditions will be integrated into
+ * the provided linear equation system. This is meaningfull if
+ * the les was created with #N_assemble_les_2d_dirichlet, because in
+ * this case Dirichlet boundary conditions are not automatically included.
+ *
+ * The provided les will be modified:
+ *
+ * Ax = b will be splitted into Ax_u + Ax_d = b
+ *
+ * x_u - the unknowns
+ * x_d - the Dirichlet cells
+ *
+ * Ax_u = b -Ax_d will be computed. Then the matrix A will be modified to
+ *
+ * | A_u  0 | x_u
+ * |  0   I | x_d
+ *
+ * \param les N_les* -- the linear equation system
+ * \param geom N_geom_data* -- geometrical data information
+ * \param status N_array_2d* -- the status array containing the cell types
+ * \param start_val N_array_2d* -- an array with start values
+ * \return int -- 1 = success, 0 = failure
+ * */
+int N_les_integrate_dirichlet_3d(N_les * les, N_geom_data * geom,
+				 N_array_3d * status, N_array_3d * start_val)
+{
+    int rows, cols, depths;
+    int count = 0;
+    int i, j, x, y, z, stat;
+    double *dvect1;
+    double *dvect2;
+
+    G_debug(2,
+	    "N_les_integrate_dirichlet_3d: integrating the dirichlet boundary condition");
+
+    rows = geom->rows;
+    cols = geom->cols;
+    depths = geom->depths;
+
+    /*we nned to additional vectors */
+    dvect1 = (double *)G_calloc(les->cols, sizeof(double));
+    dvect2 = (double *)G_calloc(les->cols, sizeof(double));
+
+    /*fill the first one with the x vector data of Dirichlet cells */
+    count = 0;
+    for (z = 0; z < depths; z++) {
+	for (y = 0; y < rows; y++) {
+	    for (x = 0; x < cols; x++) {
+		stat = (int)N_get_array_3d_d_value(status, x, y, z);
+		if (stat > N_CELL_ACTIVE && stat < N_MAX_CELL_STATE) {
+		    dvect1[count] =
+			N_get_array_3d_d_value(start_val, x, y, z);
+		    count++;
+		}
+		else if (stat == N_CELL_ACTIVE) {
+		    dvect1[count] = 0.0;
+		    count++;
+		}
+	    }
+	}
+    }
+
+#pragma omp parallel default(shared)
+    {
+	/*perform the matrix vector product and */
+	if (les->type == N_SPARSE_LES)
+	    G_math_Ax_sparse(les->Asp, dvect1, dvect2, les->rows);
+	else
+	    G_math_d_Ax(les->A, dvect1, dvect2, les->rows, les->cols);
+#pragma omp for schedule (static) private(i)
+	for (i = 0; i < les->cols; i++)
+	    les->b[i] = les->b[i] - dvect2[i];
+    }
+
+    /*now set the Dirichlet cell rows and cols to zero and the 
+     * diagonal entry to 1*/
+    count = 0;
+    for (z = 0; z < depths; z++) {
+	for (y = 0; y < rows; y++) {
+	    for (x = 0; x < cols; x++) {
+		stat = (int)N_get_array_3d_d_value(status, x, y, z);
+		if (stat > N_CELL_ACTIVE && stat < N_MAX_CELL_STATE) {
+		    if (les->type == N_SPARSE_LES) {
+			/*set the rows to zero */
+			for (i = 0; i < les->Asp[count]->cols; i++)
+			    les->Asp[count]->values[i] = 0.0;
+			/*set the cols to zero */
+			for (i = 0; i < les->rows; i++) {
+			    for (j = 0; j < les->Asp[i]->cols; j++) {
+				if (les->Asp[i]->index[j] == count)
+				    les->Asp[i]->values[j] = 0.0;
+			    }
+			}
+
+			/*entry on the diagonal */
+			les->Asp[count]->values[0] = 1.0;
+
+		    }
+		    else {
+			/*set the rows to zero */
+			for (i = 0; i < les->cols; i++)
+			    les->A[count][i] = 0.0;
+			/*set the cols to zero */
+			for (i = 0; i < les->rows; i++)
+			    les->A[i][count] = 0.0;
+
+			/*entry on the diagonal */
+			les->A[count][count] = 1.0;
+		    }
+		}
+		count++;
+	    }
+	}
+    }
+
+    return 0;
+
+}
+
+/* **************************************************************** */
+/* **** make an entry in the les (3d) ***************************** */
+/* **************************************************************** */
+int make_les_entry_3d(int i, int j, int k, int offset_i, int offset_j,
+		      int offset_k, int count, int pos, N_les * les,
+		      G_math_spvector * spvect, N_array_3d * cell_count,
+		      N_array_3d * status, N_array_3d * start_val,
+		      double entry, int cell_type)
+{
+    int K;
+    int di = offset_i;
+    int dj = offset_j;
+    int dk = offset_k;
+
+    K = (int)N_get_array_3d_d_value(cell_count, i + di, j + dj, k + dk) -
+	(int)N_get_array_3d_d_value(cell_count, i, j, k);
+
+    if (cell_type == N_CELL_ACTIVE) {
+	if ((int)N_get_array_3d_d_value(status, i + di, j + dj, k + dk) >
+	    N_CELL_ACTIVE &&
+	    (int)N_get_array_3d_d_value(status, i + di, j + dj,
+					k + dk) < N_MAX_CELL_STATE)
+	    les->b[count] -=
+		N_get_array_3d_d_value(start_val, i + di, j + dj,
+				       k + dk) * entry;
+	else if ((int)N_get_array_3d_d_value(status, i + di, j + dj, k + dk)
+		 == N_CELL_ACTIVE) {
+	    if ((count + K) >= 0 && (count + K) < les->cols) {
+		G_debug(5,
+			" make_les_entry_3d: (N_CELL_ACTIVE) create matrix entry at row[%i] col[%i] value %g\n",
+			count, count + K, entry);
+		pos++;
+		if (les->type == N_SPARSE_LES) {
+		    spvect->index[pos] = count + K;
+		    spvect->values[pos] = entry;
+		}
+		else {
+		    les->A[count][count + K] = entry;
+		}
+	    }
+	}
+    }
+    else if (cell_type == N_CELL_DIRICHLET) {
+	if ((int)N_get_array_3d_d_value(status, i + di, j + dj, k + dk)
+	    != N_CELL_INACTIVE) {
+	    if ((count + K) >= 0 && (count + K) < les->cols) {
+		G_debug(5,
+			" make_les_entry_3d: (N_CELL_DIRICHLET) create matrix entry at row[%i] col[%i] value %g\n",
+			count, count + K, entry);
+		pos++;
+		if (les->type == N_SPARSE_LES) {
+		    spvect->index[pos] = count + K;
+		    spvect->values[pos] = entry;
+		}
+		else {
+		    les->A[count][count + K] = entry;
+		}
+	    }
+	}
+    }
+
+    return pos;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_parse_options.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_parse_options.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_parse_options.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_parse_options.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,111 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:      standard parser option for the numerical pde library
+*
+* COPYRIGHT:    (C) 2000 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grass/glocale.h>
+#include <grass/N_pde.h>
+
+/*!
+ * \brief Create standardised Option structure related to the gpde library.
+ *
+ * This function will create a standardised Option structure
+ * defined by parameter opt. A list of valid parameters can be found in N_pde.h.
+ * It allocates memory for the Option structure and returns a pointer to
+ * this memory (of <i>type struct Option *</i>).<br>
+ *
+ * If an invalid parameter was specified an empty Option structure will
+ * be returned (not NULL).
+ *
+ * This function is related to the gpde library, general standard options can be 
+ * found in lib/gis/parser.c. These options are set with G_define_standard_option ();
+ *
+ * \param[in] opt Type of Option struct to create
+ * \return Option * Pointer to an Option struct
+ *
+ * */
+struct Option *N_define_standard_option(int opt)
+{
+    struct Option *Opt;
+
+    Opt = G_define_option();
+
+    switch (opt) {
+	/*solver for symmetric, positive definite linear equation systems */
+    case N_OPT_SOLVER_SYMM:
+	Opt->key = "solver";
+	Opt->type = TYPE_STRING;
+	Opt->required = NO;
+	Opt->key_desc = "name";
+	Opt->answer = "cg";
+	Opt->options = "gauss,lu,cholesky,jacobi,sor,cg,bicgstab,pcg";
+        Opt->guisection = "Solver";
+	Opt->description =
+	    ("The type of solver which should solve the symmetric linear equation system");
+	break;
+	/*solver for unsymmetric linear equation systems */
+    case N_OPT_SOLVER_UNSYMM:
+	Opt->key = "solver";
+	Opt->type = TYPE_STRING;
+	Opt->required = NO;
+	Opt->key_desc = "name";
+	Opt->answer = "bicgstab";
+	Opt->options = "gauss,lu,jacobi,sor,bicgstab";
+        Opt->guisection = "Solver";
+	Opt->description =
+	    ("The type of solver which should solve the linear equation system");
+	break;
+    case N_OPT_MAX_ITERATIONS:
+	Opt->key = "maxit";
+	Opt->type = TYPE_INTEGER;
+	Opt->required = NO;
+	Opt->answer = "10000";
+        Opt->guisection = "Solver";
+	Opt->description =
+	    ("Maximum number of iteration used to solve the linear equation system");
+	break;
+    case N_OPT_ITERATION_ERROR:
+	Opt->key = "error";
+	Opt->type = TYPE_DOUBLE;
+	Opt->required = NO;
+	Opt->answer = "0.000001";
+        Opt->guisection = "Solver";
+	Opt->description =
+	    ("Error break criteria for iterative solver");
+	break;
+    case N_OPT_SOR_VALUE:
+	Opt->key = "relax";
+	Opt->type = TYPE_DOUBLE;
+	Opt->required = NO;
+	Opt->answer = "1";
+        Opt->guisection = "Solver";
+	Opt->description =
+	    ("The relaxation parameter used by the jacobi and sor solver for speedup or stabilizing");
+	break;
+    case N_OPT_CALC_TIME:
+	Opt->key = "dt";
+	Opt->type = TYPE_DOUBLE;
+	Opt->required = YES;
+	Opt->answer = "86400";
+        Opt->guisection = "Solver";
+	Opt->description = _("The calculation time in seconds");
+	break;
+    }
+
+    return Opt;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_solute_transport.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_solute_transport.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_solute_transport.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_solute_transport.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,772 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:      solute transport in porous media
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2007 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 <grass/N_solute_transport.h>
+
+/* ************************************************************************* *
+ * ************************************************************************* *
+ * ************************************************************************* */
+/*! \brief This is just a placeholder
+ *
+ * */
+N_data_star *N_callback_solute_transport_3d(void *solutedata,
+					    N_geom_data * geom, int col,
+					    int row, int depth)
+{
+    double Df_e = 0, Df_w = 0, Df_n = 0, Df_s = 0, Df_t = 0, Df_b = 0;
+    double dx, dy, dz, Az;
+    double diff_x, diff_y, diff_z;
+    double diff_xw, diff_yn;
+    double diff_xe, diff_ys;
+    double diff_zt, diff_zb;
+    double cin = 0, cg, cg_start;
+    double R, nf, cs, q;
+    double C, W, E, N, S, T, B, V;
+    double vw = 0, ve = 0, vn = 0, vs = 0, vt = 0, vb = 0;
+    double Ds_w = 0, Ds_e = 0, Ds_n = 0, Ds_s = 0, Ds_t = 0, Ds_b = 0;
+    double Dw = 0, De = 0, Dn = 0, Ds = 0, Dt = 0, Db = 0;
+    double rw = 0.5, re = 0.5, rn = 0.5, rs = 0.5, rt = 0.5, rb = 0.5;
+
+    N_solute_transport_data3d *data = NULL;
+    N_data_star *mat_pos;
+    N_gradient_3d grad;
+
+    /*cast the void pointer to the right data structure */
+    data = (N_solute_transport_data3d *) solutedata;
+
+    N_get_gradient_3d(data->grad, &grad, col, row, depth);
+
+    dx = geom->dx;
+    dy = geom->dy;
+    dz = geom->dz;
+    Az = N_get_geom_data_area_of_cell(geom, row);
+
+    /*read the data from the arrays */
+    cg_start = N_get_array_3d_d_value(data->c_start, col, row, depth);
+    cg = N_get_array_3d_d_value(data->c, col, row, depth);
+
+    /*get the surrounding diffusion tensor entries */
+    diff_x = N_get_array_3d_d_value(data->diff_x, col, row, depth);
+    diff_y = N_get_array_3d_d_value(data->diff_y, col, row, depth);
+    diff_z = N_get_array_3d_d_value(data->diff_z, col, row, depth);
+    diff_xw = N_get_array_3d_d_value(data->diff_x, col - 1, row, depth);
+    diff_xe = N_get_array_3d_d_value(data->diff_x, col + 1, row, depth);
+    diff_yn = N_get_array_3d_d_value(data->diff_y, col, row - 1, depth);
+    diff_ys = N_get_array_3d_d_value(data->diff_y, col, row + 1, depth);
+    diff_zt = N_get_array_3d_d_value(data->diff_z, col, row, depth + 1);
+    diff_zb = N_get_array_3d_d_value(data->diff_z, col, row, depth - 1);
+
+    /* calculate the diffusion on the cell borders using the harmonical mean */
+    Df_w = N_calc_harmonic_mean(diff_xw, diff_x);
+    Df_e = N_calc_harmonic_mean(diff_xe, diff_x);
+    Df_n = N_calc_harmonic_mean(diff_yn, diff_y);
+    Df_s = N_calc_harmonic_mean(diff_ys, diff_y);
+    Df_t = N_calc_harmonic_mean(diff_zt, diff_z);
+    Df_b = N_calc_harmonic_mean(diff_zb, diff_z);
+
+    /* calculate the dispersion */
+    /*todo */
+
+    /* calculate the velocity parts  with full upwinding scheme */
+    vw = grad.WC;
+    ve = grad.EC;
+    vn = grad.NC;
+    vs = grad.SC;
+    vt = grad.TC;
+    vb = grad.BC;
+
+    /* put the diffusion and dispersion together */
+    Dw = ((Df_w + Ds_w)) / dx;
+    De = ((Df_e + Ds_e)) / dx;
+    Dn = ((Df_n + Ds_n)) / dy;
+    Ds = ((Df_s + Ds_s)) / dy;
+    Dt = ((Df_t + Ds_t)) / dz;
+    Db = ((Df_b + Ds_b)) / dz;
+
+    rw = N_exp_upwinding(-1 * vw, dx, Dw);
+    re = N_exp_upwinding(ve, dx, De);
+    rs = N_exp_upwinding(-1 * vs, dy, Ds);
+    rn = N_exp_upwinding(vn, dy, Dn);
+    rb = N_exp_upwinding(-1 * vb, dz, Dn);
+    rt = N_exp_upwinding(vt, dz, Dn);
+
+    /*mass balance center cell to western cell */
+    W = -1 * (Dw) * dy * dz - vw * (1 - rw) * dy * dz;
+    /*mass balance center cell to eastern cell */
+    E = -1 * (De) * dy * dz + ve * (1 - re) * dy * dz;
+    /*mass balance center cell to southern cell */
+    S = -1 * (Ds) * dx * dz - vs * (1 - rs) * dx * dz;
+    /*mass balance center cell to northern cell */
+    N = -1 * (Dn) * dx * dz + vn * (1 - rn) * dx * dz;
+    /*mass balance center cell to bottom cell */
+    B = -1 * (Db) * Az - vb * (1 - rb) * Az;
+    /*mass balance center cell to top cell */
+    T = -1 * (Dt) * Az + vt * (1 - rt) * Az;
+
+    /* Retardation */
+    R = N_get_array_3d_d_value(data->R, col, row, depth);
+    /* Inner sources */
+    cs = N_get_array_3d_d_value(data->cs, col, row, depth);
+    /* effective porosity */
+    nf = N_get_array_3d_d_value(data->nf, col, row, depth);
+    /* groundwater sources and sinks */
+    q = N_get_array_3d_d_value(data->q, col, row, depth);
+    /* concentration of influent water */
+    cin = N_get_array_3d_d_value(data->cin, col, row, depth);
+
+    /*the diagonal entry of the matrix */
+    C = ((Dw - vw) * dy * dz +
+	 (De + ve) * dy * dz +
+	 (Ds - vs) * dx * dz +
+	 (Dn + vn) * dx * dz +
+	 (Db - vb) * Az + (Dt + vt) * Az + Az * dz * R / data->dt - q / nf);
+
+    /*the entry in the right side b of Ax = b */
+    V = (cs + cg_start * Az * dz * R / data->dt - q / nf * cin);
+
+    /*
+     * printf("nf %g\n", nf);
+     * printf("q %g\n", q);
+     * printf("cs %g\n", cs);
+     * printf("cin %g\n", cin);
+     * printf("cg %g\n", cg);
+     * printf("cg_start %g\n", cg_start);
+     * printf("Az %g\n", Az);
+     * printf("z %g\n", z);
+     * printf("R %g\n", R);
+     * printf("dt %g\n", data->dt);
+     */
+    G_debug(6, "N_callback_solute_transport_3d: called [%i][%i][%i]", row,
+	    col, depth);
+
+    /*create the 7 point star entries */
+    mat_pos = N_create_7star(C, W, E, N, S, T, B, V);
+
+    return mat_pos;
+}
+
+/* ************************************************************************* *
+ * ************************************************************************* *
+ * ************************************************************************* */
+/*!
+ * \brief This callback function creates the mass balance of a 5 point star
+ *
+ * The mass balance is based on the common solute transport equation:
+ *
+ * \f[\frac{\partial c_g}{\partial t} R = \nabla \cdot ({\bf D} \nabla c_g - {\bf u} c_g) + \sigma + \frac{q}{n_f}(c_g - c_in) \f]
+ *
+ * This equation is discretizised with the finite volume method in two dimensions.
+ *
+ *
+ * \param solutedata  * N_solute_transport_data2d - a void pointer to the data structure
+ * \param geom N_geom_data *
+ * \param col   int
+ * \param row   int
+ * \return N_data_star * - a five point data star
+ *
+ * */
+N_data_star *N_callback_solute_transport_2d(void *solutedata,
+					    N_geom_data * geom, int col,
+					    int row)
+{
+    double Df_e = 0, Df_w = 0, Df_n = 0, Df_s = 0;
+    double z_e = 0, z_w = 0, z_n = 0, z_s = 0;
+    double dx, dy, Az;
+    double diff_x, diff_y;
+    double disp_x, disp_y;
+    double z;
+    double diff_xw, diff_yn;
+    double disp_xw, disp_yn;
+    double z_xw, z_yn;
+    double diff_xe, diff_ys;
+    double disp_xe, disp_ys;
+    double z_xe, z_ys;
+    double cin = 0, cg, cg_start;
+    double R, nf, cs, q;
+    double C, W, E, N, S, V, NE, NW, SW, SE;
+    double vw = 0, ve = 0, vn = 0, vs = 0;
+    double Ds_w = 0, Ds_e = 0, Ds_n = 0, Ds_s = 0;
+    double Dw = 0, De = 0, Dn = 0, Ds = 0;
+    double rw = 0.5, re = 0.5, rn = 0.5, rs = 0.5;
+
+    N_solute_transport_data2d *data = NULL;
+    N_data_star *mat_pos;
+    N_gradient_2d grad;
+
+    /*cast the void pointer to the right data structure */
+    data = (N_solute_transport_data2d *) solutedata;
+
+    N_get_gradient_2d(data->grad, &grad, col, row);
+
+    dx = geom->dx;
+    dy = geom->dy;
+    Az = N_get_geom_data_area_of_cell(geom, row);
+
+    /*read the data from the arrays */
+    cg_start = N_get_array_2d_d_value(data->c_start, col, row);
+    cg = N_get_array_2d_d_value(data->c, col, row);
+
+    /* calculate the cell height */
+    z = N_get_array_2d_d_value(data->top, col,
+			       row) -
+	N_get_array_2d_d_value(data->bottom, col, row);
+    z_xw =
+	N_get_array_2d_d_value(data->top, col - 1,
+			       row) -
+	N_get_array_2d_d_value(data->bottom, col - 1, row);
+    z_xe =
+	N_get_array_2d_d_value(data->top, col + 1,
+			       row) -
+	N_get_array_2d_d_value(data->bottom, col + 1, row);
+    z_yn =
+	N_get_array_2d_d_value(data->top, col,
+			       row - 1) -
+	N_get_array_2d_d_value(data->bottom, col, row - 1);
+    z_ys =
+	N_get_array_2d_d_value(data->top, col,
+			       row + 1) -
+	N_get_array_2d_d_value(data->bottom, col, row + 1);
+
+    /*geometrical mean of cell height */
+    z_w = N_calc_geom_mean(z_xw, z);
+    z_e = N_calc_geom_mean(z_xe, z);
+    z_n = N_calc_geom_mean(z_yn, z);
+    z_s = N_calc_geom_mean(z_ys, z);
+
+    /*get the surrounding diffusion tensor entries */
+    diff_x = N_get_array_2d_d_value(data->diff_x, col, row);
+    diff_y = N_get_array_2d_d_value(data->diff_y, col, row);
+    diff_xw = N_get_array_2d_d_value(data->diff_x, col - 1, row);
+    diff_xe = N_get_array_2d_d_value(data->diff_x, col + 1, row);
+    diff_yn = N_get_array_2d_d_value(data->diff_y, col, row - 1);
+    diff_ys = N_get_array_2d_d_value(data->diff_y, col, row + 1);
+
+    /* calculate the diffusion at the cell borders using the harmonical mean */
+    Df_w = N_calc_harmonic_mean(diff_xw, diff_x);
+    Df_e = N_calc_harmonic_mean(diff_xe, diff_x);
+    Df_n = N_calc_harmonic_mean(diff_yn, diff_y);
+    Df_s = N_calc_harmonic_mean(diff_ys, diff_y);
+
+    /* calculate the dispersion */
+    /*get the surrounding dispersion tensor entries */
+    disp_x = N_get_array_2d_d_value(data->disp_xx, col, row);
+    disp_y = N_get_array_2d_d_value(data->disp_yy, col, row);
+    if (N_get_array_2d_d_value(data->status, col - 1, row) ==
+	N_CELL_TRANSMISSION) {
+	disp_xw = disp_x;
+    }
+    else {
+	disp_xw = N_get_array_2d_d_value(data->disp_xx, col - 1, row);
+    }
+    if (N_get_array_2d_d_value(data->status, col + 1, row) ==
+	N_CELL_TRANSMISSION) {
+	disp_xe = disp_x;
+    }
+    else {
+	disp_xe = N_get_array_2d_d_value(data->disp_xx, col + 1, row);
+    }
+    if (N_get_array_2d_d_value(data->status, col, row - 1) ==
+	N_CELL_TRANSMISSION) {
+	disp_yn = disp_y;
+    }
+    else {
+	disp_yn = N_get_array_2d_d_value(data->disp_yy, col, row - 1);
+    }
+    if (N_get_array_2d_d_value(data->status, col, row + 1) ==
+	N_CELL_TRANSMISSION) {
+	disp_ys = disp_y;
+    }
+    else {
+	disp_ys = N_get_array_2d_d_value(data->disp_yy, col, row + 1);
+    }
+
+    /* calculate the dispersion at the cell borders using the harmonical mean */
+    Ds_w = N_calc_harmonic_mean(disp_xw, disp_x);
+    Ds_e = N_calc_harmonic_mean(disp_xe, disp_x);
+    Ds_n = N_calc_harmonic_mean(disp_yn, disp_y);
+    Ds_s = N_calc_harmonic_mean(disp_ys, disp_y);
+
+    /* put the diffusion and dispersion together */
+    Dw = ((Df_w + Ds_w)) / dx;
+    De = ((Df_e + Ds_e)) / dx;
+    Ds = ((Df_s + Ds_s)) / dy;
+    Dn = ((Df_n + Ds_n)) / dy;
+
+    vw = -1.0 * grad.WC;
+    ve = grad.EC;
+    vs = -1.0 * grad.SC;
+    vn = grad.NC;
+
+    if (data->stab == N_UPWIND_FULL) {
+	rw = N_full_upwinding(vw, dx, Dw);
+	re = N_full_upwinding(ve, dx, De);
+	rs = N_full_upwinding(vs, dy, Ds);
+	rn = N_full_upwinding(vn, dy, Dn);
+    }
+    else if (data->stab == N_UPWIND_EXP) {
+	rw = N_exp_upwinding(vw, dx, Dw);
+	re = N_exp_upwinding(ve, dx, De);
+	rs = N_exp_upwinding(vs, dy, Ds);
+	rn = N_exp_upwinding(vn, dy, Dn);
+    }
+
+    /*mass balance center cell to western cell */
+    W = -1 * (Dw) * dy * z_w + vw * (1 - rw) * dy * z_w;
+    /*mass balance center cell to eastern cell */
+    E = -1 * (De) * dy * z_e + ve * (1 - re) * dy * z_e;
+    /*mass balance center cell to southern cell */
+    S = -1 * (Ds) * dx * z_s + vs * (1 - rs) * dx * z_s;
+    /*mass balance center cell to northern cell */
+    N = -1 * (Dn) * dx * z_n + vn * (1 - rn) * dx * z_n;
+
+    NW = 0.0;
+    SW = 0.0;
+    NE = 0.0;
+    SE = 0.0;
+
+    /* Retardation */
+    R = N_get_array_2d_d_value(data->R, col, row);
+    /* Inner sources */
+    cs = N_get_array_2d_d_value(data->cs, col, row);
+    /* effective porosity */
+    nf = N_get_array_2d_d_value(data->nf, col, row);
+    /* groundwater sources and sinks */
+    q = N_get_array_2d_d_value(data->q, col, row);
+    /* concentration of influent water */
+    cin = N_get_array_2d_d_value(data->cin, col, row);
+
+    /*the diagonal entry of the matrix */
+    C = (Dw + vw * rw) * dy * z_w +
+	(De + ve * re) * dy * z_e +
+	(Ds + vs * rs) * dx * z_s +
+	(Dn + vn * rn) * dx * z_n + Az * z * R / data->dt - q / nf;
+
+    /*the entry in the right side b of Ax = b */
+    V = (cs + cg_start * Az * z * R / data->dt + q / nf * cin);
+
+    /*
+       fprintf(stderr, "nf %g\n", nf);
+       fprintf(stderr, "q %g\n", q);
+       fprintf(stderr, "cs %g\n", cs);
+       fprintf(stderr, "cin %g\n", cin);
+       fprintf(stderr, "cg %g\n", cg);
+       fprintf(stderr, "cg_start %g\n", cg_start);
+       fprintf(stderr, "Az %g\n", Az);
+       fprintf(stderr, "z %g\n", z);
+       fprintf(stderr, "R %g\n", R);
+       fprintf(stderr, "dt %g\n", data->dt);
+     */
+
+    G_debug(6, "N_callback_solute_transport_2d: called [%i][%i]", row, col);
+
+    /*create the 9 point star entries */
+    mat_pos = N_create_9star(C, W, E, N, S, NW, SW, NE, SE, V);
+
+    return mat_pos;
+}
+
+/* ************************************************************************* *
+ * ************************************************************************* *
+ * ************************************************************************* */
+/*!
+ * \brief Alllocate memory for the solute transport data structure in three dimensions
+ *
+ * The solute transport data structure will be allocated including
+ * all appendant 3d arrays. The offset for the 3d arrays is one
+ * to establish homogeneous Neumann boundary conditions at the calculation area border.
+ * This data structure is used to create a linear equation system based on the computation of
+ * solute transport in porous media with the finite volume method.
+ *
+ * \param cols   int
+ * \param rows   int
+ * \param depths int
+ * \return N_solute_transport_data3d *
+ * */
+
+N_solute_transport_data3d *N_alloc_solute_transport_data3d(int cols, int rows,
+							   int depths)
+{
+    N_solute_transport_data3d *data = NULL;
+
+    data =
+	(N_solute_transport_data3d *) G_calloc(1,
+					       sizeof
+					       (N_solute_transport_data3d));
+
+    data->c = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->c_start = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->status = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->diff_x = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->diff_y = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->diff_z = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->q = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->cs = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->R = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->nf = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->cin = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+
+    /*Allocate the dispersivity tensor */
+    data->disp_xx = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->disp_yy = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->disp_zz = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->disp_xy = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->disp_xz = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+    data->disp_yz = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
+
+
+    data->grad = N_alloc_gradient_field_3d(cols, rows, depths);
+    data->stab = N_UPWIND_EXP;
+
+    return data;
+}
+
+/* ************************************************************************* *
+ * ************************************************************************* *
+ * ************************************************************************* */
+/*!
+ * \brief Alllocate memory for the solute transport data structure in two dimensions
+ *
+ * The solute transport data structure will be allocated including
+ * all appendant 2d arrays. The offset for the 2d arrays is one
+ * to establish homogeneous Neumann boundary conditions at the calculation area border.
+ * This data structure is used to create a linear equation system based on the computation of
+ * solute transport in porous media with the finite volume method.
+ *
+ * \param cols   int
+ * \param rows   int
+ * \return N_solute_transport_data2d *
+ * */
+
+
+N_solute_transport_data2d *N_alloc_solute_transport_data2d(int cols, int rows)
+{
+    N_solute_transport_data2d *data = NULL;
+
+    data =
+	(N_solute_transport_data2d *) G_calloc(1,
+					       sizeof
+					       (N_solute_transport_data2d));
+
+    data->c = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->c_start = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->status = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->diff_x = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->diff_y = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->q = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->cs = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->R = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->nf = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->cin = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->top = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->bottom = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+
+    /*Allocate the dispersivity tensor */
+    data->disp_xx = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->disp_yy = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+    data->disp_xy = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
+
+    data->grad = N_alloc_gradient_field_2d(cols, rows);
+    data->stab = N_UPWIND_EXP;
+
+    return data;
+}
+
+/* ************************************************************************* *
+ * ************************************************************************* *
+ * ************************************************************************* */
+/*!
+ * \brief Release the memory of the solute transport data structure in three dimensions
+ *
+ * \param data N_solute_transport_data2d *
+ * \return void *
+ * */
+void N_free_solute_transport_data3d(N_solute_transport_data3d * data)
+{
+    N_free_array_3d(data->c);
+    N_free_array_3d(data->c_start);
+    N_free_array_3d(data->status);
+    N_free_array_3d(data->diff_x);
+    N_free_array_3d(data->diff_y);
+    N_free_array_3d(data->diff_z);
+    N_free_array_3d(data->q);
+    N_free_array_3d(data->cs);
+    N_free_array_3d(data->R);
+    N_free_array_3d(data->nf);
+    N_free_array_3d(data->cin);
+
+    N_free_array_3d(data->disp_xx);
+    N_free_array_3d(data->disp_yy);
+    N_free_array_3d(data->disp_zz);
+    N_free_array_3d(data->disp_xy);
+    N_free_array_3d(data->disp_xz);
+    N_free_array_3d(data->disp_yz);
+
+    G_free(data);
+
+    data = NULL;
+
+    return;
+}
+
+/* ************************************************************************* *
+ * ************************************************************************* *
+ * ************************************************************************* */
+/*!
+ * \brief Release the memory of the solute transport data structure in two dimensions
+ *
+ * \param data N_solute_transport_data2d *
+ * \return void *
+ * */
+void N_free_solute_transport_data2d(N_solute_transport_data2d * data)
+{
+    N_free_array_2d(data->c);
+    N_free_array_2d(data->c_start);
+    N_free_array_2d(data->status);
+    N_free_array_2d(data->diff_x);
+    N_free_array_2d(data->diff_y);
+    N_free_array_2d(data->q);
+    N_free_array_2d(data->cs);
+    N_free_array_2d(data->R);
+    N_free_array_2d(data->nf);
+    N_free_array_2d(data->cin);
+    N_free_array_2d(data->top);
+    N_free_array_2d(data->bottom);
+
+    N_free_array_2d(data->disp_xx);
+    N_free_array_2d(data->disp_yy);
+    N_free_array_2d(data->disp_xy);
+
+    G_free(data);
+
+    data = NULL;
+
+    return;
+}
+
+/*!
+ * \brief Compute the transmission boundary condition in 2d
+ *
+ * This function calculates the transmission boundary condition
+ * for each cell with status N_CELL_TRANSMISSION. The surrounding
+ * gradient field is used to verfiy the flow direction. If a flow
+ * goes into a cell, the concentration (data->c) from the neighbour cell is
+ * added to the transmission cell. If the flow from several neighbour 
+ * cells goes into the cell, the concentration mean is calculated.
+ * 
+ * The new concentrations are written into the data->c_start array,
+ * so they can be handled by the matrix assembling function.
+ *
+ * \param data N_solute_transport_data2d *
+ * \return void *
+ * */
+void N_calc_solute_transport_transmission_2d(N_solute_transport_data2d * data)
+{
+    int i, j, count = 1;
+    int cols, rows;
+    double c;
+    N_gradient_2d grad;
+
+    cols = data->grad->cols;
+    rows = data->grad->rows;
+
+    G_debug(2,
+	    "N_calc_solute_transport_transmission_2d: calculating transmission boundary");
+
+    for (j = 0; j < rows; j++) {
+	for (i = 0; i < cols; i++) {
+	    if (N_get_array_2d_d_value(data->status, i, j) ==
+		N_CELL_TRANSMISSION) {
+		count = 0;
+		/*get the gradient neighbours */
+		N_get_gradient_2d(data->grad, &grad, i, j);
+		c = 0;
+		/*
+		   c = N_get_array_2d_d_value(data->c_start, i, j);
+		   if(c > 0)
+		   count++;
+		 */
+
+		if (grad.WC > 0 &&
+		    !N_is_array_2d_value_null(data->c, i - 1, j)) {
+		    c += N_get_array_2d_d_value(data->c, i - 1, j);
+		    count++;
+		}
+		if (grad.EC < 0 &&
+		    !N_is_array_2d_value_null(data->c, i + 1, j)) {
+		    c += N_get_array_2d_d_value(data->c, i + 1, j);
+		    count++;
+		}
+		if (grad.NC < 0 &&
+		    !N_is_array_2d_value_null(data->c, i, j - 1)) {
+		    c += N_get_array_2d_d_value(data->c, i, j - 1);
+		    count++;
+		}
+		if (grad.SC > 0 &&
+		    !N_is_array_2d_value_null(data->c, i, j + 1)) {
+		    c += N_get_array_2d_d_value(data->c, i, j + 1);
+		    count++;
+		}
+		if (count != 0)
+		    c = c / (double)count;
+		/*make sure it is not NAN */
+		if (c > 0 || c == 0 || c < 0)
+		    N_put_array_2d_d_value(data->c_start, i, j, c);
+	    }
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief Compute the dispersivity tensor based on the solute transport data in 2d
+ *
+ * The dispersivity tensor is stored in the data structure.
+ * To compute the dispersivity tensor, the dispersivity lentghs and the gradient field
+ * must be present.
+ *
+ * This is just a simple tensor computation which should be extended.
+ *
+ * \todo Change the tensor calculation to a mor realistic algorithm 
+ *
+ * \param data N_solute_transport_data2d *
+ * \return void *
+ * */
+void N_calc_solute_transport_disptensor_2d(N_solute_transport_data2d * data)
+{
+    int i, j;
+    int cols, rows;
+    double vx, vy, vv;
+    double disp_xx, disp_yy, disp_xy;
+    N_gradient_2d grad;
+
+    cols = data->grad->cols;
+    rows = data->grad->rows;
+
+    G_debug(2,
+	    "N_calc_solute_transport_disptensor_2d: calculating the dispersivity tensor");
+
+    for (j = 0; j < rows; j++) {
+	for (i = 0; i < cols; i++) {
+
+	    disp_xx = 0;
+	    disp_yy = 0;
+	    disp_xy = 0;
+
+	    /*get the gradient neighbours */
+	    N_get_gradient_2d(data->grad, &grad, i, j);
+	    vx = (grad.WC + grad.EC) / 2;
+	    vy = (grad.NC + grad.SC) / 2;
+	    vv = sqrt(vx * vx + vy * vy);
+
+	    if (vv != 0) {
+		disp_xx = data->al * vx * vx / vv + data->at * vy * vy / vv;
+		disp_yy = data->at * vx * vx / vv + data->al * vy * vy / vv;
+		disp_xy = (data->al - data->at) * vx * vy / vv;
+	    }
+
+	    G_debug(5,
+		    "N_calc_solute_transport_disptensor_2d: [%i][%i] disp_xx %g disp_yy %g disp_xy %g",
+		    i, j, disp_xx, disp_yy, disp_xy);
+	    N_put_array_2d_d_value(data->disp_xx, i, j, disp_xx);
+	    N_put_array_2d_d_value(data->disp_yy, i, j, disp_yy);
+	    N_put_array_2d_d_value(data->disp_xy, i, j, disp_xy);
+	}
+    }
+
+    return;
+}
+
+/*!
+ * \brief Compute the dispersivity tensor based on the solute transport data in 3d
+ *
+ * The dispersivity tensor is stored in the data structure.
+ * To compute the dispersivity tensor, the dispersivity lentghs and the gradient field
+ * must be present.
+ * 
+ * This is just a simple tensor computation which should be extended.
+ *
+ * \todo Change the tensor calculation to a mor realistic algorithm 
+ *
+ * \param data N_solute_transport_data3d *
+ * \return void *
+ * */
+void N_calc_solute_transport_disptensor_3d(N_solute_transport_data3d * data)
+{
+    int i, j, k;
+    int cols, rows, depths;
+    double vx, vy, vz, vv;
+    double disp_xx, disp_yy, disp_zz, disp_xy, disp_xz, disp_yz;
+    N_gradient_3d grad;
+
+    cols = data->grad->cols;
+    rows = data->grad->rows;
+    depths = data->grad->depths;
+
+    G_debug(2,
+	    "N_calc_solute_transport_disptensor_3d: calculating the dispersivity tensor");
+
+    for (k = 0; k < depths; k++) {
+	for (j = 0; j < rows; j++) {
+	    for (i = 0; i < cols; i++) {
+		disp_xx = 0;
+		disp_yy = 0;
+		disp_zz = 0;
+		disp_xy = 0;
+		disp_xz = 0;
+		disp_yz = 0;
+
+		/*get the gradient neighbours */
+		N_get_gradient_3d(data->grad, &grad, i, j, k);
+		vx = (grad.WC + grad.EC) / 2;
+		vy = (grad.NC + grad.SC) / 2;
+		vz = (grad.BC + grad.TC) / 2;
+		vv = sqrt(vx * vx + vy * vy + vz * vz);
+
+		if (vv != 0) {
+		    disp_xx =
+			data->al * vx * vx / vv + data->at * vy * vy / vv +
+			data->at * vz * vz / vv;
+		    disp_yy =
+			data->at * vx * vx / vv + data->al * vy * vy / vv +
+			data->at * vz * vz / vv;
+		    disp_zz =
+			data->at * vx * vx / vv + data->at * vy * vy / vv +
+			data->al * vz * vz / vv;
+		    disp_xy = (data->al - data->at) * vx * vy / vv;
+		    disp_xz = (data->al - data->at) * vx * vz / vv;
+		    disp_yz = (data->al - data->at) * vy * vz / vv;
+		}
+
+		G_debug(5,
+			"N_calc_solute_transport_disptensor_3d: [%i][%i][%i] disp_xx %g disp_yy %g disp_zz %g  disp_xy %g disp_xz %g disp_yz %g ",
+			i, j, k, disp_xx, disp_yy, disp_zz, disp_xy, disp_xz,
+			disp_yz);
+		N_put_array_3d_d_value(data->disp_xx, i, j, k, disp_xx);
+		N_put_array_3d_d_value(data->disp_yy, i, j, k, disp_yy);
+		N_put_array_3d_d_value(data->disp_zz, i, j, k, disp_zz);
+		N_put_array_3d_d_value(data->disp_xy, i, j, k, disp_xy);
+		N_put_array_3d_d_value(data->disp_xz, i, j, k, disp_xz);
+		N_put_array_3d_d_value(data->disp_yz, i, j, k, disp_yz);
+	    }
+	}
+    }
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_tools.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_tools.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_tools.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_tools.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,200 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:     	Array managment functions 
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+#include <grass/glocale.h>
+
+
+/*!
+ * \brief Calculate the arithmetic mean of values a and b
+ *
+ * mean = (a+b)/2
+ *
+ * \param a double
+ * \param b double
+ * \return val double
+ * */
+double N_calc_arith_mean(double a, double b)
+{
+    double val = 0;
+
+    val = (a + b) / 2.0;
+
+    return val;
+}
+
+/*!
+ * \brief Calculate the arithmetic mean of the values in vector a
+ * of size n
+ *
+ * n = [0 ... size[
+ * mean =  (a[0] + a[1] + ... + a[n])/size
+ *
+ * \param a double * -- the value vector 
+ * \param size int -- the size of the vector a
+ * \return val double
+ * */
+double N_calc_arith_mean_n(double *a, int size)
+{
+    double val = 0.0;
+    int i;
+
+    for (i = 0; i < size; i++)
+	val += a[i];
+
+    val = (val / (double)size);
+
+    return val;
+}
+
+
+/*!
+ * \brief Calculate the geometrical mean of values a and b
+ *
+ * mean = sqrt(a*b)
+ *
+ * \param a double
+ * \param b double
+ * \return val double
+ * */
+double N_calc_geom_mean(double a, double b)
+{
+    double val = 0;
+
+    val = sqrt(a * b);
+
+    return val;
+}
+
+/*!
+ * \brief Calculate the geometrical mean of the values in vector a
+ * of size n
+ *
+ * n = [0 ... size[
+ * mean =  pow((a[0] * a[1] * ... * a[n]), 1.0/size)
+ *
+ * \param a double * -- the value vector 
+ * \param size int -- the size of the vector a
+ * \return val double
+ * */
+double N_calc_geom_mean_n(double *a, int size)
+{
+    double val = 1;
+    int i;
+
+    for (i = 0; i < size; i++)
+	val *= a[i];
+
+    val = (double)pow((long double)val, (long double)1.0 / (long double)size);
+
+    return val;
+}
+
+
+/*!
+ * \brief Calculate the harmonical mean of values a and b
+ *
+ * mean = 2*(a*b)/(a + b)
+ *
+ * \param a double
+ * \param b double
+ * \return val double -- if (a + b) == 0, a 0 is returned
+ * */
+double N_calc_harmonic_mean(double a, double b)
+{
+    double val = 0.0;
+
+    if ((a + b) != 0)
+	val = 2.0 * (a * b) / (a + b);
+
+    return val;
+}
+
+/*!
+ * \brief Calculate the harmonical mean of the values in vector a
+ * of size n
+ *
+ * n = [0 ... size[
+ * mean = 1/(1/size *(1/a[0] + 1/a[1] + ... + 1/a[n]))
+ * 
+ * \param a double * -- the value vector 
+ * \param size int -- the size of the vector a
+ * \return val double -- if one division with 0 is detected, 0 will be returned
+ * */
+double N_calc_harmonic_mean_n(double *a, int size)
+{
+    double val = 0;
+    int i;
+
+    for (i = 0; i < size; i++)
+	if (a[i] != 0.0)
+	    val += 1.0 / a[i];
+	else
+	    return 0.0;
+
+    if (val == 0.0)
+	return 0.0;
+    else
+	val = 1.0 / (1.0 / (double)size * val);
+
+    return val;
+}
+
+
+/*!
+ * \brief Calculate the quadratic mean of values a and b
+ *
+ * mean = sqrt((a*a + b*b)/2)
+ *
+ * \param a double
+ * \param b double
+ * \return val double 
+ * */
+double N_calc_quad_mean(double a, double b)
+{
+    double val = 0.0;
+
+    val = sqrt((a * a + b * b) / 2.0);
+
+    return val;
+}
+
+/*!
+ * \brief Calculate the quadratic mean of the values in vector a
+ * of size n
+ *
+ * n = [0 ... size[
+ * mean = sqrt((a[0]*a[0] + a[1]*a[1] + ... + a[n]*a[n])/size)
+ * 
+ * \param a double * -- the value vector 
+ * \param size int -- the size of the vector a
+ * \return val double 
+ * */
+double N_calc_quad_mean_n(double *a, int size)
+{
+    double val = 0;
+    int i;
+
+    for (i = 0; i < size; i++)
+	val += a[i] * a[i];
+
+    val = sqrt(val / (double)size);
+
+    return val;
+}

Copied: grass/branches/releasebranch_7_0/lib/gpde/n_upwind.c (from rev 62432, grass/branches/releasebranch_7_0/lib/gpde/N_upwind.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/gpde/n_upwind.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/gpde/n_upwind.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,77 @@
+
+/*****************************************************************************
+*
+* MODULE:       Grass PDE Numerical Library
+* AUTHOR(S):    Soeren Gebbert, Berlin (GER) Dec 2006
+* 		soerengebbert <at> gmx <dot> de
+*               
+* PURPOSE:      upwinding stabilization algorithms
+* 		part of the gpde library
+*
+* COPYRIGHT:    (C) 2000 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 <grass/N_pde.h>
+
+
+/*! \brief full upwinding stabilization algorithm
+ *
+ * The arguments are values to compute the local peclet number
+ *
+ * \param sprod double -- the scalar produkt between the velocity vector and the normal vector between two points
+ * \param distance double -- distance between two points
+ * \param D double -- diffusion/dispersion tensor part between two points
+ *
+ * \return the weighting factor
+ * */
+double N_full_upwinding(double sprod, double distance, double D)
+{
+    double z;
+
+    if (D == 0)
+	return 0.5;
+
+    /*compute the local peclet number */
+    z = sprod * distance / D;
+
+    if (z > 0)
+	return 1;
+    if (z == 0)
+	return 0.5;
+    if (z < 0)
+	return 0;
+
+    return 0;
+}
+
+/*! \brief exponential upwinding stabilization algorithm
+ *
+ * The arguments are values to compute the local peclet number
+ *
+ * \param sprod double -- the scalar produkt between the velocity vector and the normal vector between two points
+ * \param distance double -- distance between two points
+ * \param D double -- diffusion/dispersion tensor part between two points
+ *
+ * \return the weighting factor
+ * */
+double N_exp_upwinding(double sprod, double distance, double D)
+{
+    double z;
+
+    if (D == 0)
+	return 0.5;
+
+    /*compute the local peclet number */
+    z = sprod * distance / D;
+
+    if (z != 0)
+	return (1 - (1 / z) * (1 - (z / (exp(z) - 1))));
+
+    return 0.5;
+}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/GK2.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/GK2.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/GK2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,625 +0,0 @@
-/*!
-   \file GK2.c
-
-   \brief OGSF library - setting and manipulating keyframes animation
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   (C) 1999-2008 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.
-
-   \author Bill Brown USACERL, GMSL/University of Illinois
-   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
- */
-
-#include <stdlib.h>
-
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/ogsf.h>
-
-static int _add_key(Keylist *, int, float);
-static void _remove_key(Keylist *);
-
-static Keylist *Keys = NULL;
-static Keylist *Keytail = NULL;
-static Viewnode *Views = NULL;
-static float Keystartpos = 0.0;
-static float Keyendpos = 1.0;
-static float Tension = 0.8;
-static int Viewsteps = 0;
-static int Numkeys = 0;
-static int Interpmode = KF_SPLINE;
-static int Fmode = 0;
-
-/* next & prior already initialized to NULL */
-static int _add_key(Keylist * newk, int force_replace, float precis)
-{
-    Keylist *k, *tempk, *prev;
-    int found;
-
-    found = 0;
-    prev = NULL;
-
-    /* if(Viewsteps) precis = 0.5/Viewsteps; */
-    for (k = Keys; k; k = k->next) {
-	if (k->pos >= newk->pos - precis && k->pos <= newk->pos + precis) {
-	    if (force_replace) {
-
-		if (k->prior) {
-		    k->prior->next = newk;
-		    newk->prior = prev;
-		}
-		else {
-		    Keys = newk;
-		}
-
-		newk->next = k->next;
-		newk->prior = k->prior;
-		tempk = k;
-		k = newk;
-		free(tempk);
-	    }
-	    else {
-		free(newk);
-	    }
-
-	    return (-1);
-	}
-    }
-
-    if (Keys) {
-	if (newk->pos < Keys->pos) {
-	    /* new will be first */
-	    newk->next = Keys;
-	    Keys->prior = newk;
-	    Keys = newk;
-	}
-	else {
-	    prev = k = Keys;
-	    while (k && !found) {
-		if (k->pos > newk->pos) {
-		    prev->next = newk;
-		    newk->next = k;
-		    newk->prior = prev;
-		    k->prior = newk;
-		    found = 1;
-		}
-
-		prev = k;
-		k = k->next;
-	    }
-	    if (!found) {
-		Keytail = prev->next = newk;
-		newk->prior = prev;
-	    }
-	}
-    }
-    else {
-	Keys = Keytail = newk;
-    }
-
-    ++Numkeys;
-    return (1);
-}
-
-static void _remove_key(Keylist * k)
-{
-    if (k->prior) {
-	k->prior->next = k->next;
-	if (k->next) {
-	    k->next->prior = k->prior;
-	}
-	else {
-	    Keytail = k->prior;
-	}
-    }
-    else {
-	Keys = k->next;
-	if (k->next) {
-	    k->next->prior = NULL;
-	}
-    }
-    k->next = k->prior = NULL;
-
-    return;
-}
-
-/*!
-   \brief Set interpolation mode 
-
-   \param mode interpolation mode (KF_LINEAR or KF_SPLINE)
-
-   \return 1 on success
-   \return -1 on error (invalid interpolation mode)
- */
-int GK_set_interpmode(int mode)
-{
-    if (KF_LEGAL_MODE(mode)) {
-	Interpmode = mode;
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set value for tension when interpmode is KF_SPLINE. 
-
-   \param tens value tens should be between 0.0; 1.0.
- */
-void GK_set_tension(float tens)
-{
-    Tension = tens > 1.0 ? 1.0 : (tens < 0.0 ? 0.0 : tens);
-
-    /* for now */
-    if (Views) {
-	GK_update_frames();
-	GS_set_draw(GSD_BACK);
-	GS_ready_draw();
-	GS_clear(GS_background_color());
-	GS_alldraw_wire();
-
-	gk_draw_path(Views, Viewsteps, Keys);
-
-	GS_done_draw();
-    }
-
-    return;
-}
-
-void GK_showtension_start(void)
-{
-    return;
-}
-
-/*!
-   \brief Show tension stop ?
-
-   Use GK_showtension_start/GK_update_tension/GK_showtension_stop to
-   initialize and stop multi-view display of path when changing
-   tension.
- */
-void GK_showtension_stop(void)
-{
-    return;
-}
-
-/*!
-   \brief Update tension
- */
-void GK_update_tension(void)
-{
-    if (Views) {
-	GK_update_frames();
-    }
-
-    return;
-}
-
-/*!
-   \brief Print keyframe info
-
-   \param name filename
- */
-void GK_print_keys(const char *name)
-{
-    Keylist *k;
-    FILE *fp;
-    int cnt = 1;
-
-    if (NULL == (fp = fopen(name, "w"))) {
-	G_fatal_error(_("Unable to open file <%s> for writing"), name);
-    }
-    /* write a default frame rate of 30 at top of file */
-    fprintf(fp, "30 \n");
-
-    for (k = Keys; k; k = k->next) {
-
-	fprintf(fp,
-		"{%f {{FromX %f} {FromY %f} {FromZ %f} {DirX %f} {DirY %f} {DirZ %f} {FOV %f} {TWIST %f} {cplane-0 {{pos_x 0.000000} {pos_y 0.000000} {pos_z 0.000000} {blend_type OFF} {rot 0.000000} {tilt 0.000000}}}} keyanimtag%d 0} ",
-		k->pos, k->fields[KF_FROMX], k->fields[KF_FROMY],
-		k->fields[KF_FROMZ], k->fields[KF_DIRX], k->fields[KF_DIRY],
-		k->fields[KF_DIRZ], k->fields[KF_FOV] / 10.,
-		k->fields[KF_TWIST], cnt);
-	cnt++;
-    }
-
-    fclose(fp);
-    return;
-
-}
-
-/*!
-   \brief Recalculate path using the current number of frames requested.
-
-   Call after changing number of frames or when
-   Keyframes change.
- */
-void GK_update_frames(void)
-{
-    Keylist *k;
-    int loop = 0;
-
-    if (Keys) {
-	if (Numkeys > 1) {
-	    k = Keytail;
-	    Keyendpos = k->pos;
-
-	    if (k->fields[KF_FROMX] == Keys->fields[KF_FROMX] &&
-		k->fields[KF_FROMY] == Keys->fields[KF_FROMY] &&
-		k->fields[KF_FROMZ] == Keys->fields[KF_FROMZ]) {
-		loop = 1;
-	    }
-	}
-
-	Keystartpos = Keys->pos;
-    }
-
-    if (Interpmode == KF_LINEAR && Numkeys > 1) {
-	if (Views) {
-	    free(Views);
-	    Views = NULL;
-	}
-
-	Views = gk_make_linear_framesfromkeys(Keys, Numkeys, Viewsteps, loop);
-
-	if (!Views) {
-	    G_warning(_("Check no. of frames requested and keyframes marked"));
-	}
-    }
-    else if (Numkeys > 2) {
-	if (Views) {
-	    free(Views);
-	    Views = NULL;
-	}
-
-	Views = gk_make_framesfromkeys
-	    (Keys, Numkeys, Viewsteps, loop, 1.0 - Tension);
-
-	if (!Views) {
-	    G_warning(_("Check no. of frames requested and keyframes marked"));
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Set the number of frames to be interpolated from keyframes
-
-   \param newsteps number of frames
- */
-void GK_set_numsteps(int newsteps)
-{
-    Viewsteps = newsteps;
-    GK_update_frames();
-
-    return;
-}
-
-/*!
-   \brief Deletes all keyframes, resets field masks.
-
-   Doesn't change number of frames requested.
- */
-void GK_clear_keys(void)
-{
-    gk_free_key(Keys);
-    Keys = NULL;
-    Numkeys = 0;
-    free(Views);
-    Views = NULL;
-
-    Keystartpos = 0.0;
-    Keyendpos = 1.0;
-
-    return;
-}
-
-/*!
-   \brief Move keyframe
-
-   Precis works as in other functions - to identify keyframe to move.
-   Only the first keyframe in the precis range will be moved.
-
-   \param oldpos old position
-   \param precis precision value
-   \param newpos new position
-
-   \return number of keys moved (1 or 0)
- */
-int GK_move_key(float oldpos, float precis, float newpos)
-{
-    Keylist *k;
-
-    for (k = Keys; k; k = k->next) {
-	if (k->pos >= oldpos - precis && k->pos <= oldpos + precis) {
-	    _remove_key(k);
-	    k->pos = newpos;
-	    _add_key(k, 1, precis);
-	    GK_update_frames();
-	    return (1);
-	}
-    }
-
-    return (0);
-}
-
-/*!
-   Delete keyframe
-
-   The values pos and precis are used to determine which keyframes to
-   delete.  Any keyframes with their position within precis of pos will
-   be deleted if justone is zero.  If justone is non-zero, only the first
-   (lowest pos) keyframe in the range will be deleted.
-
-   \param pos position
-   \param precis precision
-   \param justone delete only one keyframe
-
-   \return number of keys deleted.
- */
-int GK_delete_key(float pos, float precis, int justone)
-{
-    Keylist *k, *next;
-    int cnt;
-
-    for (cnt = 0, k = Keys; k;) {
-	next = k->next;
-
-	if (k->pos >= pos - precis && k->pos <= pos + precis) {
-	    cnt++;
-	    _remove_key(k);
-	    free(k);
-	    if (justone) {
-		break;
-	    }
-	}
-
-	k = next;
-    }
-
-    GK_update_frames();
-    return (cnt);
-}
-
-/*!
-   \brief Add keyframe
-
-   The pos value is the relative position in the animation for this
-   particular keyframe - used to compare relative distance to neighboring
-   keyframes, it can be any floating point value.
-
-   The fmask value can be any of the following or'd together:    
-   - KF_FROMX_MASK    
-   - KF_FROMY_MASK    
-   - KF_FROMZ_MASK    
-   - KF_FROM_MASK (KF_FROMX_MASK | KF_FROMY_MASK | KF_FROMZ_MASK) 
-
-   - KF_DIRX_MASK    
-   - KF_DIRY_MASK    
-   - KF_DIRZ_MASK    
-   - KF_DIR_MASK (KF_DIRX_MASK | KF_DIRY_MASK | KF_DIRZ_MASK) 
-
-   - KF_FOV_MASK    
-   - KF_TWIST_MASK    
-
-   - KF_ALL_MASK (KF_FROM_MASK | KF_DIR_MASK | KF_FOV_MASK | KF_TWIST_MASK) 
-
-   Other fields will be added later.
-
-   The value precis and the boolean force_replace are used to determine
-   if a keyframe should be considered to be at the same position as a
-   pre-existing keyframe. e.g., if anykey.pos - newkey.pos <= precis,
-   GK_add_key() will fail unless force_replace is TRUE.
-
-   \param pos postion
-   \param fmaks
-   \param force_replace
-   \param precis precision value
-
-   \return 1 if key is added
-   \return -1 key not added
- */
-int GK_add_key(float pos, unsigned long fmask, int force_replace,
-	       float precis)
-{
-    Keylist *newk;
-    float tmp[3];
-
-    if (NULL == (newk = (Keylist *) malloc(sizeof(Keylist)))) {
-	fprintf(stderr, "Out of memory\n");
-	return (-1);
-    }
-
-    /* All fields set, don't use mask until making Views */
-
-    GS_get_from(tmp);
-    newk->fields[KF_FROMX] = tmp[X];
-    newk->fields[KF_FROMY] = tmp[Y];
-    newk->fields[KF_FROMZ] = tmp[Z];
-
-    G_debug(3, "KEY FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]);
-
-    /* Instead of View Dir try get_focus (view center) */
-    /* View Dir is implied from eye and center position */
-    /*    GS_get_viewdir(tmp); */
-
-    /* ACS 1 line: was      GS_get_focus(tmp);
-       with this kanimator works also for flythrough navigation
-       also changed in gk.c
-     */
-    GS_get_viewdir(tmp);
-    newk->fields[KF_DIRX] = tmp[X];
-    newk->fields[KF_DIRY] = tmp[Y];
-    newk->fields[KF_DIRZ] = tmp[Z];
-
-    newk->fields[KF_FOV] = GS_get_fov();
-    newk->fields[KF_TWIST] = GS_get_twist();
-    newk->pos = pos;
-    newk->fieldmask = fmask;
-    newk->next = NULL;
-    newk->prior = NULL;
-
-    if (0 < _add_key(newk, force_replace, precis)) {
-	GK_update_frames();
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Moves the animation to frame number "step".
-
-   Step should be a value between 1 and the number of frames.  If
-   render is non-zero, calls draw_all.
-
-   \param step step value
-   \param render
- */
-void GK_do_framestep(int step, int render)
-{
-    if (Views) {
-	if (step > 0 && step <= Viewsteps) {
-	    gk_follow_frames(Views, Viewsteps, Keys, step, 1, render, Fmode);
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw the current path
-
-   \param flag
- */
-void GK_show_path(int flag)
-{
-    if (flag) {
-	Fmode |= FM_PATH;
-
-	if (Views) {
-	    GS_set_draw(GSD_FRONT);
-	    GS_ready_draw();
-
-	    gk_draw_path(Views, Viewsteps, Keys);
-
-	    GS_done_draw();
-
-	}
-    }
-    else {
-	Fmode &= ~FM_PATH;
-    }
-
-    return;
-}
-
-/*!
-   \brief Show vector sets
-
-   \param flag
- */
-void GK_show_vect(int flag)
-{
-    if (flag) {
-	Fmode |= FM_VECT;
-	if (Views) {
-
-	    GS_set_draw(GSD_FRONT);
-	    GS_ready_draw();
-
-	    GV_alldraw_vect();
-
-	    GS_done_draw();
-	}
-    }
-    else {
-	Fmode &= ~FM_VECT;
-    }
-
-    return;
-}
-
-/*!
-   \brief Show point sets
-
-   \param flag
- */
-void GK_show_site(int flag)
-{
-    if (flag) {
-	Fmode |= FM_SITE;
-
-	if (Views) {
-
-	    GS_set_draw(GSD_FRONT);
-	    GS_ready_draw();
-
-	    GP_alldraw_site();
-
-	    GS_done_draw();
-
-	}
-    }
-    else {
-	Fmode &= ~FM_SITE;
-    }
-
-    return;
-}
-
-/*!
-   \brief Show volumes
-
-   \param flag
- */
-void GK_show_vol(int flag)
-{
-    if (flag) {
-	Fmode |= FM_VOL;
-
-	if (Views) {
-
-	    GS_set_draw(GSD_FRONT);
-	    GS_ready_draw();
-
-	    GVL_alldraw_vol();
-
-	    GS_done_draw();
-
-	}
-    }
-    else {
-	Fmode &= ~FM_VOL;
-    }
-
-    return;
-}
-
-/*!
-   \brief Show list
-
-   \param flag
- */
-void GK_show_list(int flag)
-{
-    if (flag) {
-	Fmode |= FM_LABEL;
-
-	if (Views) {
-	    GS_draw_all_list();
-	}
-    }
-    else {
-	Fmode &= ~FM_LABEL;
-    }
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/GP2.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/GP2.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/GP2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,710 +0,0 @@
-/*!
-   \file lib/ogsf/GP2.c
-
-   \brief OGSF library - loading and manipulating point sets (higher level functions)
-
-   (C) 1999-2008, 2011 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.
-
-   \author Bill Brown USACERL (January 1994)
-   \author Updated by Martin landa <landa.martin gmail.com>
-   (doxygenized in May 2008, thematic mapping in June 2011)
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grass/gis.h>
-#include <grass/ogsf.h>
-#include <grass/glocale.h>
-
-#include "gsget.h"
-
-static int Site_ID[MAX_SITES];
-static int Next_site = 0;
-
-/*!
-   \brief Check if point set exists
-
-   \param id point set id
-
-   \return 1 found
-   \return 0 not found
- */
-int GP_site_exists(int id)
-{
-    int i, found = 0;
-
-    G_debug(4, "GP_site_exists(%d)", id);
-
-    if (NULL == gp_get_site(id)) {
-	return 0;
-    }
-
-    for (i = 0; i < Next_site && !found; i++) {
-	if (Site_ID[i] == id) {
-	    found = 1;
-	}
-    }
-
-    G_debug(3, "GP_site_exists(): found=%d", found);
-
-    return found;
-}
-
-/*!
-   \brief Create new point set
-
-   \return point set id
-   \return -1 on error (number of point sets exceeded)
- */
-int GP_new_site(void)
-{
-    geosite *np;
-
-    if (Next_site < MAX_SITES) {
-	np = gp_get_new_site();
-	gp_set_defaults(np);
-	Site_ID[Next_site] = np->gsite_id;
-	++Next_site;
-
-	G_debug(3, "GP_new_site() id=%d", np->gsite_id);
-
-	return np->gsite_id;
-    }
-
-    return -1;
-}
-
-/*!
-   \brief Get number of loaded point sets
-
-   \return number of point sets
- */
-int GP_num_sites(void)
-{
-    return gp_num_sites();
-}
-
-/*!
-   \brief Get list of point sets
-
-   Must freed when no longer needed!
-
-   \param numsites number of point sets
-
-   \return pointer to list of points sets
-   \return NULL on error
- */
-int *GP_get_site_list(int *numsites)
-{
-    int i, *ret;
-
-    *numsites = Next_site;
-
-    if (Next_site) {
-	ret = (int *)G_malloc(Next_site * sizeof(int));	/* G_fatal_error */
-	if (!ret) {
-	    return NULL;
-	}
-
-	for (i = 0; i < Next_site; i++) {
-	    ret[i] = Site_ID[i];
-	}
-
-	return ret;
-    }
-
-    return NULL;
-}
-
-/*!
-   \brief Delete registrated point set
-
-   \param id point set id
-
-   \return 1 on success
-   \return -1 on error (point sets not available)
- */
-int GP_delete_site(int id)
-{
-    int i, j, found = 0;
-
-    G_debug(4, "GP_delete_site(%d)", id);
-
-    if (GP_site_exists(id)) {
-	gp_delete_site(id);
-
-	for (i = 0; i < Next_site && !found; i++) {
-	    if (Site_ID[i] == id) {
-		found = 1;
-		for (j = i; j < Next_site; j++) {
-		    Site_ID[j] = Site_ID[j + 1];
-		}
-	    }
-	}
-
-	if (found) {
-	    --Next_site;
-	    return 1;
-	}
-    }
-
-    return -1;
-}
-
-/*!
-   \brief Load point set from file
-
-   Check to see if handle already loaded, if so - free before loading
-   new for now, always load to memory.
-
-   \todo load file handle & ready for reading instead of using memory
-
-   \param id point set id
-   \param filename point set filename
-
-   \return -1 on error
-   \return 1 on success
- */
-int GP_load_site(int id, const char *filename)
-{
-    geosite *gp;
-
-    G_debug(3, "GP_load_site(id=%d, name=%s)", id, filename);
-
-    if (NULL == (gp = gp_get_site(id))) {
-	return -1;
-    }
-
-    if (gp->points) {
-	gp_free_sitemem(gp);
-    }
-
-    gp->filename = G_store(filename);
-
-    gp->points = Gp_load_sites(filename, &(gp->n_sites), &(gp->has_z));
-    
-    if (gp->points) {
-	return 1;
-    }
-
-    return -1;
-}
-
-/*!
-   \brief Get point set filename
-
-   Note: char array is allocated by G_store()
-
-   \param id point set id
-   \param[out] filename point set filename
-
-   \return -1 on error (point set not found)
-   \return 1 on success
- */
-int GP_get_sitename(int id, char **filename)
-{
-    geosite *gp;
-
-    G_debug(4, "GP_get_sitename(%d)", id);
-
-    if (NULL == (gp = gp_get_site(id))) {
-	return -1;
-    }
-
-    *filename = G_store(gp->filename);
-
-    return 1;
-}
-
-/*!
-   \brief Get point set style
-
-   \param id point set id
-
-   \return 1 on success
-   \return -1 on error (point set not found)
- */
-int GP_get_style(int id, int *color, int *width, float *size, int *symbol)
-{
-    geosite *gp;
-
-    G_debug(4, "GP_get_style(%d)", id);
-
-    if (NULL == (gp = gp_get_site(id))) {
-	return -1;
-    }
-
-    *color = gp->style->color;
-    *width = gp->style->width;
-    *symbol = gp->style->symbol;
-    *size = gp->style->size;
-
-    return 1;
-}
-
-/*!
-   \brief Set point style
-
-   Supported icon symbols (markers):
-    - ST_X
-    - ST_BOX
-    - ST_SPHERE
-    - ST_CUBE
-    - ST_DIAMOND
-    - ST_DEC_TREE
-    - ST_CON_TREE
-    - ST_ASTER
-    - ST_GYRO
-    - ST_HISTOGRAM
-
-   \param id point set id
-   \param color icon color
-   \param width icon line width
-   \param size icon size
-   \param symbol icon symbol
-
-   \return 1 on success
-   \return -1 on error (point set not found)
- */
-int GP_set_style(int id, int color, int width, float size, int symbol)
-{
-    geosite *gp;
-
-    G_debug(4, "GP_set_style(id=%d, color=%d, width=%d, size=%f, symbol=%d)", id, color, width, size,
-	    symbol);
-
-    if (NULL == (gp = gp_get_site(id))) {
-	return -1;
-    }
-
-    gp->style->color = color;
-    gp->style->symbol = symbol;
-    gp->style->size = size;
-    gp->style->width = width;
-
-    return 1;
-}
-
-/*!
-   \brief Set point set style for thematic mapping
-
-   Updates also style for each geopoint.
-   
-   \param id point set id
-   \param layer layer number for thematic mapping (-1 for undefined)
-   \param color icon color column name
-   \param width icon line width column name
-   \param size icon size column name
-   \param symbol icon symbol column name
-   \param colors pointer to Colors structure or NULL
-
-   \return 1 on success
-   \return -1 on error (point set not found)
- */
-int GP_set_style_thematic(int id, int layer, const char* color, const char* width,
-			  const char* size, const char* symbol, struct Colors *color_rules)
-{
-    geosite *gp;
-    
-    G_debug(4, "GP_set_style_thematic(id=%d, layer=%d, color=%s, width=%s, size=%s, symbol=%s)", id, layer,
-	    color, width, size, symbol);
-
-    if (NULL == (gp = gp_get_site(id))) {
-	return -1;
-    }
-
-    if(!gp->tstyle)
-	gp->tstyle = (gvstyle_thematic *)G_malloc(sizeof(gvstyle_thematic));
-    G_zero(gp->tstyle, sizeof(gvstyle_thematic));
-    
-    gp->tstyle->active = 1;
-    gp->tstyle->layer = layer;
-    if (color)
-	gp->tstyle->color_column = G_store(color);
-    if (symbol)
-	gp->tstyle->symbol_column = G_store(symbol);
-    if (size)
-	gp->tstyle->size_column = G_store(size);
-    if (width)
-	gp->tstyle->width_column = G_store(width);
-
-    Gp_load_sites_thematic(gp, color_rules);
-
-    return 1;
-}
-
-/*!
-   \brief Make style for thematic mapping inactive
-   
-   \param id point set id
-
-   \return 1 on success
-   \return -1 on error (point set not found)
- */
-int GP_unset_style_thematic(int id)
-{
-    geosite *gp;
-
-    G_debug(4, "GP_unset_style_thematic(): id=%d", id);
-
-    if (NULL == (gp = gp_get_site(id))) {
-	return -1;
-    }
-
-    if (gp->tstyle) {
-	gp->tstyle->active = 0;
-    }
-
-    return 1;
-}
-
-/*!
-   \brief Set z mode for point set
-
-   \param id point set id
-   \param use_z TRUE to use z-coordinaces when vector map is 3D
-
-   \return 1 on success
-   \return 0 vector map is not 3D
-   \return -1 on error (invalid point set id)
- */
-/* I don't see who is using it? Why it's required? */
-int GP_set_zmode(int id, int use_z)
-{
-    geosite *gp;
-
-    G_debug(3, "GP_set_zmode(%d,%d)", id, use_z);
-
-    if (NULL == (gp = gp_get_site(id))) {
-	return -1;
-    }
-
-    if (use_z) {
-	if (gp->has_z) {
-	    gp->use_z = 1;
-	    return 1;
-	}
-
-	return 0;
-    }
-
-    gp->use_z = 0;
-    return 1;
-}
-
-/*!
-   \brief Get z-mode
-
-   \todo Who's using this?
-   
-   \param id point set id
-   \param[out] use_z non-zero code to use z
-
-   \return -1 on error (invalid point set id)
-   \return 1 on success
- */
-int GP_get_zmode(int id, int *use_z)
-{
-    geosite *gp;
-
-    G_debug(4, "GP_get_zmode(%d)", id);
-
-    if (NULL == (gp = gp_get_site(id))) {
-	return -1;
-    }
-
-    *use_z = gp->use_z;
-    return 1;
-}
-
-/*!
-   \brief Set transformation params
-
-   \param id point set id
-   \param xtrans,ytrans,ztrans x/y/z values
- */
-void GP_set_trans(int id, float xtrans, float ytrans, float ztrans)
-{
-    geosite *gp;
-
-    G_debug(3, "GP_set_trans(): id=%d trans=%f,%f,%f",
-	    id, xtrans, ytrans, ztrans);
-
-    gp = gp_get_site(id);
-    if (gp) {
-	gp->x_trans = xtrans;
-	gp->y_trans = ytrans;
-	gp->z_trans = ztrans;
-    }
-
-    return;
-}
-
-/*!
-   \brief Get transformation params
-
-   \param id point set id
-   \param[out] xtrans,ytrans,ztrans x/y/z values
- */
-void GP_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
-{
-    geosite *gp;
-
-    gp = gp_get_site(id);
-
-    if (gp) {
-	*xtrans = gp->x_trans;
-	*ytrans = gp->y_trans;
-	*ztrans = gp->z_trans;
-    }
-
-    G_debug(3, "GP_get_trans(): id=%d, trans=%f,%f,%f",
-	    id, *xtrans, *ytrans, *ztrans);
-
-    return;
-}
-
-/*!
-   \brief Select surface for given point set
-
-   \param hp point set id
-   \param hs surface id
-
-   \return 1 surface selected
-   \return -1 on error
- */
-int GP_select_surf(int hp, int hs)
-{
-    geosite *gp;
-
-    G_debug(3, "GP_select_surf(%d,%d)", hp, hs);
-
-    if (GP_surf_is_selected(hp, hs)) {
-	return 1;
-    }
-
-    gp = gp_get_site(hp);
-
-    if (gp && GS_surf_exists(hs)) {
-	gp->drape_surf_id[gp->n_surfs] = hs;
-	gp->n_surfs += 1;
-	return 1;
-    }
-
-    return -1;
-}
-
-/*!
-   \brief Unselect surface
-
-   \param hp point set id
-   \param hs surface id
-
-   \return 1 surface unselected
-   \return -1 on error
- */
-int GP_unselect_surf(int hp, int hs)
-{
-    geosite *gp;
-    int i, j;
-
-    G_debug(3, "GP_unselect_surf(%d,%d)", hp, hs);
-
-    if (!GP_surf_is_selected(hp, hs)) {
-	return 1;
-    }
-
-    gp = gp_get_site(hp);
-
-    if (gp) {
-	for (i = 0; i < gp->n_surfs; i++) {
-	    if (gp->drape_surf_id[i] == hs) {
-		for (j = i; j < gp->n_surfs - 1; j++) {
-		    gp->drape_surf_id[j] = gp->drape_surf_id[j + 1];
-		}
-
-		gp->n_surfs -= 1;
-		return 1;
-	    }
-	}
-    }
-
-    return -1;
-}
-
-/*!
-   \brief Check if surface is selected
-
-   \param hp point set id
-   \param hs surface id
-
-   \return 1 selected
-   \return 0 not selected
- */
-int GP_surf_is_selected(int hp, int hs)
-{
-    int i;
-    geosite *gp;
-
-    G_debug(3, "GP_surf_is_selected(%d,%d)", hp, hs);
-
-    gp = gp_get_site(hp);
-
-    if (gp) {
-	for (i = 0; i < gp->n_surfs; i++) {
-	    if (hs == gp->drape_surf_id[i]) {
-		return 1;
-	    }
-	}
-    }
-
-    return 0;
-}
-
-/*!
-   \brief Draw point set
-
-   \param id point set id
- */
-void GP_draw_site(int id)
-{
-    geosurf *gs;
-    geosite *gp;
-    int i;
-    float n, yo, xo, e;
-
-    gp = gp_get_site(id);
-    GS_get_region(&n, &yo, &xo, &e);
-
-    /* kind of sloppy - maybe site files should have an origin, too */
-    if (gp) {
-	if (gp->use_z && gp->has_z) {
-	    gpd_3dsite(gp, xo, yo, 0);
-	}
-	else {
-	    for (i = 0; i < gp->n_surfs; i++) {
-		gs = gs_get_surf(gp->drape_surf_id[i]);
-
-		if (gs) {
-		    gpd_2dsite(gp, gs, 0);
-		    G_debug(5, "Drawing site %d on Surf %d", id,
-			    gp->drape_surf_id[i]);
-		}
-	    }
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw all available point sets
- */
-void GP_alldraw_site(void)
-{
-    int id;
-
-    for (id = 0; id < Next_site; id++) {
-	GP_draw_site(Site_ID[id]);
-    }
-
-    return;
-}
-
-/*!
-   \brief Set client data
-
-   \param id point set id
-   \param clientd client data
-
-   \return 1 on success
-   \return -1 on error (invalid point set id)
- */
-int GP_Set_ClientData(int id, void *clientd)
-{
-    geosite *gp;
-
-    gp = gp_get_site(id);
-
-    if (gp) {
-	gp->clientdata = clientd;
-	return 1;
-    }
-
-    return -1;
-}
-
-/*!
-   \brief Get client data
-
-   \param id point set id
-
-   \return pointer to client data
-   \return NULL on error
- */
-void *GP_Get_ClientData(int id)
-{
-    geosite *gp;
-
-    gp = gp_get_site(id);
-    if (gp) {
-	return (gp->clientdata);
-    }
-
-    return NULL;
-}
-
-/*!
-  \brief Determine point marker symbol for string
-
-  Supported markers:
-    - ST_X
-    - ST_BOX
-    - ST_SPHERE
-    - ST_CUBE
-    - ST_DIAMOND
-    - ST_DEC_TREE
-    - ST_CON_TREE
-    - ST_ASTER
-    - ST_GYRO
-    - ST_HISTOGRAM
-
-  \param str string buffer
-
-  \return marker code (default: ST_SPHERE)
-*/
-int GP_str_to_marker(const char *str)
-{
-    int marker;
-
-    if (strcmp(str, "x") == 0)
-	marker = ST_X;
-    else if (strcmp(str, "box") == 0)
-	marker = ST_BOX;
-    else if (strcmp(str, "sphere") == 0)
-	marker = ST_SPHERE;
-    else if (strcmp(str, "cube") == 0)
-	marker = ST_CUBE;
-    else if (strcmp(str, "diamond") == 0)
-	marker = ST_DIAMOND;
-    else if (strcmp(str, "dec_tree") == 0)
-	marker = ST_DEC_TREE;
-    else if (strcmp(str, "con_tree") == 0)
-	marker = ST_CON_TREE;
-    else if (strcmp(str, "aster") == 0)
-	marker = ST_ASTER;
-    else if (strcmp(str, "gyro") == 0)
-	marker = ST_GYRO;
-    else if (strcmp(str, "histogram") == 0)
-	marker = ST_HISTOGRAM;
-    else {
-	G_warning(_("Unknown icon marker, using \"sphere\""));
-	marker = ST_SPHERE;
-    }
-
-    return marker;
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/GS2.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/GS2.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/GS2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,3498 +0,0 @@
-/*!
-   \file GS2.c
-
-   \brief OGSF library - loading and manipulating surfaces (higher level functions)
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   Plans for handling color maps:
-   NOW:
-   if able to load as unsigned char, make lookup table containing palette
-   otherwise, load directly as packed color, set lookup = NULL
-   MAYBE LATER:
-   if able to load as POSITIVE short, make lookup table containing palette
-   - may want to calculate savings first (ie,  numcells > 32768)
-   (not exactly, it's Friday & time to go home - figure it later)
-   otherwise, load directly as packed color, set lookup = NULL
-   MESSY! - need to fix up!
-
-   (C) 1999-2008 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.
-
-   \author Bill Brown USACERL (1993)
-   \author Pierre de Mouveaux <p_de_mouveaux hotmail.com> (updated October 1999)
-   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include <grass/config.h>
-
-#if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
-#include <GL/gl.h>
-#include <GL/glu.h>
-#elif defined(OPENGL_AQUA)
-#include <OpenGL/gl.h>
-#include <OpenGL/glu.h>
-#endif
-
-#include <grass/gis.h>
-#include <grass/raster.h>
-#include <grass/ogsf.h>
-#include <grass/glocale.h>
-
-#include "gsget.h"
-#include "rowcol.h"
-#include "rgbpack.h"
-
-/* Hack to make NVIZ2.2 query functions.("What's Here" and "Look at")
- * to work.
- * Uses gs_los_intersect1() instead of gs_los_intersect().
- * Pierre de Mouveaux - 31 oct. 1999. p_de_mouveaux at hotmail.com.
- */
-#define NVIZ_HACK 1
-
-int gsd_getViewport(GLint *, GLint *);
-
-/* array of surface ids */
-static int Surf_ID[MAX_SURFS];
-static int Next_surf = 0;
-static int SDref_surf = 0;
-
-/* attributes array */
-static float Default_const[MAX_ATTS];
-static float Default_nulls[MAX_ATTS];
-
-/* largest dimension */
-static float Longdim;
-
-/* N, S, W, E */
-static float Region[4];
-static geoview Gv;
-static geodisplay Gd;
-static struct Cell_head wind;
-static int Buffermode;
-static int Numlights = 0;
-static int Resetlight = 1;
-static int Modelshowing = 0;
-
-void void_func(void)
-{
-    return;
-}
-
-/*!
-   \brief Initialize OGSF library
-
-   Get region settings - wind
-
-   Set Region (NSWE array) and compute scale
- */
-void GS_libinit(void)
-{
-    static int first = 1;
-
-    G_get_set_window(&wind);
-
-    Region[0] = wind.north;
-    Region[1] = wind.south;
-    Region[2] = wind.west;
-    Region[3] = wind.east;
-
-    /* scale largest dimension to GS_UNIT_SIZE */
-    if ((wind.east - wind.west) > (wind.north - wind.south)) {
-	Longdim = (wind.east - wind.west);
-    }
-    else {
-	Longdim = (wind.north - wind.south);
-    }
-
-    Gv.scale = GS_UNIT_SIZE / Longdim;
-
-    G_debug(1, "GS_libinit(): n=%f s=%f w=%f e=%f scale=%f first=%d",
-	    Region[0], Region[1], Region[2], Region[3], Gv.scale, first);
-    
-    Cxl_func = void_func;
-    Swap_func = void_func;
-
-    
-    if (first) {
-	gs_init();
-    }
-
-    first = 0;
-
-    return;
-}
-
-/*!
-   \brief Get largest dimension
-
-   \param[out] dim dimension
-
-   \return 1
- */
-int GS_get_longdim(float *dim)
-{
-    *dim = Longdim;
-
-    G_debug(3, "GS_get_longdim(): dim=%g", *dim);
-
-    return (1);
-}
-
-/*!
-   \brief Get 2D region extent
-
-   \param[out] n,s,w,e extent values
-
-   \return 1
- */
-int GS_get_region(float *n, float *s, float *w, float *e)
-{
-    *n = Region[0];
-    *s = Region[1];
-    *w = Region[2];
-    *e = Region[3];
-
-    return (1);
-}
-
-/*!
-   \brief Set default attributes for map objects
-
-   \param defs attributes array (dim MAX_ATTS)
-   \param null_defs null attributes array (dim MAX_ATTS)
- */
-void GS_set_att_defaults(float *defs, float *null_defs)
-{
-    int i;
-
-    G_debug(3, "GS_set_att_defaults");
-
-    for (i = 0; i < MAX_ATTS; i++) {
-	Default_const[i] = defs[i];
-	Default_nulls[i] = null_defs[i];
-    }
-
-    return;
-}
-
-/*!
-   Check if surface exists
-
-   \param id surface id
-
-   \return 0 not found
-   \return 1 found
- */
-int GS_surf_exists(int id)
-{
-    int i, found = 0;
-
-    G_debug(3, "GS_surf_exists(): id=%d", id);
-
-
-    if (NULL == gs_get_surf(id)) {
-	return (0);
-    }
-
-    for (i = 0; i < Next_surf && !found; i++) {
-	if (Surf_ID[i] == id) {
-	    found = 1;
-	}
-    }
-
-    return (found);
-}
-
-/*!
-   \brief Add new surface
-
-   Note that origin has 1/2 cell added to represent center of cells
-   because library assumes that east - west = (cols - 1) * ew_res,
-   since left and right columns are on the edges.
-
-   \return surface id
-   \return -1 on error (MAX_SURFS exceded)
- */
-int GS_new_surface(void)
-{
-    geosurf *ns;
-
-    G_debug(3, "GS_new_surface():");
-
-    if (Next_surf < MAX_SURFS) {
-	ns = gs_get_new_surface();
-	gs_init_surf(ns, wind.west + wind.ew_res / 2.,
-		     wind.south + wind.ns_res / 2., wind.rows, wind.cols,
-		     wind.ew_res, wind.ns_res);
-	gs_set_defaults(ns, Default_const, Default_nulls);
-
-	/* make default shine current */
-	gs_set_att_src(ns, ATT_SHINE, CONST_ATT);
-
-	Surf_ID[Next_surf] = ns->gsurf_id;
-	++Next_surf;
-
-	G_debug(3, "    id=%d", ns->gsurf_id);
-
-	return (ns->gsurf_id);
-    }
-
-
-
-    return (-1);
-}
-void GS_set_light_reset(int i)
-{
-    Resetlight = i;
-    if (i)
-	Numlights = 0;
-}
-int GS_get_light_reset(void)
-{
-    return Resetlight;
-}
-/*!
-   \brief Add new model light
-
-   \return light model id
-   \return -1 on error (MAX_LIGHTS exceded)
- */
-int GS_new_light(void)
-{
-    int i;
-
-    if (GS_get_light_reset()) {
-
-	GS_set_light_reset(0);
-
-	for (i = 0; i < MAX_LIGHTS; i++) {
-	    Gv.lights[i].position[X] = Gv.lights[i].position[Y] = 0.0;
-	    Gv.lights[i].position[Z] = 1.0;
-	    Gv.lights[i].position[W] = 0.0;	/* infinite */
-	    Gv.lights[i].color[0] = Gv.lights[i].color[1] =
-		Gv.lights[i].color[2] = 1.0;
-	    Gv.lights[i].ambient[0] = Gv.lights[i].ambient[1] =
-		Gv.lights[i].ambient[2] = 0.2;
-	    Gv.lights[i].shine = 32.0;
-	}
-
-	gsd_init_lightmodel();
-    }
-
-    if (Numlights < MAX_LIGHTS) {
-	gsd_deflight(Numlights + 1, &(Gv.lights[Numlights]));
-	gsd_switchlight(Numlights + 1, 1);
-
-	return ++Numlights;
-    }
-
-    return -1;
-}
-
-/*!
-   \brief Set light position
-
-   \bug I think lights array doesnt match sgi_light array
-
-   \param num light id (starts with 1)
-   \param xpos,ypos,zpos coordinates (model)
-   \param local local coordinate (for viewport)
- */
-void GS_setlight_position(int num, float xpos, float ypos, float zpos,
-			  int local)
-{
-    if (num) {
-	num -= 1;
-	if (num < Numlights) {
-	    Gv.lights[num].position[X] = xpos;
-	    Gv.lights[num].position[Y] = ypos;
-	    Gv.lights[num].position[Z] = zpos;
-	    Gv.lights[num].position[W] = (float)local;
-
-	    gsd_deflight(num + 1, &(Gv.lights[num]));
-	}
-    }
-
-    return;
-}
-
-
-/*!
-   \brief Get light position
-
-   \param num light id (starts at 1)
-   \param[out] xpos,ypos,zpos coordinates
-   \param[out] local ?
- */
-void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos,
-			  int *local)
-{
-    if (num) {
-	num -= 1;
-	if (num < Numlights) {
-	    *xpos = Gv.lights[num].position[X];
-	    *ypos = Gv.lights[num].position[Y];
-	    *zpos = Gv.lights[num].position[Z];
-	    *local = (int)Gv.lights[num].position[W];
-
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Set light color
-
-   \param num light id (starts at 1)
-   \param red,green,blue color values (from 0.0 to 1.0)
- */
-void GS_setlight_color(int num, float red, float green, float blue)
-{
-    if (num) {
-	num -= 1;
-	if (num < Numlights) {
-	    Gv.lights[num].color[0] = red;
-	    Gv.lights[num].color[1] = green;
-	    Gv.lights[num].color[2] = blue;
-
-	    gsd_deflight(num + 1, &(Gv.lights[num]));
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Get light color
-
-   \param num light id (starts at 1)
-   \param[out] red,green,blue color values
- */
-void GS_getlight_color(int num, float *red, float *green, float *blue)
-{
-    if (num) {
-	num -= 1;
-	if (num < Numlights) {
-	    *red = Gv.lights[num].color[0];
-	    *green = Gv.lights[num].color[1];
-	    *blue = Gv.lights[num].color[2];
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Set light ambient
-
-   Red, green, blue from 0.0 to 1.0
-
-   \param num light id (starts at 1)
-   \param red,green,blue color values
- */
-void GS_setlight_ambient(int num, float red, float green, float blue)
-{
-    if (num) {
-	num -= 1;
-	if (num < Numlights) {
-	    Gv.lights[num].ambient[0] = red;
-	    Gv.lights[num].ambient[1] = green;
-	    Gv.lights[num].ambient[2] = blue;
-
-	    gsd_deflight(num + 1, &(Gv.lights[num]));
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Get light ambient
-
-   \param num light id (starts at 1)
-   \param[out] red,green,blue color values
- */
-void GS_getlight_ambient(int num, float *red, float *green, float *blue)
-{
-    if (num) {
-	num -= 1;
-	if (num < Numlights) {
-	    *red = Gv.lights[num].ambient[0];
-	    *green = Gv.lights[num].ambient[1];
-	    *blue = Gv.lights[num].ambient[2];
-	}
-    }
-
-    return;
-}
-
-
-/*!
-   \brief Switch off all lights
- */
-void GS_lights_off(void)
-{
-    int i;
-
-    for (i = 0; i < Numlights; i++) {
-	gsd_switchlight(i + 1, 0);
-    }
-
-    return;
-}
-
-/*!
-   \brief Switch on all lights
- */
-void GS_lights_on(void)
-{
-    int i;
-
-    for (i = 0; i < Numlights; i++) {
-	gsd_switchlight(i + 1, 1);
-    }
-
-    return;
-}
-
-/*!
-   \brief Switch on/off light
-
-   \param num light id (starts at 1)
-   \param on non-zero for 'on' otherwise 'off'
- */
-void GS_switchlight(int num, int on)
-{
-    if (num) {
-	num -= 1;
-
-	if (num < Numlights) {
-	    gsd_switchlight(num + 1, on);
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Check if transparency is set
-
-   \return 0 transparency not set
-   \return 1 transparency is set
- */
-int GS_transp_is_set(void)
-{
-    return (gs_att_is_set(NULL, ATT_TRANSP) || (FC_GREY == gsd_getfc()));
-}
-
-/*!
-   \brief Retrieves coordinates for lighting model position, at center of view
-
-   \param pos[out] coordinates
- */
-void GS_get_modelposition1(float pos[])
-{
-    /* TODO: Still needs work to handle other cases */
-    /* this is a quick hack to get lighting adjustments debugged */
-    /*
-       GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], center);
-       GS_v3mult(center, 1000);
-       GS_v3add(center, Gv.from_to[FROM]);
-     */
-
-    gs_get_datacenter(pos);
-    gs_get_data_avg_zmax(&(pos[Z]));
-
-    G_debug(1, "GS_get_modelposition1(): model position: %f %f %f",
-	    pos[X], pos[Y], pos[Z]);
-
-    return;
-}
-
-/*!
-   \brief Retrieves coordinates for lighting model position, at center of view
-
-   Position at nearclip * 2: tried nearclip + siz, but since need to
-   know position to calculate size, have two dependent variables
-   (nearclip * 2) from eye.
-
-   \param siz[out] size
-   \param pos[out] coordinates (X, Y, Z)
- */
-void GS_get_modelposition(float *siz, float *pos)
-{
-    float dist, near_h, dir[3];
-
-    dist = 2. * Gd.nearclip;
-
-    near_h = 2.0 * tan(4.0 * atan(1.) * Gv.fov / 3600.) * dist;
-    *siz = near_h / 8.0;
-
-    /* prevent clipping - would only happen if fov > ~127 degrees, at
-       fov = 2.0 * atan(2.0) */
-
-    if (*siz > Gd.nearclip) {
-	*siz = Gd.nearclip;
-    }
-
-    GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
-
-    pos[X] = Gv.from_to[FROM][X] + dir[X] * dist;
-    pos[Y] = Gv.from_to[FROM][Y] + dir[Y] * dist;
-    pos[Z] = Gv.from_to[FROM][Z] + dir[Z] * dist;
-
-    return;
-}
-
-
-/*!
-   \brief Set decoration, north arrow ??
-
-   \todo scale used to calculate len of arrow still needs work
-   needs go function that returns center / eye distance
-   gsd_get_los function is not working correctly ??
-
-   \param pt point value in true world coordinates (?)
-   \param id surface id
-   \param[out] pos2 output coordinates
- */
-void GS_set_Narrow(int *pt, int id, float *pos2)
-{
-    geosurf *gs;
-    float x, y, z;
-    GLdouble modelMatrix[16], projMatrix[16];
-    GLint viewport[4];
-
-    if (GS_get_selected_point_on_surface(pt[X], pt[Y], &id, &x, &y, &z)) {
-	gs = gs_get_surf(id);
-	if (gs) {
-	    z = gs->zmax;
-	    pos2[X] = (float)x - gs->ox + gs->x_trans;
-	    pos2[Y] = (float)y - gs->oy + gs->y_trans;
-	    pos2[Z] = (float)z + gs->z_trans;
-
-	    return;
-	}
-    }
-    else {
-	gs = gs_get_surf(id);
-
-	/* Need to get model matrix, etc 
-	 * to run gluUnProject
-	 */
-	gsd_pushmatrix();
-	gsd_do_scale(1);
-	glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
-	glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
-	glGetIntegerv(GL_VIEWPORT, viewport);
-
-	if (gs) {
-	    GLdouble out_near[3], out_far[3];
-	    GLdouble factor;
-	    GLdouble out[3];
-
-	    z = (float)gs->zmax + gs->z_trans;
-
-	    gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 0.,
-			 modelMatrix, projMatrix, viewport,
-			 &out_near[X], &out_near[Y], &out_near[Z]);
-	    gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 1.,
-			 modelMatrix, projMatrix, viewport,
-			 &out_far[X], &out_far[Y], &out_far[Z]);
-
-	    glPopMatrix();
-
-	    factor = (out_near[Z] - z) / (out_near[Z] - out_far[Z]);
-
-	    out[X] = out_near[X] - ((out_near[X] - out_far[X]) * factor);
-	    out[Y] = out_near[Y] - ((out_near[Y] - out_far[Y]) * factor);
-	    out[Z] = z;
-
-	    pos2[X] = (float)out[X];
-	    pos2[Y] = (float)out[Y];
-	    pos2[Z] = (float)out[Z];
-
-	    return;
-
-	}
-    }
-    return;
-}
-
-/*!
-   \brief Draw place marker
-
-   Used to display query point for raster queries.
-
-   \param id surface id
-   \param pt point, X, Y value in true world coordinates
- */
-void GS_draw_X(int id, float *pt)
-{
-    geosurf *gs;
-    Point3 pos;
-    float siz;
-    gvstyle style;
-
-    if ((gs = gs_get_surf(id))) {
-	GS_get_longdim(&siz);
-	style.size = siz / 200.;
-	pos[X] = pt[X] - gs->ox;
-	pos[Y] = pt[Y] - gs->oy;
-	_viewcell_tri_interp(gs, pos);
-
-	gsd_pushmatrix();
-
-	gsd_do_scale(1);
-	gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
-	gsd_linewidth(1);
-
-	if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
-	    pos[Z] = gs->att[ATT_TOPO].constant;
-	    gs = NULL;		/* tells gpd_obj to use given Z val */
-	}
-	style.color = Gd.bgcol;
-	style.symbol = ST_GYRO;
-	gpd_obj(gs, &style, pos);
-	gsd_flush();
-
-	gsd_popmatrix();
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw line on surface
-
-   \param id surface id
-   \param x1,y1,x2,y2 line nodes
- */
-void GS_draw_line_onsurf(int id, float x1, float y1, float x2, float y2)
-{
-    float p1[2], p2[2];
-    geosurf *gs;
-
-    if ((gs = gs_get_surf(id))) {
-	p1[X] = x1 - gs->ox;
-	p1[Y] = y1 - gs->oy;
-	p2[X] = x2 - gs->ox;
-	p2[Y] = y2 - gs->oy;
-
-	gsd_pushmatrix();
-
-	gsd_do_scale(1);
-	gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
-	gsd_linewidth(1);
-
-	gsd_color_func(GS_default_draw_color());
-	gsd_line_onsurf(gs, p1, p2);
-
-	gsd_popmatrix();
-	gsd_flush();
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw multiline on surface
-
-   Like above but limits points in line to n or points found in segment,
-   whichever is smaller.
-
-   \param id surface id
-   \param x1,y1,x2,y2 line nodes
-
-   \return number of points used
- */
-int GS_draw_nline_onsurf(int id, float x1, float y1, float x2, float y2,
-			 float *lasp, int n)
-{
-    float p1[2], p2[2];
-    geosurf *gs;
-    int ret = 0;
-
-    if ((gs = gs_get_surf(id))) {
-	p1[X] = x1 - gs->ox;
-	p1[Y] = y1 - gs->oy;
-	p2[X] = x2 - gs->ox;
-	p2[Y] = y2 - gs->oy;
-
-	gsd_pushmatrix();
-
-	gsd_do_scale(1);
-	gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
-	gsd_linewidth(1);
-	gsd_color_func(GS_default_draw_color());
-	ret = gsd_nline_onsurf(gs, p1, p2, lasp, n);
-	gsd_surf2real(gs, lasp);
-
-	gsd_popmatrix();
-	gsd_flush();
-    }
-
-    return (ret);
-}
-
-/*!
-   \brief Draw flow-line on surace
-
-   This is slow - should be moved to gs_ but GS_ good for testing
-   and useful for app programmer
-
-   \param id surface id
-   \param x,y coordinates of flow-line
- */
-void GS_draw_flowline_at_xy(int id, float x, float y)
-{
-    geosurf *gs;
-    float nv[3], pdir[2], mult;
-    float p1[2], p2[2], next[2];
-    int i = 0;
-
-    if ((gs = gs_get_surf(id))) {
-	p1[X] = x;
-	p1[Y] = y;
-	/* multiply by 1.5 resolutions to ensure a crossing ? */
-	mult = .1 * (VXRES(gs) > VYRES(gs) ? VXRES(gs) : VYRES(gs));
-
-	GS_coordpair_repeats(p1, p1, 50);
-
-	while (1 == GS_get_norm_at_xy(id, p1[X], p1[Y], nv)) {
-	    if (nv[Z] == 1.0) {
-		if (pdir[X] == 0.0 && pdir[Y] == 0.0) {
-		    break;
-		}
-
-		p2[X] = p1[X] + (pdir[X] * mult);
-		p2[Y] = p1[Y] + (pdir[Y] * mult);
-	    }
-	    else {
-		/* use previous direction */
-		GS_v2norm(nv);
-		p2[X] = p1[X] + (nv[X] * mult);
-		p2[Y] = p1[Y] + (nv[Y] * mult);
-		pdir[X] = nv[X];
-		pdir[Y] = nv[Y];
-	    }
-
-	    if (i > 2000) {
-		break;
-	    }
-
-	    if (GS_coordpair_repeats(p1, p2, 0)) {
-		break;
-	    }
-
-	    /* Think about this: */
-	    /* degenerate line means edge or level edge ? */
-	    /* next is filled with last point drawn */
-	    if (2 > GS_draw_nline_onsurf(id, p1[X], p1[Y],
-					 p2[X], p2[Y], next, 3)) {
-		break;
-	    }
-
-	    p1[X] = next[X];
-	    p1[Y] = next[Y];
-	}
-
-	G_debug(3, "GS_draw_flowline_at_xy(): dir: %f %f", nv[X], nv[Y]);
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw fringe around data (surface) at selected corners
-
-   \param id surface id
-   \param clr color
-   \param elev elevation value
-   \param where nw/ne/sw/se edges - 0 (turn off) 1 (turn on)
- */
-void GS_draw_fringe(int id, unsigned long clr, float elev, int *where)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_draw_fringe(): id: %d clr: %ld elev %f edges: %d %d %d %d",
-	    id, clr, elev, where[0], where[1], where[2], where[3]);
-    if ((gs = gs_get_surf(id)))
-	gsd_display_fringe(gs, clr, elev, where);
-
-}
-
-
-/*!
-   \brief Draw legend
-
-   \todo add legend from list option
-   make font loading more flexible
-
-   \param name legend name
-   \param fontbase font-base
-   \param size ? 
-   \param flags legend flags
-   \param range values range
-   \param pt ?
- */
-int GS_draw_legend(const char *name, GLuint fontbase, int size, int *flags,
-		   float *range, int *pt)
-{
-    int list_no;
-
-    list_no = gsd_put_legend(name, fontbase, size, flags, range, pt);
-
-    return (list_no);
-}
-
-/*!
-   \brief Draw pre-defined list
-
-   Uses glFlush() to ensure all drawing is complete
-   before returning
-
-   \param list_id list id
- */
-void GS_draw_list(GLuint list_id)
-{
-    gsd_calllist(list_id);
-    glFlush();
-    return;
-}
-
-/*!
-   \brief Draw all glLists
-
-   Uses glFlush() to ensure all drawing is complete
-   before returning
- */
-void GS_draw_all_list(void)
-{
-    gsd_calllists(0);		/* not sure if 0 is right - MN */
-    glFlush();
-    return;
-}
-
-/*!
-   \brief Delete pre-defined list
-
-   \param list_id list id
- */
-void GS_delete_list(GLuint list_id)
-{
-    gsd_deletelist(list_id, 1);
-
-    return;
-}
-
-/*!
-   \brief Draw lighting model
- */
-void GS_draw_lighting_model1(void)
-{
-    static float center[3];
-    float tcenter[3];
-
-    if (!Modelshowing) {
-	GS_get_modelposition1(center);
-    }
-
-    GS_v3eq(tcenter, center);
-
-    gsd_zwritemask(0x0);
-    gsd_backface(1);
-
-    gsd_colormode(CM_AD);
-    gsd_shademodel(DM_GOURAUD);
-    gsd_pushmatrix();
-    gsd_do_scale(1);
-
-    if (Gv.vert_exag) {
-	tcenter[Z] *= Gv.vert_exag;
-	gsd_scale(1.0, 1.0, 1. / Gv.vert_exag);
-    }
-
-    gsd_drawsphere(tcenter, 0xDDDDDD, (float)(Longdim / 10.));
-    gsd_popmatrix();
-    Modelshowing = 1;
-
-    gsd_backface(0);
-    gsd_zwritemask(0xffffffff);
-
-    return;
-}
-
-/*!
-   \brief Draw lighting model
-
-   Just turn off any cutting planes and draw it just outside near
-   clipping plane, since lighting is infinite now
- */
-void GS_draw_lighting_model(void)
-{
-    static float center[3], size;
-    float tcenter[3], tsize;
-    int i, wason[MAX_CPLANES];
-
-    gsd_get_cplanes_state(wason);
-
-    for (i = 0; i < MAX_CPLANES; i++) {
-	if (wason[i]) {
-	    gsd_cplane_off(i);
-	}
-    }
-
-
-    if (!Modelshowing) {
-	GS_get_modelposition(&size, center);
-    }
-
-    GS_v3eq(tcenter, center);
-    tsize = size;
-
-    gsd_zwritemask(0x0);
-    gsd_backface(1);
-
-    gsd_colormode(CM_DIFFUSE);
-    gsd_shademodel(DM_GOURAUD);
-    gsd_pushmatrix();
-    gsd_drawsphere(tcenter, 0xDDDDDD, tsize);
-    gsd_popmatrix();
-    Modelshowing = 1;
-
-    gsd_backface(0);
-    gsd_zwritemask(0xffffffff);
-
-    for (i = 0; i < MAX_CPLANES; i++) {
-	if (wason[i]) {
-	    gsd_cplane_on(i);
-	}
-    }
-
-    gsd_flush();
-
-    return;
-}
-
-/*!
-   \brief Update current mask
-
-   May be called to update total mask for a surface at convenient times
-   instead of waiting until ready to redraw surface
-
-   \param id surface id
-
-   \return ?
- */
-int GS_update_curmask(int id)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-    return (gs_update_curmask(gs));
-}
-
-/*!
-   \brief Check if point is masked ?
-
-   \param id surface id
-   \param pt point
-
-   \return 1 masked
-   \return 0 not masked
-   \return -1 on error, invalid surface id
- */
-int GS_is_masked(int id, float *pt)
-{
-    geosurf *gs;
-    Point3 tmp;
-
-    if ((gs = gs_get_surf(id))) {
-	tmp[X] = pt[X] - gs->ox;
-	tmp[Y] = pt[Y] - gs->oy;
-
-	return (gs_point_is_masked(gs, tmp));
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Unset Scaled Difference surface
- */
-void GS_unset_SDsurf(void)
-{
-    gsdiff_set_SDref(NULL);
-    SDref_surf = 0;
-
-    return;
-}
-
-/*!
-   \brief Set surface as Scaled Difference surface
-
-   \param id surface id
-
-   \return 1 on success
-   \return 0 on error, invalid surface id
- */
-int GS_set_SDsurf(int id)
-{
-    geosurf *gs;
-
-    if ((gs = gs_get_surf(id))) {
-	gsdiff_set_SDref(gs);
-	SDref_surf = id;
-
-	return (1);
-    }
-
-    return (0);
-}
-
-/*!
-   \brief Set ?
-
-   \param scale scale value
-
-   \return 1
- */
-int GS_set_SDscale(float scale)
-{
-    gsdiff_set_SDscale(scale);
-
-    return (1);
-}
-
-/*!
-   \brief Get ?
-
-   \param[out] id ?
-
-   \return 1 on success
-   \return 0 on error
- */
-int GS_get_SDsurf(int *id)
-{
-    geosurf *gs;
-
-    if ((gs = gsdiff_get_SDref())) {
-	*id = SDref_surf;
-
-	return (1);
-    }
-
-    return (0);
-}
-
-/*!
-   \brief Get ?
-
-   \param[out] scale value
-
-   \return 1
- */
-int GS_get_SDscale(float *scale)
-{
-    *scale = gsdiff_get_SDscale();
-
-    return (1);
-}
-
-/*!
-   \brief Update normals
-
-   \param id surface id
-
-   \return ?
- */
-int GS_update_normals(int id)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    return (gs_calc_normals(gs));
-}
-
-/*!
-   \brief Get attributes
-
-   \param id surface id
-   \param att
-   \param[out] set
-   \param[out] constant
-   \param[out] mapname
-
-   \return 1 on success
-   \return -1 on error (invalid surface id)
- */
-int GS_get_att(int id, int att, int *set, float *constant, char *mapname)
-{
-    int src;
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-    if (gs) {
-	if (-1 != (src = gs_get_att_src(gs, att))) {
-	    *set = src;
-
-	    if (src == CONST_ATT) {
-		*constant = gs->att[att].constant;
-	    }
-	    else if (src == MAP_ATT) {
-		strcpy(mapname, gsds_get_name(gs->att[att].hdata));
-	    }
-
-	    return (1);
-	}
-
-	return (-1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get surface category on given position
-
-   Prints "no data" or a description (i.e., "coniferous forest") to
-   <i>catstr</i>. Usually call after GS_get_selected_point_on_surface().
-   Define <i>att</i> as MAP_ATT
-
-   \todo Allocate catstr using G_store()
-   
-   \param id surface id
-   \param att attribute id (MAP_ATT)
-   \param catstr cat string (must be allocated, dim?)
-   \param x,y real coordinates
-
-   \return -1 if no category info or point outside of window
-   \return 1 on success
-*/
-int GS_get_cat_at_xy(int id, int att, char *catstr, float x, float y)
-{
-    int offset, drow, dcol, vrow, vcol;
-    float ftmp, pt[3];
-    typbuff *buff;
-    geosurf *gs;
-
-    *catstr = '\0';
-    gs = gs_get_surf(id);
-
-    if (NULL == gs) {
-	return -1;
-    }
-
-    pt[X] = x;
-    pt[Y] = y;
-
-    gsd_real2surf(gs, pt);
-    if (gs_point_is_masked(gs, pt)) {
-	return -1;
-    }
-
-    if (!in_vregion(gs, pt)) {
-	return -1;
-    }
-
-    if (MAP_ATT != gs_get_att_src(gs, att)) {
-	sprintf(catstr, _("no category info"));
-	return -1;
-    }
-
-    buff = gs_get_att_typbuff(gs, att, 0);
-
-    vrow = Y2VROW(gs, pt[Y]);
-    vcol = X2VCOL(gs, pt[X]);
-    drow = VROW2DROW(gs, vrow);
-    dcol = VCOL2DCOL(gs, vcol);
-
-    offset = DRC2OFF(gs, drow, dcol);
-    
-    if (GET_MAPATT(buff, offset, ftmp)) {
-	return
-	    (Gs_get_cat_label(gsds_get_name(gs->att[att].hdata),
-			      drow, dcol, catstr));
-    }
-
-    sprintf(catstr, _("no data"));
-
-    return 1;
-}
-
-/*!
-   \brief Get surface normal at x,y (real coordinates)
-
-   Usually call after GS_get_selected_point_on_surface()
-
-   \param id surface id
-   \param x,y real coordinates
-   \param[out] nv surface normal
-
-   \return -1 if point outside of window or masked
-   \return 1 on success
- */
-int GS_get_norm_at_xy(int id, float x, float y, float *nv)
-{
-    int offset, drow, dcol, vrow, vcol;
-    float pt[3];
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    if (NULL == gs) {
-	return (-1);
-    }
-
-    if (gs->norm_needupdate) {
-	gs_calc_normals(gs);
-    }
-
-    pt[X] = x;
-    pt[Y] = y;
-
-    gsd_real2surf(gs, pt);
-    if (gs_point_is_masked(gs, pt)) {
-	return (-1);
-    }
-
-    if (!in_vregion(gs, pt)) {
-	return (-1);
-    }
-
-    vrow = Y2VROW(gs, pt[Y]);
-    vcol = X2VCOL(gs, pt[X]);
-    drow = VROW2DROW(gs, vrow);
-    dcol = VCOL2DCOL(gs, vcol);
-
-    offset = DRC2OFF(gs, drow, dcol);
-
-    if (gs->norms) {
-	FNORM(gs->norms[offset], nv);
-    }
-    else {
-	/* otherwise must be a constant */
-	nv[0] = 0.0;
-	nv[1] = 0.0;
-	nv[2] = 1.0;
-    }
-
-    return (1);
-}
-
-/*!
-   \brief Get RGB color at given point
-
-   Colors are translated to rgb and returned as Rxxx Gxxx Bxxx Usually
-   call after GS_get_selected_point_on_surface().
-
-   Prints NULL or the value (i.e., "921.5") to valstr
-
-   \param id surface id
-   \param att attribute id
-   \param[out] valstr value string (allocated, dim?)
-   \param x,y real coordinates
-   
-   \return -1 if point outside of window or masked
-   \return 1 on success
- */
-int GS_get_val_at_xy(int id, int att, char *valstr, float x, float y)
-{
-    int offset, drow, dcol, vrow, vcol;
-    float ftmp, pt[3];
-    typbuff *buff;
-    geosurf *gs;
-
-    *valstr = '\0';
-    gs = gs_get_surf(id);
-    
-    if (NULL == gs) {
-	return -1;
-    }
-
-    pt[X] = x;
-    pt[Y] = y;
-
-    gsd_real2surf(gs, pt);
-
-    if (gs_point_is_masked(gs, pt)) {
-	return -1;
-    }
-
-    if (!in_vregion(gs, pt)) {
-	return (-1);
-    }
-
-    if (CONST_ATT == gs_get_att_src(gs, att)) {
-	if (att == ATT_COLOR) {
-	    int r, g, b, i;
-
-	    i = gs->att[att].constant;
-	    sprintf(valstr, "R%d G%d B%d",
-		    INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
-	}
-	else {
-	    sprintf(valstr, "%f", gs->att[att].constant);
-	}
-
-	return 1;
-    }
-    else if (MAP_ATT != gs_get_att_src(gs, att)) {
-	return -1;
-    }
-
-    buff = gs_get_att_typbuff(gs, att, 0);
-
-    vrow = Y2VROW(gs, pt[Y]);
-    vcol = X2VCOL(gs, pt[X]);
-    drow = VROW2DROW(gs, vrow);
-    dcol = VCOL2DCOL(gs, vcol);
-
-    offset = DRC2OFF(gs, drow, dcol);
-
-    if (GET_MAPATT(buff, offset, ftmp)) {
-	if (att == ATT_COLOR) {
-	    int r, g, b, i;
-
-	    i = gs_mapcolor(gs_get_att_typbuff(gs, ATT_COLOR, 0),
-			    &(gs->att[ATT_COLOR]), offset);
-	    sprintf(valstr, "R%d G%d B%d",
-		    INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
-	}
-	else {
-	    sprintf(valstr, "%f", ftmp);
-	}
-
-	return (1);
-    }
-
-    sprintf(valstr, "NULL");
-
-    return (1);
-}
-
-/*!
-   \brief Unset attribute
-
-   \param id surface id
-   \param att attribute id
-
-   \return ?
- */
-int GS_unset_att(int id, int att)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-    gs->mask_needupdate = 1;
-
-    return (gs_set_att_src(gs, att, NOTSET_ATT));
-}
-
-/*!
-   \brief Set attribute constant
-
-   \param id surface id
-   \param att attribute id
-   \param constant value
-
-   \return ?
- */
-int GS_set_att_const(int id, int att, float constant)
-{
-    geosurf *gs;
-    int ret;
-
-    gs = gs_get_surf(id);
-    ret = (gs_set_att_const(gs, att, constant));
-
-    Gs_update_attrange(gs, att);
-
-    return (ret);
-}
-
-/*!
-   \brief Set mask mode
-
-   Mask attribute special: constant is set to indicate invert or no
-
-   \param id surface id
-   \param mode id
-
-   \return mode id
-   \return -1 on error (invalid surface id)
- */
-int GS_set_maskmode(int id, int mode)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	gs->att[ATT_MASK].constant = mode;
-	gs->mask_needupdate = 1;
-
-	return (mode);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get mask mode
-
-   \param id surface id
-   \param[out] mode id
-
-   \return 1 on success
-   \return -1 on error (invalid surface id)
- */
-int GS_get_maskmode(int id, int *mode)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	*mode = gs->att[ATT_MASK].constant;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set client data
-
-   \param id surface id
-   \param clientd pointer to client data struct
-
-   \return 1 on success
-   \return -1 on error (invalid surface id)
- */
-int GS_Set_ClientData(int id, void *clientd)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-    if (gs) {
-	gs->clientdata = clientd;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get client data
-
-   \param id surface id
-
-   \return pointer to client data
-   \return NULL on error
- */
-void *GS_Get_ClientData(int id)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-    if (gs) {
-	return (gs->clientdata);
-    }
-
-    return (NULL);
-}
-
-/*!
-   \brief Get number of surfaces
-
-   \return number of surfaces
- */
-int GS_num_surfs(void)
-{
-    return (gs_num_surfaces());
-}
-
-/*!
-   \brief Get surface list
-
-   Must be freed when not neeed!
-
-   \param[out] numsurf number of available surfaces
-
-   \return pointer to surface array
-   \return NULL on error
- */
-int *GS_get_surf_list(int *numsurfs)
-{
-    int i, *ret;
-
-    *numsurfs = Next_surf;
-
-    if (Next_surf) {
-	ret = (int *)G_malloc(Next_surf * sizeof(int));
-
-	for (i = 0; i < Next_surf; i++) {
-	    ret[i] = Surf_ID[i];
-	}
-
-	return (ret);
-    }
-
-    return (NULL);
-}
-
-/*!
-   \brief Delete surface
-
-   \param id surface id
-
-   \return 1 on success
-   \return -1 on error
- */
-int GS_delete_surface(int id)
-{
-    int i, j, found;
-    
-    found = FALSE;
-    
-    G_debug(1, "GS_delete_surface(): id=%d", id);
-    
-    if (GS_surf_exists(id)) {
-	gs_delete_surf(id);
-	for (i = 0; i < Next_surf && !found; i++) {
-	    if (Surf_ID[i] == id) {
-		found = TRUE;
-
-		for (j = i; j < Next_surf; j++) {
-		    Surf_ID[j] = Surf_ID[j + 1];
-		}
-	    }
-	}
-	
-	gv_update_drapesurfs();
-
-	if (found) {
-	    --Next_surf;
-	    return 1;
-	}
-    }
-
-    return -1;
-}
-
-
-/*!
-   \brief Load raster map as attribute
-
-   \param id surface id
-   \param filename filename
-   \param att attribute descriptor
-
-   \return -1 on error (invalid surface id)
-   \return ?
- */
-int GS_load_att_map(int id, const char *filename, int att)
-{
-    geosurf *gs;
-    unsigned int changed;
-    unsigned int atty;
-    const char *mapset;
-    struct Cell_head rast_head;
-    int reuse, begin, hdata, ret, neg, has_null;
-    typbuff *tbuff;
-
-    G_debug(3, "GS_load_att_map(): map=%s", filename);
-
-    reuse = ret = neg = has_null = 0;
-    gs = gs_get_surf(id);
-
-    if (NULL == gs) {
-	return -1;
-    }
-
-    gs->mask_needupdate = (ATT_MASK == att || ATT_TOPO == att ||
-			   (gs->nz_topo && ATT_TOPO == att) ||
-			   (gs->nz_color && ATT_COLOR == att));
-
-    gs_set_att_src(gs, att, MAP_ATT);
-
-    /* Check against maps already loaded in memory   */
-    /* if to be color attribute:
-       - if packed color for another surface, OK to reuse
-       - if unchanged, ok to reuse IF it's of type char (will have lookup)
-     */
-    begin = hdata = 1;
-
-    /* Get MAPSET to ensure names are fully qualified */
-    mapset = G_find_raster2(filename, "");
-    if (mapset == NULL) {
-	/* Check for valid filename */
-	G_warning("Raster map <%s> not found", filename);
-	return -1;
-    }
-    
-    /* Check to see if map is in Region */
-    Rast_get_cellhd(filename, mapset, &rast_head);
-    if (rast_head.north <= wind.south ||
-	rast_head.south >= wind.north ||
-	rast_head.east <= wind.west || rast_head.west >= wind.east) {
-
-	G_warning(_("Raster map <%s> is outside of current region. Load failed."),
-		  G_fully_qualified_name(filename, mapset));
-    }
-
-    while (!reuse && (0 < hdata)) {
-	changed = CF_COLOR_PACKED;
-	atty = ATTY_FLOAT | ATTY_CHAR | ATTY_INT | ATTY_SHORT | ATTY_MASK;
-
-	if (0 < (hdata = gsds_findh(filename, &changed, &atty, begin))) {
-
-	    G_debug(3, "GS_load_att_map(): %s already has data handle %d.CF=%x",
-		    filename, hdata, changed);
-
-	    /* handle found */
-	    if (ATT_COLOR == att) {
-		if ((changed == CF_COLOR_PACKED) ||
-		    (!changed && atty == ATTY_CHAR)) {
-		    reuse = 1;
-		}
-	    }
-	    else if (atty == ATTY_MASK && att != ATT_MASK) {
-		reuse = 0;
-		/* should also free mask data & share new - but need backward
-		   reference? */
-	    }
-	    else if (!changed) {
-		reuse = 1;
-	    }
-	}
-
-	begin = 0;
-    }
-
-    if (reuse) {
-	gs->att[att].hdata = hdata;
-	gs_set_att_type(gs, att, atty);	/* ?? */
-
-	/* free lookup  & set to NULL! */
-	if (atty == ATTY_INT) {
-	    if (gs->att[att].lookup) {
-		free(gs->att[att].lookup);
-		gs->att[att].lookup = NULL;
-	    }
-	}
-	/* TODO: FIX THIS stuff with lookup sharing! */
-
-	G_debug(3, "GS_load_att_map(): %s is being reused. hdata=%d",
-		filename, hdata);
-    }
-    else {
-	G_debug(3, "GS_load_att_map(): %s not loaded in correct form - loading now",
-		filename);
-
-	/* not loaded - need to get new dataset handle */
-	gs->att[att].hdata = gsds_newh(filename);
-
-	tbuff = gs_get_att_typbuff(gs, att, 1);
-
-	/* TODO: Provide mechanism for loading certain attributes at
-	   specified sizes, allow to scale or cap, or scale non-zero */
-	if (ATT_MASK == att) {
-	    atty = ATTY_MASK;
-	}
-	else {
-	    atty = Gs_numtype(filename, &neg);
-	}
-
-#ifdef MAYBE_LATER
-	if (att == ATT_COLOR && atty == ATTY_SHORT) {
-	    atty = (neg ? ATTY_INT : ATTY_SHORT);
-	}
-#endif
-
-	if (att == ATT_COLOR && atty == ATTY_SHORT) {
-	    atty = ATTY_INT;
-	}
-
-	if (0 == gs_malloc_att_buff(gs, att, ATTY_NULL)) {
-	    G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
-	}
-
-	switch (atty) {
-	case ATTY_MASK:
-	    if (0 == gs_malloc_att_buff(gs, att, ATTY_MASK)) {
-		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
-	    }
-
-	    ret = Gs_loadmap_as_bitmap(&wind, filename, tbuff->bm);
-	    
-	    break;
-	case ATTY_CHAR:
-	    if (0 == gs_malloc_att_buff(gs, att, ATTY_CHAR)) {
-		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
-	    }
-
-	    ret = Gs_loadmap_as_char(&wind, filename, tbuff->cb,
-				     tbuff->nm, &has_null);
-
-	    break;
-	case ATTY_SHORT:
-	    if (0 == gs_malloc_att_buff(gs, att, ATTY_SHORT)) {
-		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
-	    }
-
-	    ret = Gs_loadmap_as_short(&wind, filename, tbuff->sb,
-				      tbuff->nm, &has_null);
-	    break;
-	case ATTY_FLOAT:
-	    if (0 == gs_malloc_att_buff(gs, att, ATTY_FLOAT)) {
-		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
-	    }
-
-	    ret = Gs_loadmap_as_float(&wind, filename, tbuff->fb,
-				      tbuff->nm, &has_null);
-
-	    break;
-	case ATTY_INT:
-	default:
-	    if (0 == gs_malloc_att_buff(gs, att, ATTY_INT)) {
-		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
-	    }
-
-	    ret = Gs_loadmap_as_int(&wind, filename, tbuff->ib,
-				    tbuff->nm, &has_null);
-	    break;
-
-	}			/* Done with switch */
-
-	if (ret == -1) {
-	    gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
-	    return -1;
-	}
-
-	G_debug(4, "  has_null=%d", has_null);
-
-	if (!has_null) {
-	    gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
-	}
-	else {
-	    gs_update_curmask(gs);
-	}
-
-    }				/* end if not reuse */
-
-    if (ATT_COLOR == att) {
-#ifdef MAYBE_LATER
-	if (ATTY_INT == atty) {
-	    Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
-	    gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
-	    gs->att[att].lookup = NULL;
-	}
-	else {
-	    gs_malloc_lookup(gs, att);
-	    Gs_build_lookup(filename, gs->att[att].lookup);
-	}
-#else
-
-	if (ATTY_CHAR == atty) {
-	    if (!gs->att[att].lookup) {
-		/* might already exist if reusing */
-		gs_malloc_lookup(gs, att);
-		Gs_build_256lookup(filename, gs->att[att].lookup);
-	    }
-	}
-	else if (ATTY_FLOAT == atty) {
-	    if (!reuse) {
-		if (0 == gs_malloc_att_buff(gs, att, ATTY_INT)) {
-		    G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
-		}
-
-		Gs_pack_colors_float(filename, tbuff->fb, tbuff->ib,
-				     gs->rows, gs->cols);
-		gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
-		gsds_free_data_buff(gs->att[att].hdata, ATTY_FLOAT);
-		gs->att[att].lookup = NULL;
-	    }
-	}
-	else {
-	    if (!reuse) {
-		Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
-		gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
-		gs->att[att].lookup = NULL;
-	    }
-	}
-#endif
-    }
-
-    if (ATT_TOPO == att) {
-	gs_init_normbuff(gs);
-	/* S_DIFF: should also check here to see if this surface is a
-	   reference surface for scaled differences, if so update references
-	   to it */
-    }
-
-    if (ret < 0) {
-	G_warning(_("Loading failed"));
-    }
-
-    if (-1 == Gs_update_attrange(gs, att)) {
-	G_warning(_("Error finding range"));
-    }
-
-    return ret;
-}
-
-/*!
-   \brief Draw surface
-
-   \param id surface id
- */
-void GS_draw_surf(int id)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_draw_surf(): id=%d", id);
-
-    gs = gs_get_surf(id);
-    if (gs) {
-	gsd_shademodel(gs->draw_mode & DM_GOURAUD);
-
-	if (gs->draw_mode & DM_POLY) {
-	    gsd_surf(gs);
-	}
-
-	if (gs->draw_mode & DM_WIRE) {
-	    gsd_wire_surf(gs);
-	}
-
-	/* TODO: write wire/poly draw routines */
-	if (gs->draw_mode & DM_WIRE_POLY) {
-	    gsd_surf(gs);
-	    gsd_wire_surf(gs);
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw surface wire
-
-   Overrides draw_mode for fast display
-
-   \param id surface id
- */
-void GS_draw_wire(int id)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_draw_wire(): id=%d", id);
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	gsd_wire_surf(gs);
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw all wires
-
-   Overrides draw_mode for fast display
- */
-void GS_alldraw_wire(void)
-{
-    geosurf *gs;
-    int i;
-
-    for (i = 0; i < Next_surf; i++) {
-	if ((gs = gs_get_surf(Surf_ID[i]))) {
-	    gsd_wire_surf(gs);
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw all surfaces
- */
-void GS_alldraw_surf(void)
-{
-    int i;
-
-    for (i = 0; i < Next_surf; i++) {
-	GS_draw_surf(Surf_ID[i]);
-    }
-
-    return;
-}
-
-/*!
-   \brief Set Z exag for surface
-
-   \param id surface id
-   \param exag z-exag value
- */
-void GS_set_exag(int id, float exag)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_set_exag");
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	if (gs->z_exag != exag) {
-	    gs->norm_needupdate = 1;
-	}
-
-	gs->z_exag = exag;
-    }
-
-    return;
-}
-
-/*!
-   \brief Set global z-exag value
-
-   \param exag exag value to be set up
- */
-void GS_set_global_exag(float exag)
-{
-
-    G_debug(3, "GS_set_global_exag");
-
-    Gv.vert_exag = exag;
-    /* GL_NORMALIZE */
-    /* Only need to update norms gs_norms.c
-     * if exag is used in norm equation which
-     * it is not! If GL_NORMALIZE is disabled
-     * will need to include.
-     gs_setall_norm_needupdate();
-     */
-
-    return;
-}
-
-/*!
-   \brief Get global z-exag value
-
-   \return value
- */
-float GS_global_exag(void)
-{
-    G_debug(3, "GS_global_exag(): %g", Gv.vert_exag);
-
-    return (Gv.vert_exag);
-}
-
-/*!
-   \brief Set wire color
-
-   \todo error-handling
-
-   \param id surface id
-   \param colr color value
- */
-void GS_set_wire_color(int id, int colr)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_set_wire_color");
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	gs->wire_color = colr;
-    }
-
-    return;
-}
-
-/*!
-   \brief Get wire color
-
-   \param id surface id
-   \param[out] colr color value
-
-   \return 1 on success
-   \return -1 on error
- */
-int GS_get_wire_color(int id, int *colr)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	*colr = gs->wire_color;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set all draw-modes
-
-   \param mode mode id
-
-   \return 0 on success
-   \return -1 on error
- */
-int GS_setall_drawmode(int mode)
-{
-    int i;
-
-    for (i = 0; i < Next_surf; i++) {
-	if (0 != GS_set_drawmode(Surf_ID[i], mode)) {
-	    return (-1);
-	}
-    }
-
-    return (0);
-}
-
-/*!
-   \brief Set draw mode
-
-   \param id surface id
-   \param mode mode type(s)
-
-   \return 0 on success
-   \return -1 on error (invalid surface id)
- */
-int GS_set_drawmode(int id, int mode)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_set_drawmode(): id=%d mode=%d", id, mode);
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	gs->draw_mode = mode;
-
-	return (0);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get draw mode
-
-   \param id surface id
-   \param[out] mode mode id
-
-   \return 1 on success
-   \return -1 on error (invalid surface id)
- */
-int GS_get_drawmode(int id, int *mode)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	*mode = gs->draw_mode;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set no-zero ?
-
-   \param id surface id
-   \param att attribute id
-   \param mode mode id
- */
-void GS_set_nozero(int id, int att, int mode)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_set_nozero");
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	if (att == ATT_TOPO) {
-	    gs->nz_topo = mode;
-	    gs->mask_needupdate = 1;
-	}
-
-	if (att == ATT_COLOR) {
-	    gs->nz_color = mode;
-	    gs->mask_needupdate = 1;
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Get no-zero ?
-
-   \param id surface id
-   \param att attribute id
-   \param[out] mode mode id
-
-   \return -1 on error (invalid surface id)
-   \return 1 on success
- */
-int GS_get_nozero(int id, int att, int *mode)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_set_nozero");
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	if (att == ATT_TOPO) {
-	    *mode = gs->nz_topo;
-	}
-	else if (att == ATT_COLOR) {
-	    *mode = gs->nz_color;
-	}
-	else {
-	    return (-1);
-	}
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set all draw resolutions
-
-   \param xres,yres x/y resolution value
-   \param xwire,ywire x/y wire value
-
-   \return 0 on success
-   \return -1 on error
- */
-int GS_setall_drawres(int xres, int yres, int xwire, int ywire)
-{
-    int i;
-
-    for (i = 0; i < Next_surf; i++) {
-	if (0 != GS_set_drawres(Surf_ID[i], xres, yres, xwire, ywire)) {
-	    return (-1);
-	}
-    }
-
-    return (0);
-}
-
-/*!
-   \brief Set draw resolution for surface
-
-   \param id surface id
-   \param xres,yres x/y resolution value
-   \param xwire,ywire x/y wire value
-
-   \return -1 on error
-   \return 0 on success
- */
-int GS_set_drawres(int id, int xres, int yres, int xwire, int ywire)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_set_drawres() id=%d xyres=%d/%d xywire=%d/%d",
-	    id, xres, yres, xwire, ywire);
-
-    if (xres < 1 || yres < 1 || xwire < 1 || ywire < 1) {
-	return (-1);
-    }
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	if (gs->x_mod != xres || gs->y_mod != yres) {
-	    gs->norm_needupdate = 1;
-	}
-
-	gs->x_mod = xres;
-	gs->y_mod = yres;
-	gs->x_modw = xwire;
-	gs->y_modw = ywire;
-    }
-
-    return (0);
-}
-
-/*!
-   \brief Get draw resolution of surface
-
-   \param id surface id
-   \param[out] xres,yres x/y resolution value
-   \param[out] xwire,ywire x/y wire value
- */
-void GS_get_drawres(int id, int *xres, int *yres, int *xwire, int *ywire)
-{
-    geosurf *gs;
-
-    G_debug(3, "GS_get_drawres");
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	*xres = gs->x_mod;
-	*yres = gs->y_mod;
-	*xwire = gs->x_modw;
-	*ywire = gs->y_modw;
-    }
-
-    return;
-}
-
-/*!
-   \brief Get dimension of surface
-
-   \param id surface id
-   \param[out] rows,cols number of rows/cols
- */
-void GS_get_dims(int id, int *rows, int *cols)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	*rows = gs->rows;
-	*cols = gs->cols;
-    }
-
-    return;
-}
-
-/*!
-   \brief Get exag-value guess
-
-   Use no_zero range because if zero IS data, then range won't be that
-   much off (it's just a GUESS, after all), but if zero is NO data, could
-   drastically affect guess
-
-   \param id surface id
-   \param[out] exag exag value
-
-   \return 1 on success
-   \return -1 on error
- */
-int GS_get_exag_guess(int id, float *exag)
-{
-    geosurf *gs;
-    float guess;
-
-    gs = gs_get_surf(id);
-    guess = 1.0;
-
-    /* if gs is type const return guess = 1.0 */
-    if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
-	*exag = guess;
-	return (1);
-    }
-
-    if (gs) {
-	if (gs->zrange_nz == 0.0) {
-	    *exag = 0.0;
-
-	    return (1);
-	}
-
-	G_debug(3, "GS_get_exag_guess(): %f %f", gs->zrange_nz, Longdim);
-
-	while (gs->zrange_nz * guess / Longdim >= .25) {
-	    guess *= .1;
-
-	    G_debug(3, "GS_get_exag_guess(): %f", guess);
-	}
-
-	while (gs->zrange_nz * guess / Longdim < .025) {
-	    guess *= 10.;
-
-	    G_debug(3, "GS_get_exag_guess(): %f", guess);
-	}
-
-	*exag = guess;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get Z extents for all loaded surfaces
-
-   Treating zeros as "no data"
-
-   \param[out] min min value
-   \param[out] max max value
- */
-void GS_get_zrange_nz(float *min, float *max)
-{
-    int i, first = 1;
-    geosurf *gs;
-
-    for (i = 0; i < Next_surf; i++) {
-	if ((gs = gs_get_surf(Surf_ID[i]))) {
-	    if (first) {
-		first = 0;
-		*min = gs->zmin_nz;
-		*max = gs->zmax_nz;
-	    }
-
-	    if (gs->zmin_nz < *min) {
-		*min = gs->zmin_nz;
-	    }
-
-	    if (gs->zmax_nz > *max) {
-		*max = gs->zmax_nz;
-	    }
-	}
-    }
-
-    G_debug(3, "GS_get_zrange_nz(): min=%g max=%g", *min, *max);
-
-    return;
-}
-
-/*!
-   \brief Set translation (surface position)
-
-   \param id surface id
-   \param xtrans,ytrans,ztrans translation values
- */
-void GS_set_trans(int id, float xtrans, float ytrans, float ztrans)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	gs->x_trans = xtrans;
-	gs->y_trans = ytrans;
-	gs->z_trans = ztrans;
-    }
-
-    G_debug(3, "GS_set_trans(): id=%d, x=%f, y=%f, z=%f",
-	    id, xtrans, ytrans, ztrans);
-
-    return;
-}
-
-/*!
-   \brief Get translation values (surface position)
-
-   \param id surface id
-   \param[out] xtrans,ytrans,ztrans trans values
- */
-void GS_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
-{
-    geosurf *gs;
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	*xtrans = gs->x_trans;
-	*ytrans = gs->y_trans;
-	*ztrans = gs->z_trans;
-    }
-
-    G_debug(3, "GS_get_trans: id=%d, x=%f, y=%f, z=%f",
-	    id, *xtrans, *ytrans, *ztrans);
-
-    return;
-}
-
-
-/*!
-   \brief Get default draw color
-
-   \return color value
- */
-unsigned int GS_default_draw_color(void)
-{
-
-    G_debug(3, "GS_default_draw_color");
-
-    return ((unsigned int)Gd.bgcol);
-}
-
-/*!
-   \brief Get background color
-
-   \return color value
- */
-unsigned int GS_background_color(void)
-{
-    return ((unsigned int)Gd.bgcol);
-}
-
-/*!
-   \brief Sets which buffer to draw to
-
-   \param where GSD_BOTH, GSD_FRONT, GSD_BACK
- */
-void GS_set_draw(int where)
-{
-    Buffermode = where;
-
-    switch (where) {
-    case GSD_BOTH:
-	gsd_frontbuffer(1);
-	gsd_backbuffer(1);
-
-	break;
-    case GSD_FRONT:
-	gsd_frontbuffer(1);
-	gsd_backbuffer(0);
-
-	break;
-    case GSD_BACK:
-    default:
-	gsd_frontbuffer(0);
-	gsd_backbuffer(1);
-
-	break;
-    }
-
-    return;
-}
-
-/*
-   \brief Ready to draw
- */
-void GS_ready_draw(void)
-{
-
-    G_debug(3, "GS_ready_draw");
-
-    gsd_set_view(&Gv, &Gd);
-
-    return;
-}
-
-/*!
-   \brief Draw done, swap buffers
- */
-void GS_done_draw(void)
-{
-
-    G_debug(3, "GS_done_draw");
-
-    if (GSD_BACK == Buffermode) {
-	gsd_swapbuffers();
-    }
-
-    gsd_flush();
-
-    return;
-}
-
-/*!
-   \brief Set focus
-
-   \param realto real coordinates to
- */
-void GS_set_focus(float *realto)
-{
-
-    G_debug(3, "GS_set_focus(): %f,%f,%f", realto[0], realto[1], realto[2]);
-
-    Gv.infocus = 1;
-    GS_v3eq(Gv.real_to, realto);
-
-    gsd_set_view(&Gv, &Gd);
-
-    return;
-}
-
-/*!
-   \brief Set real focus
-
-   \param realto real coordinates to
- */
-void GS_set_focus_real(float *realto)
-{
-
-    G_get_set_window(&wind);
-    realto[X] = realto[X] - wind.west - (wind.ew_res / 2.);
-    realto[Y] = realto[Y] - wind.south - (wind.ns_res / 2.);
-
-    Gv.infocus = 1;
-    GS_v3eq(Gv.real_to, realto);
-
-    gsd_set_view(&Gv, &Gd);
-
-    return;
-}
-
-
-/*!
-   \brief Get focus
-
-   OK to call with NULL argument if just want to check state
-
-   \param realto real coordinates to
-
-   \return ?
- */
-int GS_get_focus(float *realto)
-{
-
-    G_debug(3, "GS_get_focus");
-
-    if (Gv.infocus) {
-	if (realto) {
-	    GS_v3eq(realto, Gv.real_to);
-	}
-    }
-
-    return (Gv.infocus);
-}
-
-/*!
-   \brief Set focus to map center
-
-   \param id surface id
- */
-void GS_set_focus_center_map(int id)
-{
-    float center[3];
-    geosurf *gs;
-
-    G_debug(3, "GS_set_focus_center_map");
-
-    gs = gs_get_surf(id);
-
-    if (gs) {
-	center[X] = (gs->xmax - gs->xmin) / 2.;
-	center[Y] = (gs->ymax - gs->ymin) / 2.;
-	center[Z] = (gs->zmax_nz + gs->zmin_nz) / 2.;
-
-	/* not yet working
-	   buff = gs_get_att_typbuff(gs, ATT_TOPO, 0);
-	   offset = gs->rows*gs->cols/2 + gs->cols/2;
-	   if (buff)
-	   {
-	   if (GET_MAPATT(buff, offset, tmp))
-	   {
-	   center[Z] = tmp;
-	   }
-	   }
-	 */
-
-	GS_set_focus(center);
-    }
-}
-
-/*!
-   \brief Move viewpoint 
-
-   \param pt 'from' model coordinates
- */
-void GS_moveto(float *pt)
-{
-    float ft[3];
-
-    G_debug(3, "GS_moveto(): %f,%f,%f", pt[0], pt[1], pt[2]);
-
-    if (Gv.infocus) {
-	GS_v3eq(Gv.from_to[FROM], pt);
-	/*
-	   GS_v3eq(Gv.from_to[TO], Gv.real_to);
-	 */
-	GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
-	/* update inclination, look_dir if we're keeping these */
-    }
-    else {
-	GS_v3eq(ft, Gv.from_to[TO]);
-	GS_v3sub(ft, Gv.from_to[FROM]);
-	GS_v3eq(Gv.from_to[FROM], pt);
-	GS_v3eq(Gv.from_to[TO], pt);
-	GS_v3add(Gv.from_to[TO], ft);
-    }
-
-    return;
-}
-
-/*!
-   \brief Move position to (real)
-
-   \param pt point real coordinates
- */
-void GS_moveto_real(float *pt)
-{
-    gsd_real2model(pt);
-    GS_moveto(pt);
-
-    return;
-}
-
-/*!
-   \brief Get z-extent for a single surface
-
-   \param id surface id
-   \param[out] min min z-value
-   \param[out] max max z-value
-   \param[out] mid middle z-value
-
-   \return -1 on error (invalid surface id)
-   \return ?
- */
-int GS_get_zextents(int id, float *min, float *max, float *mid)
-{
-    geosurf *gs;
-
-    if (NULL == (gs = gs_get_surf(id))) {
-	return (-1);
-    }
-
-    G_debug(3, "GS_get_zextents(): id=%d", id);
-
-    return (gs_get_zextents(gs, min, max, mid));
-}
-
-/*!
-   \brief Get z-extent for all loaded surfaces
-
-   \param[out] min min z-value
-   \param[out] max max z-value
-   \param doexag use z-exaggeration
-
-   \return 1 on success
-   \return -1 on error
- */
-int GS_get_zrange(float *min, float *max, int doexag)
-{
-    int ret_surf, ret_vol;
-    float surf_min, surf_max;
-    float vol_min, vol_max;
-
-    ret_surf = gs_get_zrange(&surf_min, &surf_max);
-    ret_vol = gvl_get_zrange(&vol_min, &vol_max);
-
-    if (ret_surf > 0 && ret_vol > 0) {
-	*min = (surf_min < vol_min) ? surf_min : vol_min;
-	*max = (surf_max < vol_max) ? surf_max : vol_max;
-    }
-    else if (ret_surf > 0) {
-	*min = surf_min;
-	*max = surf_max;
-    }
-    else if (ret_vol > 0) {
-	*min = vol_min;
-	*max = vol_max;
-    }
-
-    if (doexag) {
-	*min *= Gv.vert_exag;
-	*max *= Gv.vert_exag;
-    }
-
-    G_debug(3, "GS_get_zrange(): min=%g max=%g", *min, *max);
-    return ((ret_surf > 0 || ret_vol > 0) ? (1) : (-1));
-}
-
-/*!
-   \brief Get viewpoint 'from' position
-
-   \param[out] fr from model coordinates
- */
-void GS_get_from(float *fr)
-{
-    GS_v3eq(fr, Gv.from_to[FROM]);
-
-    G_debug(3, "GS_get_from(): %f,%f,%f", fr[0], fr[1], fr[2]);
-
-    return;
-}
-
-/*!
-   \brief Get viewpoint 'from' real coordinates
-
-   \param[out] fr 'from' real coordinates
- */
-void GS_get_from_real(float *fr)
-{
-    GS_v3eq(fr, Gv.from_to[FROM]);
-    gsd_model2real(fr);
-
-    return;
-}
-
-/*!
-   \brief Get 'to' real coordinates
-
-   \param[out] to 'to' real coordinates
- */
-void GS_get_to_real(float *to)
-{
-    float realto[3];
-
-    G_get_set_window(&wind);
-    GS_get_focus(realto);
-    to[X] = realto[X] + wind.west + (wind.ew_res / 2.);
-    to[Y] = realto[Y] + wind.south + (wind.ns_res / 2.);
-    to[Z] = realto[Z];
-
-    return;
-}
-
-
-/*!
-   \brief Get zoom setup
-
-   \param[out] a,b,c,d current viewport settings
-   \param[out] maxx,maxy max viewport size
- */
-void GS_zoom_setup(int *a, int *b, int *c, int *d, int *maxx, int *maxy)
-{
-    GLint tmp[4];
-    GLint num[2];
-
-    gsd_getViewport(tmp, num);
-    *a = tmp[0];
-    *b = tmp[1];
-    *c = tmp[2];
-    *d = tmp[3];
-    *maxx = num[0];
-    *maxy = num[1];
-
-    return;
-}
-
-/*!
-   \brief Get 'to' model coordinates
-
-   \todo need set_to? - just use viewdir?
-
-   \param[out] to 'to' model coordinates
- */
-void GS_get_to(float *to)
-{
-    G_debug(3, "GS_get_to");
-
-    GS_v3eq(to, Gv.from_to[TO]);
-
-    return;
-}
-
-/*!
-   \brief Get viewdir
-
-   \param[out] dir viewdir value
- */
-void GS_get_viewdir(float *dir)
-{
-    GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
-
-    return;
-}
-
-/*!
-   \brief Set viewdir
-
-   Automatically turns off focus
-
-   \param dir viewdir value
- */
-void GS_set_viewdir(float *dir)
-{
-    float tmp[3];
-
-    GS_v3eq(tmp, dir);
-    GS_v3norm(tmp);
-    GS_v3eq(Gv.from_to[TO], Gv.from_to[FROM]);
-    GS_v3add(Gv.from_to[TO], tmp);
-
-    GS_set_nofocus();
-    gsd_set_view(&Gv, &Gd);
-
-    return;
-}
-
-/*!
-   \brief Set field of view
-
-   \param fov fov value
- */
-void GS_set_fov(int fov)
-{
-    Gv.fov = fov;
-
-    return;
-}
-
-/*!
-   \brief Get fied of view
-
-   \return field of view, in 10ths of degrees
- */
-int GS_get_fov(void)
-{
-    return (Gv.fov);
-}
-
-/*!
-   \brief Get twist value
-
-   10ths of degrees off twelve o'clock
- */
-int GS_get_twist(void)
-{
-    return (Gv.twist);
-}
-
-/*!
-   \brief Set viewpoint twist value
-
-   10ths of degrees off twelve o'clock
-
-   \param t tenths of degrees clockwise from 12:00.
- */
-void GS_set_twist(int t)
-{
-    Gv.twist = t;
-
-    return;
-}
-
-/*!
-   \brief Set rotation params
- */
-void GS_set_rotation(double angle, double x, double y, double z)
-{
-    Gv.rotate.rot_angle = angle;
-    Gv.rotate.rot_axes[0] = x;
-    Gv.rotate.rot_axes[1] = y;
-    Gv.rotate.rot_axes[2] = z;
-    Gv.rotate.do_rot = 1;
-
-    return;
-}
-
-/*!
-   \brief Stop scene rotation
- */
-void GS_unset_rotation(void)
-{
-    Gv.rotate.do_rot = 0;
-}
-
-/*!
-   \brief Reset scene rotation
- */
-void GS_init_rotation(void)
-{
-    int i;
-
-    for (i = 0; i < 16; i++) {
-	if (i == 0 || i == 5 || i == 10 || i == 15)
-	    Gv.rotate.rotMatrix[i] = 1.0;
-	else
-	    Gv.rotate.rotMatrix[i] = 0.0;
-    }
-    Gv.rotate.rot_angle = 0.0;
-    Gv.rotate.rot_axes[0] = 0.0;
-    Gv.rotate.rot_axes[1] = 0.0;
-    Gv.rotate.rot_axes[2] = 0.0;
-    Gv.rotate.do_rot = 0;
-    
-}
-/*!
- * \brief Get rotation matrix
- */ 
-void GS_get_rotation_matrix(double *matrix)
-{
-    int i;
-
-    for (i = 0; i < 16; i++) {
-	matrix[i] = Gv.rotate.rotMatrix[i];
-    }
-}
-
-/*!
- * \brief Set rotation matrix
- */ 
-void GS_set_rotation_matrix(double *matrix)
-{
-    int i;
-
-    for (i = 0; i < 16; i++) {
-	Gv.rotate.rotMatrix[i] = matrix[i];
-    }
-}
-
-/*!
-   \brief Unset focus
- */
-void GS_set_nofocus(void)
-{
-    G_debug(3, "GS_set_nofocus");
-
-    Gv.infocus = 0;
-
-    return;
-}
-
-/*!
-   \brief Set focus
-
-   Make sure that the center of view is set
- */
-void GS_set_infocus(void)
-{
-    G_debug(3, "GS_set_infocus");
-
-    Gv.infocus = 1;
-
-    return;
-}
-
-/*!
-   \brief Set viewport
-
-   \param left,right,bottom,top viewport extent values
- */
-void GS_set_viewport(int left, int right, int bottom, int top)
-{
-    G_debug(3, "GS_set_viewport(): left=%d, right=%d, "
-	    "bottom=%d, top=%d", left, right, bottom, top);
-
-    gsd_viewport(left, right, bottom, top);
-
-    return;
-}
-
-/*!
-   \brief Send screen coords sx and sy, lib traces through surfaces; sets
-   new center to point of nearest intersection.
-
-   If no intersection, uses line of sight with length of current view
-   ray (eye to center) to set new center.
-
-   Reset center of view to screen coordinates sx, sy.
-
-   \param sx,sy screen coordinates
-
-   \return 1 on success
-   \return 0 on error (invalid surface id)
- */
-int GS_look_here(int sx, int sy)
-{
-    float x, y, z, len, los[2][3];
-    Point3 realto, dir;
-    int id;
-    geosurf *gs;
-
-    if (GS_get_selected_point_on_surface(sx, sy, &id, &x, &y, &z)) {
-	gs = gs_get_surf(id);
-	if (gs) {
-	    realto[X] = x - gs->ox + gs->x_trans;
-	    realto[Y] = y - gs->oy + gs->y_trans;
-	    realto[Z] = z + gs->z_trans;
-	    GS_set_focus(realto);
-
-	    return (1);
-	}
-    }
-    else {
-	if (gsd_get_los(los, (short)sx, (short)sy)) {
-	    len = GS_distance(Gv.from_to[FROM], Gv.real_to);
-	    GS_v3dir(los[FROM], los[TO], dir);
-	    GS_v3mult(dir, len);
-	    realto[X] = Gv.from_to[FROM][X] + dir[X];
-	    realto[Y] = Gv.from_to[FROM][Y] + dir[Y];
-	    realto[Z] = Gv.from_to[FROM][Z] + dir[Z];
-	    GS_set_focus(realto);
-
-	    return (1);
-	}
-    }
-
-    return (0);
-}
-
-/*!
-   \brief Get selected point of surface
-
-   Given screen coordinates sx and sy, find closest intersection of
-   view ray with surfaces and return coordinates of intersection in x, y,
-   z, and identifier of surface in id.
-
-   \param sx,sy screen coordinates
-   \param[out] id surface id
-   \param[out] x,y,z point on surface (model coordinates?)
-
-   \returns 0 if no intersections found
-   \return number of intersections
- */
-int GS_get_selected_point_on_surface(int sx, int sy, int *id, float *x,
-				     float *y, float *z)
-{
-    float los[2][3], find_dist[MAX_SURFS], closest;
-    Point3 point, tmp, finds[MAX_SURFS];
-    int surfs[MAX_SURFS], i, iclose, numhits = 0;
-    geosurf *gs;
-
-    /* returns surface-world coords */
-    gsd_get_los(los, (short)sx, (short)sy);
-
-    if (!gs_setlos_enterdata(los)) {
-	G_debug(3, "gs_setlos_enterdata(los): returns false");
-	return (0);
-    }
-
-    for (i = 0; i < Next_surf; i++) {
-	G_debug(3, "id=%d", i);
-
-	gs = gs_get_surf(Surf_ID[i]);
-
-	/* los_intersect expects surf-world coords (xy transl, no scaling) */
-
-#if NVIZ_HACK
-	if (gs_los_intersect1(Surf_ID[i], los, point)) {
-#else
-	if (gs_los_intersect(Surf_ID[i], los, point)) {
-#endif
-	    if (!gs_point_is_masked(gs, point)) {
-		GS_v3eq(tmp, point);
-		tmp[X] += gs->x_trans;
-		tmp[Y] += gs->y_trans;
-		tmp[Z] += gs->z_trans;
-		find_dist[numhits] = GS_distance(los[FROM], tmp);
-		gsd_surf2real(gs, point);
-		GS_v3eq(finds[numhits], point);
-		surfs[numhits] = Surf_ID[i];
-		numhits++;
-	    }
-	}
-    }
-
-    for (i = iclose = 0; i < numhits; i++) {
-	closest = find_dist[iclose];
-
-	if (find_dist[i] < closest) {
-	    iclose = i;
-	}
-    }
-
-    if (numhits) {
-	*x = finds[iclose][X];
-	*y = finds[iclose][Y];
-	*z = finds[iclose][Z];
-	*id = surfs[iclose];
-    }
-
-    G_debug(3, "NumHits %d, next %d", numhits, Next_surf);
-
-    return (numhits);
-}
-
-/*!
-   \brief Set cplace rotation
-
-   \param num cplace id
-   \param dx,dy,dz rotation values
- */
-void GS_set_cplane_rot(int num, float dx, float dy, float dz)
-{
-    gsd_cplane_setrot(num, dx, dy, dz);
-
-    return;
-}
-
-/*!
-   \brief Set cplace trans
-
-   \param num cplace id
-   \param dx,dy,dz rotation values
- */
-void GS_set_cplane_trans(int num, float dx, float dy, float dz)
-{
-    gsd_cplane_settrans(num, dx, dy, dz);
-
-    return;
-}
-
-
-/*!
-   \brief Draw cplace
-
-   \param num cplace id
- */
-void GS_draw_cplane(int num)
-{
-    geosurf *gsurfs[MAX_SURFS];
-    int nsurfs;
-
-    nsurfs = gs_num_surfaces();
-    if (2 == nsurfs) {
-	/* testing */
-	gs_getall_surfaces(gsurfs);
-	gsd_draw_cplane_fence(gsurfs[0], gsurfs[1], num);
-    }
-    else {
-	gsd_draw_cplane(num);
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw cplace fence ?
-
-   \param hs1,hs2
-   \param num cplane id
-
-   \return 0 on error
-   \return 1 on success
- */
-int GS_draw_cplane_fence(int hs1, int hs2, int num)
-{
-    geosurf *gs1, *gs2;
-
-    if (NULL == (gs1 = gs_get_surf(hs1))) {
-	return (0);
-    }
-
-    if (NULL == (gs2 = gs_get_surf(hs2))) {
-	return (0);
-    }
-
-    gsd_draw_cplane_fence(gs1, gs2, num);
-
-    return (1);
-}
-
-/*!
-   \brief Draw all cplace fences ?
- */
-void GS_alldraw_cplane_fences(void)
-{
-    int onstate[MAX_CPLANES], i;
-
-    gsd_get_cplanes_state(onstate);
-
-    for (i = 0; i < MAX_CPLANES; i++) {
-	if (onstate[i]) {
-	    GS_draw_cplane_fence(Surf_ID[0], Surf_ID[1], i);
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Set cplace
-
-   \param num cplane id
- */
-void GS_set_cplane(int num)
-{
-    gsd_cplane_on(num);
-
-    return;
-}
-
-/*!
-   \brief Unset clip place (turn off)
-
-   \param num cplane id
- */
-void GS_unset_cplane(int num)
-{
-    gsd_cplane_off(num);
-
-    return;
-}
-
-/*!
-   \brief Get axis scale
-
-   \param sx,sy,sz x/y/z scale values
-   \param doexag use vertical exaggeration
- */
-void GS_get_scale(float *sx, float *sy, float *sz, int doexag)
-{
-    float zexag;
-
-    zexag = doexag ? Gv.vert_exag : 1.;
-    *sx = *sy = Gv.scale;
-    *sz = Gv.scale * zexag;
-
-    return;
-}
-
-/*!
-   \brief Set fence color
-
-   \param mode mode id
- */
-void GS_set_fencecolor(int mode)
-{
-    gsd_setfc(mode);
-
-    return;
-}
-
-/*!
-   \brief Get fence color
-
-   \return color value
- */
-int GS_get_fencecolor(void)
-{
-    return gsd_getfc();
-}
-
-/*!
-   \brief Measure distance "as the ball rolls" between two points on
-   surface
-
-   \param hs surface id
-   \param x1,y1,x2,y2 two points on surface
-   \param[out] dist measured distance
-   \param use_exag use exag. surface
-
-   \return 0 on error or if one or more points is not in region
-   \return distance following terrain
- */
-int GS_get_distance_alongsurf(int hs, float x1, float y1, float x2, float y2,
-			      float *dist, int use_exag)
-{
-    geosurf *gs;
-    float p1[2], p2[2];
-    
-    gs = gs_get_surf(hs);
-    if (gs == NULL) {
-	return 0;
-    }
-    
-    p1[X] = x1;
-    p1[Y] = y1;
-    p2[X] = x2;
-    p2[Y] = y2;
-    gsd_real2surf(gs, p1);
-    gsd_real2surf(gs, p2);
-
-    G_debug(3, "GS_get_distance_alongsurf(): hs=%d p1=%f,%f p2=%f,%f",
-	    hs, x1, y1, x2, y2);
-    return gs_distance_onsurf(gs, p1, p2, dist, use_exag);
-}
-
-/*!
-   \brief Save 3d view
-
-   \param vname view file name
-   \param surfid surface id
-
-   \return ?
- */
-int GS_save_3dview(const char *vname, int surfid)
-{
-    return (Gs_save_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
-}
-
-/*!
-   \brief Load 3d view
-
-   \param vname view file name
-   \param surfid surface id
-
-   \return ?
- */
-int GS_load_3dview(const char *vname, int surfid)
-{
-
-    return (Gs_load_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
-
-    /* what to do about lights - I guess, delete all &
-       create any that exist in 3dview file */
-}
-
-/************************************************************************
-* Following routines use Graphics Library
-************************************************************************/
-
-/*!
-   \brief Init viewpoint
-
-   \todo allow to set center?
- */
-void GS_init_view(void)
-{
-    static int first = 1;
-
-    G_debug(3, "GS_init_view");
-
-    if (first) {
-	first = 0;
-	glMatrixMode(GL_MODELVIEW);
-
-	/* OGLXXX doublebuffer: use GLX_DOUBLEBUFFER in attriblist */
-	/* glxChooseVisual(*dpy, screen, *attriblist); */
-	/* OGLXXX
-	 * ZMIN not needed -- always 0.
-	 * ZMAX not needed -- always 1.
-	 * getgdesc other posiblilties:
-	 *      glxGetConfig();
-	 *      glxGetCurrentContext();
-	 *      glxGetCurrentDrawable();
-	 * GLint gdtmp;
-	 * getgdesc other posiblilties:
-	 *      glxGetConfig();
-	 *      glxGetCurrentContext();
-	 *      glxGetCurrentDrawable();
-	 * GLint gdtmp;
-	 * glDepthRange params must be scaled to [0, 1]
-	 */
-	glDepthRange(0.0, 1.0);
-	glEnable(GL_DEPTH_TEST);
-	glDepthFunc(GL_LEQUAL);
-	/* } */
-
-	/* replace these with something meaningful */
-	Gv.fov = 450;
-	Gv.twist = 0;
-
-	GS_init_rotation();
-
-	Gv.from_to[FROM][X] = Gv.from_to[FROM][Y] =
-	    Gv.from_to[FROM][Z] = GS_UNIT_SIZE / 2.;
-
-	Gv.from_to[TO][X] = GS_UNIT_SIZE / 2.;
-	Gv.from_to[TO][Y] = GS_UNIT_SIZE / 2.;
-	Gv.from_to[TO][Z] = 0.;
-	Gv.from_to[TO][W] = Gv.from_to[FROM][W] = 1.;
-
-	Gv.real_to[W] = 1.;
-	Gv.vert_exag = 1.;
-
-	GS_v3eq(Gv.real_to, Gv.from_to[TO]);
-	GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
-
-	/*
-	   Gd.nearclip = 50;
-	   Gd.farclip = 10000.;
-	 */
-	Gd.nearclip = 10.;
-	Gd.farclip = 10000.;
-	Gd.aspect = (float)GS_get_aspect();
-
-	GS_set_focus(Gv.real_to);
-    }
-
-    return;
-}
-
-/*!
-   \brief Clear view
-
-   \param col color value
- */
-void GS_clear(int col)
-{
-    G_debug(3, "GS_clear");
-
-    col = col | 0xFF000000;
-
-    /* OGLXXX
-     * change glClearDepth parameter to be in [0, 1]
-     * ZMAX not needed -- always 1.
-     * getgdesc other posiblilties:
-     *      glxGetConfig();
-     *      glxGetCurrentContext();
-     *      glxGetCurrentDrawable();
-     * GLint gdtmp;
-     */
-    glClearDepth(1.0);
-    glClearColor(((float)((col) & 0xff)) / 255.,
-		 (float)((col) >> 8 & 0xff) / 255.,
-		 (float)((col) >> 16 & 0xff) / 255.,
-		 (float)((col) >> 24 & 0xff) / 255.);
-    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-
-    Gd.bgcol = col;
-    Modelshowing = 0;
-    gsd_flush();
-
-    return;
-}
-
-/*!
-   \brief Get aspect value
-
-   \return aspect value
- */
-double GS_get_aspect(void)
-{
-    int left, right, bottom, top;
-    GLint tmp[4];
-
-    /* OGLXXX
-     * get GL_VIEWPORT:
-     * You can probably do better than this.
-     */
-    glGetIntegerv(GL_VIEWPORT, tmp);
-    left = tmp[0];
-    right = tmp[0] + tmp[2] - 1;
-    bottom = tmp[1];
-    top = tmp[1] + tmp[3] - 1;
-
-    G_debug(3, "GS_get_aspect(): left=%d, right=%d, top=%d, bottom=%d",
-	    left, right, top, bottom);
-
-    return ((double)(right - left) / (top - bottom));
-}
-
-/*!
-   \brief Check for transparency
-
-   Disabled.
-
-   \return 1
- */
-int GS_has_transparency(void)
-{
-    /* OGLXXX
-     * getgdesc other posiblilties:
-     *      glxGetConfig();
-     *      glxGetCurrentContext();
-     *      glxGetCurrentDrawable();
-     * GLint gdtmp;
-     * blending is ALWAYS supported.
-     * This function returns whether it is enabled.
-     * return((glGetIntegerv(GL_BLEND, &gdtmp), gdtmp));
-     */
-
-    return (1);
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/GSX.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/GSX.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/GSX.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,70 +0,0 @@
-/*!
-   \file GSX.c
-
-   \brief OGSF library - loading and manipulating surfaces
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   (C) 1999-2008 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.
-
-   \author Bill Brown USACERL (December 1993)
-   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
- */
-
-#include <grass/ogsf.h>
-
-void (*Cxl_func) ();
-void (*Swap_func) ();
-
-static int Cxl = 0;
-
-/*!
-   \brief Check for cancel
-
-   \return code
- */
-int GS_check_cancel(void)
-{
-    Cxl_func();
-
-    return (Cxl);
-}
-
-/*!
-   \brief Set cancel
- */
-void GS_set_cancel(int c)
-{
-    Cxl = c;
-
-    return;
-}
-
-/*!
-   \brief Set cxl function
-
-   \param pointer to function
- */
-void GS_set_cxl_func(void (*f) (void))
-{
-    Cxl_func = f;
-
-    return;
-}
-
-/*!
-   \brief Set swap function
-
-   \param pointer to function
- */
-void GS_set_swap_func(void (*f) (void))
-{
-    Swap_func = f;
-
-    return;
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/GS_util.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/GS_util.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/GS_util.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,486 +0,0 @@
-/*!
-   \file GS_util.c
-
-   \brief OGSF library - loading and manipulating surfaces
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   (C) 1999-2008 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.
-
-   \author Bill Brown USACERL, GMSL/University of Illinois
-   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
- */
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#include <grass/gis.h>
-#include <grass/ogsf.h>
-
-/*!
-   \brief Calculate distance between 2 coordinates
-
-   Units is one of:
-   - "meters",
-   - "miles",
-   - "kilometers",
-   - "feet",
-   - "yards",
-   - "nmiles" (nautical miles),
-   - "rods",
-   - "inches",
-   - "centimeters",
-   - "millimeters",
-   - "micron",
-   - "nanometers",
-   - "cubits",
-   - "hands",
-   - "furlongs",
-   - "chains"
-
-   Default is meters.
-
-   \param from starting point
-   \param to ending point
-   \param units map units
-
-   \return distance between two geographic coordinates in current projection
- */
-double GS_geodistance(double *from, double *to, const char *units)
-{
-    double meters;
-
-    meters = Gs_distance(from, to);
-
-    if (!units) {
-	return (meters);
-    }
-
-    if (strcmp(units, "meters") == 0) {
-	return (meters);
-    }
-
-    if (strcmp(units, "miles") == 0) {
-	return (meters * .0006213712);
-    }
-
-    if (strcmp(units, "kilometers") == 0) {
-	return (meters * .001);
-    }
-
-    if (strcmp(units, "feet") == 0) {
-	return (meters * 3.280840);
-    }
-
-    if (strcmp(units, "yards") == 0) {
-	return (meters * 1.093613);
-    }
-
-    if (strcmp(units, "rods") == 0) {
-	return (meters * .1988388);
-    }
-
-    if (strcmp(units, "inches") == 0) {
-	return (meters * 39.37008);
-    }
-
-    if (strcmp(units, "centimeters") == 0) {
-	return (meters * 100.0);
-    }
-
-    if (strcmp(units, "millimeters") == 0) {
-	return (meters * 1000.0);
-    }
-
-    if (strcmp(units, "micron") == 0) {
-	return (meters * 1000000.0);
-    }
-
-    if (strcmp(units, "nanometers") == 0) {
-	return (meters * 1000000000.0);
-    }
-
-    if (strcmp(units, "cubits") == 0) {
-	return (meters * 2.187227);
-    }
-
-    if (strcmp(units, "hands") == 0) {
-	return (meters * 9.842520);
-    }
-
-    if (strcmp(units, "furlongs") == 0) {
-	return (meters * .004970970);
-    }
-
-    if (strcmp(units, "nmiles") == 0) {
-	/* nautical miles */
-	return (meters * .0005399568);
-    }
-
-    if (strcmp(units, "chains") == 0) {
-	return (meters * .0497097);
-    }
-
-    return (meters);
-}
-
-/*!
-   \brief Calculate distance
-
-   \param from 'from' point (X,Y,Z)
-   \param to 'to' point (X,Y,Z)
-
-   \return distance
- */
-float GS_distance(float *from, float *to)
-{
-    float x, y, z;
-
-    x = from[X] - to[X];
-    y = from[Y] - to[Y];
-    z = from[Z] - to[Z];
-
-    return (float)sqrt(x * x + y * y + z * z);
-}
-
-/*!
-   \brief Calculate distance in plane
-
-   \param from 'from' point (X,Y)
-   \param to 'to' point (X,Y)
-
-   \return distance
- */
-float GS_P2distance(float *from, float *to)
-{
-    float x, y;
-
-    x = from[X] - to[X];
-    y = from[Y] - to[Y];
-
-    return (float)sqrt(x * x + y * y);
-}
-
-/*!
-   \brief Copy vector values
-
-   v1 = v2
-
-   \param[out] v1 first vector
-   \param v2 second vector
- */
-void GS_v3eq(float *v1, float *v2)
-{
-    v1[X] = v2[X];
-    v1[Y] = v2[Y];
-    v1[Z] = v2[Z];
-
-    return;
-}
-
-/*!
-   \brief Sum vectors
-
-   v1 += v2
-
-   \param[in,out] v1 first vector
-   \param v2 second vector
- */
-void GS_v3add(float *v1, float *v2)
-{
-    v1[X] += v2[X];
-    v1[Y] += v2[Y];
-    v1[Z] += v2[Z];
-
-    return;
-}
-
-/*!
-   \brief Subtract vectors
-
-   v1 -= v2
-
-   \param[in,out] v1 first vector
-   \param v2 second vector
- */
-void GS_v3sub(float *v1, float *v2)
-{
-    v1[X] -= v2[X];
-    v1[Y] -= v2[Y];
-    v1[Z] -= v2[Z];
-
-    return;
-}
-
-/*!
-   \brief Multiple vectors
-
-   v1 *= k
-
-   \param[in,out] v1 vector
-   \param k multiplicator
- */
-void GS_v3mult(float *v1, float k)
-{
-    v1[X] *= k;
-    v1[Y] *= k;
-    v1[Z] *= k;
-
-    return;
-}
-
-/*!
-   \brief Change v1 so that it is a unit vector (2D)
-
-   \param[in,out] v1 vector
-
-   \return 0 if magnitude of v1 is zero
-   \return 1 if magnitude of v1 > 0
- */
-int GS_v3norm(float *v1)
-{
-    float n;
-
-    n = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y] + v1[Z] * v1[Z]);
-
-    if (n == 0.0) {
-	return (0);
-    }
-
-    v1[X] /= n;
-    v1[Y] /= n;
-    v1[Z] /= n;
-
-    return (1);
-}
-
-/*!
-   \brief Change v1 so that it is a unit vector (3D)
-
-   \param[in,out] v1 vector
-
-   \return 0 if magnitude of v1 is zero
-   \return 1 if magnitude of v1 > 0
- */
-int GS_v2norm(float *v1)
-{
-    float n;
-
-    n = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y]);
-
-    if (n == 0.0) {
-	return (0);
-    }
-
-    v1[X] /= n;
-    v1[Y] /= n;
-
-    return (1);
-}
-
-/*!
-   \brief Changes v1 so that it is a unit vector
-
-   \param dv1 vector
-
-   \return 0 if magnitude of dv1 is zero
-   \return 1 if magnitude of dv1 > 0
- */
-int GS_dv3norm(double *dv1)
-{
-    double n;
-
-    n = sqrt(dv1[X] * dv1[X] + dv1[Y] * dv1[Y] + dv1[Z] * dv1[Z]);
-
-    if (n == 0.0) {
-	return (0);
-    }
-
-    dv1[X] /= n;
-    dv1[Y] /= n;
-    dv1[Z] /= n;
-
-    return (1);
-}
-
-
-/*!
-   \brief Change v2 so that v1v2 is a unit vector
-
-   \param v1 first vector
-   \param v2[in,out] second vector
-
-   \return 0 if magnitude of dx is zero
-   \return 1 if magnitude of dx > 0
- */
-int GS_v3normalize(float *v1, float *v2)
-{
-    float n, dx, dy, dz;
-
-    dx = v2[X] - v1[X];
-    dy = v2[Y] - v1[Y];
-    dz = v2[Z] - v1[Z];
-    n = sqrt(dx * dx + dy * dy + dz * dz);
-
-    if (n == 0.0) {
-	return (0);
-    }
-
-    v2[X] = v1[X] + dx / n;
-    v2[Y] = v1[Y] + dy / n;
-    v2[Z] = v1[Z] + dz / n;
-
-    return (1);
-}
-
-
-/*!
-   \brief Get a normalized direction from v1 to v2, store in v3
-
-   \param v1 first vector
-   \param v2 second vector
-   \param[out] v3 output vector
-
-   \return 0 if magnitude of dx is zero
-   \return 1 if magnitude of dx > 0
- */
-int GS_v3dir(float *v1, float *v2, float *v3)
-{
-    float n, dx, dy, dz;
-
-    dx = v2[X] - v1[X];
-    dy = v2[Y] - v1[Y];
-    dz = v2[Z] - v1[Z];
-    n = sqrt(dx * dx + dy * dy + dz * dz);
-
-    if (n == 0.0) {
-	v3[X] = v3[Y] = v3[Z] = 0.0;
-	return (0);
-    }
-
-    v3[X] = dx / n;
-    v3[Y] = dy / n;
-    v3[Z] = dz / n;
-
-    return (1);
-}
-
-
-/*!
-   \brief Get a normalized direction from v1 to v2, store in v3 (2D)
-
-   \param v1 first vector
-   \param v2 second vector
-   \param[out] v3 output vector
-
-   \return 0 if magnitude of dx is zero
-   \return 1 if magnitude of dx > 0
- */
-void GS_v2dir(float *v1, float *v2, float *v3)
-{
-    float n, dx, dy;
-
-    dx = v2[X] - v1[X];
-    dy = v2[Y] - v1[Y];
-    n = sqrt(dx * dx + dy * dy);
-
-    v3[X] = dx / n;
-    v3[Y] = dy / n;
-
-    return;
-}
-
-/*!
-   \brief Get the cross product v3 = v1 cross v2
-
-   \param v1 first vector
-   \param v2 second vector
-   \param[out] v3 output vector
- */
-void GS_v3cross(float *v1, float *v2, float *v3)
-{
-    v3[X] = (v1[Y] * v2[Z]) - (v1[Z] * v2[Y]);
-    v3[Y] = (v1[Z] * v2[X]) - (v1[X] * v2[Z]);
-    v3[Z] = (v1[X] * v2[Y]) - (v1[Y] * v2[X]);
-
-    return;
-}
-
-/*!
-   \brief Magnitude of vector
-
-   \param v1 vector
-   \param[out] mag magnitude value
- */
-void GS_v3mag(float *v1, float *mag)
-{
-    *mag = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y] + v1[Z] * v1[Z]);
-
-    return;
-}
-
-/*!
-   \brief ADD
-
-   Initialize by calling with a number nhist to represent number of
-   previous entrys to check, then call with zero as nhist
-
-   \param p1 first point
-   \param p2 second point
-   \param nhist ?
-
-   \return -1 on error
-   \return -2
-   \return 1
-   \return 9
- */
-int GS_coordpair_repeats(float *p1, float *p2, int nhist)
-{
-    static float *entrys = NULL;
-    static int next = 0;
-    static int len = 0;
-    int i;
-
-    if (nhist) {
-	if (entrys) {
-	    G_free(entrys);
-	}
-
-	entrys = (float *)G_malloc(4 * nhist * sizeof(float));
-
-	if (!entrys)
-	    return (-1);
-
-	len = nhist;
-	next = 0;
-    }
-
-    if (!len) {
-	return (-2);
-    }
-
-    for (i = 0; i < next; i += 4) {
-	if (entrys[i] == p1[0] && entrys[i + 1] == p1[1]
-	    && entrys[i + 2] == p2[0] && entrys[i + 3] == p2[1]) {
-	    return (1);
-	}
-    }
-
-    if (len == next / 4) {
-	next = 0;
-    }
-
-    entrys[next] = p1[0];
-    entrys[next + 1] = p1[1];
-    entrys[next + 2] = p2[0];
-    entrys[next + 3] = p2[1];
-    next += 4;
-
-    return (0);
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/GV2.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/GV2.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/GV2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,601 +0,0 @@
-/*!
-   \file lib/ogsf/GV2.c
-
-   \brief OGSF library - loading and manipulating vector sets (higher level functions)
-
-   (C) 1999-2008, 2011 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.
-
-   \author Bill Brown USACERL, GMSL/University of Illinois
-   \author Updated by Martin landa <landa.martin gmail.com>
-   (doxygenized in May 2008, thematic mapping in June 2011)
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grass/gis.h>
-#include <grass/ogsf.h>
-
-#include "gsget.h"
-
-static int Vect_ID[MAX_VECTS];
-static int Next_vect = 0;
-
-/*!
-   \brief Check if vector set exists
-
-   \param id vector set id
-
-   \return 0 not found
-   \return 1 found
- */
-int GV_vect_exists(int id)
-{
-    int i, found = 0;
-
-    G_debug(3, "GV_vect_exists");
-
-    if (NULL == gv_get_vect(id)) {
-	return (0);
-    }
-
-    for (i = 0; i < Next_vect && !found; i++) {
-	if (Vect_ID[i] == id) {
-	    found = 1;
-	}
-    }
-
-    return (found);
-}
-
-/*!
-   \brief Register new vector set
-
-   \return vector set id
-   \return -1 on error
- */
-int GV_new_vector(void)
-{
-    geovect *nv;
-
-    if (Next_vect < MAX_VECTS) {
-	nv = gv_get_new_vect();
-	gv_set_defaults(nv);
-	Vect_ID[Next_vect] = nv->gvect_id;
-	++Next_vect;
-
-	G_debug(3, "GV_new_vector(): id=%d", nv->gvect_id);
-
-	return nv->gvect_id;
-    }
-
-    return -1;
-}
-
-/*!
-   \brief Get number of available vector sets
-
-   \return number of vector sets
- */
-int GV_num_vects(void)
-{
-    return (gv_num_vects());
-}
-
-/*!
-   \brief Get list of vector sets
-
-   Must free when no longer needed!
-
-   \param numvects number of vector sets
-
-   \return pointer to list of point sets
-   \return NULL on error
- */
-int *GV_get_vect_list(int *numvects)
-{
-    int i, *ret;
-
-    *numvects = Next_vect;
-
-    if (Next_vect) {
-	ret = (int *)G_malloc(Next_vect * sizeof(int));
-	if (!ret) {
-	    return (NULL);
-	}
-
-	for (i = 0; i < Next_vect; i++) {
-	    ret[i] = Vect_ID[i];
-	}
-
-	return (ret);
-    }
-
-    return (NULL);
-}
-
-/*!
-   \brief Delete vector set from list
-
-   \param id vector set id
-
-   \return 1 on success
-   \return -1 on error
- */
-int GV_delete_vector(int id)
-{
-    int i, j, found = 0;
-
-    G_debug(3, "GV_delete_vect");
-
-    if (GV_vect_exists(id)) {
-	gv_delete_vect(id);
-
-	for (i = 0; i < Next_vect && !found; i++) {
-	    if (Vect_ID[i] == id) {
-		found = 1;
-
-		for (j = i; j < Next_vect; j++) {
-		    Vect_ID[j] = Vect_ID[j + 1];
-		}
-	    }
-	}
-
-	if (found) {
-	    --Next_vect;
-	    return (1);
-	}
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Load vector set
-
-   Check to see if handle already loaded, if so - free before loading
-   new for now, always load to memory
-
-   \todo Load file handle & ready for reading instead of using
-   memory
-
-   \param id vector set id
-   \param filename filename
-
-   \return -1 on error (invalid vector set id)
-   \return 1 on success
- */
-int GV_load_vector(int id, const char *filename)
-{
-    geovect *gv;
-
-    if (NULL == (gv = gv_get_vect(id))) {
-	return (-1);
-    }
-
-    if (gv->lines) {
-	gv_free_vectmem(gv);
-    }
-
-    gv->filename = G_store(filename);
-
-    if ((gv->lines = Gv_load_vect(filename, &(gv->n_lines)))) {
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get vector map name
-
-   Note: char array is allocated by G_store()
-
-   \param id vector set id
-   \param filename &filename
-
-   \return -1 on error (invalid vector set id)
-   \return 1 on success
- */
-int GV_get_vectname(int id, char **filename)
-{
-    geovect *gv;
-
-    if (NULL == (gv = gv_get_vect(id))) {
-	return (-1);
-    }
-
-    *filename = G_store(gv->filename);
-
-    return (1);
-}
-
-/*!
-   \brief Set vector style
-
-   \param id vector set id
-   \param mem non-zero for use memory
-   \param color color value
-   \param width line width
-   \param flat non-zero for flat mode
-
-   \return -1 on error (invalid vector set id)
-   \return 1 on success
- */
-int GV_set_style(int id, int mem, int color, int width, int flat)
-{
-    geovect *gv;
-
-    if (NULL == (gv = gv_get_vect(id))) {
-	return -1;
-    }
-
-    gv->use_mem = mem;
-    gv->flat_val = flat;
-    gv->style->color = color;
-    gv->style->width = width;
-
-    return 1;
-}
-
-
-/*!
-   \brief Get vector style
-
-   \param id vector set id
-   \param[out] mem non-zero for use memory
-   \param[out] color color value
-   \param[out] width line width
-   \param[out] flat non-zero for flat mode
-
-   \return -1 on error (invalid vector set id)
-   \return 1 on success
- */
-int GV_get_style(int id, int *mem, int *color, int *width, int *flat)
-{
-    geovect *gv;
-
-    if (NULL == (gv = gv_get_vect(id))) {
-	return -1;
-    }
-
-    *mem = gv->use_mem;
-    *color = gv->style->color;
-    *width = gv->style->width;
-    *flat = gv->flat_val;
-
-    return 1;
-}
-
-/*!
-   \brief Set vector set style for thematic mapping
-   
-   Updates also style for each geoline.
-   
-   \param id vector set id
-   \param layer layer number for thematic mapping
-   \param color color column name
-   \param width width column name
-   \param colors pointer to Colors structure or NULL
-
-   \return 1 on success
-   \return -1 on error (point set not found)
- */
-int GV_set_style_thematic(int id, int layer, const char* color, const char* width,
-			  struct Colors *color_rules)
-{
-    geovect *gv;
-
-    if (NULL == (gv = gv_get_vect(id))) {
-	return -1;
-    }
-
-    if(!gv->tstyle)
-	gv->tstyle = (gvstyle_thematic *)G_malloc(sizeof(gvstyle_thematic));
-    G_zero(gv->tstyle, sizeof(gvstyle_thematic));
-    
-    gv->tstyle->active = 1;
-    gv->tstyle->layer = layer;
-    if (color)
-	gv->tstyle->color_column = G_store(color);
-    if (width)
-	gv->tstyle->width_column = G_store(width);
-
-    Gv_load_vect_thematic(gv, color_rules);
-
-    return 1;
-}
-
-/*!
-   \brief Make style for thematic mapping inactive
-   
-   \param id vector set id
-
-   \return 1 on success
-   \return -1 on error (point set not found)
- */
-int GV_unset_style_thematic(int id)
-{
-    geovect *gv;
-
-    G_debug(4, "GV_unset_style_thematic(): id=%d", id);
-
-    if (NULL == (gv = gv_get_vect(id))) {
-	return -1;
-    }
-
-    if (gv->tstyle) {
-	gv->tstyle->active = 0;
-    }
-
-    return 1;
-}
-
-/*!
-   \brief Set trans ?
-
-   \param id vector set id
-   \param xtrans,ytrans,ztrans x/y/z trans values
- */
-void GV_set_trans(int id, float xtrans, float ytrans, float ztrans)
-{
-    geovect *gv;
-
-    G_debug(3, "GV_set_trans");
-
-    gv = gv_get_vect(id);
-
-    if (gv) {
-	gv->x_trans = xtrans;
-	gv->y_trans = ytrans;
-	gv->z_trans = ztrans;
-    }
-
-    return;
-}
-
-/*!
-   \brief Get trans ?
-
-   \param id vector set id
-   \param[out] xtrans,ytrans,ztrans x/y/z trans values
- */
-int GV_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
-{
-    geovect *gv;
-
-    gv = gv_get_vect(id);
-
-    if (gv) {
-	*xtrans = gv->x_trans;
-	*ytrans = gv->y_trans;
-	*ztrans = gv->z_trans;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Select surface identified by hs to have vector identified
-   by hv draped over it
-
-   \param hv vector set id
-   \param hs surface id
-
-   \return 1 on success
-   \return -1 on error
- */
-int GV_select_surf(int hv, int hs)
-{
-    geovect *gv;
-
-    if (GV_surf_is_selected(hv, hs)) {
-	return (1);
-    }
-
-    gv = gv_get_vect(hv);
-
-    if (gv && GS_surf_exists(hs)) {
-	gv->drape_surf_id[gv->n_surfs] = hs;
-	gv->n_surfs += 1;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Unselect surface
-
-   \param hv vector set id
-   \param hs surface id
-
-   \return 1 on success
-   \return -1 on error
- */
-int GV_unselect_surf(int hv, int hs)
-{
-    geovect *gv;
-    int i, j;
-
-    if (!GV_surf_is_selected(hv, hs)) {
-	return (1);
-    }
-
-    gv = gv_get_vect(hv);
-
-    if (gv) {
-	for (i = 0; i < gv->n_surfs; i++) {
-	    if (gv->drape_surf_id[i] == hs) {
-		for (j = i; j < gv->n_surfs - 1; j++) {
-		    gv->drape_surf_id[j] = gv->drape_surf_id[j + 1];
-		}
-
-		gv->n_surfs -= 1;
-
-		return (1);
-	    }
-	}
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Check if surface is selected
-
-   \param hv vector set id
-   \param hs surface id
-
-   \return 1 selected
-   \return 0 not selected
- */
-int GV_surf_is_selected(int hv, int hs)
-{
-    int i;
-    geovect *gv;
-
-    gv = gv_get_vect(hv);
-
-    if (gv) {
-	for (i = 0; i < gv->n_surfs; i++) {
-	    if (hs == gv->drape_surf_id[i]) {
-		return (1);
-	    }
-	}
-    }
-
-    return (0);
-}
-
-/*!
-   \brief Draw vector set
-
-   \param vid vector set id
- */
-void GV_draw_vect(int vid)
-{
-    geosurf *gs;
-    geovect *gv;
-    int i;
-
-    gv = gv_get_vect(vid);
-
-    if (gv) {
-	for (i = 0; i < gv->n_surfs; i++) {
-	    gs = gs_get_surf(gv->drape_surf_id[i]);
-
-	    if (gs) {
-		gvd_vect(gv, gs, 0);
-	    }
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw all loaded vector sets
- */
-void GV_alldraw_vect(void)
-{
-    int id;
-
-    for (id = 0; id < Next_vect; id++) {
-	GV_draw_vect(Vect_ID[id]);
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw vector set (fast mode)
-
-   \todo Seems to be broken, nothing is drawn
-
-   \param vid vector set id
- */
-void GV_draw_fastvect(int vid)
-{
-    geosurf *gs;
-    geovect *gv;
-    int i;
-
-    gv = gv_get_vect(vid);
-
-    if (gv) {
-	for (i = 0; i < gv->n_surfs; i++) {
-	    gs = gs_get_surf(gv->drape_surf_id[i]);
-
-	    if (gs) {
-		gvd_vect(gv, gs, 1);
-	    }
-	}
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw all loaded vector sets (fast mode)
- */
-void GV_alldraw_fastvect(void)
-{
-    int id;
-
-    for (id = 0; id < Next_vect; id++) {
-	GV_draw_fastvect(Vect_ID[id]);
-    }
-
-    return;
-}
-
-/*!
-   \brief Set client data
-
-   \param id vector set id
-   \param clientd pointer to client data
-
-   \return 1 on success
-   \return -1 on error
- */
-int GV_Set_ClientData(int id, void *clientd)
-{
-    geovect *gv;
-
-    gv = gv_get_vect(id);
-    if (gv) {
-	gv->clientdata = clientd;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get client data
-
-   \param id vector set id
-
-   \return pointer to client data
-   \return NULL on error
- */
-void *GV_Get_ClientData(int id)
-{
-    geovect *gv;
-
-    gv = gv_get_vect(id);
-
-    if (gv) {
-	return (gv->clientdata);
-    }
-
-    return (NULL);
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/GVL2.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/GVL2.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/GVL2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,1521 +0,0 @@
-/*!
-   \file GVL2.c
-
-   \brief OGSF library - loading and manipulating volumes
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   (C) 1999-2008 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.
-
-   \author Bill Brown UI-GMSL (May 1997)
-   Tomas Paudits (February 2004)
- */
-
-#include <string.h>
-#include <grass/gis.h>
-#include <grass/raster3d.h>
-#include <grass/ogsf.h>
-#include <grass/glocale.h>
-#include "gsget.h"
-
-static int Vol_ID[MAX_VOLS];
-static int Next_vol = 0;
-
-static RASTER3D_Region wind3;
-static double Region[6];
-
-/*!
-   \brief Library intialization for volumes
-
-   Set region extent (N,S,W,E,T,B)
- */
-void GVL_libinit(void)
-{
-    Rast3d_init_defaults();
-    Rast3d_get_window(&wind3);
-
-    Region[0] = wind3.north;
-    Region[1] = wind3.south;
-    Region[2] = wind3.west;
-    Region[3] = wind3.east;
-    Region[4] = wind3.top;
-    Region[5] = wind3.bottom;
-
-    return;
-}
-
-/*!
-   \brief Initialize 3D region
-
-   Set region extent (N,S,W,E,T,B)
- */
-void GVL_init_region(void)
-{
-    Rast3d_read_window(&wind3, NULL);
-
-    Region[0] = wind3.north;
-    Region[1] = wind3.south;
-    Region[2] = wind3.west;
-    Region[3] = wind3.east;
-    Region[4] = wind3.top;
-    Region[5] = wind3.bottom;
-
-    return;
-}
-
-/*!
-   \brief Get region extent settings
-
-   \param[out] n,s,w,e north, south, west, east
-   \param[out] t,b top, bottom
-
-   \return 1
- */
-int GVL_get_region(float *n, float *s, float *w, float *e, float *t, float *b)
-{
-    *n = Region[0];
-    *s = Region[1];
-    *w = Region[2];
-    *e = Region[3];
-    *t = Region[4];
-    *b = Region[5];
-
-    return (1);
-}
-
-/*!
-   \brief Get window 
-
-   \todo gvl_file.c use this - change
-
-   \return pointer to RASTER3D_Region struct (static)
- */
-void *GVL_get_window()
-{
-    return &wind3;
-}
-
-/*!
-   \brief Check if volume set exists
-
-   \param id volume set id
-
-   \return 1 found
-   \return 0 not found
- */
-int GVL_vol_exists(int id)
-{
-    int i, found = 0;
-
-    G_debug(3, "GVL_vol_exists");
-
-    if (NULL == gvl_get_vol(id)) {
-	return (0);
-    }
-
-    for (i = 0; i < Next_vol && !found; i++) {
-	if (Vol_ID[i] == id) {
-	    found = 1;
-	}
-    }
-
-    return (found);
-}
-
-/*!
-   \brief Create new volume set
-
-   \return volume set id
-   \return -1 on error
- */
-int GVL_new_vol(void)
-{
-    geovol *nvl;
-
-    G_debug(3, "GVL_new_vol():");
-
-    if (Next_vol < MAX_VOLS) {
-	nvl = gvl_get_new_vol();
-
-	gvl_init_vol(nvl, wind3.west + wind3.ew_res / 2.,
-		     wind3.south + wind3.ns_res / 2., wind3.bottom,
-		     wind3.rows, wind3.cols, wind3.depths,
-		     wind3.ew_res, wind3.ns_res, wind3.tb_res);
-
-	Vol_ID[Next_vol] = nvl->gvol_id;
-	++Next_vol;
-
-	G_debug(3, "    id=%d", nvl->gvol_id);
-	
-	return (nvl->gvol_id);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get number of loaded volume sets
-
-   \return number of volume sets
- */
-int GVL_num_vols(void)
-{
-    return (gvl_num_vols());
-}
-
-/*!
-   \brief Get list of loaded volume sets
-
-   Must be freed if not needed!
-
-   \param[out] numvols number of volume sets
-
-   \return pointer to list of volume sets
-   \return NULL on error
- */
-int *GVL_get_vol_list(int *numvols)
-{
-    int i, *ret;
-
-    *numvols = Next_vol;
-
-    if (Next_vol) {
-	ret = (int *)G_malloc(Next_vol * sizeof(int));
-	if (!ret)
-	    return (NULL);
-
-	for (i = 0; i < Next_vol; i++) {
-	    ret[i] = Vol_ID[i];
-	}
-
-	return (ret);
-    }
-
-    return (NULL);
-}
-
-/*!
-   \brief Delete volume set from list
-
-   \param id volume set id
-
-   \return 1 on success
-   \return -1 on error (invalid volume set id)
- */
-int GVL_delete_vol(int id)
-{
-    int i, j, found = 0;
-
-    G_debug(3, "GVL_delete_vol");
-
-    if (GVL_vol_exists(id)) {
-
-	for (i = 0; i < GVL_isosurf_num_isosurfs(id); i++) {
-	    GVL_isosurf_del(id, 0);
-	}
-
-	for (i = 0; i < GVL_slice_num_slices(id); i++) {
-	    GVL_slice_del(id, 0);
-	}
-
-	gvl_delete_vol(id);
-
-	for (i = 0; i < Next_vol && !found; i++) {
-	    if (Vol_ID[i] == id) {
-		found = 1;
-		for (j = i; j < Next_vol; j++) {
-		    Vol_ID[j] = Vol_ID[j + 1];
-		}
-	    }
-	}
-
-	if (found) {
-	    --Next_vol;
-
-	    return (1);
-	}
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Load 3d raster map to volume set
-
-   \param id volume set id
-   \param filename 3d raster map name
-
-   \return -1 on error
-   \return 0 on success
- */
-int GVL_load_vol(int id, const char *filename)
-{
-    geovol *gvl;
-    int handle;
-
-    G_debug(3, "GVL_load_vol(): id=%d, name=%s", id, filename);
-
-    if (NULL == (gvl = gvl_get_vol(id))) {
-	return (-1);
-    }
-
-    G_message(_("Loading 3d raster map <%s>..."), filename);
-
-    if (0 > (handle = gvl_file_newh(filename, VOL_FTYPE_RASTER3D)))
-	return (-1);
-
-    gvl->hfile = handle;
-
-    return (0);
-}
-
-/*!
-   \brief Get volume set name
-
-   \param id volume set id
-   \param[out] filename name (must be allocated)
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_get_volname(int id, char *filename)
-{
-    geovol *gvl;
-
-    if (NULL == (gvl = gvl_get_vol(id))) {
-	return (-1);
-    }
-
-    if (0 > gvl->hfile) {
-	return (-1);
-    }
-
-    strcpy(filename, gvl_file_get_name(gvl->hfile));
-
-    return (1);
-}
-
-/*!
-   \brief Get volume dimensions
-
-   \param id volume set id
-   \param[out] rows,cols,depths number of rows, cols, depths
- */
-void GVL_get_dims(int id, int *rows, int *cols, int *depths)
-{
-    geovol *gvl;
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	*rows = gvl->rows;
-	*cols = gvl->cols;
-	*depths = gvl->depths;
-    }
-
-    G_debug(3, "GVL_get_dims() id=%d, rows=%d, cols=%d, depths=%d",
-	    gvl->gvol_id, gvl->rows, gvl->cols, gvl->depths);
-    
-    return;
-}
-
-/*!
-   \brief Set trans ?
-
-   \param id volume set id
-   \param xtrans,ytrans,ztrans x/y/z trans values
- */
-void GVL_set_trans(int id, float xtrans, float ytrans, float ztrans)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_set_trans");
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	gvl->x_trans = xtrans;
-	gvl->y_trans = ytrans;
-	gvl->z_trans = ztrans;
-    }
-
-    return;
-}
-
-/*!
-   \brief Get trans ?
-
-   \param id volume set id
-   \param[out] xtrans,ytrans,ztrans x/y/z trans values
-
-   \return 1 on success
-   \return -1 on error
- */
-int GVL_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
-{
-    geovol *gvl;
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	*xtrans = gvl->x_trans;
-	*ytrans = gvl->y_trans;
-	*ztrans = gvl->z_trans;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set drawing wire box
-
-   \param id volume set id
-   \param draw_wire 1 for drawing wire, 0 otherwise
- */
-void GVL_set_draw_wire(int id, int draw_wire)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_set_draw_wire");
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	gvl->draw_wire = draw_wire;
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw volume set
-
-   \param vid volume set id
- */
-void GVL_draw_vol(int vid)
-{
-    geovol *gvl;
-
-    gvl = gvl_get_vol(vid);
-
-    if (gvl) {
-	gvld_vol(gvl);
-        if (gvl->draw_wire) {
-	    gvld_wind3_box(gvl);
-        }
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw volume in wire mode
-
-   \param id volume set id
- */
-void GVL_draw_wire(int id)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_draw_wire(): id=%d", id);
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	gvld_wire_vol(gvl);
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw all volume sets
- */
-void GVL_alldraw_vol(void)
-{
-    int id;
-
-    for (id = 0; id < Next_vol; id++) {
-	GVL_draw_vol(Vol_ID[id]);
-    }
-
-    return;
-}
-
-/*!
-   \brief Draw all volume sets in wire mode
- */
-void GVL_alldraw_wire(void)
-{
-    int id;
-
-    for (id = 0; id < Next_vol; id++) {
-	GVL_draw_wire(Vol_ID[id]);
-    }
-
-    return;
-}
-
-/*!
-   \brief Set client data for volume set
-
-   \param id volume set id
-   \param clientd pointer to client data
-
-   \return 1 on success
-   \return -1 on error
- */
-int GVL_Set_ClientData(int id, void *clientd)
-{
-    geovol *gvl;
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	gvl->clientdata = clientd;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get client data
-
-   \param id volume set id
-
-   \return pointer to client data
-   \return NULL on error
- */
-void *GVL_Get_ClientData(int id)
-{
-    geovol *gvl;
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	return (gvl->clientdata);
-    }
-
-    return (NULL);
-}
-
-/*!
-   \brief Set focus on map center
-
-   \param id volume set id
- */
-void GVL_set_focus_center_map(int id)
-{
-    float center[3];
-    geovol *gvl;
-
-    G_debug(3, "GS_set_focus_center_map");
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	center[X] = (gvl->xmax - gvl->xmin) / 2.;
-	center[Y] = (gvl->ymax - gvl->ymin) / 2.;
-	center[Z] = (gvl->zmax - gvl->zmin) / 2.;
-
-	GS_set_focus(center);
-    }
-
-    return;
-}
-
-/************************************************************************/
-/* ISOSURFACES */
-
-/************************************************************************/
-
-/*!
-   \brief Get draw resolution for isosurface
-
-   \todo error handling
-
-   \param id volume set id
-   \param[out] xres,yres,zres x/y/z resolution value
- */
-void GVL_isosurf_get_drawres(int id, int *xres, int *yres, int *zres)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_isosurf_get_drawres");
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	*xres = gvl->isosurf_x_mod;
-	*yres = gvl->isosurf_y_mod;
-	*zres = gvl->isosurf_z_mod;
-    }
-
-    return;
-}
-
-/*!
-   \brief Set isosurface draw resolution
-
-   \param id volume set id
-   \param xres,yres,zres x/y/z resolution value
-
-   \return -1 on error (invalid values/volume set id)
-   \return 0 on success
- */
-int GVL_isosurf_set_drawres(int id, int xres, int yres, int zres)
-{
-    geovol *gvl;
-    int i;
-
-    G_debug(3, "GVL_isosurf_set_drawres(): id=%d", id);
-
-    if (xres < 1 || yres < 1 || zres < 1) {
-	return (-1);
-    }
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	gvl->isosurf_x_mod = xres;
-	gvl->isosurf_y_mod = yres;
-	gvl->isosurf_z_mod = zres;
-
-	for (i = 0; i < gvl->n_isosurfs; i++) {
-	    gvl_isosurf_set_att_changed(gvl->isosurf[i], ATT_TOPO);
-	}
-
-	return (0);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get isosurface draw mode
-
-   \param id volume set id
-   \param[out] mode draw-mode
-
-   \return 1 on success
-   \return -1 on error
- */
-int GVL_isosurf_get_drawmode(int id, int *mode)
-{
-    geovol *gvl;
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	*mode = gvl->isosurf_draw_mode;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set isosurface draw mode
-
-   \param id volume set id
-   \param mode draw mode
-
-   \return 0 on success
-   \return -1 on error (invalid volume set id)
- */
-int GVL_isosurf_set_drawmode(int id, int mode)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_isosurf_set_drawmode(): id=%d mode=%d", id, mode);
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	gvl->isosurf_draw_mode = mode;
-
-	return (0);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Add isosurface
-
-   \param id volume set id
-
-   \return -1 on error (invalid volume set id
-   \return 1 on success
- */
-int GVL_isosurf_add(int id)
-{
-    geovol *gvl;
-    geovol_isosurf *isosurf;
-
-    G_debug(3, "GVL_isosurf_add() id=%d", id);
-
-    gvl = gvl_get_vol(id);
-
-    if (!gvl)
-	return (-1);
-
-    if (gvl->n_isosurfs == MAX_ISOSURFS)
-	return (-1);
-
-    isosurf = (geovol_isosurf *) G_malloc(sizeof(geovol_isosurf));
-    if (!isosurf) {
-	return (-1);
-    }
-
-    gvl_isosurf_init(isosurf);
-
-    gvl->n_isosurfs++;
-    gvl->isosurf[gvl->n_isosurfs - 1] = (geovol_isosurf *) isosurf;
-
-    return (1);
-}
-
-/*!
-   \brief Delete isosurface
-
-   \param id volume set id
-   \param isosurf_id isosurface id
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_isosurf_del(int id, int isosurf_id)
-{
-    geovol *gvl;
-    geovol_isosurf *isosurf;
-    int i;
-
-    G_debug(3, "GVL_isosurf_del");
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (!isosurf)
-	return (-1);
-
-    if (!gvl_isosurf_freemem(isosurf)) {
-	return (-1);
-    }
-
-    gvl = gvl_get_vol(id);
-
-    G_free(gvl->isosurf[isosurf_id]);
-
-    for (i = isosurf_id + 1; i < gvl->n_isosurfs; i++) {
-	gvl->isosurf[i - 1] = gvl->isosurf[i];
-    }
-
-    gvl->n_isosurfs--;
-
-    return (1);
-}
-
-/*!
-   \brief Move up isosurface in list
-
-   \param id volume set id
-   \param isosurf_id isosurface id
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_isosurf_move_up(int id, int isosurf_id)
-{
-    geovol *gvl;
-    geovol_isosurf *tmp;
-
-    G_debug(3, "GVL_isosurf_move_up");
-
-    gvl = gvl_get_vol(id);
-
-    if (!gvl)
-	return (-1);
-
-    if (isosurf_id < 0 || isosurf_id > (gvl->n_isosurfs - 1))
-	return (-1);
-
-    if (isosurf_id == 0)
-	return (1);
-
-    tmp = gvl->isosurf[isosurf_id - 1];
-    gvl->isosurf[isosurf_id - 1] = gvl->isosurf[isosurf_id];
-    gvl->isosurf[isosurf_id] = tmp;
-
-    return (1);
-}
-
-/*!
-   \brief Move down isosurface in list
-
-   \param id volume set id
-   \param isosurf_id isosurface id
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_isosurf_move_down(int id, int isosurf_id)
-{
-    geovol *gvl;
-    geovol_isosurf *tmp;
-
-    G_debug(3, "GVL_isosurf_move_up");
-
-    gvl = gvl_get_vol(id);
-
-    if (!gvl)
-	return (-1);
-
-    if (isosurf_id < 0 || isosurf_id > (gvl->n_isosurfs - 1))
-	return (-1);
-
-    if (isosurf_id == (gvl->n_isosurfs - 1))
-	return (1);
-
-    tmp = gvl->isosurf[isosurf_id + 1];
-    gvl->isosurf[isosurf_id + 1] = gvl->isosurf[isosurf_id];
-    gvl->isosurf[isosurf_id] = tmp;
-
-    return (1);
-}
-
-/*!
-   \brief Get isosurface attributes
-
-   \param id volume set id
-   \param isosurf_id surface id
-   \param att attribute id
-   \param[out] set
-   \param[out] constant
-   \param[out] mapname
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_isosurf_get_att(int id, int isosurf_id,
-			int att, int *set, float *constant, char *mapname)
-{
-    int src;
-    geovol_isosurf *isosurf;
-
-    G_debug(3, "GVL_isosurf_get_att");
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (isosurf) {
-	if (-1 != (src = gvl_isosurf_get_att_src(isosurf, att))) {
-	    *set = src;
-
-	    if (src == CONST_ATT) {
-		*constant = isosurf->att[att].constant;
-	    }
-	    else if (src == MAP_ATT) {
-		strcpy(mapname, gvl_file_get_name(isosurf->att[att].hfile));
-	    }
-
-	    return (1);
-	}
-
-	return (-1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Unset isosurface attributes
-
-   \param id volume set id
-   \param isosurface_id isosurface id
-   \param att attribute id
-
-   \return ?
-   \return -1 on error
- */
-int GVL_isosurf_unset_att(int id, int isosurf_id, int att)
-{
-    geovol_isosurf *isosurf;
-
-    G_debug(3, "GVL_isosurf_unset_att");
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (isosurf) {
-	return (gvl_isosurf_set_att_src(isosurf, att, NOTSET_ATT));
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set constant isosurface attribute
-
-   Attributes:
-    - ATT_NORM
-    - ATT_TOPO topography (level) constant
-    - ATT_COLOR color map/constant
-    - ATT_MASK mask map
-    - ATT_TRANSP transparency map/constant
-    - ATT_SHINE shininess map/constant
-    - ATT_EMIT emission map/constant
-
-   \param id volume set id
-   \param isosurf_id isosurface id (0 - MAX_ISOSURFS)
-   \param att attribute descriptor
-   \param constant constant value
-
-   \return 1 on success
-   \return -1 on error
- */
-int GVL_isosurf_set_att_const(int id, int isosurf_id, int att, float constant)
-{
-    geovol_isosurf *isosurf;
-
-    G_debug(3, "GVL_isosurf_set_att_const() id=%d isosurf_id=%d "
-	    "att=%d const=%f", id, isosurf_id, att, constant);
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (isosurf) {
-	return (gvl_isosurf_set_att_const(isosurf, att, constant));
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set isosurface map attribute
-
-   Attributes:
-    - ATT_NORM
-    - ATT_TOPO topography (level) constant
-    - ATT_COLOR color map/constant
-    - ATT_MASK mask map
-    - ATT_TRANSP transparency map/constant
-    - ATT_SHINE shininess map/constant
-    - ATT_EMIT emission map/constant
-
-   \param id volume set id
-   \param isosurf_id isosurface id (0 - MAX_ISOSURFS)
-   \param att attribute descriptor
-   \param filename map name
-
-   \return 1 on success
-   \return -1 on error
- */
-int GVL_isosurf_set_att_map(int id, int isosurf_id, int att,
-			    const char *filename)
-{
-    geovol_isosurf *isosurf;
-
-    G_debug(3, "GVL_isosurf_set_att_map(): id=%d, isosurf_id=%d "
-	    "att=%d map=%s", id, isosurf_id, att, filename);
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (isosurf) {
-	return gvl_isosurf_set_att_map(isosurf, att, filename);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get isosurface flags
-
-   \param id volume set id
-   \param isosurf_id isosurface id
-   \param[out] inout map name
-
-   \return 1 on success
-   \return -1 on error
- */
-int GVL_isosurf_get_flags(int id, int isosurf_id, int *inout)
-{
-    geovol_isosurf *isosurf;
-
-    G_debug(3, "GVL_isosurf_get_flags");
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (isosurf) {
-	*inout = isosurf->inout_mode;
-
-	return (1);
-    }
-    return (-1);
-}
-
-/*!
-   \brief Set isosurface flags
-
-   \param id volume set id
-   \param isosurf_id isosurface id
-   \param inout map name
-
-   \return 1 on success
-   \return -1 on error
- */
-int GVL_isosurf_set_flags(int id, int isosurf_id, int inout)
-{
-    geovol_isosurf *isosurf;
-
-    G_debug(3, "GVL_isosurf_get_flags");
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (isosurf) {
-	isosurf->inout_mode = inout;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get number of available isosurfaces
-
-   \param id volume set id
-
-   \return number of isosurfaces
-   \return -1 on error
- */
-int GVL_isosurf_num_isosurfs(int id)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_isosurf_num_isosurfs");
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	return gvl->n_isosurfs;
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set mask attribute mode
-
-   Mask attribute special: constant is set to indicate invert or no
-
-   \param id volume set id
-   \param isosurf_id isosurface id
-   \param mode attribute mode
-
-   \return mode id
-   \return -1 on error
- */
-int GVL_isosurf_set_maskmode(int id, int isosurf_id, int mode)
-{
-    geovol_isosurf *isosurf;
-
-    G_debug(3, "GVL_isosurf_set_att_const");
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (isosurf) {
-	isosurf->att[ATT_MASK].constant = mode;
-
-	return (mode);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get isosurface mask mode
-
-   \param id volume set id
-   \param isosurf_id isosurface id
-   \param mode attribute mode
-
-   \return 1 on success
-   \return -1 on error
- */
-int GVL_isosurf_get_maskmode(int id, int isosurf_id, int *mode)
-{
-    geovol_isosurf *isosurf;
-
-    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
-
-    if (isosurf) {
-	*mode = isosurf->att[ATT_MASK].constant;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/************************************************************************/
-/* SLICES */
-
-/************************************************************************/
-
-/*!
-   \brief Get draw resolution of slice
-
-   \param id volume set id
-   \param[out] xres,yres,zres x/y/z resolution value
- */
-void GVL_slice_get_drawres(int id, int *xres, int *yres, int *zres)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_slice_get_drawres");
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	*xres = gvl->slice_x_mod;
-	*yres = gvl->slice_y_mod;
-	*zres = gvl->slice_z_mod;
-    }
-
-    return;
-}
-
-/*!
-   \brief Set slice draw resolution
-
-   \param id volume set id
-   \param xres,yres,zres x/y/z resolution value
-
-   \return 0 on success
-   \return -1 on error (invalid value or id)
- */
-int GVL_slice_set_drawres(int id, int xres, int yres, int zres)
-{
-    geovol *gvl;
-    int i;
-
-    G_debug(3, "GVL_slice_set_drawres(): id=%d", id);
-
-    if (xres < 1 || yres < 1 || zres < 1) {
-	return (-1);
-    }
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	gvl->slice_x_mod = xres;
-	gvl->slice_y_mod = yres;
-	gvl->slice_z_mod = zres;
-
-	for (i = 0; i < gvl->n_slices; i++) {
-	    gvl->slice[i]->changed = 1;
-	}
-
-	return (0);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get slice draw mode
-
-   \param id volume set id
-   \param[out] mode draw mode
-
-   \return 1 on success
-   \return -1 on error (invalid id)
- */
-int GVL_slice_get_drawmode(int id, int *mode)
-{
-    geovol *gvl;
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	*mode = gvl->slice_draw_mode;
-
-	return (1);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Set slice draw mode
-
-   \param id volume set id
-   \param mode draw mode
-
-   \return 0 on success
-   \return -1 on error (invalid id)
- */
-int GVL_slice_set_drawmode(int id, int mode)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_slice_set_drawmode(): id=%d, mode=%d", id, mode);
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	gvl->slice_draw_mode = mode;
-
-	return (0);
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Add slice
-
-   \param id volume set id
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_slice_add(int id)
-{
-    geovol *gvl;
-    geovol_slice *slice;
-
-    G_debug(3, "GVL_slice_add");
-
-    gvl = gvl_get_vol(id);
-
-    if (!gvl)
-	return (-1);
-
-    if (gvl->n_slices == MAX_SLICES)
-	return (-1);
-
-    if (NULL == (slice = (geovol_slice *) G_malloc(sizeof(geovol_slice)))) {
-	return (-1);
-    }
-
-    gvl_slice_init(slice);
-
-    gvl->n_slices++;
-    gvl->slice[gvl->n_slices - 1] = (geovol_slice *) slice;
-
-    return (1);
-}
-
-/*!
-   \brief Delete slice
-
-   \param id volume set id
-   \param slice_id slice id
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_slice_del(int id, int slice_id)
-{
-    geovol *gvl;
-    geovol_slice *slice;
-    int i;
-
-    G_debug(3, "GVL_slice_del");
-
-    slice = gvl_slice_get_slice(id, slice_id);
-
-    if (!slice)
-	return (-1);
-
-    if (!gvl_slice_freemem(slice)) {
-	return (-1);
-    }
-
-    gvl = gvl_get_vol(id);
-
-    G_free(gvl->slice[slice_id]);
-
-    for (i = slice_id + 1; i < gvl->n_slices; i++) {
-	gvl->slice[i - 1] = gvl->slice[i];
-    }
-
-    gvl->n_slices--;
-
-    return (1);
-}
-
-/*!
-   \brief Move up slice
-
-   \param id volume set id
-   \param slice_id slice id
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_slice_move_up(int id, int slice_id)
-{
-    geovol *gvl;
-    geovol_slice *tmp;
-
-    G_debug(3, "GVL_slice_move_up");
-
-    gvl = gvl_get_vol(id);
-
-    if (!gvl)
-	return (-1);
-
-    if (slice_id < 0 || slice_id > (gvl->n_slices - 1))
-	return (-1);
-
-    if (slice_id == 0)
-	return (1);
-
-    tmp = gvl->slice[slice_id - 1];
-    gvl->slice[slice_id - 1] = gvl->slice[slice_id];
-    gvl->slice[slice_id] = tmp;
-
-    return (1);
-}
-
-/*!
-   \brief Move down slice
-
-   \param id volume set id
-   \param slice_id slice id
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_slice_move_down(int id, int slice_id)
-{
-    geovol *gvl;
-    geovol_slice *tmp;
-
-    G_debug(3, "GVL_slice_move_up");
-
-    gvl = gvl_get_vol(id);
-
-    if (!gvl)
-	return (-1);
-
-    if (slice_id < 0 || slice_id > (gvl->n_slices - 1))
-	return (-1);
-
-    if (slice_id == (gvl->n_slices - 1))
-	return (1);
-
-    tmp = gvl->slice[slice_id + 1];
-    gvl->slice[slice_id + 1] = gvl->slice[slice_id];
-    gvl->slice[slice_id] = tmp;
-
-    return (1);
-}
-
-/*!
-   \brief Get number or slices
-
-   \param id volume set id
-
-   \return number of slices
-   \return -1 on error
- */
-int GVL_slice_num_slices(int id)
-{
-    geovol *gvl;
-
-    G_debug(3, "GVL_isosurf_num_isosurfs");
-
-    gvl = gvl_get_vol(id);
-
-    if (gvl) {
-	return gvl->n_slices;
-    }
-
-    return (-1);
-}
-
-/*!
-   \brief Get slice position
-
-   \param id volume set id
-   \param slice_id slice id
-   \param[out] x1,y1,z1 coordinates ?
-   \param[out] x2,y2,z2 coordinates ?
-   \param[out] dir direction
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_slice_get_pos(int id, int slice_id,
-		      float *x1, float *x2, float *y1, float *y2, float *z1,
-		      float *z2, int *dir)
-{
-    geovol *gvl;
-    geovol_slice *slice;
-    int cols, rows, depths;
-
-    gvl = gvl_get_vol(id);
-
-    if (!gvl)
-	return (-1);
-
-    slice = gvl_slice_get_slice(id, slice_id);
-
-    if (!slice)
-	return (-1);
-
-    if (slice->dir == X) {
-	cols = gvl->rows;
-	rows = gvl->depths;
-	depths = gvl->cols;
-    }
-    else if (slice->dir == Y) {
-	cols = gvl->cols;
-	rows = gvl->depths;
-	depths = gvl->rows;
-    }
-    else if (slice->dir == Z) {
-	cols = gvl->cols;
-	rows = gvl->rows;
-	depths = gvl->depths;
-    }
-    else {
-	return (-1);
-    }
-
-    *x1 = slice->x1 / (cols - 1);
-    *x2 = slice->x2 / (cols - 1);
-    *y1 = slice->y1 / (rows - 1);
-    *y2 = slice->y2 / (rows - 1);
-    *z1 = slice->z1 / (depths - 1);
-    *z2 = slice->z2 / (depths - 1);
-
-    *dir = slice->dir;
-
-    return (1);
-}
-
-/*!
-   \brief Get slice position
-
-   \param id volume set id
-   \param slice_id slice id
-   \param x1,y1,z1 coordinates ?
-   \param x2,y2,z2 coordinates ?
-   \param dir direction
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_slice_set_pos(int id, int slice_id,
-		      float x1, float x2, float y1, float y2, float z1,
-		      float z2, int dir)
-{
-    geovol *gvl;
-    geovol_slice *slice;
-    int cols, rows, depths;
-
-    gvl = gvl_get_vol(id);
-
-    if (!gvl)
-	return (-1);
-
-    slice = gvl_slice_get_slice(id, slice_id);
-
-    if (!slice)
-	return (-1);
-
-    if (dir == X) {
-	cols = gvl->rows;
-	rows = gvl->depths;
-	depths = gvl->cols;
-    }
-    else if (dir == Y) {
-	cols = gvl->cols;
-	rows = gvl->depths;
-	depths = gvl->rows;
-    }
-    else if (dir == Z) {
-	cols = gvl->cols;
-	rows = gvl->rows;
-	depths = gvl->depths;
-    }
-    else {
-	return (-1);
-    }
-
-    slice->x1 = ((x1 < 0.) ? 0. : ((x1 > 1.) ? 1. : x1)) * (cols - 1);
-    slice->x2 = ((x2 < 0.) ? 0. : ((x2 > 1.) ? 1. : x2)) * (cols - 1);
-    slice->y1 = ((y1 < 0.) ? 0. : ((y1 > 1.) ? 1. : y1)) * (rows - 1);
-    slice->y2 = ((y2 < 0.) ? 0. : ((y2 > 1.) ? 1. : y2)) * (rows - 1);
-    slice->z1 = ((z1 < 0.) ? 0. : ((z1 > 1.) ? 1. : z1)) * (depths - 1);
-    slice->z2 = ((z2 < 0.) ? 0. : ((z2 > 1.) ? 1. : z2)) * (depths - 1);
-
-    slice->dir = dir;
-
-    slice->changed = 1;
-
-    return (1);
-}
-
-/*!
-   \brief Get slice trans ?
-
-   \param id volume set id
-   \param slice_id slice id
-   \param[out] transp transp value
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_slice_get_transp(int id, int slice_id, int *transp)
-{
-    geovol_slice *slice;
-
-    G_debug(3, "GVL_get_transp");
-
-    slice = gvl_slice_get_slice(id, slice_id);
-
-    if (!slice)
-	return (-1);
-
-    *transp = slice->transp;
-
-    return (1);
-}
-
-/*!
-   \brief Set slice trans ?
-
-   \param id volume set id
-   \param slice_id slice id
-   \param transp transp value
-
-   \return -1 on error
-   \return 1 on success
- */
-int GVL_slice_set_transp(int id, int slice_id, int transp)
-{
-    geovol_slice *slice;
-
-    G_debug(3, "GVL_set_transp");
-
-    slice = gvl_slice_get_slice(id, slice_id);
-
-    if (!slice)
-	return (-1);
-
-    slice->transp = transp;
-
-    return (1);
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/Gp3.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/Gp3.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/Gp3.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,292 +0,0 @@
-/*!
-   \file lib/ogsf/Gp3.c
-
-   \brief OGSF library - loading point sets (lower level functions)
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   (C) 1999-2008, 2011 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.
-
-   \author Bill Brown USACERL, GMSL/University of Illinois (January 1994)
-   \author Updated by Martin Landa <landa.martin gmail.com>
-   (doxygenized in May 2008, thematic mapping in June 2011)
- */
-
-#include <stdlib.h>
-
-#include <grass/gis.h>
-#include <grass/colors.h>
-#include <grass/raster.h>
-#include <grass/vector.h>
-#include <grass/dbmi.h>
-#include <grass/glocale.h>
-#include <grass/ogsf.h>
-
-/*!
-   \brief Load to points to memory
-
-   The other alternative may be to load to a tmp file.
-
-   \param name name of vector map to be loaded
-   \param[out] nsites number of loaded points
-   \param[out] has_z 2D or 3D points data loaded?
-
-   \return pointer to geopoint struct (array)
-   \return NULL on failure
- */
-geopoint *Gp_load_sites(const char *name, int *nsites, int *has_z)
-{
-    struct Map_info map;
-    static struct line_pnts *Points = NULL;
-    struct line_cats *Cats = NULL;
-    geopoint *top, *gpt, *prev;
-    int np, ltype, eof;
-    struct Cell_head wind;
-    int ndim;
-    const char *mapset;
-
-    np = 0;
-    eof = 0;
-    
-    mapset = G_find_vector2(name, "");
-    if (!mapset) {
-	G_warning(_("Vector map <%s> not found"), name);
-	return NULL;
-    }
-    
-    Vect_set_open_level(1);
-    if (Vect_open_old(&map, name, "") == -1) {
-	G_fatal_error(_("Unable to open vector map <%s>"),
-		      G_fully_qualified_name(name, mapset));
-    }
-    
-    Points = Vect_new_line_struct();
-    Cats = Vect_new_cats_struct();
-    
-    top = gpt = (geopoint *) G_malloc(sizeof(geopoint));
-    G_zero(gpt, sizeof(geopoint));
-    if (!top) {
-	return NULL;
-    }
-
-    G_get_set_window(&wind);
-    Vect_set_constraint_region(&map, wind.north, wind.south, wind.east,
-			       wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
-
-    /* get ndim */
-    *has_z = 0;
-    ndim = 2;
-    if (Vect_is_3d(&map)) {
-	*has_z = 1;
-	ndim = 3;
-    }
-
-    while (eof == 0) {
-	ltype = Vect_read_next_line(&map, Points, Cats);
-	switch (ltype) {
-	case -1:
-	    {
-		G_warning(_("Unable to read vector map <%s>"),
-			  G_fully_qualified_name(name, mapset));
-		return NULL;
-	    }
-	case -2:		/* EOF */
-	    {
-		eof = 1;
-		continue;
-	    }
-	}
-	if ((ltype & GV_POINTS)) {
-	    np++;
-	    gpt->p3[X] = Points->x[0];
-	    gpt->p3[Y] = Points->y[0];
-
-	    if (ndim > 2) {
-		gpt->dims = 3;
-		gpt->p3[Z] = Points->z[0];
-	    }
-	    else {
-		gpt->dims = 2;
-	    }
-
-	    /* Store category info for thematic display */
-	    if (Cats->n_cats > 0) {
-		gpt->cats = Cats;
-		Cats = Vect_new_cats_struct();
-	    }
-	    else {
-		Vect_reset_cats(Cats);
-	    }
-	    /* initialize style */
-	    gpt->highlighted = 0;
-	    
-	    G_debug(5, "loading vector point %d x=%f y=%f ncats=%d",
-		    np, Points->x[0], Points->y[0], Cats->n_cats);
-
-	    gpt->next = (geopoint *) G_malloc(sizeof(geopoint));	/* G_fatal_error */
-	    G_zero(gpt->next, sizeof(geopoint));
-	    if (!gpt->next) {
-		return NULL;
-	    }
-
-	    prev = gpt;
-	    gpt = gpt->next;
-	}
-
-    }
-    if (np > 0) {
-	prev->next = NULL;
-	G_free(gpt);
-    }
-
-    Vect_close(&map);
-
-    if (!np) {
-	G_warning(_("No points from vector map <%s> fall within current region"),
-		  G_fully_qualified_name(name, mapset));
-	return (NULL);
-    }
-    else {
-	G_message(_("Vector map <%s> loaded (%d points)"),
-		  G_fully_qualified_name(name, mapset), np);
-    }
-
-    *nsites = np;
-
-    return top;
-}
-
-/*!
-  \brief Load styles for geopoints based on thematic mapping
-
-  \param gp pointer to geosite structure
-  \param colors pointer to Colors structure or NULL
-  
-  \return number of points defined by thematic mapping
-  \return -1 on error
-*/
-int Gp_load_sites_thematic(geosite *gp, struct Colors *colors)
-{
-    geopoint *gpt;
-
-    struct Map_info Map;
-    struct field_info *Fi;
-    
-    int nvals, cat, npts, nskipped;
-    int red, blu, grn;
-    const char *str;
-    const char *mapset;
-
-    dbDriver *driver;
-    dbValue value;
-    
-    if(!gp || !gp->tstyle || !gp->filename)
-	return -1;
-
-    mapset = G_find_vector2(gp->filename, "");
-    if (!mapset) {
-	G_fatal_error(_("Vector map <%s> not found"), gp->filename);
-    }
-    
-    Vect_set_open_level(1);
-    if (Vect_open_old(&Map, gp->filename, "") == -1) {
-	G_fatal_error(_("Unable to open vector map <%s>"),
-		      G_fully_qualified_name(gp->filename, mapset));
-    }
-    
-    Fi = Vect_get_field(&Map, gp->tstyle->layer);
-    if (!Fi) {
-	G_warning(_("Database connection not defined for layer %d"),
-		  gp->tstyle->layer);
-    }
-    else {
-	driver = db_start_driver_open_database(Fi->driver, Fi->database);
-	if (!driver)
-	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
-			  Fi->database, Fi->driver);
-    }
-    G_message(_("Loading thematic points layer <%s>..."),
-	      G_fully_qualified_name(gp->filename, mapset));
-    npts = nskipped = 0;
-    for(gpt = gp->points; gpt; gpt = gpt->next) {
-	gpt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
-	G_zero(gpt->style, sizeof(gvstyle));
-	
-	/* use default style */
-	gpt->style->color  = gp->style->color;
-	gpt->style->symbol = gp->style->symbol;
-	gpt->style->size   = gp->style->size;
-	gpt->style->width  = gp->style->width;
-	
-	cat = -1;
-	if (gpt->cats)
-	    Vect_cat_get(gpt->cats, gp->tstyle->layer, &cat);
-	if (cat < 0) {
-	    nskipped++;
-	    continue;
-	}
-
-	/* color */
-	if (colors) {
-	    if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
-		G_warning(_("No color rule defined for category %d"), cat);
-		gpt->style->color = gp->style->color;
-	    }
-	    gpt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
-		((int)((blu) << 16) & BLU_MASK);
-	}
-	if (gp->tstyle->color_column) {
-	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->color_column, &value);
-	    if (nvals < 1)
-		continue;
-	    str = db_get_value_string(&value);
-	    if (!str)
-		continue;
-	    if (G_str_to_color(str, &red, &grn, &blu) != 1) {
-		G_warning(_("Invalid color definition (%s)"),
-			  str);
-		gpt->style->color = gp->style->color;
-	    }
-	    else {
-		gpt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
-		    ((int)((blu) << 16) & BLU_MASK);
-	    }
-	}
-	
-	/* size */
-	if (gp->tstyle->size_column) {
-	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->size_column, &value);
-	    if (nvals < 1)
-		continue;
-	    gpt->style->size = db_get_value_int(&value);
-	}
-
-	/* width */
-	if (gp->tstyle->width_column) {
-	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->width_column, &value);
-	    if (nvals < 1)
-		continue;
-	    gpt->style->width = db_get_value_int(&value);
-	}
-
-	/* symbol/marker */
-	if (gp->tstyle->symbol_column) {
-	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->symbol_column, &value);
-	    if (nvals < 1)
-		continue;
-	    str = db_get_value_string(&value);
-	    gpt->style->symbol = GP_str_to_marker(str);
-	}
-	
-	npts++;
-    }
-    
-    if (nskipped > 0)
-	G_warning(_("%d points without category. "
-		    "Unable to determine color rules for features without category."),
-		  nskipped);
-    return npts;
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/Gs3.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/Gs3.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/Gs3.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,1198 +0,0 @@
-/*!
-   \file Gs3.c
-
-   \brief OGSF library - loading surfaces (lower level functions)
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   (C) 1999-2008 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.
-
-   \author Bill Brown USACERL, GMSL/University of Illinois (January 1993)
-   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grass/gis.h>
-#include <grass/raster.h>
-#include <grass/glocale.h>
-#include <grass/bitmap.h>
-
-#include <grass/ogsf.h>
-/* for geoview & geodisplay in 3dview stuff */
-#include "gsget.h"
-/* for update_attrange - might be able to move this func now */
-
-/*!
-   \brief Used in the function Gs_update_attrange()
- */
-#define INIT_MINMAX(p, nm, size, min, max, found) \
-	found = 0; \
-	p+=(size-1); \
-	while (size--) \
-	{ \
-	    if (!BM_GET_BYOFFSET(nm, size)) \
-	    { \
-		min = max = *p; \
-		found = 1; \
-		break; \
-	    } \
-	    p--; \
-	}
-
-/*!
-   \brief Used in the function Gs_update_attrange()
- */
-#define SET_MINMAX(p, nm, size, min, max) \
-	p+=(size-1); \
-	while(size--) \
-	{ \
-	    if (!BM_GET_BYOFFSET(nm, size)) \
-	    { \
-		if (*p < min) \
-		{ \
-		    min = *p; \
-		} \
-		else if (*p > max) \
-		{ \
-		    max = *p; \
-		}  \
-	    } \
-	    p--; \
-	}
-
-typedef int FILEDESC;
-
-#define NO_DATA_COL 0xffffff
-
-/*!
-   \brief Calculates distance in METERS between two points in current projection (2D)
-
-   Uses G_distance().
-
-   \param from 'from' point (X, Y)
-   \param to 'to' point (X, Y)
-
-   \return distance
- */
-double Gs_distance(double *from, double *to)
-{
-    static int first = 1;
-
-    if (first) {
-	first = 0;
-	G_begin_distance_calculations();
-    }
-
-    return G_distance(from[0], from[1], to[0], to[1]);
-}
-
-/*!
-   \brief Load raster map as floating point map
-
-   Calling function must have already allocated space in buff for
-   wind->rows * wind->cols floats.
-
-   This routine simply loads the map into a 2d array by repetitve calls
-   to get_f_raster_row.
-
-   \param wind current window
-   \param map_name raster map name
-   \param[out] buff data buffer
-   \param[out] nullmap null map buffer
-   \param[out] has_null indicates if raster map contains null-data
-
-   \return 1 on success
-   \return 0 on failure
- */
-int Gs_loadmap_as_float(struct Cell_head *wind, const char *map_name,
-			float *buff, struct BM *nullmap, int *has_null)
-{
-    FILEDESC cellfile;
-    const char *map_set;
-    int offset, row, col;
-
-    G_debug(3, "Gs_loadmap_as_float(): name=%s", map_name);
-
-    map_set = G_find_raster2(map_name, "");
-    if (!map_set) {
-	G_warning(_("Raster map <%s> not found"), map_name);
-	return 0;
-    }
-    *has_null = 0;
-
-    cellfile = Rast_open_old(map_name, map_set);
-
-    G_message(_("Loading raster map <%s>..."),
-	      G_fully_qualified_name(map_name, map_set));
-
-    for (row = 0; row < wind->rows; row++) {
-	offset = row * wind->cols;
-	Rast_get_f_row(cellfile, &(buff[offset]), row);
-
-	G_percent(row, wind->rows, 2);
-
-	for (col = 0; col < wind->cols; col++) {
-	    if (Rast_is_f_null_value(buff + offset + col)) {
-		*has_null = 1;
-		BM_set(nullmap, col, row, 1);
-	    }
-	    /* set nm */
-	}
-    }
-    G_percent(1, 1, 1);
-
-    G_debug(4, "  has_null=%d", *has_null);
-
-    Rast_close(cellfile);
-
-    return (1);
-}
-
-/*!
-   \brief Load raster map as integer map
-
-   Calling function must have already allocated space in buff for
-   wind->rows * wind->cols floats.
-
-   This routine simply loads the map into a 2d array by repetitve calls
-   to get_f_raster_row.
-
-   \todo fn body of Gs_loadmap_as_float()
-
-   \param wind current window
-   \param map_name raster map name
-   \param[out] buff data buffer
-   \param[out] nullmap null map buffer
-   \param[out] has_null indicates if raster map contains null-data
-
-   \return 1 on success
-   \return 0 on failure
- */
-int Gs_loadmap_as_int(struct Cell_head *wind, const char *map_name, int *buff,
-		      struct BM *nullmap, int *has_null)
-{
-    FILEDESC cellfile;
-    const char *map_set;
-    int offset, row, col;
-
-    G_debug(3, "Gs_loadmap_as_int");
-
-    map_set = G_find_raster2(map_name, "");
-    if (!map_set) {
-	G_warning(_("Raster map <%s> not found"), map_name);
-	return 0;
-    }
-    *has_null = 0;
-
-    cellfile = Rast_open_old(map_name, map_set);
-
-    G_message(_("Loading raster map <%s>..."),
-	      G_fully_qualified_name(map_name, map_set));
-
-    for (row = 0; row < wind->rows; row++) {
-	offset = row * wind->cols;
-	Rast_get_c_row(cellfile, &(buff[offset]), row);
-
-	G_percent(row, wind->rows, 2);
-
-	for (col = 0; col < wind->cols; col++) {
-	    if (Rast_is_f_null_value(buff + offset + col)) {
-		*has_null = 1;
-		BM_set(nullmap, col, row, 1);
-	    }
-
-	    /* set nm */
-	}
-    }
-    G_percent(1, 1, 1);
-    
-    Rast_close(cellfile);
-
-    return (1);
-}
-
-/*!
-   \brief Get map data type
-
-   \param filename raster map name
-   \param negflag
-
-   \return -1 if map is integer and Rast_read_range() fails
-   \return data type (ARRY_*)
- */
-int Gs_numtype(const char *filename, int *negflag)
-{
-    CELL max = 0, min = 0;
-    struct Range range;
-    const char *mapset;
-    int shortbits, charbits, bitplace;
-    static int max_short, max_char;
-    static int first = 1;
-
-    if (first) {
-	max_short = max_char = 1;
-	shortbits = 8 * sizeof(short);
-
-	for (bitplace = 1; bitplace < shortbits; ++bitplace) {
-	    /*1 bit for sign */
-	    max_short *= 2;
-	}
-
-	max_short -= 1;
-
-	/* NO bits for sign, using unsigned char */
-	charbits = 8 * sizeof(unsigned char);
-
-	for (bitplace = 0; bitplace < charbits; ++bitplace) {
-	    max_char *= 2;
-	}
-
-	max_char -= 1;
-
-	first = 0;
-    }
-
-    mapset = G_find_raster2(filename, "");
-    if (!mapset) {
-	G_warning(_("Raster map <%s> not found"), filename);
-	return -1;
-    }
-
-    if (Rast_map_is_fp(filename, mapset)) {
-	G_debug(3, "Gs_numtype(): fp map detected");
-
-	return (ATTY_FLOAT);
-    }
-
-    if (-1 == Rast_read_range(filename, mapset, &range)) {
-	return (-1);
-    }
-
-    Rast_get_range_min_max(&range, &min, &max);
-    *negflag = (min < 0);
-
-    if (max < max_char && min > 0) {
-	return (ATTY_CHAR);
-    }
-
-    if (max < max_short && min > -max_short) {
-	return (ATTY_SHORT);
-    }
-
-    return (ATTY_INT);
-}
-
-/*!
-   \brief Load raster map as integer map
-
-   Calling function must have already allocated space in buff for
-   wind->rows * wind->cols shorts.  
-
-   This routine simply loads the map into a 2d array by repetitve calls
-   to get_map_row.
-
-   \param wind current window
-   \param map_name raster map name
-   \param[out] buff data buffer
-   \param[out] nullmap null map buffer
-   \param[out] has_null indicates if raster map contains null-data
-
-   \return 1 on success
-   \return -1 on failure,
-   \return -2 if read ok, but 1 or more values were too large (small)
-   to fit into a short (in which case the max (min) short is used)
- */
-int Gs_loadmap_as_short(struct Cell_head *wind, const char *map_name,
-			short *buff, struct BM *nullmap, int *has_null)
-{
-    FILEDESC cellfile;
-    const char *map_set;
-    int *ti, *tmp_buf;
-    int offset, row, col, val, max_short, overflow, shortsize, bitplace;
-    short *ts;
-
-    G_debug(3, "Gs_loadmap_as_short");
-
-    overflow = 0;
-    shortsize = 8 * sizeof(short);
-
-    /* 1 bit for sign */
-    /* same as 2 << (shortsize-1) */
-    for (max_short = bitplace = 1; bitplace < shortsize; ++bitplace) {
-	max_short *= 2;
-    }
-
-    max_short -= 1;
-
-    map_set = G_find_raster2(map_name, "");
-    if (!map_set) {
-	G_warning(_("Raster map <%s> not found"), map_name);
-	return -1;
-    }
-    *has_null = 0;
-
-    cellfile = Rast_open_old(map_name, map_set);
-
-    tmp_buf = (int *)G_malloc(wind->cols * sizeof(int));	/* G_fatal_error */
-    if (!tmp_buf) {
-	return -1;
-    }
-
-    G_message(_("Loading raster map <%s>..."),
-	      G_fully_qualified_name(map_name, map_set));
-
-    for (row = 0; row < wind->rows; row++) {
-	offset = row * wind->cols;
-	Rast_get_c_row(cellfile, tmp_buf, row);
-
-	G_percent(row, wind->rows, 2);
-
-	ts = &(buff[offset]);
-	ti = tmp_buf;
-
-	for (col = 0; col < wind->cols; col++) {
-	    if (Rast_is_c_null_value(&tmp_buf[col])) {
-		*has_null = 1;
-		BM_set(nullmap, col, row, 1);
-	    }
-	    else {
-		val = *ti;
-		if (abs(val) > max_short) {
-		    overflow = 1;
-		    /* assign floor/ceiling value?
-		     */
-		    *ts = (short)(max_short * val / abs(val));
-		}
-		else {
-		    *ts = (short)val;
-		}
-	    }
-
-	    ti++;
-	    ts++;
-	}
-    }
-    G_percent(1, 1, 1);
-    
-    Rast_close(cellfile);
-
-    G_free(tmp_buf);
-
-    return (overflow ? -2 : 1);
-}
-
-/*!
-   \brief Load raster map as integer map
-
-   Calling function must have already allocated space in buff for
-   wind->rows * wind->cols unsigned chars.  
-
-   This routine simply loads the map into a 2d array by repetitve calls
-   to get_map_row.
-
-   Since signs of chars can be tricky, we only load positive chars
-   between 0-255.
-
-   \todo fn body Gs_loadmap_as_float()
-
-   \param wind current window
-   \param map_name raster map name
-   \param[out] buff data buffer
-   \param[out] nullmap null map buffer
-   \param[out] has_null indicates if raster map contains null-data
-
-   \return 1 on success
-   \return -1 on failure
-   \return -2 if read ok, but 1 or more values
-   were too large (small) to fit into an unsigned char.
-   (in which case the max (min) char is used)
- */
-int Gs_loadmap_as_char(struct Cell_head *wind, const char *map_name,
-		       unsigned char *buff, struct BM *nullmap, int *has_null)
-{
-    FILEDESC cellfile;
-    const char *map_set;
-    int *ti, *tmp_buf;
-    int offset, row, col, val, max_char, overflow, charsize, bitplace;
-    unsigned char *tc;
-
-    G_debug(3, "Gs_loadmap_as_char");
-
-    overflow = 0;
-    charsize = 8 * sizeof(unsigned char);
-
-    /* 0 bits for sign! */
-    max_char = 1;
-
-    for (bitplace = 0; bitplace < charsize; ++bitplace) {
-	max_char *= 2;
-    }
-
-    max_char -= 1;
-
-    map_set = G_find_raster2(map_name, "");
-    if (!map_set) {
-	G_warning(_("Raster map <%s> not found"), map_name);
-	return -1;
-    }
-    *has_null = 0;
-
-    cellfile = Rast_open_old(map_name, map_set);
-
-    tmp_buf = (int *)G_malloc(wind->cols * sizeof(int));	/* G_fatal_error */
-    if (!tmp_buf) {
-	return -1;
-    }
-
-    G_message(_("Loading raster map <%s>..."),
-	      G_fully_qualified_name(map_name, map_set));
-
-    for (row = 0; row < wind->rows; row++) {
-	offset = row * wind->cols;
-	Rast_get_c_row(cellfile, tmp_buf, row);
-	tc = (unsigned char *)&(buff[offset]);
-	ti = tmp_buf;
-
-	G_percent(row, wind->rows, 2);
-
-	for (col = 0; col < wind->cols; col++) {
-	    if (Rast_is_c_null_value(&tmp_buf[col])) {
-		*has_null = 1;
-		BM_set(nullmap, col, row, 1);
-	    }
-	    else {
-		val = *ti;
-		if (val > max_char) {
-		    overflow = 1;
-		    *tc = (unsigned char)max_char;
-		}
-		else if (val < 0) {
-		    overflow = 1;
-		    *tc = 0;
-		}
-		else {
-		    *tc = (unsigned char)val;
-		}
-	    }
-
-	    ti++;
-	    tc++;
-	}
-    }
-    G_percent(1, 1, 1);
-    
-    Rast_close(cellfile);
-
-    G_free(tmp_buf);
-
-    return (overflow ? -2 : 1);
-}
-
-/*!
-   \brief Load raster map as integer map
-
-   Calling function must have already allocated space in buff for
-   struct BM of wind->rows & wind->cols.
-
-   This routine simply loads the map into the bitmap by repetitve calls
-   to get_map_row.  Any value other than 0 in the map will set the bitmap.
-   (may want to change later to allow specific value to set)
-
-   Changed to use null.
-
-   \param wind current window
-   \param map_name raster map name
-   \param[out] buff data buffer
-
-   \returns 1 on success
-   \return -1 on failure
- */
-int Gs_loadmap_as_bitmap(struct Cell_head *wind, const char *map_name,
-			 struct BM *buff)
-{
-    FILEDESC cellfile;
-    const char *map_set;
-    int *tmp_buf;
-    int row, col;
-
-    G_debug(3, "Gs_loadmap_as_bitmap");
-
-    map_set = G_find_raster2(map_name, "");
-    if (!map_set) {
-	G_warning(_("Raster map <%s> not found"), map_name);
-	return -1;
-    }
-
-    cellfile = Rast_open_old(map_name, map_set);
-
-    tmp_buf = (int *)G_malloc(wind->cols * sizeof(int));	/* G_fatal_error */
-    if (!tmp_buf) {
-	return -1;
-    }
-
-    G_message(_("Loading raster map <%s>..."),
-	      G_fully_qualified_name(map_name, map_set));
-
-    for (row = 0; row < wind->rows; row++) {
-	Rast_get_c_row(cellfile, tmp_buf, row);
-
-	for (col = 0; col < wind->cols; col++) {
-	    if (Rast_is_c_null_value(&tmp_buf[col])) {
-		/* no data */
-		BM_set(buff, col, row, 1);
-	    }
-	    else {
-		BM_set(buff, col, row, 0);
-	    }
-	}
-    }
-
-    Rast_close(cellfile);
-
-    G_free(tmp_buf);
-
-    return (1);
-}
-
-/*!
-   \brief Build color table (256)
-
-   Calling function must have already allocated space in buff for range of
-   data (256 for now) - simply calls get_color for each cat in color range
-
-   \param filename raster map name
-   \param[out] buff data buffer
-
-   \return 1 on success
-   \return 0 on failure
- */
-int Gs_build_256lookup(const char *filename, int *buff)
-{
-    const char *mapset;
-    struct Colors colrules;
-    CELL min, max, cats[256];
-    int i;
-    unsigned char r[256], g[256], b[256], set[256];
-
-    G_debug(3, "building color table");
-
-    mapset = G_find_raster2(filename, "");
-    if (!mapset) {
-	G_warning(_("Raster map <%s> not found"), filename);
-	return 0;
-    }
-
-    Rast_read_colors(filename, mapset, &colrules);
-    Rast_get_c_color_range(&min, &max, &colrules);
-
-    if (min < 0 || max > 255) {
-	G_warning(_("Color table range doesn't match data (mincol=%d, maxcol=%d"),
-		  min, max);
-
-	min = min < 0 ? 0 : min;
-	max = max > 255 ? 255 : max;
-    }
-
-    G_zero(cats, 256 * sizeof(CELL));
-
-    for (i = min; i <= max; i++) {
-	cats[i] = i;
-    }
-
-    Rast_lookup_c_colors(cats, r, g, b, set, 256, &colrules);
-
-    for (i = 0; i < 256; i++) {
-
-	if (set[i]) {
-	    buff[i] =
-		(r[i] & 0xff) | ((g[i] & 0xff) << 8) | ((b[i] & 0xff) << 16);
-	}
-	else {
-	    buff[i] = NO_DATA_COL;
-	}
-    }
-
-    return (1);
-}
-
-/*!
-   \brief Pack color table
-
-   Passed an array of 32 bit ints that is converted from cell values
-   to packed colors (0xbbggrr) 
-
-   \param filename raster map name
-   \param buff
-   \param rows number of rows
-   \param cols number of cols
- */
-void Gs_pack_colors(const char *filename, int *buff, int rows, int cols)
-{
-    const char *mapset;
-    struct Colors colrules;
-    unsigned char *r, *g, *b, *set;
-    int *cur, i, j;
-
-    mapset = G_find_raster2(filename, "");
-    if (!mapset) {
-	G_warning(_("Raster map <%s> not found"), filename);
-	return;
-    }
-
-    r = (unsigned char *)G_malloc(cols);
-    g = (unsigned char *)G_malloc(cols);
-    b = (unsigned char *)G_malloc(cols);
-    set = (unsigned char *)G_malloc(cols);
-
-    Rast_read_colors(filename, mapset, &colrules);
-
-    cur = buff;
-
-    G_message(_("Translating colors from raster map <%s>..."),
-	      G_fully_qualified_name(filename, mapset));
-
-    for (i = 0; i < rows; i++) {
-	Rast_lookup_c_colors(cur, r, g, b, set, cols, &colrules);
-	G_percent(i, rows, 2);
-
-	for (j = 0; j < cols; j++) {
-	    if (set[j]) {
-		cur[j] =
-		    (r[j] & 0xff) | ((g[j] & 0xff) << 8) | ((b[j] & 0xff) <<
-							    16);
-	    }
-	    else {
-		cur[j] = NO_DATA_COL;
-	    }
-	}
-
-	cur = &(cur[cols]);
-    }
-    G_percent(1, 1, 1);
-    
-    Rast_free_colors(&colrules);
-
-    G_free(r);
-    G_free(g);
-    G_free(b);
-
-    G_free(set);
-
-    return;
-}
-
-/*!
-   \brief Pack color table (floating-point map)
-
-   Passed a array of floats that will be converted from cell values
-   to packed colors (0xbbggrr) and float to int 
-   Floating point data not freed here, use: 
-   gsds_free_data_buff(id, ATTY_FLOAT)
-
-   \param filename raster map name
-   \param fbuf
-   \param ibuf
-   \param rows number of rows
-   \param cols number of cols
- */
-void Gs_pack_colors_float(const char *filename, float *fbuf, int *ibuf,
-			  int rows, int cols)
-{
-    const char *mapset;
-    struct Colors colrules;
-    unsigned char *r, *g, *b, *set;
-    int i, j, *icur;
-    FCELL *fcur;
-
-    mapset = G_find_raster2(filename, "");
-    if (!mapset) {
-	G_warning(_("Raster map <%s> not found"), filename);
-	return;
-    }
-
-    r = (unsigned char *)G_malloc(cols);
-    g = (unsigned char *)G_malloc(cols);
-    b = (unsigned char *)G_malloc(cols);
-    set = (unsigned char *)G_malloc(cols);
-
-    Rast_read_colors(filename, mapset, &colrules);
-
-    fcur = fbuf;
-    icur = ibuf;
-
-    G_message(_("Translating colors from raster map <%s>..."),
-	      G_fully_qualified_name(filename, mapset));
-    
-    for (i = 0; i < rows; i++) {
-	Rast_lookup_f_colors(fcur, r, g, b, set, cols, &colrules);
-	G_percent(i, rows, 2);
-
-	for (j = 0; j < cols; j++) {
-	    if (set[j]) {
-		icur[j] =
-		    (r[j] & 0xff) | ((g[j] & 0xff) << 8) | ((b[j] & 0xff) <<
-							    16);
-	    }
-	    else {
-		icur[j] = NO_DATA_COL;
-	    }
-	}
-
-	icur = &(icur[cols]);
-	fcur = &(fcur[cols]);
-    }
-    G_percent(1, 1, 1);
-    
-    Rast_free_colors(&colrules);
-
-    G_free(r);
-    G_free(g);
-    G_free(b);
-    G_free(set);
-
-    return;
-}
-
-/*!
-   \brief Get categories/labels
-
-   Formats label as in d.what.rast -> (catval) catlabel 
-
-   \param filename raster map name
-   \param drow
-   \param dcol
-   \param catstr category string
-
-   \return 1 on success
-   \return 0 on failure
- */
-int Gs_get_cat_label(const char *filename, int drow, int dcol, char *catstr)
-{
-    struct Categories cats;
-    const char *mapset;
-    CELL *buf;
-    DCELL *dbuf;
-    RASTER_MAP_TYPE map_type;
-    int fd = -1;
-
-    if ((mapset = G_find_raster2(filename, "")) == NULL) {
-	G_warning(_("Raster map <%s> not found"), filename);
-	return 0;
-    }
-
-    if (-1 != Rast_read_cats(filename, mapset, &cats)) {
-	fd = Rast_open_old(filename, mapset);
-	map_type = Rast_get_map_type(fd);
-
-	if (map_type == CELL_TYPE) {
-	    buf = Rast_allocate_c_buf();
-
-	    Rast_get_c_row(fd, buf, drow);
-	    if (Rast_is_c_null_value(&buf[dcol])) {
-		sprintf(catstr, "(NULL) %s",
-			Rast_get_c_cat(&buf[dcol], &cats));
-	    }
-	    else {
-		sprintf(catstr, "(%d) %s", buf[dcol],
-			Rast_get_c_cat(&buf[dcol], &cats));
-	    }
-
-	    G_free(buf);
-	}
-
-	else {
-	    /* fp map */
-	    dbuf = Rast_allocate_d_buf();
-
-	    Rast_get_d_row(fd, dbuf, drow);
-	    if (Rast_is_d_null_value(&dbuf[dcol])) {
-		sprintf(catstr, "(NULL) %s",
-			Rast_get_d_cat(&dbuf[dcol], &cats));
-	    }
-	    else {
-		sprintf(catstr, "(%g) %s", dbuf[dcol],
-			Rast_get_d_cat(&dbuf[dcol], &cats));
-	    }
-
-	    G_free(dbuf);
-	}
-    }
-    else {
-	strcpy(catstr, "no category label");
-	return 0;
-    }
-
-    /* TODO: may want to keep these around for multiple queries */
-    Rast_free_cats(&cats);
-
-    if (fd >= 0)
-	Rast_close(fd);
-
-    return (1);
-}
-
-/*!
-   \brief Save 3dview
-
-   \param vname view name
-   \param gv pointer to geoview struct
-   \param gd pointer to geodisplay struct
-   \param w current window
-   \param defsurf default geosurf struct
-
-   \return -1 on error
-   \return ?
- */
-int Gs_save_3dview(const char *vname, geoview * gv, geodisplay * gd,
-		   struct Cell_head *w, geosurf * defsurf)
-{
-    const char *mapset;
-    struct G_3dview v;
-    float zmax, zmin;
-
-    GS_get_zrange(&zmin, &zmax, 0);
-
-    G_get_3dview_defaults(&v, w);
-    mapset = G_mapset();
-
-    if (mapset != NULL) {
-	if (defsurf) {
-	    if (defsurf->draw_mode & DM_WIRE_POLY) {
-		v.display_type = 3;
-	    }
-	    else if (defsurf->draw_mode & DM_WIRE ||
-		     defsurf->draw_mode & DM_COL_WIRE) {
-		v.display_type = 1;
-	    }
-	    else if (defsurf->draw_mode & DM_POLY) {
-		v.display_type = 2;
-	    }
-
-	    v.mesh_freq = defsurf->x_modw;	/* mesh resolution */
-	    v.poly_freq = defsurf->x_mod;	/* poly resolution */
-	    v.dozero = !(defsurf->nz_topo);
-	    v.colorgrid = (defsurf->draw_mode & DM_COL_WIRE) ? 1 : 0;
-	    v.shading = (defsurf->draw_mode & DM_GOURAUD) ? 1 : 0;
-	}
-
-	if (gv->infocus) {
-	    GS_v3eq(v.from_to[TO], gv->real_to);
-	    v.from_to[TO][Z] -= zmin;
-	    GS_v3mult(v.from_to[TO], gv->scale);
-	    v.from_to[TO][Z] *= gv->vert_exag;
-	}
-	else {
-	    GS_v3eq(v.from_to[TO], gv->from_to[TO]);
-	}
-
-	gsd_model2real(v.from_to[TO]);
-
-	GS_v3eq(v.from_to[FROM], gv->from_to[FROM]);
-	gsd_model2real(v.from_to[FROM]);
-
-	v.exag = gv->vert_exag;
-	v.fov = gv->fov / 10.;
-	v.twist = gv->twist;
-	v.fringe = 0;		/* not implemented here */
-
-	v.lightson = 1;		/* always true, curently */
-
-	if (gv->lights[0].position[W] == 1) {
-	    /* local */
-	    v.lightpos[X] = gv->lights[0].position[X];
-	    v.lightpos[Y] = gv->lights[0].position[Y];
-	    v.lightpos[Z] = gv->lights[0].position[Z];
-	    gsd_model2real(v.lightpos);
-	    v.lightpos[W] = 1.0;	/* local */
-	}
-	else {
-	    v.lightpos[X] = gv->lights[0].position[X];
-	    v.lightpos[Y] = gv->lights[0].position[Y];
-	    v.lightpos[Z] = gv->lights[0].position[Z];
-	    v.lightpos[W] = 0.0;	/* inf */
-	}
-
-	v.lightcol[0] = gv->lights[0].color[0];
-	v.lightcol[1] = gv->lights[0].color[1];
-	v.lightcol[2] = gv->lights[0].color[2];
-
-	v.ambient = (gv->lights[0].ambient[0] + gv->lights[0].ambient[1] +
-		     gv->lights[0].ambient[2]) / 3.;
-	v.shine = gv->lights[0].shine;
-
-	v.surfonly = 0;		/* N/A - now uses constant color */
-	strcpy((v.pgm_id), "Nvision-ALPHA!");
-
-	return (G_put_3dview(vname, mapset, &v, w));
-    }
-    else {
-	return (-1);
-    }
-}
-
-/*!
-   \brief Load 3dview
-
-   \param vname view name
-   \param gv pointer to geoview struct
-   \param gd pointer to geodisplay struct
-   \param w current window
-   \param defsurf default geosurf struct
-
-   \return 1
- */
-int Gs_load_3dview(const char *vname, geoview * gv, geodisplay * gd,
-		   struct Cell_head *w, geosurf * defsurf)
-{
-    const char *mapset;
-    struct G_3dview v;
-    int ret = -1;
-    float pt[3];
-
-    mapset = G_find_file2("3d.view", vname, "");
-
-    if (mapset != NULL) {
-	ret = G_get_3dview(vname, mapset, &v);
-    }
-
-    if (ret >= 0) {
-	if (strcmp((v.pgm_id), "Nvision-ALPHA!")) {
-	    G_warning(_("View not saved by this program,"
-			"there may be some inconsistancies"));
-	}
-
-	/* set poly and mesh resolutions */
-	v.mesh_freq = (int)(v.mesh_freq * v.vwin.ns_res / w->ns_res);
-	v.poly_freq = (int)(v.poly_freq * v.vwin.ns_res / w->ns_res);
-
-	/* Set To and FROM positions */
-	/* TO */
-	pt[0] = (v.from_to[TO][X] - w->west) - w->ew_res / 2.;
-	pt[1] = (v.from_to[TO][Y] - w->south) - w->ns_res / 2.;
-	pt[2] = v.from_to[TO][Z];
-	GS_set_focus(pt);
-
-	/* FROM */
-	pt[0] = (float)v.from_to[FROM][X];
-	pt[1] = (float)v.from_to[FROM][Y];
-	pt[2] = (float)v.from_to[FROM][Z];
-	GS_moveto_real(pt);
-
-	if (defsurf) {
-	    int dmode = 0;
-
-	    GS_setall_drawres(v.poly_freq, v.poly_freq,
-			      v.mesh_freq, v.mesh_freq);
-
-	    while (v.display_type >= 10) {
-		/* globe stuff not used */
-		v.display_type -= 10;
-	    }
-
-	    /* set drawing modes */
-	    if (v.colorgrid) {
-		dmode |= DM_COL_WIRE;
-	    }
-
-	    if (v.shading) {
-		dmode |= DM_GOURAUD;
-	    }
-
-	    switch (v.display_type) {
-	    case 1:
-		dmode |= DM_WIRE;
-
-		break;
-	    case 2:
-		dmode |= DM_POLY;
-
-		break;
-	    case 3:
-		dmode |= DM_WIRE_POLY;
-
-		break;
-	    }
-	    GS_setall_drawmode(dmode);
-
-	    /* should also set nozeros here */
-	}
-
-	/* set exaggeration */
-	if (v.exag)
-	    GS_set_global_exag(v.exag);
-
-	/* Set FOV */
-	if (v.fov) {
-	    GS_set_fov((int)
-		       (v.fov > 0 ? v.fov * 10. + 0.5 : v.fov * 10. - 0.5));
-	}
-	else {
-	    /* TODO: do ortho */
-	}
-
-	/* Set twist */
-	if (v.twist)
-	    GS_set_twist((int)(v.twist > 0 ? v.twist + 0.5 : v.twist - 0.5));
-
-
-	/* TODO:  OK to here - need to unravel/reverse lights stuff*** */
-
-	if (v.lightson) {
-	    /* Lights are on */
-
-	    /* Light Position */
-	    gv->lights[0].position[X] = v.lightpos[X];
-	    gv->lights[0].position[Y] = v.lightpos[Y];
-	    gv->lights[0].position[Z] = v.lightpos[Z];
-
-	    /* Light Color */
-	    gv->lights[0].color[0] = v.lightcol[0];
-	    gv->lights[0].color[1] = v.lightcol[1];
-	    gv->lights[0].color[2] = v.lightcol[2];
-
-	    /* Light Shininess */
-	    gv->lights[0].shine = v.shine;
-
-	    /* Light Ambient */
-	    gv->lights[0].ambient[0] = gv->lights[0].ambient[1] =
-		gv->lights[0].ambient[2] = v.ambient * 3.;
-
-
-	}			/* Done with lights */
-
-
-	GS_alldraw_wire();
-
-    }				/* Done with file */
-    return (1);
-
-}
-
-/*!
-   \brief Update no_zero ranges for attribute (actually no_null now)
-
-   \param gs pointer to geosurf struct
-   \param desc attribute id (descriptor)
-
-   \return -1 on error
-   \return 1 on success
- */
-int Gs_update_attrange(geosurf * gs, int desc)
-{
-    long size;
-    float min, max;
-    typbuff *tb;
-    struct BM *nm;
-    int found;
-
-    gs->att[desc].max_nz = gs->att[desc].min_nz = gs->att[desc].range_nz =
-	0.0;
-
-    if (CONST_ATT == gs_get_att_src(gs, desc)) {
-	gs->att[desc].max_nz = gs->att[desc].min_nz = gs->att[desc].constant;
-	min = max = gs->att[desc].constant;
-	gs->att[desc].range_nz = 0.0;
-    }
-    else if (CF_COLOR_PACKED & gsds_get_changed(gs->att[desc].hdata)) {
-	gs->att[desc].max_nz = 0xFFFFFF;
-	gs->att[desc].min_nz = 0x010101;
-	gs->att[desc].range_nz = 0xFFFFFF;
-    }
-    else {
-	if (NULL == (tb = gsds_get_typbuff(gs->att[desc].hdata, 0))) {
-	    return (-1);
-	}
-
-	nm = tb->nm;
-
-	if (tb->ib) {
-	    int *p;
-
-	    size = gs->rows * gs->cols;
-	    p = tb->ib;
-	    INIT_MINMAX(p, nm, size, min, max, found);
-
-	    if (!found) {
-		/* all nulls! */
-		return (-1);
-	    }
-
-	    size = gs->rows * gs->cols;
-	    p = tb->ib;
-	    SET_MINMAX(p, nm, size, min, max);
-	}
-	else if (tb->sb) {
-	    short *p;
-
-	    size = gs->rows * gs->cols;
-	    p = tb->sb;
-	    INIT_MINMAX(p, nm, size, min, max, found);
-
-	    if (!found) {
-		/* all nulls! */
-		return (-1);
-	    }
-
-	    size = gs->rows * gs->cols;
-	    p = tb->sb;
-	    SET_MINMAX(p, nm, size, min, max);
-	}
-	else if (tb->cb) {
-	    char *p;
-
-	    size = gs->rows * gs->cols;
-	    p = (char *)tb->cb;
-	    INIT_MINMAX(p, nm, size, min, max, found);
-
-	    if (!found) {
-		/* all nulls! */
-		return (-1);
-	    }
-
-	    size = gs->rows * gs->cols;
-	    p = (char *)tb->cb;
-	    SET_MINMAX(p, nm, size, min, max);
-	}
-	else if (tb->fb) {
-	    float *p;
-
-	    size = gs->rows * gs->cols;
-	    p = tb->fb;
-	    INIT_MINMAX(p, nm, size, min, max, found);
-
-	    if (!found) {
-		/* all nulls! */
-		return (-1);
-	    }
-
-	    size = gs->rows * gs->cols;
-	    p = tb->fb;
-	    SET_MINMAX(p, nm, size, min, max);
-	}
-
-	gs->att[desc].max_nz = max;
-	gs->att[desc].min_nz = min;
-	gs->att[desc].range_nz = gs->att[desc].max_nz - gs->att[desc].min_nz;
-    }
-
-    if (ATT_TOPO == desc) {
-	gs->zmin = min;
-	gs->zmax = max;
-	gs->zrange = gs->zmax - gs->zmin;
-	gs->zminmasked = gs->zmin;
-	gs->zmax_nz = gs->zmax;
-	gs->zmin_nz = gs->zmin;
-	gs->zrange_nz = gs->zmax_nz - gs->zmin_nz;
-    }
-
-    G_debug(3, "Gs_update_attrange(): min=%f max=%f", gs->zmin, gs->zmax);
-
-    return (1);
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/Gv3.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/Gv3.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/Gv3.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,419 +0,0 @@
-/*!
-   \file lib/ogsf/Gv3.c
-
-   \brief OGSF library - loading vector sets (lower level functions)
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   (C) 1999-2008, 2011 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.
-
-   \author Bill Brown USACERL (December 1993)
-   \author Updated by Martin Landa <landa.martin gmail.com>
-   (doxygenized in May 2008, thematic mapping in August 2011)
- */
-
-#include <stdlib.h>
-
-#include <grass/gis.h>
-#include <grass/colors.h>
-#include <grass/raster.h>
-#include <grass/vector.h>
-#include <grass/dbmi.h>
-#include <grass/glocale.h>
-#include <grass/ogsf.h>
-
-/*
-   #define TRAK_MEM
-*/
-
-#ifdef TRAK_MEM
-static int Tot_mem = 0;
-#endif
-
-/*!
-   \brief Load vector map to memory
-
-   The other alternative may be to load to a tmp file
-
-   \param grassname vector map name
-   \param[out] number of loaded features
-
-   \return pointer to geoline struct
-   \return NULL on failure
- */
-geoline *Gv_load_vect(const char *grassname, int *nlines)
-{
-    struct Map_info map;
-    struct line_pnts *points;
-    struct line_cats *Cats = NULL;
-    geoline *top, *gln, *prev;
-    int np, i, n, nareas, nl = 0, area, type, is3d;
-    struct Cell_head wind;
-    float vect[2][3];
-    const char *mapset;
-
-    mapset = G_find_vector2(grassname, "");
-    if (!mapset) {
-	G_warning(_("Vector map <%s> not found"), grassname);
-	return NULL;
-    }
-
-    Vect_set_open_level(2);
-    if (Vect_open_old(&map, grassname, "") == -1) {
-	G_warning(_("Unable to open vector map <%s>"),
-		  G_fully_qualified_name(grassname, mapset));
-	return NULL;
-    }
-
-    top = gln = (geoline *) G_malloc(sizeof(geoline));	/* G_fatal_error */
-    if (!top) {
-	return NULL;
-    }
-
-    prev = top;
-
-#ifdef TRAK_MEM
-    Tot_mem += sizeof(geoline);
-#endif
-
-    points = Vect_new_line_struct();
-    Cats = Vect_new_cats_struct();
-
-    G_get_set_window(&wind);
-    Vect_set_constraint_region(&map, wind.north, wind.south, wind.east,
-			       wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
-
-    is3d = Vect_is_3d(&map);
-
-    /* Read areas */
-    n = Vect_get_num_areas(&map);
-    nareas = 0;
-    G_debug(3, "Reading vector areas (nareas = %d)", n);
-    for (area = 1; area <= n; area++) {
-	G_debug(3, " area %d", area);
-	Vect_get_area_points(&map, area, points);
-	if (points->n_points < 3)
-	    continue;
-
-	/* initialize style */
-	gln->highlighted = 0;
-
-	gln->type = OGSF_POLYGON;
-	gln->npts = np = points->n_points;
-	G_debug(3, "  np = %d", np);
-
-	if (is3d) {
-	    gln->dims = 3;
-	    gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3));	/* G_fatal_error */
-	    if (!gln->p3) {
-		return (NULL);
-	    }
-#ifdef TRAK_MEM
-	    Tot_mem += (np * sizeof(Point3));
-#endif
-	}
-	else {
-	    gln->dims = 2;
-	    gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2));	/* G_fatal_error */
-	    if (!gln->p2) {
-		return (NULL);
-	    }
-#ifdef TRAK_MEM
-	    Tot_mem += (np * sizeof(Point2));
-#endif
-	}
-
-	for (i = 0; i < np; i++) {
-	    if (is3d) {
-		gln->p3[i][X] = points->x[i];
-		gln->p3[i][Y] = points->y[i];
-		gln->p3[i][Z] = points->z[i];
-	    }
-	    else {
-		gln->p2[i][X] = points->x[i];
-		gln->p2[i][Y] = points->y[i];
-	    }
-	}
-	/* Calc normal (should be average) */
-	if (is3d) {
-	    vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
-	    vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
-	    vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
-	    vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
-	    vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
-	    vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
-	    GS_v3cross(vect[1], vect[0], gln->norm);
-
-	}
-
-	gln->cats = NULL;
-	gln->next = (geoline *) G_malloc(sizeof(geoline));	/* G_fatal_error */
-	if (!gln->next) {
-	    return (NULL);
-	}
-
-#ifdef TRAK_MEM
-	Tot_mem += sizeof(geoline);
-#endif
-
-	prev = gln;
-	gln = gln->next;
-	nareas++;
-    }
-    G_debug(3, "%d areas loaded", nareas);
-
-    /* Read all lines */
-    G_debug(3, "Reading vector lines ...");
-    while (-1 < (type = Vect_read_next_line(&map, points, Cats))) {
-	G_debug(3, "line type = %d", type);
-	if (type & (GV_LINES | GV_FACE)) {
-	    if (type & (GV_LINES)) {
-		gln->type = OGSF_LINE;
-	    }
-	    else {
-		gln->type = OGSF_POLYGON;
-		/* Vect_append_point ( points, points->x[0], points->y[0], points->z[0] ); */
-	    }
-
-	    /* initialize style */
-	    gln->highlighted = 0;
-
-	    gln->npts = np = points->n_points;
-	    G_debug(3, "  np = %d", np);
-
-	    if (is3d) {
-		gln->dims = 3;
-		gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3));	/* G_fatal_error */
-		if (!gln->p3) {
-		    return (NULL);
-		}
-#ifdef TRAK_MEM
-		Tot_mem += (np * sizeof(Point3));
-#endif
-	    }
-	    else {
-		gln->dims = 2;
-		gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2));	/* G_fatal_error */
-		if (!gln->p2) {
-		    return (NULL);
-		}
-#ifdef TRAK_MEM
-		Tot_mem += (np * sizeof(Point2));
-#endif
-	    }
-
-	    for (i = 0; i < np; i++) {
-		if (is3d) {
-		    gln->p3[i][X] = points->x[i];
-		    gln->p3[i][Y] = points->y[i];
-		    gln->p3[i][Z] = points->z[i];
-		}
-		else {
-		    gln->p2[i][X] = points->x[i];
-		    gln->p2[i][Y] = points->y[i];
-		}
-	    }
-	    /* Calc normal (should be average) */
-	    if (is3d && gln->type == OGSF_POLYGON) {
-		vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
-		vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
-		vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
-		vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
-		vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
-		vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
-		GS_v3cross(vect[1], vect[0], gln->norm);
-		G_debug(3, "norm %f %f %f", gln->norm[0], gln->norm[1],
-			gln->norm[2]);
-	    }
-
-	    /* Store category info for thematic display */
-	    if (Cats->n_cats > 0) {
-		gln->cats = Cats;
-		Cats = Vect_new_cats_struct();
-	    }
-	    else {
-		gln->cats = NULL;
-		Vect_reset_cats(Cats);
-	    }
-
-	    gln->next = (geoline *) G_malloc(sizeof(geoline));	/* G_fatal_error */
-	    if (!gln->next) {
-		return (NULL);
-	    }
-#ifdef TRAK_MEM
-	    Tot_mem += sizeof(geoline);
-#endif
-
-	    prev = gln;
-	    gln = gln->next;
-	    nl++;
-	}
-    }
-    G_debug(3, "%d lines loaded", nl);
-
-    nl += nareas;
-
-    prev->next = NULL;
-    G_free(gln);
-
-#ifdef TRAK_MEM
-    Tot_mem -= sizeof(geoline);
-#endif
-
-    Vect_close(&map);
-
-    if (!nl) {
-	G_warning(_("No features from vector map <%s> fall within current region"),
-		  G_fully_qualified_name(grassname, mapset));
-	return (NULL);
-    }
-    else {
-	G_message(_("Vector map <%s> loaded (%d features)"),
-		  G_fully_qualified_name(grassname, mapset), nl);
-    }
-
-    *nlines = nl;
-
-#ifdef TRAK_MEM
-    G_debug(3, "Total vect memory = %d Kbytes", Tot_mem / 1000);
-#endif
-
-    return (top);
-}
-
-/*! 
-   \brief Tracking memory 
-
-   \param minus mimus number 
- */
-void sub_Vectmem(int minus)
-{
-    G_debug(5, "sub_Vectmem(): minus=%d", minus);
-#ifdef TRAK_MEM
-    {
-	Tot_mem -= minus;
-    }
-#endif
-
-    return;
-}
-
-/*!
-  \brief Load styles for geolines based on thematic mapping
-
-  \param gv pointer to geovect structure
-  \param colors pointer to Colors structure or NULL
-
-  \return number of features defined by thematic mapping
-  \return -1 on error
-*/
-int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
-{
-    geoline *gvt;
-
-    struct Map_info Map;
-    struct field_info *Fi;
-    
-    int nvals, cat, nlines, nskipped;
-    int red, blu, grn;
-    const char *str;
-    const char *mapset;
-
-    dbDriver *driver;
-    dbValue value;
-    
-    if(!gv || !gv->tstyle || !gv->filename)
-	return -1;
-
-    mapset = G_find_vector2(gv->filename, "");
-    if (!mapset) {
-	G_fatal_error(_("Vector map <%s> not found"), gv->filename);
-    }
-    
-    Vect_set_open_level(1);
-    if (Vect_open_old(&Map, gv->filename, "") == -1) {
-	G_fatal_error(_("Unable to open vector map <%s>"),
-		      G_fully_qualified_name(gv->filename, mapset));
-    }
-    
-    Fi = Vect_get_field(&Map, gv->tstyle->layer);
-    if (!Fi) {
-	G_warning(_("Database connection not defined for layer %d"),
-		  gv->tstyle->layer);
-    }
-    else {
-      driver = db_start_driver_open_database(Fi->driver, Fi->database);
-      if (!driver)
-	  G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
-			Fi->database, Fi->driver);
-    }
-    G_message(_("Loading thematic vector layer <%s>..."),
-	      G_fully_qualified_name(gv->filename, mapset));
-    nlines = nskipped = 0;
-    for(gvt = gv->lines; gvt; gvt = gvt->next) {
-	gvt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
-	G_zero(gvt->style, sizeof(gvstyle));
-	
-	/* use default style */
-	gvt->style->color  = gv->style->color;
-	gvt->style->symbol = gv->style->symbol;
-	gvt->style->size   = gv->style->size;
-	gvt->style->width  = gv->style->width;
-
-	cat = -1;
-	if (gvt->cats)
-	    Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat);
-	if (cat < 0) {
-	    nskipped++;
-	    continue;
-	}
-	
-	/* color */
-	if (colors) {
-	    if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
-		G_warning(_("No color rule defined for category %d"), cat);
-		gvt->style->color = gv->style->color;
-	    }
-	    gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
-		((int)((blu) << 16) & BLU_MASK);
-	}
-	
-	if (gv->tstyle->color_column) {
-	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->color_column, &value);
-	    if (nvals < 1)
-		continue;
-	    str = db_get_value_string(&value);
-	    if (!str)
-		continue;
-	    if (G_str_to_color(str, &red, &grn, &blu) != 1) {
-		G_warning(_("Invalid color definition (%s)"),
-			  str);
-		gvt->style->color = gv->style->color;
-	    }
-	    else {
-		gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
-		    ((int)((blu) << 16) & BLU_MASK);
-	    }
-	}
-	
-	/* width */
-	if (gv->tstyle->width_column) {
-	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->width_column, &value);
-	    if (nvals < 1)
-		continue;
-	    gvt->style->width = db_get_value_int(&value);
-	}
-
-	nlines++;
-    }
-
-    if (nskipped > 0)
-	G_warning(_("%d features without category. "
-		    "Unable to determine color rules for features without category."),
-		  nskipped);
-    
-    return nlines;
-}

Deleted: grass/branches/releasebranch_7_0/lib/ogsf/Gvl3.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/Gvl3.c	2014-10-28 13:30:41 UTC (rev 62435)
+++ grass/branches/releasebranch_7_0/lib/ogsf/Gvl3.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -1,88 +0,0 @@
-/*!
-   \file Gvl3.c
-
-   \brief OGSF library - loading volumes (lower level functions)
-
-   GRASS OpenGL gsurf OGSF Library 
-
-   (C) 1999-2008 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.
-
-   \author Tomas Paudits (December 2003)
-   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
- */
-
-#include <grass/gis.h>
-#include <grass/raster.h>
-#include <grass/raster3d.h>
-#include <grass/ogsf.h>
-#include <grass/glocale.h>
-
-/*!
-   \brief Load color table
-
-   \param[out] color_data color data buffer
-   \param name 3D raster map name
-
-   \return -1 on failure
-   \return 1 on success
- */
-int Gvl_load_colors_data(void **color_data, const char *name)
-{
-    const char *mapset;
-    struct Colors *colors;
-
-    if (NULL == (mapset = G_find_raster3d(name, ""))) {
-	G_warning(_("3D raster map <%s> not found"), name);
-	return (-1);
-    }
-
-    if (NULL == (colors = (struct Colors *)G_malloc(sizeof(struct Colors))))
-	return (-1);
-
-    if (0 > Rast3d_read_colors(name, mapset, colors)) {
-	G_free(colors);
-	return (-1);
-    }
-
-    *color_data = colors;
-
-    return (1);
-}
-
-/*!
-   \brief Unload color table
-
-   \param color_data color data buffer
-
-   \return -1 on failure
-   \return 1 on success
- */
-int Gvl_unload_colors_data(void *color_data)
-{
-    Rast_free_colors(color_data);
-
-    G_free(color_data);
-
-    return (1);
-}
-
-/*!
-   \brief Get color for value
-
-   \param color_data color data value
-   \param value data value
-
-   \return color value
- */
-int Gvl_get_color_for_value(void *color_data, float *value)
-{
-    int r, g, b;
-
-    Rast_get_f_color((FCELL *) value, &r, &g, &b, color_data);
-    return ((r & 0xff) | ((g & 0xff) << 8) | ((b & 0xff) << 16));
-}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gk2.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/GK2.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gk2.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gk2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,625 @@
+/*!
+   \file GK2.c
+
+   \brief OGSF library - setting and manipulating keyframes animation
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   (C) 1999-2008 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.
+
+   \author Bill Brown USACERL, GMSL/University of Illinois
+   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
+ */
+
+#include <stdlib.h>
+
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include <grass/ogsf.h>
+
+static int _add_key(Keylist *, int, float);
+static void _remove_key(Keylist *);
+
+static Keylist *Keys = NULL;
+static Keylist *Keytail = NULL;
+static Viewnode *Views = NULL;
+static float Keystartpos = 0.0;
+static float Keyendpos = 1.0;
+static float Tension = 0.8;
+static int Viewsteps = 0;
+static int Numkeys = 0;
+static int Interpmode = KF_SPLINE;
+static int Fmode = 0;
+
+/* next & prior already initialized to NULL */
+static int _add_key(Keylist * newk, int force_replace, float precis)
+{
+    Keylist *k, *tempk, *prev;
+    int found;
+
+    found = 0;
+    prev = NULL;
+
+    /* if(Viewsteps) precis = 0.5/Viewsteps; */
+    for (k = Keys; k; k = k->next) {
+	if (k->pos >= newk->pos - precis && k->pos <= newk->pos + precis) {
+	    if (force_replace) {
+
+		if (k->prior) {
+		    k->prior->next = newk;
+		    newk->prior = prev;
+		}
+		else {
+		    Keys = newk;
+		}
+
+		newk->next = k->next;
+		newk->prior = k->prior;
+		tempk = k;
+		k = newk;
+		free(tempk);
+	    }
+	    else {
+		free(newk);
+	    }
+
+	    return (-1);
+	}
+    }
+
+    if (Keys) {
+	if (newk->pos < Keys->pos) {
+	    /* new will be first */
+	    newk->next = Keys;
+	    Keys->prior = newk;
+	    Keys = newk;
+	}
+	else {
+	    prev = k = Keys;
+	    while (k && !found) {
+		if (k->pos > newk->pos) {
+		    prev->next = newk;
+		    newk->next = k;
+		    newk->prior = prev;
+		    k->prior = newk;
+		    found = 1;
+		}
+
+		prev = k;
+		k = k->next;
+	    }
+	    if (!found) {
+		Keytail = prev->next = newk;
+		newk->prior = prev;
+	    }
+	}
+    }
+    else {
+	Keys = Keytail = newk;
+    }
+
+    ++Numkeys;
+    return (1);
+}
+
+static void _remove_key(Keylist * k)
+{
+    if (k->prior) {
+	k->prior->next = k->next;
+	if (k->next) {
+	    k->next->prior = k->prior;
+	}
+	else {
+	    Keytail = k->prior;
+	}
+    }
+    else {
+	Keys = k->next;
+	if (k->next) {
+	    k->next->prior = NULL;
+	}
+    }
+    k->next = k->prior = NULL;
+
+    return;
+}
+
+/*!
+   \brief Set interpolation mode 
+
+   \param mode interpolation mode (KF_LINEAR or KF_SPLINE)
+
+   \return 1 on success
+   \return -1 on error (invalid interpolation mode)
+ */
+int GK_set_interpmode(int mode)
+{
+    if (KF_LEGAL_MODE(mode)) {
+	Interpmode = mode;
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set value for tension when interpmode is KF_SPLINE. 
+
+   \param tens value tens should be between 0.0; 1.0.
+ */
+void GK_set_tension(float tens)
+{
+    Tension = tens > 1.0 ? 1.0 : (tens < 0.0 ? 0.0 : tens);
+
+    /* for now */
+    if (Views) {
+	GK_update_frames();
+	GS_set_draw(GSD_BACK);
+	GS_ready_draw();
+	GS_clear(GS_background_color());
+	GS_alldraw_wire();
+
+	gk_draw_path(Views, Viewsteps, Keys);
+
+	GS_done_draw();
+    }
+
+    return;
+}
+
+void GK_showtension_start(void)
+{
+    return;
+}
+
+/*!
+   \brief Show tension stop ?
+
+   Use GK_showtension_start/GK_update_tension/GK_showtension_stop to
+   initialize and stop multi-view display of path when changing
+   tension.
+ */
+void GK_showtension_stop(void)
+{
+    return;
+}
+
+/*!
+   \brief Update tension
+ */
+void GK_update_tension(void)
+{
+    if (Views) {
+	GK_update_frames();
+    }
+
+    return;
+}
+
+/*!
+   \brief Print keyframe info
+
+   \param name filename
+ */
+void GK_print_keys(const char *name)
+{
+    Keylist *k;
+    FILE *fp;
+    int cnt = 1;
+
+    if (NULL == (fp = fopen(name, "w"))) {
+	G_fatal_error(_("Unable to open file <%s> for writing"), name);
+    }
+    /* write a default frame rate of 30 at top of file */
+    fprintf(fp, "30 \n");
+
+    for (k = Keys; k; k = k->next) {
+
+	fprintf(fp,
+		"{%f {{FromX %f} {FromY %f} {FromZ %f} {DirX %f} {DirY %f} {DirZ %f} {FOV %f} {TWIST %f} {cplane-0 {{pos_x 0.000000} {pos_y 0.000000} {pos_z 0.000000} {blend_type OFF} {rot 0.000000} {tilt 0.000000}}}} keyanimtag%d 0} ",
+		k->pos, k->fields[KF_FROMX], k->fields[KF_FROMY],
+		k->fields[KF_FROMZ], k->fields[KF_DIRX], k->fields[KF_DIRY],
+		k->fields[KF_DIRZ], k->fields[KF_FOV] / 10.,
+		k->fields[KF_TWIST], cnt);
+	cnt++;
+    }
+
+    fclose(fp);
+    return;
+
+}
+
+/*!
+   \brief Recalculate path using the current number of frames requested.
+
+   Call after changing number of frames or when
+   Keyframes change.
+ */
+void GK_update_frames(void)
+{
+    Keylist *k;
+    int loop = 0;
+
+    if (Keys) {
+	if (Numkeys > 1) {
+	    k = Keytail;
+	    Keyendpos = k->pos;
+
+	    if (k->fields[KF_FROMX] == Keys->fields[KF_FROMX] &&
+		k->fields[KF_FROMY] == Keys->fields[KF_FROMY] &&
+		k->fields[KF_FROMZ] == Keys->fields[KF_FROMZ]) {
+		loop = 1;
+	    }
+	}
+
+	Keystartpos = Keys->pos;
+    }
+
+    if (Interpmode == KF_LINEAR && Numkeys > 1) {
+	if (Views) {
+	    free(Views);
+	    Views = NULL;
+	}
+
+	Views = gk_make_linear_framesfromkeys(Keys, Numkeys, Viewsteps, loop);
+
+	if (!Views) {
+	    G_warning(_("Check no. of frames requested and keyframes marked"));
+	}
+    }
+    else if (Numkeys > 2) {
+	if (Views) {
+	    free(Views);
+	    Views = NULL;
+	}
+
+	Views = gk_make_framesfromkeys
+	    (Keys, Numkeys, Viewsteps, loop, 1.0 - Tension);
+
+	if (!Views) {
+	    G_warning(_("Check no. of frames requested and keyframes marked"));
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Set the number of frames to be interpolated from keyframes
+
+   \param newsteps number of frames
+ */
+void GK_set_numsteps(int newsteps)
+{
+    Viewsteps = newsteps;
+    GK_update_frames();
+
+    return;
+}
+
+/*!
+   \brief Deletes all keyframes, resets field masks.
+
+   Doesn't change number of frames requested.
+ */
+void GK_clear_keys(void)
+{
+    gk_free_key(Keys);
+    Keys = NULL;
+    Numkeys = 0;
+    free(Views);
+    Views = NULL;
+
+    Keystartpos = 0.0;
+    Keyendpos = 1.0;
+
+    return;
+}
+
+/*!
+   \brief Move keyframe
+
+   Precis works as in other functions - to identify keyframe to move.
+   Only the first keyframe in the precis range will be moved.
+
+   \param oldpos old position
+   \param precis precision value
+   \param newpos new position
+
+   \return number of keys moved (1 or 0)
+ */
+int GK_move_key(float oldpos, float precis, float newpos)
+{
+    Keylist *k;
+
+    for (k = Keys; k; k = k->next) {
+	if (k->pos >= oldpos - precis && k->pos <= oldpos + precis) {
+	    _remove_key(k);
+	    k->pos = newpos;
+	    _add_key(k, 1, precis);
+	    GK_update_frames();
+	    return (1);
+	}
+    }
+
+    return (0);
+}
+
+/*!
+   Delete keyframe
+
+   The values pos and precis are used to determine which keyframes to
+   delete.  Any keyframes with their position within precis of pos will
+   be deleted if justone is zero.  If justone is non-zero, only the first
+   (lowest pos) keyframe in the range will be deleted.
+
+   \param pos position
+   \param precis precision
+   \param justone delete only one keyframe
+
+   \return number of keys deleted.
+ */
+int GK_delete_key(float pos, float precis, int justone)
+{
+    Keylist *k, *next;
+    int cnt;
+
+    for (cnt = 0, k = Keys; k;) {
+	next = k->next;
+
+	if (k->pos >= pos - precis && k->pos <= pos + precis) {
+	    cnt++;
+	    _remove_key(k);
+	    free(k);
+	    if (justone) {
+		break;
+	    }
+	}
+
+	k = next;
+    }
+
+    GK_update_frames();
+    return (cnt);
+}
+
+/*!
+   \brief Add keyframe
+
+   The pos value is the relative position in the animation for this
+   particular keyframe - used to compare relative distance to neighboring
+   keyframes, it can be any floating point value.
+
+   The fmask value can be any of the following or'd together:    
+   - KF_FROMX_MASK    
+   - KF_FROMY_MASK    
+   - KF_FROMZ_MASK    
+   - KF_FROM_MASK (KF_FROMX_MASK | KF_FROMY_MASK | KF_FROMZ_MASK) 
+
+   - KF_DIRX_MASK    
+   - KF_DIRY_MASK    
+   - KF_DIRZ_MASK    
+   - KF_DIR_MASK (KF_DIRX_MASK | KF_DIRY_MASK | KF_DIRZ_MASK) 
+
+   - KF_FOV_MASK    
+   - KF_TWIST_MASK    
+
+   - KF_ALL_MASK (KF_FROM_MASK | KF_DIR_MASK | KF_FOV_MASK | KF_TWIST_MASK) 
+
+   Other fields will be added later.
+
+   The value precis and the boolean force_replace are used to determine
+   if a keyframe should be considered to be at the same position as a
+   pre-existing keyframe. e.g., if anykey.pos - newkey.pos <= precis,
+   GK_add_key() will fail unless force_replace is TRUE.
+
+   \param pos postion
+   \param fmaks
+   \param force_replace
+   \param precis precision value
+
+   \return 1 if key is added
+   \return -1 key not added
+ */
+int GK_add_key(float pos, unsigned long fmask, int force_replace,
+	       float precis)
+{
+    Keylist *newk;
+    float tmp[3];
+
+    if (NULL == (newk = (Keylist *) malloc(sizeof(Keylist)))) {
+	fprintf(stderr, "Out of memory\n");
+	return (-1);
+    }
+
+    /* All fields set, don't use mask until making Views */
+
+    GS_get_from(tmp);
+    newk->fields[KF_FROMX] = tmp[X];
+    newk->fields[KF_FROMY] = tmp[Y];
+    newk->fields[KF_FROMZ] = tmp[Z];
+
+    G_debug(3, "KEY FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]);
+
+    /* Instead of View Dir try get_focus (view center) */
+    /* View Dir is implied from eye and center position */
+    /*    GS_get_viewdir(tmp); */
+
+    /* ACS 1 line: was      GS_get_focus(tmp);
+       with this kanimator works also for flythrough navigation
+       also changed in gk.c
+     */
+    GS_get_viewdir(tmp);
+    newk->fields[KF_DIRX] = tmp[X];
+    newk->fields[KF_DIRY] = tmp[Y];
+    newk->fields[KF_DIRZ] = tmp[Z];
+
+    newk->fields[KF_FOV] = GS_get_fov();
+    newk->fields[KF_TWIST] = GS_get_twist();
+    newk->pos = pos;
+    newk->fieldmask = fmask;
+    newk->next = NULL;
+    newk->prior = NULL;
+
+    if (0 < _add_key(newk, force_replace, precis)) {
+	GK_update_frames();
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Moves the animation to frame number "step".
+
+   Step should be a value between 1 and the number of frames.  If
+   render is non-zero, calls draw_all.
+
+   \param step step value
+   \param render
+ */
+void GK_do_framestep(int step, int render)
+{
+    if (Views) {
+	if (step > 0 && step <= Viewsteps) {
+	    gk_follow_frames(Views, Viewsteps, Keys, step, 1, render, Fmode);
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw the current path
+
+   \param flag
+ */
+void GK_show_path(int flag)
+{
+    if (flag) {
+	Fmode |= FM_PATH;
+
+	if (Views) {
+	    GS_set_draw(GSD_FRONT);
+	    GS_ready_draw();
+
+	    gk_draw_path(Views, Viewsteps, Keys);
+
+	    GS_done_draw();
+
+	}
+    }
+    else {
+	Fmode &= ~FM_PATH;
+    }
+
+    return;
+}
+
+/*!
+   \brief Show vector sets
+
+   \param flag
+ */
+void GK_show_vect(int flag)
+{
+    if (flag) {
+	Fmode |= FM_VECT;
+	if (Views) {
+
+	    GS_set_draw(GSD_FRONT);
+	    GS_ready_draw();
+
+	    GV_alldraw_vect();
+
+	    GS_done_draw();
+	}
+    }
+    else {
+	Fmode &= ~FM_VECT;
+    }
+
+    return;
+}
+
+/*!
+   \brief Show point sets
+
+   \param flag
+ */
+void GK_show_site(int flag)
+{
+    if (flag) {
+	Fmode |= FM_SITE;
+
+	if (Views) {
+
+	    GS_set_draw(GSD_FRONT);
+	    GS_ready_draw();
+
+	    GP_alldraw_site();
+
+	    GS_done_draw();
+
+	}
+    }
+    else {
+	Fmode &= ~FM_SITE;
+    }
+
+    return;
+}
+
+/*!
+   \brief Show volumes
+
+   \param flag
+ */
+void GK_show_vol(int flag)
+{
+    if (flag) {
+	Fmode |= FM_VOL;
+
+	if (Views) {
+
+	    GS_set_draw(GSD_FRONT);
+	    GS_ready_draw();
+
+	    GVL_alldraw_vol();
+
+	    GS_done_draw();
+
+	}
+    }
+    else {
+	Fmode &= ~FM_VOL;
+    }
+
+    return;
+}
+
+/*!
+   \brief Show list
+
+   \param flag
+ */
+void GK_show_list(int flag)
+{
+    if (flag) {
+	Fmode |= FM_LABEL;
+
+	if (Views) {
+	    GS_draw_all_list();
+	}
+    }
+    else {
+	Fmode &= ~FM_LABEL;
+    }
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gp2.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/GP2.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gp2.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gp2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,710 @@
+/*!
+   \file lib/ogsf/GP2.c
+
+   \brief OGSF library - loading and manipulating point sets (higher level functions)
+
+   (C) 1999-2008, 2011 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.
+
+   \author Bill Brown USACERL (January 1994)
+   \author Updated by Martin landa <landa.martin gmail.com>
+   (doxygenized in May 2008, thematic mapping in June 2011)
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grass/gis.h>
+#include <grass/ogsf.h>
+#include <grass/glocale.h>
+
+#include "gsget.h"
+
+static int Site_ID[MAX_SITES];
+static int Next_site = 0;
+
+/*!
+   \brief Check if point set exists
+
+   \param id point set id
+
+   \return 1 found
+   \return 0 not found
+ */
+int GP_site_exists(int id)
+{
+    int i, found = 0;
+
+    G_debug(4, "GP_site_exists(%d)", id);
+
+    if (NULL == gp_get_site(id)) {
+	return 0;
+    }
+
+    for (i = 0; i < Next_site && !found; i++) {
+	if (Site_ID[i] == id) {
+	    found = 1;
+	}
+    }
+
+    G_debug(3, "GP_site_exists(): found=%d", found);
+
+    return found;
+}
+
+/*!
+   \brief Create new point set
+
+   \return point set id
+   \return -1 on error (number of point sets exceeded)
+ */
+int GP_new_site(void)
+{
+    geosite *np;
+
+    if (Next_site < MAX_SITES) {
+	np = gp_get_new_site();
+	gp_set_defaults(np);
+	Site_ID[Next_site] = np->gsite_id;
+	++Next_site;
+
+	G_debug(3, "GP_new_site() id=%d", np->gsite_id);
+
+	return np->gsite_id;
+    }
+
+    return -1;
+}
+
+/*!
+   \brief Get number of loaded point sets
+
+   \return number of point sets
+ */
+int GP_num_sites(void)
+{
+    return gp_num_sites();
+}
+
+/*!
+   \brief Get list of point sets
+
+   Must freed when no longer needed!
+
+   \param numsites number of point sets
+
+   \return pointer to list of points sets
+   \return NULL on error
+ */
+int *GP_get_site_list(int *numsites)
+{
+    int i, *ret;
+
+    *numsites = Next_site;
+
+    if (Next_site) {
+	ret = (int *)G_malloc(Next_site * sizeof(int));	/* G_fatal_error */
+	if (!ret) {
+	    return NULL;
+	}
+
+	for (i = 0; i < Next_site; i++) {
+	    ret[i] = Site_ID[i];
+	}
+
+	return ret;
+    }
+
+    return NULL;
+}
+
+/*!
+   \brief Delete registrated point set
+
+   \param id point set id
+
+   \return 1 on success
+   \return -1 on error (point sets not available)
+ */
+int GP_delete_site(int id)
+{
+    int i, j, found = 0;
+
+    G_debug(4, "GP_delete_site(%d)", id);
+
+    if (GP_site_exists(id)) {
+	gp_delete_site(id);
+
+	for (i = 0; i < Next_site && !found; i++) {
+	    if (Site_ID[i] == id) {
+		found = 1;
+		for (j = i; j < Next_site; j++) {
+		    Site_ID[j] = Site_ID[j + 1];
+		}
+	    }
+	}
+
+	if (found) {
+	    --Next_site;
+	    return 1;
+	}
+    }
+
+    return -1;
+}
+
+/*!
+   \brief Load point set from file
+
+   Check to see if handle already loaded, if so - free before loading
+   new for now, always load to memory.
+
+   \todo load file handle & ready for reading instead of using memory
+
+   \param id point set id
+   \param filename point set filename
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GP_load_site(int id, const char *filename)
+{
+    geosite *gp;
+
+    G_debug(3, "GP_load_site(id=%d, name=%s)", id, filename);
+
+    if (NULL == (gp = gp_get_site(id))) {
+	return -1;
+    }
+
+    if (gp->points) {
+	gp_free_sitemem(gp);
+    }
+
+    gp->filename = G_store(filename);
+
+    gp->points = Gp_load_sites(filename, &(gp->n_sites), &(gp->has_z));
+    
+    if (gp->points) {
+	return 1;
+    }
+
+    return -1;
+}
+
+/*!
+   \brief Get point set filename
+
+   Note: char array is allocated by G_store()
+
+   \param id point set id
+   \param[out] filename point set filename
+
+   \return -1 on error (point set not found)
+   \return 1 on success
+ */
+int GP_get_sitename(int id, char **filename)
+{
+    geosite *gp;
+
+    G_debug(4, "GP_get_sitename(%d)", id);
+
+    if (NULL == (gp = gp_get_site(id))) {
+	return -1;
+    }
+
+    *filename = G_store(gp->filename);
+
+    return 1;
+}
+
+/*!
+   \brief Get point set style
+
+   \param id point set id
+
+   \return 1 on success
+   \return -1 on error (point set not found)
+ */
+int GP_get_style(int id, int *color, int *width, float *size, int *symbol)
+{
+    geosite *gp;
+
+    G_debug(4, "GP_get_style(%d)", id);
+
+    if (NULL == (gp = gp_get_site(id))) {
+	return -1;
+    }
+
+    *color = gp->style->color;
+    *width = gp->style->width;
+    *symbol = gp->style->symbol;
+    *size = gp->style->size;
+
+    return 1;
+}
+
+/*!
+   \brief Set point style
+
+   Supported icon symbols (markers):
+    - ST_X
+    - ST_BOX
+    - ST_SPHERE
+    - ST_CUBE
+    - ST_DIAMOND
+    - ST_DEC_TREE
+    - ST_CON_TREE
+    - ST_ASTER
+    - ST_GYRO
+    - ST_HISTOGRAM
+
+   \param id point set id
+   \param color icon color
+   \param width icon line width
+   \param size icon size
+   \param symbol icon symbol
+
+   \return 1 on success
+   \return -1 on error (point set not found)
+ */
+int GP_set_style(int id, int color, int width, float size, int symbol)
+{
+    geosite *gp;
+
+    G_debug(4, "GP_set_style(id=%d, color=%d, width=%d, size=%f, symbol=%d)", id, color, width, size,
+	    symbol);
+
+    if (NULL == (gp = gp_get_site(id))) {
+	return -1;
+    }
+
+    gp->style->color = color;
+    gp->style->symbol = symbol;
+    gp->style->size = size;
+    gp->style->width = width;
+
+    return 1;
+}
+
+/*!
+   \brief Set point set style for thematic mapping
+
+   Updates also style for each geopoint.
+   
+   \param id point set id
+   \param layer layer number for thematic mapping (-1 for undefined)
+   \param color icon color column name
+   \param width icon line width column name
+   \param size icon size column name
+   \param symbol icon symbol column name
+   \param colors pointer to Colors structure or NULL
+
+   \return 1 on success
+   \return -1 on error (point set not found)
+ */
+int GP_set_style_thematic(int id, int layer, const char* color, const char* width,
+			  const char* size, const char* symbol, struct Colors *color_rules)
+{
+    geosite *gp;
+    
+    G_debug(4, "GP_set_style_thematic(id=%d, layer=%d, color=%s, width=%s, size=%s, symbol=%s)", id, layer,
+	    color, width, size, symbol);
+
+    if (NULL == (gp = gp_get_site(id))) {
+	return -1;
+    }
+
+    if(!gp->tstyle)
+	gp->tstyle = (gvstyle_thematic *)G_malloc(sizeof(gvstyle_thematic));
+    G_zero(gp->tstyle, sizeof(gvstyle_thematic));
+    
+    gp->tstyle->active = 1;
+    gp->tstyle->layer = layer;
+    if (color)
+	gp->tstyle->color_column = G_store(color);
+    if (symbol)
+	gp->tstyle->symbol_column = G_store(symbol);
+    if (size)
+	gp->tstyle->size_column = G_store(size);
+    if (width)
+	gp->tstyle->width_column = G_store(width);
+
+    Gp_load_sites_thematic(gp, color_rules);
+
+    return 1;
+}
+
+/*!
+   \brief Make style for thematic mapping inactive
+   
+   \param id point set id
+
+   \return 1 on success
+   \return -1 on error (point set not found)
+ */
+int GP_unset_style_thematic(int id)
+{
+    geosite *gp;
+
+    G_debug(4, "GP_unset_style_thematic(): id=%d", id);
+
+    if (NULL == (gp = gp_get_site(id))) {
+	return -1;
+    }
+
+    if (gp->tstyle) {
+	gp->tstyle->active = 0;
+    }
+
+    return 1;
+}
+
+/*!
+   \brief Set z mode for point set
+
+   \param id point set id
+   \param use_z TRUE to use z-coordinaces when vector map is 3D
+
+   \return 1 on success
+   \return 0 vector map is not 3D
+   \return -1 on error (invalid point set id)
+ */
+/* I don't see who is using it? Why it's required? */
+int GP_set_zmode(int id, int use_z)
+{
+    geosite *gp;
+
+    G_debug(3, "GP_set_zmode(%d,%d)", id, use_z);
+
+    if (NULL == (gp = gp_get_site(id))) {
+	return -1;
+    }
+
+    if (use_z) {
+	if (gp->has_z) {
+	    gp->use_z = 1;
+	    return 1;
+	}
+
+	return 0;
+    }
+
+    gp->use_z = 0;
+    return 1;
+}
+
+/*!
+   \brief Get z-mode
+
+   \todo Who's using this?
+   
+   \param id point set id
+   \param[out] use_z non-zero code to use z
+
+   \return -1 on error (invalid point set id)
+   \return 1 on success
+ */
+int GP_get_zmode(int id, int *use_z)
+{
+    geosite *gp;
+
+    G_debug(4, "GP_get_zmode(%d)", id);
+
+    if (NULL == (gp = gp_get_site(id))) {
+	return -1;
+    }
+
+    *use_z = gp->use_z;
+    return 1;
+}
+
+/*!
+   \brief Set transformation params
+
+   \param id point set id
+   \param xtrans,ytrans,ztrans x/y/z values
+ */
+void GP_set_trans(int id, float xtrans, float ytrans, float ztrans)
+{
+    geosite *gp;
+
+    G_debug(3, "GP_set_trans(): id=%d trans=%f,%f,%f",
+	    id, xtrans, ytrans, ztrans);
+
+    gp = gp_get_site(id);
+    if (gp) {
+	gp->x_trans = xtrans;
+	gp->y_trans = ytrans;
+	gp->z_trans = ztrans;
+    }
+
+    return;
+}
+
+/*!
+   \brief Get transformation params
+
+   \param id point set id
+   \param[out] xtrans,ytrans,ztrans x/y/z values
+ */
+void GP_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
+{
+    geosite *gp;
+
+    gp = gp_get_site(id);
+
+    if (gp) {
+	*xtrans = gp->x_trans;
+	*ytrans = gp->y_trans;
+	*ztrans = gp->z_trans;
+    }
+
+    G_debug(3, "GP_get_trans(): id=%d, trans=%f,%f,%f",
+	    id, *xtrans, *ytrans, *ztrans);
+
+    return;
+}
+
+/*!
+   \brief Select surface for given point set
+
+   \param hp point set id
+   \param hs surface id
+
+   \return 1 surface selected
+   \return -1 on error
+ */
+int GP_select_surf(int hp, int hs)
+{
+    geosite *gp;
+
+    G_debug(3, "GP_select_surf(%d,%d)", hp, hs);
+
+    if (GP_surf_is_selected(hp, hs)) {
+	return 1;
+    }
+
+    gp = gp_get_site(hp);
+
+    if (gp && GS_surf_exists(hs)) {
+	gp->drape_surf_id[gp->n_surfs] = hs;
+	gp->n_surfs += 1;
+	return 1;
+    }
+
+    return -1;
+}
+
+/*!
+   \brief Unselect surface
+
+   \param hp point set id
+   \param hs surface id
+
+   \return 1 surface unselected
+   \return -1 on error
+ */
+int GP_unselect_surf(int hp, int hs)
+{
+    geosite *gp;
+    int i, j;
+
+    G_debug(3, "GP_unselect_surf(%d,%d)", hp, hs);
+
+    if (!GP_surf_is_selected(hp, hs)) {
+	return 1;
+    }
+
+    gp = gp_get_site(hp);
+
+    if (gp) {
+	for (i = 0; i < gp->n_surfs; i++) {
+	    if (gp->drape_surf_id[i] == hs) {
+		for (j = i; j < gp->n_surfs - 1; j++) {
+		    gp->drape_surf_id[j] = gp->drape_surf_id[j + 1];
+		}
+
+		gp->n_surfs -= 1;
+		return 1;
+	    }
+	}
+    }
+
+    return -1;
+}
+
+/*!
+   \brief Check if surface is selected
+
+   \param hp point set id
+   \param hs surface id
+
+   \return 1 selected
+   \return 0 not selected
+ */
+int GP_surf_is_selected(int hp, int hs)
+{
+    int i;
+    geosite *gp;
+
+    G_debug(3, "GP_surf_is_selected(%d,%d)", hp, hs);
+
+    gp = gp_get_site(hp);
+
+    if (gp) {
+	for (i = 0; i < gp->n_surfs; i++) {
+	    if (hs == gp->drape_surf_id[i]) {
+		return 1;
+	    }
+	}
+    }
+
+    return 0;
+}
+
+/*!
+   \brief Draw point set
+
+   \param id point set id
+ */
+void GP_draw_site(int id)
+{
+    geosurf *gs;
+    geosite *gp;
+    int i;
+    float n, yo, xo, e;
+
+    gp = gp_get_site(id);
+    GS_get_region(&n, &yo, &xo, &e);
+
+    /* kind of sloppy - maybe site files should have an origin, too */
+    if (gp) {
+	if (gp->use_z && gp->has_z) {
+	    gpd_3dsite(gp, xo, yo, 0);
+	}
+	else {
+	    for (i = 0; i < gp->n_surfs; i++) {
+		gs = gs_get_surf(gp->drape_surf_id[i]);
+
+		if (gs) {
+		    gpd_2dsite(gp, gs, 0);
+		    G_debug(5, "Drawing site %d on Surf %d", id,
+			    gp->drape_surf_id[i]);
+		}
+	    }
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw all available point sets
+ */
+void GP_alldraw_site(void)
+{
+    int id;
+
+    for (id = 0; id < Next_site; id++) {
+	GP_draw_site(Site_ID[id]);
+    }
+
+    return;
+}
+
+/*!
+   \brief Set client data
+
+   \param id point set id
+   \param clientd client data
+
+   \return 1 on success
+   \return -1 on error (invalid point set id)
+ */
+int GP_Set_ClientData(int id, void *clientd)
+{
+    geosite *gp;
+
+    gp = gp_get_site(id);
+
+    if (gp) {
+	gp->clientdata = clientd;
+	return 1;
+    }
+
+    return -1;
+}
+
+/*!
+   \brief Get client data
+
+   \param id point set id
+
+   \return pointer to client data
+   \return NULL on error
+ */
+void *GP_Get_ClientData(int id)
+{
+    geosite *gp;
+
+    gp = gp_get_site(id);
+    if (gp) {
+	return (gp->clientdata);
+    }
+
+    return NULL;
+}
+
+/*!
+  \brief Determine point marker symbol for string
+
+  Supported markers:
+    - ST_X
+    - ST_BOX
+    - ST_SPHERE
+    - ST_CUBE
+    - ST_DIAMOND
+    - ST_DEC_TREE
+    - ST_CON_TREE
+    - ST_ASTER
+    - ST_GYRO
+    - ST_HISTOGRAM
+
+  \param str string buffer
+
+  \return marker code (default: ST_SPHERE)
+*/
+int GP_str_to_marker(const char *str)
+{
+    int marker;
+
+    if (strcmp(str, "x") == 0)
+	marker = ST_X;
+    else if (strcmp(str, "box") == 0)
+	marker = ST_BOX;
+    else if (strcmp(str, "sphere") == 0)
+	marker = ST_SPHERE;
+    else if (strcmp(str, "cube") == 0)
+	marker = ST_CUBE;
+    else if (strcmp(str, "diamond") == 0)
+	marker = ST_DIAMOND;
+    else if (strcmp(str, "dec_tree") == 0)
+	marker = ST_DEC_TREE;
+    else if (strcmp(str, "con_tree") == 0)
+	marker = ST_CON_TREE;
+    else if (strcmp(str, "aster") == 0)
+	marker = ST_ASTER;
+    else if (strcmp(str, "gyro") == 0)
+	marker = ST_GYRO;
+    else if (strcmp(str, "histogram") == 0)
+	marker = ST_HISTOGRAM;
+    else {
+	G_warning(_("Unknown icon marker, using \"sphere\""));
+	marker = ST_SPHERE;
+    }
+
+    return marker;
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gp3.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/Gp3.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gp3.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gp3.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,292 @@
+/*!
+   \file lib/ogsf/Gp3.c
+
+   \brief OGSF library - loading point sets (lower level functions)
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   (C) 1999-2008, 2011 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.
+
+   \author Bill Brown USACERL, GMSL/University of Illinois (January 1994)
+   \author Updated by Martin Landa <landa.martin gmail.com>
+   (doxygenized in May 2008, thematic mapping in June 2011)
+ */
+
+#include <stdlib.h>
+
+#include <grass/gis.h>
+#include <grass/colors.h>
+#include <grass/raster.h>
+#include <grass/vector.h>
+#include <grass/dbmi.h>
+#include <grass/glocale.h>
+#include <grass/ogsf.h>
+
+/*!
+   \brief Load to points to memory
+
+   The other alternative may be to load to a tmp file.
+
+   \param name name of vector map to be loaded
+   \param[out] nsites number of loaded points
+   \param[out] has_z 2D or 3D points data loaded?
+
+   \return pointer to geopoint struct (array)
+   \return NULL on failure
+ */
+geopoint *Gp_load_sites(const char *name, int *nsites, int *has_z)
+{
+    struct Map_info map;
+    static struct line_pnts *Points = NULL;
+    struct line_cats *Cats = NULL;
+    geopoint *top, *gpt, *prev;
+    int np, ltype, eof;
+    struct Cell_head wind;
+    int ndim;
+    const char *mapset;
+
+    np = 0;
+    eof = 0;
+    
+    mapset = G_find_vector2(name, "");
+    if (!mapset) {
+	G_warning(_("Vector map <%s> not found"), name);
+	return NULL;
+    }
+    
+    Vect_set_open_level(1);
+    if (Vect_open_old(&map, name, "") == -1) {
+	G_fatal_error(_("Unable to open vector map <%s>"),
+		      G_fully_qualified_name(name, mapset));
+    }
+    
+    Points = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+    
+    top = gpt = (geopoint *) G_malloc(sizeof(geopoint));
+    G_zero(gpt, sizeof(geopoint));
+    if (!top) {
+	return NULL;
+    }
+
+    G_get_set_window(&wind);
+    Vect_set_constraint_region(&map, wind.north, wind.south, wind.east,
+			       wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
+
+    /* get ndim */
+    *has_z = 0;
+    ndim = 2;
+    if (Vect_is_3d(&map)) {
+	*has_z = 1;
+	ndim = 3;
+    }
+
+    while (eof == 0) {
+	ltype = Vect_read_next_line(&map, Points, Cats);
+	switch (ltype) {
+	case -1:
+	    {
+		G_warning(_("Unable to read vector map <%s>"),
+			  G_fully_qualified_name(name, mapset));
+		return NULL;
+	    }
+	case -2:		/* EOF */
+	    {
+		eof = 1;
+		continue;
+	    }
+	}
+	if ((ltype & GV_POINTS)) {
+	    np++;
+	    gpt->p3[X] = Points->x[0];
+	    gpt->p3[Y] = Points->y[0];
+
+	    if (ndim > 2) {
+		gpt->dims = 3;
+		gpt->p3[Z] = Points->z[0];
+	    }
+	    else {
+		gpt->dims = 2;
+	    }
+
+	    /* Store category info for thematic display */
+	    if (Cats->n_cats > 0) {
+		gpt->cats = Cats;
+		Cats = Vect_new_cats_struct();
+	    }
+	    else {
+		Vect_reset_cats(Cats);
+	    }
+	    /* initialize style */
+	    gpt->highlighted = 0;
+	    
+	    G_debug(5, "loading vector point %d x=%f y=%f ncats=%d",
+		    np, Points->x[0], Points->y[0], Cats->n_cats);
+
+	    gpt->next = (geopoint *) G_malloc(sizeof(geopoint));	/* G_fatal_error */
+	    G_zero(gpt->next, sizeof(geopoint));
+	    if (!gpt->next) {
+		return NULL;
+	    }
+
+	    prev = gpt;
+	    gpt = gpt->next;
+	}
+
+    }
+    if (np > 0) {
+	prev->next = NULL;
+	G_free(gpt);
+    }
+
+    Vect_close(&map);
+
+    if (!np) {
+	G_warning(_("No points from vector map <%s> fall within current region"),
+		  G_fully_qualified_name(name, mapset));
+	return (NULL);
+    }
+    else {
+	G_message(_("Vector map <%s> loaded (%d points)"),
+		  G_fully_qualified_name(name, mapset), np);
+    }
+
+    *nsites = np;
+
+    return top;
+}
+
+/*!
+  \brief Load styles for geopoints based on thematic mapping
+
+  \param gp pointer to geosite structure
+  \param colors pointer to Colors structure or NULL
+  
+  \return number of points defined by thematic mapping
+  \return -1 on error
+*/
+int Gp_load_sites_thematic(geosite *gp, struct Colors *colors)
+{
+    geopoint *gpt;
+
+    struct Map_info Map;
+    struct field_info *Fi;
+    
+    int nvals, cat, npts, nskipped;
+    int red, blu, grn;
+    const char *str;
+    const char *mapset;
+
+    dbDriver *driver;
+    dbValue value;
+    
+    if(!gp || !gp->tstyle || !gp->filename)
+	return -1;
+
+    mapset = G_find_vector2(gp->filename, "");
+    if (!mapset) {
+	G_fatal_error(_("Vector map <%s> not found"), gp->filename);
+    }
+    
+    Vect_set_open_level(1);
+    if (Vect_open_old(&Map, gp->filename, "") == -1) {
+	G_fatal_error(_("Unable to open vector map <%s>"),
+		      G_fully_qualified_name(gp->filename, mapset));
+    }
+    
+    Fi = Vect_get_field(&Map, gp->tstyle->layer);
+    if (!Fi) {
+	G_warning(_("Database connection not defined for layer %d"),
+		  gp->tstyle->layer);
+    }
+    else {
+	driver = db_start_driver_open_database(Fi->driver, Fi->database);
+	if (!driver)
+	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+			  Fi->database, Fi->driver);
+    }
+    G_message(_("Loading thematic points layer <%s>..."),
+	      G_fully_qualified_name(gp->filename, mapset));
+    npts = nskipped = 0;
+    for(gpt = gp->points; gpt; gpt = gpt->next) {
+	gpt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
+	G_zero(gpt->style, sizeof(gvstyle));
+	
+	/* use default style */
+	gpt->style->color  = gp->style->color;
+	gpt->style->symbol = gp->style->symbol;
+	gpt->style->size   = gp->style->size;
+	gpt->style->width  = gp->style->width;
+	
+	cat = -1;
+	if (gpt->cats)
+	    Vect_cat_get(gpt->cats, gp->tstyle->layer, &cat);
+	if (cat < 0) {
+	    nskipped++;
+	    continue;
+	}
+
+	/* color */
+	if (colors) {
+	    if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
+		G_warning(_("No color rule defined for category %d"), cat);
+		gpt->style->color = gp->style->color;
+	    }
+	    gpt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
+		((int)((blu) << 16) & BLU_MASK);
+	}
+	if (gp->tstyle->color_column) {
+	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->color_column, &value);
+	    if (nvals < 1)
+		continue;
+	    str = db_get_value_string(&value);
+	    if (!str)
+		continue;
+	    if (G_str_to_color(str, &red, &grn, &blu) != 1) {
+		G_warning(_("Invalid color definition (%s)"),
+			  str);
+		gpt->style->color = gp->style->color;
+	    }
+	    else {
+		gpt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
+		    ((int)((blu) << 16) & BLU_MASK);
+	    }
+	}
+	
+	/* size */
+	if (gp->tstyle->size_column) {
+	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->size_column, &value);
+	    if (nvals < 1)
+		continue;
+	    gpt->style->size = db_get_value_int(&value);
+	}
+
+	/* width */
+	if (gp->tstyle->width_column) {
+	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->width_column, &value);
+	    if (nvals < 1)
+		continue;
+	    gpt->style->width = db_get_value_int(&value);
+	}
+
+	/* symbol/marker */
+	if (gp->tstyle->symbol_column) {
+	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->symbol_column, &value);
+	    if (nvals < 1)
+		continue;
+	    str = db_get_value_string(&value);
+	    gpt->style->symbol = GP_str_to_marker(str);
+	}
+	
+	npts++;
+    }
+    
+    if (nskipped > 0)
+	G_warning(_("%d points without category. "
+		    "Unable to determine color rules for features without category."),
+		  nskipped);
+    return npts;
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gs2.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/GS2.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gs2.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gs2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,3498 @@
+/*!
+   \file GS2.c
+
+   \brief OGSF library - loading and manipulating surfaces (higher level functions)
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   Plans for handling color maps:
+   NOW:
+   if able to load as unsigned char, make lookup table containing palette
+   otherwise, load directly as packed color, set lookup = NULL
+   MAYBE LATER:
+   if able to load as POSITIVE short, make lookup table containing palette
+   - may want to calculate savings first (ie,  numcells > 32768)
+   (not exactly, it's Friday & time to go home - figure it later)
+   otherwise, load directly as packed color, set lookup = NULL
+   MESSY! - need to fix up!
+
+   (C) 1999-2008 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.
+
+   \author Bill Brown USACERL (1993)
+   \author Pierre de Mouveaux <p_de_mouveaux hotmail.com> (updated October 1999)
+   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <grass/config.h>
+
+#if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
+#include <GL/gl.h>
+#include <GL/glu.h>
+#elif defined(OPENGL_AQUA)
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#endif
+
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/ogsf.h>
+#include <grass/glocale.h>
+
+#include "gsget.h"
+#include "rowcol.h"
+#include "rgbpack.h"
+
+/* Hack to make NVIZ2.2 query functions.("What's Here" and "Look at")
+ * to work.
+ * Uses gs_los_intersect1() instead of gs_los_intersect().
+ * Pierre de Mouveaux - 31 oct. 1999. p_de_mouveaux at hotmail.com.
+ */
+#define NVIZ_HACK 1
+
+int gsd_getViewport(GLint *, GLint *);
+
+/* array of surface ids */
+static int Surf_ID[MAX_SURFS];
+static int Next_surf = 0;
+static int SDref_surf = 0;
+
+/* attributes array */
+static float Default_const[MAX_ATTS];
+static float Default_nulls[MAX_ATTS];
+
+/* largest dimension */
+static float Longdim;
+
+/* N, S, W, E */
+static float Region[4];
+static geoview Gv;
+static geodisplay Gd;
+static struct Cell_head wind;
+static int Buffermode;
+static int Numlights = 0;
+static int Resetlight = 1;
+static int Modelshowing = 0;
+
+void void_func(void)
+{
+    return;
+}
+
+/*!
+   \brief Initialize OGSF library
+
+   Get region settings - wind
+
+   Set Region (NSWE array) and compute scale
+ */
+void GS_libinit(void)
+{
+    static int first = 1;
+
+    G_get_set_window(&wind);
+
+    Region[0] = wind.north;
+    Region[1] = wind.south;
+    Region[2] = wind.west;
+    Region[3] = wind.east;
+
+    /* scale largest dimension to GS_UNIT_SIZE */
+    if ((wind.east - wind.west) > (wind.north - wind.south)) {
+	Longdim = (wind.east - wind.west);
+    }
+    else {
+	Longdim = (wind.north - wind.south);
+    }
+
+    Gv.scale = GS_UNIT_SIZE / Longdim;
+
+    G_debug(1, "GS_libinit(): n=%f s=%f w=%f e=%f scale=%f first=%d",
+	    Region[0], Region[1], Region[2], Region[3], Gv.scale, first);
+    
+    Cxl_func = void_func;
+    Swap_func = void_func;
+
+    
+    if (first) {
+	gs_init();
+    }
+
+    first = 0;
+
+    return;
+}
+
+/*!
+   \brief Get largest dimension
+
+   \param[out] dim dimension
+
+   \return 1
+ */
+int GS_get_longdim(float *dim)
+{
+    *dim = Longdim;
+
+    G_debug(3, "GS_get_longdim(): dim=%g", *dim);
+
+    return (1);
+}
+
+/*!
+   \brief Get 2D region extent
+
+   \param[out] n,s,w,e extent values
+
+   \return 1
+ */
+int GS_get_region(float *n, float *s, float *w, float *e)
+{
+    *n = Region[0];
+    *s = Region[1];
+    *w = Region[2];
+    *e = Region[3];
+
+    return (1);
+}
+
+/*!
+   \brief Set default attributes for map objects
+
+   \param defs attributes array (dim MAX_ATTS)
+   \param null_defs null attributes array (dim MAX_ATTS)
+ */
+void GS_set_att_defaults(float *defs, float *null_defs)
+{
+    int i;
+
+    G_debug(3, "GS_set_att_defaults");
+
+    for (i = 0; i < MAX_ATTS; i++) {
+	Default_const[i] = defs[i];
+	Default_nulls[i] = null_defs[i];
+    }
+
+    return;
+}
+
+/*!
+   Check if surface exists
+
+   \param id surface id
+
+   \return 0 not found
+   \return 1 found
+ */
+int GS_surf_exists(int id)
+{
+    int i, found = 0;
+
+    G_debug(3, "GS_surf_exists(): id=%d", id);
+
+
+    if (NULL == gs_get_surf(id)) {
+	return (0);
+    }
+
+    for (i = 0; i < Next_surf && !found; i++) {
+	if (Surf_ID[i] == id) {
+	    found = 1;
+	}
+    }
+
+    return (found);
+}
+
+/*!
+   \brief Add new surface
+
+   Note that origin has 1/2 cell added to represent center of cells
+   because library assumes that east - west = (cols - 1) * ew_res,
+   since left and right columns are on the edges.
+
+   \return surface id
+   \return -1 on error (MAX_SURFS exceded)
+ */
+int GS_new_surface(void)
+{
+    geosurf *ns;
+
+    G_debug(3, "GS_new_surface():");
+
+    if (Next_surf < MAX_SURFS) {
+	ns = gs_get_new_surface();
+	gs_init_surf(ns, wind.west + wind.ew_res / 2.,
+		     wind.south + wind.ns_res / 2., wind.rows, wind.cols,
+		     wind.ew_res, wind.ns_res);
+	gs_set_defaults(ns, Default_const, Default_nulls);
+
+	/* make default shine current */
+	gs_set_att_src(ns, ATT_SHINE, CONST_ATT);
+
+	Surf_ID[Next_surf] = ns->gsurf_id;
+	++Next_surf;
+
+	G_debug(3, "    id=%d", ns->gsurf_id);
+
+	return (ns->gsurf_id);
+    }
+
+
+
+    return (-1);
+}
+void GS_set_light_reset(int i)
+{
+    Resetlight = i;
+    if (i)
+	Numlights = 0;
+}
+int GS_get_light_reset(void)
+{
+    return Resetlight;
+}
+/*!
+   \brief Add new model light
+
+   \return light model id
+   \return -1 on error (MAX_LIGHTS exceded)
+ */
+int GS_new_light(void)
+{
+    int i;
+
+    if (GS_get_light_reset()) {
+
+	GS_set_light_reset(0);
+
+	for (i = 0; i < MAX_LIGHTS; i++) {
+	    Gv.lights[i].position[X] = Gv.lights[i].position[Y] = 0.0;
+	    Gv.lights[i].position[Z] = 1.0;
+	    Gv.lights[i].position[W] = 0.0;	/* infinite */
+	    Gv.lights[i].color[0] = Gv.lights[i].color[1] =
+		Gv.lights[i].color[2] = 1.0;
+	    Gv.lights[i].ambient[0] = Gv.lights[i].ambient[1] =
+		Gv.lights[i].ambient[2] = 0.2;
+	    Gv.lights[i].shine = 32.0;
+	}
+
+	gsd_init_lightmodel();
+    }
+
+    if (Numlights < MAX_LIGHTS) {
+	gsd_deflight(Numlights + 1, &(Gv.lights[Numlights]));
+	gsd_switchlight(Numlights + 1, 1);
+
+	return ++Numlights;
+    }
+
+    return -1;
+}
+
+/*!
+   \brief Set light position
+
+   \bug I think lights array doesnt match sgi_light array
+
+   \param num light id (starts with 1)
+   \param xpos,ypos,zpos coordinates (model)
+   \param local local coordinate (for viewport)
+ */
+void GS_setlight_position(int num, float xpos, float ypos, float zpos,
+			  int local)
+{
+    if (num) {
+	num -= 1;
+	if (num < Numlights) {
+	    Gv.lights[num].position[X] = xpos;
+	    Gv.lights[num].position[Y] = ypos;
+	    Gv.lights[num].position[Z] = zpos;
+	    Gv.lights[num].position[W] = (float)local;
+
+	    gsd_deflight(num + 1, &(Gv.lights[num]));
+	}
+    }
+
+    return;
+}
+
+
+/*!
+   \brief Get light position
+
+   \param num light id (starts at 1)
+   \param[out] xpos,ypos,zpos coordinates
+   \param[out] local ?
+ */
+void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos,
+			  int *local)
+{
+    if (num) {
+	num -= 1;
+	if (num < Numlights) {
+	    *xpos = Gv.lights[num].position[X];
+	    *ypos = Gv.lights[num].position[Y];
+	    *zpos = Gv.lights[num].position[Z];
+	    *local = (int)Gv.lights[num].position[W];
+
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Set light color
+
+   \param num light id (starts at 1)
+   \param red,green,blue color values (from 0.0 to 1.0)
+ */
+void GS_setlight_color(int num, float red, float green, float blue)
+{
+    if (num) {
+	num -= 1;
+	if (num < Numlights) {
+	    Gv.lights[num].color[0] = red;
+	    Gv.lights[num].color[1] = green;
+	    Gv.lights[num].color[2] = blue;
+
+	    gsd_deflight(num + 1, &(Gv.lights[num]));
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Get light color
+
+   \param num light id (starts at 1)
+   \param[out] red,green,blue color values
+ */
+void GS_getlight_color(int num, float *red, float *green, float *blue)
+{
+    if (num) {
+	num -= 1;
+	if (num < Numlights) {
+	    *red = Gv.lights[num].color[0];
+	    *green = Gv.lights[num].color[1];
+	    *blue = Gv.lights[num].color[2];
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Set light ambient
+
+   Red, green, blue from 0.0 to 1.0
+
+   \param num light id (starts at 1)
+   \param red,green,blue color values
+ */
+void GS_setlight_ambient(int num, float red, float green, float blue)
+{
+    if (num) {
+	num -= 1;
+	if (num < Numlights) {
+	    Gv.lights[num].ambient[0] = red;
+	    Gv.lights[num].ambient[1] = green;
+	    Gv.lights[num].ambient[2] = blue;
+
+	    gsd_deflight(num + 1, &(Gv.lights[num]));
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Get light ambient
+
+   \param num light id (starts at 1)
+   \param[out] red,green,blue color values
+ */
+void GS_getlight_ambient(int num, float *red, float *green, float *blue)
+{
+    if (num) {
+	num -= 1;
+	if (num < Numlights) {
+	    *red = Gv.lights[num].ambient[0];
+	    *green = Gv.lights[num].ambient[1];
+	    *blue = Gv.lights[num].ambient[2];
+	}
+    }
+
+    return;
+}
+
+
+/*!
+   \brief Switch off all lights
+ */
+void GS_lights_off(void)
+{
+    int i;
+
+    for (i = 0; i < Numlights; i++) {
+	gsd_switchlight(i + 1, 0);
+    }
+
+    return;
+}
+
+/*!
+   \brief Switch on all lights
+ */
+void GS_lights_on(void)
+{
+    int i;
+
+    for (i = 0; i < Numlights; i++) {
+	gsd_switchlight(i + 1, 1);
+    }
+
+    return;
+}
+
+/*!
+   \brief Switch on/off light
+
+   \param num light id (starts at 1)
+   \param on non-zero for 'on' otherwise 'off'
+ */
+void GS_switchlight(int num, int on)
+{
+    if (num) {
+	num -= 1;
+
+	if (num < Numlights) {
+	    gsd_switchlight(num + 1, on);
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Check if transparency is set
+
+   \return 0 transparency not set
+   \return 1 transparency is set
+ */
+int GS_transp_is_set(void)
+{
+    return (gs_att_is_set(NULL, ATT_TRANSP) || (FC_GREY == gsd_getfc()));
+}
+
+/*!
+   \brief Retrieves coordinates for lighting model position, at center of view
+
+   \param pos[out] coordinates
+ */
+void GS_get_modelposition1(float pos[])
+{
+    /* TODO: Still needs work to handle other cases */
+    /* this is a quick hack to get lighting adjustments debugged */
+    /*
+       GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], center);
+       GS_v3mult(center, 1000);
+       GS_v3add(center, Gv.from_to[FROM]);
+     */
+
+    gs_get_datacenter(pos);
+    gs_get_data_avg_zmax(&(pos[Z]));
+
+    G_debug(1, "GS_get_modelposition1(): model position: %f %f %f",
+	    pos[X], pos[Y], pos[Z]);
+
+    return;
+}
+
+/*!
+   \brief Retrieves coordinates for lighting model position, at center of view
+
+   Position at nearclip * 2: tried nearclip + siz, but since need to
+   know position to calculate size, have two dependent variables
+   (nearclip * 2) from eye.
+
+   \param siz[out] size
+   \param pos[out] coordinates (X, Y, Z)
+ */
+void GS_get_modelposition(float *siz, float *pos)
+{
+    float dist, near_h, dir[3];
+
+    dist = 2. * Gd.nearclip;
+
+    near_h = 2.0 * tan(4.0 * atan(1.) * Gv.fov / 3600.) * dist;
+    *siz = near_h / 8.0;
+
+    /* prevent clipping - would only happen if fov > ~127 degrees, at
+       fov = 2.0 * atan(2.0) */
+
+    if (*siz > Gd.nearclip) {
+	*siz = Gd.nearclip;
+    }
+
+    GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
+
+    pos[X] = Gv.from_to[FROM][X] + dir[X] * dist;
+    pos[Y] = Gv.from_to[FROM][Y] + dir[Y] * dist;
+    pos[Z] = Gv.from_to[FROM][Z] + dir[Z] * dist;
+
+    return;
+}
+
+
+/*!
+   \brief Set decoration, north arrow ??
+
+   \todo scale used to calculate len of arrow still needs work
+   needs go function that returns center / eye distance
+   gsd_get_los function is not working correctly ??
+
+   \param pt point value in true world coordinates (?)
+   \param id surface id
+   \param[out] pos2 output coordinates
+ */
+void GS_set_Narrow(int *pt, int id, float *pos2)
+{
+    geosurf *gs;
+    float x, y, z;
+    GLdouble modelMatrix[16], projMatrix[16];
+    GLint viewport[4];
+
+    if (GS_get_selected_point_on_surface(pt[X], pt[Y], &id, &x, &y, &z)) {
+	gs = gs_get_surf(id);
+	if (gs) {
+	    z = gs->zmax;
+	    pos2[X] = (float)x - gs->ox + gs->x_trans;
+	    pos2[Y] = (float)y - gs->oy + gs->y_trans;
+	    pos2[Z] = (float)z + gs->z_trans;
+
+	    return;
+	}
+    }
+    else {
+	gs = gs_get_surf(id);
+
+	/* Need to get model matrix, etc 
+	 * to run gluUnProject
+	 */
+	gsd_pushmatrix();
+	gsd_do_scale(1);
+	glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
+	glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+	glGetIntegerv(GL_VIEWPORT, viewport);
+
+	if (gs) {
+	    GLdouble out_near[3], out_far[3];
+	    GLdouble factor;
+	    GLdouble out[3];
+
+	    z = (float)gs->zmax + gs->z_trans;
+
+	    gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 0.,
+			 modelMatrix, projMatrix, viewport,
+			 &out_near[X], &out_near[Y], &out_near[Z]);
+	    gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 1.,
+			 modelMatrix, projMatrix, viewport,
+			 &out_far[X], &out_far[Y], &out_far[Z]);
+
+	    glPopMatrix();
+
+	    factor = (out_near[Z] - z) / (out_near[Z] - out_far[Z]);
+
+	    out[X] = out_near[X] - ((out_near[X] - out_far[X]) * factor);
+	    out[Y] = out_near[Y] - ((out_near[Y] - out_far[Y]) * factor);
+	    out[Z] = z;
+
+	    pos2[X] = (float)out[X];
+	    pos2[Y] = (float)out[Y];
+	    pos2[Z] = (float)out[Z];
+
+	    return;
+
+	}
+    }
+    return;
+}
+
+/*!
+   \brief Draw place marker
+
+   Used to display query point for raster queries.
+
+   \param id surface id
+   \param pt point, X, Y value in true world coordinates
+ */
+void GS_draw_X(int id, float *pt)
+{
+    geosurf *gs;
+    Point3 pos;
+    float siz;
+    gvstyle style;
+
+    if ((gs = gs_get_surf(id))) {
+	GS_get_longdim(&siz);
+	style.size = siz / 200.;
+	pos[X] = pt[X] - gs->ox;
+	pos[Y] = pt[Y] - gs->oy;
+	_viewcell_tri_interp(gs, pos);
+
+	gsd_pushmatrix();
+
+	gsd_do_scale(1);
+	gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
+	gsd_linewidth(1);
+
+	if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
+	    pos[Z] = gs->att[ATT_TOPO].constant;
+	    gs = NULL;		/* tells gpd_obj to use given Z val */
+	}
+	style.color = Gd.bgcol;
+	style.symbol = ST_GYRO;
+	gpd_obj(gs, &style, pos);
+	gsd_flush();
+
+	gsd_popmatrix();
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw line on surface
+
+   \param id surface id
+   \param x1,y1,x2,y2 line nodes
+ */
+void GS_draw_line_onsurf(int id, float x1, float y1, float x2, float y2)
+{
+    float p1[2], p2[2];
+    geosurf *gs;
+
+    if ((gs = gs_get_surf(id))) {
+	p1[X] = x1 - gs->ox;
+	p1[Y] = y1 - gs->oy;
+	p2[X] = x2 - gs->ox;
+	p2[Y] = y2 - gs->oy;
+
+	gsd_pushmatrix();
+
+	gsd_do_scale(1);
+	gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
+	gsd_linewidth(1);
+
+	gsd_color_func(GS_default_draw_color());
+	gsd_line_onsurf(gs, p1, p2);
+
+	gsd_popmatrix();
+	gsd_flush();
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw multiline on surface
+
+   Like above but limits points in line to n or points found in segment,
+   whichever is smaller.
+
+   \param id surface id
+   \param x1,y1,x2,y2 line nodes
+
+   \return number of points used
+ */
+int GS_draw_nline_onsurf(int id, float x1, float y1, float x2, float y2,
+			 float *lasp, int n)
+{
+    float p1[2], p2[2];
+    geosurf *gs;
+    int ret = 0;
+
+    if ((gs = gs_get_surf(id))) {
+	p1[X] = x1 - gs->ox;
+	p1[Y] = y1 - gs->oy;
+	p2[X] = x2 - gs->ox;
+	p2[Y] = y2 - gs->oy;
+
+	gsd_pushmatrix();
+
+	gsd_do_scale(1);
+	gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
+	gsd_linewidth(1);
+	gsd_color_func(GS_default_draw_color());
+	ret = gsd_nline_onsurf(gs, p1, p2, lasp, n);
+	gsd_surf2real(gs, lasp);
+
+	gsd_popmatrix();
+	gsd_flush();
+    }
+
+    return (ret);
+}
+
+/*!
+   \brief Draw flow-line on surace
+
+   This is slow - should be moved to gs_ but GS_ good for testing
+   and useful for app programmer
+
+   \param id surface id
+   \param x,y coordinates of flow-line
+ */
+void GS_draw_flowline_at_xy(int id, float x, float y)
+{
+    geosurf *gs;
+    float nv[3], pdir[2], mult;
+    float p1[2], p2[2], next[2];
+    int i = 0;
+
+    if ((gs = gs_get_surf(id))) {
+	p1[X] = x;
+	p1[Y] = y;
+	/* multiply by 1.5 resolutions to ensure a crossing ? */
+	mult = .1 * (VXRES(gs) > VYRES(gs) ? VXRES(gs) : VYRES(gs));
+
+	GS_coordpair_repeats(p1, p1, 50);
+
+	while (1 == GS_get_norm_at_xy(id, p1[X], p1[Y], nv)) {
+	    if (nv[Z] == 1.0) {
+		if (pdir[X] == 0.0 && pdir[Y] == 0.0) {
+		    break;
+		}
+
+		p2[X] = p1[X] + (pdir[X] * mult);
+		p2[Y] = p1[Y] + (pdir[Y] * mult);
+	    }
+	    else {
+		/* use previous direction */
+		GS_v2norm(nv);
+		p2[X] = p1[X] + (nv[X] * mult);
+		p2[Y] = p1[Y] + (nv[Y] * mult);
+		pdir[X] = nv[X];
+		pdir[Y] = nv[Y];
+	    }
+
+	    if (i > 2000) {
+		break;
+	    }
+
+	    if (GS_coordpair_repeats(p1, p2, 0)) {
+		break;
+	    }
+
+	    /* Think about this: */
+	    /* degenerate line means edge or level edge ? */
+	    /* next is filled with last point drawn */
+	    if (2 > GS_draw_nline_onsurf(id, p1[X], p1[Y],
+					 p2[X], p2[Y], next, 3)) {
+		break;
+	    }
+
+	    p1[X] = next[X];
+	    p1[Y] = next[Y];
+	}
+
+	G_debug(3, "GS_draw_flowline_at_xy(): dir: %f %f", nv[X], nv[Y]);
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw fringe around data (surface) at selected corners
+
+   \param id surface id
+   \param clr color
+   \param elev elevation value
+   \param where nw/ne/sw/se edges - 0 (turn off) 1 (turn on)
+ */
+void GS_draw_fringe(int id, unsigned long clr, float elev, int *where)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_draw_fringe(): id: %d clr: %ld elev %f edges: %d %d %d %d",
+	    id, clr, elev, where[0], where[1], where[2], where[3]);
+    if ((gs = gs_get_surf(id)))
+	gsd_display_fringe(gs, clr, elev, where);
+
+}
+
+
+/*!
+   \brief Draw legend
+
+   \todo add legend from list option
+   make font loading more flexible
+
+   \param name legend name
+   \param fontbase font-base
+   \param size ? 
+   \param flags legend flags
+   \param range values range
+   \param pt ?
+ */
+int GS_draw_legend(const char *name, GLuint fontbase, int size, int *flags,
+		   float *range, int *pt)
+{
+    int list_no;
+
+    list_no = gsd_put_legend(name, fontbase, size, flags, range, pt);
+
+    return (list_no);
+}
+
+/*!
+   \brief Draw pre-defined list
+
+   Uses glFlush() to ensure all drawing is complete
+   before returning
+
+   \param list_id list id
+ */
+void GS_draw_list(GLuint list_id)
+{
+    gsd_calllist(list_id);
+    glFlush();
+    return;
+}
+
+/*!
+   \brief Draw all glLists
+
+   Uses glFlush() to ensure all drawing is complete
+   before returning
+ */
+void GS_draw_all_list(void)
+{
+    gsd_calllists(0);		/* not sure if 0 is right - MN */
+    glFlush();
+    return;
+}
+
+/*!
+   \brief Delete pre-defined list
+
+   \param list_id list id
+ */
+void GS_delete_list(GLuint list_id)
+{
+    gsd_deletelist(list_id, 1);
+
+    return;
+}
+
+/*!
+   \brief Draw lighting model
+ */
+void GS_draw_lighting_model1(void)
+{
+    static float center[3];
+    float tcenter[3];
+
+    if (!Modelshowing) {
+	GS_get_modelposition1(center);
+    }
+
+    GS_v3eq(tcenter, center);
+
+    gsd_zwritemask(0x0);
+    gsd_backface(1);
+
+    gsd_colormode(CM_AD);
+    gsd_shademodel(DM_GOURAUD);
+    gsd_pushmatrix();
+    gsd_do_scale(1);
+
+    if (Gv.vert_exag) {
+	tcenter[Z] *= Gv.vert_exag;
+	gsd_scale(1.0, 1.0, 1. / Gv.vert_exag);
+    }
+
+    gsd_drawsphere(tcenter, 0xDDDDDD, (float)(Longdim / 10.));
+    gsd_popmatrix();
+    Modelshowing = 1;
+
+    gsd_backface(0);
+    gsd_zwritemask(0xffffffff);
+
+    return;
+}
+
+/*!
+   \brief Draw lighting model
+
+   Just turn off any cutting planes and draw it just outside near
+   clipping plane, since lighting is infinite now
+ */
+void GS_draw_lighting_model(void)
+{
+    static float center[3], size;
+    float tcenter[3], tsize;
+    int i, wason[MAX_CPLANES];
+
+    gsd_get_cplanes_state(wason);
+
+    for (i = 0; i < MAX_CPLANES; i++) {
+	if (wason[i]) {
+	    gsd_cplane_off(i);
+	}
+    }
+
+
+    if (!Modelshowing) {
+	GS_get_modelposition(&size, center);
+    }
+
+    GS_v3eq(tcenter, center);
+    tsize = size;
+
+    gsd_zwritemask(0x0);
+    gsd_backface(1);
+
+    gsd_colormode(CM_DIFFUSE);
+    gsd_shademodel(DM_GOURAUD);
+    gsd_pushmatrix();
+    gsd_drawsphere(tcenter, 0xDDDDDD, tsize);
+    gsd_popmatrix();
+    Modelshowing = 1;
+
+    gsd_backface(0);
+    gsd_zwritemask(0xffffffff);
+
+    for (i = 0; i < MAX_CPLANES; i++) {
+	if (wason[i]) {
+	    gsd_cplane_on(i);
+	}
+    }
+
+    gsd_flush();
+
+    return;
+}
+
+/*!
+   \brief Update current mask
+
+   May be called to update total mask for a surface at convenient times
+   instead of waiting until ready to redraw surface
+
+   \param id surface id
+
+   \return ?
+ */
+int GS_update_curmask(int id)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+    return (gs_update_curmask(gs));
+}
+
+/*!
+   \brief Check if point is masked ?
+
+   \param id surface id
+   \param pt point
+
+   \return 1 masked
+   \return 0 not masked
+   \return -1 on error, invalid surface id
+ */
+int GS_is_masked(int id, float *pt)
+{
+    geosurf *gs;
+    Point3 tmp;
+
+    if ((gs = gs_get_surf(id))) {
+	tmp[X] = pt[X] - gs->ox;
+	tmp[Y] = pt[Y] - gs->oy;
+
+	return (gs_point_is_masked(gs, tmp));
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Unset Scaled Difference surface
+ */
+void GS_unset_SDsurf(void)
+{
+    gsdiff_set_SDref(NULL);
+    SDref_surf = 0;
+
+    return;
+}
+
+/*!
+   \brief Set surface as Scaled Difference surface
+
+   \param id surface id
+
+   \return 1 on success
+   \return 0 on error, invalid surface id
+ */
+int GS_set_SDsurf(int id)
+{
+    geosurf *gs;
+
+    if ((gs = gs_get_surf(id))) {
+	gsdiff_set_SDref(gs);
+	SDref_surf = id;
+
+	return (1);
+    }
+
+    return (0);
+}
+
+/*!
+   \brief Set ?
+
+   \param scale scale value
+
+   \return 1
+ */
+int GS_set_SDscale(float scale)
+{
+    gsdiff_set_SDscale(scale);
+
+    return (1);
+}
+
+/*!
+   \brief Get ?
+
+   \param[out] id ?
+
+   \return 1 on success
+   \return 0 on error
+ */
+int GS_get_SDsurf(int *id)
+{
+    geosurf *gs;
+
+    if ((gs = gsdiff_get_SDref())) {
+	*id = SDref_surf;
+
+	return (1);
+    }
+
+    return (0);
+}
+
+/*!
+   \brief Get ?
+
+   \param[out] scale value
+
+   \return 1
+ */
+int GS_get_SDscale(float *scale)
+{
+    *scale = gsdiff_get_SDscale();
+
+    return (1);
+}
+
+/*!
+   \brief Update normals
+
+   \param id surface id
+
+   \return ?
+ */
+int GS_update_normals(int id)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    return (gs_calc_normals(gs));
+}
+
+/*!
+   \brief Get attributes
+
+   \param id surface id
+   \param att
+   \param[out] set
+   \param[out] constant
+   \param[out] mapname
+
+   \return 1 on success
+   \return -1 on error (invalid surface id)
+ */
+int GS_get_att(int id, int att, int *set, float *constant, char *mapname)
+{
+    int src;
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+    if (gs) {
+	if (-1 != (src = gs_get_att_src(gs, att))) {
+	    *set = src;
+
+	    if (src == CONST_ATT) {
+		*constant = gs->att[att].constant;
+	    }
+	    else if (src == MAP_ATT) {
+		strcpy(mapname, gsds_get_name(gs->att[att].hdata));
+	    }
+
+	    return (1);
+	}
+
+	return (-1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get surface category on given position
+
+   Prints "no data" or a description (i.e., "coniferous forest") to
+   <i>catstr</i>. Usually call after GS_get_selected_point_on_surface().
+   Define <i>att</i> as MAP_ATT
+
+   \todo Allocate catstr using G_store()
+   
+   \param id surface id
+   \param att attribute id (MAP_ATT)
+   \param catstr cat string (must be allocated, dim?)
+   \param x,y real coordinates
+
+   \return -1 if no category info or point outside of window
+   \return 1 on success
+*/
+int GS_get_cat_at_xy(int id, int att, char *catstr, float x, float y)
+{
+    int offset, drow, dcol, vrow, vcol;
+    float ftmp, pt[3];
+    typbuff *buff;
+    geosurf *gs;
+
+    *catstr = '\0';
+    gs = gs_get_surf(id);
+
+    if (NULL == gs) {
+	return -1;
+    }
+
+    pt[X] = x;
+    pt[Y] = y;
+
+    gsd_real2surf(gs, pt);
+    if (gs_point_is_masked(gs, pt)) {
+	return -1;
+    }
+
+    if (!in_vregion(gs, pt)) {
+	return -1;
+    }
+
+    if (MAP_ATT != gs_get_att_src(gs, att)) {
+	sprintf(catstr, _("no category info"));
+	return -1;
+    }
+
+    buff = gs_get_att_typbuff(gs, att, 0);
+
+    vrow = Y2VROW(gs, pt[Y]);
+    vcol = X2VCOL(gs, pt[X]);
+    drow = VROW2DROW(gs, vrow);
+    dcol = VCOL2DCOL(gs, vcol);
+
+    offset = DRC2OFF(gs, drow, dcol);
+    
+    if (GET_MAPATT(buff, offset, ftmp)) {
+	return
+	    (Gs_get_cat_label(gsds_get_name(gs->att[att].hdata),
+			      drow, dcol, catstr));
+    }
+
+    sprintf(catstr, _("no data"));
+
+    return 1;
+}
+
+/*!
+   \brief Get surface normal at x,y (real coordinates)
+
+   Usually call after GS_get_selected_point_on_surface()
+
+   \param id surface id
+   \param x,y real coordinates
+   \param[out] nv surface normal
+
+   \return -1 if point outside of window or masked
+   \return 1 on success
+ */
+int GS_get_norm_at_xy(int id, float x, float y, float *nv)
+{
+    int offset, drow, dcol, vrow, vcol;
+    float pt[3];
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    if (NULL == gs) {
+	return (-1);
+    }
+
+    if (gs->norm_needupdate) {
+	gs_calc_normals(gs);
+    }
+
+    pt[X] = x;
+    pt[Y] = y;
+
+    gsd_real2surf(gs, pt);
+    if (gs_point_is_masked(gs, pt)) {
+	return (-1);
+    }
+
+    if (!in_vregion(gs, pt)) {
+	return (-1);
+    }
+
+    vrow = Y2VROW(gs, pt[Y]);
+    vcol = X2VCOL(gs, pt[X]);
+    drow = VROW2DROW(gs, vrow);
+    dcol = VCOL2DCOL(gs, vcol);
+
+    offset = DRC2OFF(gs, drow, dcol);
+
+    if (gs->norms) {
+	FNORM(gs->norms[offset], nv);
+    }
+    else {
+	/* otherwise must be a constant */
+	nv[0] = 0.0;
+	nv[1] = 0.0;
+	nv[2] = 1.0;
+    }
+
+    return (1);
+}
+
+/*!
+   \brief Get RGB color at given point
+
+   Colors are translated to rgb and returned as Rxxx Gxxx Bxxx Usually
+   call after GS_get_selected_point_on_surface().
+
+   Prints NULL or the value (i.e., "921.5") to valstr
+
+   \param id surface id
+   \param att attribute id
+   \param[out] valstr value string (allocated, dim?)
+   \param x,y real coordinates
+   
+   \return -1 if point outside of window or masked
+   \return 1 on success
+ */
+int GS_get_val_at_xy(int id, int att, char *valstr, float x, float y)
+{
+    int offset, drow, dcol, vrow, vcol;
+    float ftmp, pt[3];
+    typbuff *buff;
+    geosurf *gs;
+
+    *valstr = '\0';
+    gs = gs_get_surf(id);
+    
+    if (NULL == gs) {
+	return -1;
+    }
+
+    pt[X] = x;
+    pt[Y] = y;
+
+    gsd_real2surf(gs, pt);
+
+    if (gs_point_is_masked(gs, pt)) {
+	return -1;
+    }
+
+    if (!in_vregion(gs, pt)) {
+	return (-1);
+    }
+
+    if (CONST_ATT == gs_get_att_src(gs, att)) {
+	if (att == ATT_COLOR) {
+	    int r, g, b, i;
+
+	    i = gs->att[att].constant;
+	    sprintf(valstr, "R%d G%d B%d",
+		    INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
+	}
+	else {
+	    sprintf(valstr, "%f", gs->att[att].constant);
+	}
+
+	return 1;
+    }
+    else if (MAP_ATT != gs_get_att_src(gs, att)) {
+	return -1;
+    }
+
+    buff = gs_get_att_typbuff(gs, att, 0);
+
+    vrow = Y2VROW(gs, pt[Y]);
+    vcol = X2VCOL(gs, pt[X]);
+    drow = VROW2DROW(gs, vrow);
+    dcol = VCOL2DCOL(gs, vcol);
+
+    offset = DRC2OFF(gs, drow, dcol);
+
+    if (GET_MAPATT(buff, offset, ftmp)) {
+	if (att == ATT_COLOR) {
+	    int r, g, b, i;
+
+	    i = gs_mapcolor(gs_get_att_typbuff(gs, ATT_COLOR, 0),
+			    &(gs->att[ATT_COLOR]), offset);
+	    sprintf(valstr, "R%d G%d B%d",
+		    INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
+	}
+	else {
+	    sprintf(valstr, "%f", ftmp);
+	}
+
+	return (1);
+    }
+
+    sprintf(valstr, "NULL");
+
+    return (1);
+}
+
+/*!
+   \brief Unset attribute
+
+   \param id surface id
+   \param att attribute id
+
+   \return ?
+ */
+int GS_unset_att(int id, int att)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+    gs->mask_needupdate = 1;
+
+    return (gs_set_att_src(gs, att, NOTSET_ATT));
+}
+
+/*!
+   \brief Set attribute constant
+
+   \param id surface id
+   \param att attribute id
+   \param constant value
+
+   \return ?
+ */
+int GS_set_att_const(int id, int att, float constant)
+{
+    geosurf *gs;
+    int ret;
+
+    gs = gs_get_surf(id);
+    ret = (gs_set_att_const(gs, att, constant));
+
+    Gs_update_attrange(gs, att);
+
+    return (ret);
+}
+
+/*!
+   \brief Set mask mode
+
+   Mask attribute special: constant is set to indicate invert or no
+
+   \param id surface id
+   \param mode id
+
+   \return mode id
+   \return -1 on error (invalid surface id)
+ */
+int GS_set_maskmode(int id, int mode)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	gs->att[ATT_MASK].constant = mode;
+	gs->mask_needupdate = 1;
+
+	return (mode);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get mask mode
+
+   \param id surface id
+   \param[out] mode id
+
+   \return 1 on success
+   \return -1 on error (invalid surface id)
+ */
+int GS_get_maskmode(int id, int *mode)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	*mode = gs->att[ATT_MASK].constant;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set client data
+
+   \param id surface id
+   \param clientd pointer to client data struct
+
+   \return 1 on success
+   \return -1 on error (invalid surface id)
+ */
+int GS_Set_ClientData(int id, void *clientd)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+    if (gs) {
+	gs->clientdata = clientd;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get client data
+
+   \param id surface id
+
+   \return pointer to client data
+   \return NULL on error
+ */
+void *GS_Get_ClientData(int id)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+    if (gs) {
+	return (gs->clientdata);
+    }
+
+    return (NULL);
+}
+
+/*!
+   \brief Get number of surfaces
+
+   \return number of surfaces
+ */
+int GS_num_surfs(void)
+{
+    return (gs_num_surfaces());
+}
+
+/*!
+   \brief Get surface list
+
+   Must be freed when not neeed!
+
+   \param[out] numsurf number of available surfaces
+
+   \return pointer to surface array
+   \return NULL on error
+ */
+int *GS_get_surf_list(int *numsurfs)
+{
+    int i, *ret;
+
+    *numsurfs = Next_surf;
+
+    if (Next_surf) {
+	ret = (int *)G_malloc(Next_surf * sizeof(int));
+
+	for (i = 0; i < Next_surf; i++) {
+	    ret[i] = Surf_ID[i];
+	}
+
+	return (ret);
+    }
+
+    return (NULL);
+}
+
+/*!
+   \brief Delete surface
+
+   \param id surface id
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GS_delete_surface(int id)
+{
+    int i, j, found;
+    
+    found = FALSE;
+    
+    G_debug(1, "GS_delete_surface(): id=%d", id);
+    
+    if (GS_surf_exists(id)) {
+	gs_delete_surf(id);
+	for (i = 0; i < Next_surf && !found; i++) {
+	    if (Surf_ID[i] == id) {
+		found = TRUE;
+
+		for (j = i; j < Next_surf; j++) {
+		    Surf_ID[j] = Surf_ID[j + 1];
+		}
+	    }
+	}
+	
+	gv_update_drapesurfs();
+
+	if (found) {
+	    --Next_surf;
+	    return 1;
+	}
+    }
+
+    return -1;
+}
+
+
+/*!
+   \brief Load raster map as attribute
+
+   \param id surface id
+   \param filename filename
+   \param att attribute descriptor
+
+   \return -1 on error (invalid surface id)
+   \return ?
+ */
+int GS_load_att_map(int id, const char *filename, int att)
+{
+    geosurf *gs;
+    unsigned int changed;
+    unsigned int atty;
+    const char *mapset;
+    struct Cell_head rast_head;
+    int reuse, begin, hdata, ret, neg, has_null;
+    typbuff *tbuff;
+
+    G_debug(3, "GS_load_att_map(): map=%s", filename);
+
+    reuse = ret = neg = has_null = 0;
+    gs = gs_get_surf(id);
+
+    if (NULL == gs) {
+	return -1;
+    }
+
+    gs->mask_needupdate = (ATT_MASK == att || ATT_TOPO == att ||
+			   (gs->nz_topo && ATT_TOPO == att) ||
+			   (gs->nz_color && ATT_COLOR == att));
+
+    gs_set_att_src(gs, att, MAP_ATT);
+
+    /* Check against maps already loaded in memory   */
+    /* if to be color attribute:
+       - if packed color for another surface, OK to reuse
+       - if unchanged, ok to reuse IF it's of type char (will have lookup)
+     */
+    begin = hdata = 1;
+
+    /* Get MAPSET to ensure names are fully qualified */
+    mapset = G_find_raster2(filename, "");
+    if (mapset == NULL) {
+	/* Check for valid filename */
+	G_warning("Raster map <%s> not found", filename);
+	return -1;
+    }
+    
+    /* Check to see if map is in Region */
+    Rast_get_cellhd(filename, mapset, &rast_head);
+    if (rast_head.north <= wind.south ||
+	rast_head.south >= wind.north ||
+	rast_head.east <= wind.west || rast_head.west >= wind.east) {
+
+	G_warning(_("Raster map <%s> is outside of current region. Load failed."),
+		  G_fully_qualified_name(filename, mapset));
+    }
+
+    while (!reuse && (0 < hdata)) {
+	changed = CF_COLOR_PACKED;
+	atty = ATTY_FLOAT | ATTY_CHAR | ATTY_INT | ATTY_SHORT | ATTY_MASK;
+
+	if (0 < (hdata = gsds_findh(filename, &changed, &atty, begin))) {
+
+	    G_debug(3, "GS_load_att_map(): %s already has data handle %d.CF=%x",
+		    filename, hdata, changed);
+
+	    /* handle found */
+	    if (ATT_COLOR == att) {
+		if ((changed == CF_COLOR_PACKED) ||
+		    (!changed && atty == ATTY_CHAR)) {
+		    reuse = 1;
+		}
+	    }
+	    else if (atty == ATTY_MASK && att != ATT_MASK) {
+		reuse = 0;
+		/* should also free mask data & share new - but need backward
+		   reference? */
+	    }
+	    else if (!changed) {
+		reuse = 1;
+	    }
+	}
+
+	begin = 0;
+    }
+
+    if (reuse) {
+	gs->att[att].hdata = hdata;
+	gs_set_att_type(gs, att, atty);	/* ?? */
+
+	/* free lookup  & set to NULL! */
+	if (atty == ATTY_INT) {
+	    if (gs->att[att].lookup) {
+		free(gs->att[att].lookup);
+		gs->att[att].lookup = NULL;
+	    }
+	}
+	/* TODO: FIX THIS stuff with lookup sharing! */
+
+	G_debug(3, "GS_load_att_map(): %s is being reused. hdata=%d",
+		filename, hdata);
+    }
+    else {
+	G_debug(3, "GS_load_att_map(): %s not loaded in correct form - loading now",
+		filename);
+
+	/* not loaded - need to get new dataset handle */
+	gs->att[att].hdata = gsds_newh(filename);
+
+	tbuff = gs_get_att_typbuff(gs, att, 1);
+
+	/* TODO: Provide mechanism for loading certain attributes at
+	   specified sizes, allow to scale or cap, or scale non-zero */
+	if (ATT_MASK == att) {
+	    atty = ATTY_MASK;
+	}
+	else {
+	    atty = Gs_numtype(filename, &neg);
+	}
+
+#ifdef MAYBE_LATER
+	if (att == ATT_COLOR && atty == ATTY_SHORT) {
+	    atty = (neg ? ATTY_INT : ATTY_SHORT);
+	}
+#endif
+
+	if (att == ATT_COLOR && atty == ATTY_SHORT) {
+	    atty = ATTY_INT;
+	}
+
+	if (0 == gs_malloc_att_buff(gs, att, ATTY_NULL)) {
+	    G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
+	}
+
+	switch (atty) {
+	case ATTY_MASK:
+	    if (0 == gs_malloc_att_buff(gs, att, ATTY_MASK)) {
+		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
+	    }
+
+	    ret = Gs_loadmap_as_bitmap(&wind, filename, tbuff->bm);
+	    
+	    break;
+	case ATTY_CHAR:
+	    if (0 == gs_malloc_att_buff(gs, att, ATTY_CHAR)) {
+		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
+	    }
+
+	    ret = Gs_loadmap_as_char(&wind, filename, tbuff->cb,
+				     tbuff->nm, &has_null);
+
+	    break;
+	case ATTY_SHORT:
+	    if (0 == gs_malloc_att_buff(gs, att, ATTY_SHORT)) {
+		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
+	    }
+
+	    ret = Gs_loadmap_as_short(&wind, filename, tbuff->sb,
+				      tbuff->nm, &has_null);
+	    break;
+	case ATTY_FLOAT:
+	    if (0 == gs_malloc_att_buff(gs, att, ATTY_FLOAT)) {
+		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
+	    }
+
+	    ret = Gs_loadmap_as_float(&wind, filename, tbuff->fb,
+				      tbuff->nm, &has_null);
+
+	    break;
+	case ATTY_INT:
+	default:
+	    if (0 == gs_malloc_att_buff(gs, att, ATTY_INT)) {
+		G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
+	    }
+
+	    ret = Gs_loadmap_as_int(&wind, filename, tbuff->ib,
+				    tbuff->nm, &has_null);
+	    break;
+
+	}			/* Done with switch */
+
+	if (ret == -1) {
+	    gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
+	    return -1;
+	}
+
+	G_debug(4, "  has_null=%d", has_null);
+
+	if (!has_null) {
+	    gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
+	}
+	else {
+	    gs_update_curmask(gs);
+	}
+
+    }				/* end if not reuse */
+
+    if (ATT_COLOR == att) {
+#ifdef MAYBE_LATER
+	if (ATTY_INT == atty) {
+	    Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
+	    gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
+	    gs->att[att].lookup = NULL;
+	}
+	else {
+	    gs_malloc_lookup(gs, att);
+	    Gs_build_lookup(filename, gs->att[att].lookup);
+	}
+#else
+
+	if (ATTY_CHAR == atty) {
+	    if (!gs->att[att].lookup) {
+		/* might already exist if reusing */
+		gs_malloc_lookup(gs, att);
+		Gs_build_256lookup(filename, gs->att[att].lookup);
+	    }
+	}
+	else if (ATTY_FLOAT == atty) {
+	    if (!reuse) {
+		if (0 == gs_malloc_att_buff(gs, att, ATTY_INT)) {
+		    G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
+		}
+
+		Gs_pack_colors_float(filename, tbuff->fb, tbuff->ib,
+				     gs->rows, gs->cols);
+		gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
+		gsds_free_data_buff(gs->att[att].hdata, ATTY_FLOAT);
+		gs->att[att].lookup = NULL;
+	    }
+	}
+	else {
+	    if (!reuse) {
+		Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
+		gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
+		gs->att[att].lookup = NULL;
+	    }
+	}
+#endif
+    }
+
+    if (ATT_TOPO == att) {
+	gs_init_normbuff(gs);
+	/* S_DIFF: should also check here to see if this surface is a
+	   reference surface for scaled differences, if so update references
+	   to it */
+    }
+
+    if (ret < 0) {
+	G_warning(_("Loading failed"));
+    }
+
+    if (-1 == Gs_update_attrange(gs, att)) {
+	G_warning(_("Error finding range"));
+    }
+
+    return ret;
+}
+
+/*!
+   \brief Draw surface
+
+   \param id surface id
+ */
+void GS_draw_surf(int id)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_draw_surf(): id=%d", id);
+
+    gs = gs_get_surf(id);
+    if (gs) {
+	gsd_shademodel(gs->draw_mode & DM_GOURAUD);
+
+	if (gs->draw_mode & DM_POLY) {
+	    gsd_surf(gs);
+	}
+
+	if (gs->draw_mode & DM_WIRE) {
+	    gsd_wire_surf(gs);
+	}
+
+	/* TODO: write wire/poly draw routines */
+	if (gs->draw_mode & DM_WIRE_POLY) {
+	    gsd_surf(gs);
+	    gsd_wire_surf(gs);
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw surface wire
+
+   Overrides draw_mode for fast display
+
+   \param id surface id
+ */
+void GS_draw_wire(int id)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_draw_wire(): id=%d", id);
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	gsd_wire_surf(gs);
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw all wires
+
+   Overrides draw_mode for fast display
+ */
+void GS_alldraw_wire(void)
+{
+    geosurf *gs;
+    int i;
+
+    for (i = 0; i < Next_surf; i++) {
+	if ((gs = gs_get_surf(Surf_ID[i]))) {
+	    gsd_wire_surf(gs);
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw all surfaces
+ */
+void GS_alldraw_surf(void)
+{
+    int i;
+
+    for (i = 0; i < Next_surf; i++) {
+	GS_draw_surf(Surf_ID[i]);
+    }
+
+    return;
+}
+
+/*!
+   \brief Set Z exag for surface
+
+   \param id surface id
+   \param exag z-exag value
+ */
+void GS_set_exag(int id, float exag)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_set_exag");
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	if (gs->z_exag != exag) {
+	    gs->norm_needupdate = 1;
+	}
+
+	gs->z_exag = exag;
+    }
+
+    return;
+}
+
+/*!
+   \brief Set global z-exag value
+
+   \param exag exag value to be set up
+ */
+void GS_set_global_exag(float exag)
+{
+
+    G_debug(3, "GS_set_global_exag");
+
+    Gv.vert_exag = exag;
+    /* GL_NORMALIZE */
+    /* Only need to update norms gs_norms.c
+     * if exag is used in norm equation which
+     * it is not! If GL_NORMALIZE is disabled
+     * will need to include.
+     gs_setall_norm_needupdate();
+     */
+
+    return;
+}
+
+/*!
+   \brief Get global z-exag value
+
+   \return value
+ */
+float GS_global_exag(void)
+{
+    G_debug(3, "GS_global_exag(): %g", Gv.vert_exag);
+
+    return (Gv.vert_exag);
+}
+
+/*!
+   \brief Set wire color
+
+   \todo error-handling
+
+   \param id surface id
+   \param colr color value
+ */
+void GS_set_wire_color(int id, int colr)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_set_wire_color");
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	gs->wire_color = colr;
+    }
+
+    return;
+}
+
+/*!
+   \brief Get wire color
+
+   \param id surface id
+   \param[out] colr color value
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GS_get_wire_color(int id, int *colr)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	*colr = gs->wire_color;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set all draw-modes
+
+   \param mode mode id
+
+   \return 0 on success
+   \return -1 on error
+ */
+int GS_setall_drawmode(int mode)
+{
+    int i;
+
+    for (i = 0; i < Next_surf; i++) {
+	if (0 != GS_set_drawmode(Surf_ID[i], mode)) {
+	    return (-1);
+	}
+    }
+
+    return (0);
+}
+
+/*!
+   \brief Set draw mode
+
+   \param id surface id
+   \param mode mode type(s)
+
+   \return 0 on success
+   \return -1 on error (invalid surface id)
+ */
+int GS_set_drawmode(int id, int mode)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_set_drawmode(): id=%d mode=%d", id, mode);
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	gs->draw_mode = mode;
+
+	return (0);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get draw mode
+
+   \param id surface id
+   \param[out] mode mode id
+
+   \return 1 on success
+   \return -1 on error (invalid surface id)
+ */
+int GS_get_drawmode(int id, int *mode)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	*mode = gs->draw_mode;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set no-zero ?
+
+   \param id surface id
+   \param att attribute id
+   \param mode mode id
+ */
+void GS_set_nozero(int id, int att, int mode)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_set_nozero");
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	if (att == ATT_TOPO) {
+	    gs->nz_topo = mode;
+	    gs->mask_needupdate = 1;
+	}
+
+	if (att == ATT_COLOR) {
+	    gs->nz_color = mode;
+	    gs->mask_needupdate = 1;
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Get no-zero ?
+
+   \param id surface id
+   \param att attribute id
+   \param[out] mode mode id
+
+   \return -1 on error (invalid surface id)
+   \return 1 on success
+ */
+int GS_get_nozero(int id, int att, int *mode)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_set_nozero");
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	if (att == ATT_TOPO) {
+	    *mode = gs->nz_topo;
+	}
+	else if (att == ATT_COLOR) {
+	    *mode = gs->nz_color;
+	}
+	else {
+	    return (-1);
+	}
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set all draw resolutions
+
+   \param xres,yres x/y resolution value
+   \param xwire,ywire x/y wire value
+
+   \return 0 on success
+   \return -1 on error
+ */
+int GS_setall_drawres(int xres, int yres, int xwire, int ywire)
+{
+    int i;
+
+    for (i = 0; i < Next_surf; i++) {
+	if (0 != GS_set_drawres(Surf_ID[i], xres, yres, xwire, ywire)) {
+	    return (-1);
+	}
+    }
+
+    return (0);
+}
+
+/*!
+   \brief Set draw resolution for surface
+
+   \param id surface id
+   \param xres,yres x/y resolution value
+   \param xwire,ywire x/y wire value
+
+   \return -1 on error
+   \return 0 on success
+ */
+int GS_set_drawres(int id, int xres, int yres, int xwire, int ywire)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_set_drawres() id=%d xyres=%d/%d xywire=%d/%d",
+	    id, xres, yres, xwire, ywire);
+
+    if (xres < 1 || yres < 1 || xwire < 1 || ywire < 1) {
+	return (-1);
+    }
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	if (gs->x_mod != xres || gs->y_mod != yres) {
+	    gs->norm_needupdate = 1;
+	}
+
+	gs->x_mod = xres;
+	gs->y_mod = yres;
+	gs->x_modw = xwire;
+	gs->y_modw = ywire;
+    }
+
+    return (0);
+}
+
+/*!
+   \brief Get draw resolution of surface
+
+   \param id surface id
+   \param[out] xres,yres x/y resolution value
+   \param[out] xwire,ywire x/y wire value
+ */
+void GS_get_drawres(int id, int *xres, int *yres, int *xwire, int *ywire)
+{
+    geosurf *gs;
+
+    G_debug(3, "GS_get_drawres");
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	*xres = gs->x_mod;
+	*yres = gs->y_mod;
+	*xwire = gs->x_modw;
+	*ywire = gs->y_modw;
+    }
+
+    return;
+}
+
+/*!
+   \brief Get dimension of surface
+
+   \param id surface id
+   \param[out] rows,cols number of rows/cols
+ */
+void GS_get_dims(int id, int *rows, int *cols)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	*rows = gs->rows;
+	*cols = gs->cols;
+    }
+
+    return;
+}
+
+/*!
+   \brief Get exag-value guess
+
+   Use no_zero range because if zero IS data, then range won't be that
+   much off (it's just a GUESS, after all), but if zero is NO data, could
+   drastically affect guess
+
+   \param id surface id
+   \param[out] exag exag value
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GS_get_exag_guess(int id, float *exag)
+{
+    geosurf *gs;
+    float guess;
+
+    gs = gs_get_surf(id);
+    guess = 1.0;
+
+    /* if gs is type const return guess = 1.0 */
+    if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
+	*exag = guess;
+	return (1);
+    }
+
+    if (gs) {
+	if (gs->zrange_nz == 0.0) {
+	    *exag = 0.0;
+
+	    return (1);
+	}
+
+	G_debug(3, "GS_get_exag_guess(): %f %f", gs->zrange_nz, Longdim);
+
+	while (gs->zrange_nz * guess / Longdim >= .25) {
+	    guess *= .1;
+
+	    G_debug(3, "GS_get_exag_guess(): %f", guess);
+	}
+
+	while (gs->zrange_nz * guess / Longdim < .025) {
+	    guess *= 10.;
+
+	    G_debug(3, "GS_get_exag_guess(): %f", guess);
+	}
+
+	*exag = guess;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get Z extents for all loaded surfaces
+
+   Treating zeros as "no data"
+
+   \param[out] min min value
+   \param[out] max max value
+ */
+void GS_get_zrange_nz(float *min, float *max)
+{
+    int i, first = 1;
+    geosurf *gs;
+
+    for (i = 0; i < Next_surf; i++) {
+	if ((gs = gs_get_surf(Surf_ID[i]))) {
+	    if (first) {
+		first = 0;
+		*min = gs->zmin_nz;
+		*max = gs->zmax_nz;
+	    }
+
+	    if (gs->zmin_nz < *min) {
+		*min = gs->zmin_nz;
+	    }
+
+	    if (gs->zmax_nz > *max) {
+		*max = gs->zmax_nz;
+	    }
+	}
+    }
+
+    G_debug(3, "GS_get_zrange_nz(): min=%g max=%g", *min, *max);
+
+    return;
+}
+
+/*!
+   \brief Set translation (surface position)
+
+   \param id surface id
+   \param xtrans,ytrans,ztrans translation values
+ */
+void GS_set_trans(int id, float xtrans, float ytrans, float ztrans)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	gs->x_trans = xtrans;
+	gs->y_trans = ytrans;
+	gs->z_trans = ztrans;
+    }
+
+    G_debug(3, "GS_set_trans(): id=%d, x=%f, y=%f, z=%f",
+	    id, xtrans, ytrans, ztrans);
+
+    return;
+}
+
+/*!
+   \brief Get translation values (surface position)
+
+   \param id surface id
+   \param[out] xtrans,ytrans,ztrans trans values
+ */
+void GS_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
+{
+    geosurf *gs;
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	*xtrans = gs->x_trans;
+	*ytrans = gs->y_trans;
+	*ztrans = gs->z_trans;
+    }
+
+    G_debug(3, "GS_get_trans: id=%d, x=%f, y=%f, z=%f",
+	    id, *xtrans, *ytrans, *ztrans);
+
+    return;
+}
+
+
+/*!
+   \brief Get default draw color
+
+   \return color value
+ */
+unsigned int GS_default_draw_color(void)
+{
+
+    G_debug(3, "GS_default_draw_color");
+
+    return ((unsigned int)Gd.bgcol);
+}
+
+/*!
+   \brief Get background color
+
+   \return color value
+ */
+unsigned int GS_background_color(void)
+{
+    return ((unsigned int)Gd.bgcol);
+}
+
+/*!
+   \brief Sets which buffer to draw to
+
+   \param where GSD_BOTH, GSD_FRONT, GSD_BACK
+ */
+void GS_set_draw(int where)
+{
+    Buffermode = where;
+
+    switch (where) {
+    case GSD_BOTH:
+	gsd_frontbuffer(1);
+	gsd_backbuffer(1);
+
+	break;
+    case GSD_FRONT:
+	gsd_frontbuffer(1);
+	gsd_backbuffer(0);
+
+	break;
+    case GSD_BACK:
+    default:
+	gsd_frontbuffer(0);
+	gsd_backbuffer(1);
+
+	break;
+    }
+
+    return;
+}
+
+/*
+   \brief Ready to draw
+ */
+void GS_ready_draw(void)
+{
+
+    G_debug(3, "GS_ready_draw");
+
+    gsd_set_view(&Gv, &Gd);
+
+    return;
+}
+
+/*!
+   \brief Draw done, swap buffers
+ */
+void GS_done_draw(void)
+{
+
+    G_debug(3, "GS_done_draw");
+
+    if (GSD_BACK == Buffermode) {
+	gsd_swapbuffers();
+    }
+
+    gsd_flush();
+
+    return;
+}
+
+/*!
+   \brief Set focus
+
+   \param realto real coordinates to
+ */
+void GS_set_focus(float *realto)
+{
+
+    G_debug(3, "GS_set_focus(): %f,%f,%f", realto[0], realto[1], realto[2]);
+
+    Gv.infocus = 1;
+    GS_v3eq(Gv.real_to, realto);
+
+    gsd_set_view(&Gv, &Gd);
+
+    return;
+}
+
+/*!
+   \brief Set real focus
+
+   \param realto real coordinates to
+ */
+void GS_set_focus_real(float *realto)
+{
+
+    G_get_set_window(&wind);
+    realto[X] = realto[X] - wind.west - (wind.ew_res / 2.);
+    realto[Y] = realto[Y] - wind.south - (wind.ns_res / 2.);
+
+    Gv.infocus = 1;
+    GS_v3eq(Gv.real_to, realto);
+
+    gsd_set_view(&Gv, &Gd);
+
+    return;
+}
+
+
+/*!
+   \brief Get focus
+
+   OK to call with NULL argument if just want to check state
+
+   \param realto real coordinates to
+
+   \return ?
+ */
+int GS_get_focus(float *realto)
+{
+
+    G_debug(3, "GS_get_focus");
+
+    if (Gv.infocus) {
+	if (realto) {
+	    GS_v3eq(realto, Gv.real_to);
+	}
+    }
+
+    return (Gv.infocus);
+}
+
+/*!
+   \brief Set focus to map center
+
+   \param id surface id
+ */
+void GS_set_focus_center_map(int id)
+{
+    float center[3];
+    geosurf *gs;
+
+    G_debug(3, "GS_set_focus_center_map");
+
+    gs = gs_get_surf(id);
+
+    if (gs) {
+	center[X] = (gs->xmax - gs->xmin) / 2.;
+	center[Y] = (gs->ymax - gs->ymin) / 2.;
+	center[Z] = (gs->zmax_nz + gs->zmin_nz) / 2.;
+
+	/* not yet working
+	   buff = gs_get_att_typbuff(gs, ATT_TOPO, 0);
+	   offset = gs->rows*gs->cols/2 + gs->cols/2;
+	   if (buff)
+	   {
+	   if (GET_MAPATT(buff, offset, tmp))
+	   {
+	   center[Z] = tmp;
+	   }
+	   }
+	 */
+
+	GS_set_focus(center);
+    }
+}
+
+/*!
+   \brief Move viewpoint 
+
+   \param pt 'from' model coordinates
+ */
+void GS_moveto(float *pt)
+{
+    float ft[3];
+
+    G_debug(3, "GS_moveto(): %f,%f,%f", pt[0], pt[1], pt[2]);
+
+    if (Gv.infocus) {
+	GS_v3eq(Gv.from_to[FROM], pt);
+	/*
+	   GS_v3eq(Gv.from_to[TO], Gv.real_to);
+	 */
+	GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
+	/* update inclination, look_dir if we're keeping these */
+    }
+    else {
+	GS_v3eq(ft, Gv.from_to[TO]);
+	GS_v3sub(ft, Gv.from_to[FROM]);
+	GS_v3eq(Gv.from_to[FROM], pt);
+	GS_v3eq(Gv.from_to[TO], pt);
+	GS_v3add(Gv.from_to[TO], ft);
+    }
+
+    return;
+}
+
+/*!
+   \brief Move position to (real)
+
+   \param pt point real coordinates
+ */
+void GS_moveto_real(float *pt)
+{
+    gsd_real2model(pt);
+    GS_moveto(pt);
+
+    return;
+}
+
+/*!
+   \brief Get z-extent for a single surface
+
+   \param id surface id
+   \param[out] min min z-value
+   \param[out] max max z-value
+   \param[out] mid middle z-value
+
+   \return -1 on error (invalid surface id)
+   \return ?
+ */
+int GS_get_zextents(int id, float *min, float *max, float *mid)
+{
+    geosurf *gs;
+
+    if (NULL == (gs = gs_get_surf(id))) {
+	return (-1);
+    }
+
+    G_debug(3, "GS_get_zextents(): id=%d", id);
+
+    return (gs_get_zextents(gs, min, max, mid));
+}
+
+/*!
+   \brief Get z-extent for all loaded surfaces
+
+   \param[out] min min z-value
+   \param[out] max max z-value
+   \param doexag use z-exaggeration
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GS_get_zrange(float *min, float *max, int doexag)
+{
+    int ret_surf, ret_vol;
+    float surf_min, surf_max;
+    float vol_min, vol_max;
+
+    ret_surf = gs_get_zrange(&surf_min, &surf_max);
+    ret_vol = gvl_get_zrange(&vol_min, &vol_max);
+
+    if (ret_surf > 0 && ret_vol > 0) {
+	*min = (surf_min < vol_min) ? surf_min : vol_min;
+	*max = (surf_max < vol_max) ? surf_max : vol_max;
+    }
+    else if (ret_surf > 0) {
+	*min = surf_min;
+	*max = surf_max;
+    }
+    else if (ret_vol > 0) {
+	*min = vol_min;
+	*max = vol_max;
+    }
+
+    if (doexag) {
+	*min *= Gv.vert_exag;
+	*max *= Gv.vert_exag;
+    }
+
+    G_debug(3, "GS_get_zrange(): min=%g max=%g", *min, *max);
+    return ((ret_surf > 0 || ret_vol > 0) ? (1) : (-1));
+}
+
+/*!
+   \brief Get viewpoint 'from' position
+
+   \param[out] fr from model coordinates
+ */
+void GS_get_from(float *fr)
+{
+    GS_v3eq(fr, Gv.from_to[FROM]);
+
+    G_debug(3, "GS_get_from(): %f,%f,%f", fr[0], fr[1], fr[2]);
+
+    return;
+}
+
+/*!
+   \brief Get viewpoint 'from' real coordinates
+
+   \param[out] fr 'from' real coordinates
+ */
+void GS_get_from_real(float *fr)
+{
+    GS_v3eq(fr, Gv.from_to[FROM]);
+    gsd_model2real(fr);
+
+    return;
+}
+
+/*!
+   \brief Get 'to' real coordinates
+
+   \param[out] to 'to' real coordinates
+ */
+void GS_get_to_real(float *to)
+{
+    float realto[3];
+
+    G_get_set_window(&wind);
+    GS_get_focus(realto);
+    to[X] = realto[X] + wind.west + (wind.ew_res / 2.);
+    to[Y] = realto[Y] + wind.south + (wind.ns_res / 2.);
+    to[Z] = realto[Z];
+
+    return;
+}
+
+
+/*!
+   \brief Get zoom setup
+
+   \param[out] a,b,c,d current viewport settings
+   \param[out] maxx,maxy max viewport size
+ */
+void GS_zoom_setup(int *a, int *b, int *c, int *d, int *maxx, int *maxy)
+{
+    GLint tmp[4];
+    GLint num[2];
+
+    gsd_getViewport(tmp, num);
+    *a = tmp[0];
+    *b = tmp[1];
+    *c = tmp[2];
+    *d = tmp[3];
+    *maxx = num[0];
+    *maxy = num[1];
+
+    return;
+}
+
+/*!
+   \brief Get 'to' model coordinates
+
+   \todo need set_to? - just use viewdir?
+
+   \param[out] to 'to' model coordinates
+ */
+void GS_get_to(float *to)
+{
+    G_debug(3, "GS_get_to");
+
+    GS_v3eq(to, Gv.from_to[TO]);
+
+    return;
+}
+
+/*!
+   \brief Get viewdir
+
+   \param[out] dir viewdir value
+ */
+void GS_get_viewdir(float *dir)
+{
+    GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
+
+    return;
+}
+
+/*!
+   \brief Set viewdir
+
+   Automatically turns off focus
+
+   \param dir viewdir value
+ */
+void GS_set_viewdir(float *dir)
+{
+    float tmp[3];
+
+    GS_v3eq(tmp, dir);
+    GS_v3norm(tmp);
+    GS_v3eq(Gv.from_to[TO], Gv.from_to[FROM]);
+    GS_v3add(Gv.from_to[TO], tmp);
+
+    GS_set_nofocus();
+    gsd_set_view(&Gv, &Gd);
+
+    return;
+}
+
+/*!
+   \brief Set field of view
+
+   \param fov fov value
+ */
+void GS_set_fov(int fov)
+{
+    Gv.fov = fov;
+
+    return;
+}
+
+/*!
+   \brief Get fied of view
+
+   \return field of view, in 10ths of degrees
+ */
+int GS_get_fov(void)
+{
+    return (Gv.fov);
+}
+
+/*!
+   \brief Get twist value
+
+   10ths of degrees off twelve o'clock
+ */
+int GS_get_twist(void)
+{
+    return (Gv.twist);
+}
+
+/*!
+   \brief Set viewpoint twist value
+
+   10ths of degrees off twelve o'clock
+
+   \param t tenths of degrees clockwise from 12:00.
+ */
+void GS_set_twist(int t)
+{
+    Gv.twist = t;
+
+    return;
+}
+
+/*!
+   \brief Set rotation params
+ */
+void GS_set_rotation(double angle, double x, double y, double z)
+{
+    Gv.rotate.rot_angle = angle;
+    Gv.rotate.rot_axes[0] = x;
+    Gv.rotate.rot_axes[1] = y;
+    Gv.rotate.rot_axes[2] = z;
+    Gv.rotate.do_rot = 1;
+
+    return;
+}
+
+/*!
+   \brief Stop scene rotation
+ */
+void GS_unset_rotation(void)
+{
+    Gv.rotate.do_rot = 0;
+}
+
+/*!
+   \brief Reset scene rotation
+ */
+void GS_init_rotation(void)
+{
+    int i;
+
+    for (i = 0; i < 16; i++) {
+	if (i == 0 || i == 5 || i == 10 || i == 15)
+	    Gv.rotate.rotMatrix[i] = 1.0;
+	else
+	    Gv.rotate.rotMatrix[i] = 0.0;
+    }
+    Gv.rotate.rot_angle = 0.0;
+    Gv.rotate.rot_axes[0] = 0.0;
+    Gv.rotate.rot_axes[1] = 0.0;
+    Gv.rotate.rot_axes[2] = 0.0;
+    Gv.rotate.do_rot = 0;
+    
+}
+/*!
+ * \brief Get rotation matrix
+ */ 
+void GS_get_rotation_matrix(double *matrix)
+{
+    int i;
+
+    for (i = 0; i < 16; i++) {
+	matrix[i] = Gv.rotate.rotMatrix[i];
+    }
+}
+
+/*!
+ * \brief Set rotation matrix
+ */ 
+void GS_set_rotation_matrix(double *matrix)
+{
+    int i;
+
+    for (i = 0; i < 16; i++) {
+	Gv.rotate.rotMatrix[i] = matrix[i];
+    }
+}
+
+/*!
+   \brief Unset focus
+ */
+void GS_set_nofocus(void)
+{
+    G_debug(3, "GS_set_nofocus");
+
+    Gv.infocus = 0;
+
+    return;
+}
+
+/*!
+   \brief Set focus
+
+   Make sure that the center of view is set
+ */
+void GS_set_infocus(void)
+{
+    G_debug(3, "GS_set_infocus");
+
+    Gv.infocus = 1;
+
+    return;
+}
+
+/*!
+   \brief Set viewport
+
+   \param left,right,bottom,top viewport extent values
+ */
+void GS_set_viewport(int left, int right, int bottom, int top)
+{
+    G_debug(3, "GS_set_viewport(): left=%d, right=%d, "
+	    "bottom=%d, top=%d", left, right, bottom, top);
+
+    gsd_viewport(left, right, bottom, top);
+
+    return;
+}
+
+/*!
+   \brief Send screen coords sx and sy, lib traces through surfaces; sets
+   new center to point of nearest intersection.
+
+   If no intersection, uses line of sight with length of current view
+   ray (eye to center) to set new center.
+
+   Reset center of view to screen coordinates sx, sy.
+
+   \param sx,sy screen coordinates
+
+   \return 1 on success
+   \return 0 on error (invalid surface id)
+ */
+int GS_look_here(int sx, int sy)
+{
+    float x, y, z, len, los[2][3];
+    Point3 realto, dir;
+    int id;
+    geosurf *gs;
+
+    if (GS_get_selected_point_on_surface(sx, sy, &id, &x, &y, &z)) {
+	gs = gs_get_surf(id);
+	if (gs) {
+	    realto[X] = x - gs->ox + gs->x_trans;
+	    realto[Y] = y - gs->oy + gs->y_trans;
+	    realto[Z] = z + gs->z_trans;
+	    GS_set_focus(realto);
+
+	    return (1);
+	}
+    }
+    else {
+	if (gsd_get_los(los, (short)sx, (short)sy)) {
+	    len = GS_distance(Gv.from_to[FROM], Gv.real_to);
+	    GS_v3dir(los[FROM], los[TO], dir);
+	    GS_v3mult(dir, len);
+	    realto[X] = Gv.from_to[FROM][X] + dir[X];
+	    realto[Y] = Gv.from_to[FROM][Y] + dir[Y];
+	    realto[Z] = Gv.from_to[FROM][Z] + dir[Z];
+	    GS_set_focus(realto);
+
+	    return (1);
+	}
+    }
+
+    return (0);
+}
+
+/*!
+   \brief Get selected point of surface
+
+   Given screen coordinates sx and sy, find closest intersection of
+   view ray with surfaces and return coordinates of intersection in x, y,
+   z, and identifier of surface in id.
+
+   \param sx,sy screen coordinates
+   \param[out] id surface id
+   \param[out] x,y,z point on surface (model coordinates?)
+
+   \returns 0 if no intersections found
+   \return number of intersections
+ */
+int GS_get_selected_point_on_surface(int sx, int sy, int *id, float *x,
+				     float *y, float *z)
+{
+    float los[2][3], find_dist[MAX_SURFS], closest;
+    Point3 point, tmp, finds[MAX_SURFS];
+    int surfs[MAX_SURFS], i, iclose, numhits = 0;
+    geosurf *gs;
+
+    /* returns surface-world coords */
+    gsd_get_los(los, (short)sx, (short)sy);
+
+    if (!gs_setlos_enterdata(los)) {
+	G_debug(3, "gs_setlos_enterdata(los): returns false");
+	return (0);
+    }
+
+    for (i = 0; i < Next_surf; i++) {
+	G_debug(3, "id=%d", i);
+
+	gs = gs_get_surf(Surf_ID[i]);
+
+	/* los_intersect expects surf-world coords (xy transl, no scaling) */
+
+#if NVIZ_HACK
+	if (gs_los_intersect1(Surf_ID[i], los, point)) {
+#else
+	if (gs_los_intersect(Surf_ID[i], los, point)) {
+#endif
+	    if (!gs_point_is_masked(gs, point)) {
+		GS_v3eq(tmp, point);
+		tmp[X] += gs->x_trans;
+		tmp[Y] += gs->y_trans;
+		tmp[Z] += gs->z_trans;
+		find_dist[numhits] = GS_distance(los[FROM], tmp);
+		gsd_surf2real(gs, point);
+		GS_v3eq(finds[numhits], point);
+		surfs[numhits] = Surf_ID[i];
+		numhits++;
+	    }
+	}
+    }
+
+    for (i = iclose = 0; i < numhits; i++) {
+	closest = find_dist[iclose];
+
+	if (find_dist[i] < closest) {
+	    iclose = i;
+	}
+    }
+
+    if (numhits) {
+	*x = finds[iclose][X];
+	*y = finds[iclose][Y];
+	*z = finds[iclose][Z];
+	*id = surfs[iclose];
+    }
+
+    G_debug(3, "NumHits %d, next %d", numhits, Next_surf);
+
+    return (numhits);
+}
+
+/*!
+   \brief Set cplace rotation
+
+   \param num cplace id
+   \param dx,dy,dz rotation values
+ */
+void GS_set_cplane_rot(int num, float dx, float dy, float dz)
+{
+    gsd_cplane_setrot(num, dx, dy, dz);
+
+    return;
+}
+
+/*!
+   \brief Set cplace trans
+
+   \param num cplace id
+   \param dx,dy,dz rotation values
+ */
+void GS_set_cplane_trans(int num, float dx, float dy, float dz)
+{
+    gsd_cplane_settrans(num, dx, dy, dz);
+
+    return;
+}
+
+
+/*!
+   \brief Draw cplace
+
+   \param num cplace id
+ */
+void GS_draw_cplane(int num)
+{
+    geosurf *gsurfs[MAX_SURFS];
+    int nsurfs;
+
+    nsurfs = gs_num_surfaces();
+    if (2 == nsurfs) {
+	/* testing */
+	gs_getall_surfaces(gsurfs);
+	gsd_draw_cplane_fence(gsurfs[0], gsurfs[1], num);
+    }
+    else {
+	gsd_draw_cplane(num);
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw cplace fence ?
+
+   \param hs1,hs2
+   \param num cplane id
+
+   \return 0 on error
+   \return 1 on success
+ */
+int GS_draw_cplane_fence(int hs1, int hs2, int num)
+{
+    geosurf *gs1, *gs2;
+
+    if (NULL == (gs1 = gs_get_surf(hs1))) {
+	return (0);
+    }
+
+    if (NULL == (gs2 = gs_get_surf(hs2))) {
+	return (0);
+    }
+
+    gsd_draw_cplane_fence(gs1, gs2, num);
+
+    return (1);
+}
+
+/*!
+   \brief Draw all cplace fences ?
+ */
+void GS_alldraw_cplane_fences(void)
+{
+    int onstate[MAX_CPLANES], i;
+
+    gsd_get_cplanes_state(onstate);
+
+    for (i = 0; i < MAX_CPLANES; i++) {
+	if (onstate[i]) {
+	    GS_draw_cplane_fence(Surf_ID[0], Surf_ID[1], i);
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Set cplace
+
+   \param num cplane id
+ */
+void GS_set_cplane(int num)
+{
+    gsd_cplane_on(num);
+
+    return;
+}
+
+/*!
+   \brief Unset clip place (turn off)
+
+   \param num cplane id
+ */
+void GS_unset_cplane(int num)
+{
+    gsd_cplane_off(num);
+
+    return;
+}
+
+/*!
+   \brief Get axis scale
+
+   \param sx,sy,sz x/y/z scale values
+   \param doexag use vertical exaggeration
+ */
+void GS_get_scale(float *sx, float *sy, float *sz, int doexag)
+{
+    float zexag;
+
+    zexag = doexag ? Gv.vert_exag : 1.;
+    *sx = *sy = Gv.scale;
+    *sz = Gv.scale * zexag;
+
+    return;
+}
+
+/*!
+   \brief Set fence color
+
+   \param mode mode id
+ */
+void GS_set_fencecolor(int mode)
+{
+    gsd_setfc(mode);
+
+    return;
+}
+
+/*!
+   \brief Get fence color
+
+   \return color value
+ */
+int GS_get_fencecolor(void)
+{
+    return gsd_getfc();
+}
+
+/*!
+   \brief Measure distance "as the ball rolls" between two points on
+   surface
+
+   \param hs surface id
+   \param x1,y1,x2,y2 two points on surface
+   \param[out] dist measured distance
+   \param use_exag use exag. surface
+
+   \return 0 on error or if one or more points is not in region
+   \return distance following terrain
+ */
+int GS_get_distance_alongsurf(int hs, float x1, float y1, float x2, float y2,
+			      float *dist, int use_exag)
+{
+    geosurf *gs;
+    float p1[2], p2[2];
+    
+    gs = gs_get_surf(hs);
+    if (gs == NULL) {
+	return 0;
+    }
+    
+    p1[X] = x1;
+    p1[Y] = y1;
+    p2[X] = x2;
+    p2[Y] = y2;
+    gsd_real2surf(gs, p1);
+    gsd_real2surf(gs, p2);
+
+    G_debug(3, "GS_get_distance_alongsurf(): hs=%d p1=%f,%f p2=%f,%f",
+	    hs, x1, y1, x2, y2);
+    return gs_distance_onsurf(gs, p1, p2, dist, use_exag);
+}
+
+/*!
+   \brief Save 3d view
+
+   \param vname view file name
+   \param surfid surface id
+
+   \return ?
+ */
+int GS_save_3dview(const char *vname, int surfid)
+{
+    return (Gs_save_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
+}
+
+/*!
+   \brief Load 3d view
+
+   \param vname view file name
+   \param surfid surface id
+
+   \return ?
+ */
+int GS_load_3dview(const char *vname, int surfid)
+{
+
+    return (Gs_load_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
+
+    /* what to do about lights - I guess, delete all &
+       create any that exist in 3dview file */
+}
+
+/************************************************************************
+* Following routines use Graphics Library
+************************************************************************/
+
+/*!
+   \brief Init viewpoint
+
+   \todo allow to set center?
+ */
+void GS_init_view(void)
+{
+    static int first = 1;
+
+    G_debug(3, "GS_init_view");
+
+    if (first) {
+	first = 0;
+	glMatrixMode(GL_MODELVIEW);
+
+	/* OGLXXX doublebuffer: use GLX_DOUBLEBUFFER in attriblist */
+	/* glxChooseVisual(*dpy, screen, *attriblist); */
+	/* OGLXXX
+	 * ZMIN not needed -- always 0.
+	 * ZMAX not needed -- always 1.
+	 * getgdesc other posiblilties:
+	 *      glxGetConfig();
+	 *      glxGetCurrentContext();
+	 *      glxGetCurrentDrawable();
+	 * GLint gdtmp;
+	 * getgdesc other posiblilties:
+	 *      glxGetConfig();
+	 *      glxGetCurrentContext();
+	 *      glxGetCurrentDrawable();
+	 * GLint gdtmp;
+	 * glDepthRange params must be scaled to [0, 1]
+	 */
+	glDepthRange(0.0, 1.0);
+	glEnable(GL_DEPTH_TEST);
+	glDepthFunc(GL_LEQUAL);
+	/* } */
+
+	/* replace these with something meaningful */
+	Gv.fov = 450;
+	Gv.twist = 0;
+
+	GS_init_rotation();
+
+	Gv.from_to[FROM][X] = Gv.from_to[FROM][Y] =
+	    Gv.from_to[FROM][Z] = GS_UNIT_SIZE / 2.;
+
+	Gv.from_to[TO][X] = GS_UNIT_SIZE / 2.;
+	Gv.from_to[TO][Y] = GS_UNIT_SIZE / 2.;
+	Gv.from_to[TO][Z] = 0.;
+	Gv.from_to[TO][W] = Gv.from_to[FROM][W] = 1.;
+
+	Gv.real_to[W] = 1.;
+	Gv.vert_exag = 1.;
+
+	GS_v3eq(Gv.real_to, Gv.from_to[TO]);
+	GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
+
+	/*
+	   Gd.nearclip = 50;
+	   Gd.farclip = 10000.;
+	 */
+	Gd.nearclip = 10.;
+	Gd.farclip = 10000.;
+	Gd.aspect = (float)GS_get_aspect();
+
+	GS_set_focus(Gv.real_to);
+    }
+
+    return;
+}
+
+/*!
+   \brief Clear view
+
+   \param col color value
+ */
+void GS_clear(int col)
+{
+    G_debug(3, "GS_clear");
+
+    col = col | 0xFF000000;
+
+    /* OGLXXX
+     * change glClearDepth parameter to be in [0, 1]
+     * ZMAX not needed -- always 1.
+     * getgdesc other posiblilties:
+     *      glxGetConfig();
+     *      glxGetCurrentContext();
+     *      glxGetCurrentDrawable();
+     * GLint gdtmp;
+     */
+    glClearDepth(1.0);
+    glClearColor(((float)((col) & 0xff)) / 255.,
+		 (float)((col) >> 8 & 0xff) / 255.,
+		 (float)((col) >> 16 & 0xff) / 255.,
+		 (float)((col) >> 24 & 0xff) / 255.);
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+    Gd.bgcol = col;
+    Modelshowing = 0;
+    gsd_flush();
+
+    return;
+}
+
+/*!
+   \brief Get aspect value
+
+   \return aspect value
+ */
+double GS_get_aspect(void)
+{
+    int left, right, bottom, top;
+    GLint tmp[4];
+
+    /* OGLXXX
+     * get GL_VIEWPORT:
+     * You can probably do better than this.
+     */
+    glGetIntegerv(GL_VIEWPORT, tmp);
+    left = tmp[0];
+    right = tmp[0] + tmp[2] - 1;
+    bottom = tmp[1];
+    top = tmp[1] + tmp[3] - 1;
+
+    G_debug(3, "GS_get_aspect(): left=%d, right=%d, top=%d, bottom=%d",
+	    left, right, top, bottom);
+
+    return ((double)(right - left) / (top - bottom));
+}
+
+/*!
+   \brief Check for transparency
+
+   Disabled.
+
+   \return 1
+ */
+int GS_has_transparency(void)
+{
+    /* OGLXXX
+     * getgdesc other posiblilties:
+     *      glxGetConfig();
+     *      glxGetCurrentContext();
+     *      glxGetCurrentDrawable();
+     * GLint gdtmp;
+     * blending is ALWAYS supported.
+     * This function returns whether it is enabled.
+     * return((glGetIntegerv(GL_BLEND, &gdtmp), gdtmp));
+     */
+
+    return (1);
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gs3.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/Gs3.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gs3.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gs3.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,1198 @@
+/*!
+   \file Gs3.c
+
+   \brief OGSF library - loading surfaces (lower level functions)
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   (C) 1999-2008 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.
+
+   \author Bill Brown USACERL, GMSL/University of Illinois (January 1993)
+   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include <grass/bitmap.h>
+
+#include <grass/ogsf.h>
+/* for geoview & geodisplay in 3dview stuff */
+#include "gsget.h"
+/* for update_attrange - might be able to move this func now */
+
+/*!
+   \brief Used in the function Gs_update_attrange()
+ */
+#define INIT_MINMAX(p, nm, size, min, max, found) \
+	found = 0; \
+	p+=(size-1); \
+	while (size--) \
+	{ \
+	    if (!BM_GET_BYOFFSET(nm, size)) \
+	    { \
+		min = max = *p; \
+		found = 1; \
+		break; \
+	    } \
+	    p--; \
+	}
+
+/*!
+   \brief Used in the function Gs_update_attrange()
+ */
+#define SET_MINMAX(p, nm, size, min, max) \
+	p+=(size-1); \
+	while(size--) \
+	{ \
+	    if (!BM_GET_BYOFFSET(nm, size)) \
+	    { \
+		if (*p < min) \
+		{ \
+		    min = *p; \
+		} \
+		else if (*p > max) \
+		{ \
+		    max = *p; \
+		}  \
+	    } \
+	    p--; \
+	}
+
+typedef int FILEDESC;
+
+#define NO_DATA_COL 0xffffff
+
+/*!
+   \brief Calculates distance in METERS between two points in current projection (2D)
+
+   Uses G_distance().
+
+   \param from 'from' point (X, Y)
+   \param to 'to' point (X, Y)
+
+   \return distance
+ */
+double Gs_distance(double *from, double *to)
+{
+    static int first = 1;
+
+    if (first) {
+	first = 0;
+	G_begin_distance_calculations();
+    }
+
+    return G_distance(from[0], from[1], to[0], to[1]);
+}
+
+/*!
+   \brief Load raster map as floating point map
+
+   Calling function must have already allocated space in buff for
+   wind->rows * wind->cols floats.
+
+   This routine simply loads the map into a 2d array by repetitve calls
+   to get_f_raster_row.
+
+   \param wind current window
+   \param map_name raster map name
+   \param[out] buff data buffer
+   \param[out] nullmap null map buffer
+   \param[out] has_null indicates if raster map contains null-data
+
+   \return 1 on success
+   \return 0 on failure
+ */
+int Gs_loadmap_as_float(struct Cell_head *wind, const char *map_name,
+			float *buff, struct BM *nullmap, int *has_null)
+{
+    FILEDESC cellfile;
+    const char *map_set;
+    int offset, row, col;
+
+    G_debug(3, "Gs_loadmap_as_float(): name=%s", map_name);
+
+    map_set = G_find_raster2(map_name, "");
+    if (!map_set) {
+	G_warning(_("Raster map <%s> not found"), map_name);
+	return 0;
+    }
+    *has_null = 0;
+
+    cellfile = Rast_open_old(map_name, map_set);
+
+    G_message(_("Loading raster map <%s>..."),
+	      G_fully_qualified_name(map_name, map_set));
+
+    for (row = 0; row < wind->rows; row++) {
+	offset = row * wind->cols;
+	Rast_get_f_row(cellfile, &(buff[offset]), row);
+
+	G_percent(row, wind->rows, 2);
+
+	for (col = 0; col < wind->cols; col++) {
+	    if (Rast_is_f_null_value(buff + offset + col)) {
+		*has_null = 1;
+		BM_set(nullmap, col, row, 1);
+	    }
+	    /* set nm */
+	}
+    }
+    G_percent(1, 1, 1);
+
+    G_debug(4, "  has_null=%d", *has_null);
+
+    Rast_close(cellfile);
+
+    return (1);
+}
+
+/*!
+   \brief Load raster map as integer map
+
+   Calling function must have already allocated space in buff for
+   wind->rows * wind->cols floats.
+
+   This routine simply loads the map into a 2d array by repetitve calls
+   to get_f_raster_row.
+
+   \todo fn body of Gs_loadmap_as_float()
+
+   \param wind current window
+   \param map_name raster map name
+   \param[out] buff data buffer
+   \param[out] nullmap null map buffer
+   \param[out] has_null indicates if raster map contains null-data
+
+   \return 1 on success
+   \return 0 on failure
+ */
+int Gs_loadmap_as_int(struct Cell_head *wind, const char *map_name, int *buff,
+		      struct BM *nullmap, int *has_null)
+{
+    FILEDESC cellfile;
+    const char *map_set;
+    int offset, row, col;
+
+    G_debug(3, "Gs_loadmap_as_int");
+
+    map_set = G_find_raster2(map_name, "");
+    if (!map_set) {
+	G_warning(_("Raster map <%s> not found"), map_name);
+	return 0;
+    }
+    *has_null = 0;
+
+    cellfile = Rast_open_old(map_name, map_set);
+
+    G_message(_("Loading raster map <%s>..."),
+	      G_fully_qualified_name(map_name, map_set));
+
+    for (row = 0; row < wind->rows; row++) {
+	offset = row * wind->cols;
+	Rast_get_c_row(cellfile, &(buff[offset]), row);
+
+	G_percent(row, wind->rows, 2);
+
+	for (col = 0; col < wind->cols; col++) {
+	    if (Rast_is_f_null_value(buff + offset + col)) {
+		*has_null = 1;
+		BM_set(nullmap, col, row, 1);
+	    }
+
+	    /* set nm */
+	}
+    }
+    G_percent(1, 1, 1);
+    
+    Rast_close(cellfile);
+
+    return (1);
+}
+
+/*!
+   \brief Get map data type
+
+   \param filename raster map name
+   \param negflag
+
+   \return -1 if map is integer and Rast_read_range() fails
+   \return data type (ARRY_*)
+ */
+int Gs_numtype(const char *filename, int *negflag)
+{
+    CELL max = 0, min = 0;
+    struct Range range;
+    const char *mapset;
+    int shortbits, charbits, bitplace;
+    static int max_short, max_char;
+    static int first = 1;
+
+    if (first) {
+	max_short = max_char = 1;
+	shortbits = 8 * sizeof(short);
+
+	for (bitplace = 1; bitplace < shortbits; ++bitplace) {
+	    /*1 bit for sign */
+	    max_short *= 2;
+	}
+
+	max_short -= 1;
+
+	/* NO bits for sign, using unsigned char */
+	charbits = 8 * sizeof(unsigned char);
+
+	for (bitplace = 0; bitplace < charbits; ++bitplace) {
+	    max_char *= 2;
+	}
+
+	max_char -= 1;
+
+	first = 0;
+    }
+
+    mapset = G_find_raster2(filename, "");
+    if (!mapset) {
+	G_warning(_("Raster map <%s> not found"), filename);
+	return -1;
+    }
+
+    if (Rast_map_is_fp(filename, mapset)) {
+	G_debug(3, "Gs_numtype(): fp map detected");
+
+	return (ATTY_FLOAT);
+    }
+
+    if (-1 == Rast_read_range(filename, mapset, &range)) {
+	return (-1);
+    }
+
+    Rast_get_range_min_max(&range, &min, &max);
+    *negflag = (min < 0);
+
+    if (max < max_char && min > 0) {
+	return (ATTY_CHAR);
+    }
+
+    if (max < max_short && min > -max_short) {
+	return (ATTY_SHORT);
+    }
+
+    return (ATTY_INT);
+}
+
+/*!
+   \brief Load raster map as integer map
+
+   Calling function must have already allocated space in buff for
+   wind->rows * wind->cols shorts.  
+
+   This routine simply loads the map into a 2d array by repetitve calls
+   to get_map_row.
+
+   \param wind current window
+   \param map_name raster map name
+   \param[out] buff data buffer
+   \param[out] nullmap null map buffer
+   \param[out] has_null indicates if raster map contains null-data
+
+   \return 1 on success
+   \return -1 on failure,
+   \return -2 if read ok, but 1 or more values were too large (small)
+   to fit into a short (in which case the max (min) short is used)
+ */
+int Gs_loadmap_as_short(struct Cell_head *wind, const char *map_name,
+			short *buff, struct BM *nullmap, int *has_null)
+{
+    FILEDESC cellfile;
+    const char *map_set;
+    int *ti, *tmp_buf;
+    int offset, row, col, val, max_short, overflow, shortsize, bitplace;
+    short *ts;
+
+    G_debug(3, "Gs_loadmap_as_short");
+
+    overflow = 0;
+    shortsize = 8 * sizeof(short);
+
+    /* 1 bit for sign */
+    /* same as 2 << (shortsize-1) */
+    for (max_short = bitplace = 1; bitplace < shortsize; ++bitplace) {
+	max_short *= 2;
+    }
+
+    max_short -= 1;
+
+    map_set = G_find_raster2(map_name, "");
+    if (!map_set) {
+	G_warning(_("Raster map <%s> not found"), map_name);
+	return -1;
+    }
+    *has_null = 0;
+
+    cellfile = Rast_open_old(map_name, map_set);
+
+    tmp_buf = (int *)G_malloc(wind->cols * sizeof(int));	/* G_fatal_error */
+    if (!tmp_buf) {
+	return -1;
+    }
+
+    G_message(_("Loading raster map <%s>..."),
+	      G_fully_qualified_name(map_name, map_set));
+
+    for (row = 0; row < wind->rows; row++) {
+	offset = row * wind->cols;
+	Rast_get_c_row(cellfile, tmp_buf, row);
+
+	G_percent(row, wind->rows, 2);
+
+	ts = &(buff[offset]);
+	ti = tmp_buf;
+
+	for (col = 0; col < wind->cols; col++) {
+	    if (Rast_is_c_null_value(&tmp_buf[col])) {
+		*has_null = 1;
+		BM_set(nullmap, col, row, 1);
+	    }
+	    else {
+		val = *ti;
+		if (abs(val) > max_short) {
+		    overflow = 1;
+		    /* assign floor/ceiling value?
+		     */
+		    *ts = (short)(max_short * val / abs(val));
+		}
+		else {
+		    *ts = (short)val;
+		}
+	    }
+
+	    ti++;
+	    ts++;
+	}
+    }
+    G_percent(1, 1, 1);
+    
+    Rast_close(cellfile);
+
+    G_free(tmp_buf);
+
+    return (overflow ? -2 : 1);
+}
+
+/*!
+   \brief Load raster map as integer map
+
+   Calling function must have already allocated space in buff for
+   wind->rows * wind->cols unsigned chars.  
+
+   This routine simply loads the map into a 2d array by repetitve calls
+   to get_map_row.
+
+   Since signs of chars can be tricky, we only load positive chars
+   between 0-255.
+
+   \todo fn body Gs_loadmap_as_float()
+
+   \param wind current window
+   \param map_name raster map name
+   \param[out] buff data buffer
+   \param[out] nullmap null map buffer
+   \param[out] has_null indicates if raster map contains null-data
+
+   \return 1 on success
+   \return -1 on failure
+   \return -2 if read ok, but 1 or more values
+   were too large (small) to fit into an unsigned char.
+   (in which case the max (min) char is used)
+ */
+int Gs_loadmap_as_char(struct Cell_head *wind, const char *map_name,
+		       unsigned char *buff, struct BM *nullmap, int *has_null)
+{
+    FILEDESC cellfile;
+    const char *map_set;
+    int *ti, *tmp_buf;
+    int offset, row, col, val, max_char, overflow, charsize, bitplace;
+    unsigned char *tc;
+
+    G_debug(3, "Gs_loadmap_as_char");
+
+    overflow = 0;
+    charsize = 8 * sizeof(unsigned char);
+
+    /* 0 bits for sign! */
+    max_char = 1;
+
+    for (bitplace = 0; bitplace < charsize; ++bitplace) {
+	max_char *= 2;
+    }
+
+    max_char -= 1;
+
+    map_set = G_find_raster2(map_name, "");
+    if (!map_set) {
+	G_warning(_("Raster map <%s> not found"), map_name);
+	return -1;
+    }
+    *has_null = 0;
+
+    cellfile = Rast_open_old(map_name, map_set);
+
+    tmp_buf = (int *)G_malloc(wind->cols * sizeof(int));	/* G_fatal_error */
+    if (!tmp_buf) {
+	return -1;
+    }
+
+    G_message(_("Loading raster map <%s>..."),
+	      G_fully_qualified_name(map_name, map_set));
+
+    for (row = 0; row < wind->rows; row++) {
+	offset = row * wind->cols;
+	Rast_get_c_row(cellfile, tmp_buf, row);
+	tc = (unsigned char *)&(buff[offset]);
+	ti = tmp_buf;
+
+	G_percent(row, wind->rows, 2);
+
+	for (col = 0; col < wind->cols; col++) {
+	    if (Rast_is_c_null_value(&tmp_buf[col])) {
+		*has_null = 1;
+		BM_set(nullmap, col, row, 1);
+	    }
+	    else {
+		val = *ti;
+		if (val > max_char) {
+		    overflow = 1;
+		    *tc = (unsigned char)max_char;
+		}
+		else if (val < 0) {
+		    overflow = 1;
+		    *tc = 0;
+		}
+		else {
+		    *tc = (unsigned char)val;
+		}
+	    }
+
+	    ti++;
+	    tc++;
+	}
+    }
+    G_percent(1, 1, 1);
+    
+    Rast_close(cellfile);
+
+    G_free(tmp_buf);
+
+    return (overflow ? -2 : 1);
+}
+
+/*!
+   \brief Load raster map as integer map
+
+   Calling function must have already allocated space in buff for
+   struct BM of wind->rows & wind->cols.
+
+   This routine simply loads the map into the bitmap by repetitve calls
+   to get_map_row.  Any value other than 0 in the map will set the bitmap.
+   (may want to change later to allow specific value to set)
+
+   Changed to use null.
+
+   \param wind current window
+   \param map_name raster map name
+   \param[out] buff data buffer
+
+   \returns 1 on success
+   \return -1 on failure
+ */
+int Gs_loadmap_as_bitmap(struct Cell_head *wind, const char *map_name,
+			 struct BM *buff)
+{
+    FILEDESC cellfile;
+    const char *map_set;
+    int *tmp_buf;
+    int row, col;
+
+    G_debug(3, "Gs_loadmap_as_bitmap");
+
+    map_set = G_find_raster2(map_name, "");
+    if (!map_set) {
+	G_warning(_("Raster map <%s> not found"), map_name);
+	return -1;
+    }
+
+    cellfile = Rast_open_old(map_name, map_set);
+
+    tmp_buf = (int *)G_malloc(wind->cols * sizeof(int));	/* G_fatal_error */
+    if (!tmp_buf) {
+	return -1;
+    }
+
+    G_message(_("Loading raster map <%s>..."),
+	      G_fully_qualified_name(map_name, map_set));
+
+    for (row = 0; row < wind->rows; row++) {
+	Rast_get_c_row(cellfile, tmp_buf, row);
+
+	for (col = 0; col < wind->cols; col++) {
+	    if (Rast_is_c_null_value(&tmp_buf[col])) {
+		/* no data */
+		BM_set(buff, col, row, 1);
+	    }
+	    else {
+		BM_set(buff, col, row, 0);
+	    }
+	}
+    }
+
+    Rast_close(cellfile);
+
+    G_free(tmp_buf);
+
+    return (1);
+}
+
+/*!
+   \brief Build color table (256)
+
+   Calling function must have already allocated space in buff for range of
+   data (256 for now) - simply calls get_color for each cat in color range
+
+   \param filename raster map name
+   \param[out] buff data buffer
+
+   \return 1 on success
+   \return 0 on failure
+ */
+int Gs_build_256lookup(const char *filename, int *buff)
+{
+    const char *mapset;
+    struct Colors colrules;
+    CELL min, max, cats[256];
+    int i;
+    unsigned char r[256], g[256], b[256], set[256];
+
+    G_debug(3, "building color table");
+
+    mapset = G_find_raster2(filename, "");
+    if (!mapset) {
+	G_warning(_("Raster map <%s> not found"), filename);
+	return 0;
+    }
+
+    Rast_read_colors(filename, mapset, &colrules);
+    Rast_get_c_color_range(&min, &max, &colrules);
+
+    if (min < 0 || max > 255) {
+	G_warning(_("Color table range doesn't match data (mincol=%d, maxcol=%d"),
+		  min, max);
+
+	min = min < 0 ? 0 : min;
+	max = max > 255 ? 255 : max;
+    }
+
+    G_zero(cats, 256 * sizeof(CELL));
+
+    for (i = min; i <= max; i++) {
+	cats[i] = i;
+    }
+
+    Rast_lookup_c_colors(cats, r, g, b, set, 256, &colrules);
+
+    for (i = 0; i < 256; i++) {
+
+	if (set[i]) {
+	    buff[i] =
+		(r[i] & 0xff) | ((g[i] & 0xff) << 8) | ((b[i] & 0xff) << 16);
+	}
+	else {
+	    buff[i] = NO_DATA_COL;
+	}
+    }
+
+    return (1);
+}
+
+/*!
+   \brief Pack color table
+
+   Passed an array of 32 bit ints that is converted from cell values
+   to packed colors (0xbbggrr) 
+
+   \param filename raster map name
+   \param buff
+   \param rows number of rows
+   \param cols number of cols
+ */
+void Gs_pack_colors(const char *filename, int *buff, int rows, int cols)
+{
+    const char *mapset;
+    struct Colors colrules;
+    unsigned char *r, *g, *b, *set;
+    int *cur, i, j;
+
+    mapset = G_find_raster2(filename, "");
+    if (!mapset) {
+	G_warning(_("Raster map <%s> not found"), filename);
+	return;
+    }
+
+    r = (unsigned char *)G_malloc(cols);
+    g = (unsigned char *)G_malloc(cols);
+    b = (unsigned char *)G_malloc(cols);
+    set = (unsigned char *)G_malloc(cols);
+
+    Rast_read_colors(filename, mapset, &colrules);
+
+    cur = buff;
+
+    G_message(_("Translating colors from raster map <%s>..."),
+	      G_fully_qualified_name(filename, mapset));
+
+    for (i = 0; i < rows; i++) {
+	Rast_lookup_c_colors(cur, r, g, b, set, cols, &colrules);
+	G_percent(i, rows, 2);
+
+	for (j = 0; j < cols; j++) {
+	    if (set[j]) {
+		cur[j] =
+		    (r[j] & 0xff) | ((g[j] & 0xff) << 8) | ((b[j] & 0xff) <<
+							    16);
+	    }
+	    else {
+		cur[j] = NO_DATA_COL;
+	    }
+	}
+
+	cur = &(cur[cols]);
+    }
+    G_percent(1, 1, 1);
+    
+    Rast_free_colors(&colrules);
+
+    G_free(r);
+    G_free(g);
+    G_free(b);
+
+    G_free(set);
+
+    return;
+}
+
+/*!
+   \brief Pack color table (floating-point map)
+
+   Passed a array of floats that will be converted from cell values
+   to packed colors (0xbbggrr) and float to int 
+   Floating point data not freed here, use: 
+   gsds_free_data_buff(id, ATTY_FLOAT)
+
+   \param filename raster map name
+   \param fbuf
+   \param ibuf
+   \param rows number of rows
+   \param cols number of cols
+ */
+void Gs_pack_colors_float(const char *filename, float *fbuf, int *ibuf,
+			  int rows, int cols)
+{
+    const char *mapset;
+    struct Colors colrules;
+    unsigned char *r, *g, *b, *set;
+    int i, j, *icur;
+    FCELL *fcur;
+
+    mapset = G_find_raster2(filename, "");
+    if (!mapset) {
+	G_warning(_("Raster map <%s> not found"), filename);
+	return;
+    }
+
+    r = (unsigned char *)G_malloc(cols);
+    g = (unsigned char *)G_malloc(cols);
+    b = (unsigned char *)G_malloc(cols);
+    set = (unsigned char *)G_malloc(cols);
+
+    Rast_read_colors(filename, mapset, &colrules);
+
+    fcur = fbuf;
+    icur = ibuf;
+
+    G_message(_("Translating colors from raster map <%s>..."),
+	      G_fully_qualified_name(filename, mapset));
+    
+    for (i = 0; i < rows; i++) {
+	Rast_lookup_f_colors(fcur, r, g, b, set, cols, &colrules);
+	G_percent(i, rows, 2);
+
+	for (j = 0; j < cols; j++) {
+	    if (set[j]) {
+		icur[j] =
+		    (r[j] & 0xff) | ((g[j] & 0xff) << 8) | ((b[j] & 0xff) <<
+							    16);
+	    }
+	    else {
+		icur[j] = NO_DATA_COL;
+	    }
+	}
+
+	icur = &(icur[cols]);
+	fcur = &(fcur[cols]);
+    }
+    G_percent(1, 1, 1);
+    
+    Rast_free_colors(&colrules);
+
+    G_free(r);
+    G_free(g);
+    G_free(b);
+    G_free(set);
+
+    return;
+}
+
+/*!
+   \brief Get categories/labels
+
+   Formats label as in d.what.rast -> (catval) catlabel 
+
+   \param filename raster map name
+   \param drow
+   \param dcol
+   \param catstr category string
+
+   \return 1 on success
+   \return 0 on failure
+ */
+int Gs_get_cat_label(const char *filename, int drow, int dcol, char *catstr)
+{
+    struct Categories cats;
+    const char *mapset;
+    CELL *buf;
+    DCELL *dbuf;
+    RASTER_MAP_TYPE map_type;
+    int fd = -1;
+
+    if ((mapset = G_find_raster2(filename, "")) == NULL) {
+	G_warning(_("Raster map <%s> not found"), filename);
+	return 0;
+    }
+
+    if (-1 != Rast_read_cats(filename, mapset, &cats)) {
+	fd = Rast_open_old(filename, mapset);
+	map_type = Rast_get_map_type(fd);
+
+	if (map_type == CELL_TYPE) {
+	    buf = Rast_allocate_c_buf();
+
+	    Rast_get_c_row(fd, buf, drow);
+	    if (Rast_is_c_null_value(&buf[dcol])) {
+		sprintf(catstr, "(NULL) %s",
+			Rast_get_c_cat(&buf[dcol], &cats));
+	    }
+	    else {
+		sprintf(catstr, "(%d) %s", buf[dcol],
+			Rast_get_c_cat(&buf[dcol], &cats));
+	    }
+
+	    G_free(buf);
+	}
+
+	else {
+	    /* fp map */
+	    dbuf = Rast_allocate_d_buf();
+
+	    Rast_get_d_row(fd, dbuf, drow);
+	    if (Rast_is_d_null_value(&dbuf[dcol])) {
+		sprintf(catstr, "(NULL) %s",
+			Rast_get_d_cat(&dbuf[dcol], &cats));
+	    }
+	    else {
+		sprintf(catstr, "(%g) %s", dbuf[dcol],
+			Rast_get_d_cat(&dbuf[dcol], &cats));
+	    }
+
+	    G_free(dbuf);
+	}
+    }
+    else {
+	strcpy(catstr, "no category label");
+	return 0;
+    }
+
+    /* TODO: may want to keep these around for multiple queries */
+    Rast_free_cats(&cats);
+
+    if (fd >= 0)
+	Rast_close(fd);
+
+    return (1);
+}
+
+/*!
+   \brief Save 3dview
+
+   \param vname view name
+   \param gv pointer to geoview struct
+   \param gd pointer to geodisplay struct
+   \param w current window
+   \param defsurf default geosurf struct
+
+   \return -1 on error
+   \return ?
+ */
+int Gs_save_3dview(const char *vname, geoview * gv, geodisplay * gd,
+		   struct Cell_head *w, geosurf * defsurf)
+{
+    const char *mapset;
+    struct G_3dview v;
+    float zmax, zmin;
+
+    GS_get_zrange(&zmin, &zmax, 0);
+
+    G_get_3dview_defaults(&v, w);
+    mapset = G_mapset();
+
+    if (mapset != NULL) {
+	if (defsurf) {
+	    if (defsurf->draw_mode & DM_WIRE_POLY) {
+		v.display_type = 3;
+	    }
+	    else if (defsurf->draw_mode & DM_WIRE ||
+		     defsurf->draw_mode & DM_COL_WIRE) {
+		v.display_type = 1;
+	    }
+	    else if (defsurf->draw_mode & DM_POLY) {
+		v.display_type = 2;
+	    }
+
+	    v.mesh_freq = defsurf->x_modw;	/* mesh resolution */
+	    v.poly_freq = defsurf->x_mod;	/* poly resolution */
+	    v.dozero = !(defsurf->nz_topo);
+	    v.colorgrid = (defsurf->draw_mode & DM_COL_WIRE) ? 1 : 0;
+	    v.shading = (defsurf->draw_mode & DM_GOURAUD) ? 1 : 0;
+	}
+
+	if (gv->infocus) {
+	    GS_v3eq(v.from_to[TO], gv->real_to);
+	    v.from_to[TO][Z] -= zmin;
+	    GS_v3mult(v.from_to[TO], gv->scale);
+	    v.from_to[TO][Z] *= gv->vert_exag;
+	}
+	else {
+	    GS_v3eq(v.from_to[TO], gv->from_to[TO]);
+	}
+
+	gsd_model2real(v.from_to[TO]);
+
+	GS_v3eq(v.from_to[FROM], gv->from_to[FROM]);
+	gsd_model2real(v.from_to[FROM]);
+
+	v.exag = gv->vert_exag;
+	v.fov = gv->fov / 10.;
+	v.twist = gv->twist;
+	v.fringe = 0;		/* not implemented here */
+
+	v.lightson = 1;		/* always true, curently */
+
+	if (gv->lights[0].position[W] == 1) {
+	    /* local */
+	    v.lightpos[X] = gv->lights[0].position[X];
+	    v.lightpos[Y] = gv->lights[0].position[Y];
+	    v.lightpos[Z] = gv->lights[0].position[Z];
+	    gsd_model2real(v.lightpos);
+	    v.lightpos[W] = 1.0;	/* local */
+	}
+	else {
+	    v.lightpos[X] = gv->lights[0].position[X];
+	    v.lightpos[Y] = gv->lights[0].position[Y];
+	    v.lightpos[Z] = gv->lights[0].position[Z];
+	    v.lightpos[W] = 0.0;	/* inf */
+	}
+
+	v.lightcol[0] = gv->lights[0].color[0];
+	v.lightcol[1] = gv->lights[0].color[1];
+	v.lightcol[2] = gv->lights[0].color[2];
+
+	v.ambient = (gv->lights[0].ambient[0] + gv->lights[0].ambient[1] +
+		     gv->lights[0].ambient[2]) / 3.;
+	v.shine = gv->lights[0].shine;
+
+	v.surfonly = 0;		/* N/A - now uses constant color */
+	strcpy((v.pgm_id), "Nvision-ALPHA!");
+
+	return (G_put_3dview(vname, mapset, &v, w));
+    }
+    else {
+	return (-1);
+    }
+}
+
+/*!
+   \brief Load 3dview
+
+   \param vname view name
+   \param gv pointer to geoview struct
+   \param gd pointer to geodisplay struct
+   \param w current window
+   \param defsurf default geosurf struct
+
+   \return 1
+ */
+int Gs_load_3dview(const char *vname, geoview * gv, geodisplay * gd,
+		   struct Cell_head *w, geosurf * defsurf)
+{
+    const char *mapset;
+    struct G_3dview v;
+    int ret = -1;
+    float pt[3];
+
+    mapset = G_find_file2("3d.view", vname, "");
+
+    if (mapset != NULL) {
+	ret = G_get_3dview(vname, mapset, &v);
+    }
+
+    if (ret >= 0) {
+	if (strcmp((v.pgm_id), "Nvision-ALPHA!")) {
+	    G_warning(_("View not saved by this program,"
+			"there may be some inconsistancies"));
+	}
+
+	/* set poly and mesh resolutions */
+	v.mesh_freq = (int)(v.mesh_freq * v.vwin.ns_res / w->ns_res);
+	v.poly_freq = (int)(v.poly_freq * v.vwin.ns_res / w->ns_res);
+
+	/* Set To and FROM positions */
+	/* TO */
+	pt[0] = (v.from_to[TO][X] - w->west) - w->ew_res / 2.;
+	pt[1] = (v.from_to[TO][Y] - w->south) - w->ns_res / 2.;
+	pt[2] = v.from_to[TO][Z];
+	GS_set_focus(pt);
+
+	/* FROM */
+	pt[0] = (float)v.from_to[FROM][X];
+	pt[1] = (float)v.from_to[FROM][Y];
+	pt[2] = (float)v.from_to[FROM][Z];
+	GS_moveto_real(pt);
+
+	if (defsurf) {
+	    int dmode = 0;
+
+	    GS_setall_drawres(v.poly_freq, v.poly_freq,
+			      v.mesh_freq, v.mesh_freq);
+
+	    while (v.display_type >= 10) {
+		/* globe stuff not used */
+		v.display_type -= 10;
+	    }
+
+	    /* set drawing modes */
+	    if (v.colorgrid) {
+		dmode |= DM_COL_WIRE;
+	    }
+
+	    if (v.shading) {
+		dmode |= DM_GOURAUD;
+	    }
+
+	    switch (v.display_type) {
+	    case 1:
+		dmode |= DM_WIRE;
+
+		break;
+	    case 2:
+		dmode |= DM_POLY;
+
+		break;
+	    case 3:
+		dmode |= DM_WIRE_POLY;
+
+		break;
+	    }
+	    GS_setall_drawmode(dmode);
+
+	    /* should also set nozeros here */
+	}
+
+	/* set exaggeration */
+	if (v.exag)
+	    GS_set_global_exag(v.exag);
+
+	/* Set FOV */
+	if (v.fov) {
+	    GS_set_fov((int)
+		       (v.fov > 0 ? v.fov * 10. + 0.5 : v.fov * 10. - 0.5));
+	}
+	else {
+	    /* TODO: do ortho */
+	}
+
+	/* Set twist */
+	if (v.twist)
+	    GS_set_twist((int)(v.twist > 0 ? v.twist + 0.5 : v.twist - 0.5));
+
+
+	/* TODO:  OK to here - need to unravel/reverse lights stuff*** */
+
+	if (v.lightson) {
+	    /* Lights are on */
+
+	    /* Light Position */
+	    gv->lights[0].position[X] = v.lightpos[X];
+	    gv->lights[0].position[Y] = v.lightpos[Y];
+	    gv->lights[0].position[Z] = v.lightpos[Z];
+
+	    /* Light Color */
+	    gv->lights[0].color[0] = v.lightcol[0];
+	    gv->lights[0].color[1] = v.lightcol[1];
+	    gv->lights[0].color[2] = v.lightcol[2];
+
+	    /* Light Shininess */
+	    gv->lights[0].shine = v.shine;
+
+	    /* Light Ambient */
+	    gv->lights[0].ambient[0] = gv->lights[0].ambient[1] =
+		gv->lights[0].ambient[2] = v.ambient * 3.;
+
+
+	}			/* Done with lights */
+
+
+	GS_alldraw_wire();
+
+    }				/* Done with file */
+    return (1);
+
+}
+
+/*!
+   \brief Update no_zero ranges for attribute (actually no_null now)
+
+   \param gs pointer to geosurf struct
+   \param desc attribute id (descriptor)
+
+   \return -1 on error
+   \return 1 on success
+ */
+int Gs_update_attrange(geosurf * gs, int desc)
+{
+    long size;
+    float min, max;
+    typbuff *tb;
+    struct BM *nm;
+    int found;
+
+    gs->att[desc].max_nz = gs->att[desc].min_nz = gs->att[desc].range_nz =
+	0.0;
+
+    if (CONST_ATT == gs_get_att_src(gs, desc)) {
+	gs->att[desc].max_nz = gs->att[desc].min_nz = gs->att[desc].constant;
+	min = max = gs->att[desc].constant;
+	gs->att[desc].range_nz = 0.0;
+    }
+    else if (CF_COLOR_PACKED & gsds_get_changed(gs->att[desc].hdata)) {
+	gs->att[desc].max_nz = 0xFFFFFF;
+	gs->att[desc].min_nz = 0x010101;
+	gs->att[desc].range_nz = 0xFFFFFF;
+    }
+    else {
+	if (NULL == (tb = gsds_get_typbuff(gs->att[desc].hdata, 0))) {
+	    return (-1);
+	}
+
+	nm = tb->nm;
+
+	if (tb->ib) {
+	    int *p;
+
+	    size = gs->rows * gs->cols;
+	    p = tb->ib;
+	    INIT_MINMAX(p, nm, size, min, max, found);
+
+	    if (!found) {
+		/* all nulls! */
+		return (-1);
+	    }
+
+	    size = gs->rows * gs->cols;
+	    p = tb->ib;
+	    SET_MINMAX(p, nm, size, min, max);
+	}
+	else if (tb->sb) {
+	    short *p;
+
+	    size = gs->rows * gs->cols;
+	    p = tb->sb;
+	    INIT_MINMAX(p, nm, size, min, max, found);
+
+	    if (!found) {
+		/* all nulls! */
+		return (-1);
+	    }
+
+	    size = gs->rows * gs->cols;
+	    p = tb->sb;
+	    SET_MINMAX(p, nm, size, min, max);
+	}
+	else if (tb->cb) {
+	    char *p;
+
+	    size = gs->rows * gs->cols;
+	    p = (char *)tb->cb;
+	    INIT_MINMAX(p, nm, size, min, max, found);
+
+	    if (!found) {
+		/* all nulls! */
+		return (-1);
+	    }
+
+	    size = gs->rows * gs->cols;
+	    p = (char *)tb->cb;
+	    SET_MINMAX(p, nm, size, min, max);
+	}
+	else if (tb->fb) {
+	    float *p;
+
+	    size = gs->rows * gs->cols;
+	    p = tb->fb;
+	    INIT_MINMAX(p, nm, size, min, max, found);
+
+	    if (!found) {
+		/* all nulls! */
+		return (-1);
+	    }
+
+	    size = gs->rows * gs->cols;
+	    p = tb->fb;
+	    SET_MINMAX(p, nm, size, min, max);
+	}
+
+	gs->att[desc].max_nz = max;
+	gs->att[desc].min_nz = min;
+	gs->att[desc].range_nz = gs->att[desc].max_nz - gs->att[desc].min_nz;
+    }
+
+    if (ATT_TOPO == desc) {
+	gs->zmin = min;
+	gs->zmax = max;
+	gs->zrange = gs->zmax - gs->zmin;
+	gs->zminmasked = gs->zmin;
+	gs->zmax_nz = gs->zmax;
+	gs->zmin_nz = gs->zmin;
+	gs->zrange_nz = gs->zmax_nz - gs->zmin_nz;
+    }
+
+    G_debug(3, "Gs_update_attrange(): min=%f max=%f", gs->zmin, gs->zmax);
+
+    return (1);
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gs_util.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/GS_util.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gs_util.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gs_util.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,486 @@
+/*!
+   \file GS_util.c
+
+   \brief OGSF library - loading and manipulating surfaces
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   (C) 1999-2008 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.
+
+   \author Bill Brown USACERL, GMSL/University of Illinois
+   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include <grass/gis.h>
+#include <grass/ogsf.h>
+
+/*!
+   \brief Calculate distance between 2 coordinates
+
+   Units is one of:
+   - "meters",
+   - "miles",
+   - "kilometers",
+   - "feet",
+   - "yards",
+   - "nmiles" (nautical miles),
+   - "rods",
+   - "inches",
+   - "centimeters",
+   - "millimeters",
+   - "micron",
+   - "nanometers",
+   - "cubits",
+   - "hands",
+   - "furlongs",
+   - "chains"
+
+   Default is meters.
+
+   \param from starting point
+   \param to ending point
+   \param units map units
+
+   \return distance between two geographic coordinates in current projection
+ */
+double GS_geodistance(double *from, double *to, const char *units)
+{
+    double meters;
+
+    meters = Gs_distance(from, to);
+
+    if (!units) {
+	return (meters);
+    }
+
+    if (strcmp(units, "meters") == 0) {
+	return (meters);
+    }
+
+    if (strcmp(units, "miles") == 0) {
+	return (meters * .0006213712);
+    }
+
+    if (strcmp(units, "kilometers") == 0) {
+	return (meters * .001);
+    }
+
+    if (strcmp(units, "feet") == 0) {
+	return (meters * 3.280840);
+    }
+
+    if (strcmp(units, "yards") == 0) {
+	return (meters * 1.093613);
+    }
+
+    if (strcmp(units, "rods") == 0) {
+	return (meters * .1988388);
+    }
+
+    if (strcmp(units, "inches") == 0) {
+	return (meters * 39.37008);
+    }
+
+    if (strcmp(units, "centimeters") == 0) {
+	return (meters * 100.0);
+    }
+
+    if (strcmp(units, "millimeters") == 0) {
+	return (meters * 1000.0);
+    }
+
+    if (strcmp(units, "micron") == 0) {
+	return (meters * 1000000.0);
+    }
+
+    if (strcmp(units, "nanometers") == 0) {
+	return (meters * 1000000000.0);
+    }
+
+    if (strcmp(units, "cubits") == 0) {
+	return (meters * 2.187227);
+    }
+
+    if (strcmp(units, "hands") == 0) {
+	return (meters * 9.842520);
+    }
+
+    if (strcmp(units, "furlongs") == 0) {
+	return (meters * .004970970);
+    }
+
+    if (strcmp(units, "nmiles") == 0) {
+	/* nautical miles */
+	return (meters * .0005399568);
+    }
+
+    if (strcmp(units, "chains") == 0) {
+	return (meters * .0497097);
+    }
+
+    return (meters);
+}
+
+/*!
+   \brief Calculate distance
+
+   \param from 'from' point (X,Y,Z)
+   \param to 'to' point (X,Y,Z)
+
+   \return distance
+ */
+float GS_distance(float *from, float *to)
+{
+    float x, y, z;
+
+    x = from[X] - to[X];
+    y = from[Y] - to[Y];
+    z = from[Z] - to[Z];
+
+    return (float)sqrt(x * x + y * y + z * z);
+}
+
+/*!
+   \brief Calculate distance in plane
+
+   \param from 'from' point (X,Y)
+   \param to 'to' point (X,Y)
+
+   \return distance
+ */
+float GS_P2distance(float *from, float *to)
+{
+    float x, y;
+
+    x = from[X] - to[X];
+    y = from[Y] - to[Y];
+
+    return (float)sqrt(x * x + y * y);
+}
+
+/*!
+   \brief Copy vector values
+
+   v1 = v2
+
+   \param[out] v1 first vector
+   \param v2 second vector
+ */
+void GS_v3eq(float *v1, float *v2)
+{
+    v1[X] = v2[X];
+    v1[Y] = v2[Y];
+    v1[Z] = v2[Z];
+
+    return;
+}
+
+/*!
+   \brief Sum vectors
+
+   v1 += v2
+
+   \param[in,out] v1 first vector
+   \param v2 second vector
+ */
+void GS_v3add(float *v1, float *v2)
+{
+    v1[X] += v2[X];
+    v1[Y] += v2[Y];
+    v1[Z] += v2[Z];
+
+    return;
+}
+
+/*!
+   \brief Subtract vectors
+
+   v1 -= v2
+
+   \param[in,out] v1 first vector
+   \param v2 second vector
+ */
+void GS_v3sub(float *v1, float *v2)
+{
+    v1[X] -= v2[X];
+    v1[Y] -= v2[Y];
+    v1[Z] -= v2[Z];
+
+    return;
+}
+
+/*!
+   \brief Multiple vectors
+
+   v1 *= k
+
+   \param[in,out] v1 vector
+   \param k multiplicator
+ */
+void GS_v3mult(float *v1, float k)
+{
+    v1[X] *= k;
+    v1[Y] *= k;
+    v1[Z] *= k;
+
+    return;
+}
+
+/*!
+   \brief Change v1 so that it is a unit vector (2D)
+
+   \param[in,out] v1 vector
+
+   \return 0 if magnitude of v1 is zero
+   \return 1 if magnitude of v1 > 0
+ */
+int GS_v3norm(float *v1)
+{
+    float n;
+
+    n = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y] + v1[Z] * v1[Z]);
+
+    if (n == 0.0) {
+	return (0);
+    }
+
+    v1[X] /= n;
+    v1[Y] /= n;
+    v1[Z] /= n;
+
+    return (1);
+}
+
+/*!
+   \brief Change v1 so that it is a unit vector (3D)
+
+   \param[in,out] v1 vector
+
+   \return 0 if magnitude of v1 is zero
+   \return 1 if magnitude of v1 > 0
+ */
+int GS_v2norm(float *v1)
+{
+    float n;
+
+    n = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y]);
+
+    if (n == 0.0) {
+	return (0);
+    }
+
+    v1[X] /= n;
+    v1[Y] /= n;
+
+    return (1);
+}
+
+/*!
+   \brief Changes v1 so that it is a unit vector
+
+   \param dv1 vector
+
+   \return 0 if magnitude of dv1 is zero
+   \return 1 if magnitude of dv1 > 0
+ */
+int GS_dv3norm(double *dv1)
+{
+    double n;
+
+    n = sqrt(dv1[X] * dv1[X] + dv1[Y] * dv1[Y] + dv1[Z] * dv1[Z]);
+
+    if (n == 0.0) {
+	return (0);
+    }
+
+    dv1[X] /= n;
+    dv1[Y] /= n;
+    dv1[Z] /= n;
+
+    return (1);
+}
+
+
+/*!
+   \brief Change v2 so that v1v2 is a unit vector
+
+   \param v1 first vector
+   \param v2[in,out] second vector
+
+   \return 0 if magnitude of dx is zero
+   \return 1 if magnitude of dx > 0
+ */
+int GS_v3normalize(float *v1, float *v2)
+{
+    float n, dx, dy, dz;
+
+    dx = v2[X] - v1[X];
+    dy = v2[Y] - v1[Y];
+    dz = v2[Z] - v1[Z];
+    n = sqrt(dx * dx + dy * dy + dz * dz);
+
+    if (n == 0.0) {
+	return (0);
+    }
+
+    v2[X] = v1[X] + dx / n;
+    v2[Y] = v1[Y] + dy / n;
+    v2[Z] = v1[Z] + dz / n;
+
+    return (1);
+}
+
+
+/*!
+   \brief Get a normalized direction from v1 to v2, store in v3
+
+   \param v1 first vector
+   \param v2 second vector
+   \param[out] v3 output vector
+
+   \return 0 if magnitude of dx is zero
+   \return 1 if magnitude of dx > 0
+ */
+int GS_v3dir(float *v1, float *v2, float *v3)
+{
+    float n, dx, dy, dz;
+
+    dx = v2[X] - v1[X];
+    dy = v2[Y] - v1[Y];
+    dz = v2[Z] - v1[Z];
+    n = sqrt(dx * dx + dy * dy + dz * dz);
+
+    if (n == 0.0) {
+	v3[X] = v3[Y] = v3[Z] = 0.0;
+	return (0);
+    }
+
+    v3[X] = dx / n;
+    v3[Y] = dy / n;
+    v3[Z] = dz / n;
+
+    return (1);
+}
+
+
+/*!
+   \brief Get a normalized direction from v1 to v2, store in v3 (2D)
+
+   \param v1 first vector
+   \param v2 second vector
+   \param[out] v3 output vector
+
+   \return 0 if magnitude of dx is zero
+   \return 1 if magnitude of dx > 0
+ */
+void GS_v2dir(float *v1, float *v2, float *v3)
+{
+    float n, dx, dy;
+
+    dx = v2[X] - v1[X];
+    dy = v2[Y] - v1[Y];
+    n = sqrt(dx * dx + dy * dy);
+
+    v3[X] = dx / n;
+    v3[Y] = dy / n;
+
+    return;
+}
+
+/*!
+   \brief Get the cross product v3 = v1 cross v2
+
+   \param v1 first vector
+   \param v2 second vector
+   \param[out] v3 output vector
+ */
+void GS_v3cross(float *v1, float *v2, float *v3)
+{
+    v3[X] = (v1[Y] * v2[Z]) - (v1[Z] * v2[Y]);
+    v3[Y] = (v1[Z] * v2[X]) - (v1[X] * v2[Z]);
+    v3[Z] = (v1[X] * v2[Y]) - (v1[Y] * v2[X]);
+
+    return;
+}
+
+/*!
+   \brief Magnitude of vector
+
+   \param v1 vector
+   \param[out] mag magnitude value
+ */
+void GS_v3mag(float *v1, float *mag)
+{
+    *mag = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y] + v1[Z] * v1[Z]);
+
+    return;
+}
+
+/*!
+   \brief ADD
+
+   Initialize by calling with a number nhist to represent number of
+   previous entrys to check, then call with zero as nhist
+
+   \param p1 first point
+   \param p2 second point
+   \param nhist ?
+
+   \return -1 on error
+   \return -2
+   \return 1
+   \return 9
+ */
+int GS_coordpair_repeats(float *p1, float *p2, int nhist)
+{
+    static float *entrys = NULL;
+    static int next = 0;
+    static int len = 0;
+    int i;
+
+    if (nhist) {
+	if (entrys) {
+	    G_free(entrys);
+	}
+
+	entrys = (float *)G_malloc(4 * nhist * sizeof(float));
+
+	if (!entrys)
+	    return (-1);
+
+	len = nhist;
+	next = 0;
+    }
+
+    if (!len) {
+	return (-2);
+    }
+
+    for (i = 0; i < next; i += 4) {
+	if (entrys[i] == p1[0] && entrys[i + 1] == p1[1]
+	    && entrys[i + 2] == p2[0] && entrys[i + 3] == p2[1]) {
+	    return (1);
+	}
+    }
+
+    if (len == next / 4) {
+	next = 0;
+    }
+
+    entrys[next] = p1[0];
+    entrys[next + 1] = p1[1];
+    entrys[next + 2] = p2[0];
+    entrys[next + 3] = p2[1];
+    next += 4;
+
+    return (0);
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gsx.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/GSX.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gsx.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gsx.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,70 @@
+/*!
+   \file GSX.c
+
+   \brief OGSF library - loading and manipulating surfaces
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   (C) 1999-2008 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.
+
+   \author Bill Brown USACERL (December 1993)
+   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
+ */
+
+#include <grass/ogsf.h>
+
+void (*Cxl_func) ();
+void (*Swap_func) ();
+
+static int Cxl = 0;
+
+/*!
+   \brief Check for cancel
+
+   \return code
+ */
+int GS_check_cancel(void)
+{
+    Cxl_func();
+
+    return (Cxl);
+}
+
+/*!
+   \brief Set cancel
+ */
+void GS_set_cancel(int c)
+{
+    Cxl = c;
+
+    return;
+}
+
+/*!
+   \brief Set cxl function
+
+   \param pointer to function
+ */
+void GS_set_cxl_func(void (*f) (void))
+{
+    Cxl_func = f;
+
+    return;
+}
+
+/*!
+   \brief Set swap function
+
+   \param pointer to function
+ */
+void GS_set_swap_func(void (*f) (void))
+{
+    Swap_func = f;
+
+    return;
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gv2.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/GV2.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gv2.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gv2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,601 @@
+/*!
+   \file lib/ogsf/GV2.c
+
+   \brief OGSF library - loading and manipulating vector sets (higher level functions)
+
+   (C) 1999-2008, 2011 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.
+
+   \author Bill Brown USACERL, GMSL/University of Illinois
+   \author Updated by Martin landa <landa.martin gmail.com>
+   (doxygenized in May 2008, thematic mapping in June 2011)
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grass/gis.h>
+#include <grass/ogsf.h>
+
+#include "gsget.h"
+
+static int Vect_ID[MAX_VECTS];
+static int Next_vect = 0;
+
+/*!
+   \brief Check if vector set exists
+
+   \param id vector set id
+
+   \return 0 not found
+   \return 1 found
+ */
+int GV_vect_exists(int id)
+{
+    int i, found = 0;
+
+    G_debug(3, "GV_vect_exists");
+
+    if (NULL == gv_get_vect(id)) {
+	return (0);
+    }
+
+    for (i = 0; i < Next_vect && !found; i++) {
+	if (Vect_ID[i] == id) {
+	    found = 1;
+	}
+    }
+
+    return (found);
+}
+
+/*!
+   \brief Register new vector set
+
+   \return vector set id
+   \return -1 on error
+ */
+int GV_new_vector(void)
+{
+    geovect *nv;
+
+    if (Next_vect < MAX_VECTS) {
+	nv = gv_get_new_vect();
+	gv_set_defaults(nv);
+	Vect_ID[Next_vect] = nv->gvect_id;
+	++Next_vect;
+
+	G_debug(3, "GV_new_vector(): id=%d", nv->gvect_id);
+
+	return nv->gvect_id;
+    }
+
+    return -1;
+}
+
+/*!
+   \brief Get number of available vector sets
+
+   \return number of vector sets
+ */
+int GV_num_vects(void)
+{
+    return (gv_num_vects());
+}
+
+/*!
+   \brief Get list of vector sets
+
+   Must free when no longer needed!
+
+   \param numvects number of vector sets
+
+   \return pointer to list of point sets
+   \return NULL on error
+ */
+int *GV_get_vect_list(int *numvects)
+{
+    int i, *ret;
+
+    *numvects = Next_vect;
+
+    if (Next_vect) {
+	ret = (int *)G_malloc(Next_vect * sizeof(int));
+	if (!ret) {
+	    return (NULL);
+	}
+
+	for (i = 0; i < Next_vect; i++) {
+	    ret[i] = Vect_ID[i];
+	}
+
+	return (ret);
+    }
+
+    return (NULL);
+}
+
+/*!
+   \brief Delete vector set from list
+
+   \param id vector set id
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GV_delete_vector(int id)
+{
+    int i, j, found = 0;
+
+    G_debug(3, "GV_delete_vect");
+
+    if (GV_vect_exists(id)) {
+	gv_delete_vect(id);
+
+	for (i = 0; i < Next_vect && !found; i++) {
+	    if (Vect_ID[i] == id) {
+		found = 1;
+
+		for (j = i; j < Next_vect; j++) {
+		    Vect_ID[j] = Vect_ID[j + 1];
+		}
+	    }
+	}
+
+	if (found) {
+	    --Next_vect;
+	    return (1);
+	}
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Load vector set
+
+   Check to see if handle already loaded, if so - free before loading
+   new for now, always load to memory
+
+   \todo Load file handle & ready for reading instead of using
+   memory
+
+   \param id vector set id
+   \param filename filename
+
+   \return -1 on error (invalid vector set id)
+   \return 1 on success
+ */
+int GV_load_vector(int id, const char *filename)
+{
+    geovect *gv;
+
+    if (NULL == (gv = gv_get_vect(id))) {
+	return (-1);
+    }
+
+    if (gv->lines) {
+	gv_free_vectmem(gv);
+    }
+
+    gv->filename = G_store(filename);
+
+    if ((gv->lines = Gv_load_vect(filename, &(gv->n_lines)))) {
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get vector map name
+
+   Note: char array is allocated by G_store()
+
+   \param id vector set id
+   \param filename &filename
+
+   \return -1 on error (invalid vector set id)
+   \return 1 on success
+ */
+int GV_get_vectname(int id, char **filename)
+{
+    geovect *gv;
+
+    if (NULL == (gv = gv_get_vect(id))) {
+	return (-1);
+    }
+
+    *filename = G_store(gv->filename);
+
+    return (1);
+}
+
+/*!
+   \brief Set vector style
+
+   \param id vector set id
+   \param mem non-zero for use memory
+   \param color color value
+   \param width line width
+   \param flat non-zero for flat mode
+
+   \return -1 on error (invalid vector set id)
+   \return 1 on success
+ */
+int GV_set_style(int id, int mem, int color, int width, int flat)
+{
+    geovect *gv;
+
+    if (NULL == (gv = gv_get_vect(id))) {
+	return -1;
+    }
+
+    gv->use_mem = mem;
+    gv->flat_val = flat;
+    gv->style->color = color;
+    gv->style->width = width;
+
+    return 1;
+}
+
+
+/*!
+   \brief Get vector style
+
+   \param id vector set id
+   \param[out] mem non-zero for use memory
+   \param[out] color color value
+   \param[out] width line width
+   \param[out] flat non-zero for flat mode
+
+   \return -1 on error (invalid vector set id)
+   \return 1 on success
+ */
+int GV_get_style(int id, int *mem, int *color, int *width, int *flat)
+{
+    geovect *gv;
+
+    if (NULL == (gv = gv_get_vect(id))) {
+	return -1;
+    }
+
+    *mem = gv->use_mem;
+    *color = gv->style->color;
+    *width = gv->style->width;
+    *flat = gv->flat_val;
+
+    return 1;
+}
+
+/*!
+   \brief Set vector set style for thematic mapping
+   
+   Updates also style for each geoline.
+   
+   \param id vector set id
+   \param layer layer number for thematic mapping
+   \param color color column name
+   \param width width column name
+   \param colors pointer to Colors structure or NULL
+
+   \return 1 on success
+   \return -1 on error (point set not found)
+ */
+int GV_set_style_thematic(int id, int layer, const char* color, const char* width,
+			  struct Colors *color_rules)
+{
+    geovect *gv;
+
+    if (NULL == (gv = gv_get_vect(id))) {
+	return -1;
+    }
+
+    if(!gv->tstyle)
+	gv->tstyle = (gvstyle_thematic *)G_malloc(sizeof(gvstyle_thematic));
+    G_zero(gv->tstyle, sizeof(gvstyle_thematic));
+    
+    gv->tstyle->active = 1;
+    gv->tstyle->layer = layer;
+    if (color)
+	gv->tstyle->color_column = G_store(color);
+    if (width)
+	gv->tstyle->width_column = G_store(width);
+
+    Gv_load_vect_thematic(gv, color_rules);
+
+    return 1;
+}
+
+/*!
+   \brief Make style for thematic mapping inactive
+   
+   \param id vector set id
+
+   \return 1 on success
+   \return -1 on error (point set not found)
+ */
+int GV_unset_style_thematic(int id)
+{
+    geovect *gv;
+
+    G_debug(4, "GV_unset_style_thematic(): id=%d", id);
+
+    if (NULL == (gv = gv_get_vect(id))) {
+	return -1;
+    }
+
+    if (gv->tstyle) {
+	gv->tstyle->active = 0;
+    }
+
+    return 1;
+}
+
+/*!
+   \brief Set trans ?
+
+   \param id vector set id
+   \param xtrans,ytrans,ztrans x/y/z trans values
+ */
+void GV_set_trans(int id, float xtrans, float ytrans, float ztrans)
+{
+    geovect *gv;
+
+    G_debug(3, "GV_set_trans");
+
+    gv = gv_get_vect(id);
+
+    if (gv) {
+	gv->x_trans = xtrans;
+	gv->y_trans = ytrans;
+	gv->z_trans = ztrans;
+    }
+
+    return;
+}
+
+/*!
+   \brief Get trans ?
+
+   \param id vector set id
+   \param[out] xtrans,ytrans,ztrans x/y/z trans values
+ */
+int GV_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
+{
+    geovect *gv;
+
+    gv = gv_get_vect(id);
+
+    if (gv) {
+	*xtrans = gv->x_trans;
+	*ytrans = gv->y_trans;
+	*ztrans = gv->z_trans;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Select surface identified by hs to have vector identified
+   by hv draped over it
+
+   \param hv vector set id
+   \param hs surface id
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GV_select_surf(int hv, int hs)
+{
+    geovect *gv;
+
+    if (GV_surf_is_selected(hv, hs)) {
+	return (1);
+    }
+
+    gv = gv_get_vect(hv);
+
+    if (gv && GS_surf_exists(hs)) {
+	gv->drape_surf_id[gv->n_surfs] = hs;
+	gv->n_surfs += 1;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Unselect surface
+
+   \param hv vector set id
+   \param hs surface id
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GV_unselect_surf(int hv, int hs)
+{
+    geovect *gv;
+    int i, j;
+
+    if (!GV_surf_is_selected(hv, hs)) {
+	return (1);
+    }
+
+    gv = gv_get_vect(hv);
+
+    if (gv) {
+	for (i = 0; i < gv->n_surfs; i++) {
+	    if (gv->drape_surf_id[i] == hs) {
+		for (j = i; j < gv->n_surfs - 1; j++) {
+		    gv->drape_surf_id[j] = gv->drape_surf_id[j + 1];
+		}
+
+		gv->n_surfs -= 1;
+
+		return (1);
+	    }
+	}
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Check if surface is selected
+
+   \param hv vector set id
+   \param hs surface id
+
+   \return 1 selected
+   \return 0 not selected
+ */
+int GV_surf_is_selected(int hv, int hs)
+{
+    int i;
+    geovect *gv;
+
+    gv = gv_get_vect(hv);
+
+    if (gv) {
+	for (i = 0; i < gv->n_surfs; i++) {
+	    if (hs == gv->drape_surf_id[i]) {
+		return (1);
+	    }
+	}
+    }
+
+    return (0);
+}
+
+/*!
+   \brief Draw vector set
+
+   \param vid vector set id
+ */
+void GV_draw_vect(int vid)
+{
+    geosurf *gs;
+    geovect *gv;
+    int i;
+
+    gv = gv_get_vect(vid);
+
+    if (gv) {
+	for (i = 0; i < gv->n_surfs; i++) {
+	    gs = gs_get_surf(gv->drape_surf_id[i]);
+
+	    if (gs) {
+		gvd_vect(gv, gs, 0);
+	    }
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw all loaded vector sets
+ */
+void GV_alldraw_vect(void)
+{
+    int id;
+
+    for (id = 0; id < Next_vect; id++) {
+	GV_draw_vect(Vect_ID[id]);
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw vector set (fast mode)
+
+   \todo Seems to be broken, nothing is drawn
+
+   \param vid vector set id
+ */
+void GV_draw_fastvect(int vid)
+{
+    geosurf *gs;
+    geovect *gv;
+    int i;
+
+    gv = gv_get_vect(vid);
+
+    if (gv) {
+	for (i = 0; i < gv->n_surfs; i++) {
+	    gs = gs_get_surf(gv->drape_surf_id[i]);
+
+	    if (gs) {
+		gvd_vect(gv, gs, 1);
+	    }
+	}
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw all loaded vector sets (fast mode)
+ */
+void GV_alldraw_fastvect(void)
+{
+    int id;
+
+    for (id = 0; id < Next_vect; id++) {
+	GV_draw_fastvect(Vect_ID[id]);
+    }
+
+    return;
+}
+
+/*!
+   \brief Set client data
+
+   \param id vector set id
+   \param clientd pointer to client data
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GV_Set_ClientData(int id, void *clientd)
+{
+    geovect *gv;
+
+    gv = gv_get_vect(id);
+    if (gv) {
+	gv->clientdata = clientd;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get client data
+
+   \param id vector set id
+
+   \return pointer to client data
+   \return NULL on error
+ */
+void *GV_Get_ClientData(int id)
+{
+    geovect *gv;
+
+    gv = gv_get_vect(id);
+
+    if (gv) {
+	return (gv->clientdata);
+    }
+
+    return (NULL);
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gv3.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/Gv3.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gv3.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gv3.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,419 @@
+/*!
+   \file lib/ogsf/Gv3.c
+
+   \brief OGSF library - loading vector sets (lower level functions)
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   (C) 1999-2008, 2011 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.
+
+   \author Bill Brown USACERL (December 1993)
+   \author Updated by Martin Landa <landa.martin gmail.com>
+   (doxygenized in May 2008, thematic mapping in August 2011)
+ */
+
+#include <stdlib.h>
+
+#include <grass/gis.h>
+#include <grass/colors.h>
+#include <grass/raster.h>
+#include <grass/vector.h>
+#include <grass/dbmi.h>
+#include <grass/glocale.h>
+#include <grass/ogsf.h>
+
+/*
+   #define TRAK_MEM
+*/
+
+#ifdef TRAK_MEM
+static int Tot_mem = 0;
+#endif
+
+/*!
+   \brief Load vector map to memory
+
+   The other alternative may be to load to a tmp file
+
+   \param grassname vector map name
+   \param[out] number of loaded features
+
+   \return pointer to geoline struct
+   \return NULL on failure
+ */
+geoline *Gv_load_vect(const char *grassname, int *nlines)
+{
+    struct Map_info map;
+    struct line_pnts *points;
+    struct line_cats *Cats = NULL;
+    geoline *top, *gln, *prev;
+    int np, i, n, nareas, nl = 0, area, type, is3d;
+    struct Cell_head wind;
+    float vect[2][3];
+    const char *mapset;
+
+    mapset = G_find_vector2(grassname, "");
+    if (!mapset) {
+	G_warning(_("Vector map <%s> not found"), grassname);
+	return NULL;
+    }
+
+    Vect_set_open_level(2);
+    if (Vect_open_old(&map, grassname, "") == -1) {
+	G_warning(_("Unable to open vector map <%s>"),
+		  G_fully_qualified_name(grassname, mapset));
+	return NULL;
+    }
+
+    top = gln = (geoline *) G_malloc(sizeof(geoline));	/* G_fatal_error */
+    if (!top) {
+	return NULL;
+    }
+
+    prev = top;
+
+#ifdef TRAK_MEM
+    Tot_mem += sizeof(geoline);
+#endif
+
+    points = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+
+    G_get_set_window(&wind);
+    Vect_set_constraint_region(&map, wind.north, wind.south, wind.east,
+			       wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
+
+    is3d = Vect_is_3d(&map);
+
+    /* Read areas */
+    n = Vect_get_num_areas(&map);
+    nareas = 0;
+    G_debug(3, "Reading vector areas (nareas = %d)", n);
+    for (area = 1; area <= n; area++) {
+	G_debug(3, " area %d", area);
+	Vect_get_area_points(&map, area, points);
+	if (points->n_points < 3)
+	    continue;
+
+	/* initialize style */
+	gln->highlighted = 0;
+
+	gln->type = OGSF_POLYGON;
+	gln->npts = np = points->n_points;
+	G_debug(3, "  np = %d", np);
+
+	if (is3d) {
+	    gln->dims = 3;
+	    gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3));	/* G_fatal_error */
+	    if (!gln->p3) {
+		return (NULL);
+	    }
+#ifdef TRAK_MEM
+	    Tot_mem += (np * sizeof(Point3));
+#endif
+	}
+	else {
+	    gln->dims = 2;
+	    gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2));	/* G_fatal_error */
+	    if (!gln->p2) {
+		return (NULL);
+	    }
+#ifdef TRAK_MEM
+	    Tot_mem += (np * sizeof(Point2));
+#endif
+	}
+
+	for (i = 0; i < np; i++) {
+	    if (is3d) {
+		gln->p3[i][X] = points->x[i];
+		gln->p3[i][Y] = points->y[i];
+		gln->p3[i][Z] = points->z[i];
+	    }
+	    else {
+		gln->p2[i][X] = points->x[i];
+		gln->p2[i][Y] = points->y[i];
+	    }
+	}
+	/* Calc normal (should be average) */
+	if (is3d) {
+	    vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
+	    vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
+	    vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
+	    vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
+	    vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
+	    vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
+	    GS_v3cross(vect[1], vect[0], gln->norm);
+
+	}
+
+	gln->cats = NULL;
+	gln->next = (geoline *) G_malloc(sizeof(geoline));	/* G_fatal_error */
+	if (!gln->next) {
+	    return (NULL);
+	}
+
+#ifdef TRAK_MEM
+	Tot_mem += sizeof(geoline);
+#endif
+
+	prev = gln;
+	gln = gln->next;
+	nareas++;
+    }
+    G_debug(3, "%d areas loaded", nareas);
+
+    /* Read all lines */
+    G_debug(3, "Reading vector lines ...");
+    while (-1 < (type = Vect_read_next_line(&map, points, Cats))) {
+	G_debug(3, "line type = %d", type);
+	if (type & (GV_LINES | GV_FACE)) {
+	    if (type & (GV_LINES)) {
+		gln->type = OGSF_LINE;
+	    }
+	    else {
+		gln->type = OGSF_POLYGON;
+		/* Vect_append_point ( points, points->x[0], points->y[0], points->z[0] ); */
+	    }
+
+	    /* initialize style */
+	    gln->highlighted = 0;
+
+	    gln->npts = np = points->n_points;
+	    G_debug(3, "  np = %d", np);
+
+	    if (is3d) {
+		gln->dims = 3;
+		gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3));	/* G_fatal_error */
+		if (!gln->p3) {
+		    return (NULL);
+		}
+#ifdef TRAK_MEM
+		Tot_mem += (np * sizeof(Point3));
+#endif
+	    }
+	    else {
+		gln->dims = 2;
+		gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2));	/* G_fatal_error */
+		if (!gln->p2) {
+		    return (NULL);
+		}
+#ifdef TRAK_MEM
+		Tot_mem += (np * sizeof(Point2));
+#endif
+	    }
+
+	    for (i = 0; i < np; i++) {
+		if (is3d) {
+		    gln->p3[i][X] = points->x[i];
+		    gln->p3[i][Y] = points->y[i];
+		    gln->p3[i][Z] = points->z[i];
+		}
+		else {
+		    gln->p2[i][X] = points->x[i];
+		    gln->p2[i][Y] = points->y[i];
+		}
+	    }
+	    /* Calc normal (should be average) */
+	    if (is3d && gln->type == OGSF_POLYGON) {
+		vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
+		vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
+		vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
+		vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
+		vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
+		vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
+		GS_v3cross(vect[1], vect[0], gln->norm);
+		G_debug(3, "norm %f %f %f", gln->norm[0], gln->norm[1],
+			gln->norm[2]);
+	    }
+
+	    /* Store category info for thematic display */
+	    if (Cats->n_cats > 0) {
+		gln->cats = Cats;
+		Cats = Vect_new_cats_struct();
+	    }
+	    else {
+		gln->cats = NULL;
+		Vect_reset_cats(Cats);
+	    }
+
+	    gln->next = (geoline *) G_malloc(sizeof(geoline));	/* G_fatal_error */
+	    if (!gln->next) {
+		return (NULL);
+	    }
+#ifdef TRAK_MEM
+	    Tot_mem += sizeof(geoline);
+#endif
+
+	    prev = gln;
+	    gln = gln->next;
+	    nl++;
+	}
+    }
+    G_debug(3, "%d lines loaded", nl);
+
+    nl += nareas;
+
+    prev->next = NULL;
+    G_free(gln);
+
+#ifdef TRAK_MEM
+    Tot_mem -= sizeof(geoline);
+#endif
+
+    Vect_close(&map);
+
+    if (!nl) {
+	G_warning(_("No features from vector map <%s> fall within current region"),
+		  G_fully_qualified_name(grassname, mapset));
+	return (NULL);
+    }
+    else {
+	G_message(_("Vector map <%s> loaded (%d features)"),
+		  G_fully_qualified_name(grassname, mapset), nl);
+    }
+
+    *nlines = nl;
+
+#ifdef TRAK_MEM
+    G_debug(3, "Total vect memory = %d Kbytes", Tot_mem / 1000);
+#endif
+
+    return (top);
+}
+
+/*! 
+   \brief Tracking memory 
+
+   \param minus mimus number 
+ */
+void sub_Vectmem(int minus)
+{
+    G_debug(5, "sub_Vectmem(): minus=%d", minus);
+#ifdef TRAK_MEM
+    {
+	Tot_mem -= minus;
+    }
+#endif
+
+    return;
+}
+
+/*!
+  \brief Load styles for geolines based on thematic mapping
+
+  \param gv pointer to geovect structure
+  \param colors pointer to Colors structure or NULL
+
+  \return number of features defined by thematic mapping
+  \return -1 on error
+*/
+int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
+{
+    geoline *gvt;
+
+    struct Map_info Map;
+    struct field_info *Fi;
+    
+    int nvals, cat, nlines, nskipped;
+    int red, blu, grn;
+    const char *str;
+    const char *mapset;
+
+    dbDriver *driver;
+    dbValue value;
+    
+    if(!gv || !gv->tstyle || !gv->filename)
+	return -1;
+
+    mapset = G_find_vector2(gv->filename, "");
+    if (!mapset) {
+	G_fatal_error(_("Vector map <%s> not found"), gv->filename);
+    }
+    
+    Vect_set_open_level(1);
+    if (Vect_open_old(&Map, gv->filename, "") == -1) {
+	G_fatal_error(_("Unable to open vector map <%s>"),
+		      G_fully_qualified_name(gv->filename, mapset));
+    }
+    
+    Fi = Vect_get_field(&Map, gv->tstyle->layer);
+    if (!Fi) {
+	G_warning(_("Database connection not defined for layer %d"),
+		  gv->tstyle->layer);
+    }
+    else {
+      driver = db_start_driver_open_database(Fi->driver, Fi->database);
+      if (!driver)
+	  G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+			Fi->database, Fi->driver);
+    }
+    G_message(_("Loading thematic vector layer <%s>..."),
+	      G_fully_qualified_name(gv->filename, mapset));
+    nlines = nskipped = 0;
+    for(gvt = gv->lines; gvt; gvt = gvt->next) {
+	gvt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
+	G_zero(gvt->style, sizeof(gvstyle));
+	
+	/* use default style */
+	gvt->style->color  = gv->style->color;
+	gvt->style->symbol = gv->style->symbol;
+	gvt->style->size   = gv->style->size;
+	gvt->style->width  = gv->style->width;
+
+	cat = -1;
+	if (gvt->cats)
+	    Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat);
+	if (cat < 0) {
+	    nskipped++;
+	    continue;
+	}
+	
+	/* color */
+	if (colors) {
+	    if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
+		G_warning(_("No color rule defined for category %d"), cat);
+		gvt->style->color = gv->style->color;
+	    }
+	    gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
+		((int)((blu) << 16) & BLU_MASK);
+	}
+	
+	if (gv->tstyle->color_column) {
+	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->color_column, &value);
+	    if (nvals < 1)
+		continue;
+	    str = db_get_value_string(&value);
+	    if (!str)
+		continue;
+	    if (G_str_to_color(str, &red, &grn, &blu) != 1) {
+		G_warning(_("Invalid color definition (%s)"),
+			  str);
+		gvt->style->color = gv->style->color;
+	    }
+	    else {
+		gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
+		    ((int)((blu) << 16) & BLU_MASK);
+	    }
+	}
+	
+	/* width */
+	if (gv->tstyle->width_column) {
+	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->width_column, &value);
+	    if (nvals < 1)
+		continue;
+	    gvt->style->width = db_get_value_int(&value);
+	}
+
+	nlines++;
+    }
+
+    if (nskipped > 0)
+	G_warning(_("%d features without category. "
+		    "Unable to determine color rules for features without category."),
+		  nskipped);
+    
+    return nlines;
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gvl2.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/GVL2.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gvl2.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gvl2.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,1521 @@
+/*!
+   \file GVL2.c
+
+   \brief OGSF library - loading and manipulating volumes
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   (C) 1999-2008 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.
+
+   \author Bill Brown UI-GMSL (May 1997)
+   Tomas Paudits (February 2004)
+ */
+
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/raster3d.h>
+#include <grass/ogsf.h>
+#include <grass/glocale.h>
+#include "gsget.h"
+
+static int Vol_ID[MAX_VOLS];
+static int Next_vol = 0;
+
+static RASTER3D_Region wind3;
+static double Region[6];
+
+/*!
+   \brief Library intialization for volumes
+
+   Set region extent (N,S,W,E,T,B)
+ */
+void GVL_libinit(void)
+{
+    Rast3d_init_defaults();
+    Rast3d_get_window(&wind3);
+
+    Region[0] = wind3.north;
+    Region[1] = wind3.south;
+    Region[2] = wind3.west;
+    Region[3] = wind3.east;
+    Region[4] = wind3.top;
+    Region[5] = wind3.bottom;
+
+    return;
+}
+
+/*!
+   \brief Initialize 3D region
+
+   Set region extent (N,S,W,E,T,B)
+ */
+void GVL_init_region(void)
+{
+    Rast3d_read_window(&wind3, NULL);
+
+    Region[0] = wind3.north;
+    Region[1] = wind3.south;
+    Region[2] = wind3.west;
+    Region[3] = wind3.east;
+    Region[4] = wind3.top;
+    Region[5] = wind3.bottom;
+
+    return;
+}
+
+/*!
+   \brief Get region extent settings
+
+   \param[out] n,s,w,e north, south, west, east
+   \param[out] t,b top, bottom
+
+   \return 1
+ */
+int GVL_get_region(float *n, float *s, float *w, float *e, float *t, float *b)
+{
+    *n = Region[0];
+    *s = Region[1];
+    *w = Region[2];
+    *e = Region[3];
+    *t = Region[4];
+    *b = Region[5];
+
+    return (1);
+}
+
+/*!
+   \brief Get window 
+
+   \todo gvl_file.c use this - change
+
+   \return pointer to RASTER3D_Region struct (static)
+ */
+void *GVL_get_window()
+{
+    return &wind3;
+}
+
+/*!
+   \brief Check if volume set exists
+
+   \param id volume set id
+
+   \return 1 found
+   \return 0 not found
+ */
+int GVL_vol_exists(int id)
+{
+    int i, found = 0;
+
+    G_debug(3, "GVL_vol_exists");
+
+    if (NULL == gvl_get_vol(id)) {
+	return (0);
+    }
+
+    for (i = 0; i < Next_vol && !found; i++) {
+	if (Vol_ID[i] == id) {
+	    found = 1;
+	}
+    }
+
+    return (found);
+}
+
+/*!
+   \brief Create new volume set
+
+   \return volume set id
+   \return -1 on error
+ */
+int GVL_new_vol(void)
+{
+    geovol *nvl;
+
+    G_debug(3, "GVL_new_vol():");
+
+    if (Next_vol < MAX_VOLS) {
+	nvl = gvl_get_new_vol();
+
+	gvl_init_vol(nvl, wind3.west + wind3.ew_res / 2.,
+		     wind3.south + wind3.ns_res / 2., wind3.bottom,
+		     wind3.rows, wind3.cols, wind3.depths,
+		     wind3.ew_res, wind3.ns_res, wind3.tb_res);
+
+	Vol_ID[Next_vol] = nvl->gvol_id;
+	++Next_vol;
+
+	G_debug(3, "    id=%d", nvl->gvol_id);
+	
+	return (nvl->gvol_id);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get number of loaded volume sets
+
+   \return number of volume sets
+ */
+int GVL_num_vols(void)
+{
+    return (gvl_num_vols());
+}
+
+/*!
+   \brief Get list of loaded volume sets
+
+   Must be freed if not needed!
+
+   \param[out] numvols number of volume sets
+
+   \return pointer to list of volume sets
+   \return NULL on error
+ */
+int *GVL_get_vol_list(int *numvols)
+{
+    int i, *ret;
+
+    *numvols = Next_vol;
+
+    if (Next_vol) {
+	ret = (int *)G_malloc(Next_vol * sizeof(int));
+	if (!ret)
+	    return (NULL);
+
+	for (i = 0; i < Next_vol; i++) {
+	    ret[i] = Vol_ID[i];
+	}
+
+	return (ret);
+    }
+
+    return (NULL);
+}
+
+/*!
+   \brief Delete volume set from list
+
+   \param id volume set id
+
+   \return 1 on success
+   \return -1 on error (invalid volume set id)
+ */
+int GVL_delete_vol(int id)
+{
+    int i, j, found = 0;
+
+    G_debug(3, "GVL_delete_vol");
+
+    if (GVL_vol_exists(id)) {
+
+	for (i = 0; i < GVL_isosurf_num_isosurfs(id); i++) {
+	    GVL_isosurf_del(id, 0);
+	}
+
+	for (i = 0; i < GVL_slice_num_slices(id); i++) {
+	    GVL_slice_del(id, 0);
+	}
+
+	gvl_delete_vol(id);
+
+	for (i = 0; i < Next_vol && !found; i++) {
+	    if (Vol_ID[i] == id) {
+		found = 1;
+		for (j = i; j < Next_vol; j++) {
+		    Vol_ID[j] = Vol_ID[j + 1];
+		}
+	    }
+	}
+
+	if (found) {
+	    --Next_vol;
+
+	    return (1);
+	}
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Load 3d raster map to volume set
+
+   \param id volume set id
+   \param filename 3d raster map name
+
+   \return -1 on error
+   \return 0 on success
+ */
+int GVL_load_vol(int id, const char *filename)
+{
+    geovol *gvl;
+    int handle;
+
+    G_debug(3, "GVL_load_vol(): id=%d, name=%s", id, filename);
+
+    if (NULL == (gvl = gvl_get_vol(id))) {
+	return (-1);
+    }
+
+    G_message(_("Loading 3d raster map <%s>..."), filename);
+
+    if (0 > (handle = gvl_file_newh(filename, VOL_FTYPE_RASTER3D)))
+	return (-1);
+
+    gvl->hfile = handle;
+
+    return (0);
+}
+
+/*!
+   \brief Get volume set name
+
+   \param id volume set id
+   \param[out] filename name (must be allocated)
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_get_volname(int id, char *filename)
+{
+    geovol *gvl;
+
+    if (NULL == (gvl = gvl_get_vol(id))) {
+	return (-1);
+    }
+
+    if (0 > gvl->hfile) {
+	return (-1);
+    }
+
+    strcpy(filename, gvl_file_get_name(gvl->hfile));
+
+    return (1);
+}
+
+/*!
+   \brief Get volume dimensions
+
+   \param id volume set id
+   \param[out] rows,cols,depths number of rows, cols, depths
+ */
+void GVL_get_dims(int id, int *rows, int *cols, int *depths)
+{
+    geovol *gvl;
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	*rows = gvl->rows;
+	*cols = gvl->cols;
+	*depths = gvl->depths;
+    }
+
+    G_debug(3, "GVL_get_dims() id=%d, rows=%d, cols=%d, depths=%d",
+	    gvl->gvol_id, gvl->rows, gvl->cols, gvl->depths);
+    
+    return;
+}
+
+/*!
+   \brief Set trans ?
+
+   \param id volume set id
+   \param xtrans,ytrans,ztrans x/y/z trans values
+ */
+void GVL_set_trans(int id, float xtrans, float ytrans, float ztrans)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_set_trans");
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	gvl->x_trans = xtrans;
+	gvl->y_trans = ytrans;
+	gvl->z_trans = ztrans;
+    }
+
+    return;
+}
+
+/*!
+   \brief Get trans ?
+
+   \param id volume set id
+   \param[out] xtrans,ytrans,ztrans x/y/z trans values
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GVL_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
+{
+    geovol *gvl;
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	*xtrans = gvl->x_trans;
+	*ytrans = gvl->y_trans;
+	*ztrans = gvl->z_trans;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set drawing wire box
+
+   \param id volume set id
+   \param draw_wire 1 for drawing wire, 0 otherwise
+ */
+void GVL_set_draw_wire(int id, int draw_wire)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_set_draw_wire");
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	gvl->draw_wire = draw_wire;
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw volume set
+
+   \param vid volume set id
+ */
+void GVL_draw_vol(int vid)
+{
+    geovol *gvl;
+
+    gvl = gvl_get_vol(vid);
+
+    if (gvl) {
+	gvld_vol(gvl);
+        if (gvl->draw_wire) {
+	    gvld_wind3_box(gvl);
+        }
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw volume in wire mode
+
+   \param id volume set id
+ */
+void GVL_draw_wire(int id)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_draw_wire(): id=%d", id);
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	gvld_wire_vol(gvl);
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw all volume sets
+ */
+void GVL_alldraw_vol(void)
+{
+    int id;
+
+    for (id = 0; id < Next_vol; id++) {
+	GVL_draw_vol(Vol_ID[id]);
+    }
+
+    return;
+}
+
+/*!
+   \brief Draw all volume sets in wire mode
+ */
+void GVL_alldraw_wire(void)
+{
+    int id;
+
+    for (id = 0; id < Next_vol; id++) {
+	GVL_draw_wire(Vol_ID[id]);
+    }
+
+    return;
+}
+
+/*!
+   \brief Set client data for volume set
+
+   \param id volume set id
+   \param clientd pointer to client data
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GVL_Set_ClientData(int id, void *clientd)
+{
+    geovol *gvl;
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	gvl->clientdata = clientd;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get client data
+
+   \param id volume set id
+
+   \return pointer to client data
+   \return NULL on error
+ */
+void *GVL_Get_ClientData(int id)
+{
+    geovol *gvl;
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	return (gvl->clientdata);
+    }
+
+    return (NULL);
+}
+
+/*!
+   \brief Set focus on map center
+
+   \param id volume set id
+ */
+void GVL_set_focus_center_map(int id)
+{
+    float center[3];
+    geovol *gvl;
+
+    G_debug(3, "GS_set_focus_center_map");
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	center[X] = (gvl->xmax - gvl->xmin) / 2.;
+	center[Y] = (gvl->ymax - gvl->ymin) / 2.;
+	center[Z] = (gvl->zmax - gvl->zmin) / 2.;
+
+	GS_set_focus(center);
+    }
+
+    return;
+}
+
+/************************************************************************/
+/* ISOSURFACES */
+
+/************************************************************************/
+
+/*!
+   \brief Get draw resolution for isosurface
+
+   \todo error handling
+
+   \param id volume set id
+   \param[out] xres,yres,zres x/y/z resolution value
+ */
+void GVL_isosurf_get_drawres(int id, int *xres, int *yres, int *zres)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_isosurf_get_drawres");
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	*xres = gvl->isosurf_x_mod;
+	*yres = gvl->isosurf_y_mod;
+	*zres = gvl->isosurf_z_mod;
+    }
+
+    return;
+}
+
+/*!
+   \brief Set isosurface draw resolution
+
+   \param id volume set id
+   \param xres,yres,zres x/y/z resolution value
+
+   \return -1 on error (invalid values/volume set id)
+   \return 0 on success
+ */
+int GVL_isosurf_set_drawres(int id, int xres, int yres, int zres)
+{
+    geovol *gvl;
+    int i;
+
+    G_debug(3, "GVL_isosurf_set_drawres(): id=%d", id);
+
+    if (xres < 1 || yres < 1 || zres < 1) {
+	return (-1);
+    }
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	gvl->isosurf_x_mod = xres;
+	gvl->isosurf_y_mod = yres;
+	gvl->isosurf_z_mod = zres;
+
+	for (i = 0; i < gvl->n_isosurfs; i++) {
+	    gvl_isosurf_set_att_changed(gvl->isosurf[i], ATT_TOPO);
+	}
+
+	return (0);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get isosurface draw mode
+
+   \param id volume set id
+   \param[out] mode draw-mode
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GVL_isosurf_get_drawmode(int id, int *mode)
+{
+    geovol *gvl;
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	*mode = gvl->isosurf_draw_mode;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set isosurface draw mode
+
+   \param id volume set id
+   \param mode draw mode
+
+   \return 0 on success
+   \return -1 on error (invalid volume set id)
+ */
+int GVL_isosurf_set_drawmode(int id, int mode)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_isosurf_set_drawmode(): id=%d mode=%d", id, mode);
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	gvl->isosurf_draw_mode = mode;
+
+	return (0);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Add isosurface
+
+   \param id volume set id
+
+   \return -1 on error (invalid volume set id
+   \return 1 on success
+ */
+int GVL_isosurf_add(int id)
+{
+    geovol *gvl;
+    geovol_isosurf *isosurf;
+
+    G_debug(3, "GVL_isosurf_add() id=%d", id);
+
+    gvl = gvl_get_vol(id);
+
+    if (!gvl)
+	return (-1);
+
+    if (gvl->n_isosurfs == MAX_ISOSURFS)
+	return (-1);
+
+    isosurf = (geovol_isosurf *) G_malloc(sizeof(geovol_isosurf));
+    if (!isosurf) {
+	return (-1);
+    }
+
+    gvl_isosurf_init(isosurf);
+
+    gvl->n_isosurfs++;
+    gvl->isosurf[gvl->n_isosurfs - 1] = (geovol_isosurf *) isosurf;
+
+    return (1);
+}
+
+/*!
+   \brief Delete isosurface
+
+   \param id volume set id
+   \param isosurf_id isosurface id
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_isosurf_del(int id, int isosurf_id)
+{
+    geovol *gvl;
+    geovol_isosurf *isosurf;
+    int i;
+
+    G_debug(3, "GVL_isosurf_del");
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (!isosurf)
+	return (-1);
+
+    if (!gvl_isosurf_freemem(isosurf)) {
+	return (-1);
+    }
+
+    gvl = gvl_get_vol(id);
+
+    G_free(gvl->isosurf[isosurf_id]);
+
+    for (i = isosurf_id + 1; i < gvl->n_isosurfs; i++) {
+	gvl->isosurf[i - 1] = gvl->isosurf[i];
+    }
+
+    gvl->n_isosurfs--;
+
+    return (1);
+}
+
+/*!
+   \brief Move up isosurface in list
+
+   \param id volume set id
+   \param isosurf_id isosurface id
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_isosurf_move_up(int id, int isosurf_id)
+{
+    geovol *gvl;
+    geovol_isosurf *tmp;
+
+    G_debug(3, "GVL_isosurf_move_up");
+
+    gvl = gvl_get_vol(id);
+
+    if (!gvl)
+	return (-1);
+
+    if (isosurf_id < 0 || isosurf_id > (gvl->n_isosurfs - 1))
+	return (-1);
+
+    if (isosurf_id == 0)
+	return (1);
+
+    tmp = gvl->isosurf[isosurf_id - 1];
+    gvl->isosurf[isosurf_id - 1] = gvl->isosurf[isosurf_id];
+    gvl->isosurf[isosurf_id] = tmp;
+
+    return (1);
+}
+
+/*!
+   \brief Move down isosurface in list
+
+   \param id volume set id
+   \param isosurf_id isosurface id
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_isosurf_move_down(int id, int isosurf_id)
+{
+    geovol *gvl;
+    geovol_isosurf *tmp;
+
+    G_debug(3, "GVL_isosurf_move_up");
+
+    gvl = gvl_get_vol(id);
+
+    if (!gvl)
+	return (-1);
+
+    if (isosurf_id < 0 || isosurf_id > (gvl->n_isosurfs - 1))
+	return (-1);
+
+    if (isosurf_id == (gvl->n_isosurfs - 1))
+	return (1);
+
+    tmp = gvl->isosurf[isosurf_id + 1];
+    gvl->isosurf[isosurf_id + 1] = gvl->isosurf[isosurf_id];
+    gvl->isosurf[isosurf_id] = tmp;
+
+    return (1);
+}
+
+/*!
+   \brief Get isosurface attributes
+
+   \param id volume set id
+   \param isosurf_id surface id
+   \param att attribute id
+   \param[out] set
+   \param[out] constant
+   \param[out] mapname
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_isosurf_get_att(int id, int isosurf_id,
+			int att, int *set, float *constant, char *mapname)
+{
+    int src;
+    geovol_isosurf *isosurf;
+
+    G_debug(3, "GVL_isosurf_get_att");
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (isosurf) {
+	if (-1 != (src = gvl_isosurf_get_att_src(isosurf, att))) {
+	    *set = src;
+
+	    if (src == CONST_ATT) {
+		*constant = isosurf->att[att].constant;
+	    }
+	    else if (src == MAP_ATT) {
+		strcpy(mapname, gvl_file_get_name(isosurf->att[att].hfile));
+	    }
+
+	    return (1);
+	}
+
+	return (-1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Unset isosurface attributes
+
+   \param id volume set id
+   \param isosurface_id isosurface id
+   \param att attribute id
+
+   \return ?
+   \return -1 on error
+ */
+int GVL_isosurf_unset_att(int id, int isosurf_id, int att)
+{
+    geovol_isosurf *isosurf;
+
+    G_debug(3, "GVL_isosurf_unset_att");
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (isosurf) {
+	return (gvl_isosurf_set_att_src(isosurf, att, NOTSET_ATT));
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set constant isosurface attribute
+
+   Attributes:
+    - ATT_NORM
+    - ATT_TOPO topography (level) constant
+    - ATT_COLOR color map/constant
+    - ATT_MASK mask map
+    - ATT_TRANSP transparency map/constant
+    - ATT_SHINE shininess map/constant
+    - ATT_EMIT emission map/constant
+
+   \param id volume set id
+   \param isosurf_id isosurface id (0 - MAX_ISOSURFS)
+   \param att attribute descriptor
+   \param constant constant value
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GVL_isosurf_set_att_const(int id, int isosurf_id, int att, float constant)
+{
+    geovol_isosurf *isosurf;
+
+    G_debug(3, "GVL_isosurf_set_att_const() id=%d isosurf_id=%d "
+	    "att=%d const=%f", id, isosurf_id, att, constant);
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (isosurf) {
+	return (gvl_isosurf_set_att_const(isosurf, att, constant));
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set isosurface map attribute
+
+   Attributes:
+    - ATT_NORM
+    - ATT_TOPO topography (level) constant
+    - ATT_COLOR color map/constant
+    - ATT_MASK mask map
+    - ATT_TRANSP transparency map/constant
+    - ATT_SHINE shininess map/constant
+    - ATT_EMIT emission map/constant
+
+   \param id volume set id
+   \param isosurf_id isosurface id (0 - MAX_ISOSURFS)
+   \param att attribute descriptor
+   \param filename map name
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GVL_isosurf_set_att_map(int id, int isosurf_id, int att,
+			    const char *filename)
+{
+    geovol_isosurf *isosurf;
+
+    G_debug(3, "GVL_isosurf_set_att_map(): id=%d, isosurf_id=%d "
+	    "att=%d map=%s", id, isosurf_id, att, filename);
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (isosurf) {
+	return gvl_isosurf_set_att_map(isosurf, att, filename);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get isosurface flags
+
+   \param id volume set id
+   \param isosurf_id isosurface id
+   \param[out] inout map name
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GVL_isosurf_get_flags(int id, int isosurf_id, int *inout)
+{
+    geovol_isosurf *isosurf;
+
+    G_debug(3, "GVL_isosurf_get_flags");
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (isosurf) {
+	*inout = isosurf->inout_mode;
+
+	return (1);
+    }
+    return (-1);
+}
+
+/*!
+   \brief Set isosurface flags
+
+   \param id volume set id
+   \param isosurf_id isosurface id
+   \param inout map name
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GVL_isosurf_set_flags(int id, int isosurf_id, int inout)
+{
+    geovol_isosurf *isosurf;
+
+    G_debug(3, "GVL_isosurf_get_flags");
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (isosurf) {
+	isosurf->inout_mode = inout;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get number of available isosurfaces
+
+   \param id volume set id
+
+   \return number of isosurfaces
+   \return -1 on error
+ */
+int GVL_isosurf_num_isosurfs(int id)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_isosurf_num_isosurfs");
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	return gvl->n_isosurfs;
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set mask attribute mode
+
+   Mask attribute special: constant is set to indicate invert or no
+
+   \param id volume set id
+   \param isosurf_id isosurface id
+   \param mode attribute mode
+
+   \return mode id
+   \return -1 on error
+ */
+int GVL_isosurf_set_maskmode(int id, int isosurf_id, int mode)
+{
+    geovol_isosurf *isosurf;
+
+    G_debug(3, "GVL_isosurf_set_att_const");
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (isosurf) {
+	isosurf->att[ATT_MASK].constant = mode;
+
+	return (mode);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get isosurface mask mode
+
+   \param id volume set id
+   \param isosurf_id isosurface id
+   \param mode attribute mode
+
+   \return 1 on success
+   \return -1 on error
+ */
+int GVL_isosurf_get_maskmode(int id, int isosurf_id, int *mode)
+{
+    geovol_isosurf *isosurf;
+
+    isosurf = gvl_isosurf_get_isosurf(id, isosurf_id);
+
+    if (isosurf) {
+	*mode = isosurf->att[ATT_MASK].constant;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/************************************************************************/
+/* SLICES */
+
+/************************************************************************/
+
+/*!
+   \brief Get draw resolution of slice
+
+   \param id volume set id
+   \param[out] xres,yres,zres x/y/z resolution value
+ */
+void GVL_slice_get_drawres(int id, int *xres, int *yres, int *zres)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_slice_get_drawres");
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	*xres = gvl->slice_x_mod;
+	*yres = gvl->slice_y_mod;
+	*zres = gvl->slice_z_mod;
+    }
+
+    return;
+}
+
+/*!
+   \brief Set slice draw resolution
+
+   \param id volume set id
+   \param xres,yres,zres x/y/z resolution value
+
+   \return 0 on success
+   \return -1 on error (invalid value or id)
+ */
+int GVL_slice_set_drawres(int id, int xres, int yres, int zres)
+{
+    geovol *gvl;
+    int i;
+
+    G_debug(3, "GVL_slice_set_drawres(): id=%d", id);
+
+    if (xres < 1 || yres < 1 || zres < 1) {
+	return (-1);
+    }
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	gvl->slice_x_mod = xres;
+	gvl->slice_y_mod = yres;
+	gvl->slice_z_mod = zres;
+
+	for (i = 0; i < gvl->n_slices; i++) {
+	    gvl->slice[i]->changed = 1;
+	}
+
+	return (0);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get slice draw mode
+
+   \param id volume set id
+   \param[out] mode draw mode
+
+   \return 1 on success
+   \return -1 on error (invalid id)
+ */
+int GVL_slice_get_drawmode(int id, int *mode)
+{
+    geovol *gvl;
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	*mode = gvl->slice_draw_mode;
+
+	return (1);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Set slice draw mode
+
+   \param id volume set id
+   \param mode draw mode
+
+   \return 0 on success
+   \return -1 on error (invalid id)
+ */
+int GVL_slice_set_drawmode(int id, int mode)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_slice_set_drawmode(): id=%d, mode=%d", id, mode);
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	gvl->slice_draw_mode = mode;
+
+	return (0);
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Add slice
+
+   \param id volume set id
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_slice_add(int id)
+{
+    geovol *gvl;
+    geovol_slice *slice;
+
+    G_debug(3, "GVL_slice_add");
+
+    gvl = gvl_get_vol(id);
+
+    if (!gvl)
+	return (-1);
+
+    if (gvl->n_slices == MAX_SLICES)
+	return (-1);
+
+    if (NULL == (slice = (geovol_slice *) G_malloc(sizeof(geovol_slice)))) {
+	return (-1);
+    }
+
+    gvl_slice_init(slice);
+
+    gvl->n_slices++;
+    gvl->slice[gvl->n_slices - 1] = (geovol_slice *) slice;
+
+    return (1);
+}
+
+/*!
+   \brief Delete slice
+
+   \param id volume set id
+   \param slice_id slice id
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_slice_del(int id, int slice_id)
+{
+    geovol *gvl;
+    geovol_slice *slice;
+    int i;
+
+    G_debug(3, "GVL_slice_del");
+
+    slice = gvl_slice_get_slice(id, slice_id);
+
+    if (!slice)
+	return (-1);
+
+    if (!gvl_slice_freemem(slice)) {
+	return (-1);
+    }
+
+    gvl = gvl_get_vol(id);
+
+    G_free(gvl->slice[slice_id]);
+
+    for (i = slice_id + 1; i < gvl->n_slices; i++) {
+	gvl->slice[i - 1] = gvl->slice[i];
+    }
+
+    gvl->n_slices--;
+
+    return (1);
+}
+
+/*!
+   \brief Move up slice
+
+   \param id volume set id
+   \param slice_id slice id
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_slice_move_up(int id, int slice_id)
+{
+    geovol *gvl;
+    geovol_slice *tmp;
+
+    G_debug(3, "GVL_slice_move_up");
+
+    gvl = gvl_get_vol(id);
+
+    if (!gvl)
+	return (-1);
+
+    if (slice_id < 0 || slice_id > (gvl->n_slices - 1))
+	return (-1);
+
+    if (slice_id == 0)
+	return (1);
+
+    tmp = gvl->slice[slice_id - 1];
+    gvl->slice[slice_id - 1] = gvl->slice[slice_id];
+    gvl->slice[slice_id] = tmp;
+
+    return (1);
+}
+
+/*!
+   \brief Move down slice
+
+   \param id volume set id
+   \param slice_id slice id
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_slice_move_down(int id, int slice_id)
+{
+    geovol *gvl;
+    geovol_slice *tmp;
+
+    G_debug(3, "GVL_slice_move_up");
+
+    gvl = gvl_get_vol(id);
+
+    if (!gvl)
+	return (-1);
+
+    if (slice_id < 0 || slice_id > (gvl->n_slices - 1))
+	return (-1);
+
+    if (slice_id == (gvl->n_slices - 1))
+	return (1);
+
+    tmp = gvl->slice[slice_id + 1];
+    gvl->slice[slice_id + 1] = gvl->slice[slice_id];
+    gvl->slice[slice_id] = tmp;
+
+    return (1);
+}
+
+/*!
+   \brief Get number or slices
+
+   \param id volume set id
+
+   \return number of slices
+   \return -1 on error
+ */
+int GVL_slice_num_slices(int id)
+{
+    geovol *gvl;
+
+    G_debug(3, "GVL_isosurf_num_isosurfs");
+
+    gvl = gvl_get_vol(id);
+
+    if (gvl) {
+	return gvl->n_slices;
+    }
+
+    return (-1);
+}
+
+/*!
+   \brief Get slice position
+
+   \param id volume set id
+   \param slice_id slice id
+   \param[out] x1,y1,z1 coordinates ?
+   \param[out] x2,y2,z2 coordinates ?
+   \param[out] dir direction
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_slice_get_pos(int id, int slice_id,
+		      float *x1, float *x2, float *y1, float *y2, float *z1,
+		      float *z2, int *dir)
+{
+    geovol *gvl;
+    geovol_slice *slice;
+    int cols, rows, depths;
+
+    gvl = gvl_get_vol(id);
+
+    if (!gvl)
+	return (-1);
+
+    slice = gvl_slice_get_slice(id, slice_id);
+
+    if (!slice)
+	return (-1);
+
+    if (slice->dir == X) {
+	cols = gvl->rows;
+	rows = gvl->depths;
+	depths = gvl->cols;
+    }
+    else if (slice->dir == Y) {
+	cols = gvl->cols;
+	rows = gvl->depths;
+	depths = gvl->rows;
+    }
+    else if (slice->dir == Z) {
+	cols = gvl->cols;
+	rows = gvl->rows;
+	depths = gvl->depths;
+    }
+    else {
+	return (-1);
+    }
+
+    *x1 = slice->x1 / (cols - 1);
+    *x2 = slice->x2 / (cols - 1);
+    *y1 = slice->y1 / (rows - 1);
+    *y2 = slice->y2 / (rows - 1);
+    *z1 = slice->z1 / (depths - 1);
+    *z2 = slice->z2 / (depths - 1);
+
+    *dir = slice->dir;
+
+    return (1);
+}
+
+/*!
+   \brief Get slice position
+
+   \param id volume set id
+   \param slice_id slice id
+   \param x1,y1,z1 coordinates ?
+   \param x2,y2,z2 coordinates ?
+   \param dir direction
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_slice_set_pos(int id, int slice_id,
+		      float x1, float x2, float y1, float y2, float z1,
+		      float z2, int dir)
+{
+    geovol *gvl;
+    geovol_slice *slice;
+    int cols, rows, depths;
+
+    gvl = gvl_get_vol(id);
+
+    if (!gvl)
+	return (-1);
+
+    slice = gvl_slice_get_slice(id, slice_id);
+
+    if (!slice)
+	return (-1);
+
+    if (dir == X) {
+	cols = gvl->rows;
+	rows = gvl->depths;
+	depths = gvl->cols;
+    }
+    else if (dir == Y) {
+	cols = gvl->cols;
+	rows = gvl->depths;
+	depths = gvl->rows;
+    }
+    else if (dir == Z) {
+	cols = gvl->cols;
+	rows = gvl->rows;
+	depths = gvl->depths;
+    }
+    else {
+	return (-1);
+    }
+
+    slice->x1 = ((x1 < 0.) ? 0. : ((x1 > 1.) ? 1. : x1)) * (cols - 1);
+    slice->x2 = ((x2 < 0.) ? 0. : ((x2 > 1.) ? 1. : x2)) * (cols - 1);
+    slice->y1 = ((y1 < 0.) ? 0. : ((y1 > 1.) ? 1. : y1)) * (rows - 1);
+    slice->y2 = ((y2 < 0.) ? 0. : ((y2 > 1.) ? 1. : y2)) * (rows - 1);
+    slice->z1 = ((z1 < 0.) ? 0. : ((z1 > 1.) ? 1. : z1)) * (depths - 1);
+    slice->z2 = ((z2 < 0.) ? 0. : ((z2 > 1.) ? 1. : z2)) * (depths - 1);
+
+    slice->dir = dir;
+
+    slice->changed = 1;
+
+    return (1);
+}
+
+/*!
+   \brief Get slice trans ?
+
+   \param id volume set id
+   \param slice_id slice id
+   \param[out] transp transp value
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_slice_get_transp(int id, int slice_id, int *transp)
+{
+    geovol_slice *slice;
+
+    G_debug(3, "GVL_get_transp");
+
+    slice = gvl_slice_get_slice(id, slice_id);
+
+    if (!slice)
+	return (-1);
+
+    *transp = slice->transp;
+
+    return (1);
+}
+
+/*!
+   \brief Set slice trans ?
+
+   \param id volume set id
+   \param slice_id slice id
+   \param transp transp value
+
+   \return -1 on error
+   \return 1 on success
+ */
+int GVL_slice_set_transp(int id, int slice_id, int transp)
+{
+    geovol_slice *slice;
+
+    G_debug(3, "GVL_set_transp");
+
+    slice = gvl_slice_get_slice(id, slice_id);
+
+    if (!slice)
+	return (-1);
+
+    slice->transp = transp;
+
+    return (1);
+}

Copied: grass/branches/releasebranch_7_0/lib/ogsf/gvl3.c (from rev 62432, grass/branches/releasebranch_7_0/lib/ogsf/Gvl3.c)
===================================================================
--- grass/branches/releasebranch_7_0/lib/ogsf/gvl3.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/lib/ogsf/gvl3.c	2014-10-28 13:32:06 UTC (rev 62436)
@@ -0,0 +1,88 @@
+/*!
+   \file Gvl3.c
+
+   \brief OGSF library - loading volumes (lower level functions)
+
+   GRASS OpenGL gsurf OGSF Library 
+
+   (C) 1999-2008 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.
+
+   \author Tomas Paudits (December 2003)
+   \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
+ */
+
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/raster3d.h>
+#include <grass/ogsf.h>
+#include <grass/glocale.h>
+
+/*!
+   \brief Load color table
+
+   \param[out] color_data color data buffer
+   \param name 3D raster map name
+
+   \return -1 on failure
+   \return 1 on success
+ */
+int Gvl_load_colors_data(void **color_data, const char *name)
+{
+    const char *mapset;
+    struct Colors *colors;
+
+    if (NULL == (mapset = G_find_raster3d(name, ""))) {
+	G_warning(_("3D raster map <%s> not found"), name);
+	return (-1);
+    }
+
+    if (NULL == (colors = (struct Colors *)G_malloc(sizeof(struct Colors))))
+	return (-1);
+
+    if (0 > Rast3d_read_colors(name, mapset, colors)) {
+	G_free(colors);
+	return (-1);
+    }
+
+    *color_data = colors;
+
+    return (1);
+}
+
+/*!
+   \brief Unload color table
+
+   \param color_data color data buffer
+
+   \return -1 on failure
+   \return 1 on success
+ */
+int Gvl_unload_colors_data(void *color_data)
+{
+    Rast_free_colors(color_data);
+
+    G_free(color_data);
+
+    return (1);
+}
+
+/*!
+   \brief Get color for value
+
+   \param color_data color data value
+   \param value data value
+
+   \return color value
+ */
+int Gvl_get_color_for_value(void *color_data, float *value)
+{
+    int r, g, b;
+
+    Rast_get_f_color((FCELL *) value, &r, &g, &b, color_data);
+    return ((r & 0xff) | ((g & 0xff) << 8) | ((b & 0xff) << 16));
+}



More information about the grass-commit mailing list