Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load ten figure UK grid refs #19

Closed
imbeingfollowed opened this issue Apr 10, 2019 · 7 comments
Closed

Load ten figure UK grid refs #19

imbeingfollowed opened this issue Apr 10, 2019 · 7 comments

Comments

@imbeingfollowed
Copy link

imbeingfollowed commented Apr 10, 2019

Hi,

I'm looking to convert 10 figure grid references to latitude/longitude pairs. I've used Jonathan's getOSRefFromSixFigureReference() and then $os6x->toLatLng() for many years, but I'm now looking for more accuracy.

I noticed that you have a fromSixFigureReference(), would you consider adding one for Ten?

Best wishes,

James

@stevegoddard
Copy link
Contributor

Just convert the grid ref to eastings/northing first. Then use:

$OSRef = new OSRef(500000, 200000); //Easting, Northing
$LatLng = $OSRef->toLatLng();

The conversion from grid ref to easting/northing is easy enough and you can decide if you want it centred or bottom left corner. I have a function that does this - it's pretty old code but still works ok. Happy to share if it helps.

Steve

@imbeingfollowed
Copy link
Author

Thanks for looking into this for me Steve.

I couldn't find a routine here to convert the 10 figure grid ref into an easting and northing, could you point me in the right direction?

Centering the result does sound good too. Any code you can share at all would be much appreciated.

Cheers,

James

@stevegoddard
Copy link
Contributor

stevegoddard commented Apr 10, 2019

Hi James,
Here you go. I did write this a long time ago - it could probably be simplified a lot. But it's fairly well commented.

Hope it helps. It doesn't do any centering - but that would be easy to add as you have the resolution - so just add half the resolution meters to easting and northing.

Steve

========================================

//Function to convert a gridref to northing and easting.
function gridref_to_ne($var_grid_ref)
{

    //Allowed prefixes.
    $var_allowed_prefixes = ['HP', 'HT', 'HU', 'HW', 'HX', 'HY', 'HZ', 'NA', 'NB', 'NC', 'ND', 'NF', 'NG', 'NH', 'NJ', 'NK', 'NL', 'NM', 'NN', 'NO', 'NR', 'NS', 'NT', 'NU', 'NW', 'NX', 'NY', 'NZ', 'OV', 'SC', 'CD', 'CE', 'SH', 'SJ', 'SK', 'SM', 'SN', 'SO', 'SP', 'SR', 'SS', 'ST', 'SU', 'SV', 'SW', 'SX', 'SY', 'SZ', 'TA', 'TF', 'TG', 'TL', 'TM', 'TQ', 'TR', 'TV'];

    //Validation. Check length, prefix letters, and that at least the next 2 characters are numeric.
    if ((strlen($var_grid_ref) >= 4) && (strlen($var_grid_ref) <= 12) && (in_array(substr($var_grid_ref, 0, 2), $var_allowed_prefixes)) && (is_numeric(substr($var_grid_ref, 2, 2)))) {

        //Clean the string.
        $var_grid_ref = strtoupper(preg_replace("/[^a-zA-Z0-9]/", "", $var_grid_ref));

        //Find the length.
        $var_grid_ref_length = strlen($var_grid_ref);

        //Chop it up.
        $var_grid_ref_prefix_1 = substr($var_grid_ref, 0, 1); //Just the first letter.
        $var_grid_ref_prefix_2 = substr($var_grid_ref, 1, 1); //Just the second letter.
        if ($var_grid_ref_length == 5) {
            //Tetrad.
            $var_grid_ref_numbers = substr($var_grid_ref, 2, 2); //2 numbers after the prefix.
            $var_grid_ref_num_1 = substr($var_grid_ref, 2, 1); //Get the first number.
            $var_grid_ref_num_2 = substr($var_grid_ref, 3, 1); //Get the second number.
            $var_tetrad = strtoupper(substr($var_grid_ref, 4, 1));
        } else {
            //Normal.
            $var_grid_ref_numbers = substr($var_grid_ref, 2, ($var_grid_ref_length - 2)); //All the numbers after the prefix.
            $var_grid_ref_num_1 = substr($var_grid_ref, 2, (($var_grid_ref_length - 2) / 2)); //Get the first N characters.
            $var_grid_ref_num_2 = substr($var_grid_ref, (2 + (($var_grid_ref_length - 2) / 2)), (($var_grid_ref_length - 2) / 2)); //Get the last N characters.
            $var_tetrad = null;
        }

        //Create variables for eastings and northing.
        $var_easting = 0;
        $var_northing = 0;

        //Handle first letters.
        if ($var_grid_ref_prefix_1 == 'S') {
            $var_easting = 0;
            $var_northing = 0;
        } else if ($var_grid_ref_prefix_1 == 'N') {
            $var_easting = 0;
            $var_northing = 500000;
        } else if ($var_grid_ref_prefix_1 == 'H') {
            $var_easting = 0;
            $var_northing = 1000000;
        } else if ($var_grid_ref_prefix_1 == 'T') {
            $var_easting = 500000;
            $var_northing = 0;
        } else if ($var_grid_ref_prefix_1 == 'O') {
            $var_easting = 500000;
            $var_northing = 500000;
        } else {
            //Unrecognised grid ref.
        }

        //Build an array for the second letter - easting.
        $var_array_second_letter_easting_array_4 = ['E', 'K', 'P', 'U', 'Z']; //400000
        $var_array_second_letter_easting_array_3 = ['D', 'J', 'O', 'T', 'Y']; //300000
        $var_array_second_letter_easting_array_2 = ['C', 'H', 'N', 'S', 'X']; //200000
        $var_array_second_letter_easting_array_1 = ['B', 'G', 'M', 'R', 'W']; //100000
        $var_array_second_letter_easting_array_0 = ['A', 'F', 'L', 'Q', 'V']; //0

        //Find the number in the array.
        $var_easting_second = 0;
        if (in_array($var_grid_ref_prefix_2, $var_array_second_letter_easting_array_4)) {
            $var_easting_second = 400000;
        } else if (in_array($var_grid_ref_prefix_2, $var_array_second_letter_easting_array_3)) {
            $var_easting_second = 300000;
        } else if (in_array($var_grid_ref_prefix_2, $var_array_second_letter_easting_array_2)) {
            $var_easting_second = 200000;
        } else if (in_array($var_grid_ref_prefix_2, $var_array_second_letter_easting_array_1)) {
            $var_easting_second = 100000;
        }

        //Build an array for the second letter - northing.
        $var_array_second_letter_northing_array_4 = ['A', 'B', 'C', 'D', 'E']; //400000
        $var_array_second_letter_northing_array_3 = ['F', 'G', 'H', 'J', 'K']; //300000
        $var_array_second_letter_northing_array_2 = ['L', 'M', 'N', 'O', 'P']; //200000
        $var_array_second_letter_northing_array_1 = ['Q', 'R', 'S', 'T', 'U']; //100000
        $var_array_second_letter_northing_array_0 = ['V', 'W', 'X', 'Y', 'Z']; //0

        //Find the number in the array.
        $var_northing_second = 0;
        if (in_array($var_grid_ref_prefix_2, $var_array_second_letter_northing_array_4)) {
            $var_northing_second = 400000;
        } else if (in_array($var_grid_ref_prefix_2, $var_array_second_letter_northing_array_3)) {
            $var_northing_second = 300000;
        } else if (in_array($var_grid_ref_prefix_2, $var_array_second_letter_northing_array_2)) {
            $var_northing_second = 200000;
        } else if (in_array($var_grid_ref_prefix_2, $var_array_second_letter_northing_array_1)) {
            $var_northing_second = 100000;
        }

        //Add them together.
        $var_easting = $var_easting + $var_easting_second;
        $var_northing = $var_northing + $var_northing_second;

        /**************************************************************/

        //Deal with possible tetrad first, then everything else.
        if ($var_grid_ref_length == 5) {
            //Tetrad.
            $var_resolution = '2km';

            $var_grid_ref_num_1 = $var_grid_ref_num_1 * 10000;
            $var_grid_ref_num_2 = $var_grid_ref_num_2 * 10000;

            //Now need to add on extra for tetrad - easting.
            $var_array_tetrad_easting_array_8k = array('V', 'W', 'X', 'Y', 'Z'); //8000
            $var_array_tetrad_easting_array_6k = array('Q', 'R', 'S', 'T', 'U'); //6000
            $var_array_tetrad_easting_array_4k = array('K', 'L', 'M', 'N', 'P'); //4000
            $var_array_tetrad_easting_array_2k = array('F', 'G', 'H', 'I', 'J'); //2000
            $var_array_tetrad_easting_array_0k = array('A', 'B', 'C', 'D', 'E'); //0

            if (in_array($var_tetrad, $var_array_tetrad_easting_array_8k)) {$var_grid_ref_num_1 = $var_grid_ref_num_1 + 8000;} else if (in_array($var_tetrad, $var_array_tetrad_easting_array_6k)) {$var_grid_ref_num_1 = $var_grid_ref_num_1 + 6000;} else if (in_array($var_tetrad, $var_array_tetrad_easting_array_4k)) {$var_grid_ref_num_1 = $var_grid_ref_num_1 + 4000;} else if (in_array($var_tetrad, $var_array_tetrad_easting_array_2k)) {$var_grid_ref_num_1 = $var_grid_ref_num_1 + 2000;} else if (in_array($var_tetrad, $var_array_tetrad_easting_array_0k)) {$var_grid_ref_num_1 = $var_grid_ref_num_1 + 0;}

            //Now need to add on extra for tetrad - northing.
            $var_array_tetrad_northing_array_8k = array('E', 'J', 'P', 'U', 'Z'); //8000
            $var_array_tetrad_northing_array_6k = array('D', 'I', 'N', 'T', 'Y'); //6000
            $var_array_tetrad_northing_array_4k = array('C', 'H', 'M', 'S', 'X'); //4000
            $var_array_tetrad_northing_array_2k = array('B', 'G', 'L', 'R', 'W'); //2000
            $var_array_tetrad_northing_array_0k = array('A', 'F', 'K', 'Q', 'V'); //0
            if (in_array($var_tetrad, $var_array_tetrad_northing_array_8k)) {$var_grid_ref_num_2 = $var_grid_ref_num_2 + 8000;} else if (in_array($var_tetrad, $var_array_tetrad_northing_array_6k)) {$var_grid_ref_num_2 = $var_grid_ref_num_2 + 6000;} else if (in_array($var_tetrad, $var_array_tetrad_northing_array_4k)) {$var_grid_ref_num_2 = $var_grid_ref_num_2 + 4000;} else if (in_array($var_tetrad, $var_array_tetrad_northing_array_2k)) {$var_grid_ref_num_2 = $var_grid_ref_num_2 + 2000;} else if (in_array($var_tetrad, $var_array_tetrad_northing_array_0k)) {$var_grid_ref_num_2 = $var_grid_ref_num_2 + 0;}

        } else if ($var_grid_ref_length == 4) {
            //2 figure grid ref.
            $var_resolution = '10km';
            $var_grid_ref_num_1 = $var_grid_ref_num_1 * 10000;
            $var_grid_ref_num_2 = $var_grid_ref_num_2 * 10000;
        } else if ($var_grid_ref_length == 6) {
            //4 figure grid ref plus letters.
            $var_resolution = '1km';
            $var_grid_ref_num_1 = $var_grid_ref_num_1 * 1000;
            $var_grid_ref_num_2 = $var_grid_ref_num_2 * 1000;
        } else if ($var_grid_ref_length == 8) {
            //6 figure grid ref plus letters.
            $var_resolution = '100m';
            $var_grid_ref_num_1 = $var_grid_ref_num_1 * 100;
            $var_grid_ref_num_2 = $var_grid_ref_num_2 * 100;
        } else if ($var_grid_ref_length == 10) {
            //8 figure grid ref plus letters.
            $var_resolution = '10m';
            $var_grid_ref_num_1 = $var_grid_ref_num_1 * 10;
            $var_grid_ref_num_2 = $var_grid_ref_num_2 * 10;
        } else if ($var_grid_ref_length == 12) {
            $var_resolution = '1m';
            //10 figure grid ref plus letters. No multiplication required.
            $var_grid_ref_num_1 = $var_grid_ref_num_1 * 1;
            $var_grid_ref_num_2 = $var_grid_ref_num_2 * 1;
        } else {
            //Odd length!
            $var_resolution = 'Unknown';
        }

        //Add it all together.
        $var_easting = $var_easting + $var_grid_ref_num_1;
        $var_northing = $var_northing + $var_grid_ref_num_2;

        //Return an array of the easting and northing.
        return [
            'status' => 'success',
            'gridref' => $var_grid_ref,
            'resolution' => $var_resolution,
            'tetrad' => $var_tetrad,
            'easting' => $var_easting,
            'northing' => $var_northing,
        ];

    } else {

        return [
            'status' => 'error',
            'message' => Lang::get('geom.invalid_gridref'),
        ];

    }

}

@imbeingfollowed
Copy link
Author

Cheers Steve.

The first two letter conversions go over my head but I can confirm your code does work well. I hope to study it soon!

Thanks again,
James

@stevegoddard
Copy link
Contributor

Glad it works James. Take a look at the image at the top of this page:

http://www.record-lrc.co.uk/c2.aspx?Mod=Article&ArticleID=GridRefs_Main

Hopefully explains how the letters work!

Steve

@dvdoug dvdoug closed this as completed in 6c7180a Apr 13, 2019
@dvdoug
Copy link
Owner

dvdoug commented Apr 13, 2019

Hi @imbeingfollowed

Thanks for the suggestion, I've now added this and released it as a new version. The master branch had been updated to have a minimum PHP7.1 version since the last release of the library, so I have released this as v3.0.0 as there are a few API-incompatible changes in there due to e.g. use of stricter typing.

If you're using an older PHP version still and need me to backport to the v2 branch, please let me know, it would be pretty easy to do

@imbeingfollowed
Copy link
Author

That's a nice added bonus, Doug - cheers!

You are doing excellent work here.

James

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants