[GRASS-SVN] r50895 - in grass/branches/releasebranch_6_4: gui/wxpython/nviz include lib/nviz lib/ogsf misc/m.nviz.image

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Feb 20 04:41:51 EST 2012


Author: annakrat
Date: 2012-02-20 01:41:50 -0800 (Mon, 20 Feb 2012)
New Revision: 50895

Added:
   grass/branches/releasebranch_6_4/misc/m.nviz.image/cplane.c
Modified:
   grass/branches/releasebranch_6_4/gui/wxpython/nviz/mapwindow.py
   grass/branches/releasebranch_6_4/include/gstypes.h
   grass/branches/releasebranch_6_4/include/nviz.h
   grass/branches/releasebranch_6_4/include/ogsf_proto.h
   grass/branches/releasebranch_6_4/lib/nviz/change_view.c
   grass/branches/releasebranch_6_4/lib/nviz/cplanes_obj.c
   grass/branches/releasebranch_6_4/lib/nviz/draw.c
   grass/branches/releasebranch_6_4/lib/nviz/lights.c
   grass/branches/releasebranch_6_4/lib/nviz/nviz.c
   grass/branches/releasebranch_6_4/lib/nviz/position.c
   grass/branches/releasebranch_6_4/lib/ogsf/GS2.c
   grass/branches/releasebranch_6_4/lib/ogsf/Gp3.c
   grass/branches/releasebranch_6_4/lib/ogsf/gs.c
   grass/branches/releasebranch_6_4/lib/ogsf/gsd_objs.c
   grass/branches/releasebranch_6_4/lib/ogsf/gsd_views.c
   grass/branches/releasebranch_6_4/lib/ogsf/gvld.c
   grass/branches/releasebranch_6_4/misc/m.nviz.image/args.c
   grass/branches/releasebranch_6_4/misc/m.nviz.image/description.html
   grass/branches/releasebranch_6_4/misc/m.nviz.image/local_proto.h
   grass/branches/releasebranch_6_4/misc/m.nviz.image/main.c
   grass/branches/releasebranch_6_4/misc/m.nviz.image/surface.c
   grass/branches/releasebranch_6_4/misc/m.nviz.image/vector.c
   grass/branches/releasebranch_6_4/misc/m.nviz.image/volume.c
Log:
ogsflib, nvizlib, m.nviz.image: synchronize with devbr6

Modified: grass/branches/releasebranch_6_4/gui/wxpython/nviz/mapwindow.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/nviz/mapwindow.py	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/gui/wxpython/nviz/mapwindow.py	2012-02-20 09:41:50 UTC (rev 50895)
@@ -24,6 +24,7 @@
 import copy
 import math
 import types
+import tempfile
 
 from threading import Thread
 

Modified: grass/branches/releasebranch_6_4/include/gstypes.h
===================================================================
--- grass/branches/releasebranch_6_4/include/gstypes.h	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/include/gstypes.h	2012-02-20 09:41:50 UTC (rev 50895)
@@ -326,12 +326,21 @@
     float shine;		/* 0. to 128. */
 };
 
+struct georot 
+{ 
+    int do_rot;                 /* do rotation */ 
+    double rot_angle;           /* rotation angle */ 
+    double rot_axes[3];         /* rotation axis */ 
+    GLdouble rotMatrix[16];     /* rotation matrix */ 
+};
+    
 typedef struct
 {
     int coord_sys;		/* latlon, equal area, etc */
     int view_proj;		/* perspective, ortho */
     int infocus;		/* fixed center of view - true or false */
     float from_to[2][4];
+    struct georot rotate;
     int twist, fov, incl, look;	/* 10ths of degrees */
     float real_to[4], vert_exag;	/* a global Z exag */
     float scale;

Modified: grass/branches/releasebranch_6_4/include/nviz.h
===================================================================
--- grass/branches/releasebranch_6_4/include/nviz.h	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/include/nviz.h	2012-02-20 09:41:50 UTC (rev 50895)
@@ -84,6 +84,21 @@
     int           where[4];
 };
 
+struct arrow_data
+{
+    unsigned long color;
+    float	  size;
+    float	  where[3];
+};
+
+struct scalebar_data
+{
+    int           id;
+    unsigned long color;
+    float	  size;
+    float	  where[3];
+};
+
 typedef struct
 {
     /* ranges */
@@ -101,7 +116,15 @@
     /* fringe */
     int num_fringes;
     struct fringe_data **fringe;
+
+    /* north arrow */
+    int draw_arrow;
+    struct arrow_data *arrow;
     
+    /* scalebar */
+    int num_scalebars;
+    struct scalebar_data **scalebar;
+    
     /* background color */
     int bgcolor;
 
@@ -129,16 +152,34 @@
 int Nviz_resize_window(int, int);
 int Nviz_update_ranges(nv_data *);
 int Nviz_set_viewpoint_position(double, double);
+void Nviz_get_viewpoint_position(double *, double *);
 int Nviz_set_viewpoint_height(double);
+void Nviz_get_viewpoint_height(double *);
 int Nviz_set_viewpoint_persp(int);
 int Nviz_set_viewpoint_twist(int);
 int Nviz_change_exag(nv_data *, double);
+int Nviz_look_here(double, double);
+void Nviz_get_modelview(double *);
+void Nviz_set_rotation(double, double, double, double);
+void Nviz_unset_rotation(void);
+void Nviz_init_rotation(void);
+void Nviz_flythrough(nv_data *, float *, int *, int);
 
 /* cplanes_obj.c */
 int Nviz_new_cplane(nv_data *, int);
+int Nviz_on_cplane(nv_data *, int);
 int Nviz_off_cplane(nv_data *, int);
 int Nviz_draw_cplane(nv_data *, int, int);
+int Nviz_num_cplanes(nv_data *);
+int Nviz_get_current_cplane(nv_data *);
+int Nviz_set_cplane_rotation(nv_data *, int, float, float, float);
+int Nviz_get_cplane_rotation(nv_data *, int, float *, float *, float *);
+int Nviz_set_cplane_translation(nv_data *, int, float, float, float);
+int Nviz_get_cplane_translation(nv_data *, int, float *, float *, float *);
+int Nviz_set_fence_color(nv_data *, int);
+int Nviz_set_cplane_here(nv_data *, int, float, float);
 
+
 /* draw.c */
 int Nviz_draw_all_surf(nv_data *);
 int Nviz_draw_all_vect();
@@ -146,6 +187,11 @@
 int Nviz_draw_all_vol();
 int Nviz_draw_all(nv_data *);
 int Nviz_draw_quick(nv_data *, int);
+int Nviz_load_image(GLubyte *, int, int, int);
+void Nviz_draw_image(int, int, int, int, int);
+void Nviz_set_2D(int, int);
+void Nviz_del_texture(int);
+void Nviz_get_max_texture(int *);
 
 /* exag.c */
 int Nviz_get_exag_height(double *, double *, double *);
@@ -158,6 +204,7 @@
 int Nviz_set_light_ambient(nv_data *, int, double);
 int Nviz_init_light(nv_data *, int);
 int Nviz_new_light(nv_data *);
+void Nviz_draw_model(nv_data *);
 
 /* map_obj.c */
 int Nviz_new_map_obj(int, const char *, double, nv_data *);
@@ -177,11 +224,25 @@
 				    double, int, int, int, int);
 struct fringe_data *Nviz_set_fringe(nv_data *, int, unsigned long,
 				    double, int, int, int, int);
+void Nviz_draw_fringe(nv_data *data);
+int Nviz_draw_arrow(nv_data *);
+int Nviz_set_arrow(nv_data *, int, int, float, unsigned int);
+void Nviz_delete_arrow(nv_data *);
+struct scalebar_data * Nviz_new_scalebar(nv_data *, int, float *, float, unsigned int);
+struct scalebar_data * Nviz_set_scalebar(nv_data *, int , int, int, float, unsigned int);
+void Nviz_draw_scalebar(nv_data *);
+void Nviz_delete_scalebar(nv_data *, int);
 
 /* position.c */
 void Nviz_init_view(nv_data *);
 int Nviz_set_focus_state(int);
 int Nviz_set_focus_map(int, int);
+int Nviz_has_focus(nv_data *);
+int Nviz_set_focus(nv_data *, float, float, float);
+int Nviz_get_focus(nv_data *, float *, float *, float *);
+float Nviz_get_xyrange(nv_data *);
+int Nviz_get_zrange(nv_data *, float *, float *);
+float Nviz_get_longdim(nv_data *);
 
 /* render.c */
 struct render_window *Nviz_new_render_window();

Modified: grass/branches/releasebranch_6_4/include/ogsf_proto.h
===================================================================
--- grass/branches/releasebranch_6_4/include/ogsf_proto.h	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/include/ogsf_proto.h	2012-02-20 09:41:50 UTC (rev 50895)
@@ -86,6 +86,8 @@
 int GS_surf_exists(int);
 int GS_new_surface(void);
 int GS_new_light(void);
+void GS_set_light_reset(int);
+int GS_get_light_reset(void);
 void GS_setlight_position(int, float, float, float, int);
 void GS_setlight_color(int, float, float, float);
 void GS_setlight_ambient(int, float, float, float);
@@ -166,6 +168,11 @@
 void GS_get_viewdir(float *);
 void GS_set_viewdir(float *);
 void GS_set_fov(int);
+void GS_set_rotation(double, double, double, double);
+void GS_get_rotation_matrix(double *);
+void GS_set_rotation_matrix(double *);
+void GS_init_rotation(void); 
+void GS_unset_rotation(void); 
 int GS_get_fov(void);
 int GS_get_twist(void);
 void GS_set_twist(int);
@@ -498,6 +505,7 @@
 int gsd_arrow_onsurf(float *, float *, unsigned long, int, geosurf *);
 void gsd_3darrow(float *, unsigned long, float, float, float *, float);
 int gsd_scalebar(float *, float, GLuint, unsigned long, unsigned long);
+int gsd_scalebar_v2(float *, float, GLuint, unsigned long, unsigned long);
 void primitive_cone(unsigned long);
 void primitive_cylinder(unsigned long, int);
 
@@ -583,6 +591,7 @@
 void gsd_real2model(Point3);
 void gsd_model2real(Point3);
 void gsd_model2surf(geosurf *, Point3);
+void gsd_surf2model(Point3);
 void gsd_surf2real(geosurf *, Point3);
 void gsd_real2surf(geosurf *, Point3);
 

Modified: grass/branches/releasebranch_6_4/lib/nviz/change_view.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/nviz/change_view.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/nviz/change_view.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -12,6 +12,8 @@
    \author Updated/modified by Martin Landa <landa.martin gmail.com> (Google SoC 2008/2010)
  */
 
+#include <math.h>
+
 #include <grass/glocale.h>
 #include <grass/nviz.h>
 
@@ -125,6 +127,25 @@
     return 1;
 }
 
