[GRASS5] 100% cpu mouse bug

Glynn Clements glynn at gclements.plus.com
Thu Apr 27 14:02:39 EDT 2006

Radim Blazek wrote:

> > > > Ideally, someone would produce a Tcl/Tk replacement for v.digit, then
> > > > the R_get_location_* stuff can be discarded altogether (no other
> > > > module is important enough to stand in the way of that change).
> > > >
> > > > Unfortunately, I don't think anyone other than Radim understands the
> > > > vector API well enough to perform the necessary enhancements to
> > > > v.{in,out}.ascii (topology support).
> > >
> > > All you need to modify a vector is Vect_write_line(),
> > > Vect_rewrite_line() and Vect_delete_line().
> >
> >
> > Is "v.build option=dump" a good starting point for a format to use
> > to describe any vector's topology?
> What do you want to do exactly?  option=dump is only for debugging.
> You dont need to care about topology, you just write/delete lines
> the topology is create automaticaly.

What I want to do exactly is extract vector maps from GRASS to a
textual format which can be read by e.g. Tcl/Tk programs, modify the
data, write it out in a textual format and import it back into GRASS,
all without loss of information.

v.out.ascii doesn't include the topology information, so if you want
to draw filled polygons, you have to build the topology yourself.

An example might help. I've attached a Tcl/Tk script which displays a
vector map in a Tk canvas. Sample usage (in spearfish):

	wish vect.tcl fields

It uses v.out.pov, because that was the only obvious way to extract a
vector map in a textual format with topology information. However,
v.out.pov doesn't export everything which makes up the map, only
enough to draw it. For a more general export tool, the textual format
needs to contain everything, so that the export/import cycle doesn't
lose anything.

v.out.ascii has all of the information, but not the topology (for a
while, I thought that it was omitting data, until I realised that the
boundary segments didn't define complete polygons).

Whilst I could probably figure out how to modify v.out.pov to behave a
bit more like v.out.ascii (i.e. dump out "raw" data), the main problem
is that, in order to avoid trashing users' data (which I'd really like
to avoid), you need to be sure to include /everything/ in the exported
data. Which essentially requires that you understand what you are
doing, rather than just dumping out whatever data you can find and
hoping that you haven't missed anything.

Glynn Clements <glynn at gclements.plus.com>

-------------- next part --------------
proc randomcolor {} {
	set r [expr int(rand() * 255.999)]
	set g [expr int(rand() * 255.999)]
	set b [expr int(rand() * 255.999)]
	format "#%02x%02x%02x" $r $g $b

proc read_map {fh} {
	set data {}

	while {![eof $fh]} {
		set line [gets $fh]
		if {[regexp -- {^sphere *\{ *< *([0-9.]+) *, *[0-9.]+ *, *([0-9.]+) *> *, *[0-9]+ *$} $line dummy x z]} {
			set line [gets $fh]
			set line [gets $fh]
			lappend data point {} [list $x $z]
		} elseif {[regexp -- {^sphere_sweep *\{ *linear_spline *([0-9]+) *, *$} $line dummy n]} {
			set verts {}
			for {set i 0} {$i < $n} {incr i} {
				set line [gets $fh]
				if {[regexp -- {^ *< *([0-9.]+) *, *[0-9.]+ *, *([0-9.]+) *> *, *[0-9]+ *$} $line dummy x z]} {
					lappend verts $x $z
			set line [gets $fh]
			set line [gets $fh]
			lappend data lines {} $verts
		} elseif {[regexp -- {^polygon *\{ *([0-9]+) *, *$} $line dummy n]} {
			set verts {}
			for {set i 0} {$i < $n} {incr i} {
				set line [gets $fh]
				if {[regexp -- {^ *< *([0-9.]+) *, *[0-9.]+ *, *([0-9.]+) *> *$} $line dummy x z]} {
					lappend verts $x $z
			set line [gets $fh]
			set line [gets $fh]
			lappend data polygon [randomcolor] $verts

	return $data

proc load_vect {name} {
	set tmpfile /tmp/vect.pov
	exec v.out.pov $name out=$tmpfile type=area,centroid,boundary 2>@stderr
	set fh [open $tmpfile r]
	set data [read_map $fh]
	close $fh
	return $data

proc get_bbox {data} {
	global x0 x1 y0 y1

	set x0 inf
	set x1 -inf
	set y0 inf
	set y1 -inf

	foreach {prim color verts} $data {
		foreach {x y} $verts {
			if {$x0 > $x} {set x0 $x}
			if {$x1 < $x} {set x1 $x}
			if {$y0 > $y} {set y0 $y}
			if {$y1 < $y} {set y1 $y}

proc make_map {data} {
	global canvas
	global x0 x1 y0 y1

	set dx [winfo width $canvas]
	set dy [winfo height $canvas]

	set mdx [expr $x1 - $x0]
	set mdy [expr $y1 - $y0]

	set sx [expr $dx / $mdx]
	set sy [expr $dy / $mdy]
	set scale [expr ($sx < $sy) ? $sx : $sy]

	set tx [expr -$x0]
	set ty [expr -$y1]

	set idx 1

	foreach {prim color verts} $data {
		switch $prim {
			point {
				set cx [lindex $verts 0]
				set cy [lindex $verts 1]
				set r [expr 3.0 / $scale]
				set rx0 [expr $cx - $r]
				set ry0 [expr $cy - $r]
				set rx1 [expr $cx + $r]
				set ry1 [expr $cy + $r]
				$canvas create oval $rx0 $ry0 $rx1 $ry1 \
				    -tags [list point $idx] \
				    -fill \#000 \
				    -activefill \#fff
			polygon {
				$canvas create polygon $verts \
				    -tags [list polygon $idx] \
				    -fill $color \
				    -activefill \#fff
			lines {
				$canvas create line $verts \
				    -tags [list lines $idx] \
				    -fill \#000 \
				    -activefill \#fff
		incr idx

	$canvas lower polygon

	$canvas move all $tx $ty
	$canvas scale all 0 0 $scale -$scale

set canvas [canvas .canvas]
pack $canvas -expand 1 -fill both
wm geometry . 640x500

set current {}
$canvas bind polygon <Enter> {set current [$canvas gettags current]}

set entry [entry .entry -textvariable current]
pack $entry -fill x

set data [load_vect [lindex $argv 0]]

get_bbox $data

bind $canvas <Configure> {make_map $data}

More information about the grass-dev mailing list