[GRASS-dev] Zooming issue in gis manager

Before we make these changes, I’d like to reiterate again what is going on with a bit of visual display to better show the issues.

  1. There is not a systematic, major inaccuracy from zooming the display in the GIS Manager.

  2. This inaccuracy reported only occurs with interactive zooming when displaying a raster map so that the raster grid squares are much larger than the pixel size. That is, when you can see only a few grid squares in the display.

  3. It affects the number of grid cells displayed, not the actual computational or display regions.

  4. It is primarily (or likely entirely) a function of using g.region -a to align the display region to the raster grid at the current resolution. I originally did NOT use this flag, because I was concerned about potentially uncontrolled changes to zoom precision, but added this to the zooming a few months back at the request of others.

Please note the screen shots links below to help document this issue. These pretty much reconstruct the original steps to show the problem, but without region alignment.

First, I took out the -a switch from the g.region command in mapcanvas.tcl

Then I interactively zoomed (zoom box) the spearfish erosion map to show 7 rows by 13 columns

This is shown in http://www.public.asu.edu/~cmbarton/files/grass_screenshots/display1.jpg

I then selected “save current region to match display” to make the WIND file match the display region set interactively with the zoom.

I next selected “display region settings” from the menu

This can be seen in http://www.public.asu.edu/~cmbarton/files/grass_screenshots/output.jpg

Next, I switched to query mode and clicked the NW and SE corners of the display

This can also be seen in output.jpg. Note that the xy values match those in the region extents output (within the small error of a mouse click)

Finally, I selected “zoom to current region” to redraw the screen and make the display match the WIND file

This can be seen in http://www.public.asu.edu/~cmbarton/files/grass_screenshots/display2.jpg

Note that display1.jpg and display2.jpg are identical.


The reported problem with displaying grid cells at high magnification is primarily or entirely a function of how g.region -a aligns the region with the raster grid cell boundaries. I don’t know how this works internally and someone with C programming experience will have to deal with it if we want it to work differently

So, what do we want to do? We can either have

  1. All zooming is aligned with the cell borders, matching the current resolution, with the possible result of a bit of rounding error in the display when zoomed in to a point where the cells are very large compared to pixel size–due to the way that g.region -a works.

OR

  1. Zooming is NOT aligned with the cell borders and the current resolution. In this case, what you see is very close to the actual region extents when zoomed in to a point where the cells are very large compared to pixel size. This is how I originally had it.

Note that if you are NOT zoomed in to a point where grid cells look very large compared with pixels (i.e., most the the time in most maps), then the displays appear identical whether the region is aligned to the cell borders or not.

We cannot have it both ways given how g.region -a works. That is, the underlying zoom math is correct and the same in both cases, but can either zoom with g.region -a or with g.region (without the -a flag).

Michael


Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

From: Hamish hamish_nospam@yahoo.com
Date: Tue, 31 Oct 2006 15:13:43 +1300
To: Maciej Sieczka tutey@o2.pl
Cc: mlennert@club.worldonline.be, michael.barton@asu.edu,
grass-dev@grass.itc.it
Subject: Re: [GRASS-dev] d.m/d.gis mysteries…

Maciej Sieczka wrote:

I, personally, would even prefer d.m as the default GUI back,

with a mind to making long term users happy, and making the wxpython
development easier, I’d like to extend the GRASS_GUI variable.

currently it is both a startup shell variable and a GRASS gisenv
variable. (if it exists, the former sets the latter at startup)

currently you can do

GRASS_GUI=text grass63
or
grass63 -text

to start with the command line one

GRASS_GUI=tcltk grass63
or
grass63 -gui
or
grass63 -tcltk

to start with the Tcl/Tk startup + gis.m

with this patch you can also do

grass63 -oldgui # for d.m

or

GRASS_GUI=d.m grass63

or

GRASS_GUI=gis.m grass63

or even

rename it to whatever the wxpython GUI will be called

GRASS_GUI=wxpython grass63

when wx becomes the default just switch “grass63 -gui” to that target.

grass remembers the last one you used and uses that as the default.

WRT, d.zoom & gis.m zooming- the x monitors and d.zoom have had more
than a decade of heavy use to become mature. gis.m has had barely 9
months of developer testing to become mature. And even then, most of the
long-time developers who hold the bulk of the “institutional knowledge”
only work from the command line… it is really great that it has come
so far so fast.

the zooming stuff is tricky business- even after all this time d.zoom
still has some problems and is far from elegant. accurate rendering &
point placement is the bread and butter of a GIS though, so it’d be nice
to have everyone happy with gis.m in the long term. Folks will be
picking points off the screen and writing down coordinates for their
field sites. All the time spent now perfecting the design choices will
pay off well, I am sure. Even if only for when we do the wxPython
version we can pick the best choices the first time.

choices are good,
Hamish


Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

Michael Barton wrote:

The reported problem with displaying grid cells at high magnification is
primarily or entirely a function of how g.region -a aligns the region with
the raster grid cell boundaries. I don't know how this works internally and
someone with C programming experience will have to deal with it if we want
it to work differently

    window.ns_res = x;
    window.ew_res = x;

    if (flag.res_set->answer) {
      window.north = ceil(window.north/x) * x ;
      window.south = floor(window.south/x) * x ;
      window.east = ceil(window.east/x) * x ;
      window.west = floor(window.west/x) * x ;
                }

IOW, it essentially shifts the cell grid such that the origin of the
coordinate system lies on the intersection between four cells.

Given that the origin for most coordinate systems is a completely
arbitrary location arising from various completely arbitrary constants
(e.g. whichever round numbers where chosen as the false easting and
northing), I have no idea what the intended purpose of the -a flag is,
but I'm fairly sure that it shouldn't be used by default.

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

This sounds like there is no good reason to set this for interactive zooming
by default. If someone wants to use this feature, they could explicitly set
it in g.region.

Michael
__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