+void Nviz_get_viewpoint_position(double *x_pos, double *y_pos)
+{
+    float from[3];
+    double xpos, ypos;
+
+    GS_get_from(from);
+    xpos = (from[X] + RANGE_OFFSET) / RANGE;
+    ypos = (from[Y] + RANGE_OFFSET) / RANGE;
+    *x_pos = xpos;
+    *x_pos = (*x_pos < 0) ? 0 : (*x_pos > 1.0) ? 1.0 : *x_pos;
+    *y_pos = 1.0 - ypos;
+    *y_pos = (*y_pos < 0) ? 0 : (*y_pos > 1.0) ? 1.0 : *y_pos;
+
+    if (xpos < 0.0 || xpos > 1.0 || ypos < 0.0 || ypos > 1.0) {
+	G_debug(3, "Invalid view position coordinates, using %f,%f",
+		  *x_pos, 1.0 - *y_pos);
+    }
+}
+
 /*!
    \brief Change viewpoint height
 
@@ -157,6 +178,16 @@
     return 1;
 }
 
+void Nviz_get_viewpoint_height(double *height)
+{
+    float from[3];
+
+    G_debug(1, "Nviz_get_viewpoint_height():");
+
+    GS_get_from_real(from);
+
+    *height = from[Z];
+}
 /*!
    \brief Change viewpoint perspective (field of view)
 
@@ -221,3 +252,127 @@
 
     return 1;
 }
+/*!
+  \brief Change focused point
+  
+  \param sx,sy screen coordinates
+  
+  \return 1
+*/
+int Nviz_look_here(double sx, double sy)
+{
+     G_debug(1, "Nviz_look_here(): screen coordinates = %f %f", sx, sy); 
+     GS_look_here(sx, sy);
+     return 1;
+}
+
+/*!
+  \brief Get current modelview matrix
+*/
+void Nviz_get_modelview(double *modelMatrix)
+{
+    glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
+}
+
+/*!
+  \brief Set rotation parameters
+
+  Rotate scene by given parameters related to mouse drag event
+  (difference from current state).
+  Coordinates determine the second point of rotation axis,
+  the first point is (0, 0, 0).
+
+  \param angle angle
+  \param x,y,z axis coordinate
+*/
+void Nviz_set_rotation(double angle, double x, double y, double z)
+{
+    G_debug(3, "Nviz_set_rotation(): angle = %f, x = %f, y = %f, z = %f", angle, x, y, z); 
+    GS_set_rotation(angle, x, y, z);
+}
+
+/*!
+  \brief Stop scene rotation
+*/
+void Nviz_unset_rotation(void)
+{
+    GS_unset_rotation();
+}
+
+/*!
+  \brief Stop scene rotation
+*/
+void Nviz_init_rotation(void)
+{
+    GS_init_rotation();
+}
+
+/*!
+  \brief Fly through the scene
+
+  Computes parameters needed for moving scene.
+  Changes viewpoint and viewdir.
+  Based on visualization/nviz/src/togl_flythrough.c and simplified.
+
+  \param fly_info values computed from mouse movement
+  \param scale rate of movement
+  \param lateral type of movement
+  
+*/
+void Nviz_flythrough(nv_data *data, float *fly_info, int *scale, int lateral)
+{
+    float dir[3], from[4], cur_from[4], cur_dir[4];
+    float speed, h, p, sh, ch, sp, cp;
+    float diff_x, diff_y, diff_z;
+    float quasi_zero;
+
+    quasi_zero = 0.0001;
+
+    GS_get_from(cur_from);
+    GS_get_viewdir(cur_dir);
+
+    p = asin(cur_dir[Z]);
+    h = atan2(- cur_dir[X], - cur_dir[Y]);
+
+    speed = scale[0] * fly_info[0];
+
+    h += scale[1] * fly_info[1]; /* change heading */
+    if (!lateral)   /* in case of "lateral" doesn't change pitch */
+        p -= scale[1] * fly_info[2];
+
+    h = fmod(h + M_PI, 2 * M_PI) - M_PI;
+
+    sh = sin(h);
+    ch = cos(h);
+    sp = sin(p);
+    cp = cos(p);
+
+    dir[X] = -sh * cp;
+    dir[Y] = -ch * cp;
+    dir[Z] = sp;
+
+    if (lateral) {
+        from[X] = cur_from[X] + speed * dir[Y];
+        from[Y] = cur_from[Y] - speed * dir[X];
+        from[Z] = cur_from[Z] + scale[0] * fly_info[2];
+    }
+    else {
+        from[X] = cur_from[X] + speed * dir[X];
+        from[Y] = cur_from[Y] + speed * dir[Y];
+        /* not sure how this should behave (change Z coord or not ?)*/
+        from[Z] = cur_from[Z]; /* + speed * dir[Z]*/
+    }
+
+    diff_x = fabs(cur_dir[X] - dir[X]);
+    diff_y = fabs(cur_dir[Y] - dir[Y]);
+    diff_z = fabs(cur_dir[Z] - dir[Z]);
+
+    if (    /* something has changed */
+        (diff_x > quasi_zero) || (diff_y > quasi_zero) ||
+        (diff_z > quasi_zero) || (cur_from[X] != from[X]) ||
+        (cur_from[Y] != from[Y]) || (cur_from[Z] != from[Z])
+    ) {
+    GS_moveto(from);
+    GS_set_viewdir(dir);	/* calls gsd_set_view */
+    }
+}

Modified: grass/branches/releasebranch_6_4/lib/nviz/cplanes_obj.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/nviz/cplanes_obj.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/nviz/cplanes_obj.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -15,6 +15,7 @@
 #include <grass/nviz.h>
 
 static void cp_draw(nv_data *, int, int, int);
+static geoview Gv;
 
 /*!
    \brief Creates a clip plane object
@@ -36,6 +37,21 @@
 }
 
 /*!
+   \brief Turn on (make current) the given clip plane.
+
+   \param data nviz data
+   \param cplane id
+ */
+int Nviz_on_cplane(nv_data * data, int id)
+{
+    data->cur_cplane = id;
+    data->cp_on[id] = 1;
+    GS_set_cplane(id);
+
+    return 1;
+}
+
+/*!
    \brief Turn off (make inactive) the given clip plane
 
    \param data nviz data
@@ -118,3 +134,153 @@
 
     return;
 }
+/*!
+   \brief Return the number of clip planes objects currently allocated.
+   
+   \param data nviz data
+ */
+int Nviz_num_cplanes(nv_data * data)
+{
+	return data->num_cplanes;
+}
+
+/*!
+   \brief Get the current active cutplane.
+   
+   \param data nviz data
+ */
+int Nviz_get_current_cplane(nv_data * data)
+{
+	return data->cur_cplane;
+}
+
+/*!
+   \brief Set the rotation for the current clip plane.
+   
+   \param data nviz data
+   \param id id of current clip plane
+   \param dx,dy,dz rotation parameters
+   
+   \return 1 
+
+ */
+int Nviz_set_cplane_rotation(nv_data * data, int id, float dx, float dy, float dz)
+{
+    data->cp_rot[id][X] = dx;
+    data->cp_rot[id][Y] = dy;
+    data->cp_rot[id][Z] = dz;
+    GS_set_cplane_rot(id, data->cp_rot[id][X], data->cp_rot[id][Y],
+		      data->cp_rot[id][Z]);
+
+    cp_draw(data, data->cur_cplane, -1, -1);
+    
+    return 1;
+}
+/*!
+   \brief Get the rotation values for the current clip plane.
+   
+   \param data nviz data
+   \param id id of current clip plane
+   \param dx,dy,dz rotation parameters
+   
+   \return 1
+   
+ */
+int Nviz_get_cplane_rotation(nv_data * data, int id, float *dx, float *dy, float *dz)
+{
+    *dx = data->cp_rot[id][X];
+    *dy = data->cp_rot[id][Y];
+    *dz = data->cp_rot[id][Z];
+
+    return 1;
+}
+
+/*!
+   \brief Set the translation for the current clip plane.
+
+   \param data nviz data
+   \param id id of current clip plane
+   \param dx,dy,dz values for setting translation
+   
+   \return 1
+ */
+int Nviz_set_cplane_translation(nv_data * data, int id, float dx, float dy, float dz)
+{
+    data->cp_trans[id][X] = dx;
+    data->cp_trans[id][Y] = dy;
+    data->cp_trans[id][Z] = dz;
+    GS_set_cplane_trans(id, data->cp_trans[id][X], data->cp_trans[id][Y],
+			data->cp_trans[id][Z]);
+
+    cp_draw(data, data->cur_cplane, -1, -1);
+    
+    return 1;
+}
+/*!
+   \brief Get the translation values for the current clip plane.
+   
+   \param data nviz data
+   \param id id of current clip plane
+   \param dx,dy,dz translation parameters
+ */
+int Nviz_get_cplane_translation(nv_data * data, int id, float *dx, float *dy, float *dz)
+{
+    *dx = data->cp_trans[id][X];
+    *dy = data->cp_trans[id][Y];
+    *dz = data->cp_trans[id][Z];
+
+    return 1;
+}
+/*!
+   \brief Set appropriate fence color
+   
+   \param type type of fence (FC_ABOVE, FC_BELOW, FC_BLEND, FC_GREY, FC_OFF)
+ */
+int Nviz_set_fence_color(nv_data * data, int type)
+{
+	GS_set_fencecolor(type);
+
+    return 1;
+
+}
+int Nviz_set_cplane_here(nv_data *data, int cplane, float sx, float sy)
+{
+    float x, y, z, len, los[2][3];
+    float dx, dy, dz;
+    float n, s, w, e;
+    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;
+	}
+	else
+	    return 0;
+    }
+    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];
+	}
+	else
+	    return 0;
+    }  
+    Nviz_get_cplane_translation(data, cplane, &dx, &dy, &dz);
+
+    GS_get_region(&n, &s, &w, &e);
+    dx = realto[X] - (e - w) / 2.;
+    dy = realto[Y] - (n - s) / 2.;
+
+    Nviz_set_cplane_translation(data, cplane, dx, dy, dz);
+
+    return 1;
+}

Modified: grass/branches/releasebranch_6_4/lib/nviz/draw.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/nviz/draw.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/nviz/draw.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -6,15 +6,20 @@
    Based on visualization/nviz/src/draw.c and
    visualization/nviz/src/togl_flythrough.c
    
-   (C) 2008, 2010 by the GRASS Development Team
+   (C) 2008, 2010-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 Updated/modified by Martin Landa <landa.martin gmail.com> (Google SoC 2008/2010)
+   \author Textures by Anna Kratochvilova 
  */
 
 #include <grass/nviz.h>
 
+#ifndef GL_CLAMP_TO_EDGE
+#define GL_CLAMP_TO_EDGE 0x812F
+#endif 
+
 static int sort_surfs_max(int *, int *, int *, int);
 
 /*!
@@ -232,11 +237,23 @@
 
     if (draw_vol)
 	Nviz_draw_all_vol(data);
-
+	
     for(i = 0; i < data->num_fringes; i++) {
 	struct fringe_data * f = data->fringe[i];
 	GS_draw_fringe(f->id, f->color, f->elev, f->where);
     }
+
+    /* North Arrow */
+    if (data->draw_arrow) {
+	gsd_north_arrow(data->arrow->where, data->arrow->size,
+			(GLuint)NULL, data->arrow->color, data->arrow->color);
+    }
+
+    /* scale bar */
+    for (i = 0; i < data->num_scalebars; i++) {
+	struct scalebar_data *s = data->scalebar[i];
+	gsd_scalebar_v2(s->where, s->size, 0, s->color, s->color);
+    }
     
     GS_done_draw();
     GS_set_draw(GSD_BACK);
@@ -287,3 +304,119 @@
     
     return 1;
 }
+
+/*!
+  \brief Load image into texture
+
+  \param image_data image data 
+  \param width, height image screen size 
+  \param alpha has alpha channel 
+*/
+int Nviz_load_image(GLubyte *image_data, int width, int height, int alpha)
+{
+    unsigned int texture_id;
+    int  in_format;
+    GLenum format;
+
+    if (alpha)
+    {
+	in_format = 4;
+	format = GL_RGBA;
+    }
+    else
+    {
+	in_format = 3;
+	format = GL_RGB;
+    }
+    glGenTextures( 1, &texture_id);
+    glBindTexture(GL_TEXTURE_2D, texture_id);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, in_format, width, height, 0,format,
+		 GL_UNSIGNED_BYTE, image_data);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
+
+    return texture_id;
+}
+
+/*!
+  \brief Set ortho view for drawing images
+
+  \param width, height image screen size 
+*/
+void Nviz_set_2D(int width, int height)
+{
+    glEnable(GL_BLEND); // images are transparent
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrtho(0, width, 0, height, -1, 1);
+    
+    // set coordinate system from upper left corner
+    glScalef(1, -1, 1);
+    glTranslatef(0, -height, 0);
+
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+}
+
+/*!
+  \brief Draw image as texture
+
+  \param x, y image coordinates 
+  \param width, height image size 
+  \param texture_id texture id 
+*/
+void Nviz_draw_image(int x, int y, int width, int height, int texture_id)
+{
+    glBindTexture(GL_TEXTURE_2D, texture_id);
+    GS_set_draw(GSD_FRONT);
+
+    glEnable(GL_TEXTURE_2D);
+
+    glBegin(GL_QUADS);
+
+    glTexCoord2d(0.0,1.0);
+    glVertex2d(x, y);
+    glTexCoord2d(0.0,0.0);
+    glVertex2d(x, y + height);
+    glTexCoord2d(1.0,0.0);
+    glVertex2d(x + width, y + height);
+    glTexCoord2d(1.0,1.0);
+    glVertex2d(x + width, y);
+
+    glEnd();
+
+    GS_done_draw();
+    glDisable(GL_TEXTURE_2D);
+}
+
+/*!
+  \brief Delete texture
+
+  \param texture_id texture id
+*/
+void Nviz_del_texture(int texture_id)
+{
+    GLuint t[1];
+
+    t[0] = texture_id;
+    glDeleteTextures(1, t);
+}
+
+/*!
+  \brief Get maximum texture size
+
+*/
+void Nviz_get_max_texture(int *size)
+{
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, size);
+}

Modified: grass/branches/releasebranch_6_4/lib/nviz/lights.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/nviz/lights.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/nviz/lights.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -39,16 +39,16 @@
 		x, y, xpos, 1.0 - ypos);
     }
     */
-    num--;
-    data->light[num].id = num + 1;
+
+    data->light[num].id = num;
     data->light[num].x = x;
     data->light[num].y = y;
     data->light[num].z = z;
     data->light[num].w = w;
 
     G_debug(1, "Nviz_set_light_position(): num = %d x = %f y = %f z = %f w = %f",
-	    num + 1, x, y, z, w);
-    GS_setlight_position(num + 1, x, y, z, w);
+	    num, x, y, z, w);
+    GS_setlight_position(num, x, y, z, w);
 
     return 1;
 }
@@ -64,7 +64,6 @@
 {
     double r, g, b;
 
-    num--;
     data->light[num].brt = value;
 
     r = data->light[num].r * data->light[num].brt;
@@ -72,8 +71,8 @@
     b = data->light[num].b * data->light[num].brt;
 
     G_debug(1, "Nviz_set_light_bright(): num = %d value = %f r = %f g = %f b = %f",
-	    num + 1, value, r, g, b);
-    GS_setlight_color(num + 1, r, g, b);
+	    num, value, r, g, b);
+    GS_setlight_color(num, r, g, b);
 
     return 1;
 }
@@ -90,7 +89,6 @@
 {
     double r, g, b;
 
-    num--;
     data->light[num].r = red / 255.;
     data->light[num].g = green / 255.;
     data->light[num].b = blue / 255.;
@@ -100,8 +98,8 @@
     b = data->light[num].b * data->light[num].brt;
 
     G_debug(1, "Nviz_set_light_color(): num = %d r = %d/%f g = %d/%f b = %d/%f",
-	    num + 1, red, r, green, g, blue, b);
-    GS_setlight_color(num + 1, r, g, b);
+	    num, red, r, green, g, blue, b);
+    GS_setlight_color(num, r, g, b);
 
     return 1;
 }
@@ -115,14 +113,13 @@
  */
 int Nviz_set_light_ambient(nv_data * data, int num, double value)
 {
-    num--;
     data->light[num].ar = value;
     data->light[num].ag = value;
     data->light[num].ab = value;
 
     G_debug(1, "Nviz_set_light_ambient(): num = %d value = %f",
-	    num + 1, value);
-    GS_setlight_ambient(num + 1, value, value, value);
+	    num, value);
+    GS_setlight_ambient(num, value, value, value);
     
     return 1;
 }
@@ -135,8 +132,8 @@
  */
 int Nviz_init_light(nv_data * data, int num)
 {
-    num--;
-    if (num >= MAX_LIGHTS) {
+	G_debug(1, "Nviz_init_light(): num = %d", num);
+    if (num > MAX_LIGHTS) {
 	return 0;
     }
 
@@ -180,3 +177,16 @@
     return 1;
 }
 
+/*!
+  \brief Draw lighting model
+
+  \param data nviz data
+*/
+void Nviz_draw_model(nv_data * data)
+{
+    GS_set_draw(GSD_FRONT);
+    GS_ready_draw();
+    GS_draw_lighting_model();
+    GS_done_draw();
+    GS_set_draw(GSD_BACK);
+}

Modified: grass/branches/releasebranch_6_4/lib/nviz/nviz.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/nviz/nviz.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/nviz/nviz.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -37,14 +37,24 @@
     }
 
     /* lights */
-    for (i = 0; i < MAX_LIGHTS; i++) {
+    GS_set_light_reset(1);
+    
+    for (i = 0; i < MAX_LIGHTS - 1; i++) {
 	Nviz_new_light(data);
     }
 
     /* fringe */
     data->num_fringes = 0;
     data->fringe = NULL;
-    
+
+    /* north arrow */
+    data->draw_arrow = 0;
+    data->arrow = NULL;
+
+    /* scale bar*/
+    data->num_scalebars = 0;
+    data->scalebar = NULL;
+
     return;
 }
 
@@ -61,6 +71,19 @@
     }
     data->num_fringes = 0;
     data->fringe = NULL;
+    
+    if (data->arrow) {
+	G_free(data->arrow);
+	data->arrow = NULL;
+	data->draw_arrow = 0;
+    }
+
+    for (i = 0; data->num_scalebars; i++) {
+	G_free(data->scalebar[i]);
+	data->scalebar[i] = NULL;
+    }
+    data->num_scalebars = 0;
+    data->scalebar = NULL;
 }
 
 /*!
@@ -134,6 +157,7 @@
 	if (num < 1)
 	    return NULL;
 	id = surf[0];
+	G_free(surf);
     }
      
 
@@ -177,6 +201,7 @@
 	if (num < 1)
 	    return NULL;
 	id = surf[0];
+	G_free(surf);
     }
     
     for (i = 0; i < data->num_fringes; i++) {
@@ -199,3 +224,211 @@
     
     return f;
 }
+/*! Draw fringe
+
+   \param data nviz data
+ */
+void Nviz_draw_fringe(nv_data *data)
+{
+    int i;
+
+    for (i = 0; i < data->num_fringes; i++) {
+	struct fringe_data *f = data->fringe[i];
+
+	GS_draw_fringe(f->id, f->color, f->elev, f->where);
+    }
+}
+/*!
+   \brief Sets the North Arrow position and return world coords
+
+   \param data nviz data
+   \param sx,sy screen coordinates
+   \param size arrow length
+   \param color arrow/text color
+ */
+int Nviz_set_arrow(nv_data *data,
+		   int sx, int sy, float size,
+		   unsigned int color)
+{
+    int id, pt[2];
+    int *surf_list, num_surfs;
+    float coords[3];
+    struct arrow_data *arw;
+
+    if (GS_num_surfs() > 0) {
+	surf_list = GS_get_surf_list(&num_surfs);
+	id = surf_list[0];
+	G_free(surf_list);
+
+	pt[0] = sx;
+	pt[1] = sy;
+
+	GS_set_Narrow(pt, id, coords);
+
+	if (data->arrow) {
+	    data->arrow->color = color;
+	    data->arrow->size  = size;
+	    data->arrow->where[0]  = coords[0];
+	    data->arrow->where[1]  = coords[1];
+	    data->arrow->where[2]  = coords[2];
+	}    
+	else {
+	    arw = (struct arrow_data *) G_malloc(sizeof(struct arrow_data));
+	    arw->color = color;
+	    arw->size  = size;
+	    arw->where[0]  = coords[0];
+	    arw->where[1]  = coords[1];
+	    arw->where[2]  = coords[2];
+
+	    data->arrow = arw;
+	}
+	return 1;
+    }
+    return 0;
+}
+
+
+/*!
+   \brief Draws the North Arrow
+
+   \param data nviz data
+ */
+int Nviz_draw_arrow(nv_data *data)
+{
+
+    struct arrow_data *arw = data->arrow;
+    GLuint FontBase = 0; /* don't know how to get fontbase*/
+
+    data->draw_arrow = 1;
+    gsd_north_arrow(arw->where, arw->size, FontBase, arw->color, arw->color);
+
+    return 1;
+}
+
+/*!
+   \brief Deletes the North Arrow
+
+   \param data nviz data
+ */
+void Nviz_delete_arrow(nv_data *data)
+{
+    data->draw_arrow = 0;
+
+    return;
+}
+
+/*! Add new scalebar
+
+  \param data nviz data
+  \param bar_id scale bar id
+  \param coords real(?) coordinates
+  \param size scale bar length
+  \param color scalebar/text color
+
+  \return pointer to allocated scalebar_data structure
+  \return NULL on error
+*/
+
+struct scalebar_data *Nviz_new_scalebar(nv_data *data,
+		      int bar_id, float *coords, float size,
+		      unsigned int color)
+{
+    struct scalebar_data *s;
+     
+
+    s = (struct scalebar_data *) G_malloc(sizeof(struct scalebar_data));
+    s->id = bar_id;
+    s->color = color;
+    s->size = size;
+    s->where[0] = coords[0];
+    s->where[1] = coords[1];
+    s->where[2] = coords[2];
+
+    data->scalebar = (struct scalebar_data **) G_realloc(data->scalebar,
+		      data->num_scalebars + 1 * sizeof(struct scalebar_data *));
+    data->scalebar[data->num_scalebars++] = s;
+
+    return s;
+
+}
+/*!
+   \brief Sets the scale bar position and return world coords
+
+   \param data nviz data
+   \param bar_id scale bar id
+   \param sx,sy screen coordinates
+   \param size scale bar length
+   \param color scalebar/text color
+
+   \return pointer to allocated scalebar_data structure
+   \return NULL when there's no surface
+ */
+struct scalebar_data *Nviz_set_scalebar(nv_data *data, int bar_id,
+		      int sx, int sy, float size,
+		      unsigned int color)
+{
+    int i, id, pt[2];
+    int *surf_list, num_surfs;
+    float coords[3];
+    struct scalebar_data *s;
+
+    if (GS_num_surfs() > 0) {
+	surf_list = GS_get_surf_list(&num_surfs);
+	id = surf_list[0];
+	G_free(surf_list);
+
+	pt[0] = sx;
+	pt[1] = sy;
+
+	GS_set_Narrow(pt, id, coords); /* the same like arrow */
+
+	for (i = 0; i < data->num_scalebars; i++) {
+	    s = data->scalebar[i];
+	    if (s->id == bar_id) {
+		s->color = color;
+		s->size = size;
+		s->where[0] = coords[0];
+		s->where[1] = coords[1];
+		s->where[2] = coords[2];
+
+		return s;
+	    }
+	}
+	
+	s = Nviz_new_scalebar(data, bar_id, coords, size, color);
+
+	return s;
+    }
+    return NULL;
+}
+/*!
+   \brief Draws the Scale bar
+
+   \param data nviz data
+ */
+void Nviz_draw_scalebar(nv_data *data)
+{
+    int i;
+
+    GLuint FontBase = 0; /* don't know how to get fontbase*/
+
+    for (i = 0; i < data->num_scalebars; i++) {
+	struct scalebar_data *s = data->scalebar[i];
+
+	gsd_scalebar_v2(s->where, s->size, FontBase, s->color, s->color);
+    }
+}
+
+/*!
+   \brief Deletes scale bar
+
+   \param data nviz data
+ */
+void Nviz_delete_scalebar(nv_data *data, int bar_id)
+{
+    if (bar_id < data->num_scalebars) {
+	G_free(data->scalebar[bar_id]);
+	data->scalebar[bar_id] = NULL;
+	data->num_scalebars--;
+    }
+}

