Skip to first unread message

Apr 5, 2016, 1:25:48 PM4/5/16

to MIT App Inventor Forum

My original post has disappeared so here goes...

Does anyone know how to convert the lat/long returned by the location sensor into OSGB British National Grid format (10 figure grid with two letter prefix). I imagine that there's a complex set of maths blocks beyond my skill.

Thanks

Apr 5, 2016, 1:32:30 PM4/5/16

to MIT App Inventor Forum

you asked the same question 2 days ago here https://groups.google.com/d/msg/mitappinventortest/w528fgeHQ-U/w47R8Uc2EgAJ

did Scott's answer not help?

A very good way to learn App Inventor is to read the free Inventor's Manual here in the AI2 free online eBook http://www.appinventor.org/book2 ... the links are at the bottom of the Web page. The book 'teaches' users how to program with AI2 blocks.

There is a free programming course here http://www.appinventor.org/content/CourseInABox/Intro and the aia files for the projects in the book are here: http://www.appinventor.org/bookFiles

How to do a lot of basic things with App Inventor are described here: http://www.appinventor.org/content/howDoYou/eventHandling .

Also do the tutorials http://appinventor.mit.edu/explore/ai2/tutorials.html to learn the basics of App Inventor, then try something and follow the

Top 5 Tips: How to learn App Inventor

You will not find a tutorial, which does exactly what you are looking for. But **doing the tutorials** (not only reading a little bit) **help you to understand, how things are working.** This is important and this is **the first step** to do.

Taifun

Trying to push the limits of App Inventor! **Snippets** and **Tutorials** from Pura Vida Apps by Taifun.

Apr 5, 2016, 1:42:15 PM4/5/16

to MIT App Inventor Forum

Thanks for the reply and the links. Yes, posted 2 days ago. It didn't appear on my list on the forum assumed it had been deleted as i accidentally replied to Scott's personal email rather than the forum.

No, Scott's post didn't help, although it was interesting. The code was in a different programming language, C if I recall, a little beyond my comprehension.

I have the book you mention here in front of me. Am half way through, just completed Xylophone so am familiar with the basics. What i cannot get my head around is my question of conversion from lat/long to OSGB. I though someone far more proficient than me may be able to save me days of heartache trying to work it out for myself. If needs be I will work it out but, if someone has already considered it...

Apr 5, 2016, 2:30:01 PM4/5/16

to mitappinv...@googlegroups.com

The code was in a different programming language, C if I recall, a little beyond my comprehension.

it seems to be, you have to do the work and translate that into App Inventor

you might want to provide your conversion to the community then

Taifun

Apr 6, 2016, 2:04:14 PM4/6/16

to MIT App Inventor Forum

It would be useful for mapping purposes in the UK. I have thought about coding up lat long to ngr conversion. I presume it would be best to do it as an AI extension.

Apr 11, 2016, 1:57:11 PM4/11/16

to MIT App Inventor Forum

This seems to be the best algorithm and instruction I could find. There's the price of a case of beer to the one who solves it!

## How to convert latitude and longitude to a British National Grid Reference.

Although there is a lot of involved maths, this is not a difficult task. There are some problems, however, firstly due to the different ways latitude and longitude can be defined. All mapping systems have to use a model of the shape of planet Earth, which is not a perfect sphere. The distance between the poles is less that the distance across the equator, making a shape called an **ellipsoid**. But the ellipsoid is not a perfect fit either.

Most accurate maps show only part of the surface of the Earth, usually a single country or part of a country. So the usual way of getting round the problem is to define an ellipsoid whose surface has a good alignment with reality over the area the maps is to cover. The Ordnance Survey maps of the United Kingdom use three such reference ellipsoids, one for the Island of Great Britain (England, Scotland and Wales), another for the Island of Ireland, and finally a third ellipsoid to deal with the Channel Islands. This article primarily describes Great Britain, but the same maths can be applied to most of the other two areas.

