public QuadKey(int x, int y, int zoomLevel, Layer layer) { this = new QuadKey(); ZoomLevel = zoomLevel; X = x; Y = y; Layer = layer; }
public QuadKey(string quadKey) { int num; int num2; int num3; Layer layer; this = new QuadKey(); QuadKeyToQuadPixel(quadKey, out num, out num2, out num3, out layer); ZoomLevel = num3; X = num; Y = num2; Layer = layer; }
public static Uri GetUri(QuadKey key) { return GetUri(key.X, key.Y, key.ZoomLevel, key.Layer); }
/// <summary> /// Determines whether the specified <see cref="QuadKey" /> is within the valid range. /// </summary> private bool IsValidKey(QuadKey key) { var x = key.X; var y = key.Y; if (x < 0 || y < 0) { return false; } var tileCount = GetTileCount(key.ZoomLevel); return x < tileCount && y < tileCount; }
/// <summary> /// Calculates a new <see cref="Point" /> represents where the specified <see cref="QuadKey" /> is in the map. /// </summary> private Point GetViewPortPoint(QuadKey key) { var x = key.X; var y = key.Y; var zoomLevel = key.ZoomLevel; var tileDimension = AbsoluteTileDimension*_tileScale; var tileCount = GetTileCount(zoomLevel); var tileNumberToGeoCenter = tileCount/2; var modifierX = x >= tileNumberToGeoCenter ? 1 : -1; var modifierY = y >= tileNumberToGeoCenter ? 1 : -1; var xNumberToGeoCenter = Math.Abs(x - tileNumberToGeoCenter); var yNumberToGeoCenter = Math.Abs(y - tileNumberToGeoCenter); var geoCenterPoint = Map.LocationToViewportPoint(_centerGeoCoordinate); var geoCenterPointX = geoCenterPoint.X; var geoCenterPointY = geoCenterPoint.Y; var tilePointX = geoCenterPointX + (tileDimension*xNumberToGeoCenter*modifierX); var tilePointY = geoCenterPointY + (tileDimension*yNumberToGeoCenter*modifierY); var tilePoint = new Point(tilePointX, tilePointY); return tilePoint; }
/// <summary> /// Calculates a new <see cref="QuadKey" /> based on the old key and the differences between the X count and Y count. /// </summary> private QuadKey GetNewKey(QuadKey oldKey, int diffX, int diffY) { var x = oldKey.X; var y = oldKey.Y; var zoomLevel = oldKey.ZoomLevel; var tileCount = GetTileCount(zoomLevel); var newX = x + diffX; if (newX < 0) { newX = tileCount + x + diffX; } else if (newX >= tileCount) { newX = diffX - (tileCount - x); } var newY = y + diffY; return new QuadKey(newX, newY, zoomLevel, oldKey.Layer); }
/// <summary> /// Gets the image where the specified <see cref="QuadKey" /> is representing. /// </summary> private void GetImage(QuadKey key, Action<Stream> callback) { var cachedKeys = GetCachedKeys(key.ZoomLevel); // Load the image from storage if it is already cached. if (cachedKeys.Contains(key)) { foreach (var cache in _tileImageCache.Where(cache => cache.Key == key)) { callback(cache.Value); return; } var file = string.Concat(OfflineTileImagePrefix, key.Key); Stream stream = null; try { stream = _fileStore.OpenFile(file, FileMode.Open); _tileImageCache.Enqueue(new KeyValuePair<QuadKey, Stream>(key, stream)); } catch {} finally { callback(stream); } return; } // Download and store the image. try { var uri = TileSource.GetUri(key); var request = WebRequest.Create(uri); request.BeginGetResponse(result => { Stream stream = null; try { var file = OfflineTileImagePrefix + key.Key; using (var response = request.EndGetResponse(result)) { stream = response.GetResponseStream(); using (var fileStream = _fileStore.CreateFile(file)) { var bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); fileStream.Write(bytes, 0, bytes.Length); cachedKeys.Add(key); _tileImageCache.Enqueue(new KeyValuePair<QuadKey, Stream>(key, stream)); } } } catch {} finally { UIThread.InvokeAsync(() => callback(stream)); } }, null); } catch { callback(null); } }
/// <summary> /// Updates the geo-location and optionally the image of the specified tile based on the given key. /// </summary> private void UpdateTile(Pushpin tile, QuadKey key, bool updateImage = true) { tile.Tag = key; var brush = ((ImageBrush) tile.Background); brush.ImageSource = null; if (!IsValidKey(key)) { return; } var newPoint = GetViewPortPoint(key); var newLocation = Map.ViewportPointToLocation(newPoint); tile.Location = newLocation; if (!updateImage) { return; } GetImage(key, stream => { // Only continue updating the image source if the key attached to the tile is still the same key. if ((QuadKey) tile.Tag != key) { return; } if (stream == null) { return; } var source = (BitmapImage) brush.ImageSource; if (source == null) { brush.ImageSource = source = new BitmapImage(); } source.SetSource(stream); }); }
/// <summary> /// Rearranges all offline tiles and updates their image according to the current location, zoom level and layer. /// </summary> private void RefreshOfflineTiles(Pushpin[,] matrix, Layer layer) { if (_isZooming || !ValidateOfflineZoomLevel()) { return; } _zoomFloor = (int) Map.ZoomLevel; UpdateTileScale(); // Update all tiles if the zoom level has reached a new floor. var centerKey = GetQuadKey(Map.Center, _zoomFloor, layer); // Calculate X index and Y index in the matrix of the center tile. var centerX = _tileMatrixLengthX/2; var centerY = _tileMatrixLengthY/2; // Update location and image of tile pushpins. for (var x = 0; x < _tileMatrixLengthX; x++) { for (var y = 0; y < _tileMatrixLengthY; y++) { // Create the tile pushpin. var tile = matrix[x, y]; // Calculate the differences between this tile's X/Y index and the center tile's X/Y index. var diffX = x - centerX; var diffY = y - centerY; // Calculate the quad key for this current tile. var key = new QuadKey(centerKey.X + diffX, centerKey.Y + diffY, _zoomFloor, layer); // Update this tile with the calculated quad key. UpdateTile(tile, key); } } }