Modified: grass/branches/releasebranch_6_4/lib/nviz/position.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/nviz/position.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/nviz/position.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -1,10 +1,10 @@
 /*!
    \file lib/nviz/position.c
-   
+
    \brief Nviz library -- Position, focus settings
-   
+
    Based on visualization/nviz/src/position.c
-   
+
    (C) 2008, 2010 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.
@@ -20,21 +20,21 @@
 
    Set position to center of view
  */
-void Nviz_init_view(nv_data *data)
+void Nviz_init_view(nv_data * data)
 {
     GS_init_view();
     Nviz_set_focus_state(1);	/* center of view */
-    
+
     /* set default lights (1 & 2) */
     Nviz_set_light_position(data, 1, 0.68, -0.68, 0.80, 0.0);
-    Nviz_set_light_bright(data,   1, 0.8);
-    Nviz_set_light_color(data,    1, 255, 255, 255);
-    Nviz_set_light_ambient(data,  1, 0.2);
+    Nviz_set_light_bright(data, 1, 0.8);
+    Nviz_set_light_color(data, 1, 255, 255, 255);
+    Nviz_set_light_ambient(data, 1, 0.2);
     Nviz_set_light_position(data, 2, 0.0, 0.0, 1.0, 0.0);
-    Nviz_set_light_bright(data,   2, 0.5);
-    Nviz_set_light_color(data,    2, 255, 255, 255);
-    Nviz_set_light_ambient(data,  2, 0.3);
-    
+    Nviz_set_light_bright(data, 2, 0.5);
+    Nviz_set_light_color(data, 2, 255, 255, 255);
+    Nviz_set_light_ambient(data, 2, 0.3);
+
     return;
 }
 
@@ -109,3 +109,97 @@
 
     return id;
 }
+
+/*!
+   \brief Get focus
+
+   \param data nviz data
+   \param x,y,z focus coordinates
+ */
+int Nviz_get_focus(nv_data * data, float *x, float *y, float *z)
+{
+    float realto[3];
+
+    /* Get current center */
+    GS_get_focus(realto);
+    *x = realto[0];
+    *y = realto[1];
+    *z = realto[2];
+    // old nviz code is more complicated and it doesn't work properly,
+    // no idea why
+
+    return 1;
+
+}
+
+/*!
+   \brief Set focus
+
+   \param data nviz data
+   \param x, y, z focus coordinates
+ */
+int Nviz_set_focus(nv_data * data, float x, float y, float z)
+{
+    float realto[3];
+
+    realto[0] = x;
+    realto[1] = y;
+    realto[2] = z;
+    GS_set_focus(realto);
+    // old nviz code is more complicated and it doesn't work properly,
+    // no idea why
+
+    return 1;
+
+}
+
+/*!
+   \brief Test focus
+
+   \param data nviz data
+ */
+int Nviz_has_focus(nv_data * data)
+{
+    float realto[3];
+
+    if (GS_get_focus(realto))
+	return 1;
+    else
+	return 0;
+}
+
+/*!
+   \brief Get xy range
+
+   \param data nviz data
+ */
+float Nviz_get_xyrange(nv_data * data)
+{
+    return data->xyrange;
+}
+
+/*!
+   \brief Get z range
+
+   \param data nviz data
+   \param min,max z range
+ */
+int Nviz_get_zrange(nv_data * data, float *min, float *max)
+{
+    GS_get_zrange_nz(min, max);
+    return 1;
+}
+
+/*!
+   \brief Get largest dimension
+
+   \param data nviz data
+ */
+float Nviz_get_longdim(nv_data * data)
+{
+    float dim;
+
+    GS_get_longdim(&dim);
+
+    return dim;
+}

Modified: grass/branches/releasebranch_6_4/lib/ogsf/GS2.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/ogsf/GS2.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/ogsf/GS2.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -78,6 +78,7 @@
 static struct Cell_head wind;
 static int Buffermode;
 static int Numlights = 0;
+static int Resetlight = 1;
 static int Modelshowing = 0;
 
 void void_func(void)
@@ -113,9 +114,13 @@
 
     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();
     }
@@ -244,7 +249,16 @@
 
     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
 
@@ -253,12 +267,12 @@
  */
 int GS_new_light(void)
 {
-    static int first = 1;
     int i;
 
-    if (first) {
-	first = 0;
+    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;
@@ -277,10 +291,10 @@
 	gsd_deflight(Numlights + 1, &(Gv.lights[Numlights]));
 	gsd_switchlight(Numlights + 1, 1);
 
-	return (++Numlights);
+	return ++Numlights;
     }
 
-    return (-1);
+    return -1;
 }
 
 /*!
@@ -1548,32 +1562,33 @@
  */
 int GS_delete_surface(int id)
 {
-    int i, j, found = 0;
-
-    G_debug(3, "GS_delete_surface");
-
+    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 = 1;
+		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;
 	}
     }
 
-    return (-1);
+    return -1;
 }
 
 
@@ -2864,6 +2879,72 @@
 }
 
 /*!
+   \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)
@@ -3262,6 +3343,7 @@
  */
 void GS_init_view(void)
 {
+    int i;
     static int first = 1;
 
     G_debug(3, "GS_init_view");
@@ -3295,6 +3377,9 @@
 	/* 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.;
 

Modified: grass/branches/releasebranch_6_4/lib/ogsf/Gp3.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/ogsf/Gp3.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/ogsf/Gp3.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -125,6 +125,8 @@
     }
 
     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 */
     ndim = 2;

Modified: grass/branches/releasebranch_6_4/lib/ogsf/gs.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/ogsf/gs.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/ogsf/gs.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -572,7 +572,7 @@
 	    /* for ea att of all other surfs */
 	    for (gs = Surf_top; gs; gs = gs->next) {
 		for (j = 0; j < MAX_ATTS; j++) {
-		    if (old_datah == gs->att[j].hdata) {
+		    if ((old_datah == gs->att[j].hdata) && (fs != gs)) {
 			same = 1;
 		    }
 		}

Modified: grass/branches/releasebranch_6_4/lib/ogsf/gsd_objs.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/ogsf/gsd_objs.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/ogsf/gsd_objs.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -1234,6 +1234,74 @@
 }
 
 /*!
+   \brief Draw Scalebar (as lines)
+
+   Adapted from gsd_scalebar A.Kratochvilova 2011
+
+   \param pos2 scalebar position
+   \param fontbase font-base (unused)
+   \param bar_clr barscale color
+   \param text_clr text color (unused)
+
+   \return 1
+ */
+int gsd_scalebar_v2(float *pos, float len, GLuint fontbase,
+		 unsigned long bar_clr, unsigned long text_clr)
+{
+    float base[6][3];
+    float Ntop[] = { 0.0, 0.0, 1.0 };
+
+    base[0][Z] = base[1][Z] = base[2][Z] = pos[Z];
+    base[3][Z] = base[4][Z] = base[5][Z] = pos[Z];
+
+    /* simple scalebar: |------| */
+    base[0][X] = base[2][X] = base[3][X] = pos[X] - len / 2.;
+    base[1][X] = base[4][X] = base[5][X] = pos[X] + len / 2.;
+    base[0][Y] = base[1][Y] = pos[Y];
+    base[2][Y] = base[4][Y] = pos[Y] - len / 12;
+    base[3][Y] = base[5][Y] = pos[Y] + len / 12;
+
+    /* make sure we are drawing in front buffer */
+    GS_set_draw(GSD_FRONT);
+
+    gsd_pushmatrix();
+    gsd_do_scale(1);		/* get map scale factor */
+
+    glNormal3fv(Ntop);
+
+    gsd_color_func(bar_clr);
+
+    gsd_linewidth(3); /* could be optional */
+
+    /* ------- */
+    gsd_bgnline();
+    gsd_vert_func(base[0]);
+    gsd_vert_func(base[1]);
+    gsd_endline();
+
+    /* |------- */
+    gsd_bgnline();
+    gsd_vert_func(base[2]);
+    gsd_vert_func(base[3]);
+    gsd_endline();
+
+    /* |-------| */
+    gsd_bgnline();
+    gsd_vert_func(base[4]);
+    gsd_vert_func(base[5]);
+    gsd_endline();
+
+    /* TODO -- draw units */
+
+    GS_done_draw();
+
+    gsd_popmatrix();
+    gsd_flush();
+
+    return 1;
+}
+
+/*!
    \brief Primitives only called after transforms
 
    Center is actually center at base of 8 sided cone

Modified: grass/branches/releasebranch_6_4/lib/ogsf/gsd_views.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/ogsf/gsd_views.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/ogsf/gsd_views.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -88,7 +88,7 @@
     return (1);
 }
 
-
+#if 0
 /*!
    \brief Set view
 
@@ -134,7 +134,79 @@
 
     return;
 }
+#endif
+/*!
+   \brief Set view
 
+   Establishes viewing & projection matrices
+
+   \param gv view (geoview)
+   \param dp display (geodisplay)
+ */
+void gsd_set_view(geoview * gv, geodisplay * gd)
+{
+    double up[3];
+    float pos[3];
+    int i;
+    GLdouble modelMatrix[16];
+    GLint mm;
+
+    /* will expand when need to check for in focus, ortho, etc. */
+
+    gsd_check_focus(gv);
+    gsd_get_zup(gv, up);
+
+    gd->aspect = GS_get_aspect();
+
+    glGetIntegerv(GL_MATRIX_MODE, &mm);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gluPerspective((double).1 * (gv->fov), (double)gd->aspect,
+		   (double)gd->nearclip, (double)gd->farclip);
+
+    glMatrixMode(mm);
+    
+    glLoadIdentity();
+
+    /* update twist parm */
+    glRotatef((float)(gv->twist / 10.), 0.0, 0.0, 1.0);
+
+    /* OGLXXX lookat: replace UPx with vector */
+    gluLookAt((double)gv->from_to[FROM][X], (double)gv->from_to[FROM][Y],
+	      (double)gv->from_to[FROM][Z], (double)gv->from_to[TO][X],
+	      (double)gv->from_to[TO][Y], (double)gv->from_to[TO][Z],
+	      (double)up[X], (double)up[Y], (double)up[Z]);
+	      
+    /* rotate to get rotation matrix and then save it*/
+    if (gv->rotate.do_rot) {
+
+	glPushMatrix();
+	glLoadMatrixd(gv->rotate.rotMatrix);
+
+	glRotated(gv->rotate.rot_angle, gv->rotate.rot_axes[0], 
+		  gv->rotate.rot_axes[1], gv->rotate.rot_axes[2]);
+	glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
+
+	for (i = 0; i < 16; i++) {
+	    gv->rotate.rotMatrix[i] = modelMatrix[i];
+	}
+
+	glPopMatrix();
+    }
+    
+    gs_get_datacenter(pos);
+    gsd_surf2model(pos);
+    /* translate rotation center to view center, rotate and translate back */
+    glTranslatef(pos[0], pos[1], pos[2]);
+    glMultMatrixd(gv->rotate.rotMatrix);
+    glTranslatef(-pos[0], -pos[1], -pos[2]);
+
+    /* have to redefine clipping planes when view changes */
+
+    gsd_update_cplanes();
+
+    return;
+}
 /*!
    \brief Check focus
 
@@ -361,7 +433,28 @@
 
     return;
 }
+/*!
+   \brief Convert surface to model coordinates
 
+   \param point 3d point (Point3)
+ */
+void gsd_surf2model(Point3 point)
+{
+    float min, max, sx, sy, sz;
+
+    /* need to undo z scaling & translate */
+    GS_get_scale(&sx, &sy, &sz, 1);
+    GS_get_zrange(&min, &max, 0);
+
+    point[Z] = (sz ? (point[Z] - min) * sz : 0.0);
+
+    /* need to unscale x & y */
+    point[X] = (sx ? point[X] * sx : 0.0);
+    point[Y] = (sy ? point[Y] * sy : 0.0);
+
+
+    return;
+}
 /*!
    \brief Convert surface to real coordinates
 

Modified: grass/branches/releasebranch_6_4/lib/ogsf/gvld.c
===================================================================
--- grass/branches/releasebranch_6_4/lib/ogsf/gvld.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/lib/ogsf/gvld.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -491,7 +491,8 @@
     float x, nextx, y, nexty, z, stepx, stepy, stepz;
     int cols, rows, c, r;
     float f_cols, f_rows, distxy, distz, modx, mody, modz, modxy;
-    int ptX, ptY, ptZ, resx, resy, resz;
+    int ptX, ptY, ptZ;
+    double resx, resy, resz;
 
     /* current slice */
     slice = gvl->slice[ndx];
@@ -664,7 +665,8 @@
 {
     float pt[3];
     int i;
-    int ptX, ptY, ptZ, resx, resy, resz;
+    int ptX, ptY, ptZ;
+    double resx, resy, resz;
 
     geovol_slice *slice;
 

Modified: grass/branches/releasebranch_6_4/misc/m.nviz.image/args.c
===================================================================
--- grass/branches/releasebranch_6_4/misc/m.nviz.image/args.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/misc/m.nviz.image/args.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -31,6 +31,8 @@
 static void args_volume(struct GParams *);
 static void args_lighting(struct GParams *);
 static void args_fringe(struct GParams *);
+static void args_cplane(struct GParams *);
+static void args_arrow(struct GParams *);
 
 /*!
   \brief Parse command
@@ -73,7 +75,13 @@
 
     /*** fringe ***/
     args_fringe(params);
-    
+
+    /*** cutting plane ***/ 
+    args_cplane(params);
+
+    /*** north arrow ***/ 
+    args_arrow(params);
+
     /*** output image ***/
     /* output */
     params->output = G_define_standard_option(G_OPT_F_OUTPUT);
@@ -377,7 +385,7 @@
     params->vpoint_size->multiple = YES;
     params->vpoint_size->description = _("Icon size");
     params->vpoint_size->guisection = _("Vector points");
-    params->vpoint_size->options = "1-1000";
+    params->vpoint_size->options = "1-10000";
     params->vpoint_size->answer = "100";
 
     /* point width */
@@ -485,6 +493,16 @@
     params->exag->multiple = NO;
     params->exag->description = _("Vertical exaggeration");
 
+    /* focus */
+    params->focus = G_define_option();
+    params->focus->key = "focus";
+    params->focus->key_desc = "x,y,z";
+    params->focus->type = TYPE_DOUBLE;
+    params->focus->required = NO;
+    params->focus->multiple = NO;
+    params->focus->description = _("Focus to point on surface (from SW corner in map units)");
+    params->focus->guisection = _("Viewpoint");
+
     return;
 }
 
@@ -551,9 +569,152 @@
     params->isosurf_level->description = _("Isosurface level");
     params->isosurf_level->guisection = _("Volumes");
 
+    /* isosurface color map */
+    params->isosurf_color_map = G_define_standard_option(G_OPT_R3_MAPS);
+    params->isosurf_color_map->key = "isosurf_color_map";
+    params->isosurf_color_map->required = NO;
+    params->isosurf_color_map->multiple = YES;
+    params->isosurf_color_map->description = _("Name of volume for isosurface color");
+    params->isosurf_color_map->guisection = _("Volumes");
+
+    /* isosurface color value */
+    params->isosurf_color_const = G_define_standard_option(G_OPT_C_FG);
+    params->isosurf_color_const->key = "isosurf_color_value";
+    params->isosurf_color_const->required = NO;
+    params->isosurf_color_const->multiple = YES;
+    params->isosurf_color_const->label = _("Isosurface color");
+    params->isosurf_color_const->guisection = _("Volumes");
+    params->isosurf_color_const->answer = NULL;
+
+    /* isosurface transparency */
+    params->isosurf_transp_map = G_define_standard_option(G_OPT_R3_MAP);
+    params->isosurf_transp_map->multiple = YES;
+    params->isosurf_transp_map->required = NO;
+    params->isosurf_transp_map->description =
+	_("Name of 3D raster map(s) for isosurface transparency");
+    params->isosurf_transp_map->guisection = _("Volumes");
+    params->isosurf_transp_map->key = "isosurf_transparency_map";
+
+    params->isosurf_transp_const = G_define_option();
+    params->isosurf_transp_const->key = "isosurf_transparency_value";
+    params->isosurf_transp_const->key_desc = "value";
+    params->isosurf_transp_const->type = TYPE_INTEGER;
+    params->isosurf_transp_const->required = NO;
+    params->isosurf_transp_const->multiple = YES;
+    params->isosurf_transp_const->description = _("Transparency value(s)for isosurfaces");
+    params->isosurf_transp_const->guisection = _("Volumes");
+    params->isosurf_transp_const->options = "0-255";
+    
+    /* isosurface shininess */
+    params->isosurf_shine_map = G_define_standard_option(G_OPT_R3_MAP);
+    params->isosurf_shine_map->multiple = YES;
+    params->isosurf_shine_map->required = NO;
+    params->isosurf_shine_map->description = _("Name of 3D raster map(s) for shininess");
+    params->isosurf_shine_map->guisection = _("Volumes");
+    params->isosurf_shine_map->key = "isosurf_shininess_map";
+
+    params->isosurf_shine_const = G_define_option();
+    params->isosurf_shine_const->key = "isosurf_shininess_value";
+    params->isosurf_shine_const->key_desc = "value";
+    params->isosurf_shine_const->type = TYPE_INTEGER;
+    params->isosurf_shine_const->required = NO;
+    params->isosurf_shine_const->multiple = YES;
+    params->isosurf_shine_const->description = _("Shininess value(s) for isosurfaces");
+    params->isosurf_shine_const->guisection = _("Volumes");
+    params->isosurf_shine_const->options = "0-255";
+
+    /* slices */
+    /* slice axis */
+    params->slice = G_define_option();
+    params->slice->key = "slice";
+    params->slice->key_desc = "volume:axis";
+    params->slice->type = TYPE_STRING;
+    params->slice->required = NO;
+    params->slice->multiple = YES;
+    params->slice->description = _("Volume slice parallel to given axis (x, y, z)");
+    params->slice->guisection = _("Volumes");
+
+    /* slice position */
+    params->slice_pos = G_define_option();
+    params->slice_pos->key = "slice_position";
+    params->slice_pos->key_desc = "x1,x2,y1,y2,z1,z2";
+    params->slice_pos->type = TYPE_DOUBLE;
+    params->slice_pos->required = NO;
+    params->slice_pos->multiple = YES;
+    params->slice_pos->description = _("Volume slice position");
+    params->slice_pos->guisection = _("Volumes");
+    params->slice_pos->answer = "0,1,0,1,0,1";
+    
+    /* slice transparency */
+    params->slice_transp = G_define_option();
+    params->slice_transp->key = "slice_transparency";
+    params->slice_transp->key_desc = "value";
+    params->slice_transp->type = TYPE_INTEGER;
+    params->slice_transp->required = NO;
+    params->slice_transp->multiple = YES;
+    params->slice_transp->description = _("Volume slice transparency");
+    params->slice_transp->guisection = _("Volumes");
+    params->slice_transp->answer = "0";
+    params->slice_transp->options = "0-255";
+
     return;
 }
 
+void args_cplane(struct GParams *params)
+{
+    params->cplane = G_define_option();
+    params->cplane->key = "cplane";
+    params->cplane->key_desc = "value";
+    params->cplane->type = TYPE_INTEGER;
+    params->cplane->required = NO;
+    params->cplane->multiple = YES;
+    params->cplane->description = _("Cutting plane index (0-5)");
+    params->cplane->guisection = _("Cutting planes");
+    
+    params->cplane_pos = G_define_option();
+    params->cplane_pos->key = "cplane_position";
+    params->cplane_pos->key_desc = "x,y,z";
+    params->cplane_pos->type = TYPE_DOUBLE;
+    params->cplane_pos->required = NO;
+    params->cplane_pos->multiple = YES;
+    params->cplane_pos->description = _("Cutting plane x,y,z coordinates");
+    params->cplane_pos->guisection = _("Cutting planes");
+    params->cplane_pos->answer = "0,0,0";
+    
+    params->cplane_rot = G_define_option();
+    params->cplane_rot->key = "cplane_rotation";
+    params->cplane_rot->key_desc = "value";
+    params->cplane_rot->type = TYPE_DOUBLE;
+    params->cplane_rot->multiple = YES;
+    params->cplane_rot->required = NO;
+    params->cplane_rot->guisection = _("Cutting planes");
+    params->cplane_rot->description = _("Cutting plane rotation along the vertical axis");
+    params->cplane_rot->answer = "0";
+    params->cplane_rot->options="0-360";
+    
+    params->cplane_tilt = G_define_option();
+    params->cplane_tilt->key = "cplane_tilt";
+    params->cplane_tilt->key_desc = "value";
+    params->cplane_tilt->type = TYPE_DOUBLE;
+    params->cplane_tilt->multiple = YES;
+    params->cplane_tilt->required = NO;
+    params->cplane_tilt->guisection = _("Cutting planes");
+    params->cplane_tilt->description = _("Cutting plane tilt");
+    params->cplane_tilt->answer = "0";
+    params->cplane_tilt->options="0-360";
+    
+    params->cplane_shading = G_define_option();
+    params->cplane_shading->key = "cplane_shading";
+    params->cplane_shading->key_desc = "string";
+    params->cplane_shading->type = TYPE_STRING;
+    params->cplane_shading->multiple = NO;
+    params->cplane_shading->required = NO;
+    params->cplane_shading->guisection = _("Cutting planes");
+    params->cplane_shading->description = _("Cutting plane color (between two surfaces)");
+    params->cplane_shading->answer = "clear";
+    params->cplane_shading->options= "clear,top,bottom,blend,shaded";
+}
+
 void args_lighting(struct GParams *params)
 {
     params->light_pos = G_define_option();
@@ -624,6 +785,36 @@
     params->fringe_elev->answer = "55";
 }
 
+void args_arrow(struct GParams *params)
+{
+    params->north_arrow = G_define_option();
+    params->north_arrow->key = "arrow_position";
+    params->north_arrow->key_desc = "x,y";
+    params->north_arrow->type = TYPE_INTEGER;
+    params->north_arrow->required = NO;
+    params->north_arrow->multiple = NO;
+    params->north_arrow->description = _("Place north arrow at given position \
+	(in screen coordinates from bottom left corner)");
+    params->north_arrow->guisection = _("Decoration");
+    
+    params->north_arrow_size = G_define_option();
+    params->north_arrow_size->key = "arrow_size";
+    params->north_arrow_size->key_desc = "value";
+    params->north_arrow_size->type = TYPE_DOUBLE;
+    params->north_arrow_size->required = NO;
+    params->north_arrow_size->multiple = NO;
+    params->north_arrow_size->description = _("North arrow size (in map units)");
+    params->north_arrow_size->guisection = _("Decoration");
+    
+    params->north_arrow_color = G_define_standard_option(G_OPT_C_FG);
+    params->north_arrow_color->key = "arrow_color";
+    params->north_arrow_color->required = NO;
+    params->north_arrow_color->multiple = NO;
+    params->north_arrow_color->label = _("North arrow color");
+    params->north_arrow_color->guisection = _("Decoration");
+    params->north_arrow_color->answer = "black";
+}
+
 /*!
    \brief Get number of answers of given option
 
@@ -642,6 +833,8 @@
 	    i++;
 	}
     }
+    
+    G_debug(3, "opt_get_num_answers(): opt=%s num=%d", opt->key, i);
 
     return i;
 }
@@ -654,10 +847,12 @@
 void check_parameters(const struct GParams *params)
 {
     int nelev_map, nelev_const, nelevs;
-    int nmaps, nconsts;
+    int nmaps, nconsts, ncoords, ncplanes;
 
     int nvects;
 
+    int nvolumes, nisosurf, nslices;
+
     /* topography */
     nelev_map = opt_get_num_answers(params->elev_map);
     nelev_const = opt_get_num_answers(params->elev_const);
@@ -742,6 +937,25 @@
 			  params->elev_map->key, params->elev_const->key,
 			  nelevs, params->wire_color->key, nconsts);
     }
