1 if (Garmin == undefined) var Garmin = {}; 2 /** Copyright � 2007 Garmin Ltd. or its subsidiaries. 3 * 4 * Licensed under the Apache License, Version 2.0 (the 'License') 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an 'AS IS' BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * @fileoverview Garmin.MapController Overlays tracks and waypoint data on Google maps. 17 * 18 * @author Jason Holmes jason.holmes.at.garmin.com 19 * @author Bobby Yang bobby.yang.at.garmin.com 20 * @version 1.0 21 */ 22 /** 23 * Accepts Garmin.Series objects and draws them on a Google Map. 24 * 25 * @class Garmin.MapController 26 * @constructor 27 * @param (String) mapString id of element to place map in 28 */ 29 Garmin.MapController = function(mapString){}; //just here for jsdoc 30 Garmin.MapController = Class.create(); 31 Garmin.MapController.prototype = { 32 33 initialize: function(mapString) { 34 this.mapElement = $(mapString); 35 this.usePositionMarker = true; 36 37 this.polylines = new Array(); 38 this.markers = new Array(); 39 this.tracks = new Array(); 40 this.markerIndex = 0; 41 42 this.timeToCheck = false; 43 try { 44 this.map = new GMap2( $(mapString) ); 45 this.map.addControl(new GSmallMapControl()); 46 this.map.addControl(new GMapTypeControl()); 47 new GKeyboardHandler(this.map); 48 } catch (e) { 49 alert("WARNING: application will not function properly with missing Google script element or invalid Google map key. Error: "+e); 50 } 51 window.onUnload = "GUnload()"; 52 }, 53 54 /** Set the center point and zoom level of the map. 55 * @param (Number) Latitude of the center point 56 * @param (Number) Longitude of the center point 57 * @param (Number) Zoom level 58 */ 59 centerAndScale: function(lat, lon, scale) { 60 scale = (scale == null ? 13 : scale); 61 this.map.setCenter(new GLatLng(lat, lon), scale); 62 }, 63 64 /** Draw track on map. 65 * @param (Garmin.Track) The track to draw 66 * @param (String) Color in RGB Hex format, default: "#ff0000" 67 */ 68 drawTrack: function(series, color) { 69 color = (color == null ? "#ff0000" : color); 70 71 // create a smaller version of the whole track 72 // create 300 points or so ... 73 // Problem is that Google Maps dies when you hit near 500 points, so we have to 74 // ensure that we create fewer than that for the track. 75 var drawAt = Math.ceil(series.getSamplesLength()/300); 76 var drawnPoints = new Array(); 77 78 try { 79 // create up to 300 points 80 for(var h = 0; h < series.getSamplesLength(); h += drawAt) { 81 drawnPoints.push(this.createNearestValidLocationPoint(series, h, -1)); 82 } 83 // create the end point 84 drawnPoints.push(this.createNearestValidLocationPoint(series, series.getSamplesLength()-1, -1)); 85 } catch( e ) { 86 alert("GoogleMapControl.drawTrack: " + e.message); 87 } 88 89 if (drawnPoints.length > 0) { 90 //draw the new smaller version 91 var polyline = new GPolyline(drawnPoints, color, 2, .8) 92 try { 93 this.centerAndScale(drawnPoints[0].lat(), drawnPoints[0].lng()); 94 this.map.addOverlay( polyline ); 95 this.addStartFinishMarkers(series); 96 this.bounds = this.findAZoomLevel(drawnPoints); 97 this.setOnBounds( this.bounds ); 98 } catch(e){ alert("GoogleMapControl.drawTrack, IE error on map.addOverlay("+polyline+") err: "+e); } 99 } 100 }, 101 102 /**Creates a GLatLng for the sample in the series closest to the index with a valid location (lat and lon). 103 * @param series - The series to search through. 104 * @param index - The index to start searching from. 105 * @param incDirection - The direction to travel for the search. 106 * @return A GLatLng of the nearest valid location sample found. 107 */ 108 createNearestValidLocationPoint: function(series, index, incDirection) { 109 var sample = series.findNearestValidLocationSample(index, -1); 110 if (sample != null) { 111 var sampleLat = sample.getMeasurement(Garmin.Sample.MEASUREMENT_KEYS.latitude).getValue(); 112 var sampleLon = sample.getMeasurement(Garmin.Sample.MEASUREMENT_KEYS.longitude).getValue(); 113 return new GLatLng(sampleLat, sampleLon); 114 } else { 115 throw new Error("No valid location point in series."); 116 } 117 }, 118 119 /** Draw waypoint on map. 120 * @param (Garmin.Series) series containing a waypoint to add to the map 121 */ 122 drawWaypoint: function(series) { 123 var sample = series.getSample(0); 124 this.centerAndScale(sample.getLatitude(), sample.getLongitude(), 15); 125 this.addMarker(sample.getLatitude(), sample.getLongitude()); 126 }, 127 128 /** Calculates minimum bounding box for an set of points. 129 * @param (Array) The array of points to find a zoom level for 130 */ 131 findAZoomLevel: function(points) { 132 var bounds = new GLatLngBounds(points[0], points[0]); 133 134 for(var i=1; i<points.length-1; i+=3) { 135 bounds.extend(points[i]); 136 } 137 138 return bounds; 139 }, 140 141 /** Check the new dimensions of the map, and determine the bounds of the tracks 142 * Then set the map to zoom to that bound level 143 * @private 144 */ 145 sizeAndSetOnBounds: function() { 146 this.map.checkResize(); 147 this.setOnBounds( this.bounds ); 148 }, 149 150 /** Set the bounding box on the map. 151 * @param (GLatLngBounds) bounding box for the 152 */ 153 setOnBounds: function(bounds) { 154 this.map.setCenter( this.bounds.getCenter(), this.map.getBoundsZoomLevel(this.bounds) ); 155 }, 156 157 /** Add an icon to a point. 158 * @param {Number} latitude of marker 159 * @param {Number} longitude of marker 160 */ 161 addMarker: function(latitude, longitude) { 162 this.addMarkerWithIcon(latitude, longitude, Garmin.MapIcons.getRedIcon()); 163 }, 164 165 /** Adds a marker to the point with the icon specified 166 * @param {Number} latitude of marker 167 * @param {Number} longitude of marker 168 * @param (GIcon) icon to add at the point 169 */ 170 addMarkerWithIcon: function(latitude, longitude, icon) { 171 var gMarker = new GMarker(new GLatLng(latitude, longitude), icon); 172 this.markers.push(gMarker); 173 this.map.addOverlay(gMarker); 174 }, 175 176 /** Add start and finish markers to a track 177 * @param (Garmin.Series) The series to add markers to 178 */ 179 addStartFinishMarkers: function(series) { 180 var firstSample = series.getFirstValidLocationSample(); 181 var lastSample = series.getLastValidLocationSample(); 182 this.addMarkerWithIcon(firstSample.getLatitude(), firstSample.getLongitude(), Garmin.MapIcons.getGreenIcon()); 183 this.addMarkerWithIcon(lastSample.getLatitude(), lastSample.getLongitude(), Garmin.MapIcons.getRedIcon()); 184 }, 185 186 /** String representation of map. 187 * @return (String) 188 */ 189 toString: function() { 190 return "Google Based Map Controller, managing " + this.tracks.length + " track(s)"; 191 } 192 }; 193 194 /** Icons used to mark waypoints and POIs on Google maps. 195 * 196 * @class Garmin.MapIcons 197 * @constructor 198 */ 199 Garmin.MapIcons = function(){}; //just here for jsdoc 200 Garmin.MapIcons = { 201 getRedIcon: function() { 202 var icon = new GIcon(); 203 icon.image = "http://trail.motionbased.com/trail/site/images/marker_red.png"; 204 return Garmin.MapIcons._applyShadowAndStuff(icon); 205 }, 206 207 getGreenIcon: function() { 208 var icon = new GIcon(); 209 icon.image = "http://trail.motionbased.com/trail/site/images/marker_green.png"; 210 return Garmin.MapIcons._applyShadowAndStuff(icon); 211 }, 212 213 getBaseIcon: function() { 214 var baseIcon = new GIcon(); 215 baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png"; 216 baseIcon.iconSize = new GSize(20, 34); 217 baseIcon.shadowSize = new GSize(37, 34); 218 baseIcon.iconAnchor = new GPoint(9, 34); 219 baseIcon.infoWindowAnchor = new GPoint(9, 2); 220 baseIcon.infoShadowAnchor = new GPoint(18, 25); 221 return baseIcon; 222 }, 223 224 _applyShadowAndStuff: function(icon) { 225 icon.iconSize = new GSize(12, 20); 226 icon.shadow = "http://trail.motionbased.com/trail/site/images/marker_shadow.png"; 227 icon.shadowSize = new GSize(22, 20); 228 icon.iconAnchor = new GPoint(6, 20); 229 icon.infoWindowAnchor = new GPoint(5, 1); 230 return icon; 231 } 232 }