diff --git a/OSRef.php b/OSRef.php index b34ba3379..e4c6d56e0 100644 --- a/OSRef.php +++ b/OSRef.php @@ -38,11 +38,6 @@ class OSRef { * object from the six-figure grid reference TG514131, the easting would * be 651400 and the northing would be 313100. * - * Grid references with accuracy greater than 1m can be represented - * using floating point values for the easting and northing. For example, - * a value representing an easting or northing accurate to 1mm would be - * given as 651400.0001. - * * @param int $aEasting the easting of the reference (with 1m accuracy) * @param int $aNorthing the northing of the reference (with 1m accuracy) */ @@ -67,41 +62,36 @@ public function __toString() { * @return string */ public function toSixFigureString() { - $hundredkmE = floor($this->easting / 100000); - $hundredkmN = floor($this->northing / 100000); - $firstLetter = ""; - if ($hundredkmN < 5) { - if ($hundredkmE < 5) { - $firstLetter = "S"; - } - else { - $firstLetter = "T"; - } + + $easting = str_pad($this->easting, 6, 0, STR_PAD_LEFT); + $northing = str_pad($this->northing, 6, 0, STR_PAD_LEFT); + + $hundredkmE = $easting[0]; + $hundredkmN = $northing[0]; + + if ($hundredkmN < 5 && $hundredkmE < 5) { + $firstLetter = 'S'; } - else if ($hundredkmN < 10) { - if ($hundredkmE < 5) { - $firstLetter = "N"; - } - else { - $firstLetter = "O"; - } + else if ($hundredkmN < 5 && $hundredkmE >= 5) { + $firstLetter = 'T'; + } + else if ($hundredkmN < 10 && $hundredkmE < 5) { + $firstLetter = 'N'; + } + else if ($hundredkmN < 10 && $hundredkmE >= 5) { + $firstLetter = 'O'; } else { - $firstLetter = "H"; + $firstLetter = 'H'; } - $secondLetter = ""; $index = 65 + ((4 - ($hundredkmN % 5)) * 5) + ($hundredkmE % 5); - $ti = $index; - if ($index >= 73) { + if ($index >= 73) { //skip the letter I $index++; } $secondLetter = chr($index); - $e = round(($this->easting - (100000 * $hundredkmE)) / 100); - $n = round(($this->northing - (100000 * $hundredkmN)) / 100); - - return sprintf("%s%s%03d%03d", $firstLetter, $secondLetter, $e, $n); + return $firstLetter . $secondLetter . substr($easting, 1, 3) . substr($northing, 1, 3); } diff --git a/README.md b/README.md index 57ceebb80..140b6d576 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,9 @@ Output of calculations have been changed from the original code in the following * Eastings and northings are rounded to 1m, and lat/long to 5dp (approx 1m) to avoid any misconceptions that precision is the same thing as accuracy * When calculating surface distances, a more accurate mean radius is now used rather than - that derived from historical definitions of a nautical mile + that derived from historical definitions of a nautical mile + * Corrected calculation of OS 6-figure grid references (rounding instead of truncating meant the + grid square was sometimes off by 1) Usage ----- diff --git a/tests/OSRefTest.php b/tests/OSRefTest.php index ba65ff1e7..12ccaac03 100644 --- a/tests/OSRefTest.php +++ b/tests/OSRefTest.php @@ -38,11 +38,20 @@ public function testLatLngOSWorkedExample() { } public function testToSixFigureString() { - - $OSRef = new OSRef(530140, 184184); - - $expected = 'TQ301842'; - + + $OSRef = new OSRef(530140, 184184); + + $expected = 'TQ301841'; + + self::assertEquals($expected, $OSRef->toSixFigureString()); + } + + public function testToSixFigureString2() { + + $OSRef = new OSRef(439145, 274187); + + $expected = 'SP391741'; + self::assertEquals($expected, $OSRef->toSixFigureString()); }