+    
+    /* 
+     * Cutting planes
+     */
+    ncplanes = opt_get_num_answers(params->cplane);
+    ncoords = opt_get_num_answers(params->cplane_pos);
+	if (ncplanes > 0 && ncplanes * 3 != ncoords)
+	    G_fatal_error(_("Inconsistent number of attributes (<%s> %d: <%s> %d x 3)"),
+			  params->cplane->key, ncplanes, params->cplane_pos->key, ncoords/3);
+              
+    nconsts = opt_get_num_answers(params->cplane_rot);
+    if (ncplanes > 0 && ncplanes != nconsts)
+        G_fatal_error(_("Inconsistent number of attributes (<%s> %d: <%s> %d)"),
+          params->cplane->key, ncplanes, params->cplane_rot->key, nconsts);
+          
+    nconsts = opt_get_num_answers(params->cplane_tilt);
+    if (ncplanes > 0 && ncplanes != nconsts)
+        G_fatal_error(_("Inconsistent number of attributes (<%s> %d: <%s> %d)"),
+          params->cplane->key, ncplanes, params->cplane_tilt->key, nconsts);
 
     /*
      * vector
@@ -776,6 +990,50 @@
 		      params->vlines->key, nvects, params->vline_height->key,
 		      nconsts);
 
+    /* position */
+    nconsts = opt_get_num_answers(params->vline_pos);
+    if (nvects > 0 && nconsts != 3 * nvects)
+	G_fatal_error(_("Inconsistent number of attributes (<%s> %d: <%s> %d)"),
+		      params->vlines->key, nvects, params->vline_pos->key,
+		      nconsts);
+
+    /*
+     * volumes
+     */
+    nvolumes = opt_get_num_answers(params->volume);
+    nisosurf = opt_get_num_answers(params->isosurf_level);
+    nslices = opt_get_num_answers(params->slice);
+
+    /* isosurface transparency */
+    nmaps = opt_get_num_answers(params->isosurf_transp_map);
+    nconsts = opt_get_num_answers(params->isosurf_transp_const);
+
+    if ((nmaps + nconsts > 0) && (nisosurf != nmaps + nconsts))
+	G_fatal_error(_("Inconsistent number of attributes (<%s> %d: <%s> %d, <%s> %d"),
+		      params->isosurf_level->key, nisosurf, params->isosurf_transp_map->key, nmaps,
+		      params->isosurf_transp_const->key, nconsts);
+
+    /* isosurface shininess */
+    nmaps = opt_get_num_answers(params->isosurf_shine_map);
+    nconsts = opt_get_num_answers(params->isosurf_shine_const);
+
+    if ((nmaps + nconsts > 0) && (nisosurf != nmaps + nconsts))
+	G_fatal_error(_("Inconsistent number of attributes (<%s> %d: <%s> %d, <%s> %d"),
+			params->isosurf_level->key, nisosurf, params->isosurf_shine_map->key, nmaps,
+			params->isosurf_shine_const->key, nconsts);
+
+    /* slice transparency */
+    nconsts = opt_get_num_answers(params->slice_transp);
+    if (nslices > 0 && nslices != nconsts)
+	G_fatal_error(_("Inconsistent number of attributes (<%s> %d: <%s> %d)"),
+			params->slice->key, nslices, params->slice_transp->key, nconsts);
+
+    /* slice position */
+    ncoords = opt_get_num_answers(params->slice_pos);
+    if (nslices > 0 && ncoords != 6 * nslices)
+	G_fatal_error(_("Inconsistent number of attributes (<%s> %d: <%s> %d x 6)"),
+			  params->slice->key, nslices, params->slice_pos->key, ncoords/6);
+
     return;
 }
 
@@ -783,7 +1041,7 @@
 		 const char *elev_map, const char *elev_const,
 		 const char *map_name, const char *const_name)
 {
-    if ((nmaps > 0 && nelevs != nmaps) || (nconsts > 0 && nelevs != nconsts))
+    if ((nmaps + nconsts > 0) && (nelevs != nmaps + nconsts))
 	G_fatal_error(_("Inconsistent number of attributes (<%s/%s> %d: <%s> %d, <%s> %d"),
 		      elev_map, elev_const, nelevs, map_name, nmaps,
 		      const_name, nconsts);

Copied: grass/branches/releasebranch_6_4/misc/m.nviz.image/cplane.c (from rev 49357, grass/branches/develbranch_6/misc/m.nviz.image/cplane.c)
===================================================================
--- grass/branches/releasebranch_6_4/misc/m.nviz.image/cplane.c	                        (rev 0)
+++ grass/branches/releasebranch_6_4/misc/m.nviz.image/cplane.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -0,0 +1,72 @@
+/*!
+   \file cplane.c
+
+   \brief Cutting plane subroutine
+
+   (C) 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 Anna Kratochvilova <kratochanna gmail.com> (Google SoC 2010/2011)
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grass/glocale.h>
+
+#include "local_proto.h"
+
+/*!
+   \brief Draw cutting planes and set their attributes
+
+   \param params module parameters
+   \param data nviz data
+ */
+void draw_cplane(const struct GParams *params, nv_data * data)
+{
+    int i, id, ncplanes;
+    float trans_x, trans_y, trans_z;
+    float rot_x, rot_y, rot_z;
+    int fence;
+
+    ncplanes = opt_get_num_answers(params->cplane);
+    for (i = 0; i < ncplanes; i++) {
+	id = atoi(params->cplane->answers[i]);
+
+	if (id < 0 || id > Nviz_num_cplanes(data))
+	    G_fatal_error(_("Cutting plane number <%d> not found"), id);
+
+	Nviz_on_cplane(data, id);
+
+	trans_x = atof(params->cplane_pos->answers[i * 3 + 0]);
+	trans_y = atof(params->cplane_pos->answers[i * 3 + 1]);
+	trans_z = atof(params->cplane_pos->answers[i * 3 + 2]);
+	Nviz_set_cplane_translation(data, id, trans_x, trans_y, trans_z);
+
+	rot_x = 0;
+	rot_y = atof(params->cplane_tilt->answers[i]);
+	rot_z = atof(params->cplane_rot->answers[i]);
+	Nviz_set_cplane_rotation(data, id, rot_x, rot_y, rot_z);
+    }
+
+    const char *shading = params->cplane_shading->answers[0];
+
+    if (strcmp(shading, "clear") == 0)
+	fence = 0;
+    else if (strcmp(shading, "top") == 0)
+	fence = 1;
+    else if (strcmp(shading, "bottom") == 0)
+	fence = 2;
+    else if (strcmp(shading, "blend") == 0)
+	fence = 3;
+    else if (strcmp(shading, "shaded") == 0)
+	fence = 4;
+    else
+	fence = 0;
+    Nviz_set_fence_color(data, fence);
+
+    return;
+}

Modified: grass/branches/releasebranch_6_4/misc/m.nviz.image/description.html
===================================================================
--- grass/branches/releasebranch_6_4/misc/m.nviz.image/description.html	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/misc/m.nviz.image/description.html	2012-02-20 09:41:50 UTC (rev 50895)
@@ -23,7 +23,13 @@
 
 <h2>AUTHOR</h2>
 
-Martin Landa (Google Summer of Code 2008/2010)
+<a href="http://geo.fsv.cvut.cz/gwiki/Landa">Martin
+Landa</a>, <a href="http://grass.osgeo.org/wiki/WxNviz_GSoC_2008">Google
+Summer of Code 2008</a> (mentor: Michael Barton)
+and <a href="http://grass.osgeo.org/wiki/WxNviz_GSoC_2010">Google
+Summer of Code 2010</a> (mentor: Helena Mitasova)<br>
+Anna Kratochvilova, <a href="http://grass.osgeo.org/wiki/WxNviz_GSoC_2011">Google
+Summer of Code 2011</a> (mentor: Martin Landa)
 
 <p>
 <i>Last changed: $Date$</i>

Modified: grass/branches/releasebranch_6_4/misc/m.nviz.image/local_proto.h
===================================================================
--- grass/branches/releasebranch_6_4/misc/m.nviz.image/local_proto.h	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/misc/m.nviz.image/local_proto.h	2012-02-20 09:41:50 UTC (rev 50895)
@@ -21,16 +21,22 @@
 	*vpoints, *vpoint_size, *vpoint_marker, *vpoint_color, *vpoint_width, *vpoint_pos,
     /* volumes */
 	*volume, *volume_mode, *volume_shade, *volume_pos, *volume_res, *isosurf_level,
+	*isosurf_color_map, *isosurf_color_const, *isosurf_transp_map, *isosurf_transp_const,
+	*isosurf_shine_map, *isosurf_shine_const, *slice_pos, *slice, *slice_transp,
     /* misc */
 	*exag, *bgcolor,
+    /* cutting planes */
+	*cplane, *cplane_pos, *cplane_rot, *cplane_tilt, *cplane_shading,
     /* viewpoint */
-	*pos, *height, *persp, *twist,
+	*pos, *height, *persp, *twist, *focus,
     /* output */
 	*output, *format, *size,
     /* lighting */
 	*light_pos, *light_color, *light_bright, *light_ambient,
     /* fringe */
-	*fringe, *fringe_color, *fringe_elev;
+	*fringe, *fringe_color, *fringe_elev,
+    /* north arrow */
+	*north_arrow, *north_arrow_size, *north_arrow_color;
 };
 
 /* args.c */
