/// <summary> /// Adds a new tile. /// </summary> /// <param name="tile"></param> /// <returns></returns> public void Add(Tile tile) { if (tile.Zoom < _range.Zoom && _range.Zoom - tile.Zoom < 3) { // add this tile to all the subtiles. var subTiles = tile.GetSubTiles(_range.Zoom); foreach (var subTile in subTiles) { if (_range.Contains(subTile)) { // ok, this tile is in this range. this.Add(subTile.Id, tile); } } } else if (tile.Zoom > _range.Zoom && tile.Zoom - _range.Zoom < 3) { // find the tile that this subtile belongs to. foreach (var rangedTile in _range) { if (rangedTile.Overlaps(tile)) { // add this this tile here. this.Add(rangedTile.Id, tile); // this tile can only belong in one place. return; } } } if (_range.Contains(tile)) { // this tile is already the correct zoom. this.Add(tile.Id, tile); } }
public void TestTileId() { var tile0 = new Tile(0, 0, 0); Assert.AreEqual(0, tile0.Id); var tile1_0_0 = new Tile(0, 0, 1); Assert.AreEqual(1, tile1_0_0.Id); var tile2_0_0 = new Tile(0, 0, 2); Assert.AreEqual(5, tile2_0_0.Id); var tile3_0_0 = new Tile(0, 0, 3); Assert.AreEqual(5 + 16, tile3_0_0.Id); var tile4_0_0 = new Tile(0, 0, 4); Assert.AreEqual(5 + 16 + 64, tile4_0_0.Id); var tile2_1_1 = new Tile(1, 1, 2); Assert.AreEqual(5 + 1 + 4, tile2_1_1.Id); var tile2_1_1_fromId = new Tile(5 + 1 + 4); Assert.AreEqual(tile2_1_1.Zoom, tile2_1_1_fromId.Zoom); Assert.AreEqual(tile2_1_1.X, tile2_1_1_fromId.X); Assert.AreEqual(tile2_1_1.Y, tile2_1_1_fromId.Y); for (ulong id = 0; id < 1000; id++) { Tile tile = new Tile(id); Assert.AreEqual(id, tile.Id); } }
public void TestTileCreation() { // 51.27056&lon=4.78849 // http://tile.deltamedia.local/tile/16/33639/21862.png Tile tile = new Tile(33639, 21862, 16); Tile tile2 = Tile.CreateAroundLocation(tile.Box.Center, 16); Assert.AreEqual(tile.X, tile2.X); Assert.AreEqual(tile.Y, tile2.Y); Assert.AreEqual(tile.Zoom, tile2.Zoom); }
private static byte[] Download(string url, Tile tile) { // load the tile. url = url.Replace("{z}", tile.Zoom.ToString()) .Replace("{x}", tile.X.ToString()) .Replace("{y}", tile.Y.ToString()); var request = (HttpWebRequest)HttpWebRequest.Create( url); request.Accept = "text/html, image/png, image/jpeg, image/gif, */*"; request.UserAgent = "OsmSharp/4.0"; OsmSharp.Logging.Log.TraceEvent(string.Empty, TraceEventType.Information, "Request tile@" + url); return ReadToEnd(request.GetResponse().GetResponseStream()); }
public void TestTileBox() { Tile tile = new Tile(33639, 21862, 16); for (double longitude = tile.Box.MinLon; longitude < tile.Box.MaxLon; longitude = longitude + tile.Box.DeltaLon / 100) { for (double latitude = tile.Box.MinLat; latitude < tile.Box.MaxLat; latitude = latitude + tile.Box.DeltaLon / 100) { Tile tile2 = Tile.CreateAroundLocation(new GeoCoordinate( latitude, longitude), tile.Zoom); Assert.AreEqual(tile.X, tile2.X); Assert.AreEqual(tile.Y, tile2.Y); Assert.AreEqual(tile.Zoom, tile2.Zoom); } } }
public void TestTileSubtiles() { var tile = new Tile(0, 0, 0); var subtiles = tile.SubTiles; Assert.AreEqual(0, subtiles.XMin); Assert.AreEqual(0, subtiles.YMin); Assert.AreEqual(1, subtiles.XMax); Assert.AreEqual(1, subtiles.YMax); Assert.AreEqual(1, subtiles.Zoom); subtiles = tile.GetSubTiles(1); Assert.AreEqual(0, subtiles.XMin); Assert.AreEqual(0, subtiles.YMin); Assert.AreEqual(1, subtiles.XMax); Assert.AreEqual(1, subtiles.YMax); Assert.AreEqual(1, subtiles.Zoom); subtiles = tile.GetSubTiles(2); Assert.AreEqual(0, subtiles.XMin); Assert.AreEqual(0, subtiles.YMin); Assert.AreEqual(3, subtiles.XMax); Assert.AreEqual(3, subtiles.YMax); Assert.AreEqual(2, subtiles.Zoom); tile = new Tile(1, 1, 1); subtiles = tile.SubTiles; Assert.AreEqual(2, subtiles.XMin); Assert.AreEqual(2, subtiles.YMin); Assert.AreEqual(3, subtiles.XMax); Assert.AreEqual(3, subtiles.YMax); Assert.AreEqual(2, subtiles.Zoom); subtiles = tile.GetSubTiles(2); Assert.AreEqual(2, subtiles.XMin); Assert.AreEqual(2, subtiles.YMin); Assert.AreEqual(3, subtiles.XMax); Assert.AreEqual(3, subtiles.YMax); Assert.AreEqual(2, subtiles.Zoom); subtiles = tile.GetSubTiles(3); Assert.AreEqual(4, subtiles.XMin); Assert.AreEqual(4, subtiles.YMin); Assert.AreEqual(7, subtiles.XMax); Assert.AreEqual(7, subtiles.YMax); Assert.AreEqual(3, subtiles.Zoom); }
public void TestTileOverlaps() { var tile = new Tile(1, 1, 1); Assert.IsTrue(tile.Overlaps(new Tile(1, 1, 1))); Assert.IsTrue(tile.Overlaps(new Tile(3, 3, 2))); Assert.IsTrue(tile.Overlaps(new Tile(8, 8, 4))); Assert.IsFalse(tile.Overlaps(new Tile(0, 0, 3))); Assert.IsFalse(tile.Overlaps(new Tile(0, 0, 4))); }
/// <summary> /// Renders a tile for the given zoom, x and y. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="zoom"></param> /// <param name="type"></param> /// <returns></returns> protected virtual Stream Render(int x, int y, int scale, ushort zoom, ImageType type) { var tile = new Tile(x, y, zoom); var projection = _map.Projection; var zoomFactor = (float)projection.ToZoomFactor(zoom); var center = tile.Box.Center; var sizeInPixels = scale * 256; // get target/image. Bitmap image = null; Graphics target = null; lock(_targetsPerScale) { Tuple<Bitmap, Graphics> tuple; if(!_targetsPerScale.TryGetValue(scale, out tuple)) { // not there yet! // build the target to render to. image = new Bitmap(sizeInPixels, sizeInPixels); target = Graphics.FromImage(image); target.SmoothingMode = SmoothingMode.HighQuality; target.PixelOffsetMode = PixelOffsetMode.HighQuality; target.CompositingQuality = CompositingQuality.HighQuality; target.InterpolationMode = InterpolationMode.HighQualityBicubic; tuple = new Tuple<Bitmap, Graphics>(image, target); _targetsPerScale[scale] = tuple; } target = tuple.Item2; image = tuple.Item1; } var stream = new MemoryStream(); lock (target) { target.FillRectangle(Brushes.White, 0, 0, sizeInPixels, sizeInPixels); var visibleView = _renderer.Create(256, 256, _map, zoomFactor, center, false, true); var renderingView = _renderer.Create(256 * 3, 256 * 3, _map, zoomFactor, center, false, true); _map.ViewChanged(zoomFactor, center, renderingView, renderingView); _renderer.Render(target, _map, visibleView, renderingView, (float)_map.Projection.ToZoomFactor(zoom)); switch (type) { case ImageType.Png: image.Save(stream, ImageFormat.Png); break; case ImageType.Bmp: image.Save(stream, ImageFormat.Bmp); break; case ImageType.Jpeg: image.Save(stream, ImageFormat.Jpeg); break; } } stream.Seek(0, SeekOrigin.Begin); return stream; }
/// <summary> /// Chooses the best tile(s) for the given tile. /// </summary> /// <param name="tile">The tile to search tiles for.</param> /// <param name="higherFirst">Choose tiles with a higher zoom level first, otherwise choose lower first.</param> /// <returns></returns> public IEnumerable<Tile> ChooseBest(Tile tile, bool higherFirst) { var tiles = new List<Tile>(this.Get(tile.Id)); tiles.Sort(delegate(Tile x, Tile y) { return TileRangeIndex.TileWeight(tile.Zoom, x.Zoom, higherFirst).CompareTo( TileRangeIndex.TileWeight(tile.Zoom, y.Zoom, higherFirst)); }); return tiles; }
/// <summary> /// Returns true if this tiles cache contains the given tile. /// </summary> /// <param name="tile">The tile.</param> /// <param name="scale">The scale.</param> /// <param name="type">The type of image.</param> /// <returns></returns> public bool Has(Tile tile, int scale, ImageType type) { var fileInfo = this.GetTileFile(tile, scale, type); lock (fileInfo.FullName) { return fileInfo.Exists && (DateTime.Now - fileInfo.CreationTime).TotalMilliseconds < _maxAge; } }
/// <summary> /// Returns a file info object for a given tile. /// </summary> /// <param name="tile">The tile.</param> /// <param name="scale">The scale.</param> /// <param name="type">The type of image.</param> /// <returns></returns> private FileInfo GetTileFile(Tile tile, int scale, ImageType type) { string extension = string.Empty; switch (type) { case ImageType.Png: extension = ".png"; break; case ImageType.Bmp: extension = ".bmp"; break; case ImageType.Jpeg: extension = ".jpg"; break; } if(scale != 0) { // add scale if needed. extension = string.Format("{0}x", scale) + extension; } return new FileInfo(Path.Combine(_cacheDir.FullName, tile.Zoom.ToString(), tile.X.ToInvariantString(), tile.Y.ToInvariantString() + extension)); }
/// <summary> /// Writes a new file to cache. /// </summary> /// <param name="tile"></param> /// <param name="scale"></param> /// <param name="type"></param> /// <param name="image"></param> public void Write(Tile tile, int scale, ImageType type, Stream image) { var fileInfo = this.GetTileFile(tile, scale, type); lock (fileInfo.FullName) { if (fileInfo.Exists) { fileInfo.Delete(); } if (!fileInfo.Directory.Exists) { fileInfo.Directory.Create(); } using (var outputStream = fileInfo.OpenWrite()) { CopyStream(image, outputStream); } } }
/// <summary> /// Tries to get a tile and returns true if successfull. /// </summary> /// <param name="tile"></param> /// <param name="scale"></param> /// <param name="type"></param> /// <param name="image"></param> /// <returns></returns> public bool TryGet(Tile tile, int scale, ImageType type, out Stream image) { var fileInfo = this.GetTileFile(tile, scale, type); lock (fileInfo.FullName) { image = null; if (fileInfo.Exists && (DateTime.Now - fileInfo.CreationTime).TotalMilliseconds < _maxAge) { using (var fileStream = fileInfo.OpenRead()) { image = new MemoryStream(); CopyStream(fileStream, image); image.Seek(0, SeekOrigin.Begin); } return true; } return false; } }
/// <summary> /// Adds the given tile as the best tile for the given tileId. /// </summary> /// <param name="tileId"></param> /// <param name="tile"></param> private void Add(ulong tileId, Tile tile) { HashSet<Tile> tilesSet; if (!_tilesIndex.TryGetValue(tileId, out tilesSet)) { // create the tiles set. tilesSet = new HashSet<Tile>(); _tilesIndex.Add(tileId, tilesSet); } tilesSet.Add(tile); }
/// <summary> /// Returns true if this tile overlaps the given tile. /// </summary> /// <param name="tile"></param> /// <returns></returns> public bool Overlaps(Tile tile) { if (tile == null) { throw new ArgumentNullException("tile"); } if (tile.Zoom == this.Zoom) { // only overlaps when identical. return tile.Equals(this); } else if (tile.Zoom > this.Zoom) { // the zoom is bigger. var range = this.GetSubTiles(tile.Zoom); return range.Contains(tile); } return false; }
/// <summary> /// Returns a tile for the given zoom, x and y. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="zoom"></param> /// <param name="scale">Scale parameter, 1 = 256, 2 = 512, ...</param> /// <param name="type"></param> /// <returns></returns> public virtual Stream Get(int x, int y, ushort zoom, int scale, ImageType type = ImageType.Png) { Stream cachedImage; var tile = new Tile(x, y, zoom); if (_cache != null && _cache.TryGet(tile, scale, type, out cachedImage)) { // read from cache. OsmSharp.Logging.Log.TraceEvent("RenderingInstance", OsmSharp.Logging.TraceEventType.Information, string.Format("Returning cached image @ {0}", tile.ToInvariantString())); return cachedImage; } var renderedImage = this.Render(x, y, scale, zoom, type); if(_cache != null) { // cache image. _cache.Write(tile, scale, type, renderedImage); renderedImage.Seek(0, SeekOrigin.Begin); } OsmSharp.Logging.Log.TraceEvent("RenderingInstance", OsmSharp.Logging.TraceEventType.Information, string.Format("Rendered new image @ {0}", tile.ToInvariantString())); return renderedImage; }
/// <summary> /// Returns all data within the given tile /// </summary> /// <param name="tile">The tile to fetch geometries from</param> /// <param name="filter">Filtering options for the results</param> /// <returns>An OsmGeoCollection object containing the data within the given tile</returns> public virtual OsmGeoCollection GetCollection(Tile tile, Filter filter) { throw new NotImplementedException(); }