From: Glynn Clements <glynn@gclements.plus.com>
Date: Wed, 1 Nov 2006 06:38:55 +0000
To: Michael Barton <michael.barton@asu.edu>
Cc: grass-dev <grass-dev@grass.itc.it>
Subject: Re: [GRASS-dev] Zooming issue in gis manager

Michael Barton wrote:

The reported problem with displaying grid cells at high magnification is
primarily or entirely a function of how g.region -a aligns the region with
the raster grid cell boundaries. I don't know how this works internally and
someone with C programming experience will have to deal with it if we want
it to work differently

window.ns_res = x;
window.ew_res = x;

if (flag.res_set->answer) {
window.north = ceil(window.north/x) * x ;
window.south = floor(window.south/x) * x ;
window.east = ceil(window.east/x) * x ;
window.west = floor(window.west/x) * x ;
                }

IOW, it essentially shifts the cell grid such that the origin of the
coordinate system lies on the intersection between four cells.

Given that the origin for most coordinate systems is a completely
arbitrary location arising from various completely arbitrary constants
(e.g. whichever round numbers where chosen as the false easting and
northing), I have no idea what the intended purpose of the -a flag is,
but I'm fairly sure that it shouldn't be used by default.

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

Michael Barton wrote:

This sounds like there is no good reason to set this for interactive zooming
by default. If someone wants to use this feature, they could explicitly set
it in g.region.

Glynn,

gis.m zoom tools should preserve the resolution while zooming, and set
the region extents properly. That's because there are tools in gis.m to
set WIND to match gis.m display, and to make the display match the
current region - thus these two operations should not lead to region or
display settings the user not wanted. The problem is that they do, because:

1. If -a is not used in g.region calls in mapcanvas.tcl (like it was
originally, few months ago), the gis.m zoom tools don't preserve the
resolution while zooming; and I don't see a reason why the resolution
should change while zooming, but do I see obvious reason why it
shouldn't. Thus, I suggested a solution: use the g.region with -a. It
fixed the resolution issue.

2. But, now it showed that if g.region -a is used in mapcanvas.tcl, the
region extent is often not set properly. This is not acceptable either,
is it?

Removing the -a flag should fix issue 2, but it will bring the issue 1
back. What do we do then?

Maciek

To clarify a bit...

In the "standard" mode, resolution and geometry are preserved by the display
in all zooming. In fact, there is no way to change resolution in this mode,
although you can interactively change the size and shape of a display region
by zooming in or out.

In the "explore" mode that Cedric Shock introduced, neither geometry nor
resolution is preserved in the display in order to provide quick,
full-screen views of maps. The display resolution changes to keep it
proportional to the number of pixels and the map always fills the display.

Users can switch back and forth between modes with the click of a button.

In all cases, display resolution and geometry have no effects at all on
computational geometry or region, although settings from the display region
can be copied to the computational region and vice versa if the users wants
to do so.

Michael
__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics and Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

From: Maciej Sieczka <tutey@o2.pl>
Date: Wed, 01 Nov 2006 16:47:05 +0100
To: Glynn Clements <glynn@gclements.plus.com>
Cc: Michael Barton <michael.barton@asu.edu>, grass-dev
<grass-dev@grass.itc.it>
Subject: Re: [GRASS-dev] Zooming issue in gis manager

Michael Barton wrote:

This sounds like there is no good reason to set this for interactive zooming
by default. If someone wants to use this feature, they could explicitly set
it in g.region.

Glynn,

gis.m zoom tools should preserve the resolution while zooming, and set
the region extents properly. That's because there are tools in gis.m to
set WIND to match gis.m display, and to make the display match the
current region - thus these two operations should not lead to region or
display settings the user not wanted. The problem is that they do, because:

1. If -a is not used in g.region calls in mapcanvas.tcl (like it was
originally, few months ago), the gis.m zoom tools don't preserve the
resolution while zooming; and I don't see a reason why the resolution
should change while zooming, but do I see obvious reason why it
shouldn't. Thus, I suggested a solution: use the g.region with -a. It
fixed the resolution issue.

2. But, now it showed that if g.region -a is used in mapcanvas.tcl, the
region extent is often not set properly. This is not acceptable either,
is it?

Removing the -a flag should fix issue 2, but it will bring the issue 1
back. What do we do then?

Maciek

Maciej Sieczka wrote:

> This sounds like there is no good reason to set this for interactive zooming
> by default. If someone wants to use this feature, they could explicitly set
> it in g.region.

gis.m zoom tools should preserve the resolution while zooming, and set
the region extents properly. That's because there are tools in gis.m to
set WIND to match gis.m display, and to make the display match the
current region - thus these two operations should not lead to region or
display settings the user not wanted. The problem is that they do, because:

1. If -a is not used in g.region calls in mapcanvas.tcl (like it was
originally, few months ago), the gis.m zoom tools don't preserve the
resolution while zooming; and I don't see a reason why the resolution
should change while zooming, but do I see obvious reason why it
shouldn't. Thus, I suggested a solution: use the g.region with -a. It
fixed the resolution issue.

While -a will preserve the resolution, it does more than that. It
doesn't just force the size of the region to be an exact multiple of
the resolution, but also forces its position to be an exact multiple
of the resolution.

2. But, now it showed that if g.region -a is used in mapcanvas.tcl, the
region extent is often not set properly. This is not acceptable either,
is it?

Removing the -a flag should fix issue 2, but it will bring the issue 1
back. What do we do then?

I think that the core problem is that d.rast cannot render an
arbitrary portion of a map; the rendered image has to be aligned to
the cell boundaries.

The region always has an integer number of rows and columns. d.rast
always ensures that the entire region just fits inside the frame; one
pair of edges will always exactly touch the corresponding edges of the
region.

Thus, the rendered image will only ever show whole cells. You will
never get a situation where part of a cell is shown and the other part
cropped.