The traditional ellipsoid adopted for Great Britain is called the Airy Spheroid. This was defined in 1830 by Britain's Astronomer Royal, Sir George Airy. This has a semi-major axis of 6377563.396 metres, and a semi-minor axis of 6356256.910 metres. In the equations that follow we use a constant called the eccentricity, this is simply the diffence between the squares of the axes, divided by the square of the major axis.

```
function ecc(major, minor)
{
return (major*major - minor*minor) / (major*major);
}
```

Using the formula above with the Airy axes we get an eccentricity of 0.006670539761597337

Let us assume that that our measurements of latitude and longitude are based on the Airy spheroid. This may not be true, but I'll cover that later on. Firstly we need to convert our measurements from degrees to radians. There is accomplished by multiplying our latitude or longitude by PI / 180. I shall call this conversion factor **deg2rad**. A few other constants are also defined:

```
function LLtoNE(lat, lon)
{
var deg2rad = Math.PI / 180;
var rad2deg = 180.0 / Math.PI;
var phi = lat * deg2rad; // convert latitude to radians
var lam = lon * deg2rad; // convert longitude to radians
a = 6377563.396; // OSGB semi-major axis
b = 6356256.91; // OSGB semi-minor axis
e0 = 400000; // OSGB easting of false origin
n0 = -100000; // OSGB northing of false origin
f0 = 0.9996012717; // OSGB scale factor on central meridian
e2 = 0.0066705397616; // OSGB eccentricity squared
lam0 = -0.034906585039886591; // OSGB false east
phi0 = 0.85521133347722145; // OSGB false north
var af0 = a * f0;
var bf0 = b * f0;
// easting
var slat2 = Math.sin(phi) * Math.sin(phi);
var nu = af0 / (Math.sqrt(1 - (e2 * (slat2))));
var rho = (nu * (1 - e2)) / (1 - (e2 * slat2));
var eta2 = (nu / rho) - 1;
var p = lam - lam0;
var IV = nu * Math.cos(phi);
var clat3 = Math.pow(Math.cos(phi),3);
var tlat2 = Math.tan(phi) * Math.tan(phi);
var V = (nu / 6) * clat3 * ((nu / rho) - tlat2);
var clat5 = Math.pow(Math.cos(phi), 5);
var tlat4 = Math.pow(Math.tan(phi), 4);
var VI = (nu / 120) * clat5 * ((5 - (18 * tlat2)) + tlat4 + (14 * eta2) - (58 * tlat2 * eta2));
east = e0 + (p * IV) + (Math.pow(p, 3) * V) + (Math.pow(p, 5) * VI);
// northing
var n = (af0 - bf0) / (af0 + bf0);
var M = Marc(bf0, n, phi0, phi);
var I = M + (n0);
var II = (nu / 2) * Math.sin(phi) * Math.cos(phi);
var III = ((nu / 24) * Math.sin(phi) * Math.pow(Math.cos(phi), 3)) * (5 - Math.pow(Math.tan(phi), 2) + (9 * eta2));
var IIIA = ((nu / 720) * Math.sin(phi) * clat5) * (61 - (58 * tlat2) + tlat4);
north = I + ((p * p) * II) + (Math.pow(p, 4) * III) + (Math.pow(p, 6) * IIIA);
east = Math.round(east); // round to whole number
north = Math.round(north); // round to whole number
nstr = String(north); // convert to string
estr = String(east); // ditto
}
function Marc(bf0, n, phi0, phi)
{
var Marc = bf0 * (((1 + n + ((5 / 4) * (n * n)) + ((5 / 4) * (n * n * n))) * (phi - phi0))
- (((3 * n) + (3 * (n * n)) + ((21 / 8) * (n * n * n))) * (Math.sin(phi - phi0)) * (Math.cos(phi + phi0)))
+ ((((15 / 8) * (n * n)) + ((15 / 8) * (n * n * n))) * (Math.sin(2 * (phi - phi0))) * (Math.cos(2 * (phi + phi0))))
- (((35 / 24) * (n * n * n)) * (Math.sin(3 * (phi - phi0))) * (Math.cos(3 * (phi + phi0)))));
return(Marc);
}
```

