Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2003:
[Freeciv-Dev] (PR#3924) Bugfix for map/canvas coordination functions
Home

[Freeciv-Dev] (PR#3924) Bugfix for map/canvas coordination functions

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] (PR#3924) Bugfix for map/canvas coordination functions
From: "a-l@xxxxxxx" <a-l@xxxxxxx>
Date: Thu, 3 Apr 2003 06:48:27 -0800
Reply-to: rt@xxxxxxxxxxxxxx

This patch fixes two bugs:
one in canvas_to_map_pos(), and one in map_to_canvas_pos().
Both are relevant only for non-isometric mode.

If this is not formalized already, I would propose that the
following should be a defined property of the two functions
in question:

That this verification procedure should hold true:
{
  map_to_canvas_pos(&x, &y, tile_x1, tile_y1);

  x += NORMAL_TILE_WIDTH / 2;
  y += NORMAL_TILE_HEIGHT / 2;

  canvas_to_map_pos(&tile_x2, &tile_y2, x, y);

  assert(tile_x1 == tile_x2);
  assert(tile_y1 == tile_y2);
}
For all tiles at all times.

We must add half a tile because of PR#3800, the bounding
draw box thing. Ie nobody should "fix" PR#3800.

It is currently only valid for the tiles that are
within the visible mapview canvas at any given time.

That makes precise map/canvas coordination impossible for, say, a
topology independent selection rectangle that is bigger than mapview.
You could possibly also run into problems when you try to make
efficient pixel-smooth scrolling by establishing a pixel buffer
outside the mapview (or so I imagine).

I don't think any current cvs code trips over these bugs, because none
of it concerns itself with out-of-sight canvas coordinates.


More technical description of the bugfixes for the interested:

Bug 1:  map_to_canvas_pos()

In this situation:

  When the wrapping axis (0, tile_y) is within the visible mapview,
  and not the leftmost column, ie mapview_canvas.map_x0 != 0.

The problem is:

  map_to_canvas_pos() only outputs meaningful canvas coordinates for
  those tiles that are currently within the mapview. All other tiles
  are assigned a canvas X coordinate of -1 * NORMAL_TILE_WIDTH.

However, when axis (0, tile_y) is out of sight, map_to_canvas_pos()
gives meaningful, consistent, canvas coordinates for all tiles,
sometimes negative.

Bug 2:  canvas_to_map_pos()

  The leftmost tile (mapview_canvas.map_x0) is defined by a sum of
  pixels that is twice the size of the sums that define other tiles.

Example of correct behaviour:

Say mapsize x is 80 and tile width is 30 pixels.
(0, y) is the leftmost tile in the visible mapview:

TILE      Valid X canvas
...
(79, y) = [-30, -1]
(0, y)  = [0, 29]
(1, y)  = [30, 59]
...

Before the bugfix, (0, y) was defined by [-29, 29] which is incorrect.


Arnstein

--- cvs-Apr-02/client/mapview_common.c  Thu Apr  3 15:38:37 2003
+++ bugfix-map-canvas/client/mapview_common.c   Thu Apr  3 15:41:04 2003
@@ -214,7 +214,7 @@
                                    + mapview_canvas.tile_width)) {
       *canvas_x = map_x + map.xsize - mapview_canvas.map_x0;
     } else {
-      *canvas_x = -1;
+      *canvas_x = map_x - mapview_canvas.map_x0;
     }
 
     *canvas_y = map_y - mapview_canvas.map_y0;
@@ -235,6 +235,8 @@
 **************************************************************************/
 bool canvas_to_map_pos(int *map_x, int *map_y, int canvas_x, int canvas_y)
 {
+  const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
+
   if (is_isometric) {
     /* The basic operation here is a simple pi/4 rotation; however, we
      * have to first scale because the tiles have different width and
@@ -261,13 +263,13 @@
      *
      * For another example of this math, see canvas_pos_to_city_pos().
      */
-    const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
-
     *map_x = DIVIDE(canvas_x * H + canvas_y * W, W * H);
     *map_y = DIVIDE(canvas_y * W - canvas_x * H, W * H);
   } else {                     /* is_isometric */
-    *map_x = canvas_x / NORMAL_TILE_WIDTH;
-    *map_y = canvas_y / NORMAL_TILE_HEIGHT;
+    *map_x = canvas_x / W;
+    *map_y = canvas_y / H;
+    if (canvas_x < 0 && canvas_x % W)   *map_x -= 1;
+    if (canvas_y < 0 && canvas_y % H)   *map_y -= 1;
   }
 
   *map_x += mapview_canvas.map_x0;

[Prev in Thread] Current Thread [Next in Thread]