@@ -52,7 +58,11 @@
 /* volume.c */
 int load_rasters3d(const struct GParams *, nv_data *);
 int add_isosurfs(const struct GParams *, nv_data *);
+int add_slices(const struct GParams *, nv_data *);
 
+/* cutting planes */
+void draw_cplane(const struct GParams *, nv_data *);
+
 /* write_img.c */
 int write_img(const char *, int);
 

Modified: grass/branches/releasebranch_6_4/misc/m.nviz.image/main.c
===================================================================
--- grass/branches/releasebranch_6_4/misc/m.nviz.image/main.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/misc/m.nviz.image/main.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -34,6 +34,7 @@
 
     int i, ret;
     int red, grn, blu;
+    float size;
     double vp_height, z_exag;	/* calculated viewpoint height, z-exag */
     int width, height;		/* output image size */
     char *output_name;
@@ -116,6 +117,11 @@
 	add_isosurfs(params, &data);
     }
 
+    /* define slices for displaying volumes */
+    if (params->slice->answer) {
+	add_slices(params, &data);
+    }
+
     /* focus on loaded data */
     Nviz_set_focus_map(MAP_OBJ_UNDEFINED, -1);
 
@@ -147,6 +153,11 @@
 				atof(params->pos->answers[1]));
     Nviz_set_viewpoint_twist(atoi(params->twist->answer));
     Nviz_set_viewpoint_persp(atoi(params->persp->answer));
+    if (params->focus->answer) {
+    Nviz_set_focus(&data, atof(params->focus->answers[0]),
+						  atof(params->focus->answers[1]), 
+						  atof(params->focus->answers[2]));
+    }
 
     /* set lights */
     Nviz_set_light_position(&data, 1,
@@ -183,11 +194,28 @@
 	Nviz_new_fringe(&data, -1, Nviz_color_from_str(params->fringe_color->answer),
 			atof(params->fringe_elev->answer), nw, ne, sw, se);
     }
-    
+
+/* draw north arrow */
+    if (params->north_arrow->answer) {
+	
+	if (!params->north_arrow_size->answer)
+	    size = Nviz_get_longdim(&data) / 8.;
+	else
+	    size = atof(params->north_arrow_size->answer);
+
+	Nviz_set_arrow(&data, atoi(params->north_arrow->answers[0]),
+			      atoi(params->north_arrow->answers[1]),
+			      size, Nviz_color_from_str(params->north_arrow_color->answer));
+	Nviz_draw_arrow(&data);
+    }
+
     GS_clear(data.bgcolor);
 
+    /* cutting planes */
+    if(params->cplane->answer)
+        draw_cplane(params, &data);
+
     /* draw */
-    Nviz_draw_cplane(&data, -1, -1);
     Nviz_draw_all(&data);
 
     /* write to image */

Modified: grass/branches/releasebranch_6_4/misc/m.nviz.image/surface.c
===================================================================
--- grass/branches/releasebranch_6_4/misc/m.nviz.image/surface.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/misc/m.nviz.image/surface.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -40,10 +40,7 @@
     nelev_map = opt_get_num_answers(params->elev_map);
     nelev_const = opt_get_num_answers(params->elev_const);
 
-    if (nelev_map > 0)
-	nelevs = nelev_map;
-    else
-	nelevs = nelev_const;
+    nelevs = nelev_const + nelev_map;
 
     /* topography (required) */
     for (i = 0; i < nelevs; i++) {
@@ -61,10 +58,10 @@
 				  0.0, data);
 	}
 	else {
-	    if (i < nelev_const && strcmp(params->elev_const->answers[i], "")) {
+	    if (i-nelev_map < nelev_const && strcmp(params->elev_const->answers[i-nelev_map], "")) {
 		id = Nviz_new_map_obj(MAP_OBJ_SURF,
 				      NULL,
-				      atof(params->elev_const->answers[i]),
+				      atof(params->elev_const->answers[i-nelev_map]),
 				      data);
 	    }
 	    else {
@@ -74,16 +71,17 @@
 	}
 
 	/* set position */
-	if (params->mode_all->answer) {	/* use one mode for all surfaces */
-	    x = atof(params->surface_pos->answers[0]);
-	    y = atof(params->surface_pos->answers[1]);
-	    z = atof(params->surface_pos->answers[2]);
-	}
-	else {
-	    x = atof(params->surface_pos->answers[i]);
-	    y = atof(params->surface_pos->answers[i+1]);
-	    z = atof(params->surface_pos->answers[i+2]);
-	}
+    if (opt_get_num_answers(params->surface_pos) != 3 * nelevs){
+        x = atof(params->surface_pos->answers[0]);
+        y = atof(params->surface_pos->answers[1]);
+        z = atof(params->surface_pos->answers[2]);
+    }
+    else {
+        x = atof(params->surface_pos->answers[i*3+0]);
+        y = atof(params->surface_pos->answers[i*3+1]);
+        z = atof(params->surface_pos->answers[i*3+2]);
+    }
+
 	GS_set_trans(id, x, y, z);
     }
 
@@ -117,19 +115,25 @@
 			  data);
 	}
 	/* check for color value */
-	else if (i < ncolor_const &&
-		 strcmp(params->color_const->answers[i], "")) {
+	else if (i-ncolor_map < ncolor_const &&
+		 strcmp(params->color_const->answers[i-ncolor_map], "")) {
 	    Nviz_set_attr(id, MAP_OBJ_SURF, ATT_COLOR, CONST_ATT, NULL,
 			  Nviz_color_from_str(params->color_const->
-					      answers[i]), data);
+					      answers[i-ncolor_map]), data);
 	}
 	else {			/* use by default elevation map for coloring */
-	    Nviz_set_attr(id, MAP_OBJ_SURF, ATT_COLOR, MAP_ATT,
-			  G_fully_qualified_name(params->elev_map->answers[i],
-						 mapset), -1.0, data);
-	    G_verbose_message(_("Color attribute not defined, using default <%s>"),
-			      G_fully_qualified_name(params->elev_map->
-						     answers[i], mapset));
+	    if (nelev_map > 0){
+	        Nviz_set_attr(id, MAP_OBJ_SURF, ATT_COLOR, MAP_ATT,
+			      G_fully_qualified_name(params->elev_map->answers[i],
+						     mapset), -1.0, data);
+	        G_verbose_message(_("Color attribute not defined, using default <%s>"),
+				  G_fully_qualified_name(params->elev_map->
+							 answers[i], mapset));
+        }
+        else{
+            G_fatal_error(_("Missing color attribute for surface %d"),
+			      i + 1);
+        }
 	}
 	/* mask */
 	if (i < nmask_map && strcmp(params->mask_map->answers[i], "")) {
@@ -145,10 +149,10 @@
 						 answers[i], mapset), -1.0,
 			  data);
 	}
-	else if (i < ntransp_const &&
-		 strcmp(params->transp_const->answers[i], "")) {
+	else if (i-ntransp_map < ntransp_const &&
+		 strcmp(params->transp_const->answers[i-ntransp_map], "")) {
 	    Nviz_set_attr(id, MAP_OBJ_SURF, ATT_TRANSP, CONST_ATT, NULL,
-			  atof(params->transp_const->answers[i]), data);
+			  atof(params->transp_const->answers[i-ntransp_map]), data);
 	}
 
 	/* shininess */
@@ -158,10 +162,10 @@
 						 answers[i], mapset), -1.0,
 			  data);
 	}
-	else if (i < nshine_const &&
-		 strcmp(params->shine_const->answers[i], "")) {
+	else if (i-nshine_map < nshine_const &&
+		 strcmp(params->shine_const->answers[i-nshine_map], "")) {
 	    Nviz_set_attr(id, MAP_OBJ_SURF, ATT_SHINE, CONST_ATT, NULL,
-			  atof(params->shine_const->answers[i]), data);
+			  atof(params->shine_const->answers[i-nshine_map]), data);
 	}
 
 	/* emission */
@@ -170,10 +174,10 @@
 			  G_fully_qualified_name(params->emit_map->answers[i],
 						 mapset), -1.0, data);
 	}
