source: subversion/sites/namefinder/php/region.php @ 4134

Last change on this file since 4134 was 4134, checked in by david, 12 years ago

Main application files

File size: 4.8 KB
Line 
1<?php
2
3/* Helper functions for managing regions.
4
5   Regions are areas of the earth's surface 1 degree of latitude high
6   and 1 degree of longitude wide at the equator (rising to about 7.5
7   degrees at 82 deg north) so that (a) there is an integral number of
8   regions around each band of latitude (360 at the equator) and (b)
9   each is approx 111km wide: rather like map tiles, but the vertical
10   edges don't all line up.
11
12   Each region is indexed by a number which is
13   HIGH*1000+AROUND. AROUND is the index number of the region starting
14   at Greenwich and moving east (so 0 is the first region east of
15   Greenwich and at the quator 359 is te first west of Greenwich. Most
16   importantly the langitudinal neighbours are +/- 1 modulo the number
17   of regions in the band).
18
19   HIGH is the whole number latitude in degrees rounded down to the
20   nearest whole number of degrees away from the equator. Thus 0.3 N
21   1.5 E will be HIGH=0 and AROUND=1 while 1.3 S 1.5 W will be HIGH=-2
22   AROUND=358.
23
24*/
25
26class region {
27
28  var $lat, $lon;
29
30  // --------------------------------------------------
31  /* constructor */ function region($lat, $lon) { $this->lat = $lat; $this->lon = $lon; }
32
33  // --------------------------------------------------
34  function considerregions() {
35    /* for the lat/lon given in this, returns an array of the region
36       number containing this and its immediate neighbours. A
37       neighbour is any region which can be reached by stepping
38       $fraction of a region in the direction of any of the eight
39       primary compass points from the given point. In this way, if
40       you are bang in the centre of a region, you only get hat
41       region, but if you are close to a boundary, you get all the
42       nearby regions. Remember that region boundaries are different
43       at the next latitude up or down, so the east/west edges don't
44       coincide */
45    $fraction = 0.35;
46    $partregionwidth = 360.0 / $this->countregionsatlat() * $fraction;
47    $regionnumbers = array($this->regionnumber());
48    $region = new region($this->lat + $fraction, $this->lon - $partregionwidth);
49    $region->adjustrange();
50    $regionnumbers[] = $region->regionnumber();
51    $region = new region($this->lat + $fraction, $this->lon);
52    $regionnumbers[] = $region->regionnumber();
53    $region = new region($this->lat + $fraction, $this->lon + $partregionwidth);
54    $region->adjustrange();
55    $regionnumbers[] = $region->regionnumber();
56    $region = new region($this->lat, $this->lon - $partregionwidth);
57    $region->adjustrange();
58    $regionnumbers[] = $region->regionnumber();
59    $region = new region($this->lat, $this->lon + $partregionwidth);
60    $region->adjustrange();
61    $regionnumbers[] = $region->regionnumber();
62    $region = new region($this->lat - $fraction, $this->lon - $partregionwidth);
63    $region->adjustrange();
64    $regionnumbers[] = $region->regionnumber();
65    $region = new region($this->lat - $fraction, $this->lon);
66    $regionnumbers[] = $region->regionnumber();
67    $region = new region($this->lat - $fraction, $this->lon + $partregionwidth);
68    $region->adjustrange();
69    $regionnumbers[] = $region->regionnumber();
70    return array_unique($regionnumbers);
71  }
72
73  // --------------------------------------------------
74  /* private */ function adjustrange() {
75    while ($this->lon >= 360.0) { $this->lon -= 360.0; }
76    while ($this->lon < 0.0) { $this->lon += 360.0; }
77  }
78
79  // --------------------------------------------------
80  /* private */ function regionnumber() {
81    return $this->high() * 1000 + $this->around();
82  }
83
84  // --------------------------------------------------
85  /* private */ function high() { return (int) floor($this->lat); }
86
87  // --------------------------------------------------
88  /* private */ function around() { return (int) $this->aroundfloat(); }
89
90  // --------------------------------------------------
91  /* private */ function aroundfloat() {
92    if ($this->lon < 0) { $this->lon = 360 - $this->lon; }
93    return ($this->lon / 360.0) * $this->countregionsatlat();
94  }
95
96  // --------------------------------------------------
97  /* private */ function countregionsatlat() {
98    static $regioncount;
99
100    $high = $this->high();
101    if (isset($regioncount[$high])) { return $regioncount[$high]; }
102
103    static $earth_radius = 6336.0; /* km */
104    static $approx_region_width = 111.0; /* km */
105    $latitudinal_circumference = 2 * M_PI * sin(deg2rad($high+0.5)) * $earth_radius;
106    $regioncount[$high] = (int) round($latitudinal_circumference / $approx_region_width);
107    return $regioncount[$high];
108  }
109
110  // --------------------------------------------------
111  /* private */   function fraction ($number) {
112    $absnumber = abs($number);
113    return $absnumber - floor($absnumber);
114  }
115
116}
117
118?>
Note: See TracBrowser for help on using the repository browser.