Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2003:
[Freeciv-Dev] Re: (PR#3936) introducing native coordinates
Home

[Freeciv-Dev] Re: (PR#3936) introducing native coordinates

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] Re: (PR#3936) introducing native coordinates
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 5 Apr 2003 10:18:10 -0800
Reply-to: rt@xxxxxxxxxxxxxx

Gregory Berkolaiko wrote:
> On Fri, 4 Apr 2003, Jason Short wrote:
> 
> 
>>This is a significant design issue, and should be closely scrutinized. 
>>I'd encourage everyone to at least read this patch.
>>
>>Native coordinates (sometimes called "compressed" coordinates in the
>>past) are a concept Ross came up with to make isometric (and other
>>non-standard) maps easier to deal with.  They save around 50% memory
>>(and on disk, in savegames) for map storage over "standard" map
>>coordinates and make topology operations *much* simpler.  Other
>>coordinate systems may share one of these properties, but none have
>>both.  In the process, they invalidate the need for "regular" map positions.
>>
>>The patch introduces native_to_map_pos and map_to_native_pos macros into
>>map.h, along with one very simple user.  I've also written an
> 
> 
> I assume this macros will change drastically when iso-rect is implemented?
> Otherwise, they seem a bit pointless...

Yep.  Eventually they may look something like this:

   void map_to_native_pos(int *nat_x, int *nat_y, int map_x, int map_y)
   {
     if (map_is_isometric()) {
       *nat_y = (map_x + map_y - map.xsize);
       *nat_x = (map_x + map_x - *nat_y - (*nat_y & 1)) / 2;
     } else {
       *nat_x = map_x;
       *nat_y = map_y;
     }
   }

   void native_to_map_pos(int *map_x, int *map_y, int nat_x, int nat_y)
   {
     if (map_is_isometric()) {
       *map_x = (nat_y + (nat_y & 1)) / 2 + nat_x;
       *map_y = nat_y - *map_x + map.xsize;
     } else {
       *map_x = nat_x;
       *map_y = nat_y;
     }
   }

   which can easily be written in macro form.

>>explanation of the coordinate systems for doc/HACKING.  I'd like
>>feedback on this explanation, particularly from people who don't already
>>know what "native coordinates" are.
> 
> 
> Nice explanation (I didn't know you terminology before).
> Suggestions:
> 1. You might mention that "natural" coordinate system is obtained by 
> sparsing the rectangular one.

Hmm.

> 2. Can you give the index notation along with "X" sketches?
> I mean when you compare
> 
>       X X X            X
>        X X X    to    XXX
>       X X X            XXX
>                         XX
> you wonder which X went to which X. But in 
>       0 1 2            0
>        3 4 5          631
>       6 7 8            742
>                         85
> it is more clear (provided I got it right).

OK.

jason

Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.143
diff -u -r1.143 map.h
--- common/map.h        2003/04/04 15:47:49     1.143
+++ common/map.h        2003/04/05 18:16:43
@@ -226,6 +226,12 @@
 #define map_adjust_y(Y) \
   (((Y)<0) ? 0 : (((Y)>=map.ysize) ? map.ysize-1 : (Y)))
 
+#define native_to_map_pos(pmap_x, pmap_y, nat_x, nat_y) \
+  (*(pmap_x) = (nat_x), *(pmap_y) = (nat_y))
+
+#define map_to_native_pos(pnat_x, pnat_y, map_x, map_y) \
+  (*(pnat_x) = (map_x), *(pnat_y) = (map_y))
+
 #define map_pos_to_index(map_x, map_y)        \
   (CHECK_MAP_POS((map_x), (map_y)),           \
    (map_x) + (map_y) * map.xsize)
Index: doc/HACKING
===================================================================
RCS file: /home/freeciv/CVS/freeciv/doc/HACKING,v
retrieving revision 1.9
diff -u -r1.9 HACKING
--- doc/HACKING 2003/02/17 02:11:26     1.9
+++ doc/HACKING 2003/04/05 18:16:44
@@ -408,6 +408,116 @@
 be used.
 
 =========================================================================
+Different coordinate systems
+=========================================================================
+
+In Freeciv, we have the general concept of a "position" or "tile"; this
+is self-explanatory.  However, a tile can be referred to in any of several
+coordinate systems.  The distinction becomes important we start to use
+non-standard types of maps.
+
+- Map (or "standard") coordinates.
+
+  All of the map manipulation examples above are in map coordinates.
+  These preserve the local geometry of square tiles, but do not represent
+  the global map geometry well.  In map coordinates, you are guaranteed
+  (so long as we use square tiles) that the tile adjacency rules
+
+      (map_x-1, map_y-1)    (map_x, map_y-1)   (map_x+1, map_y-1)
+      (map_x-1, map_y)      (map_x, map_y)     (map_x+1, map_y)
+      (map_x-1, map_y+1)    (map_x, map_y+1)   (map_x+1, map_y+1)
+
+  are preserved, regardless of what the underlying map or drawing code
+  looks like.  This is the definition of this system.
+
+  Map coordinates are easiest for local operations (like square_iterate
+  or adjc_iterate) but unwieldy for global operations.
+
+- Native coordinates.
+
+  With an iso-rectangular map, global operations are difficult using map
+  coordinates.  Imagine a simple iso-rectangular map.  Its "natural"
+  representation is
+
+                 X X X        (0,0)   (2,0)   (4,0)
+                  X X X  <=>      (1,1)   (3,1)   (5,1)
+                 X X X        (0,2)   (2,2)   (4,2)
+
+  while its representation in map coordinates would be
+
+                     XX                   (2,0)
+                    XXX  <=>        (1,1) (2,1) (3,1)
+                   XXX        (0,2) (1,2) (2,2)
+                    X               (1,3)
+
+  Neither is particularly good for a global map operation such as
+  whole_map_iterate.  Something better is needed.
+
+  Native coordinates compress the map into a continuous rectangle, the
+  dimensions are defined as map.xsize x map.ysize.  For instance the
+  above iso-rectangular map is represented in native coordinates by
+  compressing the natural representation in the X axis to get the
+  3x3 iso-rectangle of
+
+                    XXX       (0,0) (1,0) (2,0)
+                    XXX  <=>  (0,1) (1,1) (2,1)
+                    XXX       (0,2) (1,2) (3,2)
+
+  The resulting coordinate system is much easier to use than map
+  coordinates in a very limited number of operations.  These include
+  most internal topology operations (e.g., normalize_map_pos,
+  whole_map_iterate) as well as storage (in map.tiles and savegames,
+  for instance).
+
+  In general, native coordinates can be defined based on this property:
+  the basic map becomes a continuous (gap-free) cardinally-oriented
+  rectangle when expressed in native coordinates.
+
+- Index coordinates.
+
+  Index coordinates simply reorder the map into a continous (filled-in)
+  one-dimensional system.  For instance the above iso-rectangular map
+  would look like
+
+        25        0 1 2         012     
+       148   <=>   3 4 5   <=>  345   <=> 012345678
+      037         6 7 8         678
+       6
+
+  in index coordinates.  This coordinate system is closely tied to
+  the ordering of the tiles in native coordinates, and is slightly
+  easier to use for some operations (like storage) because it is
+  one-dimensional.
+
+- Natural coordinates.
+
+  These have been hinted at above, but are not actually used in Freeciv.  But
+  they are very helpful for human understanding of non-standard maps.
+
+  Natural coordinates preserve the geometry of map coordinates, but also have
+  the rectangular property of native coordinates.  They are unweildy for
+  some operations because of their sparseness - they may not have the
+  same scale as map coordinates and, in the iso case, there are gaps in
+  the natural representation of a map.
+
+  For an isometric map, natural coordinates are the same as
+  called "isometric coordinates".
+
+With a standard rectangular map, map and native coordinates are
+equivalent.  When we introduce isometric maps, the distinction becomes
+important, as demonstrated above.  Many places in the code have
+introduced "map_x/map_y" or "nat_x/nat_y" to help distinguish whether
+map or native coordinates are being used.  Other places are not yet
+rigorous in keeping them apart, and will often just name their variables
+"x" and "y".
+
+Note that map.xsize and map.ysize define the dimension of the map in
+_native_ coordinates.
+
+Of course, if a future topology does not fit these rules for coordinate
+systems, they will have to be refined.
+
+=========================================================================
 Unknown tiles and Fog of War
 =========================================================================
 
Index: server/gamelog.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamelog.c,v
retrieving revision 1.27
diff -u -r1.27 gamelog.c
--- server/gamelog.c    2003/04/04 15:47:49     1.27
+++ server/gamelog.c    2003/04/05 18:16:45
@@ -93,16 +93,13 @@
 
 void gamelog_map(void)
 {
-  int x, y;
+  int nat_x, nat_y, map_x, map_y;
   char *hline = fc_calloc(map.xsize+1, sizeof(char));
 
-  for (y = 0; y < map.ysize; y++) {
-    for (x = 0; x < map.xsize; x++) {
-      if (regular_map_pos_is_normal(x, y)) {
-       hline[x] = is_ocean(map_get_terrain(x, y)) ? ' ' : '.';
-      } else {
-       hline[x] = '#';
-      }
+  for (nat_y = 0; nat_y < map.ysize; nat_y++) {
+    for (nat_x = 0; nat_x < map.xsize; nat_x++) {
+      native_to_map_pos(&map_x, &map_y, nat_x, nat_y);
+      hline[nat_x] = is_ocean(map_get_terrain(map_x, map_y)) ? ' ' : '.';
     }
     gamelog(GAMELOG_MAP, "%s", hline);
   }

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