| 1 | /** |
|---|
| 2 | * @requires OpenLayers/Layer/WMS.js |
|---|
| 3 | * @requires OpenLayers/Projection.js |
|---|
| 4 | * |
|---|
| 5 | * Class: OpenLayers.Layer.OpenSpace |
|---|
| 6 | * |
|---|
| 7 | * Inherits from: |
|---|
| 8 | * - <OpenLayers.Layer.WMS> |
|---|
| 9 | */ |
|---|
| 10 | OpenLayers.Layer.OpenSpace = OpenLayers.Class(OpenLayers.Layer.WMS, { |
|---|
| 11 | |
|---|
| 12 | /** |
|---|
| 13 | * Property: url |
|---|
| 14 | * {String} URL of OS tileserver API. |
|---|
| 15 | */ |
|---|
| 16 | url: "http://openspace.ordnancesurvey.co.uk/osmapapi/ts", |
|---|
| 17 | |
|---|
| 18 | /** |
|---|
| 19 | * Constructor: OpenLayers.Layer.OpenSpace |
|---|
| 20 | * |
|---|
| 21 | * Parameters: |
|---|
| 22 | * name - {String} |
|---|
| 23 | * apikey - {String} Ordnance Survey OpenSpace API Key |
|---|
| 24 | * options - {Object} Hashtable of extra options to tag onto the layer |
|---|
| 25 | */ |
|---|
| 26 | initialize: function(name, apikey, options) { |
|---|
| 27 | options = OpenLayers.Util.extend({ |
|---|
| 28 | attribution: "© Crown Copyright and database right 2008. All rights reserved. <a target='_blank' href='http://openspace.ordnancesurvey.co.uk/openspace/developeragreement.html#enduserlicense'>End User License Agreement</a>", |
|---|
| 29 | maxExtent: new OpenLayers.Bounds(0, 0, 1000000, 1300000), |
|---|
| 30 | resolutions: [2500, 1000, 500, 200, 100, 50, 25, 10, 5, 2, 1], |
|---|
| 31 | units: "m", |
|---|
| 32 | projection: new OpenLayers.Projection("EPSG:27700") |
|---|
| 33 | }, options); |
|---|
| 34 | |
|---|
| 35 | var params = { |
|---|
| 36 | "KEY": apikey |
|---|
| 37 | } |
|---|
| 38 | |
|---|
| 39 | var newArguments = [name, this.url, params, options]; |
|---|
| 40 | OpenLayers.Layer.WMS.prototype.initialize.apply(this, newArguments); |
|---|
| 41 | }, |
|---|
| 42 | |
|---|
| 43 | /** |
|---|
| 44 | * Method: getFullRequestString |
|---|
| 45 | * Combine the layer's url with its params and these newParams. |
|---|
| 46 | * We add the OS API key to the request string |
|---|
| 47 | * |
|---|
| 48 | * Parameters: |
|---|
| 49 | * newParams - {Object} |
|---|
| 50 | * altUrl - {String} Use this as the url instead of the layer's url |
|---|
| 51 | * |
|---|
| 52 | * Returns: |
|---|
| 53 | * {String} |
|---|
| 54 | */ |
|---|
| 55 | getFullRequestString: function(newParams, altUrl) { |
|---|
| 56 | this.params.LAYERS = this.resolutions[this.map.getZoom()]; |
|---|
| 57 | |
|---|
| 58 | return OpenLayers.Layer.WMS.prototype.getFullRequestString.apply( |
|---|
| 59 | this, arguments); |
|---|
| 60 | }, |
|---|
| 61 | |
|---|
| 62 | /** |
|---|
| 63 | * Method: initGriddedTiles |
|---|
| 64 | * |
|---|
| 65 | * Parameters: |
|---|
| 66 | * bounds - {<OpenLayers.Bounds>} |
|---|
| 67 | */ |
|---|
| 68 | initGriddedTiles: function(bounds) { |
|---|
| 69 | var tileSize; |
|---|
| 70 | // The OS make it difficult for us, the highest resolution tiles are |
|---|
| 71 | // served as 250x250px images, rather than the 200x200px as the rest. |
|---|
| 72 | // OpenLayers.Layer.Grid calls this function if the zoom level changes |
|---|
| 73 | |
|---|
| 74 | var res = this.map.getResolution(); |
|---|
| 75 | if(res > 2) { |
|---|
| 76 | tileSize = new OpenLayers.Size(200,200); |
|---|
| 77 | } else { |
|---|
| 78 | tileSize = new OpenLayers.Size(250,250); |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | // If we do actually change tile size, we need to clear the grid |
|---|
| 82 | if(!tileSize.equals(this.tileSize)) { |
|---|
| 83 | this.tileSize = tileSize; |
|---|
| 84 | this.clearGrid(); |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | // Pass onto the grid class to actually recreate the grid |
|---|
| 88 | OpenLayers.Layer.WMS.prototype.initGriddedTiles.apply(this, [bounds]); |
|---|
| 89 | }, |
|---|
| 90 | |
|---|
| 91 | CLASS_NAME: "OpenLayers.Layer.OpenSpace" |
|---|
| 92 | }); |
|---|
| 93 | |
|---|
| 94 | /** |
|---|
| 95 | * OpenLayers OSGB & Irish Grid Projection Transformations |
|---|
| 96 | * |
|---|
| 97 | * Conversion to OpenLayers by Thomas Wood (grand.edgemaster@gmail.com) |
|---|
| 98 | * |
|---|
| 99 | * this program is free software; you can redistribute it and/or |
|---|
| 100 | * modify it under the terms of the GNU General Public License |
|---|
| 101 | * as published by the Free Software Foundation; either version 2 |
|---|
| 102 | * of the License, or (at your option) any later version. |
|---|
| 103 | * |
|---|
| 104 | * this program is distributed in the hope that it will be useful, |
|---|
| 105 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 106 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 107 | * GNU General Public License for more details. |
|---|
| 108 | * |
|---|
| 109 | * You should have received a copy of the GNU General Public License |
|---|
| 110 | * along with this program; if not, write to the Free Software |
|---|
| 111 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 112 | * |
|---|
| 113 | * --------------------------------------------------------------------------- |
|---|
| 114 | * |
|---|
| 115 | * Credits: |
|---|
| 116 | * Based from the geotools js library by Paul Dixon |
|---|
| 117 | * GeoTools javascript coordinate transformations |
|---|
| 118 | * http://files.dixo.net/geotools.html |
|---|
| 119 | * |
|---|
| 120 | * Portions of this file copyright (c)2005 Paul Dixon (paul@elphin.com) |
|---|
| 121 | * |
|---|
| 122 | * The algorithm used by the script for WGS84-OSGB36 conversions is derived |
|---|
| 123 | * from an OSGB spreadsheet (www.gps.gov.uk) with permission. This has been |
|---|
| 124 | * adapted into Perl by Ian Harris, and into PHP by Barry Hunter. Conversion |
|---|
| 125 | * accuracy is in the order of 7m for 90% of Great Britain, and should be |
|---|
| 126 | * be similar to the conversion made by a typical GPSr |
|---|
| 127 | * |
|---|
| 128 | */ |
|---|
| 129 | |
|---|
| 130 | OpenLayers.Projection.OS = { |
|---|
| 131 | |
|---|
| 132 | /** |
|---|
| 133 | * Method: projectForwardBritish |
|---|
| 134 | * Given an object with x and y properties in EPSG:4326, modify the x,y |
|---|
| 135 | * properties on the object to be the OSGB36 (transverse mercator) |
|---|
| 136 | * projected coordinates. |
|---|
| 137 | * |
|---|
| 138 | * Parameters: |
|---|
| 139 | * point - {Object} An object with x and y properties. |
|---|
| 140 | * |
|---|
| 141 | * Returns: |
|---|
| 142 | * {Object} The point, with the x and y properties transformed to spherical |
|---|
| 143 | * mercator. |
|---|
| 144 | */ |
|---|
| 145 | projectForwardBritish: function(point) { |
|---|
| 146 | var x1 = OpenLayers.Projection.OS.Lat_Long_H_to_X(point.y,point.x,0,6378137.00,6356752.313); |
|---|
| 147 | var y1 = OpenLayers.Projection.OS.Lat_Long_H_to_Y(point.y,point.x,0,6378137.00,6356752.313); |
|---|
| 148 | var z1 = OpenLayers.Projection.OS.Lat_H_to_Z (point.y, 0,6378137.00,6356752.313); |
|---|
| 149 | |
|---|
| 150 | var x2 = OpenLayers.Projection.OS.Helmert_X(x1,y1,z1,-446.448,-0.2470,-0.8421,20.4894); |
|---|
| 151 | var y2 = OpenLayers.Projection.OS.Helmert_Y(x1,y1,z1, 125.157,-0.1502,-0.8421,20.4894); |
|---|
| 152 | var z2 = OpenLayers.Projection.OS.Helmert_Z(x1,y1,z1,-542.060,-0.1502,-0.2470,20.4894); |
|---|
| 153 | |
|---|
| 154 | var lat2 = OpenLayers.Projection.OS.XYZ_to_Lat (x2,y2,z2,6377563.396,6356256.910); |
|---|
| 155 | var lon2 = OpenLayers.Projection.OS.XYZ_to_Long(x2,y2); |
|---|
| 156 | |
|---|
| 157 | point.x = OpenLayers.Projection.OS.Lat_Long_to_East (lat2,lon2,6377563.396,6356256.910,400000,0.999601272,49.00000,-2.00000); |
|---|
| 158 | point.y = OpenLayers.Projection.OS.Lat_Long_to_North(lat2,lon2,6377563.396,6356256.910,400000,-100000,0.999601272,49.00000,-2.00000); |
|---|
| 159 | |
|---|
| 160 | return point; |
|---|
| 161 | }, |
|---|
| 162 | |
|---|
| 163 | /** |
|---|
| 164 | * Method: projectInverseBritish |
|---|
| 165 | * Given an object with x and y properties in OSGB36 (transverse mercator), |
|---|
| 166 | * modify the x,y properties on the object to be the unprojected coordinates. |
|---|
| 167 | * |
|---|
| 168 | * Parameters: |
|---|
| 169 | * point - {Object} An object with x and y properties. |
|---|
| 170 | * |
|---|
| 171 | * Returns: |
|---|
| 172 | * {Object} The point, with the x and y properties transformed from |
|---|
| 173 | * OSGB36 to unprojected coordinates.. |
|---|
| 174 | */ |
|---|
| 175 | projectInverseBritish: function(point) { |
|---|
| 176 | var lat1 = OpenLayers.Projection.OS.E_N_to_Lat (point.x,point.y,6377563.396,6356256.910,400000,-100000,0.999601272,49.00000,-2.00000); |
|---|
| 177 | var lon1 = OpenLayers.Projection.OS.E_N_to_Long(point.x,point.y,6377563.396,6356256.910,400000,-100000,0.999601272,49.00000,-2.00000); |
|---|
| 178 | |
|---|
| 179 | var x1 = OpenLayers.Projection.OS.Lat_Long_H_to_X(lat1,lon1,0,6377563.396,6356256.910); |
|---|
| 180 | var y1 = OpenLayers.Projection.OS.Lat_Long_H_to_Y(lat1,lon1,0,6377563.396,6356256.910); |
|---|
| 181 | var z1 = OpenLayers.Projection.OS.Lat_H_to_Z (lat1, 0,6377563.396,6356256.910); |
|---|
| 182 | |
|---|
| 183 | var x2 = OpenLayers.Projection.OS.Helmert_X(x1,y1,z1,446.448 ,0.2470,0.8421,-20.4894); |
|---|
| 184 | var y2 = OpenLayers.Projection.OS.Helmert_Y(x1,y1,z1,-125.157,0.1502,0.8421,-20.4894); |
|---|
| 185 | var z2 = OpenLayers.Projection.OS.Helmert_Z(x1,y1,z1,542.060 ,0.1502,0.2470,-20.4894); |
|---|
| 186 | |
|---|
| 187 | var lat = OpenLayers.Projection.OS.XYZ_to_Lat(x2,y2,z2,6378137.000,6356752.313); |
|---|
| 188 | var lon = OpenLayers.Projection.OS.XYZ_to_Long(x2,y2); |
|---|
| 189 | |
|---|
| 190 | point.x = lon; |
|---|
| 191 | point.y = lat; |
|---|
| 192 | return point; |
|---|
| 193 | }, |
|---|
| 194 | |
|---|
| 195 | goog2osgb: function(point) { |
|---|
| 196 | return OpenLayers.Projection.OS.projectForwardBritish(OpenLayers.Layer.SphericalMercator.projectInverse(point)); |
|---|
| 197 | }, |
|---|
| 198 | |
|---|
| 199 | osgb2goog: function(point) { |
|---|
| 200 | return OpenLayers.Layer.SphericalMercator.projectForward(OpenLayers.Projection.OS.projectInverseBritish(point)); |
|---|
| 201 | }, |
|---|
| 202 | |
|---|
| 203 | /***** |
|---|
| 204 | * Mathematical functions |
|---|
| 205 | *****/ |
|---|
| 206 | E_N_to_Lat: function(East, North, a, b, e0, n0, f0, PHI0, LAM0) { |
|---|
| 207 | //Un-project Transverse Mercator eastings and northings back to latitude. |
|---|
| 208 | //eastings (East) and northings (North) in meters; _ |
|---|
| 209 | //ellipsoid axis dimensions (a & b) in meters; _ |
|---|
| 210 | //eastings (e0) and northings (n0) of false origin in meters; _ |
|---|
| 211 | //central meridian scale factor (f0) and _ |
|---|
| 212 | //latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees. |
|---|
| 213 | |
|---|
| 214 | //Convert angle measures to radians |
|---|
| 215 | var Pi = 3.14159265358979; |
|---|
| 216 | var RadPHI0 = PHI0 * (Pi / 180); |
|---|
| 217 | var RadLAM0 = LAM0 * (Pi / 180); |
|---|
| 218 | |
|---|
| 219 | //Compute af0, bf0, e squared (e2), n and Et |
|---|
| 220 | var af0 = a * f0; |
|---|
| 221 | var bf0 = b * f0; |
|---|
| 222 | var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); |
|---|
| 223 | var n = (af0 - bf0) / (af0 + bf0); |
|---|
| 224 | var Et = East - e0; |
|---|
| 225 | |
|---|
| 226 | //Compute initial value for latitude (PHI) in radians |
|---|
| 227 | var PHId = OpenLayers.Projection.OS.InitialLat(North, n0, af0, RadPHI0, n, bf0); |
|---|
| 228 | |
|---|
| 229 | //Compute nu, rho and eta2 using value for PHId |
|---|
| 230 | var nu = af0 / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(PHId),2))))); |
|---|
| 231 | var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(PHId),2))); |
|---|
| 232 | var eta2 = (nu / rho) - 1; |
|---|
| 233 | |
|---|
| 234 | //Compute Latitude |
|---|
| 235 | var VII = (Math.tan(PHId)) / (2 * rho * nu); |
|---|
| 236 | var VIII = ((Math.tan(PHId)) / (24 * rho * Math.pow(nu,3))) * (5 + (3 * (Math.pow(Math.tan(PHId),2))) + eta2 - (9 * eta2 * (Math.pow(Math.tan(PHId),2)))); |
|---|
| 237 | var IX = ((Math.tan(PHId)) / (720 * rho * Math.pow(nu,5))) * (61 + (90 * ((Math.tan(PHId)) ^ 2)) + (45 * (Math.pow(Math.tan(PHId),4)))); |
|---|
| 238 | |
|---|
| 239 | var E_N_to_Lat = (180 / Pi) * (PHId - (Math.pow(Et,2) * VII) + (Math.pow(Et,4) * VIII) - ((Et ^ 6) * IX)); |
|---|
| 240 | |
|---|
| 241 | return (E_N_to_Lat); |
|---|
| 242 | }, |
|---|
| 243 | |
|---|
| 244 | E_N_to_Long: function(East, North, a, b, e0, n0, f0, PHI0, LAM0) { |
|---|
| 245 | //Un-project Transverse Mercator eastings and northings back to longitude. |
|---|
| 246 | //eastings (East) and northings (North) in meters; _ |
|---|
| 247 | //ellipsoid axis dimensions (a & b) in meters; _ |
|---|
| 248 | //eastings (e0) and northings (n0) of false origin in meters; _ |
|---|
| 249 | //central meridian scale factor (f0) and _ |
|---|
| 250 | //latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees. |
|---|
| 251 | |
|---|
| 252 | //Convert angle measures to radians |
|---|
| 253 | var Pi = 3.14159265358979; |
|---|
| 254 | var RadPHI0 = PHI0 * (Pi / 180); |
|---|
| 255 | var RadLAM0 = LAM0 * (Pi / 180); |
|---|
| 256 | |
|---|
| 257 | //Compute af0, bf0, e squared (e2), n and Et |
|---|
| 258 | var af0 = a * f0; |
|---|
| 259 | var bf0 = b * f0; |
|---|
| 260 | var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); |
|---|
| 261 | var n = (af0 - bf0) / (af0 + bf0); |
|---|
| 262 | var Et = East - e0; |
|---|
| 263 | |
|---|
| 264 | //Compute initial value for latitude (PHI) in radians |
|---|
| 265 | var PHId = OpenLayers.Projection.OS.InitialLat(North, n0, af0, RadPHI0, n, bf0); |
|---|
| 266 | |
|---|
| 267 | //Compute nu, rho and eta2 using value for PHId |
|---|
| 268 | var nu = af0 / (Math.sqrt(1 - (e2 * (Math.pow(Math.sin(PHId),2))))); |
|---|
| 269 | var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(PHId),2))); |
|---|
| 270 | var eta2 = (nu / rho) - 1; |
|---|
| 271 | |
|---|
| 272 | //Compute Longitude |
|---|
| 273 | var X = (Math.pow(Math.cos(PHId),-1)) / nu; |
|---|
| 274 | var XI = ((Math.pow(Math.cos(PHId),-1)) / (6 * Math.pow(nu,3))) * ((nu / rho) + (2 * (Math.pow(Math.tan(PHId),2)))); |
|---|
| 275 | var XII = ((Math.pow(Math.cos(PHId),-1)) / (120 * Math.pow(nu,5))) * (5 + (28 * (Math.pow(Math.tan(PHId),2))) + (24 * (Math.pow(Math.tan(PHId),4)))); |
|---|
| 276 | var XIIA = ((Math.pow(Math.cos(PHId),-1)) / (5040 * Math.pow(nu,7))) * (61 + (662 * (Math.pow(Math.tan(PHId),2))) + (1320 * (Math.pow(Math.tan(PHId),4))) + (720 * (Math.pow(Math.tan(PHId),6)))); |
|---|
| 277 | |
|---|
| 278 | var E_N_to_Long = (180 / Pi) * (RadLAM0 + (Et * X) - (Math.pow(Et,3) * XI) + (Math.pow(Et,5) * XII) - (Math.pow(Et,7) * XIIA)); |
|---|
| 279 | |
|---|
| 280 | return E_N_to_Long; |
|---|
| 281 | }, |
|---|
| 282 | |
|---|
| 283 | InitialLat: function(North, n0, afo, PHI0, n, bfo) { |
|---|
| 284 | //Compute initial value for Latitude (PHI) IN RADIANS. |
|---|
| 285 | //northing of point (North) and northing of false origin (n0) in meters; _ |
|---|
| 286 | //semi major axis multiplied by central meridian scale factor (af0) in meters; _ |
|---|
| 287 | //latitude of false origin (PHI0) IN RADIANS; _ |
|---|
| 288 | //n (computed from a, b and f0) and _ |
|---|
| 289 | //ellipsoid semi major axis multiplied by central meridian scale factor (bf0) in meters. |
|---|
| 290 | |
|---|
| 291 | //First PHI value (PHI1) |
|---|
| 292 | var PHI1 = ((North - n0) / afo) + PHI0; |
|---|
| 293 | |
|---|
| 294 | //Calculate M |
|---|
| 295 | var M = OpenLayers.Projection.OS.Marc(bfo, n, PHI0, PHI1); |
|---|
| 296 | |
|---|
| 297 | //Calculate new PHI value (PHI2) |
|---|
| 298 | var PHI2 = ((North - n0 - M) / afo) + PHI1; |
|---|
| 299 | |
|---|
| 300 | //Iterate to get final value for InitialLat |
|---|
| 301 | while (Math.abs(North - n0 - M) > 0.00001) |
|---|
| 302 | { |
|---|
| 303 | PHI2 = ((North - n0 - M) / afo) + PHI1; |
|---|
| 304 | M = OpenLayers.Projection.OS.Marc(bfo, n, PHI0, PHI2); |
|---|
| 305 | PHI1 = PHI2; |
|---|
| 306 | } |
|---|
| 307 | return PHI2; |
|---|
| 308 | }, |
|---|
| 309 | |
|---|
| 310 | Lat_Long_H_to_X: function(PHI, LAM, H, a, b) { |
|---|
| 311 | // Convert geodetic coords lat (PHI), long (LAM) and height (H) to cartesian X coordinate. |
|---|
| 312 | // Input: - _ |
|---|
| 313 | // Latitude (PHI)& Longitude (LAM) both in decimal degrees; _ |
|---|
| 314 | // Ellipsoidal height (H) and ellipsoid axis dimensions (a & b) all in meters. |
|---|
| 315 | |
|---|
| 316 | // Convert angle measures to radians |
|---|
| 317 | var Pi = 3.14159265358979; |
|---|
| 318 | var RadPHI = PHI * (Pi / 180); |
|---|
| 319 | var RadLAM = LAM * (Pi / 180); |
|---|
| 320 | |
|---|
| 321 | // Compute eccentricity squared and nu |
|---|
| 322 | var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); |
|---|
| 323 | var V = a / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(RadPHI),2))))); |
|---|
| 324 | |
|---|
| 325 | // Compute X |
|---|
| 326 | return (V + H) * (Math.cos(RadPHI)) * (Math.cos(RadLAM)); |
|---|
| 327 | }, |
|---|
| 328 | |
|---|
| 329 | |
|---|
| 330 | Lat_Long_H_to_Y: function(PHI, LAM, H, a, b) { |
|---|
| 331 | // Convert geodetic coords lat (PHI), long (LAM) and height (H) to cartesian Y coordinate. |
|---|
| 332 | // Input: - _ |
|---|
| 333 | // Latitude (PHI)& Longitude (LAM) both in decimal degrees; _ |
|---|
| 334 | // Ellipsoidal height (H) and ellipsoid axis dimensions (a & b) all in meters. |
|---|
| 335 | |
|---|
| 336 | // Convert angle measures to radians |
|---|
| 337 | var Pi = 3.14159265358979; |
|---|
| 338 | var RadPHI = PHI * (Pi / 180); |
|---|
| 339 | var RadLAM = LAM * (Pi / 180); |
|---|
| 340 | |
|---|
| 341 | // Compute eccentricity squared and nu |
|---|
| 342 | var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); |
|---|
| 343 | var V = a / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(RadPHI),2))) )); |
|---|
| 344 | |
|---|
| 345 | // Compute Y |
|---|
| 346 | return (V + H) * (Math.cos(RadPHI)) * (Math.sin(RadLAM)); |
|---|
| 347 | }, |
|---|
| 348 | |
|---|
| 349 | |
|---|
| 350 | Lat_H_to_Z: function(PHI, H, a, b) { |
|---|
| 351 | // Convert geodetic coord components latitude (PHI) and height (H) to cartesian Z coordinate. |
|---|
| 352 | // Input: - _ |
|---|
| 353 | // Latitude (PHI) decimal degrees; _ |
|---|
| 354 | // Ellipsoidal height (H) and ellipsoid axis dimensions (a & b) all in meters. |
|---|
| 355 | |
|---|
| 356 | // Convert angle measures to radians |
|---|
| 357 | var Pi = 3.14159265358979; |
|---|
| 358 | var RadPHI = PHI * (Pi / 180); |
|---|
| 359 | |
|---|
| 360 | // Compute eccentricity squared and nu |
|---|
| 361 | var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); |
|---|
| 362 | var V = a / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(RadPHI),2)) ))); |
|---|
| 363 | |
|---|
| 364 | // Compute X |
|---|
| 365 | return ((V * (1 - e2)) + H) * (Math.sin(RadPHI)); |
|---|
| 366 | }, |
|---|
| 367 | |
|---|
| 368 | |
|---|
| 369 | Helmert_X: function(X,Y,Z,DX,Y_Rot,Z_Rot,s) { |
|---|
| 370 | |
|---|
| 371 | // (X, Y, Z, DX, Y_Rot, Z_Rot, s) |
|---|
| 372 | // Computed Helmert transformed X coordinate. |
|---|
| 373 | // Input: - _ |
|---|
| 374 | // cartesian XYZ coords (X,Y,Z), X translation (DX) all in meters ; _ |
|---|
| 375 | // Y and Z rotations in seconds of arc (Y_Rot, Z_Rot) and scale in ppm (s). |
|---|
| 376 | |
|---|
| 377 | // Convert rotations to radians and ppm scale to a factor |
|---|
| 378 | var Pi = 3.14159265358979; |
|---|
| 379 | var sfactor = s * 0.000001; |
|---|
| 380 | |
|---|
| 381 | var RadY_Rot = (Y_Rot / 3600) * (Pi / 180); |
|---|
| 382 | |
|---|
| 383 | var RadZ_Rot = (Z_Rot / 3600) * (Pi / 180); |
|---|
| 384 | |
|---|
| 385 | //Compute transformed X coord |
|---|
| 386 | return (X + (X * sfactor) - (Y * RadZ_Rot) + (Z * RadY_Rot) + DX); |
|---|
| 387 | }, |
|---|
| 388 | |
|---|
| 389 | |
|---|
| 390 | Helmert_Y: function(X,Y,Z,DY,X_Rot,Z_Rot,s) { |
|---|
| 391 | // Computed Helmert transformed Y coordinate. |
|---|
| 392 | // Input: - _ |
|---|
| 393 | // cartesian XYZ coords (X,Y,Z), Y translation (DY) all in meters ; _ |
|---|
| 394 | // X and Z rotations in seconds of arc (X_Rot, Z_Rot) and scale in ppm (s). |
|---|
| 395 | |
|---|
| 396 | // Convert rotations to radians and ppm scale to a factor |
|---|
| 397 | var Pi = 3.14159265358979; |
|---|
| 398 | var sfactor = s * 0.000001; |
|---|
| 399 | var RadX_Rot = (X_Rot / 3600) * (Pi / 180); |
|---|
| 400 | var RadZ_Rot = (Z_Rot / 3600) * (Pi / 180); |
|---|
| 401 | |
|---|
| 402 | // Compute transformed Y coord |
|---|
| 403 | return (X * RadZ_Rot) + Y + (Y * sfactor) - (Z * RadX_Rot) + DY; |
|---|
| 404 | }, |
|---|
| 405 | |
|---|
| 406 | |
|---|
| 407 | |
|---|
| 408 | Helmert_Z: function(X, Y, Z, DZ, X_Rot, Y_Rot, s) { |
|---|
| 409 | // Computed Helmert transformed Z coordinate. |
|---|
| 410 | // Input: - _ |
|---|
| 411 | // cartesian XYZ coords (X,Y,Z), Z translation (DZ) all in meters ; _ |
|---|
| 412 | // X and Y rotations in seconds of arc (X_Rot, Y_Rot) and scale in ppm (s). |
|---|
| 413 | // |
|---|
| 414 | // Convert rotations to radians and ppm scale to a factor |
|---|
| 415 | var Pi = 3.14159265358979; |
|---|
| 416 | var sfactor = s * 0.000001; |
|---|
| 417 | var RadX_Rot = (X_Rot / 3600) * (Pi / 180); |
|---|
| 418 | var RadY_Rot = (Y_Rot / 3600) * (Pi / 180); |
|---|
| 419 | |
|---|
| 420 | // Compute transformed Z coord |
|---|
| 421 | return (-1 * X * RadY_Rot) + (Y * RadX_Rot) + Z + (Z * sfactor) + DZ; |
|---|
| 422 | } , |
|---|
| 423 | |
|---|
| 424 | XYZ_to_Lat: function(X, Y, Z, a, b) { |
|---|
| 425 | // Convert XYZ to Latitude (PHI) in Dec Degrees. |
|---|
| 426 | // Input: - _ |
|---|
| 427 | // XYZ cartesian coords (X,Y,Z) and ellipsoid axis dimensions (a & b), all in meters. |
|---|
| 428 | |
|---|
| 429 | var RootXYSqr = Math.sqrt(Math.pow(X,2) + Math.pow(Y,2)); |
|---|
| 430 | var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); |
|---|
| 431 | var PHI1 = Math.atan2(Z , (RootXYSqr * (1 - e2)) ); |
|---|
| 432 | |
|---|
| 433 | var PHI = OpenLayers.Projection.OS.Iterate_XYZ_to_Lat(a, e2, PHI1, Z, RootXYSqr); |
|---|
| 434 | |
|---|
| 435 | var Pi = 3.14159265358979; |
|---|
| 436 | |
|---|
| 437 | return PHI * (180 / Pi); |
|---|
| 438 | }, |
|---|
| 439 | |
|---|
| 440 | |
|---|
| 441 | Iterate_XYZ_to_Lat: function(a, e2, PHI1, Z, RootXYSqr) { |
|---|
| 442 | // Iteratively computes Latitude (PHI). |
|---|
| 443 | // Input: - _ |
|---|
| 444 | // ellipsoid semi major axis (a) in meters; _ |
|---|
| 445 | // eta squared (e2); _ |
|---|
| 446 | // estimated value for latitude (PHI1) in radians; _ |
|---|
| 447 | // cartesian Z coordinate (Z) in meters; _ |
|---|
| 448 | // RootXYSqr computed from X & Y in meters. |
|---|
| 449 | |
|---|
| 450 | |
|---|
| 451 | var V = a / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2)))); |
|---|
| 452 | var PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr); |
|---|
| 453 | |
|---|
| 454 | while (Math.abs(PHI1 - PHI2) > 0.000000001) { |
|---|
| 455 | PHI1 = PHI2; |
|---|
| 456 | V = a / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2)))); |
|---|
| 457 | PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr); |
|---|
| 458 | } |
|---|
| 459 | |
|---|
| 460 | return PHI2; |
|---|
| 461 | }, |
|---|
| 462 | |
|---|
| 463 | |
|---|
| 464 | XYZ_to_Long: function (X, Y) { |
|---|
| 465 | // Convert XYZ to Longitude (LAM) in Dec Degrees. |
|---|
| 466 | // Input: - _ |
|---|
| 467 | // X and Y cartesian coords in meters. |
|---|
| 468 | |
|---|
| 469 | var Pi = 3.14159265358979; |
|---|
| 470 | return Math.atan2(Y , X) * (180 / Pi); |
|---|
| 471 | }, |
|---|
| 472 | |
|---|
| 473 | Marc: function (bf0, n, PHI0, PHI) { |
|---|
| 474 | //Compute meridional arc. |
|---|
| 475 | //Input: - _ |
|---|
| 476 | // ellipsoid semi major axis multiplied by central meridian scale factor (bf0) in meters; _ |
|---|
| 477 | // n (computed from a, b and f0); _ |
|---|
| 478 | // lat of false origin (PHI0) and initial or final latitude of point (PHI) IN RADIANS. |
|---|
| 479 | |
|---|
| 480 | 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 |
|---|
| 481 | ) * 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))))); |
|---|
| 482 | }, |
|---|
| 483 | |
|---|
| 484 | Lat_Long_to_East: function (PHI, LAM, a, b, e0, f0, PHI0, LAM0) { |
|---|
| 485 | //Project Latitude and longitude to Transverse Mercator eastings. |
|---|
| 486 | //Input: - _ |
|---|
| 487 | // Latitude (PHI) and Longitude (LAM) in decimal degrees; _ |
|---|
| 488 | // ellipsoid axis dimensions (a & b) in meters; _ |
|---|
| 489 | // eastings of false origin (e0) in meters; _ |
|---|
| 490 | // central meridian scale factor (f0); _ |
|---|
| 491 | // latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees. |
|---|
| 492 | |
|---|
| 493 | // Convert angle measures to radians |
|---|
| 494 | var Pi = 3.14159265358979; |
|---|
| 495 | var RadPHI = PHI * (Pi / 180); |
|---|
| 496 | var RadLAM = LAM * (Pi / 180); |
|---|
| 497 | var RadPHI0 = PHI0 * (Pi / 180); |
|---|
| 498 | var RadLAM0 = LAM0 * (Pi / 180); |
|---|
| 499 | |
|---|
| 500 | var af0 = a * f0; |
|---|
| 501 | var bf0 = b * f0; |
|---|
| 502 | var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); |
|---|
| 503 | var n = (af0 - bf0) / (af0 + bf0); |
|---|
| 504 | var nu = af0 / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(RadPHI),2) ))); |
|---|
| 505 | var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(RadPHI),2) )); |
|---|
| 506 | var eta2 = (nu / rho) - 1; |
|---|
| 507 | var p = RadLAM - RadLAM0; |
|---|
| 508 | |
|---|
| 509 | var IV = nu * (Math.cos(RadPHI)); |
|---|
| 510 | var V = (nu / 6) * ( Math.pow(Math.cos(RadPHI),3)) * ((nu / rho) - (Math.pow(Math.tan(RadPHI),2))); |
|---|
| 511 | 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)); |
|---|
| 512 | |
|---|
| 513 | return e0 + (p * IV) + (Math.pow(p,3) * V) + (Math.pow(p,5) * VI); |
|---|
| 514 | }, |
|---|
| 515 | |
|---|
| 516 | Lat_Long_to_North: function (PHI, LAM, a, b, e0, n0, f0, PHI0, LAM0) { |
|---|
| 517 | // Project Latitude and longitude to Transverse Mercator northings |
|---|
| 518 | // Input: - _ |
|---|
| 519 | // Latitude (PHI) and Longitude (LAM) in decimal degrees; _ |
|---|
| 520 | // ellipsoid axis dimensions (a & b) in meters; _ |
|---|
| 521 | // eastings (e0) and northings (n0) of false origin in meters; _ |
|---|
| 522 | // central meridian scale factor (f0); _ |
|---|
| 523 | // latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees. |
|---|
| 524 | |
|---|
| 525 | // REQUIRES THE "Marc" FUNCTION |
|---|
| 526 | |
|---|
| 527 | // Convert angle measures to radians |
|---|
| 528 | var Pi = 3.14159265358979; |
|---|
| 529 | var RadPHI = PHI * (Pi / 180); |
|---|
| 530 | var RadLAM = LAM * (Pi / 180); |
|---|
| 531 | var RadPHI0 = PHI0 * (Pi / 180); |
|---|
| 532 | var RadLAM0 = LAM0 * (Pi / 180); |
|---|
| 533 | |
|---|
| 534 | var af0 = a * f0; |
|---|
| 535 | var bf0 = b * f0; |
|---|
| 536 | var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); |
|---|
| 537 | var n = (af0 - bf0) / (af0 + bf0); |
|---|
| 538 | var nu = af0 / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(RadPHI),2)))); |
|---|
| 539 | var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(RadPHI),2))); |
|---|
| 540 | var eta2 = (nu / rho) - 1; |
|---|
| 541 | var p = RadLAM - RadLAM0; |
|---|
| 542 | var M = OpenLayers.Projection.OS.Marc(bf0, n, RadPHI0, RadPHI); |
|---|
| 543 | |
|---|
| 544 | var I = M + n0; |
|---|
| 545 | var II = (nu / 2) * (Math.sin(RadPHI)) * (Math.cos(RadPHI)); |
|---|
| 546 | var III = ((nu / 24) * (Math.sin(RadPHI)) * (Math.pow(Math.cos(RadPHI),3))) * (5 - (Math.pow(Math.tan(RadPHI),2)) + (9 * eta2)); |
|---|
| 547 | 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))); |
|---|
| 548 | |
|---|
| 549 | return I + (Math.pow(p,2) * II) + (Math.pow(p,4) * III) + (Math.pow(p,6) * IIIA); |
|---|
| 550 | } |
|---|
| 551 | |
|---|
| 552 | }; |
|---|
| 553 | |
|---|
| 554 | /** |
|---|
| 555 | * Note: Two transforms declared |
|---|
| 556 | * Transforms from EPSG:4326 to EPSG:27700 and from EPSG:27700 to EPSG:4326 |
|---|
| 557 | * are set by this class. |
|---|
| 558 | */ |
|---|
| 559 | OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:27700", |
|---|
| 560 | OpenLayers.Projection.OS.projectForwardBritish); |
|---|
| 561 | OpenLayers.Projection.addTransform("EPSG:27700", "EPSG:4326", |
|---|
| 562 | OpenLayers.Projection.OS.projectInverseBritish); |
|---|
| 563 | OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:27700", |
|---|
| 564 | OpenLayers.Projection.OS.goog2osgb); |
|---|
| 565 | OpenLayers.Projection.addTransform("EPSG:27700", "EPSG:900913", |
|---|
| 566 | OpenLayers.Projection.OS.osgb2goog); |
|---|
| 567 | |
|---|