[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(®ion);
-
- /*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(®ion);
-
- 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(®ion);
-
- 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(®ion);
-
- 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, ®ion, DCELL_TYPE, 32);
- else if (type == FCELL_TYPE)
- map = Rast3d_open_new_opt_tile_size(name, RASTER3D_USE_CACHE_XY, ®ion, 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(®ion2d); /*this function is not thread safe */
- Rast3d_region_to_cell_head(region3d, ®ion2d);
- }
-
- return N_init_geom_data_2d(®ion2d, 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(®ion);
+
+ /*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(®ion);
+
+ 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(®ion);
+
+ 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(®ion);
+
+ 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, ®ion, DCELL_TYPE, 32);
+ else if (type == FCELL_TYPE)
+ map = Rast3d_open_new_opt_tile_size(name, RASTER3D_USE_CACHE_XY, ®ion, 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(®ion2d); /*this function is not thread safe */
+ Rast3d_region_to_cell_head(region3d, ®ion2d);
+ }
+
+ return N_init_geom_data_2d(®ion2d, 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