[GRASS-dev] [bug #5212] (grass) default color map range does not cover full data

this bug's URL: http://intevation.de/rt/webrt?serial_num=5212
-------------------------------------------------------------------------

Subject: default color map range does not cover full data

Hi,

if you create a map as follows:

g.region n=50 s=0 w=0 e=50 res=1
r.mapcalc colorbug="x()*y()"
d.rast colorbug

you can see the top right cell has no color.

d.what.rast shows that the cell has data, (2450.25 = 49.5^2, center of top-
right cell)

r.colors colorbug rule=rainbow # doesn't fix it (thankfully)

nor do any of the other dynamic color rules (same with color=).

using a fixed-rule color map like rule=terrain is ok.

The bug is not seen with CELL maps:
r.mapcalc colorbug="int(x()*y())"

tweak beyond-color-range check from >= to >, or add GRASS_EPSILON to range_max
before applying rules for FP maps?

Hamish

-------------------------------------------- Managed by Request Tracker

Request Tracker wrote:

this bug's URL: http://intevation.de/rt/webrt?serial_num=5212
-------------------------------------------------------------------------

Subject: default color map range does not cover full data

Hi,

if you create a map as follows:

g.region n=50 s=0 w=0 e=50 res=1
r.mapcalc colorbug="x()*y()"
d.rast colorbug

you can see the top right cell has no color.

Actually, it's white rather than "no colour" (run e.g. "d.erase green"
first).

d.what.rast shows that the cell has data, (2450.25 = 49.5^2, center of top-
right cell)

r.colors colorbug rule=rainbow # doesn't fix it (thankfully)

nor do any of the other dynamic color rules (same with color=).

using a fixed-rule color map like rule=terrain is ok.

The bug is not seen with CELL maps:
r.mapcalc colorbug="int(x()*y())"

tweak beyond-color-range check from >= to >, or add GRASS_EPSILON to range_max
before applying rules for FP maps?

This isn't an issue with colour tables per se, but with the range
calculation. "r.info colorbug" says:

| Range of data: min = 0.250000 max = 2400.750000 |

Likewise, the colour table for the map ends at 2400.75.

If I manually edit the colour table to end at 2450.25, the top-right
cell has the correct colour.

Note that 2400.75 = 48.5 * 49.5.

Changing the region to:

$ g.region n=25 s=0 w=0 e=50 res=1
$ r.mapcalc colorbug="x()*y()"
$ r.info colorbug | fgrep Range
| Range of data: min = 0.250000 max = 1188.250000 |

Note that 1188.25 = 48.5 * 24.5.

So, it's missing the right-most cell on the top row.

Looking at G_row_update_fp_range():

  int G_row_update_fp_range (
      void *rast,int n,
      struct FPRange *range,
      RASTER_MAP_TYPE data_type)
  {
      DCELL val = 0L;
  
      while (n-- > 0)
      {
    switch(data_type)
    {
       case CELL_TYPE: val = (DCELL) *((CELL *) rast); break;
       case FCELL_TYPE: val = (DCELL) *((FCELL *) rast); break;
       case DCELL_TYPE: val = *((DCELL *) rast); break;
          }
  
          if (G_is_null_value(rast, data_type))
    {
             rast = G_incr_void_ptr(rast, G_raster_size(data_type));
       continue;
          }
          if (range->first_time)
          {
             range->first_time = 0;
             range->min = val;
             range->max = val;
             continue;
          }
    if (val < range->min)
        range->min = val;
    if (val > range->max)
        range->max = val;
  
          rast = G_incr_void_ptr(rast, G_raster_size(data_type));
      }
  
      return 0;
  }

For the first cell processed, it sets both min and max to the cell's
value, then executes a "continue", which skips the G_incr_void_ptr()
(but n is still decremented). Thus, it's processing the first cell
twice, and missing the last cell.

Fix:

--- range.c 23 Jul 2006 01:32:16 -0000 2.3
+++ range.c 17 Oct 2006 14:22:09 -0000
@@ -565,12 +565,14 @@
            range->first_time = 0;
            range->min = val;
            range->max = val;
- continue;
         }
- if (val < range->min)
- range->min = val;
- if (val > range->max)
- range->max = val;
+ else
+ {
+ if (val < range->min)
+ range->min = val;
+ if (val > range->max)
+ range->max = val;
+ }

         rast = G_incr_void_ptr(rast, G_raster_size(data_type));
     }

With the above fix, r.info reports the correct range, and the white
pixel is gone.

Committed to CVS.

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

> this bug's URL: http://intevation.de/rt/webrt?serial_num=5212
> -------------------------------------------------------------------
>
> Subject: default color map range does not cover full data

..

This isn't an issue with colour tables per se, but with the range
calculation. "r.info colorbug" says:

..

$ r.info colorbug | fgrep Range
| Range of data: min = 0.250000 max = 2400.750000

[less keystrokes: r.info -r]

Looking at G_row_update_fp_range():

[Glynn fixes it]

I take it this also affected the g3d library & fixes any problems there?
  lib/g3d/g3drange.c

Hamish

Hamish wrote:

> > this bug's URL: http://intevation.de/rt/webrt?serial_num=5212
> > -------------------------------------------------------------------
> >
> > Subject: default color map range does not cover full data
..
> This isn't an issue with colour tables per se, but with the range
> calculation. "r.info colorbug" says:
..
> $ r.info colorbug | fgrep Range
> | Range of data: min = 0.250000 max = 2400.750000

[less keystrokes: r.info -r]

> Looking at G_row_update_fp_range():

[Glynn fixes it]

I take it this also affected the g3d library & fixes any problems there?
  lib/g3d/g3drange.c

Probably. G3d_range_updateFromTile() uses G_row_update_fp_range(),
which is the function which I fixed.

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