At magnifications significantly above unity, this is likely to be
problematic for interactive zooming. You either have to adjust the
bounds so that they aligh with the existing cell grid, or adjust the
resolution so that the cell grid aligns with the bounds.

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

On 11/2/06, Glynn Clements <glynn@gclements.plus.com> wrote:

I think that the core problem is that d.rast cannot render an
arbitrary portion of a map; the rendered image has to be aligned to
the cell boundaries.

The region always has an integer number of rows and columns. d.rast
always ensures that the entire region just fits inside the frame; one
pair of edges will always exactly touch the corresponding edges of the
region.

Thus, the rendered image will only ever show whole cells. You will
never get a situation where part of a cell is shown and the other part
cropped.

How much difficulty would it be to alter the behaviour of d.rast to
allow partial
cells to be rendered?

If someone were to make the change, can anyone think of what flow on
effects this would have for other components of GRASS? (Not too much
of an issue since a flag could be added to d.rast to have this as
optional behaviour).

--
-Joel

"Wish not to seem, but to be, the best."
                -- Aeschylus

Joel Pitt wrote:

> I think that the core problem is that d.rast cannot render an
> arbitrary portion of a map; the rendered image has to be aligned to
> the cell boundaries.
>
> The region always has an integer number of rows and columns. d.rast
> always ensures that the entire region just fits inside the frame; one
> pair of edges will always exactly touch the corresponding edges of the
> region.
>
> Thus, the rendered image will only ever show whole cells. You will
> never get a situation where part of a cell is shown and the other part
> cropped.

How much difficulty would it be to alter the behaviour of d.rast to
allow partial
cells to be rendered?

If someone were to make the change, can anyone think of what flow on
effects this would have for other components of GRASS? (Not too much
of an issue since a flag could be added to d.rast to have this as
optional behaviour).

It isn't trivial, for reasons of both implementation and design.

d.rast uses various functions from lib/display to do most of the work.
Either these functions would need to be changed, or d.rast would need
to be re-implemented without them.

The main one is D_do_conversions() from lib/display/cnversions.c,
which is used by D_cell_draw_setup[_RGB](). This takes a Cell_head and
a screen rectangle (integer coordinates), and determines the
offset/scale parameters for a set of linear transformations which can
convert between cell array indices, geographic coordinates and screen
coordinates.

These parameters are then used by D_u_to_a_row() etc, which in turn
are used by D_draw_cell().

Probably the most viable solution would be an extended version of
D_do_conversions() which takes two Cell_head structures.

The first would be the current region (which determines the mapping
between geographic coordinates and cell array indices), while the
second would be the region to fit to the screen rectangle (only the
bounds would be used, with the resolution and rows/cols being
ignored).

The existing D_do_conversions() would just call the extended version
with the same Cell_head for both arguments.

