Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2003:
[Freeciv-Dev] spherical map
Home

[Freeciv-Dev] spherical map

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: <freeciv-dev@xxxxxxxxxxx>
Subject: [Freeciv-Dev] spherical map
From: "Kurt Yoder" <kyhome@xxxxxxxxxx>
Date: Sun, 16 Mar 2003 01:44:33 -0500 (EST)
Reply-to: kyhome@xxxxxxxxxx

Hello folks

Is play on a spherical map (globe) still being considered? If so, I have
an idea for how this might be implemented and would appreciate feedback.
Follows:

I'll start by specifying distance from north pole to south pole in game
squares, for example 31 (equator + 15 N, 15 S).

Now I draw a "prime meridian" along a globe 31 squares long; total
circumference is 62 squares.

Radius of sphere is thus 31 / pi, about 9.8676.

Number of degrees between each game square at prime meridian and equator
is 180 / 31, about 5.8065 degrees.

As the latitude of the map squares increases (move towards either pole),
the shortest distance to the globe's north-south axis decreases. This
distance is the radius at that latitude, so we can also infer the
circumference at that latitude, and thus derive the number of map squares
at that latitude.

I have made a perl script to make these calculations, and get these
results for a 31-length prime meridian:

latitude goes from -15 (S) to 15 (N)
lat     circ    # pixs  width p p dev
---     ----    ------  ------- -----
15      3.1402  3       0.9553  4
14      9.3885  9       0.9586  4
13      15.5405 16      1.0296  2
12      21.5329 22      1.0217  2
11      27.3044 27      0.9889  1
10      32.7958 33      1.0062  0
9       37.9506 38      1.0013  0
8       42.7159 43      1.0066  0
7       47.0430 47      0.9991  0
6       50.8873 51      1.0022  0
5       54.2095 54      0.9961  0
4       56.9754 57      1.0004  0
3       59.1566 59      0.9974  0
2       60.7309 61      1.0044  0
1       61.6819 62      1.0052  0
0       62.0000 62      1.0000  0
-1      61.6819 62      1.0052  0
-2      60.7309 61      1.0044  0
-3      59.1566 59      0.9974  0
-4      56.9754 57      1.0004  0
-5      54.2095 54      0.9961  0
-6      50.8873 51      1.0022  0
-7      47.0430 47      0.9991  0
-8      42.7159 43      1.0066  0
-9      37.9506 38      1.0013  0
-10     32.7958 33      1.0062  0
-11     27.3044 27      0.9889  1
-12     21.5329 22      1.0217  2
-13     15.5405 16      1.0296  2
-14     9.3885  9       0.9586  4
-15     3.1402  3       0.9553  4

In this table "lat" is the latitude above or below 0. "circ" is the
circumference at that latitude. "# pixs" is the number of pixels aka map
squares at that latitude. "width p" is the width of each map square;
height is of course 1. "p dev" is the deviation of the map square width
from 1 at that latitude multiplied by 100; higher equals more deviation
and roughly means "would look weirder if rendered on a flat area" (more
distortion at the poles as you can see).

So given this information, I can figure out which map squares border each
other by calculating distances from square to square. In a map composed of
squares, I need to calculate the 8 closest squares: n, ne, e, se, s, sw,
w, nw. E and W are easy, they're the right- and left-bordering squares at
the current latitude. The closest square at the latitude north of the
current latitude will give me the square most directly north of me.

To find this, I will need exact latitude and longitude of the current
square.  For example, I'm on my 62-circumference sphere above at latitude
5 N, 15 W. Exact latitude is 5 N. Exact longitude is 15 * .9961 = 14.9415
W. Now all I need is to look through the squares at 6 N and see which is
closest to me. Although I don't have the method for calculating the
arc-length between two points on a globe based on latitude and longitude
coordinates, I know it can be done. So after I find the shortest
arc-length, I've found the square most directly north of me. This square's
western neighbor will be nw of me; its eastern neighbor will be ne of me.
I can also find the squares se, s, and sw of me by finding the square on
latitude 4N with the shortest arc-length to my square.

So now I have my 9 squares, I can draw them on a flat map sensibly. Of
course, I can't extend the flat version of the globe to show the whole
globe without progressively stretching the squares closer to the poles.
So, I'd probably only display my flat map 10 or 15 squares out. The flat
map can be extended more squares in each direction  without noticeable
distortion if the globe's circumference is increased.

If anyone on this list knows how to determine arc-length between two
points, please let me know. So far I found this link:
http://www.math.niu.edu/~rusin/known-math/96/latlon, but I'm not certain
how to apply it.

Also for anyone interested in my method of generating the table above,
here's the perl script I used. Sorry, it's in-line, I'm not sure if the
freeciv mailing list software would strip an attachment. Here it is:

#!/usr/bin/perl -w
#input initial number of points (map squares) on a globe's prime meridian
#from this information, derive the number of map squares at each latitude
#also calculate total number of map squares on the globe
use strict;
use diagnostics;

my $pi = 3.14159265358979;

my $points_on_meridian = "";
while( $points_on_meridian !~ /^\d+$/ ){
        print( "enter number of equidistant points on prime meridian
(integers only): " );
        $points_on_meridian = <>;
        chomp( $points_on_meridian );
}
print( "entered $points_on_meridian\n" );

my $radius_at_meridian = $points_on_meridian / $pi;
print( "radius at prime meridian: " );
printf( "%1.4f", $radius_at_meridian );
print( "\n" );

my $degrees_between_latitudes = 180 / $points_on_meridian;
printf( "number of degrees between each latitude line: %1.4f\n",
$degrees_between_latitudes );

my $max_latitude = ( $points_on_meridian - 1 ) / 2;
my $min_latitude = $max_latitude * -1;
print( "latitude goes from $min_latitude (S) to $max_latitude (N)\n" );

print( "lat\tcirc\t# pixs\twidth p\tp dev\n" );
print( "---\t----\t------\t-------\t-----\n" );

my $counter = $max_latitude;
my $total_pixels = 0;
while( $counter >= $min_latitude ){
        my $degrees_above_meridian = abs( $counter *
$degrees_between_latitudes );
        my $radians_above_meridian = $degrees_above_meridian * $pi / 180;
        my $latitude_radius =  $radius_at_meridian * ( cos(
$radians_above_meridian ) );
        my $latitude_circumference = $latitude_radius * $pi * 2;
        my $number_of_pixels = int ( $latitude_circumference + .5 );
        my $width_of_pixels = $number_of_pixels / $latitude_circumference;
        my $pixel_deviation = int( abs ( 1 - $width_of_pixels ) * 100 );

        print( "$counter\t" );
        printf( "%1.4f", $latitude_circumference );
        print( "\t$number_of_pixels\t" );
        printf( "%1.4f\t", $width_of_pixels );
        print( "$pixel_deviation\n" );

        print( "$counter\t" );
        printf( "%1.4f", $latitude_circumference );
        print( "\t$number_of_pixels\t" );
        printf( "%1.4f\t", $width_of_pixels );
        print( "$pixel_deviation\n" );

        $total_pixels += $number_of_pixels;
        $counter--;
}

print( "total pixels: $total_pixels\n" );

my $square_side = int( sqrt( $total_pixels ) );
print( "total surface area approximately equivalent to $square_side x
$square_side map\n" );



-- 
Kurt Yoder





[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] spherical map, Kurt Yoder <=