This is quite involved maths, and I am not going to try to explain it! This is the same as that used in the Ordnance Survey document A Guide to Coordinate Systems in Great Britain and converts latitude and longitude to a Transverse Mercator projection. These projections are often used for paper (flat) maps. You can find some explanation in the OS document.

The Javascript maths functions are fairly obvious, I hope! You will have to scroll far to the right to see some of the code. Some of the expressions are quite long-winded, so I have split them up a little to avoid too many confusing brackets and Math functions.

We can now try this with some test figures, latitude 52° 39’ 27.2531" north, 1° 43’ 4.5177" east. These figures are taken from a worked example in the Ordnance Survey document.

```
lat = 52.65757; // decimal version of latitude
lon = 1.71791; // decimal version of longitude
LLtoNE(lat, lon);
document.write("And the results are:");
document.write("Northings: ",nstr, " metres.");
document.write("Eastings: ", estr, " metres.");
```

And the results are:

Northings: 313177 metres.

Eastings: 651409 metres.

The NGR northings and eastings are shown along the axes of any Ordnance Survey map. Normally the NGR is shown as letters and numbers. The letters replace the 100km digit(s) of the eastings and northings. This could easily be determined from a simple look-up table, which would need to handle the ninety one 100km 'squares'. So here is a weird formula, source unknown, which does the job in less space:

```
function NE2NGR(east, north)
{
var eX = east / 500000;
var nX = north / 500000;
var tmp = Math.floor(eX)-5.0 * Math.floor(nX)+17.0;
nX = 5 * (nX - Math.floor(nX));
eX = 20 - 5.0 * Math.floor(nX) + Math.floor(5.0 * (eX - Math.floor(eX)));
if (eX > 7.5)
eX = eX + 1;
if (tmp > 7.5)
tmp = tmp + 1;
var eing = String(east);
var ning = String(north);
var lnth = eing.length;
eing = eing.substring(lnth - 5, lnth);
lnth = ning.length;
ning = ning.substring(lnth - 5, lnth);
ngr = String.fromCharCode(tmp + 65) + String.fromCharCode(eX + 65) + " " + eing + " " + ning;
return ngr;
}
```

So for a worked example using the same latitude and longitude, we run the code:

```
lat = 52.65757;
lon = 1.71791;
LLtoNE(lat, lon);
document.write("And the results are:");
document.write("Northings: ",nstr, " metres.");
document.write("Eastings: ", estr, " metres.");
ngr = NE2NGR(east, north);
document.write("NGR:", ngr);
```

And the results are:

Northings: 313177 metres.

Eastings: 651409 metres.

NGR: TG 51409 13177

This is a one metre grid reference, it can be reduced to the standard 100m reference by omitting the last two figures of each five figure group: TG 514 131.

That is basically how it is done. There are a few short cuts, for example I have not taken into account the fact that the NGR grid has a scale factor that varies as you move laterally across the map. You can find appropriate code to deal with this issue in the OS document linked to earlier. I haven't bothered here, in any case the error involved is quite small.

Apr 11, 2016, 2:10:50 PM4/11/16

to MIT App Inventor Forum

This seems to be the best algorithm and instruction I could find

just for completeness: algorithm copied from here http://www.dorcus.co.uk/carabus/ll_ngr.html

Taifun

Apr 11, 2016, 11:06:30 PM4/11/16

to mitappinv...@googlegroups.com

Since the sources were Javascript, we can use the WebViewer and the WebViewString property to pass the lat,long values to an html document stored in the app.

The javascript in the html document calculates the British National Grid value and returns it via the WebViewString property where it is displayed in a label.

So the html document+javascript are only used for the computations.

