1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* PHPCoord. |
4
|
|
|
* |
5
|
|
|
* @author Jonathan Stott |
6
|
|
|
* @author Doug Wright |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace PHPCoord; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Ordnance Survey grid reference |
13
|
|
|
* References are accurate to 1m. |
14
|
|
|
* |
15
|
|
|
* @author Jonathan Stott |
16
|
|
|
* @author Doug Wright |
17
|
|
|
*/ |
18
|
|
|
class OSRef extends TransverseMercator |
19
|
|
|
{ |
20
|
|
|
const GRID_LETTERS = 'VWXYZQRSTULMNOPFGHJKABCDE'; |
21
|
|
|
|
22
|
3 |
|
public function getReferenceEllipsoid() |
23
|
|
|
{ |
24
|
3 |
|
return RefEll::airy1830(); |
25
|
|
|
} |
26
|
|
|
|
27
|
5 |
|
public function getScaleFactor() |
28
|
|
|
{ |
29
|
5 |
|
return 0.9996012717; |
30
|
|
|
} |
31
|
|
|
|
32
|
5 |
|
public function getOriginNorthing() |
33
|
|
|
{ |
34
|
5 |
|
return -100000; |
35
|
|
|
} |
36
|
|
|
|
37
|
5 |
|
public function getOriginEasting() |
38
|
|
|
{ |
39
|
5 |
|
return 400000; |
40
|
|
|
} |
41
|
|
|
|
42
|
5 |
|
public function getOriginLatitude() |
43
|
|
|
{ |
44
|
5 |
|
return 49; |
45
|
|
|
} |
46
|
|
|
|
47
|
5 |
|
public function getOriginLongitude() |
48
|
|
|
{ |
49
|
5 |
|
return -2; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Create a new object representing a OSGB reference. |
54
|
|
|
* |
55
|
|
|
* @param int $x |
56
|
|
|
* @param int $y |
57
|
|
|
* @param int $z |
58
|
|
|
*/ |
59
|
17 |
|
public function __construct($x, $y, $z = 0) |
60
|
|
|
{ |
61
|
17 |
|
parent::__construct($x, $y, $z, RefEll::airy1830()); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Take a string formatted as a six-figure OS grid reference (e.g. |
66
|
|
|
* "TG514131") and return a reference to an OSRef object that represents |
67
|
|
|
* that grid reference. |
68
|
|
|
* |
69
|
|
|
* @param string $ref |
70
|
|
|
* |
71
|
|
|
* @return OSRef |
72
|
|
|
*/ |
73
|
2 |
|
public static function fromSixFigureReference($ref) |
74
|
|
|
{ |
75
|
|
|
|
76
|
|
|
//first (major) letter is the 500km grid sq, origin at -1000000, -500000 |
77
|
2 |
|
$majorEasting = strpos(self::GRID_LETTERS, $ref[0]) % 5 * 500000 - 1000000; |
78
|
2 |
|
$majorNorthing = (floor(strpos(self::GRID_LETTERS, $ref[0]) / 5)) * 500000 - 500000; |
79
|
|
|
|
80
|
|
|
//second (minor) letter is 100km grid sq, origin at 0,0 of this square |
81
|
2 |
|
$minorEasting = strpos(self::GRID_LETTERS, $ref[1]) % 5 * 100000; |
82
|
2 |
|
$minorNorthing = (floor(strpos(self::GRID_LETTERS, $ref[1]) / 5)) * 100000; |
83
|
|
|
|
84
|
2 |
|
$easting = $majorEasting + $minorEasting + (substr($ref, 2, 3) * 100); |
85
|
2 |
|
$northing = $majorNorthing + $minorNorthing + (substr($ref, 5, 3) * 100); |
86
|
|
|
|
87
|
2 |
|
return new self($easting, $northing); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Convert this grid reference into a grid reference string of a |
92
|
|
|
* given length (2, 4, 6, 8 or 10) including the two-character |
93
|
|
|
* designation for the 100km square. e.g. TG514131. |
94
|
|
|
* |
95
|
|
|
* @return string |
96
|
|
|
*/ |
97
|
7 |
|
private function toGridReference($length) |
98
|
|
|
{ |
99
|
7 |
|
$halfLength = $length / 2; |
100
|
|
|
|
101
|
7 |
|
$easting = str_pad($this->x, 6, 0, STR_PAD_LEFT); |
102
|
7 |
|
$northing = str_pad($this->y, 6, 0, STR_PAD_LEFT); |
103
|
|
|
|
104
|
7 |
|
$adjustedX = $this->x + 1000000; |
105
|
7 |
|
$adjustedY = $this->y + 500000; |
106
|
7 |
|
$majorSquaresEast = floor($adjustedX / 500000); |
107
|
7 |
|
$majorSquaresNorth = floor($adjustedY / 500000); |
108
|
7 |
|
$majorLetterIndex = (int) (5 * $majorSquaresNorth + $majorSquaresEast); |
109
|
7 |
|
$majorLetter = substr(self::GRID_LETTERS, $majorLetterIndex, 1); |
110
|
|
|
|
111
|
|
|
//second (minor) letter is 100km grid sq, origin at 0,0 of this square |
112
|
7 |
|
$minorSquaresEast = $easting[0] % 5; |
113
|
7 |
|
$minorSquaresNorth = $northing[0] % 5; |
114
|
7 |
|
$minorLetterIndex = (int) (5 * $minorSquaresNorth + $minorSquaresEast); |
115
|
7 |
|
$minorLetter = substr(self::GRID_LETTERS, $minorLetterIndex, 1); |
116
|
|
|
|
117
|
7 |
|
return $majorLetter.$minorLetter.substr($easting, 1, $halfLength).substr($northing, 1, $halfLength); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Convert this grid reference into a string using a standard two-figure |
122
|
|
|
* grid reference including the two-character designation for the 100km |
123
|
|
|
* square. e.g. TG51 (10km square). |
124
|
|
|
* |
125
|
|
|
* @return string |
126
|
|
|
*/ |
127
|
1 |
|
public function toTwoFigureReference() |
128
|
|
|
{ |
129
|
1 |
|
return $this->toGridReference(2); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Convert this grid reference into a string using a standard four-figure |
134
|
|
|
* grid reference including the two-character designation for the 100km |
135
|
|
|
* square. e.g. TG5113 (1km square). |
136
|
|
|
* |
137
|
|
|
* @return string |
138
|
|
|
*/ |
139
|
1 |
|
public function toFourFigureReference() |
140
|
|
|
{ |
141
|
1 |
|
return $this->toGridReference(4); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Convert this grid reference into a string using a standard six-figure |
146
|
|
|
* grid reference including the two-character designation for the 100km |
147
|
|
|
* square. e.g. TG514131 (100m square). |
148
|
|
|
* |
149
|
|
|
* @return string |
150
|
|
|
*/ |
151
|
3 |
|
public function toSixFigureReference() |
152
|
|
|
{ |
153
|
3 |
|
return $this->toGridReference(6); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Convert this grid reference into a string using a standard eight-figure |
158
|
|
|
* grid reference including the two-character designation for the 100km |
159
|
|
|
* square. e.g. TG51431312 (10m square). |
160
|
|
|
* |
161
|
|
|
* @return string |
162
|
|
|
*/ |
163
|
1 |
|
public function toEightFigureReference() |
164
|
|
|
{ |
165
|
1 |
|
return $this->toGridReference(8); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Convert this grid reference into a string using a standard ten-figure |
170
|
|
|
* grid reference including the two-character designation for the 100km |
171
|
|
|
* square. e.g. TG5143113121 (1m square). |
172
|
|
|
* |
173
|
|
|
* @return string |
174
|
|
|
*/ |
175
|
1 |
|
public function toTenFigureReference() |
176
|
|
|
{ |
177
|
1 |
|
return $this->toGridReference(10); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Convert this grid reference into a latitude and longitude. |
182
|
|
|
* |
183
|
|
|
* @return LatLng |
184
|
|
|
*/ |
185
|
3 |
View Code Duplication |
public function toLatLng() |
|
|
|
|
186
|
|
|
{ |
187
|
3 |
|
$N = $this->y; |
188
|
3 |
|
$E = $this->x; |
189
|
3 |
|
$N0 = $this->getOriginNorthing(); |
190
|
3 |
|
$E0 = $this->getOriginEasting(); |
191
|
3 |
|
$phi0 = $this->getOriginLatitude(); |
192
|
3 |
|
$lambda0 = $this->getOriginLongitude(); |
193
|
|
|
|
194
|
3 |
|
return $this->convertToLatitudeLongitude($N, $E, $N0, $E0, $phi0, $lambda0); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* String version of coordinate. |
199
|
|
|
* |
200
|
|
|
* @return string |
201
|
|
|
*/ |
202
|
5 |
|
public function __toString() |
203
|
|
|
{ |
204
|
5 |
|
return "({$this->x}, {$this->y})"; |
205
|
|
|
} |
206
|
|
|
} |
207
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.