[GRASS-dev] Modules
Glynn Clements
glynn at gclements.plus.com
Wed Feb 21 23:56:57 EST 2007
Glynn Clements wrote:
> > > It's looking as if the most practical replacement is going to be to
> > > take the existing v.digit, and replace R_*, D_* and Tcl_* with a real
> > > GUI toolkit.
> >
> > To this end, I've started refactoring v.digit in the hope of making it
> > easier to use a conventional GUI toolkit.
> >
> > So far, I've modified attr.c and line.c, corresponding to the
> > following "tools":
> >
> > copy cats
> > display attributes
> > display cats
> > new line
> > edit line
> > move line
> > delete line
>
> I've now modified the remaining tools, namely:
>
> split line
> add vertex
> move vertex
> remove vertex
> zoom pan
> zoom window
>
> All usage of R_get_location_with_* is now localised to a single
> function.
The next bit is somewhat more radical, so I haven't committed it to
CVS yet.
The attached patch completely eliminates the use of the raster library
and display drivers by v.digit, in favour of a Tk canvas widget. The
patch needs to be applied from within the v.digit directory.
Testing and comments would be appreciated.
--
Glynn Clements <glynn at gclements.plus.com>
-------------- next part --------------
Index: c_face.c
===================================================================
RCS file: /grassrepository/grass6/vector/v.digit/c_face.c,v
retrieving revision 1.17
diff -u -r1.17 c_face.c
--- c_face.c 4 May 2006 19:37:26 -0000 1.17
+++ c_face.c 22 Feb 2007 04:19:33 -0000
@@ -20,7 +20,7 @@
c_cancel ( ClientData cdata, Tcl_Interp *interp, int argc, char *argv[])
{
G_debug (3, "c_cancel()");
- R_set_cancel ( 1 );
+ cancel_tool ();
Tool_next = TOOL_NOTHING;
return TCL_OK;
}
@@ -90,7 +90,7 @@
G_debug (2, " Tool_next = %d", Tool_next);
/* Stop running if any */
- R_set_cancel ( 1 );
+ cancel_tool ();
return TCL_OK;
}
Index: display.c
===================================================================
RCS file: /grassrepository/grass6/vector/v.digit/display.c,v
retrieving revision 1.12
diff -u -r1.12 display.c
--- display.c 18 Feb 2007 20:16:33 -0000 1.12
+++ display.c 22 Feb 2007 04:19:33 -0000
@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
+#include <math.h>
#include <grass/gis.h>
#include <grass/Vect.h>
#include <grass/raster.h>
@@ -24,13 +25,70 @@
G_debug (2, "display_points()");
- R_line_width ( var_geti( VAR_LINEWIDTH ) );
- for(i=1; i < Points->n_points; i++) {
- G_plot_line ( Points->x[i-1], Points->y[i-1], Points->x[i], Points->y[i]);
- }
- R_line_width ( 0 );
-
- if ( flsh ) R_flush();
+ driver_line_width ( var_geti( VAR_LINEWIDTH ) );
+ for(i=1; i < Points->n_points; i++)
+ driver_plot_line(Points->x[i-1], Points->y[i-1],
+ Points->x[i ], Points->y[i ]);
+ driver_line_width( 0 );
+}
+
+static int trans ( double *x, double *y, int n_points, double angle, double scale,
+ double xc, double yc ) {
+ int i;
+ double r, a;
+
+ for ( i = 0; i < n_points; i++) {
+ r = scale * hypot ( x[i], y[i] );
+ a = atan2 ( y[i], x[i] );
+ a += angle;
+ x[i] = r * cos(a) + xc;
+ y[i] = r * sin(a) + yc;
+ }
+
+ return 1;
+}
+
+/* Plot icon */
+static void plot_icon(double xc, double yc, int type, double angle, double scale)
+{
+ int i, np = 0;
+ double x[10], y[10];
+
+
+ /* diamond, box */
+ switch(type) {
+ case G_ICON_CROSS:
+ x[0] = -0.5; y[0] = 0.0;
+ x[1] = 0.5; y[1] = 0.0;
+ x[2] = 0.0; y[2] = -0.5;
+ x[3] = 0.0; y[3] = 0.5;
+ np = 4;
+ break;
+ case G_ICON_BOX:
+ G_debug (1, "box");
+ x[0] = -0.5; y[0] = -0.5;
+ x[1] = 0.5; y[1] = -0.5;
+ x[2] = 0.5; y[2] = -0.5;
+ x[3] = 0.5; y[3] = 0.5;
+ x[4] = 0.5; y[4] = 0.5;
+ x[5] = -0.5; y[5] = 0.5;
+ x[6] = -0.5; y[6] = 0.5;
+ x[7] = -0.5; y[7] = -0.5;
+ np = 8;
+ break;
+ case G_ICON_ARROW:
+ x[0] = -1; y[0] = 0.5;
+ x[1] = 0; y[1] = 0.0;
+ x[2] = -1; y[2] = -0.5;
+ x[3] = 0; y[3] = 0.0;
+ np = 4;
+ break;
+ }
+
+ trans ( x, y, np, angle, scale, xc, yc);
+
+ for ( i = 0; i < np; i += 2 )
+ driver_plot_line(x[i], y[i], x[i+1], y[i+1]);
}
/* Display icon */
@@ -38,11 +96,9 @@
{
G_debug (2, "display_icon()");
- R_line_width ( var_geti( VAR_LINEWIDTH ) );
- G_plot_icon(x, y, icon, angle, Scale * size);
- R_line_width ( 0 );
-
- if ( flsh ) R_flush();
+ driver_line_width ( var_geti( VAR_LINEWIDTH ) );
+ plot_icon(x, y, icon, angle, Scale * size);
+ driver_line_width ( 0 );
}
/* Display vector line
@@ -91,7 +147,6 @@
if ( !Vect_line_alive ( &Map, line ) ) continue;
display_line ( line, symb, 0 );
}
- R_flush();
}
/* Display node, color may be given but shape and size is read from symbology table,
@@ -130,7 +185,6 @@
if ( NodeSymb[node] == SYMB_NODE_0 ) continue;
display_node ( node, symb, 0);
}
- R_flush();
}
/* Display vector map */
@@ -155,7 +209,6 @@
if ( !Symb[symb].on ) continue;
display_line ( i , SYMB_DEFAULT, 0 );
}
- R_flush();
/* Nodes: first nodes with more than 1 line, then nodes with only 1 line,
* so that dangles are not hidden, and nodes without lines (points,
@@ -169,7 +222,6 @@
if ( NodeSymb[i] != SYMB_NODE_2 ) continue;
display_node(i, NodeSymb[i], 0);
}
- R_flush();
}
if ( Symb[SYMB_NODE_1].on ) {
@@ -180,34 +232,28 @@
if ( NodeSymb[i] != SYMB_NODE_1 ) continue;
display_node(i, NodeSymb[i], 0);
}
- R_flush();
}
}
/* Display bacground */
void display_bg ( void )
{
+#if 0
int i;
G_debug (2, "display_bg()");
- driver_close();
for(i=0; i < nbgcmd; i++) {
if ( Bgcmd[i].on )
system ( Bgcmd[i].cmd );
}
- driver_open();
+#endif
}
/* Erase */
void display_erase ( void )
{
- char command[128];
-
- driver_close();
- sprintf(command, "d.erase color=white");
- system( command ); /* It does everything and command is registered */
- driver_open();
+ Tcl_Eval(Toolbox, ".screen.canvas delete all");
/* As erase must be run after each zoom by v.digit, here is good place to reset plot.
* Other such place is display_map() */
Index: driver.c
===================================================================
RCS file: /grassrepository/grass6/vector/v.digit/driver.c,v
retrieving revision 1.6
diff -u -r1.6 driver.c
--- driver.c 18 Feb 2007 20:16:33 -0000 1.6
+++ driver.c 22 Feb 2007 04:19:33 -0000
@@ -5,57 +5,97 @@
#include "global.h"
#include "proto.h"
+static char color[16];
+static int width;
+
+void driver_rgb_color(int r, int g, int b)
+{
+ sprintf(color, "#%02x%02x%02x", r, g, b);
+}
+
+void driver_line_width(int w)
+{
+ width = w ? w : 1;
+}
+
+static int round(double x)
+{
+ return (int) floor(x + 0.5);
+}
+
+void driver_plot_line(double x1, double y1, double x2, double y2)
+{
+ char buf[1024];
+
+ sprintf(buf, ".screen.canvas create line %d %d %d %d -width %d -fill %s",
+ round(D_u_to_d_col(x1)),
+ round(D_u_to_d_row(y1)),
+ round(D_u_to_d_col(x2)),
+ round(D_u_to_d_row(y2)),
+ width, color);
+
+ Tcl_Eval(Toolbox, buf);
+}
+
+static void get_window(int *t, int *b, int *l, int *r)
+{
+ Tcl_Eval(Toolbox, "list 0 [.screen.canvas cget -width] 0 [.screen.canvas cget -height]");
+ sscanf(Toolbox->result, "%d %d %d %d", t, b, l, r);
+}
+
+static void setup(void)
+{
+ struct Cell_head region;
+ int t, b, l, r;
+
+ get_window(&t, &b, &l, &r);
+
+ /* Set the map region associated with graphics frame */
+ G_get_set_window(®ion);
+ if(G_set_window(®ion) < 0)
+ G_fatal_error ("Invalid graphics coordinates");
+
+ /* Determine conversion factors */
+ if (D_do_conversions(®ion, t, b, l, r))
+ G_fatal_error("Error calculating graphics-region conversions") ;
+}
int driver_refresh (void)
{
- D_setup (0);
- G_setup_plot (D_get_d_north(), D_get_d_south(), D_get_d_west(), D_get_d_east(),
- D_move_abs, D_cont_abs);
+ setup();
return 1;
}
-
+
int driver_open (void)
{
int top, bot, left, right;
double n, s, e, w;
- G_debug (5, "driver_open()");
- if (R_open_driver() != 0) G_fatal_error ("No graphics device selected");
- G_debug (5, " -> opened");
-
- D_setup (0);
- D_get_screen_window ( &top, &bot, &left, &right);
- G_debug (2, "top = %d bot = %d, left = %d right = %d", top, bot, left, right);
+ Tcl_Eval(Toolbox,
+ "if {![winfo exists .screen]} {\n"
+ " toplevel .screen\n"
+ " canvas .screen.canvas -background white -width 640 -height 480\n"
+ " pack .screen.canvas -fill both -expand yes\n"
+ " wm withdraw .screen.canvas\n"
+ " wm deiconify .screen.canvas\n"
+ " update\n"
+ "}");
+
+ setup();
+ get_window ( &top, &bot, &left, &right);
+
+ n = D_d_to_u_row(D_get_d_north());
+ s = D_d_to_u_row(D_get_d_south());
+ w = D_d_to_u_col(D_get_d_west());
+ e = D_d_to_u_col(D_get_d_east());
-
- G_debug (2, "n = %f s = %f, w = %f e = %f", D_get_d_north(), D_get_d_south(), D_get_d_west(), D_get_d_east() );
- n = D_d_to_u_row ( D_get_d_north() );
- s = D_d_to_u_row ( D_get_d_south() );
- w = D_d_to_u_col ( D_get_d_west() );
- e = D_d_to_u_col ( D_get_d_east() );
- G_debug (2, "n = %f s = %f, w = %f e = %f", n, s, w, e );
-
Scale = (n - s) / ( D_get_d_south() - D_get_d_north() );
- G_debug (2, "Scale = %f", Scale);
- /*
- Xscale = ( GRegion.east - GRegion.west ) / ( right - left );
- Yscale = ( GRegion.north - GRegion.south ) / ( top - bot );
-
- G_debug (2, "Xscale = %f Yscale = %f", Xscale, Yscale);
- */
- G_setup_plot (D_get_d_north(), D_get_d_south(), D_get_d_west(), D_get_d_east(),
- D_move_abs, D_cont_abs);
-
- D_set_clip_window_to_map_window ();
return 1;
}
int driver_close (void)
{
- G_debug (5, "driver_close()");
- R_close_driver();
- G_debug (5, " -> closed");
return 1;
}
Index: main.c
===================================================================
RCS file: /grassrepository/grass6/vector/v.digit/main.c,v
retrieving revision 1.25
diff -u -r1.25 main.c
--- main.c 19 Aug 2006 12:52:24 -0000 1.25
+++ main.c 22 Feb 2007 04:19:35 -0000
@@ -71,6 +71,20 @@
var_seti ( VAR_SNAP_MODE, SNAP_SCREEN );
var_seti ( VAR_SNAP_SCREEN, 10 );
var_setd ( VAR_SNAP_MAP, 10 );
+
+ /* Display the map */
+ symb_init ();
+ G_get_window(&window);
+ driver_open ();
+ display_erase ();
+ display_bg ();
+ display_map ();
+ driver_close ();
+
+ G_get_window(&window);
+
+ /* Set tool */
+ Tool_next = TOOL_NEW_POINT;
G_debug (3, "Starting toolbox.tcl");
@@ -138,13 +152,6 @@
G_debug (1, "Region: N = %f S = %f E = %f W = %f", GRegion.north,
GRegion.south, GRegion.east, GRegion.west);
- /* Check driver */
- if (R_open_driver() != 0)
- G_fatal_error(_("No graphics device selected"));
- R_close_driver();
-
- G_debug (1, "Driver opened");
-
/* Open map */
mapset = G_find_vector2 (map_opt->answer, G_mapset());
if ( mapset == NULL ) {
@@ -174,20 +181,6 @@
symb_lines_init ();
symb_nodes_init ();
- /* Display the map */
- symb_init ();
- G_get_window(&window);
- driver_open ();
- display_erase ();
- display_bg ();
- display_map ();
- driver_close ();
-
- G_get_window(&window);
-
- /* Set tool */
- Tool_next = TOOL_NEW_POINT;
-
G_debug (3, "Starting Tk_Main.");
/* Open toolbox */
@@ -211,10 +204,7 @@
G_message(_("Region restored to original extent."));
/* clear the screen */
- R_open_driver();
- D_setup(TRUE);
- D_clear_window();
- R_close_driver();
+ Tcl_Eval(Toolbox, ".screen.canvas delete all");
return 1;
}
Index: proto.h
===================================================================
RCS file: /grassrepository/grass6/vector/v.digit/proto.h,v
retrieving revision 1.14
diff -u -r1.14 proto.h
--- proto.h 21 Feb 2007 22:15:41 -0000 1.14
+++ proto.h 22 Feb 2007 04:19:35 -0000
@@ -2,6 +2,9 @@
int driver_open (void);
int driver_close (void);
int driver_refresh (void);
+void driver_rgb_color(int r, int g, int b);
+void driver_line_width(int w);
+void driver_plot_line(double x1, double y1, double x2, double y2);
/* Miscellaneous */
int update (int, int);
@@ -130,3 +133,4 @@
tool_func_update *update,
tool_func_end *end,
void *closure);
+void cancel_tool(void);
Index: symb.c
===================================================================
RCS file: /grassrepository/grass6/vector/v.digit/symb.c,v
retrieving revision 1.6
diff -u -r1.6 symb.c
--- symb.c 11 Feb 2007 20:26:19 -0000 1.6
+++ symb.c 22 Feb 2007 04:19:35 -0000
@@ -110,7 +110,7 @@
{
G_debug ( 2, "set color to symb %d: %d %d %d", code, Symb[code].r, Symb[code].g, Symb[code].b );
- R_RGB_color ( Symb[code].r, Symb[code].g, Symb[code].b);
+ driver_rgb_color ( Symb[code].r, Symb[code].g, Symb[code].b);
}
Index: toolbox.tcl
===================================================================
RCS file: /grassrepository/grass6/vector/v.digit/toolbox.tcl,v
retrieving revision 1.25
diff -u -r1.25 toolbox.tcl
--- toolbox.tcl 9 Oct 2006 01:46:10 -0000 1.25
+++ toolbox.tcl 22 Feb 2007 04:19:35 -0000
@@ -25,6 +25,47 @@
set prompt_right [G_msg "Right mouse button"]
set coor ""
+proc get_w_point {} {
+ global get_done
+ set get_done {}
+ bind .screen.canvas <ButtonPress> { set get_done "%x %y %b" }
+ bind .screen.canvas <Motion> { set get_done "%x %y -1" }
+ tkwait variable get_done
+ return $get_done
+}
+
+proc get_update_line {ox oy x y} {
+ .screen.canvas delete active
+ .screen.canvas create line $ox $oy $x $y -tags active -dash {4 4}
+}
+
+proc get_w_line {ox oy} {
+ global get_done get_x get_y
+ set get_done {}
+ set get_x $ox
+ set get_y $oy
+ bind .screen.canvas <ButtonPress> { set get_done "%x %y %b" }
+ bind .screen.canvas <Motion> [subst { get_update_line $ox $oy %x %y ; set get_done "%x %y -1" }]
+ tkwait variable get_done
+ return $get_done
+}
+
+proc get_update_box {ox oy x y} {
+ .screen.canvas delete active
+ .screen.canvas create line $ox $oy $ox $y $x $y $x $oy $ox $oy -tags active -dash {4 4}
+}
+
+proc get_w_box {ox oy} {
+ global get_done get_x get_y
+ set get_done false
+ set get_x $ox
+ set get_y $oy
+ bind .screen.canvas <ButtonPress> { set get_done "%x %y %b" }
+ bind .screen.canvas <Motion> [subst { get_update_box $ox $oy %x %y ; set get_done "%x %y -1" }]
+ tkwait variable get_done
+ return $get_done
+}
+
# GVariable stores variables by key, this variables are (should be) synchronized with
# variables in Variable array in C (synchronization should be done somehow better). Key is
# 'name' in VAR structure in C. Variables are initialized by var_init() on startup.
Index: util.c
===================================================================
RCS file: /grassrepository/grass6/vector/v.digit/util.c,v
retrieving revision 1.4
diff -u -r1.4 util.c
--- util.c 21 Feb 2007 22:15:41 -0000 1.4
+++ util.c 22 Feb 2007 04:19:35 -0000
@@ -47,22 +47,62 @@
mode = m;
}
+static int cancel;
+
+void cancel_tool(void)
+{
+ cancel = 1;
+}
+
void get_location(int *sxn, int *syn, int *button)
{
- R_set_update_function (update);
+ char buf[1024];
+
+ cancel = 0;
+
+ Tcl_Eval(Toolbox, ".screen.canvas configure -cursor crosshair");
switch (mode)
{
case MOUSE_POINT:
- R_get_location_with_pointer (sxn, syn, button);
+ while (!cancel)
+ {
+ Tcl_Eval(Toolbox, "get_w_point");
+ sscanf(Toolbox->result, "%d %d %d", sxn, syn, button);
+ if (*button >= 0)
+ break;
+ update(*sxn, *syn);
+ }
break;
case MOUSE_LINE:
- R_get_location_with_line (sxo, syo, sxn, syn, button);
+ while (!cancel)
+ {
+ sprintf(buf, "get_w_line %d %d", sxo, syo);
+ Tcl_Eval(Toolbox, buf);
+ sscanf(Toolbox->result, "%d %d %d", sxn, syn, button);
+ if (*button >= 0)
+ break;
+ update(*sxn, *syn);
+ }
break;
case MOUSE_BOX:
- R_get_location_with_box (sxo, syo, sxn, syn, button);
+ while (!cancel)
+ {
+ sprintf(buf, "get_w_box %d %d", sxo, syo);
+ Tcl_Eval(Toolbox, buf);
+ sscanf(Toolbox->result, "%d %d %d", sxn, syn, button);
+ if (*button >= 0)
+ break;
+ update(*sxn, *syn);
+ }
break;
}
+
+ Tcl_Eval(Toolbox, ".screen.canvas configure -cursor {}");
+ Tcl_Eval(Toolbox, ".screen.canvas delete active");
+
+ if (cancel)
+ *button = 0;
}
int do_tool(tool_func_begin *begin, tool_func_update *update, tool_func_end *end, void *closure)
More information about the grass-dev
mailing list