/// <summary> /// Get map from google maps and it on a frame /// </summary> public override void Draw(Graphics grfx, float time) { if (this.map == null) { GetBoundSize();//TODO: remove this dependancy GPSBox box = Gps.GetBox(); var southWest = new GPSCoord(box.Position.Longitude, box.Position.Latitude, 0); var northEast = new GPSCoord(box.Position.Longitude + box.Size.Longitude, box.Position.Latitude + box.Size.Latitude, 0); int curentZoomLevel = this.GetBoundsZoomLevel(northEast, southWest, WidgetSize); int curentRouteHeightPixels = UnscaledMapImageHeight(box.Size.Latitude, curentZoomLevel); double currentRatio = (double)WidgetSize.Height / curentRouteHeightPixels; int nextZoomLevel = curentZoomLevel + 1; int nextRouteHeightPixels = UnscaledMapImageHeight(box.Size.Latitude, nextZoomLevel); double nextRatio = (double)WidgetSize.Height / nextRouteHeightPixels; var nextRouteWidth = (int)Math.Floor(WidgetSize.Width / nextRatio); double minDeltaRatio; int chosenHeight, chosenWidth; if (nextRouteHeightPixels <= 640 && nextRouteWidth <= 640) { double currentDelta = Math.Abs(1 - currentRatio); double nextDelta = Math.Abs(1 - nextRatio); if (currentDelta < nextDelta) { minDeltaRatio = currentRatio; chosenHeight = curentRouteHeightPixels; chosenWidth = (int)(WidgetSize.Width / currentRatio); } else { minDeltaRatio = nextRatio; chosenHeight = nextRouteHeightPixels; chosenWidth = nextRouteWidth; } } else { minDeltaRatio = currentRatio; chosenHeight = curentRouteHeightPixels; chosenWidth = (int)(WidgetSize.Width / currentRatio); } var chosenSize = new Point(chosenWidth, chosenHeight); var widgetSize = new Point(WidgetSize.Width, WidgetSize.Height); this.map = GetMap(southWest, northEast, chosenSize); this.map = ImageEffects.ResizeImage(this.map, WidgetSize.Width, WidgetSize.Height); this.map = ImageEffects.ChangeOpacity(this.map, ProjectSettings.GetSettings().MapOpacity); } grfx.DrawImage(this.map, PecentToPixels(ProjectSettings.GetSettings().TrackPostion)); }
//source http://stackoverflow.com/questions/6048975/google-maps-v3-how-to-calculate-the-zoom-level-for-a-given-bounds private int GetBoundsZoomLevel(GPSCoord northEast, GPSCoord southWest, Size mapDim) { var worldDim = new Size(256, 256); int zoomMax = 21; double latFraction = (LatRad(northEast.Latitude) - LatRad(southWest.Latitude)) / Math.PI; double lngDiff = northEast.Longitude - southWest.Longitude; double lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360; int latZoom = Zoom(mapDim.Height, worldDim.Height, latFraction); int lngZoom = Zoom(mapDim.Width, worldDim.Width, lngFraction); return new[] { latZoom, lngZoom, zoomMax }.Min();//Math.Min(); }
private Bitmap GetMap(GPSCoord southWest, GPSCoord northEast, Point imageSize) { //GPSBox box = Gps.GetBox(); var webClient = new WebClient(); string path = @"http://maps.googleapis.com/maps/api/staticmap?size="// TODO max height=640, max width=640 + imageSize.X + 'x' + imageSize.Y +//+10 "&path=color:0x00000000|weight:5|" + (southWest.Latitude - 0.00).ToString() + "," + (southWest.Longitude - 0.00).ToString() + "|" + (northEast.Latitude).ToString() + ',' + (northEast.Longitude).ToString() + "+%20&sensor=false"; try { this.map = new Bitmap(webClient.OpenRead(path)); } catch (WebException) { throw new WebException("Could not load google map"); } return this.map; }
public void Update(List<GPSPoint> pts) { double maxLong = double.MinValue; double maxLat = double.MinValue; double maxEle = double.MinValue; double minLong = double.MaxValue; double minLat = double.MaxValue; double minEle = double.MaxValue; var settigs = ProjectSettings.GetSettings(); // trim track if (settigs.TrackEnd == 0) { settigs.TrackEnd = pts[pts.Count - 1].Time; } int trackStartPos = pts.FindIndex(0, p => p.Time >= settigs.TrackStart); // trackStartPos==-1 && trackEndPos==0 we have no coords that overlap the movie if (trackStartPos == -1) { trackStartPos = 0; } int trackEndPos = pts.FindIndex(trackStartPos, p => p.Time > settigs.TrackEnd); if (trackEndPos == -1) { trackEndPos = pts.Count - 1; } pts.RemoveRange(0, trackStartPos); trackEndPos = trackEndPos - trackStartPos; pts.RemoveRange(trackEndPos, pts.Count - trackEndPos); // TODO: lists are fast enough this.gpsPoints = new GPSPoint[pts.Count]; // we need an array rather than list for faster access if (this.gpsPoints.Length == 0) { throw new EmptyTrackException("The generated track is empty! Try the default sync settings or another track file."); } int n = 0; foreach (GPSPoint point in pts) { // coppy to array this.gpsPoints[n] = point; n++; // find BoundingBox valuse maxLong = Math.Max(point.Longitude, maxLong); maxLat = Math.Max(point.Latitude, maxLat); maxEle = Math.Max(point.Elevation, maxEle); minLong = Math.Min(point.Longitude, minLong); minLat = Math.Min(point.Latitude, minLat); minEle = Math.Min(point.Elevation, minEle); } GPSCoord boundingBoxPosition = new GPSCoord(minLong, minLat, minEle); GPSCoord boundingBoxSize = new GPSCoord(maxLong - minLong, maxLat - minLat, maxEle - minEle); this.boundingBox = new GPSBox(boundingBoxPosition, boundingBoxSize); // for drawing maps LongtitudeCorrectionScale = Math.Cos((Math.PI / 180) * (maxLat + minLat) / 2); // distances from start point double distanceSum = 0; for (int i = 1; i < this.gpsPoints.Length; i++) { distanceSum += this.gpsPoints[i].DistanceFromPoint(this.gpsPoints[i - 1]); this.gpsPoints[i].Distance = distanceSum; } }
// converts a GPS coordinate to pixel coordinate // size and return value are in pixels public PointF ToPixelCoordinate(GPSCoord pt, SizeF size, int border = 0) { double ratio = size.Height / this.boundingBox.Size.Latitude; return new PointF( (float)((pt.Longitude - this.boundingBox.Position.Longitude) * ratio * LongtitudeCorrectionScale) + ((float)border) / 2, size.Height - (float)((pt.Latitude - this.boundingBox.Position.Latitude) * ratio) + ((float)border) / 2); }