function CoverageMapType() { this.start = '2014-04-14'; this.end = '2200-01-01'; this.station = ""; this.source = "max"; this.colours = []; this.colour = ''; } var id = 0; var cache = {}; var cacheUTM = {}; CoverageMapType.prototype.setStation = function(newStation) { this.station = newStation; } CoverageMapType.prototype.setColourScheme = function(_colour) { this.colour = _colour; var s = _colour.split( ':' ); var start = tinycolor( s[1] ); start = start.toRgb(); var end = tinycolor( s[0] ); end = end.toRgb(); console.log( _colour ); console.log( "start:" ); console.log( start ); for (i = 0; i < 25; i++) { var alphablend = 1-(i/24); var c = { r: start.r * alphablend + (1 - alphablend) * end.r, g: start.g * alphablend + (1 - alphablend) * end.g, b: start.b * alphablend + (1 - alphablend) * end.b, a: start.a * alphablend + (1 - alphablend) * end.a }; this.colours[i] = tinycolor(c).toRgbString(); } } CoverageMapType.prototype.setDates = function(_start,_end) { this.start = _start; this.end = _end; } CoverageMapType.prototype.setSource = function(_source) { this.source = _source; } let canvasC = null; CoverageMapType.prototype.canvasFunctionCoverage = function( extent, resolution, pixelRatio, size, // [canvasWidth, canvasHeight], projection ) { if (!canvasC) { canvasC = document.createElement("canvas"); canvasC.setAttribute("id", "canvasCoverage"); } var canvasWidth = size[0], canvasHeight = size[1]; canvasC.setAttribute("width", canvasWidth); canvasC.setAttribute("height", canvasHeight); var contextC = canvasC.getContext("2d"); // erase the canvas before re-drawing contextC.clearRect(0, 0, canvasWidth, canvasHeight); // do nothing if too much out zoom var zoom = map.getView().getZoom(); if ( ( zoom < minZoomLevel && this.source != 'lowres-coverage' ) || ( zoom > maxZoomLevel ) ) { return canvasC; } // determine coordinates corners TopLeft and BottomRight // Canvas extent (larger) is different than map extent // need to compute delta between left-top of map and canvas extent. var mapExtent = map.getView().calculateExtent(map.getSize()) var canvasOrigin = map.getPixelFromCoordinate([extent[0], extent[3]]); var mapOrigin = map.getPixelFromCoordinate([mapExtent[0], mapExtent[3]]); var delta = [ mapOrigin[0]-canvasOrigin[0], mapOrigin[1]-canvasOrigin[1] ]; // var mapOpposite = map.getPixelFromCoordinate([mapExtent[2], mapExtent[1]]); //convert from pixel to xy var xyTL = map.getCoordinateFromPixel([0,0]); var xyBR = map.getCoordinateFromPixel([canvasWidth,canvasHeight]); // convert from xy to lat/long var latlonTL = ol.proj.transform(xyTL, 'EPSG:3857', 'EPSG:4326'); var latlonBR = ol.proj.transform(xyBR, 'EPSG:3857', 'EPSG:4326'); // plot a square that has been fetched // each item is ~1 km square function plotRef(json) { // convert from lat/long to canvas pixels var toScreen = function(latlonPoint) { var xyPoint = ol.proj.transform(latlonPoint, 'EPSG:4326', 'EPSG:3857'); var pxPoint = map.getPixelFromCoordinate(xyPoint); return ( [ (pxPoint[0]+delta[0])*pixelRatio, (pxPoint[1]+delta[1])*pixelRatio ] ); } function fillBox(x) { var tl = toScreen([x[0],x[1]]); var br = toScreen([x[2],x[3]]); contextC.fillRect( tl[0], tl[1], br[0] - tl[0], br[1] - tl[1] ); } if ( coverageOverlay.colours.length > 0 && json.p ) { // expand out the compressed data - smaller over the network var points = []; json.p.forEach( function(position) { var data = position.split('/'); var mgrs = json.t + data[0]; points.push( { a: data[1], m: mgrs } ); if ( ! cacheUTM[ mgrs ] ) { cacheUTM[ mgrs ] = inverse( mgrs ); } } ); contextC.save(); contextC.globalAlpha = 1; contextC.lineWidth = 0.2; for( var i = 250, p = 1000000, n = 0; i >= 10; p = i, i-=10, n++ ) { contextC.fillStyle = contextC.strokeStyle = coverageOverlay.colours[ n ]; var t = i/5; points.forEach( function(position) { if ( position.a >= i && position.a < p ) { fillBox( cacheUTM[ position.m ] ); } }); } contextC.restore(); } map.render(); // redraw map after every plotref }; var tiles = {}; // 0.1 deg by 0.1 deg (~11 km square) for( var x = Math.min(latlonTL[0],latlonBR[0]), xm = Math.max(latlonTL[0],latlonBR[0]); x <= xm ;x+= 0.1 ) { for( var y = Math.min(latlonBR[1],latlonTL[1]), ym = Math.max(latlonBR[1],latlonTL[1]); y <= ym; y+= 0.1 ) { tiles[ forward([x,y],1).substr(0,5) ] = 1; } } var source = coverageOverlay.source; var station = coverageOverlay.station; var start = coverageOverlay.start; var end = coverageOverlay.end; // fetch each square Object.keys(tiles).sort().forEach( function(tile) { var cacheKey = tile+source+station+start+end; if ( ! cache[cacheKey] ) { cache[cacheKey] = [ plotRef ]; $.ajax({ type: "GET", url: OgR+"/perl/"+source+"-tile-mgrs.pl", data: { station: station, start: start, end: end, squares: tile}, timeout:20000, cache: true, error: function (xhr, ajaxOptions, thrownError) { }, success: function(json) { cache[cacheKey].forEach( function(x) { x(json); } ); cache[cacheKey] = undefined; } }); } else { cache[cacheKey].push( plotRef ); } }); $(document).ajaxStop(function () { // 0 === $.active }); return canvasC; } function bound(value, opt_min, opt_max) { if (opt_min != null) value = Math.max(value, opt_min); if (opt_max != null) value = Math.min(value, opt_max); return value; } function AmbiguityMapType() { this.ambiguity = false; } AmbiguityMapType.prototype.setAmbiguity = function(_ambiguity) { this.ambiguity = _ambiguity; } let canvasA = null; AmbiguityMapType.prototype.canvasFunctionAmbiguity = function( extent, resolution, pixelRatio, size, // [canvasWidth, canvasHeight], projection ) { if (!canvasA) { canvasA = document.createElement("canvas"); canvasA.setAttribute("id", "canvasAmbiguity"); } var canvasWidth = size[0], canvasHeight = size[1]; canvasA.setAttribute("width", canvasWidth); canvasA.setAttribute("height", canvasHeight); var contextA = canvasA.getContext("2d"); // erase the canvas before re-drawing contextA.clearRect(0, 0, canvasWidth, canvasHeight); // do nothing if too much out zoom (<7) var zoom = map.getView().getZoom(); if ( zoom < 7 && this.source != 'lowres-coverage' ) { return canvasA; } // determine coordinates corners TopLeft and BottomRight // Canvas extent (larger) is different than map extent // need to compute delta between left-top of map and canvas extent. var mapExtent = map.getView().calculateExtent(map.getSize()) var canvasOrigin = map.getPixelFromCoordinate([extent[0], extent[3]]); var mapOrigin = map.getPixelFromCoordinate([mapExtent[0], mapExtent[3]]); var delta = [mapOrigin[0]-canvasOrigin[0], mapOrigin[1]-canvasOrigin[1]] // var mapOpposite = map.getPixelFromCoordinate([mapExtent[2], mapExtent[1]]); //convert from pixel to xy var xyTL = map.getCoordinateFromPixel([0,0]); var xyBR = map.getCoordinateFromPixel([canvasWidth,canvasHeight]); // convert from xy to lat/long var latlonTL = ol.proj.transform(xyTL, 'EPSG:3857', 'EPSG:4326'); var latlonBR = ol.proj.transform(xyBR, 'EPSG:3857', 'EPSG:4326'); // TBD for V4, draw squares in transition zone properly instead of limiting to 45 // draw ambiguity if selected and if latitude > 45 deg /* if ( ambiguity && latlonTL[1] > 45 && latlonBR[1] > 45 )*/ { // convert from lat/long to canvas pixels var toScreen = function(latlonPoint) { var xyPoint = ol.proj.transform(latlonPoint, 'EPSG:4326', 'EPSG:3857'); var pxPoint = map.getPixelFromCoordinate(xyPoint); return ( [ (pxPoint[0]+delta[0])*pixelRatio, (pxPoint[1]+delta[1])*pixelRatio ] ); } var shiftBits = 7; // var truncBits = 16; // V4 var truncBits = 19; // V5 var scaleBits = 1e7/(1<<(shiftBits+truncBits)); // lets draw the lines; horizontal first then vertical contextA.save(); contextA.strokeStyle = 'red'; for( var t = (latlonBR[1] * scaleBits)|0, r = ((latlonTL[1] * scaleBits)|0)+1; t <= r; t++) { var s = toScreen( [ latlonTL[0], t / scaleBits ] ); var f = toScreen( [ latlonBR[0], t / scaleBits ] ); contextA.beginPath(); contextA.moveTo(s[0],s[1]); contextA.lineTo(f[0],f[1]); contextA.stroke(); } // var shiftBits = (( (latlonTL[1] <= 45) && (latlonTL[1] >= -45) ? 7 : 8) ); // V4 var shiftBits = 7; // V5 // var truncBits = 16; // V4 var truncBits = 20; // V5 var scaleBits = 1e7/(1<<(shiftBits+truncBits)); for( var t = (latlonTL[0] * scaleBits)|0, r = ((latlonBR[0] * scaleBits)|0)+1; t <= r; t++) { var s = toScreen( [ t / scaleBits, latlonTL[1] ] ); var f = toScreen( [ t / scaleBits, latlonBR[1] ] ); contextA.beginPath(); contextA.moveTo(s[0],s[1]); contextA.lineTo(f[0],f[1]); contextA.stroke(); } contextA.restore(); } return canvasA; }