There would also need to be extended D_cell_draw_setup[_RGB]
functions, and some means to tell d.rast (and d.rgb, d.his, ...) which
region to draw (you can't use the current region, because the current
region is always subdivided into an exact number of rows and columns,
and changing that certainly isn't viable).

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

Glynn Clements wrote:

Maciej Sieczka wrote:

This sounds like there is no good reason to set this for interactive zooming
by default. If someone wants to use this feature, they could explicitly set
it in g.region.

gis.m zoom tools should preserve the resolution while zooming, and set
the region extents properly. That's because there are tools in gis.m to
set WIND to match gis.m display, and to make the display match the
current region - thus these two operations should not lead to region or
display settings the user not wanted. The problem is that they do, because:

1. If -a is not used in g.region calls in mapcanvas.tcl (like it was
originally, few months ago), the gis.m zoom tools don't preserve the
resolution while zooming; and I don't see a reason why the resolution
should change while zooming, but do I see obvious reason why it
shouldn't. Thus, I suggested a solution: use the g.region with -a. It
fixed the resolution issue.

While -a will preserve the resolution, it does more than that. It
doesn't just force the size of the region to be an exact multiple of
the resolution, but also forces its position to be an exact multiple
of the resolution.

2. But, now it showed that if g.region -a is used in mapcanvas.tcl, the
region extent is often not set properly. This is not acceptable either,
is it?

Removing the -a flag should fix issue 2, but it will bring the issue 1
back. What do we do then?

I think that the core problem is that d.rast cannot render an
arbitrary portion of a map; the rendered image has to be aligned to
the cell boundaries.

Thanks Glynn. Another question - so how does is happen that the X
monitors don't have that problem, while gis.m displays do?

I mean:

1. When I set a region to match, say, 5 cols/6 rows (using g.region)
and d.rast on X monitor - I see 5 cols/6 rows of a raster.

2. And when I use d.zoom and set the display on X monitor so that I
see, say, 3 cols/7 rows, and I do g.region -p - I see that my region
indeed has 3 cols/7 rows, and the resolution has not changed while zooming.

But when gis.m interacts modifies WIND to match it's display, we have,
either, only the resolution, or only the number or rows and cols set
properly, depending on if the g.region is used with or without -a.

The region always has an integer number of rows and columns. d.rast
always ensures that the entire region just fits inside the frame; one
pair of edges will always exactly touch the corresponding edges of the
region.

Thus, the rendered image will only ever show whole cells. You will
never get a situation where part of a cell is shown and the other part
cropped.

But I don't even want it. I'm saying that gis.m interaction with WIND
must not corrupt the resolution or the number of rows and cols. If that
is not possible, then we should not ask people to use gis.m yet. Or
disable the WIND<->gis.m interaction alltogether.

At magnifications significantly above unity, this is likely to be
problematic for interactive zooming. You either have to adjust the
bounds so that they aligh with the existing cell grid, or adjust the
resolution so that the cell grid aligns with the bounds.

So having both bounds and resolution preserved when gis.m interatcs
with WIND is not possible, is that what you mean?

Maciek

Michael Barton wrote:

To clarify a bit...

In the "standard" mode, resolution and geometry are preserved by the display
in all zooming.

Michael,

Not really. The resolution is preserved *only* if -a flag is set in
g.region call in mapcanvas.tcl, lines 1068/1066. If this -a flag is
removed, the res is not preserved when you set WIND to match the gis.m
display (eg. instead of 30 you get 29.56552545). Try to reproduce that,
can you? And do you confirm my observation or not?

As to preserving the region extent - this is achieved only if the -a
flag in question is removed (however, the number of cols on the status
bar below still doesn't match, interestingly).

So we can't currently have both: the resolution and the number of rows
and cols to be preserved when setting WIND to match the gis.m display.
But we need both. Could we have them?

Maciek

I've looked even further and found that as Glynn notes, d.rast also will
align with cells, even if the -a flag is not set in g.region. It also seems
to do so somewhat more accurately than with the -a flag set. That is, it
produces a much better (exact?) match between the display and computational
region in a more predictable way, as you can see in the graphics I showed
last night.

However, if you want to *really* see where the grid cells are at high
magnification, try the explore mode. Because it increases the resolution as
you zoom in (to keep a constant number of cells/pixel) you can set the
display to zoom across original cell boundaries. It also shows a point
overlaying cells in a slightly differently place even than "normal" display
mode with -a not set--by about a quarter of a cell on the display I'm
looking at. With -a set, the difference is more than 1/2 cell in the other
direction.

I can't tell which is "right" for certain. That is, I'm not sure how to tell
mathematically where the cell boundaries ought to lie with respect to their
actual coordinates and where a point should lie within a cell. I'm betting
that explore mode is the most "accurate" in terms of the relationship
between cells and a point. How can we determine what the cell boundaries
ought to be? Since this is a function of the interaction between g.region
and the display driver, do we need to do anything about it (as Joel asks)?
If so, what? Also, I assume that this is only affecting the graphics created
out of d.rast (and d.vect??), and does not affect any overlay operations. So
how should it be prioritized?

Michael

__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics and Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

From: Joel Pitt <joel.pitt@gmail.com>
Reply-To: <joel.pitt@gmail.com>
Date: Thu, 2 Nov 2006 10:08:48 +1300
To: Glynn Clements <glynn@gclements.plus.com>
Cc: Maciej Sieczka <tutey@o2.pl>, Michael Barton <michael.barton@asu.edu>,
grass-dev <grass-dev@grass.itc.it>
Subject: Re: [GRASS-dev] Zooming issue in gis manager

On 11/2/06, Glynn Clements <glynn@gclements.plus.com> wrote:

I think that the core problem is that d.rast cannot render an
arbitrary portion of a map; the rendered image has to be aligned to
the cell boundaries.

The region always has an integer number of rows and columns. d.rast
always ensures that the entire region just fits inside the frame; one
pair of edges will always exactly touch the corresponding edges of the
region.

Thus, the rendered image will only ever show whole cells. You will
never get a situation where part of a cell is shown and the other part
cropped.

How much difficulty would it be to alter the behaviour of d.rast to
allow partial
cells to be rendered?

If someone were to make the change, can anyone think of what flow on
effects this would have for other components of GRASS? (Not too much
of an issue since a flag could be added to d.rast to have this as
optional behaviour).

--
-Joel

"Wish not to seem, but to be, the best."
                -- Aeschylus

Maciej Sieczka wrote:

> I think that the core problem is that d.rast cannot render an
> arbitrary portion of a map; the rendered image has to be aligned to
> the cell boundaries.

Thanks Glynn. Another question - so how does is happen that the X
monitors don't have that problem, while gis.m displays do?

X displays have exactly the same problem. gis.m might have some
*other* problems, but the d.rast/libdisplay issue I was discussing
applies regardless.

I mean:

1. When I set a region to match, say, 5 cols/6 rows (using g.region)
and d.rast on X monitor - I see 5 cols/6 rows of a raster.

2. And when I use d.zoom and set the display on X monitor so that I
see, say, 3 cols/7 rows, and I do g.region -p - I see that my region
indeed has 3 cols/7 rows, and the resolution has not changed while zooming.

But when gis.m interacts modifies WIND to match it's display, we have,
either, only the resolution, or only the number or rows and cols set
properly, depending on if the g.region is used with or without -a.

I would guess that d.zoom adjusts the bounds manually, whereas gis.m
uses "g.region -a". The latter does more than just preserve the
resolution; it also aligns the grid with the coordinate system's
origin, then aligns the bounds with that grid, rounding outwards (i.e.
enlarging the region).

Thus, "panning" (moving the region without changing the e-w or n-s
differences) with "g.region -a" will change the size of the region if
the requested bounds aren't aligned to the grid, as it will round
opposing edges in opposite directions.

> The region always has an integer number of rows and columns. d.rast
> always ensures that the entire region just fits inside the frame; one
> pair of edges will always exactly touch the corresponding edges of the
> region.

> Thus, the rendered image will only ever show whole cells. You will
> never get a situation where part of a cell is shown and the other part
> cropped.

But I don't even want it. I'm saying that gis.m interaction with WIND
must not corrupt the resolution or the number of rows and cols. If that
is not possible, then we should not ask people to use gis.m yet. Or
disable the WIND<->gis.m interaction alltogether.

So, you're complaining about the fact that preserving the resolution
means moving the bounds outwards by up to 1 cell in each direction,
right? Or something else?

If it's the former, gis.m will need to adjust the bounds itself; there
isn't any g.region option which will do the right thing (it's possible
that this was what -a was supposed to do; it would make more sense
than the existing behaviour).

If it's the latter, you'll need to explain more clearly.

> At magnifications significantly above unity, this is likely to be
> problematic for interactive zooming. You either have to adjust the
> bounds so that they aligh with the existing cell grid, or adjust the
> resolution so that the cell grid aligns with the bounds.

So having both bounds and resolution preserved when gis.m interatcs
with WIND is not possible, is that what you mean?

The distance between opposing edges has to be an integer multiple of
the resolution (i.e. the number of rows and columns must be integers).

But that should be true even within gis.m. It's possible that gis.m
fails to enforce this requirement, in which case, it will end up being
enforced whenever gis.m interfaces with the rest of GRASS, either by
adjusting the bounds to fit the resolution or by adjusting the
resolution to fit the bounds.

That isn't limited to updating the WIND file; it will also affect
rendering. If gis.m is reporting region parameters which don't satisfy
the "integer multiple" requirement, it's lying; the numbers will get
"corrected" as soon as they leave gis.m.

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

Glynn,

This may not be the issue, but it does illustrate what you are talking
about. I've shrunk the images quite a bit in the hopes they make it by the
developer list filter.

Both images are close-ups of Spearfish elevation_dem, with a 30m vector grid
drawn over it (origin at 0,20 to make it align with the raster cells).

G.region is run without the -a flag in both examples.

"normal_mode.jpg" shows the map grid cells in the "normal" display mode that
preserves resolution in the display region settings. Note the 30m resolution
at the bottom of the display

"explore_mode.jpg" shows the same part of the map in the "explore" mode that
greatly increases resolution when zoomed in like this. Note the 0.7m
resolution at the bottom of the of the display.

The overlaid vector grid ought to line up with the cells. In explore mode it
does line up, because the 30m "cells" of the original DEM are actually
composed of >1800 cells in this close-up display. D.rast is aligning with
the tiny new cells, not the original 30m cells, and this is not noticeable
because the new cells are so small compared with the display and pixel size.

In normal mode, the grid cells are indeed 30x30m and d.rast does whatever it
does to squeeze an integer number of cells into the display. This is
noticeable because the cells are large relative to the display. The vector
grid does not line up with the cells.

I have no idea how the GIS Manager displays could compensate for d.rast
behavior like this, though it only is a problem when the cell size is very
large compared to pixel size. Ideally, I guess it should always "snap" to
the grid resolution when displaying rasters (vectors seem to be another
matter). But I haven't the foggiest notion of how this could be done with
continuously variable window sizing and zoom box sizing. I'm not even clear
if this is better done when setting the display resolution somehow (but what
happens if you set the display to match the WIND file or a map?), or if this
should be done when coming up with output PPM geometry (but how do you make
it fit a canvas then?). If someone wants to give it a try, more power to
them. Fortunately, the explore mode approach works quite nicely to produce a
display of zoomed in cells that is precisely rendered. If you want to set
the computational region from the display, switch to normal mode first (I
took out the -a switch today, so this is working fine in that the region
gets set to what it appears to be in the display); then switch back to
explore mode to look at it.

Michael
__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

From: Glynn Clements <glynn@gclements.plus.com>
Date: Thu, 2 Nov 2006 01:40:41 +0000
To: Maciej Sieczka <tutey@o2.pl>
Cc: Michael Barton <michael.barton@asu.edu>, grass-dev
<grass-dev@grass.itc.it>
Subject: Re: [GRASS-dev] Zooming issue in gis manager

Maciej Sieczka wrote:

I think that the core problem is that d.rast cannot render an
arbitrary portion of a map; the rendered image has to be aligned to
the cell boundaries.

Thanks Glynn. Another question - so how does is happen that the X
monitors don't have that problem, while gis.m displays do?

X displays have exactly the same problem. gis.m might have some
*other* problems, but the d.rast/libdisplay issue I was discussing
applies regardless.

I mean:

1. When I set a region to match, say, 5 cols/6 rows (using g.region)
and d.rast on X monitor - I see 5 cols/6 rows of a raster.

2. And when I use d.zoom and set the display on X monitor so that I
see, say, 3 cols/7 rows, and I do g.region -p - I see that my region
indeed has 3 cols/7 rows, and the resolution has not changed while zooming.

But when gis.m interacts modifies WIND to match it's display, we have,
either, only the resolution, or only the number or rows and cols set
properly, depending on if the g.region is used with or without -a.

I would guess that d.zoom adjusts the bounds manually, whereas gis.m
uses "g.region -a". The latter does more than just preserve the
resolution; it also aligns the grid with the coordinate system's
origin, then aligns the bounds with that grid, rounding outwards (i.e.
enlarging the region).

Thus, "panning" (moving the region without changing the e-w or n-s
differences) with "g.region -a" will change the size of the region if
the requested bounds aren't aligned to the grid, as it will round
opposing edges in opposite directions.

The region always has an integer number of rows and columns. d.rast
always ensures that the entire region just fits inside the frame; one
pair of edges will always exactly touch the corresponding edges of the
region.

Thus, the rendered image will only ever show whole cells. You will
never get a situation where part of a cell is shown and the other part
cropped.

But I don't even want it. I'm saying that gis.m interaction with WIND
must not corrupt the resolution or the number of rows and cols. If that
is not possible, then we should not ask people to use gis.m yet. Or
disable the WIND<->gis.m interaction alltogether.

So, you're complaining about the fact that preserving the resolution
means moving the bounds outwards by up to 1 cell in each direction,
right? Or something else?

If it's the former, gis.m will need to adjust the bounds itself; there
isn't any g.region option which will do the right thing (it's possible
that this was what -a was supposed to do; it would make more sense
than the existing behaviour).