-	else if (i < nemit_const &&
-		 strcmp(params->emit_const->answers[i], "")) {
+	else if (i-nemit_map < nemit_const &&
+		 strcmp(params->emit_const->answers[i-nemit_map], "")) {
 	    Nviz_set_attr(id, MAP_OBJ_SURF, ATT_EMIT, CONST_ATT, NULL,
-			  atof(params->emit_const->answers[i]), data);
+			  atof(params->emit_const->answers[i-nemit_map]), data);
 	}
 
 	/*
@@ -192,7 +196,7 @@
 */
 void surface_set_draw_mode(const struct GParams *params)
 {
-    int *surf_list, nsurfs, idx;
+    int *surf_list, nsurfs;
     int i, id, draw_mode;
     int resol_fine, resol_coarse;
 
@@ -200,26 +204,29 @@
 
     surf_list = GS_get_surf_list(&nsurfs);
 
-    /* use one mode for all surfaces */
-    if (params->mode_all->answer)
-	idx = 0;
-    
     for (i = 0; i < nsurfs; i++) {
 	draw_mode = 0;
 	id = surf_list[i];
 	if (!GS_surf_exists(id))
 	    G_fatal_error(_("Surface id %d doesn't exist"), id);
 
-	if (!params->mode_all->answer)
-	    idx = i;
+	if (params->mode_all->answer) {	/* use one mode for all surfaces */
+	    mode = params->mode->answers[0];
+	    style = params->style->answers[0];
+	    shade = params->shade->answers[0];
+	    res_fine = params->res_fine->answers[0];
+	    res_coarse = params->res_coarse->answers[0];
+	    wire_color = params->wire_color->answers[0];
+	}
+	else {
+	    mode = params->mode->answers[i];
+	    style = params->style->answers[i];
+	    shade = params->shade->answers[i];
+	    res_fine = params->res_fine->answers[i];
+	    res_coarse = params->res_coarse->answers[i];
+	    wire_color = params->wire_color->answers[i];
+	}
 
-	mode = params->mode->answers[idx];
-	style = params->style->answers[idx];
-	shade = params->shade->answers[idx];
-	res_fine = params->res_fine->answers[idx];
-	res_coarse = params->res_coarse->answers[idx];
-	wire_color = params->wire_color->answers[idx];
-	
 	/* mode */
 	if (strcmp(mode, "coarse") == 0) {
 	    draw_mode |= DM_WIRE;
@@ -232,7 +239,7 @@
 	}
 
 	/* style */
-	if (strcmp(params->style->answers[idx], "wire") == 0) {
+	if (strcmp(style, "wire") == 0) {
 	    draw_mode |= DM_GRID_WIRE;
 	}
 	else {			/* surface */
@@ -240,7 +247,7 @@
 	}
 
 	/* shading */
-	if (strcmp(params->shade->answers[idx], "flat") == 0) {
+	if (strcmp(shade, "flat") == 0) {
 	    draw_mode |= DM_FLAT;
 	}
 	else {			/* gouraud */

Modified: grass/branches/releasebranch_6_4/misc/m.nviz.image/vector.c
===================================================================
--- grass/branches/releasebranch_6_4/misc/m.nviz.image/vector.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/misc/m.nviz.image/vector.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -85,9 +85,9 @@
 			      0.0, data);
 
 	/* set position */
-	x = atof(position->answers[i]);
-	y = atof(position->answers[i+1]);
-	z = atof(position->answers[i+2]);
+	x = atof(position->answers[i*3+0]);
+	y = atof(position->answers[i*3+1]);
+	z = atof(position->answers[i*3+2]);
 
 	if (map_obj_type == MAP_OBJ_VECT)
 	    GV_set_trans(id, x, y, z);

Modified: grass/branches/releasebranch_6_4/misc/m.nviz.image/volume.c
===================================================================
--- grass/branches/releasebranch_6_4/misc/m.nviz.image/volume.c	2012-02-20 04:29:26 UTC (rev 50894)
+++ grass/branches/releasebranch_6_4/misc/m.nviz.image/volume.c	2012-02-20 09:41:50 UTC (rev 50895)
@@ -13,6 +13,7 @@
 */
 
 #include <stdlib.h>
+#include <string.h>
 
 #include <grass/G3d.h>
 #include <grass/glocale.h>
@@ -29,7 +30,8 @@
 */
 int load_rasters3d(const struct GParams *params, nv_data *data)
 {
-  int i, nvol, id;
+    int i, nvol, id;
+    float x, y, z;
     char *mapset;
     
     nvol = opt_get_num_answers(params->volume);
@@ -45,6 +47,20 @@
 			      G_fully_qualified_name(params->volume->answers[i],
 						     mapset),
 			      0.0, data);
+    
+	/* set position */
+	if (opt_get_num_answers(params->volume_pos) != 3 * nvol) {
+	    x = atof(params->volume_pos->answers[0]);
+	    y = atof(params->volume_pos->answers[1]);
+	    z = atof(params->volume_pos->answers[2]);
+	}
+	else {
+	    x = atof(params->volume_pos->answers[i*3+0]);
+	    y = atof(params->volume_pos->answers[i*3+1]);
+	    z = atof(params->volume_pos->answers[i*3+2]);
+	}
+    
+	GVL_set_trans(id, x, y, z);
     }
 
     return 1;
@@ -61,8 +77,12 @@
 int add_isosurfs(const struct GParams *params, nv_data *data)
 {
     int i;
-    int num, level, nvols, *vol_list, id, nisosurfs;
+    float level;
+    int num, nvols, *vol_list, id, nisosurfs;
+    int ncolor_map, ncolor_const, ntransp_map, ntransp_const, nshine_map, nshine_const;
+    int res, draw_mode;
     char **tokens;
+    const char *mapset, *style;
     
     vol_list = GVL_get_vol_list(&nvols);
 
@@ -72,7 +92,7 @@
 	    G_fatal_error(_("Error tokenize '%s'"), 
 			  params->isosurf_level->answers[i]);
 	num = atoi(tokens[0]);
-	level = atoi(tokens[1]);
+	level = atof(tokens[1]);
 	G_free_tokens(tokens);
 
 	if (num > nvols) {
@@ -95,11 +115,192 @@
 	}
 
 	/* color */
-	if (GVL_isosurf_set_att_map(id, nisosurfs-1, ATT_COLOR, params->volume->answers[0]) < 0) {
-	    G_fatal_error(_("Unable to set isosurface (%d) attribute (%d) of volume %d"),
-			  nisosurfs-1, ATT_COLOR, id);
+	ncolor_map = opt_get_num_answers(params->isosurf_color_map);
+	ncolor_const = opt_get_num_answers(params->isosurf_color_const);
+
+	if (i < ncolor_map && strcmp(params->isosurf_color_map->answers[i], "")) {
+	    mapset = G_find_grid3(params->isosurf_color_map->answers[i], "");
+
+	    if (mapset == NULL) {
+		G_fatal_error(_("3d raster map <%s> not found"),
+			      params->isosurf_color_map->answers[i]);
+	    }
+
+	    if (GVL_isosurf_set_att_map(id, nisosurfs-1, ATT_COLOR, 
+					params->isosurf_color_map->answers[i]) < 0)
+		G_fatal_error(_("Unable to set isosurface (%d) attribute (%d) of volume %d"),
+				nisosurfs-1, ATT_COLOR, id);
 	}
+	else if (i-ncolor_map < ncolor_const &&
+		 strcmp(params->isosurf_color_const->answers[i-ncolor_map], "")) {
+
+	    if (GVL_isosurf_set_att_const(id, nisosurfs-1, ATT_COLOR,
+			    Nviz_color_from_str(params->isosurf_color_const->answers[i-ncolor_map])) < 0)
+		G_fatal_error(_("Unable to set isosurface (%d) attribute (%d) of volume %d"),
+				nisosurfs-1, ATT_COLOR, id);
+	}
+	else {			/* use by default 3d raster map for coloring */
+	    GVL_isosurf_set_att_map(id, nisosurfs-1, ATT_COLOR, params->volume->answers[num-1]);
+	    G_verbose_message(_("Color attribute not defined, using default <%s>"),
+				params->volume->answers[num-1]);
+	}
+
+	/* transparency */
+	ntransp_map = opt_get_num_answers(params->isosurf_transp_map);
+	ntransp_const = opt_get_num_answers(params->isosurf_transp_const);
+
+	if (i < ntransp_map && strcmp(params->isosurf_transp_map->answers[i], "")) {
+	    if (GVL_isosurf_set_att_map(id, nisosurfs-1, ATT_TRANSP, 
+					params->isosurf_transp_map->answers[i]) < 0)
+		G_fatal_error(_("Unable to set isosurface (%d) attribute (%d) of volume %d"),
+				nisosurfs-1, ATT_TRANSP, id);
+	}
+	else if (i-ntransp_map < ntransp_const &&
+		 strcmp(params->isosurf_transp_const->answers[i-ntransp_map], "")) {
+	    if (GVL_isosurf_set_att_const(id, nisosurfs-1, ATT_TRANSP,
+					  atof(params->isosurf_transp_const->answers[i-ntransp_map])) < 0)
+		G_fatal_error(_("Unable to set isosurface (%d) attribute (%d) of volume %d"),
+				nisosurfs-1, ATT_TRANSP, id);
+	}
+
+	/* shine */
+	nshine_map = opt_get_num_answers(params->isosurf_shine_map);
+	nshine_const = opt_get_num_answers(params->isosurf_shine_const);
+
+	if (i < nshine_map && strcmp(params->isosurf_shine_map->answers[i], "")) {
+	    if (GVL_isosurf_set_att_map(id, nisosurfs-1, ATT_SHINE, 
+					params->isosurf_shine_map->answers[i]) < 0)
+		G_fatal_error(_("Unable to set isosurface (%d) attribute (%d) of volume %d"),
+				nisosurfs-1, ATT_SHINE, id);
+	}
+	else if (i-nshine_map < nshine_const &&
+		 strcmp(params->isosurf_shine_const->answers[i-nshine_map], "")) {
+	    if (GVL_isosurf_set_att_const(id, nisosurfs-1, ATT_SHINE,
+					  atof(params->isosurf_shine_const->answers[i-nshine_map])) < 0)
+		G_fatal_error(_("Unable to set isosurface (%d) attribute (%d) of volume %d"),
+				nisosurfs-1, ATT_SHINE, id);
+	}
     }
-    
+
+        /* set draw resolution and shading after isosurfaces are added*/
+    for (i = 0; i < nvols; i++) {
+
+	id = vol_list[i];
+	/* set resolution */
+	if (opt_get_num_answers(params->volume_res) != nvols)
+	    res = atof(params->volume_res->answers[0]);
+	else
+	    res = atof(params->volume_res->answers[i]);
+
+	GVL_isosurf_set_drawres(id, res, res, res);
+
+	/* set shading */
+	if (opt_get_num_answers(params->volume_shade) != nvols)
+	    style = params->volume_shade->answers[0];
+	else
+	    style = params->volume_shade->answers[i];
+
+	draw_mode = 0;
+
+	if (strcmp(style, "flat") == 0) {
+	    draw_mode |= DM_FLAT;
+	}
+	else {
+	    draw_mode |= DM_GOURAUD;
+	}
+	
+	GVL_isosurf_set_drawmode(id, draw_mode);
+    }
+
     return 1;
 }
+
+int add_slices(const struct GParams *params, nv_data *data)
+{
+    int i;
+    int num, nvols, *vol_list, id, nslices, axis;
+    int res, draw_mode;
+    char **tokens;
+    const char* style;
+
+    vol_list = GVL_get_vol_list(&nvols);
+
+    for (i = 0; params->slice->answers[i]; i++) {
+	tokens = G_tokenize(params->slice->answers[i], ":");
+	if (G_number_of_tokens(tokens) != 2) 
+	    G_fatal_error(_("Error tokenize '%s'"), 
+			  params->slice->answers[i]);
+	num = atoi(tokens[0]);
+
+	if (!strcmp(tokens[1],"x") || !strcmp(tokens[1],"X"))
+	    axis = 0;
+	else if (!strcmp(tokens[1],"y") || !strcmp(tokens[1],"Y"))
+	    axis = 1;
+	else if (!strcmp(tokens[1],"z") || !strcmp(tokens[1],"Z"))
+	    axis = 2;
+	else
+	    G_fatal_error(_("Wrong name for axis: %s"), 
+			  tokens[1]);
+	G_free_tokens(tokens);
+
+	if (num > nvols) {
+	    G_fatal_error(_("Volume set number %d is not available"), 
+			  num);
+	}
+
+	id = vol_list[num-1];
+	if (GVL_slice_add(id) < 0) {
+	    G_fatal_error(_("Unable to add slice (volume set %d)"),
+			  id);
+	}
+
+	nslices = GVL_slice_num_slices(id);
+
+	if (GVL_slice_set_pos(id, nslices-1, atof(params->slice_pos->answers[i*6+0]),
+					     atof(params->slice_pos->answers[i*6+1]),
+					     atof(params->slice_pos->answers[i*6+2]),
+					     atof(params->slice_pos->answers[i*6+3]),
+					     atof(params->slice_pos->answers[i*6+4]),
+					     atof(params->slice_pos->answers[i*6+5]),
+					     axis) < 0) 
+	    G_fatal_error(_("Unable to set slice (%d) position of volume %d"),
+			  nslices-1, id);
+
+	/* set transparency */
+	if (GVL_slice_set_transp(id, nslices-1, atoi(params->slice_transp->answers[i])) < 0)
+	    G_fatal_error(_("Unable to set slice (%d) transparency of volume %d"),
+			  nslices-1, id);
+    }
+
+    /* set draw resolution and shading after slices are added*/
+    for (i = 0; i < nvols; i++) {
+
+	id = vol_list[i];
+	/* set resolution */
+	if (opt_get_num_answers(params->volume_res) != nvols)
+	    res = atof(params->volume_res->answers[0]);
+	else
+	    res = atof(params->volume_res->answers[i]);
+
+	GVL_slice_set_drawres(id, res, res, res);
+
+	/* set shading */
+	if (opt_get_num_answers(params->volume_shade) != nvols)
+	    style = params->volume_shade->answers[0];
+	else
+	    style = params->volume_shade->answers[i];
+
+	draw_mode = 0;
+
+	if (strcmp(style, "flat") == 0) {
+	    draw_mode |= DM_FLAT;
+	}
+	else {
+	    draw_mode |= DM_GOURAUD;
+	}
+
+	GVL_slice_set_drawmode(id, draw_mode);
+    }
+
+    return 1;
+}



More information about the grass-commit mailing list