Complete.Org: Mailing Lists: Archives: freeciv-dev: December 2001:
[Freeciv-Dev] find_representative_map_pos (PR#1151)
Home

[Freeciv-Dev] find_representative_map_pos (PR#1151)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Cc: bugs@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] find_representative_map_pos (PR#1151)
From: jdorje@xxxxxxxxxxxxxxxxxxxxx
Date: Wed, 19 Dec 2001 22:21:25 -0800 (PST)

The attached patch provides a new topology function, find_representative_map_pos, that wraps a map position to be within a given map "window".

Its immediate use is in map_pos_to_canvas_pos(), where it can provide the topology backend (wrapping) for the conversion from a map position to a canvas position. This allows the topology code to be separated from the GUI code.

Please test and review.

jason
? jason.gz
? old
? topology
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.3
diff -u -r1.3 mapview_common.c
--- client/mapview_common.c     2001/12/13 15:30:30     1.3
+++ client/mapview_common.c     2001/12/20 06:15:27
@@ -93,6 +93,7 @@
                          int map_view_pixel_width,
                          int map_view_pixel_height)
 {
+  struct win_map_context win_mc;
   if (is_isometric) {
     /* For a simpler example of this math, see
        city_pos_to_canvas_pos(). */
@@ -100,20 +101,24 @@
 
     /*
      * First we wrap the coordinates to hopefully be within the the
-     * GUI window.  This isn't perfect; notice that when the mapview
-     * approaches the size of the map some tiles won't be shown at
-     * all.
+     * GUI window.  We leave the actual wrapping up to the
+     * find_representative_map_pos function, but we must give it the
+     * location of the GUI window.
      */
-    map_x %= map.xsize;
-    if (map_x < map_view_topleft_map_x) {
-      map_x += map.xsize;
-    }
+    win_mc.win_is_iso = 1;
+    win_mc.x0 = map_view_topleft_map_x - 1;
+    win_mc.y0 = map_view_topleft_map_y - 1;
+    /* We must round up; plus we get an extra tile on all four sides. */
+    win_mc.width = (map_view_pixel_width - 1) / (NORMAL_TILE_WIDTH/2) + 3;
+    win_mc.height = (map_view_pixel_height - 1) / (NORMAL_TILE_HEIGHT/2) + 3;
 
+    find_representative_map_pos(&map_x, &map_y, &win_mc);
+
     /*
      * Next we convert the flat GUI coordinates to isometric GUI
      * coordinates.  We'll make tile (x0, y0) be the origin, and
      * transform like this:
-     * 
+     *
      *                     3
      * 123                2 6
      * 456 -> becomes -> 1 5 9
@@ -147,31 +152,18 @@
        && (*canvas_y > -NORMAL_TILE_HEIGHT)
        && (*canvas_y < map_view_pixel_height);
   } else {                     /* is_isometric */
-    /* map_view_map_width is the width in tiles/map positions */
-    int map_view_map_width =
-       (map_view_pixel_width + NORMAL_TILE_WIDTH - 1) / NORMAL_TILE_WIDTH;
-
-    if (map_view_topleft_map_x + map_view_map_width <= map.xsize) {
-      *canvas_x = map_x - map_view_topleft_map_x;
-    } else if (map_x >= map_view_topleft_map_x) {
-      *canvas_x = map_x - map_view_topleft_map_x;
-    }
-      else if (map_x <
-              map_adjust_x(map_view_topleft_map_x +
-                           map_view_map_width)) {*canvas_x =
-         map_x + map.xsize - map_view_topleft_map_x;
-    } else {
-      *canvas_x = -1;
-    }
-
-    *canvas_y = map_y - map_view_topleft_map_y;
-
-    *canvas_x *= NORMAL_TILE_WIDTH;
-    *canvas_y *= NORMAL_TILE_HEIGHT;
-
-    return *canvas_x >= 0
-       && *canvas_x < map_view_pixel_width
-       && *canvas_y >= 0 && *canvas_y < map_view_pixel_height;
+    win_mc.win_is_iso = 0;
+    win_mc.x0 = map_view_topleft_map_x;
+    win_mc.y0 = map_view_topleft_map_y;
+    win_mc.width = (map_view_pixel_width - 1) / NORMAL_TILE_WIDTH + 1;
+    win_mc.height = (map_view_pixel_height - 1) / NORMAL_TILE_HEIGHT + 1;
+
+    find_representative_map_pos(&map_x, &map_y, &win_mc);
+
+    *canvas_x = (map_x - map_view_topleft_map_x) * NORMAL_TILE_WIDTH;
+    *canvas_y = (map_y - map_view_topleft_map_y) * NORMAL_TILE_HEIGHT;
+    return *canvas_x >= 0 && *canvas_x < map_view_pixel_width
+        && *canvas_y >= 0 && *canvas_y < map_view_pixel_height;
   }
 }
 
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.103
diff -u -r1.103 map.c
--- common/map.c        2001/12/13 19:13:16     1.103
+++ common/map.c        2001/12/20 06:15:28
@@ -1272,6 +1272,48 @@
   return (0 <= *y && *y < map.ysize);
 }
 
