From 0f0b622ef21001f770767f01ecdd42dc85cea270 Mon Sep 17 00:00:00 2001 From: Steve Goddard Date: Tue, 16 Apr 2019 12:43:26 +0100 Subject: [PATCH 1/7] Added support for tetrads to OSRef.php. --- src/OSRef.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/OSRef.php b/src/OSRef.php index 494c820a3..327d8599f 100644 --- a/src/OSRef.php +++ b/src/OSRef.php @@ -19,6 +19,7 @@ class OSRef extends TransverseMercator { private const GRID_LETTERS = 'VWXYZQRSTULMNOPFGHJKABCDE'; + private const GRID_LETTERS_TETRAD = 'AFKQVBGLRWCHMSXDINTYEJPUZ'; /** * @return RefEll @@ -91,7 +92,9 @@ public function __construct($x, $y, $z = 0) */ public static function fromGridReference(string $ref): self { - if (strlen($ref) % 2 !== 0) { + if(strlen($ref) === 5) { + $tetrad = TRUE; + } elseif (strlen($ref) % 2 !== 0) { throw new LengthException('Grid ref must be an even number of characters'); } @@ -103,13 +106,26 @@ public static function fromGridReference(string $ref): self $minorEasting = strpos(self::GRID_LETTERS, $ref[1]) % 5 * 100000; $minorNorthing = (floor(strpos(self::GRID_LETTERS, $ref[1]) / 5)) * 100000; + //tetrad letter is 2km grid sq. THE GRID HAS A DIFFERENT ORIENTATION - starts botom left and runs bottom to top. Includes I but no O. + $tetradEasting = 0; + $tetradNorthing = 0; + if($tetrad) { + $tetradEasting = strpos(self::GRID_LETTERS_TETRAD, $ref[4]) % 5 * 2000; + $tetradNorthing = (floor(strpos(self::GRID_LETTERS_TETRAD, $ref[4]) / 5)) * 2000; + } + //numbers are a division of that square into smaller and smaller pieces - $numericPortion = substr($ref, 2); - $numericPortionSize = strlen($numericPortion) / 2; + if($tetrad) { + $numericPortion = substr($ref, 2, 2); + $numericPortionSize = strlen($numericPortion) / 2; + } else { + $numericPortion = substr($ref, 2); + $numericPortionSize = strlen($numericPortion) / 2; + } $gridSizeInMetres = 1 * (10 ** (5 - $numericPortionSize)); - $easting = $majorEasting + $minorEasting + (substr($numericPortion, 0, $numericPortionSize) * $gridSizeInMetres); - $northing = $majorNorthing + $minorNorthing + (substr($numericPortion, -$numericPortionSize, $numericPortionSize) * $gridSizeInMetres); + $easting = $majorEasting + $minorEasting + $tetradEasting + (substr($numericPortion, 0, $numericPortionSize) * $gridSizeInMetres); + $northing = $majorNorthing + $minorNorthing + $tetradNorthing + (substr($numericPortion, -$numericPortionSize, $numericPortionSize) * $gridSizeInMetres); return new static((int) $easting, (int) $northing); } From e3821444bdb2dead7b90cdc594538e2af786eba1 Mon Sep 17 00:00:00 2001 From: Steve Goddard Date: Tue, 16 Apr 2019 12:53:09 +0100 Subject: [PATCH 2/7] Added test to OSRefTest.php. --- tests/OSRefTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/OSRefTest.php b/tests/OSRefTest.php index 778bd5443..d4e48565f 100644 --- a/tests/OSRefTest.php +++ b/tests/OSRefTest.php @@ -147,6 +147,14 @@ public function testFromSixFigureString2(): void self::assertEquals($expected, $OSRef->__toString()); } + public function testFromTetradString(): void + { + $OSRef = OSRef::fromGridReference('SO24G'); + $expected = '(322000, 242000)'; + + self::assertEquals($expected, $OSRef->__toString()); + } + public function testIssue7(): void { $osRef = new OSRef(322000, 241000); From 6cdd714a3f9bdbadc9f10922b6523d9cc73fa6fc Mon Sep 17 00:00:00 2001 From: Steve Goddard Date: Tue, 16 Apr 2019 13:24:43 +0100 Subject: [PATCH 3/7] Added support for tetrads to OSRef.php. Tweak bug in OSRef.php. --- src/OSRef.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OSRef.php b/src/OSRef.php index 327d8599f..1b8fea733 100644 --- a/src/OSRef.php +++ b/src/OSRef.php @@ -92,6 +92,7 @@ public function __construct($x, $y, $z = 0) */ public static function fromGridReference(string $ref): self { + $tetrad = FALSE; if(strlen($ref) === 5) { $tetrad = TRUE; } elseif (strlen($ref) % 2 !== 0) { From cb4b5a6defdc818851dff325859329a616e491a2 Mon Sep 17 00:00:00 2001 From: Steve Goddard Date: Tue, 7 May 2019 16:59:53 +0100 Subject: [PATCH 4/7] Add support to OSRef to export to tetrad grid reference. --- src/OSRef.php | 55 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/src/OSRef.php b/src/OSRef.php index 1b8fea733..54c3cde7c 100644 --- a/src/OSRef.php +++ b/src/OSRef.php @@ -92,9 +92,9 @@ public function __construct($x, $y, $z = 0) */ public static function fromGridReference(string $ref): self { - $tetrad = FALSE; + $tetrad = false; if(strlen($ref) === 5) { - $tetrad = TRUE; + $tetrad = true; } elseif (strlen($ref) % 2 !== 0) { throw new LengthException('Grid ref must be an even number of characters'); } @@ -107,16 +107,16 @@ public static function fromGridReference(string $ref): self $minorEasting = strpos(self::GRID_LETTERS, $ref[1]) % 5 * 100000; $minorNorthing = (floor(strpos(self::GRID_LETTERS, $ref[1]) / 5)) * 100000; - //tetrad letter is 2km grid sq. THE GRID HAS A DIFFERENT ORIENTATION - starts botom left and runs bottom to top. Includes I but no O. + //tetrad letter is 2km grid sq. THE GRID HAS A DIFFERENT ORIENTATION - starts bottom left and runs bottom to top. Includes I but no O. $tetradEasting = 0; $tetradNorthing = 0; - if($tetrad) { + if ($tetrad) { $tetradEasting = strpos(self::GRID_LETTERS_TETRAD, $ref[4]) % 5 * 2000; $tetradNorthing = (floor(strpos(self::GRID_LETTERS_TETRAD, $ref[4]) / 5)) * 2000; } //numbers are a division of that square into smaller and smaller pieces - if($tetrad) { + if ($tetrad) { $numericPortion = substr($ref, 2, 2); $numericPortionSize = strlen($numericPortion) / 2; } else { @@ -133,7 +133,7 @@ public static function fromGridReference(string $ref): self /** * Convert this grid reference into a grid reference string of a - * given length (2, 4, 6, 8 or 10) including the two-character + * given length (2, 5, 4, 6, 8 or 10) including the two-character * designation for the 100km square. e.g. TG514131. * * @param int $length @@ -142,29 +142,50 @@ public static function fromGridReference(string $ref): self */ public function toGridReference(int $length): string { - if ($length % 2 !== 0) { + $tetrad = false; + if($length === 5) { + $tetrad = true; + } elseif ($length % 2 !== 0) { throw new LengthException('Chosen length must be an even number'); } - $halfLength = $length / 2; + // manually set tetrad half length + if ($tetrad) { + $halfLength = 1; + } else { + $halfLength = $length / 2; + } $easting = str_pad((string) $this->x, 6, '0', STR_PAD_LEFT); $northing = str_pad((string) $this->y, 6, '0', STR_PAD_LEFT); - $adjustedX = $this->x + 1000000; - $adjustedY = $this->y + 500000; - $majorSquaresEast = floor($adjustedX / 500000); - $majorSquaresNorth = floor($adjustedY / 500000); + $adjustedX = $this->x + 1000000; // Takes us to REAL point of origin. + $adjustedY = $this->y + 500000; // Takes us to REAL point of origin. + $majorSquaresEast = floor($adjustedX / 500000); // Divide by 500000 and round down. Base of MAJOR square. + $majorSquaresNorth = floor($adjustedY / 500000); // Divide by 500000 and round down. Base of MAJOR square. $majorLetterIndex = (int) (5 * $majorSquaresNorth + $majorSquaresEast); $majorLetter = substr(self::GRID_LETTERS, $majorLetterIndex, 1); - //second (minor) letter is 100km grid sq, origin at 0,0 of this square - $minorSquaresEast = $easting[0] % 5; - $minorSquaresNorth = $northing[0] % 5; - $minorLetterIndex = (5 * $minorSquaresNorth + $minorSquaresEast); + //second (minor) letter is 100km grid sq, origin at 0,0 of this square - work from the modulus + $majorSquaresEastModulus = $adjustedX % 500000; + $majorSquaresNorthModulus = $adjustedY % 500000; + $minorSquaresEast = floor($majorSquaresEastModulus / 100000); + $minorSquaresNorth = floor($majorSquaresNorthModulus / 100000); + $minorLetterIndex = (int) (5 * $minorSquaresNorth + $minorSquaresEast); $minorLetter = substr(self::GRID_LETTERS, $minorLetterIndex, 1); - return $majorLetter . $minorLetter . substr($easting, 1, $halfLength) . substr($northing, 1, $halfLength); + // tetrad + $tetradLetter = null; + if ($tetrad) { + $minorSquaresEastModulus = $majorSquaresEastModulus % 10000; + $minorSquaresNorthModulus = $majorSquaresNorthModulus % 10000; + $tetradSquaresEast = floor($minorSquaresEastModulus / 2000); + $tetradSquaresNorth = floor($minorSquaresNorthModulus / 2000); + $tetradLetterIndex = (int) (5 * $tetradSquaresNorth + $tetradSquaresEast); + $tetradLetter = substr(self::GRID_LETTERS_TETRAD, $tetradLetterIndex, 1); + } + + return $majorLetter . $minorLetter . substr($easting, 1, $halfLength) . substr($northing, 1, $halfLength) . $tetradLetter; } /** From 5789f39689f956537c3fa478785838fd4bb11cfc Mon Sep 17 00:00:00 2001 From: Steve Goddard Date: Tue, 7 May 2019 17:04:19 +0100 Subject: [PATCH 5/7] Add test for export to tetrad grid reference. --- tests/OSRefTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/OSRefTest.php b/tests/OSRefTest.php index d4e48565f..62025d3e1 100644 --- a/tests/OSRefTest.php +++ b/tests/OSRefTest.php @@ -155,6 +155,15 @@ public function testFromTetradString(): void self::assertEquals($expected, $OSRef->__toString()); } + public function testToTetradString(): void + { + $OSRef = new OSRef(216604, 771209); + + $expected = 'NN17Q'; + + self::assertEquals($expected, $OSRef->toGridReference(5)); + } + public function testIssue7(): void { $osRef = new OSRef(322000, 241000); From db633d274183c7bcc477c663e083e1f61d4d6a35 Mon Sep 17 00:00:00 2001 From: Steve Goddard Date: Tue, 7 May 2019 17:07:36 +0100 Subject: [PATCH 6/7] Add support to OSRef.php to export to tetrad grid reference. Tidy up code. --- src/OSRef.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OSRef.php b/src/OSRef.php index 54c3cde7c..c95bc97b1 100644 --- a/src/OSRef.php +++ b/src/OSRef.php @@ -159,10 +159,10 @@ public function toGridReference(int $length): string $easting = str_pad((string) $this->x, 6, '0', STR_PAD_LEFT); $northing = str_pad((string) $this->y, 6, '0', STR_PAD_LEFT); - $adjustedX = $this->x + 1000000; // Takes us to REAL point of origin. - $adjustedY = $this->y + 500000; // Takes us to REAL point of origin. - $majorSquaresEast = floor($adjustedX / 500000); // Divide by 500000 and round down. Base of MAJOR square. - $majorSquaresNorth = floor($adjustedY / 500000); // Divide by 500000 and round down. Base of MAJOR square. + $adjustedX = $this->x + 1000000; + $adjustedY = $this->y + 500000; + $majorSquaresEast = floor($adjustedX / 500000); + $majorSquaresNorth = floor($adjustedY / 500000); $majorLetterIndex = (int) (5 * $majorSquaresNorth + $majorSquaresEast); $majorLetter = substr(self::GRID_LETTERS, $majorLetterIndex, 1); From dd38048a9bf2116f097b2898bdf92317f104ae3f Mon Sep 17 00:00:00 2001 From: Steve Goddard Date: Thu, 16 May 2019 11:41:59 +0100 Subject: [PATCH 7/7] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ad55823eb..8cb7ac49a 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "php-coord/php-coord", + "name": "stevegoddard/php-coord", "description": "PHPCoord is a set of PHP functions for handling various co-ordinate systems and converting between them", "keywords": ["coord","geo", "wgs84", "osgb36", "latitude", "longitude", "grid ref", "utm", "itm" ,"gps"], "homepage": "https://github.com/dvdoug/PHPCoord",