If it's the latter, you'll need to explain more clearly.

At magnifications significantly above unity, this is likely to be
problematic for interactive zooming. You either have to adjust the
bounds so that they aligh with the existing cell grid, or adjust the
resolution so that the cell grid aligns with the bounds.

So having both bounds and resolution preserved when gis.m interatcs
with WIND is not possible, is that what you mean?

The distance between opposing edges has to be an integer multiple of
the resolution (i.e. the number of rows and columns must be integers).

But that should be true even within gis.m. It's possible that gis.m
fails to enforce this requirement, in which case, it will end up being
enforced whenever gis.m interfaces with the rest of GRASS, either by
adjusting the bounds to fit the resolution or by adjusting the
resolution to fit the bounds.

That isn't limited to updating the WIND file; it will also affect
rendering. If gis.m is reporting region parameters which don't satisfy
the "integer multiple" requirement, it's lying; the numbers will get
"corrected" as soon as they leave gis.m.

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

(attachments)

normal_mode.jpg
explore_mode.jpg

You are correct. If -a is not set in g.region it makes small rounding errors
every time you change the region, even if you do not change the resolution
or even if you try to set it explicitly.

Given this, I guess it's better to avoid the small, but annoying rounding
errors of g.region at common map scales than to keep the aligned region
display appearing to be more accurate in less common close-ups of rasters,
especially given that explore mode can be used to produce a display that
correctly matches a region of a few original grid cells in close-ups.

Michael
__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

From: Maciej Sieczka <tutey@o2.pl>
Date: Wed, 01 Nov 2006 23:09:56 +0100
To: grass-dev <grass-dev@grass.itc.it>
Cc: Michael Barton <michael.barton@asu.edu>
Subject: Re: [GRASS-dev] Zooming issue in gis manager

Michael Barton wrote:

To clarify a bit...

In the "standard" mode, resolution and geometry are preserved by the display
in all zooming.

Michael,

Not really. The resolution is preserved *only* if -a flag is set in
g.region call in mapcanvas.tcl, lines 1068/1066. If this -a flag is
removed, the res is not preserved when you set WIND to match the gis.m
display (eg. instead of 30 you get 29.56552545). Try to reproduce that,
can you? And do you confirm my observation or not?

As to preserving the region extent - this is achieved only if the -a
flag in question is removed (however, the number of cols on the status
bar below still doesn't match, interestingly).

So we can't currently have both: the resolution and the number of rows
and cols to be preserved when setting WIND to match the gis.m display.
But we need both. Could we have them?

Maciek

The original post here didn't make it past the list file size filter. So
I've reduced it to one graphic that should make it. I've also done a few
more tests.

In addition to what I mention below, g.region run without the -a flag
creates rounding errors in resolution--minimal but annoying.

Without the -a flag, the number of cells displayed accurately reflects the
actual display region setting. So if you save the display region to the WIND
file, and reset the display to match the new current region (i.e., WIND
file), it looks the same as before. But, as noted below, it does this by
shrinking the cells a bit to make them squeeze into the PPM output created
by the PNG driver (could the X-driver be doing this differently???).

With the -a flag, the number of rows or columns displayed is one or two less
than the number in the display region. This is not noticeable (and maybe
doesn't even happen) when there are a lot of cells in the display, but can
be noticeable when there are very few cells in the display. The result is
that if you copy the display region to the WIND file and display it back
again, you see more cells than you started with. This is the "correct"
number of rows and columns, but it not what was displayed. However, there
are no rounding errors in the resolution as reported by g.region.

Is this all happening in g.region? The display driver? Or both? As I say
below, I can't think of how gis.m could compensate for this. In the region
computation, it would involve 'rounding' to the nearest resolution value.
But how can you round to the nearest 0.0001543 degrees? ...or even the
nearest 25m? There is no 'starting place' to round from, since the region
boundary can potentially be anywhere theoretically.

I'm going to put the -a flag back into gis.m to keep the resolution rounding
errors out. If you want to set region with precision, especially in a
close-up view with few cells showing in a raster, you need to use g.region.
If you want to display a region in a close-up view of a raster, where the
cell sizes are large compared with the display and pixel size, you'll need
to use explore mode for now at least. As documented below and in the
attached graphic, this does a good job of making a display with accurately
rendered raster cells. Vectors either don't face these issues or have
different ones, as they are not behaving parallel to rasters in this.

Michael
__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

------ Forwarded Message
From: Michael Barton <michael.barton@asu.edu>
Date: Wed, 01 Nov 2006 22:01:24 -0700
To: Glynn Clements <glynn@gclements.plus.com>
Cc: grass-dev <grass-dev@grass.itc.it>
Conversation: [GRASS-dev] Zooming issue in gis manager
Subject: Re: [GRASS-dev] Zooming issue in gis manager

Glynn,

This may not be the issue, but it does illustrate what you are talking
about. I've shrunk the images quite a bit in the hopes they make it by the
developer list filter.

Both images are close-ups of Spearfish elevation_dem, with a 30m vector grid
drawn over it (origin at 0,20 to make it align with the raster cells).

G.region is run without the -a flag in both examples.

"normal_mode.jpg" shows the map grid cells in the "normal" display mode that
preserves resolution in the display region settings. Note the 30m resolution
at the bottom of the display [THIS GRAPHIC IS NO LONGER ATTACHED; YOU JUST
HAVE TO IMAGINE IT]

"explore_mode.jpg" shows the same part of the map in the "explore" mode that
greatly increases resolution when zoomed in like this. Note the 0.7m
resolution at the bottom of the of the display.

The overlaid vector grid ought to line up with the cells. In explore mode it
does line up, because the 30m "cells" of the original DEM are actually
composed of >1800 cells in this close-up display. D.rast is aligning with
the tiny new cells, not the original 30m cells, and this is not noticeable
because the new cells are so small compared with the display and pixel size.

In normal mode, the grid cells are indeed 30x30m and d.rast does whatever it
does to squeeze an integer number of cells into the display. This is
noticeable because the cells are large relative to the display. The vector
grid does not line up with the cells.

I have no idea how the GIS Manager displays could compensate for d.rast
behavior like this, though it only is a problem when the cell size is very
large compared to pixel size. Ideally, I guess it should always "snap" to
the grid resolution when displaying rasters (vectors seem to be another
matter). But I haven't the foggiest notion of how this could be done with
continuously variable window sizing and zoom box sizing. I'm not even clear
if this is better done when setting the display resolution somehow (but what
happens if you set the display to match the WIND file or a map?), or if this
should be done when coming up with output PPM geometry (but how do you make
it fit a canvas then?). If someone wants to give it a try, more power to
them. Fortunately, the explore mode approach works quite nicely to produce a
display of zoomed in cells that is precisely rendered. If you want to set
the computational region from the display, switch to normal mode first (I
took out the -a switch today, so this is working fine in that the region
gets set to what it appears to be in the display); then switch back to
explore mode to look at it.

Michael
__________________________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Center for Social Dynamics & Complexity
Arizona State University

phone: 480-965-6213
fax: 480-965-7671
www: http://www.public.asu.edu/~cmbarton

From: Glynn Clements <glynn@gclements.plus.com>
Date: Thu, 2 Nov 2006 01:40:41 +0000
To: Maciej Sieczka <tutey@o2.pl>
Cc: Michael Barton <michael.barton@asu.edu>, grass-dev
<grass-dev@grass.itc.it>
Subject: Re: [GRASS-dev] Zooming issue in gis manager

Maciej Sieczka wrote:

I think that the core problem is that d.rast cannot render an
arbitrary portion of a map; the rendered image has to be aligned to
the cell boundaries.

Thanks Glynn. Another question - so how does is happen that the X
monitors don't have that problem, while gis.m displays do?

X displays have exactly the same problem. gis.m might have some
*other* problems, but the d.rast/libdisplay issue I was discussing
applies regardless.

I mean:

1. When I set a region to match, say, 5 cols/6 rows (using g.region)
and d.rast on X monitor - I see 5 cols/6 rows of a raster.

2. And when I use d.zoom and set the display on X monitor so that I
see, say, 3 cols/7 rows, and I do g.region -p - I see that my region
indeed has 3 cols/7 rows, and the resolution has not changed while zooming.

But when gis.m interacts modifies WIND to match it's display, we have,
either, only the resolution, or only the number or rows and cols set
properly, depending on if the g.region is used with or without -a.

I would guess that d.zoom adjusts the bounds manually, whereas gis.m
uses "g.region -a". The latter does more than just preserve the
resolution; it also aligns the grid with the coordinate system's
origin, then aligns the bounds with that grid, rounding outwards (i.e.
enlarging the region).

Thus, "panning" (moving the region without changing the e-w or n-s
differences) with "g.region -a" will change the size of the region if
the requested bounds aren't aligned to the grid, as it will round
opposing edges in opposite directions.

The region always has an integer number of rows and columns. d.rast
always ensures that the entire region just fits inside the frame; one
pair of edges will always exactly touch the corresponding edges of the
region.

Thus, the rendered image will only ever show whole cells. You will
never get a situation where part of a cell is shown and the other part
cropped.

But I don't even want it. I'm saying that gis.m interaction with WIND
must not corrupt the resolution or the number of rows and cols. If that
is not possible, then we should not ask people to use gis.m yet. Or
disable the WIND<->gis.m interaction alltogether.

So, you're complaining about the fact that preserving the resolution
means moving the bounds outwards by up to 1 cell in each direction,
right? Or something else?

If it's the former, gis.m will need to adjust the bounds itself; there
isn't any g.region option which will do the right thing (it's possible
that this was what -a was supposed to do; it would make more sense
than the existing behaviour).

If it's the latter, you'll need to explain more clearly.

At magnifications significantly above unity, this is likely to be
problematic for interactive zooming. You either have to adjust the
bounds so that they aligh with the existing cell grid, or adjust the
resolution so that the cell grid aligns with the bounds.

So having both bounds and resolution preserved when gis.m interatcs
with WIND is not possible, is that what you mean?

The distance between opposing edges has to be an integer multiple of
the resolution (i.e. the number of rows and columns must be integers).

But that should be true even within gis.m. It's possible that gis.m
fails to enforce this requirement, in which case, it will end up being
enforced whenever gis.m interfaces with the rest of GRASS, either by
adjusting the bounds to fit the resolution or by adjusting the
resolution to fit the bounds.

That isn't limited to updating the WIND file; it will also affect
rendering. If gis.m is reporting region parameters which don't satisfy
the "integer multiple" requirement, it's lying; the numbers will get
"corrected" as soon as they leave gis.m.

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

------ End of Forwarded Message

(attachments)

explore_mode.jpg

Glynn Clements wrote:

Given that the origin for most coordinate systems is a completely
arbitrary location arising from various completely arbitrary constants
(e.g. whichever round numbers where chosen as the false easting and
northing), I have no idea what the intended purpose of the -a flag is,
but I'm fairly sure that it shouldn't be used by default.

it keeps you from needlessly resampling (degrading) your raster data as
you zoom+pan around & create new maps using the new map bounds?

Hamish

maybe "d.grid size=$res" helps explain what's going on in those
screenshots a bit better. and/or v.mkgrid at the given resolution/origin.

Hamish

Glynn Clements wrote:

At magnifications significantly above unity, this is likely to be
problematic for interactive zooming. You either have to adjust the
bounds so that they aligh with the existing cell grid, or adjust the
resolution so that the cell grid aligns with the bounds.

Surely adjusting the region bounds to match the data is better than
adjusting the data (visually) to fit in the region bounds.

The data is sacrosanct. The region bounds are a temporary whim.

As long as the gui window's x,y cursor output etc keeps up to date with
any adjustments, it doesn't seem very problematic to me to slightly
nudge the zoom box to fit the data's resolution before rendering.

Hamish

Glynn Clements wrote:

> How much difficulty would it be to alter the behaviour of d.rast to
> allow partial
> cells to be rendered?
>
> If someone were to make the change, can anyone think of what flow on
> effects this would have for other components of GRASS? (Not too much
> of an issue since a flag could be added to d.rast to have this as
> optional behaviour).

It isn't trivial, for reasons of both implementation and design.

d.rast uses various functions from lib/display to do most of the work.

Either these functions would need to be changed, or d.rast would need
to be re-implemented without them.

The main one is D_do_conversions() from lib/display/cnversions.c,
which is used by D_cell_draw_setup[_RGB](). This takes a Cell_head and
a screen rectangle (integer coordinates), and determines the
offset/scale parameters for a set of linear transformations which can
convert between cell array indices, geographic coordinates and screen
coordinates.

These parameters are then used by D_u_to_a_row() etc, which in turn
are used by D_draw_cell().

Probably the most viable solution would be an extended version of
D_do_conversions() which takes two Cell_head structures.

The first would be the current region (which determines the mapping
between geographic coordinates and cell array indices), while the
second would be the region to fit to the screen rectangle (only the
bounds would be used, with the resolution and rows/cols being
ignored).

The existing D_do_conversions() would just call the extended version
with the same Cell_head for both arguments.

There would also need to be extended D_cell_draw_setup[_RGB]
functions, and some means to tell d.rast (and d.rgb, d.his, ...) which
region to draw (you can't use the current region, because the current
region is always subdivided into an exact number of rows and columns,
and changing that certainly isn't viable).

.. the resultant module should proabably be called something other
than "d.rast". ("d.raster", "d.rast.fuzzy",...)

Hamish

Michael Barton wrote:

The original post here didn't make it past the list file size filter. So
I've reduced it to one graphic that should make it. I've also done a few
more tests.

In addition to what I mention below, g.region run without the -a flag
creates rounding errors in resolution--minimal but annoying.

Without the -a flag, the number of cells displayed accurately reflects the
actual display region setting. So if you save the display region to the WIND
file, and reset the display to match the new current region (i.e., WIND
file), it looks the same as before. But, as noted below, it does this by
shrinking the cells a bit to make them squeeze into the PPM output created
by the PNG driver (could the X-driver be doing this differently???).

There is no difference between the X and PNG drivers.

However, using direct rendering can potentially produce different
results to using a driver.

Each display frame can have a geographic region associated with it. If
the current frame has a region, this is used in place of the current
region (whether from the WIND file, $WIND_OVERRIDE or $GRASS_REGION).

If you draw something on a monitor, change the current region, then
draw something else without running d.erase, it will use the region
stored on the frame rather than the current region.

This can't happen with direct rendering, as nothing persists between
commands.

With the -a flag, the number of rows or columns displayed is one or two less
than the number in the display region. This is not noticeable (and maybe
doesn't even happen) when there are a lot of cells in the display, but can
be noticeable when there are very few cells in the display. The result is
that if you copy the display region to the WIND file and display it back
again, you see more cells than you started with. This is the "correct"
number of rows and columns, but it not what was displayed. However, there
are no rounding errors in the resolution as reported by g.region.

"g.region -a" expands the region so that the bounds are aligned to a
grid whose spacing is determine by the existing resolution and whose
alignment is such that the origin of the coordinate system falls on a
grid point (an intersection between four cells).

Is this all happening in g.region?

g.region.

The display driver? Or both? As I say
below, I can't think of how gis.m could compensate for this. In the region
computation, it would involve 'rounding' to the nearest resolution value.
But how can you round to the nearest 0.0001543 degrees? ...or even the
nearest 25m? There is no 'starting place' to round from, since the region
boundary can potentially be anywhere theoretically.

First, you have to choose some point which will not change as a result
of the adjustment, e.g. the centre or one of the four corners.

If you pick the south-west corner, then you adjust the north and east
bounds so that the height and width of the region are multiples of the
resolution, i.e.

  width = east - west
  height = north - south

  width = (width / ewres + 0.5) * ewres # round to nearest integer multiple of ewres
  height = (height / nsres + 0.5) * nsres # round to nearest integer multiple of nsres

  east = west + width
  north = south + height

The same applies for any other corner, except that either or both of
the last two lines would be replaced by:

  west = east - width
  south = north - height

To keep the centre fixed, the last two lines would be replaced by:

  cx = (east + west ) / 2
  cy = (north + south) / 2
  east = cx + width / 2
  west = cx - width / 2
  north = cy + height / 2
  south = cy - height / 2

The end result will be similar to using "g.region -a", except that:

1. The grid is anchored at either the centre or a corner of the
region, not the origin of the coordinate system.

2. Each bound is aligned to the nearest grid line, rather than always
rounding outwards.

When panning, you might want to align the region to the previous grid.

If (px, py) is some point which is aligned to the previous grid (e.g.
one corner of a region which was so aligned), then you can align with:

  east = px + ((east - px) / ewres) * ewres
  west = px + ((west - px) / ewres) * ewres
  north = py + ((north - py) / nsres) * nsres
  south = py + ((south - py) / nsres) * nsres

I'm going to put the -a flag back into gis.m to keep the resolution rounding
errors out. If you want to set region with precision, especially in a
close-up view with few cells showing in a raster, you need to use g.region.
If you want to display a region in a close-up view of a raster, where the
cell sizes are large compared with the display and pixel size, you'll need
to use explore mode for now at least. As documented below and in the
attached graphic, this does a good job of making a display with accurately
rendered raster cells. Vectors either don't face these issues or have
different ones, as they are not behaving parallel to rasters in this.

I think the main point is that you need to keep gis.m's internal
regions valid at all times. Whenever a new region is created due to
zooming or panning, it should be adjusted (so that its size is an
integer multiple of the resolution) as soon as it is created, rather
than storing an invalid region and relying upon it being coerced into
compliance when passed to GRASS (G__read_Cell_head_array() calls
G_adjust_Cell_head(), which affects anything which reads a region).

E.g. if the user marks a rectangle on a map, it should ideally be
adjusted as it is being entered, so that WYSIWYG.

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