+
+/**************************************************************************
+Wraps (map_x, map_y) to be within the specified "window" if possible.  Note
+this "window" may or may not have anything to do with a GUI window; it's
+just like a fixed area floating over the underlying map.
+
+Note, (map_x, map_y) need not be real to fit under the "window": the
+window may float over unreal positions as well.  However, we will never
+wrap unreal coordinates to try to fit them within the window (any code
+which requires this functionality would most likely be flawed anyway).
+**************************************************************************/
+void find_representative_map_pos(int *map_x, int *map_y,
+                               struct win_map_context *win_mc)
+{
+  /* We absolutely don't wrap unreal coordinates. */
+  if (*map_y < 0 || *map_y >= map.ysize)
+    return;
+               
+  /* The implementation if this function is incredibly tricky,
+     although it doesn't seem like it would be.  The problem is
+     that not only is (*map_x,*map_y) not necessarily normal,
+     but neither is (win_mc->x0,win_mc->y0).  In this
+     implementation I assume that (win_mc->x0,win_mc->y0) is at
+     least _close_ to normal...which is the case right now.  Once
+     we allow wrapping in multiple directions, nothing outside
+     of linear algebra methods will be reasonable. */
+#define WRAP(x, size) ((x) % (size) >= 0 ?   \
+                      (x) % (size) :        \
+                      (x) % (size) + (size))
+       
+  if (win_mc->win_is_iso) {
+    /* This wrapping isn't complete, but it'll do for now. */
+    *map_x = WRAP(*map_x, map.xsize);
+    if (*map_x < win_mc->x0)
+      (*map_x) += map.xsize;
+  } else {
+    (*map_x) -= win_mc->x0;
+    *map_x = WRAP(*map_x, map.xsize);
+    (*map_x) += win_mc->x0;
+  }
+}
+
 /**************************************************************************
 Twiddle *x and *y to point the the nearest real tile, and ensure that the
 position is normalized.
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.108
diff -u -r1.108 map.h
--- common/map.h        2001/12/13 19:13:16     1.108
+++ common/map.h        2001/12/20 06:15:29
@@ -295,6 +295,13 @@
    (y) == map.ysize-1 || (x) == map.xsize-1)
 
 int normalize_map_pos(int *x, int *y);
+struct win_map_context {
+       int x0, y0;
+       int width, height;
+       int win_is_iso;
+};
+void find_representative_map_pos(int *map_x, int *map_y,
+                               struct win_map_context *win_mc);
 void nearest_real_pos(int *x, int *y);
 void map_distance_vector(int *dx, int *dy, int x0, int y0, int x1, int y1);
 int map_num_tiles(void);

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