[Script] WMEOpenData v2.3 (20140201)

Moderators: krankyd, Unholy, dmcconachie

Re: OS Open Data User Scripts

Postby Twister-UK » Wed Jun 27, 2012 12:47 am

Update for WME to OS, incorporating various suggestions made above...

Code: Select all
// ==UserScript==
// @name                WME to OS link
// @namespace           http://greasemonkey.chizzum.com
// @description         Adds link to WME to open up OS Open Data/Musical Chairs sites at same map location
// @include             https://world.waze.com/editor/*
// @version             0.3
// ==/UserScript==


// Modified from the original (c) Chris Veness 2005-2012
//   www.movable-type.co.uk/scripts/gridref.js
//   www.movable-type.co.uk/scripts/latlon-gridref.html
function toOSGrid(lat, lon)
{
   lat = (lat * Math.PI) / 180;
   lon = (lon * Math.PI) / 180;

   // Airy 1830 major & minor semi-axes
   var a = 6377563.396;
   var b = 6356256.910;
   // NatGrid scale factor on central meridian
   var F0 = 0.9996012717;
   // NatGrid true origin is 49N,2W
   var lat0 = 0.85521;
   var lon0 = -0.0349;
   // northing & easting of true origin, metres
   var N0 = -100000;
   var E0 = 400000;
   // eccentricity squared
   var e2 = 1 - (b*b)/(a*a);

   var n = (a-b)/(a+b);
   var n2 = n*n;
   var n3 = n*n*n;
   var cosLat = Math.cos(lat);
   var sinLat = Math.sin(lat);
   // transverse radius of curvature
   var nu = a*F0/Math.sqrt(1-e2*sinLat*sinLat);
   // meridional radius of curvature
   var rho = a*F0*(1-e2)/Math.pow(1-e2*sinLat*sinLat, 1.5);
   var eta2 = nu/rho-1;
   var Ma = (1 + n + (5/4)*n2 + (5/4)*n3) * (lat-lat0);
   var Mb = (3*n + 3*n*n + (21/8)*n3) * Math.sin(lat-lat0) * Math.cos(lat+lat0);
   var Mc = ((15/8)*n2 + (15/8)*n3) * Math.sin(2*(lat-lat0)) * Math.cos(2*(lat+lat0));
   var Md = (35/24)*n3 * Math.sin(3*(lat-lat0)) * Math.cos(3*(lat+lat0));
   // meridional arc
   var M = b * F0 * (Ma - Mb + Mc - Md);
   var cos3lat = cosLat*cosLat*cosLat;
   var cos5lat = cos3lat*cosLat*cosLat;
   var tan2lat = Math.tan(lat)*Math.tan(lat);
   var tan4lat = tan2lat*tan2lat;
   var I = M + N0;
   var II = (nu/2)*sinLat*cosLat;
   var III = (nu/24)*sinLat*cos3lat*(5-tan2lat+9*eta2);
   var IIIA = (nu/720)*sinLat*cos5lat*(61-58*tan2lat+tan4lat);
   var IV = nu*cosLat;
   var V = (nu/6)*cos3lat*(nu/rho-tan2lat);
   var VI = (nu/120) * cos5lat * (5 - 18*tan2lat + tan4lat + 14*eta2 - 58*tan2lat*eta2);
   var dLon = lon-lon0;
   var dLon2 = dLon*dLon;
   var dLon3 = dLon2*dLon;
   var dLon4 = dLon3*dLon;
   var dLon5 = dLon4*dLon;
   var dLon6 = dLon5*dLon;
   var N = Math.round(I + II*dLon2 + III*dLon4 + IIIA*dLon6);
   var E = Math.round(E0 + IV*dLon + V*dLon3 + VI*dLon5);
   return '?e='+E+'&n='+N;
}


function processPermalink()
{
   // extract current lat/lon & zoom level from the permalink URL
   var plsrc = document.getElementById("permalink-container").innerHTML;
   var zoompos = plsrc.indexOf("?zoom=");
   var latpos = plsrc.indexOf("&lat=");
   var lonpos = plsrc.indexOf("&lon=");
   var layerpos = plsrc.indexOf("&layers=");

   // does the URL contain all three parameters?
   if((zoompos != -1)&&(latpos != -1)&&(lonpos != -1)&&(layerpos != -1))
   {
      // yes, so extract them...
      var zoom = parseInt(plsrc.substr(zoompos+6,latpos-(zoompos+6)));
      var lat = plsrc.substr(latpos+9,lonpos-(latpos+9));
      var lon = plsrc.substr(lonpos+9,layerpos-(lonpos+9));

      // compare the freshly extracted parameters against the persistent copies, and update the
      // links to OSMC & OSOD only if there's a change required - the newly-inserted <a> element
      // can't be clicked on until the insertion process is complete, and if we were to re-insert
      // it every 250ms then it'd spend a lot of its time giving the appearance of being clickable
      // but without actually doing anything...
      if((zoom != sessionStorage.zoom)||(lat != sessionStorage.lat)||(lon != sessionStorage.lon))
      {
         // update the persistent vars with the new position
         sessionStorage.zoom = zoom;
         sessionStorage.lat = lat;
         sessionStorage.lon = lon;

         // translate the zoom level between WME and Musical Chairs - this gives a pretty close match
         var mczoom = zoom + 12;
         if(mczoom > 18) mczoom = 18;
         // generate the Musical Chairs URL
         var osmc_url = 'http://ris.dev.openstreetmap.org/oslmusicalchairs/map?zoom='+mczoom+'&lat='+lat+'&lon='+lon+'&layers=B0TT&view_mode=pseudorandom';

         // translate the zoom level between WME and OpenData - the match here isn't quite so good...
         var odzoom = zoom + 5;
         if(odzoom < 6) odzoom = 6;
         if(odzoom > 10) odzoom = 10;
         // generate the OpenData URL - requires the support of os_opendata_fullheight.user.js
         var osod_url = 'http://www.ordnancesurvey.co.uk/oswebsite/opendata/viewer/'+toOSGrid(lat,lon)+'&z='+odzoom;

         // translate the zoom level between WME and live map.  The only correlation is (WME)=[Live] (0 or 1)=[7], (2 or 3)=[8], (4 or more)=[9]
         var livemap_zoom = Math.floor(zoom/2)+7;
         if (livemap_zoom > 9 ) livemap_zoom = 9;
         var livemap_url = 'https://world.waze.com/livemap/?zoom='+livemap_zoom+'&lat='+lat+'&lon='+lon+'&layers=BTTTT';
         // Modify existing livemap link to reference current position in WME
         document.getElementById("livemap").href = livemap_url;
         document.getElementById("livemap").target = '_blank';

         // "borrow" the Bing attribution div to insert the new clicky-links, remembering to maintain the attribution after we're done messing with it!
         var pl_colour = document.defaultView.getComputedStyle(document.getElementById("map-footer"),"").getPropertyValue("color");
         document.getElementById("bing-attribution").innerHTML = ' <a href="'+osod_url+'" target=_osopendata style="color:' + pl_colour +'">OS OpenData</a> | <a href="'+osmc_url+'" target=_osmusicalchairs style="color:' + pl_colour +'">OS Musical Chairs</a> | Imagery by Bing';

         // uncomment these lines if you want the OpenData and/or MusicalChairs tabs to auto-follow the WME location...
         // window.open(osod_url,'_osopendata');
         // window.open(osmc_url,'_osmusicalchairs');
      }
   }
}

// initialise persistent vars
sessionStorage.zoom = 0;
sessionStorage.lat = '';
sessionStorage.lon = '';

// check for new map co-ords every 250ms
setInterval(processPermalink,250);


Changes:
* Top navbar link back to the livemap uses WME location (Dave2084)
* OSMC/OSOD links copy style from permalink (Dave2084)
* OpenData and MusicalChairs links reuse any existing tabs/windows (Timbones)

Not enabled by default, uncomment the last two lines in the processPermalink() function:
* OpenData and MusicalChairs tabs/windows automatically track WME position (xteejx)

I didn't enable this last change by default since I'm not entirely sure I like it - if the extents of the OSOD map viewport exactly matched that of the WME viewport for all zoom levels, it might work well, but there are often times when the mismatch between the two viewports means that I only need to drag the WME map a little to expose a road which is still visible on the OSOD map (don't really use OSMC so I'm not sure if that is any better in this respect), and I wouldn't then want OSOD to reload. Comments are welcomed from anyone who does try it out!
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Thu Jun 28, 2012 8:54 pm

Code: Select all
// ==UserScript==
// @name                WME to OS link
// @namespace           http://greasemonkey.chizzum.com
// @description         Adds link to WME to open up various mapping sites at the same map location
// @include             https://world.waze.com/editor/*
// @include             https://descartesw.waze.com/beta/*
// @version             0.4
// ==/UserScript==


// Modified from the original (c) Chris Veness 2005-2012
//   www.movable-type.co.uk/scripts/gridref.js
//   www.movable-type.co.uk/scripts/latlon-gridref.html
function toOSGrid(lat, lon)
{
   lat = (lat * Math.PI) / 180;
   lon = (lon * Math.PI) / 180;

   // Airy 1830 major & minor semi-axes
   var a = 6377563.396;
   var b = 6356256.910;
   // NatGrid scale factor on central meridian
   var F0 = 0.9996012717;
   // NatGrid true origin is 49N,2W
   var lat0 = 0.85521;
   var lon0 = -0.0349;
   // northing & easting of true origin, metres
   var N0 = -100000;
   var E0 = 400000;
   // eccentricity squared
   var e2 = 1 - (b*b)/(a*a);

   var n = (a-b)/(a+b);
   var n2 = n*n;
   var n3 = n*n*n;
   var cosLat = Math.cos(lat);
   var sinLat = Math.sin(lat);
   // transverse radius of curvature
   var nu = a*F0/Math.sqrt(1-e2*sinLat*sinLat);
   // meridional radius of curvature
   var rho = a*F0*(1-e2)/Math.pow(1-e2*sinLat*sinLat, 1.5);
   var eta2 = nu/rho-1;
   var Ma = (1 + n + (5/4)*n2 + (5/4)*n3) * (lat-lat0);
   var Mb = (3*n + 3*n*n + (21/8)*n3) * Math.sin(lat-lat0) * Math.cos(lat+lat0);
   var Mc = ((15/8)*n2 + (15/8)*n3) * Math.sin(2*(lat-lat0)) * Math.cos(2*(lat+lat0));
   var Md = (35/24)*n3 * Math.sin(3*(lat-lat0)) * Math.cos(3*(lat+lat0));
   // meridional arc
   var M = b * F0 * (Ma - Mb + Mc - Md);
   var cos3lat = cosLat*cosLat*cosLat;
   var cos5lat = cos3lat*cosLat*cosLat;
   var tan2lat = Math.tan(lat)*Math.tan(lat);
   var tan4lat = tan2lat*tan2lat;
   var I = M + N0;
   var II = (nu/2)*sinLat*cosLat;
   var III = (nu/24)*sinLat*cos3lat*(5-tan2lat+9*eta2);
   var IIIA = (nu/720)*sinLat*cos5lat*(61-58*tan2lat+tan4lat);
   var IV = nu*cosLat;
   var V = (nu/6)*cos3lat*(nu/rho-tan2lat);
   var VI = (nu/120) * cos5lat * (5 - 18*tan2lat + tan4lat + 14*eta2 - 58*tan2lat*eta2);
   var dLon = lon-lon0;
   var dLon2 = dLon*dLon;
   var dLon3 = dLon2*dLon;
   var dLon4 = dLon3*dLon;
   var dLon5 = dLon4*dLon;
   var dLon6 = dLon5*dLon;
   var N = Math.round(I + II*dLon2 + III*dLon4 + IIIA*dLon6);
   var E = Math.round(E0 + IV*dLon + V*dLon3 + VI*dLon5);
   return '?e='+E+'&n='+N;
}


function processPermalink()
{
   // extract current lat/lon & zoom level from the permalink URL
   var plsrc = document.getElementById("permalink-container").innerHTML;
   var zoompos = plsrc.indexOf("?zoom=");
   var latpos = plsrc.indexOf("&amp;lat=");
   var lonpos = plsrc.indexOf("&amp;lon=");
   var layerpos = plsrc.indexOf("&amp;layers=");

   // does the URL contain all three parameters?
   if((zoompos != -1)&&(latpos != -1)&&(lonpos != -1)&&(layerpos != -1))
   {
      // yes, so extract them...
      var zoom = parseInt(plsrc.substr(zoompos+6,latpos-(zoompos+6)));
      var lat = plsrc.substr(latpos+9,lonpos-(latpos+9));
      var lon = plsrc.substr(lonpos+9,layerpos-(lonpos+9));

      // compare the freshly extracted parameters against the persistent copies, and update the
      // links to OSMC & OSOD only if there's a change required - the newly-inserted <a> element
      // can't be clicked on until the insertion process is complete, and if we were to re-insert
      // it every 250ms then it'd spend a lot of its time giving the appearance of being clickable
      // but without actually doing anything...
      if((zoom != sessionStorage.zoom)||(lat != sessionStorage.lat)||(lon != sessionStorage.lon))
      {
         // update the persistent vars with the new position
         sessionStorage.zoom = zoom;
         sessionStorage.lat = lat;
         sessionStorage.lon = lon;

         // translate the zoom level between WME and Musical Chairs - this gives a pretty close match
         var mczoom = zoom + 12;
         if(mczoom > 18) mczoom = 18;
         // generate the Musical Chairs URL
         var osmc_url = 'http://ris.dev.openstreetmap.org/oslmusicalchairs/map?zoom='+mczoom+'&lat='+lat+'&lon='+lon+'&layers=B0TT&view_mode=pseudorandom';

         // translate the zoom level between WME and OpenData - the match here isn't quite so good...
         var odzoom = zoom + 5;
         if(odzoom < 6) odzoom = 6;
         if(odzoom > 10) odzoom = 10;
         // generate the OpenData URL - requires the support of os_opendata_fullheight.user.js
         var osod_url = 'http://www.ordnancesurvey.co.uk/oswebsite/opendata/viewer/'+toOSGrid(lat,lon)+'&z='+odzoom;

         // generate the Cartouche URL
         var cartouche_url = 'http://world.waze.com/cartouche_old/?zoom='+zoom+'&lon='+lon+'&lat='+lat;

         // translate the zoom level between WME and live map.  The only correlation is (WME)=[Live] (0 or 1)=[7], (2 or 3)=[8], (4 or more)=[9]
         var livemap_zoom = Math.floor(zoom/2)+7;
         if (livemap_zoom > 9 ) livemap_zoom = 9;
         var livemap_url = 'https://world.waze.com/livemap/?zoom='+livemap_zoom+'&lat='+lat+'&lon='+lon+'&layers=BTTTT';
         // Modify existing livemap link to reference current position in WME
         document.getElementById("livemap").href = livemap_url;
         document.getElementById("livemap").target = '_blank';

         // update the link URLs
         document.getElementById("_linkOSOD").href = osod_url;
         document.getElementById("_linkOSMC").href = osmc_url;
         document.getElementById("_linkCartouche").href = cartouche_url;

         // refresh any of the site tabs/windows we've checked for auto-tracking
         if(document.getElementById('_cbAutoTrackOSOD').checked == 1) window.open(osod_url,'_osopendata');
         if(document.getElementById('_cbAutoTrackOSMC').checked == 1) window.open(osmc_url,'_osmusicalchairs');
         if(document.getElementById('_cbAutoTrackCartouche').checked == 1) window.open(cartouche_url,'_cartouche');
      }
   }
}

// initialise persistent vars
sessionStorage.zoom = 0;
sessionStorage.lat = '';
sessionStorage.lon = '';

// get the colour attribute for the permalink, so that our new links are visually consistent
var pl_colour = document.defaultView.getComputedStyle(document.getElementById("map-footer"),"").getPropertyValue("color");
// create a new child div in the existing map footer div, so we don't have to borrow the bing attrinution one any more...
var mlcDiv = document.createElement('div');
mlcDiv.setAttribute('id','MapLinkControls');
// add the anchors and auto-track checkboxes for OS OpenData, Musical Chairs and Cartouche.  Note that the urls are blank at this stage,
// they'll be filled in as soon as we've done our first processPermalink() call
mlcDiv.innerHTML = '<a href="" id="_linkOSOD" target=_osopendata style="color:' + pl_colour +'">OS OpenData</a> <input type="checkbox" id="_cbAutoTrackOSOD"></input> | ';
mlcDiv.innerHTML += '<a href="" id="_linkOSMC" target=_osmusicalchairs style="color:' + pl_colour +'">OS Musical Chairs</a> <input type="checkbox" id="_cbAutoTrackOSMC"></input> | ';
mlcDiv.innerHTML += '<a href="" id="_linkCartouche" target=_cartouche style="color:' + pl_colour +'">Cartouche</a> <input type="checkbox" id="_cbAutoTrackCartouche"></input>';
mlcDiv.innerHTML += '<br>(Checkboxes enable auto-tracking)';
document.getElementById('map-footer').appendChild(mlcDiv);

// set up a check for new map co-ords every 250ms
setInterval(processPermalink,250);


On the "what's new" menu for today...

  • Enabled for descartes - I can't fully test it as I don't have a login, but I at least can see the new links are being inserted as expected, so it looks as if it'll work ok...
  • Added link to Cartouche
  • Moved links over to left of screen in their own div
  • Added checkboxes to enable auto-tracking without requiring any code edits - if the relevant box is ticked, that site will be reloaded each time the script detects a change in the current map position/zoom level
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Thu Jun 28, 2012 9:25 pm

Now uploaded both scripts to userscripts.org
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Fri Jun 29, 2012 8:14 pm

Yep, I always test for compatibility with whatever the current release versions are of FF and Chrome for Win7, and so unless stated otherwise then I expect them to behave the same in either browser.

Now that they're on userscripts I don't think there should be any installation issues if you're just using the unmodified code, but if you've got it saved locally for tweaking purposes, then provided you remember to add the .user.js double-suffix onto the filename, you can also simply drag and drop the file onto FF or Chrome to invoke the script installation process.
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Fri Jun 29, 2012 8:19 pm

Dave2084 wrote:All we need now is "WME musical chairs" to check Waze road-names against the OS Locator DB :D


Don't go giving me ideas like that, all this scripting has put me waaaay behind in my editing - I need to lock away the greasemonkey programmers guide for a bit and spend some time putting these scripts to work :lol:
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Fri Jun 29, 2012 9:05 pm

Minor updates to both scripts:

WME to OS now supports the URL discovered by Dave2084

OS FullHeight now reliably uses the full viewport height in Chrome when the map is initially loaded (was quite obvious when using the auto-track option, with all the reloads that requires...).

Both available from userscripts (see sig)...
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Sat Jul 07, 2012 5:35 pm

Minor update to the WME to OS script uploaded to userscripts.org, to accommodate the recent formatting change in the WME permalink URL.
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Thu Jul 12, 2012 11:37 pm

Another WME to OS update, improving the accuracy of the lat/lon to gridref conversion by performing the proper WGS84->OSGB36 transformation rather than simply assuming the two are equal...
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Mon Jul 16, 2012 11:11 pm

Haven't put this one on userscripts.org, as it's a proof of concept release not intended for general use. The concept being evaluated here is the first version of my OS Locator lookup code, which may, possibly, lead to a point-n-click means of populating the road properties fields.

That's a probably optimistic, and definitely distant, goal. At present the code simply performs a basic grid ref comparison between the centrepoint of the WME map window and the bounding boxes defined in the OS data, and then lists all the matches it finds in the space below the map. This alone may be of some use in sanity-checking any existing road names, but it's really only intended to prove that we can pull, fairly quickly, the correct OS data into WME for the given map location.


Notes:

Not Chrome-compatible at present due to Chrome not implementing the Greasemonkey @require feature.

On installation, it downloads a pre-processed copy of the OS Locator dataset from my server - the file is 120MB so this may take some time... This data is cached locally as part of the installation process, and so it doesn't need to be downloaded each time the script runs.

All of the previous functionality of the script should still be present and work as before.



Code: Select all
// ==UserScript==
// @name                WME to OS link
// @namespace           http://greasemonkey.chizzum.com
// @description         Adds link to WME to open up various mapping sites at the same map location
// @include             https://world.waze.com/editor/*
// @include             https://world.waze.com/map-editor/*
// @include             https://descartesw.waze.com/beta/*
// @require             http://greasemonkey.chizzum.com/osl_10km.js
// @version             0.8
// ==/UserScript==

// Contains Ordnance Survey data Crown copyright and database right 2012
// Contents of the osl_10km.js file are derived under the Open Government Licence from the OS Locator dataset


//-----------------------------------------------------------------------------------------------------------------------------------------
// all code between here and the next ------------- marker line is a stripped down version of the original from Paul Dixon
//
// * GeoTools javascript coordinate transformations
// * http://files.dixo.net/geotools.html
// *
// * This file copyright (c)2005 Paul Dixon (paul@elphin.com)
// *
// * This program is free software; you can redistribute it and/or
// * modify it under the terms of the GNU General Public License
// * as published by the Free Software Foundation; either version 2
// * of the License, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program; if not, write to the Free Software
// * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
// *
// * ---------------------------------------------------------------------------
// *
// * Credits
// *
// * The algorithm used by the script for WGS84-OSGB36 conversions is derived
// * from an OSGB spreadsheet (www.gps.gov.uk) with permission. This has been
// * adapted into Perl by Ian Harris, and into PHP by Barry Hunter. Conversion
// * accuracy is in the order of 7m for 90% of Great Britain, and should be
// * be similar to the conversion made by a typical GPSr
// *
// * See accompanying documentation for more information
// * http://files.dixo.net/geotools.html

var northings;
var eastings;
var latitude;
var longitude;

var helmX, helmY, helmZ;
var Pi = 3.14159265358979;

function wgs_to_osgb()
{
   LatLon_to_HelmXYZ();
   var latitude2  = XYZ_to_Lat();
   var longitude2 = Math.atan2(helmY , helmX) * (180 / Pi);
   LatLon_to_OSGrid(latitude2,longitude2);
}

function LatLon_to_HelmXYZ()
{
   var a = 6378137.0;
   var b = 6356752.313;
   var DX = -446.448;
   var DY = 125.157;
   var DZ = -542.060;
   var rotX = -0.1502;
   var rotY = -0.2470;
   var rotZ = -0.8421;
   var sfactor = 20.4894 * 0.000001;

   // perform initial lat-lon to cartesian coordinate translation
   var RadPHI = latitude * (Pi / 180);
   var RadLAM = longitude * (Pi / 180);
   var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2);
   var V = a / (Math.sqrt(1 - (e2 * (  Math.pow(Math.sin(RadPHI),2)))));
   var cartX = V * (Math.cos(RadPHI)) * (Math.cos(RadLAM));
   var cartY = V * (Math.cos(RadPHI)) * (Math.sin(RadLAM));
   var cartZ = (V * (1 - e2)) * (Math.sin(RadPHI));

   // Compute Helmert transformed coordinates
   var RadX_Rot = (rotX / 3600) * (Pi / 180);
   var RadY_Rot = (rotY / 3600) * (Pi / 180);
   var RadZ_Rot = (rotZ / 3600) * (Pi / 180);
   helmX = (cartX + (cartX * sfactor) - (cartY * RadZ_Rot) + (cartZ * RadY_Rot) + DX);
   helmY = (cartX * RadZ_Rot) + cartY + (cartY * sfactor) - (cartZ * RadX_Rot) + DY;
   helmZ = (-1 * cartX * RadY_Rot) + (cartY * RadX_Rot) + cartZ + (cartZ * sfactor) + DZ;
}

function XYZ_to_Lat()
{
   var a = 6377563.396;
   var b = 6356256.910;
   var RootXYSqr = Math.sqrt(Math.pow(helmX,2) + Math.pow(helmY,2));
   var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2);
   var PHI1 = Math.atan2(helmZ , (RootXYSqr * (1 - e2)) );
   var PHI = Iterate_XYZ_to_Lat(a, e2, PHI1, helmZ, RootXYSqr);
   return PHI * (180 / Pi);
}

function Iterate_XYZ_to_Lat(a, e2, PHI1, Z, RootXYSqr)
{
   var V = a / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2))));
   var PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr);
   while (Math.abs(PHI1 - PHI2) > 0.000000001)
   {
      PHI1 = PHI2;
      V = a / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2))));
      PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr);
   }
   return PHI2;
}

function Marc(bf0, n, PHI0, PHI)
{
   return bf0 * (((1 + n + ((5 / 4) * Math.pow(n,2)) + ((5 / 4) * Math.pow(n,3))) * (PHI - PHI0)) - (((3 * n) + (3 * Math.pow(n,2)) +
          ((21 / 8) * Math.pow(n,3))) * (Math.sin(PHI - PHI0)) * (Math.cos(PHI + PHI0))) + ((((15 / 8) * Math.pow(n,2)) + ((15 / 8) *
          Math.pow(n,3))) * (Math.sin(2 * (PHI - PHI0))) * (Math.cos(2 * (PHI + PHI0)))) - (((35 / 24) * Math.pow(n,3)) *
          (Math.sin(3 * (PHI - PHI0))) * (Math.cos(3 * (PHI + PHI0)))));
}

function LatLon_to_OSGrid(PHI, LAM)
{
   var a = 6377563.396;
   var b = 6356256.910;
   var e0 = 400000;
   var n0 = -100000;
   var f0 = 0.999601272;
   var PHI0 = 49.00000;
   var LAM0 = -2.00000;

   var RadPHI = PHI * (Pi / 180);
   var RadLAM = LAM * (Pi / 180);
   var RadPHI0 = PHI0 * (Pi / 180);
   var RadLAM0 = LAM0 * (Pi / 180);
   var af0 = a * f0;
   var bf0 = b * f0;
   var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2);
   var n = (af0 - bf0) / (af0 + bf0);
   var nu = af0 / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(RadPHI),2) )));
   var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(RadPHI),2) ));
   var eta2 = (nu / rho) - 1;
   var p = RadLAM - RadLAM0;
   var M = Marc(bf0, n, RadPHI0, RadPHI);
   var I = M + n0;
   var II = (nu / 2) * (Math.sin(RadPHI)) * (Math.cos(RadPHI));
   var III = ((nu / 24) * (Math.sin(RadPHI)) * (Math.pow(Math.cos(RadPHI),3))) * (5 - (Math.pow(Math.tan(RadPHI),2)) + (9 * eta2));
   var IIIA = ((nu / 720) * (Math.sin(RadPHI)) * (Math.pow(Math.cos(RadPHI),5))) * (61 - (58 * (Math.pow(Math.tan(RadPHI),2))) + (Math.pow(Math.tan(RadPHI),4)));
   var IV = nu * (Math.cos(RadPHI));
   var V = (nu / 6) * ( Math.pow(Math.cos(RadPHI),3)) * ((nu / rho) - (Math.pow(Math.tan(RadPHI),2)));
   var VI = (nu / 120) * (Math.pow(Math.cos(RadPHI),5)) * (5 - (18 * (Math.pow(Math.tan(RadPHI),2))) + (Math.pow(Math.tan(RadPHI),4)) + (14 * eta2) - (58 * (Math.pow(Math.tan(RadPHI),2)) * eta2));
   eastings = Math.round(e0 + (p * IV) + (Math.pow(p,3) * V) + (Math.pow(p,5) * VI));
   northings = Math.round(I + (Math.pow(p,2) * II) + (Math.pow(p,4) * III) + (Math.pow(p,6) * IIIA));
}
//-----------------------------------------------------------------------------------------------------------------------------------------

function toOSGrid(lat, lon)
{
   latitude = lat;
   longitude = lon;
   wgs_to_osgb();

   // determine which 10km grid block contains the current WME centrepoint
   var eBlock = (Math.floor(eastings/10000)) * 10000;
   var nBlock = (Math.floor(northings/10000)) * 10000;
   // check to see if there's a corresponding array in the osl_10km data
   var evalstr = 'typeof locatorData_'+eBlock+'_'+nBlock;
   if(eval(evalstr) != "undefined")
   {
      // yes...  make a local copy to avoid having an eval() in each iteration of the loop
      evalstr = 'var blockData = locatorData_'+eBlock+'_'+nBlock;
      eval(evalstr);
      oslDiv.innerHTML = 'Potential names at '+eastings+','+northings+':<br>';
      for(var loop = 0;loop < blockData.length; loop++)
      {
         // for each entry in the array, test the centrepoint position to see if it lies within the bounding box for that entry
         // note that we allow a 10m tolerance on all sides of the box to allow for inaccuracies in the latlon->gridref conversion,
         // and to increase the chance of a successful match when the road runs E-W or N-S and thus has a long but narrow bounding box
         var locatorElements = blockData[loop].split(":");
         if((eastings>=parseInt(locatorElements[4])-10)&&(eastings<=parseInt(locatorElements[5])+10)&&(northings>=parseInt(locatorElements[6])-10)&&(northings<=parseInt(locatorElements[7])+10))
         {
            if(locatorElements[1].length > 0)
            {
               oslDiv.innerHTML += locatorElements[1];
               if(locatorElements[0].length > 0)
               {
                  oslDiv.innerHTML += " - ";
               }
            }
            oslDiv.innerHTML += locatorElements[0]+'<br>';
         }
      }
   }

   return '?e='+eastings+'&n='+northings;
}

function processPermalink()
{
   // extract current lat/lon & zoom level from the permalink URL
   var plsrc = document.getElementById("permalink-container").innerHTML;
   var zoompos = plsrc.indexOf("?zoom=");
   var latpos = plsrc.indexOf("&amp;lat=");
   var lonpos = plsrc.indexOf("&amp;lon=");
   var layerpos = plsrc.indexOf("&amp;layers=");

   // does the URL contain all three parameters?
   if((zoompos != -1)&&(latpos != -1)&&(lonpos != -1)&&(layerpos != -1))
   {
      // yes, so extract them...
      var zoom = parseInt(plsrc.substr(zoompos+6,latpos-(zoompos+6)));

      // accommodate both the original permalink ordering of zoom, lat then lon, and the present
      // ordering (as of early July 2012) of zoom, lon then lat...
      if(latpos < lonpos)
      {
         var lat = plsrc.substr(latpos+9,lonpos-(latpos+9));
         var lon = plsrc.substr(lonpos+9,layerpos-(lonpos+9));
      }
      else
      {
         var lat = plsrc.substr(latpos+9,layerpos-(latpos+9));
         var lon = plsrc.substr(lonpos+9,latpos-(lonpos+9));
      }

      // compare the freshly extracted parameters against the persistent copies, and update the
      // links to OSMC & OSOD only if there's a change required - the newly-inserted <a> element
      // can't be clicked on until the insertion process is complete, and if we were to re-insert
      // it every 250ms then it'd spend a lot of its time giving the appearance of being clickable
      // but without actually doing anything...
      if((zoom != sessionStorage.zoom)||(lat != sessionStorage.lat)||(lon != sessionStorage.lon))
      {
         // update the persistent vars with the new position
         sessionStorage.zoom = zoom;
         sessionStorage.lat = lat;
         sessionStorage.lon = lon;

         // translate the zoom level between WME and Musical Chairs - this gives a pretty close match
         var mczoom = zoom + 12;
         if(mczoom > 18) mczoom = 18;
         // generate the Musical Chairs URL
         var osmc_url = 'http://ris.dev.openstreetmap.org/oslmusicalchairs/map?zoom='+mczoom+'&lat='+lat+'&lon='+lon+'&layers=B0TT&view_mode=pseudorandom';

         // translate the zoom level between WME and OpenData - the match here isn't quite so good...
         var odzoom = zoom + 5;
         if(odzoom < 6) odzoom = 6;
         if(odzoom > 10) odzoom = 10;
         // generate the OpenData URL - requires the support of os_opendata_fullheight.user.js
         var osod_url = 'http://www.ordnancesurvey.co.uk/oswebsite/opendata/viewer/'+toOSGrid(lat,lon)+'&z='+odzoom;

         // generate the Cartouche URL
         var cartouche_url = 'http://world.waze.com/cartouche_old/?zoom='+zoom+'&lon='+lon+'&lat='+lat;

         // translate the zoom level between WME and live map.  The only correlation is (WME)=[Live] (0 or 1)=[7], (2 or 3)=[8], (4 or more)=[9]
         var livemap_zoom = Math.floor(zoom/2)+7;
         if (livemap_zoom > 9 ) livemap_zoom = 9;
         var livemap_url = 'https://world.waze.com/livemap/?zoom='+livemap_zoom+'&lat='+lat+'&lon='+lon+'&layers=BTTTT';
         // Modify existing livemap link to reference current position in WME
         document.getElementById("livemap").href = livemap_url;
         document.getElementById("livemap").target = '_blank';

         // update the link URLs
         document.getElementById("_linkOSOD").href = osod_url;
         document.getElementById("_linkOSMC").href = osmc_url;
         document.getElementById("_linkCartouche").href = cartouche_url;

         // refresh any of the site tabs/windows we've checked for auto-tracking
         if(document.getElementById('_cbAutoTrackOSOD').checked == 1) window.open(osod_url,'_osopendata');
         if(document.getElementById('_cbAutoTrackOSMC').checked == 1) window.open(osmc_url,'_osmusicalchairs');
         if(document.getElementById('_cbAutoTrackCartouche').checked == 1) window.open(cartouche_url,'_cartouche');
      }
   }
}

// initialise persistent vars
sessionStorage.zoom = 0;
sessionStorage.lat = '';
sessionStorage.lon = '';

// get the colour attribute for the permalink, so that our new links are visually consistent
var pl_colour = document.defaultView.getComputedStyle(document.getElementById("map-footer"),"").getPropertyValue("color");
// create a new child div in the existing map footer div, so we don't have to borrow the bing attrinution one any more...
var mlcDiv = document.createElement('div');
var oslDiv = document.createElement('div');
mlcDiv.setAttribute('id','MapLinkControls');
// add the anchors and auto-track checkboxes for OS OpenData, Musical Chairs and Cartouche.  Note that the urls are blank at this stage,
// they'll be filled in as soon as we've done our first processPermalink() call
mlcDiv.innerHTML = '<a href="" id="_linkOSOD" target=_osopendata style="color:' + pl_colour +'">OS OpenData</a> <input type="checkbox" id="_cbAutoTrackOSOD"></input> | ';
mlcDiv.innerHTML += '<a href="" id="_linkOSMC" target=_osmusicalchairs style="color:' + pl_colour +'">OS Musical Chairs</a> <input type="checkbox" id="_cbAutoTrackOSMC"></input> | ';
mlcDiv.innerHTML += '<a href="" id="_linkCartouche" target=_cartouche style="color:' + pl_colour +'">Cartouche</a> <input type="checkbox" id="_cbAutoTrackCartouche"></input>';
mlcDiv.innerHTML += '<br>(Checkboxes enable auto-tracking)';
document.getElementById('map-footer').appendChild(mlcDiv);
document.getElementById('map-footer').appendChild(oslDiv);

// set up a check for new map co-ords every 250ms
setInterval(processPermalink,250);
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

Re: OS Open Data User Scripts

Postby Twister-UK » Tue Jul 17, 2012 10:09 am

The OS Locator data consists of a whole bunch of fields per road, with the road name and road number being two seperate fields, so it's simple to add the two together with a - seperator to get the Waze-preferred format. Other fields include locality data (city/town/village name and county/area name) which could also be useful... As far as upper/lower case and abbreviations go, I'll probably sort all of that out in the pre-processing stage rather than expect the script to get it correct on the fly - having all the abbreviations baked into the preprocessed data will, along with some other optimisations, also help bring the data size down a little.

Layout-wise, the goal is ultimately to have the potential names listed as clickable links in the road properties section of the WME screen - click the name to auto-populate the relevant properties fields, then move the mouse pointer up a bit to do whatever fine tuning is required. It might be possible to quickly relocate the current non-clickable output up there too, I haven't yet had a look at that part of the WME page layout to see how much work is involved.

From a targetting point of view, I'd like to have it perform the lookup when you click on an existing road segment rather than having it constantly doing lookups every time the map is dragged - not only would this improve overall performance, but it'd also mean you'd know exactly which location was being used for the search. Not so sure if this is easily doable since it'd mean intercepting the mouse click before WME gets its hands on it, and from what I've seen so far the WME code isn't the easiest to follow...


Anyway, it is very early days for this evolution of the script, so right now I'm just happy that the OS lookup is working for at least one other person!
L4 AM for NW London and Shetland Islands - HTC One X/Android 4.1.1
WME/Livemap enhancement scripts @ userscripts.org and Chrome Web Store
Twister-UK
 
Posts: 858
Joined: Sat Jan 07, 2012 12:00 am
Location: NW London
Has thanked: 44 times
Been thanked: 325 times

PreviousNext

Return to United Kingdom

Who is online

Users browsing this forum: No registered users