---

Happy Inventing!

Apr 12, 2016, 1:37:59 AM4/12/16

to MIT App Inventor Forum

Awesome. Will check this out later and get back, thanks.

Apr 12, 2016, 3:02:52 AM4/12/16

to MIT App Inventor Forum

Hi Scott,

I did a test and something didn't quite work out. test data is Lat: 51.30220, Lon: 2.54200 - this should equate to: ST 93505 78582 but the app returns TS 16533 65755

How about taking in the data provided by the location sensor and converting that? I'll then be asking for your PayPal email for the case of beer value :)

Apr 12, 2016, 8:14:35 AM4/12/16

to MIT App Inventor Forum

This version adds a button for getting the lat,lon from the location sensor.

The test lat,lon from the original javascript tutorial was used in this project for testing and returns the same result as the author's.

So the calculations are working the same here.

If his javascript has a bug somewhere, then it will show up here as well.

Apr 15, 2016, 10:30:47 AM4/15/16

to MIT App Inventor Forum

Sorry Scott, been away for a few days. Will look at this and get back to you over the weekend. Cheers.

Apr 21, 2016, 5:05:53 AM4/21/16

to MIT App Inventor Forum

Sorry for the delay - this seems to work really well. Scott, what's your PayPal address and what's the cost of your tipple?

I now need to work out how to get this into an existing app i'm working on. Can't quite get my head around where the conversion code is retrieved from the htm file. Can you tell me where it's stored and, if i was to transfer your blocks and design across to another app would it still work?

Cheers

Richie

Apr 21, 2016, 7:36:27 AM4/21/16

to MIT App Inventor Forum

Thanks for the offer but I don't accept payment for MITAI support -- it's one of my hobbies :)

The html file with javascript is attached but it is also stored in the aia project Media folder as well.

You can download it from there also.

Here is the entire html source for the conversion code with my few lines of code added to communicate with MITAI:

<html>

<head>

<script>

function NE2NGR(east, north)

{

var eX = east / 500000;

var nX = north / 500000;

var tmp = Math.floor(eX)-5.0 * Math.floor(nX)+17.0;

nX = 5 * (nX - Math.floor(nX));

eX = 20 - 5.0 * Math.floor(nX) + Math.floor(5.0 * (eX - Math.floor(eX)));

if (eX > 7.5)

eX = eX + 1;

if (tmp > 7.5)

tmp = tmp + 1;

var eing = String(east);

var ning = String(north);

var lnth = eing.length;

eing = eing.substring(lnth - 5, lnth);

lnth = ning.length;

ning = ning.substring(lnth - 5, lnth);

ngr = String.fromCharCode(tmp + 65) + String.fromCharCode(eX + 65) + " " + eing + " " + ning;

return ngr;

}

function LatLon2Ngr()

{

// pass the lat,lon as a space-separated string: "<lat value> <lon value>"

var latlon = window.AppInventor.getWebViewString().split(" ");

var lat = latlon[0];

var lon = latlon[1];

LLtoNE(lat, lon);

window.AppInventor.setWebViewString(NE2NGR(east, north));

}

</script>

</head>

<body onload="LatLon2Ngr()">

</body>

</html>

The code to get the lat,lon from MITAI is in blue:

The code to send back the result is in magenta.

function LatLon2Ngr()

{

// pass the lat,lon as a space-separated string: "<lat value> <lon value>"

LLtoNE(lat, lon);

window.AppInventor.setWebViewString(NE2NGR(east, north));

}

</script>

</head>

<body onload="LatLon2Ngr()">

</body>

</html>

The east and north variables are set in his LL2NE() procedure.

Yes. Just use similar blocks to mine on the MITAI side to send the lat,lon values and receive the result.

---

Happy Inventing!

Apr 21, 2016, 8:47:39 AM4/21/16

to MIT App Inventor Forum

You Sir, are a scholar and a gentleman.

Many thanks :)

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu