// temporary holding place for polyline and associated functions // most basicest class to represent an x-y point function Point(x,y) { this.x = x; this.y = y; } // class to represent a bounding box // min and max must be LatLonPoints function LatLonBounds(min,max) { this.min = min; this.max = max; } LatLonBounds.prototype.contains = function(point) { return (point.lat < max.lat && point.lon < max.lon && point.lat > min.lat && point.lon > min.lon); } // get back a LatLonBounds object with min and max LatLonPoint objects for the current map Mapstraction.prototype.getLatLonBounds = function() { var bounds = undefined; switch (this.api) { case 'yahoo': var bds = this.map.getBoundsLatLon(); bounds = new LatLonBounds(new LatLonPoint(bds.LatMin,bds.LonMin),new LatLonPoint(bds.LatMax,bds.LonMax)); break; case 'google': var bds = this.map.getBounds(); var sw = bds.getSouthWest(); var ne = bds.getNorthEast(); bounds = new LatLonBounds(new LatLonPoint(sw.lat(),sw.lon()),new LatLonPoint(ne.lat(),ne.lon())); break; case 'microsoft': bounds = new LatLonBounds(new LatLonPoint(this.map.latlongRect.Southwest.Latitude,this.map.latlongRect.Southwest.Longitude), new LatLonPoint(this.map.latlongRect.Northeast.Latitude,this.map.latlongRect.Northeast.Longitude)); break; default: alert(this.api + ' not supported by Mapstraction.getLatLonBounds'); } return bounds; } // Mercator functions "borrowed" from http://mapnut.com/testzoom.html (Yahoo-specific) and adapted to Mapstraction // TODO: check licensing/copyright/permissions? // get the number of degrees per pixel at the equator for the given Mapstraction zoom Mapstraction.prototype.degreesPerPixelEquator = function(zoom) { // Each tile image in supported platforms is 256 pixels wide. // At Mapstraction zoom 1 the world is 2 tiles wide (as of 28 May 2006) // Therefore, the equator is 360/256*2^zoom degrees per pixel. return 360.0/(256 * Math.pow(2.0,zoom)); } // return "projected latitude" in degrees Mapstraction.prototype.mercatorProjectY = function(latitude) { var latradians = latitude * Math.PI / 180.0; var yProjradians = Math.log((1 + Math.sin(latradians))/(1 - Math.sin(latradians))) / 2.0; return (yProjradians * 180.0 / Math.PI); } // return latitude (from "projected latitude") in degrees Mapstraction.prototype.inverseMercatorProjectY = function(yProj) { var yProjradians = yProj * Math.PI /180.0; var latradians = 2 * Math.atan(Math.exp(yProjradians)) - Math.PI / 2; return (latradians * 180.0 / Math.PI); } // LatLonPoint -> local Point in the current div Mapstraction.prototype.mercatorProject = function(point) { // absolute x,y of given point var givenXY = absProject(point,map.getZoom()); // absolute x,y of top left map corner var bounds = map.getLatLonBounds(); // calculate absolute x-y of northwest bound var cornerXY = absproject(new LatLonPoint(bounds.max.lat,bounds.min.lon), map.getZoom()); // return relative x-y return new Point(givenXY.x-cornerXY.x,cornerXY.y-givenXY.y); } // LatLonPoint -> absolute Point on the whole map Mapstraction.prototype.absMercatorProject = function(point,zoom) { var sc = degreesPerPixelEquator(zoom); var x = (point.lon + 180.0) / sc; var y = (mercatorProjectY(point.lat) + 90.0) / sc; return new Point(Math.round(x),Math.round(y)); } // Polyline functions until Yahoo releases polylines... Gg has their own (including SVG stuff), and MS have their own now (dunno about compatibility though) Mapstraction.prototype.addPolyLine = function(polyline) { switch (this.api) { case 'yahoo': if (!this.polylines) { this.polylines = []; } this.polylines.push(polyline); var themap = this; YEvent.Capture(this, EventsList.changeZoom, function() { polyline.redraw(themap); } ); polyline.redraw(this); break; case 'google': case 'microsoft': } } Mapstraction.prototype.removePolyLine = function(polyline) { switch (this.api) { case 'yahoo': // TODO: what's the opposite of YEvent.capture? // remove the custom overlay if (polyline.overlay) { this.removeOverlay(polyline.overlay); polyline.overlay = null; } break; } } Mapstraction.prototype.clearPolyLines = function() { switch (this.api) { case 'yahoo': for (var i = this.polylines.length-1; i >= 0; i--) { this.removePolyLine(this.polylines[i]); } this.polylines = []; break; } } // // Make a PolyLine object // function PolyLine(points) { if (!points) { this.points = []; } else { this.points = points; } } // TODO: Polyline.prototype.addPoint etc. PolyLine.prototype.redraw = function(_map) { // no point drawing an un-line if (!this.points || !this.points.length || this.points.length < 2) { return; } // make a transformed polyline this.tpoly = []; // project into coord space (requires ymercator.js) for (var i = 0; i < this.points.length; i++) { this.tpoly[i] = project(this.points[i],_map); } // get extents of transformed coords this.minX = this.tpoly[0].x; this.minY = this.tpoly[0].y; this.maxX = this.tpoly[0].x; this.maxY = this.tpoly[0].y; for (var i = 0; i < this.tpoly.length; i++) { this.minX = Math.min(this.tpoly[i].x,this.minX); this.minY = Math.min(this.tpoly[i].y,this.minY); this.maxX = Math.max(this.tpoly[i].x,this.maxX); this.maxY = Math.max(this.tpoly[i].y,this.maxY); } // remove any existing overlay if (this.overlay) { _map.removeOverlay(this.overlay); this.overlay = null; } // create a custom overlay at the lat lon of the top left point this.overlay = new YCustomOverlay(_map.convertXYLatLon(new YCoordPoint(this.minX, this.minY))); _map.addOverlay(this.overlay); if(this.graphic) { this.graphic = null; } // canvas version: if (window.CanvasRenderingContext2D) { // make a this.graphic = YUtility.createNode('canvas','poly'); // TODO uid, not 'poly'? // kick start Explorer Canvas (NB: excanvas.js has been modified slightly for this demo!) if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(this.graphic); } } // image version: else { this.graphic = YUtility.createNode('img','poly'); // TODO uid, not 'poly'? } // set size (belt and braces) this.graphic.width = Math.round(this.maxX-this.minX); this.graphic.height = Math.round(this.maxY-this.minY); this.graphic.style.width = this.graphic.width + 'px'; this.graphic.style.height = this.graphic.height + 'px'; // set position and zindex this.graphic.style.position = 'absolute'; this.graphic.style.zIndex = '-1'; // canvas version: if (window.CanvasRenderingContext2D) { this.ctx = this.graphic.getContext("2d"); this.ctx.clearRect(0, 0, this.graphic.width, this.graphic.height); // set line style this.ctx.lineWidth = "3"; this.ctx.strokeStyle = "rgb(0, 0, 255)"; // draw poly this.ctx.translate(-this.minX, -this.minY); this.ctx.beginPath(); this.ctx.moveTo(this.tpoly[0].x, this.tpoly[0].y); for(var i = 1; i < this.tpoly.length; i++) { this.ctx.lineTo(this.tpoly[i].x, this.tpoly[i].y); } this.ctx.stroke(); } // image version: else { // draw poly this.pointString = (this.tpoly[0].x-this.minX) + ',' + (this.tpoly[0].y-this.minY); // no leading comma for(var i = 1; i < this.tpoly.length; i++) { this.pointString += ',' + (this.tpoly[i].x-this.minX) + ',' + (this.tpoly[i].y-this.minY); } this.graphic.src = 'polyline.php?width='+this.graphic.width+'&height='+this.graphic.height+'&points='+this.pointString; } YUtility.appendNode(this.overlay,this.graphic); }