[GRASS5] R_line_width()

Hi,

I added 'int R_line_width(int width)' to the raster library. This
changes line width for Draw_line().

Huidae Cho

Huidae Cho wrote:

I added 'int R_line_width(int width)' to the raster library. This
changes line width for Draw_line().

The implementation in the PNG driver is massively inefficient (calls
acos() and tan() once per pixel). A more sensible approach would just
draw multiple, parallel single-pixel lines.

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

You're right. The first version was drawing two vertical lines at a
time. But the horizontal width of line (point) was not correct
(linewidth"+1"). Well, who cares about this extra one pixel, but it was
little fat horizontally. If I add one more vertical pixel to avoid this
problem, a line looked even fatter in both x-y direction.

With the PNG driver, if line width is not that big, it seems working at
reasonable speed. However, if you have a good idea, please let me know.

Thank you.
Huidae Cho

On Tue, Aug 09, 2005 at 03:57:11PM +0100, Glynn Clements wrote:

Huidae Cho wrote:

> I added 'int R_line_width(int width)' to the raster library. This
> changes line width for Draw_line().

The implementation in the PNG driver is massively inefficient (calls
acos() and tan() once per pixel). A more sensible approach would just
draw multiple, parallel single-pixel lines.

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

Huidae Cho wrote:

You're right. The first version was drawing two vertical lines at a
time. But the horizontal width of line (point) was not correct
(linewidth"+1"). Well, who cares about this extra one pixel, but it was
little fat horizontally. If I add one more vertical pixel to avoid this
problem, a line looked even fatter in both x-y direction.

With the PNG driver, if line width is not that big, it seems working at
reasonable speed. However, if you have a good idea, please let me know.

The simplest way is to draw parallelograms. If the line is close to
vertical (i.e. |dy|>|dx|) call the original draw_line() linewidth
times, each with different X offset. If it's closer to horizontal, use
a Y offset instead.

E.g.:

int draw_thick_line(int x1, int y1, int x2, int y2)
{
  int k = linewidth/2;
  int i;

  for (i = 0; i < linewidth; i++)
    if (abs(y2-y1) > abs(x2-x1))
      draw_line(x1-k+i, y1, x2-k+i, y2);
    else
      draw_line(x1, y1-k+i, x2, y2-k+i);

  return 0;
}

This will be adequate except when drawing particularly thick lines
with a significant slope (i.e. neither horizontal nor vertical), where
the caps will be noticably wrong. For lines a few pixels thick, it's
unlikely to matter.

A more accurate (but more complex) solution is to use both X and Y
offsets generated by computing the perpendicular line. The problem
here is that you have to initialise the remainder correctly so that
the "steps" align (otherwise you get "holes").

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