[GRASS-dev] Modules

Glynn Clements glynn at gclements.plus.com
Mon Feb 19 00:02:48 EST 2007


Hamish wrote:

> > > Getting back to your previous "not enough manpower for v.digit"
> > > argument, please note that there is already a nice v.digit
> > > replacement in QGIS 0.8:
> 
> Glynn Clements wrote:
> > So why are we still maintaining v.digit?
> 
> because it doesn't cost us much in development time to maintain

The issue isn't maintaining v.digit, but everything beneath it.

If we keep v.digit (etc), we have to keep R_get_location_with_* and
R_panel_*, which means that we have to keep XDRIVER, and the existing
libdriver and libraster, which in turn ties down the structure of the
PNG driver and direct rendering, which in turn ties down the rest of
d.*.

An example: you have a function to draw a box (filled rectangle):

[lib/pngdriver/pngdriver.h]

	extern void PNG_Box_abs(int,int,int,int);

[lib/pngdriver/Box.c]

	void PNG_Box_abs(int x1, int y1, int x2, int y2)
	{
		...
	}

So, you have a function which draws a box, and its prototype. 
Straightforward enough.

Now, suppose that you need that function within the existing graphics
architecture. Instead of the above, you end up with:

[include/raster.h]

	void R_box_abs(int,int,int,int);

[lib/raster/com_proto.c]

	void R_box_abs(int x1, int y1, int x2, int y2)
	{
		trans->box_abs(x1, y1, x2, y2);
	}

[lib/raster/transport.h]

	extern void LOC_box_abs(int x1, int y1, int x2, int y2);
	
	extern void REM_box_abs(int x1, int y1, int x2, int y2);
	
	struct transport
	{
		...
		void (*box_abs)(int, int, int, int);
		...
	};

[lib/raster/com_io.c]

	struct transport loc_trans =
	{
		...
		LOC_box_abs,
		...
	};
	
	#ifdef HAVE_SOCKET
	
	struct transport rem_trans =
	{
		...
		REM_box_abs,
		...
	};
	
	#endif

[lib/raster/loc_proto.c]

	void LOC_box_abs(int x1, int y1, int x2, int y2)
	{
		COM_Box_abs(x1, y1, x2, y2);
	}

[lib/raster/rem_proto.c]

	void REM_box_abs(int x1, int y1, int x2, int y2)
	{
		_send_ident(BOX_ABS);
		_send_int(&x1);
		_send_int(&y1);
		_send_int(&x2);
		_send_int(&y2);
	}

[include/graphics.h]

	#define BOX_ABS                     48

[lib/driver/command.c]

	    case BOX_ABS:
		REC(&l, sizeof l);
		REC(&t, sizeof t);
		REC(&r, sizeof r);
		REC(&b, sizeof b);
		COM_Box_abs(l, t, r, b);
		break;

[lib/driver/Box.c]

	void COM_Box_abs(int x1, int y1, int x2, int y2)
	{
		int x[4], y[4];
	
		if (driver->Box_abs)
		{
			(*driver->Box_abs)(x1, y1, x2, y2);
			return;
		}
	
		x[0] = x1; y[0] = y1;
		x[1] = x1; y[1] = y2;
		x[2] = x2; y[2] = y2;
		x[3] = x2; y[3] = y1;
	
		COM_Polygon_abs(x, y, 4);
	}

[lib/driver/driver.h]

	struct driver
	{
		void (*Box_abs)(int,int,int,int);
		...
	}

[lib/pngdriver/pngdriver.h]

	extern void PNG_Box_abs(int,int,int,int);

[display/drivers/PNG/main.c]

	int main(int argc, char **argv)
	{
		static struct driver drv;
	
		drv.Box_abs		= PNG_Box_abs;
		...
	}

[lib/pngdriver/Box.c]

	void PNG_Box_abs(int x1, int y1, int x2, int y2)
	{
		...
	}

[display/drivers/XDRIVER/XDRIVER.h]

	extern void XD_Box_abs(int,int,int,int);

[display/drivers/XDRIVER/main.c]

	int main(int argc, char **argv)
	{
		struct driver drv;
	
		drv.Box_abs		= XD_Box_abs;
		...
	}

[display/drivers/XDRIVER/Box.c]

	void XD_Box_abs(int x1, int y1, int x2, int y2)
	{
		...
	}

If you want to add another graphics primitive (or other operation),
you need to add equivalents to all of the above for each one. If you
want to change the prototype (e.g. add another parameter), you have to
change most of the above.

At present, lib/{raster,driver,pngdriver} and display/drivers/*
consist of 135 files, totalling 13066 lines and ~300KB. And between
them, they do very little: rectangle, polyline, polygon, dots, raster,
and text, with the bare minimum of options (it isn't exactly
SVG/OpenGL/PostScript).

And given the "magnification" of effort required to enhance it in any
way, it's likely to stay that way. All of the work I've done recently
has basically been cleaning it up in the hope of making it easier to
migrate away from.

> and it
> gives us a mostly functional solution now.
> 
>  * QGIS would be a very big (too big?) new dependancy,
>  * the two projects have different focus, goals, & target audiences,
>  * at that point the debate could(should) easily morph into why we need
>    our own GUI at all.
> 
> But side stepping those questions, 
> 
> If the v.digit replacement must be some full featured 2D CAD program,
> and we don't want to write our own, then we might as well use QGIS.
> Qcad is functional, but I wouldn't say I enjoy using it. No idea about
> PythonCAD, but it would be interesting to try. If it is simple enough
> maybe we could rip out the core and port it to GRASS.
> 
> If all we need is something simple, I don't think it is too far beyond
> our reach to write a working v.digit replacement, preferably using
> Python + SWIG. Maybe Jachym already has a prototype?? I don't see it
> being /that/ hard of a chore. Especially if we start out with digitizing
> new maps over raster backdrops, but not allow editing of existing data.
> (gui creates v.out.ascii standard format or r.in.poly format)

Right. In spite of my comments about limited manpower, if there's one
thing which is bound to be more primitive than something which we have
to maintain ourselves, it's something which we have to maintain
ourselves *and* which uses lib/raster as its GUI toolkit.

[Incidentally, if v.digit goes, we can also abandon lib/form. 
d.what.vect uses it, but only because its already there; it wouldn't
be worth maintaining it for d.what.vect alone.]

-- 
Glynn Clements <glynn at gclements.plus.com>




More information about the grass-dev mailing list