/// <summary> /// Loads all vertices inside the given boundingbox. /// </summary> /// <param name="box"></param> /// <returns></returns> private HashSet <uint> LoadVerticesIn(GeoCoordinateBox box) { var vertices = new HashSet <uint>(); var range = TileRange.CreateAroundBoundingBox(box, _zoom); foreach (Tile tile in range) { CHVertexRegion region; if (!_regions.TryGet(tile.Id, out region)) { region = this.DeserializeRegion(tile.Id); if (region != null) { _regions.Add(tile.Id, region); } } if (region != null) { for (int idx = 0; idx < region.Vertices.Length; idx++) { vertices.Add(region.Vertices[idx]); } } } return(vertices); }
/// <summary> /// Called when the mapview has changed. /// </summary> /// <param name="map"></param> /// <param name="zoomFactor"></param> /// <param name="center"></param> /// <param name="view"></param> public void ViewChanged(Map map, float zoomFactor, GeoCoordinate center, View2D view) { // calculate the current zoom level. var zoomLevel = (int)System.Math.Round(map.Projection.ToZoomLevel(zoomFactor), 0); // build the boundingbox. var box = new GeoCoordinateBox( map.Projection.ToGeoCoordinates(view.Left, view.Top), map.Projection.ToGeoCoordinates(view.Right, view.Bottom)); // build the tile range. TileRange range = TileRange.CreateAroundBoundingBox(box, zoomLevel); DateTime now = DateTime.Now; // build the new scene. Scene2D newScene = new Scene2D(); if (_connection.State == System.Data.ConnectionState.Closed) { _connection.Open(); } lock (_connection) { // make sure the connection is accessed synchronously. // TODO: Investigate the SQLite multithreaded behaviour.. // TODO: this a very naive way of loading these tiles. Find a way to query SQLite more efficiently // TODO: find a way to have some cached tiles. foreach (var tile in range) { Tile invertTile = tile.InvertY(); SQLiteCommand command = new SQLiteCommand("SELECT * FROM tiles WHERE zoom_level = :zoom_level AND tile_column = :tile_column AND tile_row = :tile_row;", _connection); command.Parameters.AddWithValue("zoom_level", invertTile.Zoom); command.Parameters.AddWithValue("tile_column", invertTile.X); command.Parameters.AddWithValue("tile_row", invertTile.Y); using (var tileReader = command.ExecuteReader()) { while (tileReader.Read()) { //Tile readTile = new Tile((int)tileReader["tile_column"], // (int)tileReader["tile_row"], (int)tileReader["zoom_level"]); float minZoom = (float)map.Projection.ToZoomFactor(tile.Zoom - 0.5f); float maxZoom = (float)map.Projection.ToZoomFactor(tile.Zoom + 0.5f); float left = (float)map.Projection.LongitudeToX(tile.TopLeft.Longitude); float right = (float)map.Projection.LongitudeToX(tile.BottomRight.Longitude); float bottom = (float)map.Projection.LatitudeToY(tile.BottomRight.Latitude); float top = (float)map.Projection.LatitudeToY(tile.TopLeft.Latitude); newScene.AddImage(0, minZoom, maxZoom, left, top, right, bottom, (byte[])tileReader["tile_data"]); } } } this.Scene = newScene; } }
/// <summary> /// Loads all missing tiles. /// </summary> /// <param name="box"></param> private void LoadMissingTile(GeoCoordinateBox box) { // creates a tile range. TileRange tileRange = TileRange.CreateAroundBoundingBox(box, _zoom); foreach (var tile in tileRange) { this.LoadMissingTile(tile); } }
/// <summary> /// Builds a list of osm-hashes. /// </summary> /// <param name="box"></param> /// <returns></returns> public static List <string> GetOsmHashes(GeoCoordinateBox box) { List <string> hashes = new List <string>(); TileRange tiles = TileRange.CreateAroundBoundingBox(box, 14); foreach (Tile tile in tiles) { hashes.Add(tile.Id.ToString()); } return(hashes); }
/// <summary> /// Notifies this layer that the current mapview has changed. /// </summary> /// <param name="map"></param> /// <param name="zoomFactor"></param> /// <param name="center"></param> /// <param name="view"></param> /// <param name="extraView"></param> protected internal override void ViewChanged(Map map, float zoomFactor, GeoCoordinate center, View2D view, View2D extraView) { // calculate the current zoom level. var zoomLevel = (int)System.Math.Round(map.Projection.ToZoomLevel(zoomFactor), 0); if (zoomLevel >= _minZoomLevel && zoomLevel <= _maxZoomLevel) { // build the bounding box. var viewBox = view.OuterBox; // build the tile range. var range = TileRange.CreateAroundBoundingBox(new GeoCoordinateBox(map.Projection.ToGeoCoordinates(viewBox.Min[0], viewBox.Min[1]), map.Projection.ToGeoCoordinates(viewBox.Max[0], viewBox.Max[1])), zoomLevel); OsmSharp.Logging.Log.TraceEvent("LayerMBTile", OsmSharp.Logging.TraceEventType.Verbose, string.Format("Requesting {0} tiles for view.", range.Count)); // request all missing tiles. lock (_connection) { // make sure the connection is accessed synchronously. // TODO: Investigate the SQLite multithreaded behaviour.. // TODO: this a very naive way of loading these tiles. Find a way to query SQLite more efficiently // TODO: find a way to have some cached tiles. foreach (var tile in range.EnumerateInCenterFirst()) { Image2D value; if (_cache.TryGet(tile, out value)) { // Tile is already in cache. We used TryGet, and not TryPeek, to inform the cache // that we intend to use the datum in question. continue; } Tile invertTile = tile.InvertY(); var tiles = _connection.Query <tiles>("SELECT * FROM tiles WHERE zoom_level = ? AND tile_column = ? AND tile_row = ?", invertTile.Zoom, invertTile.X, invertTile.Y); foreach (var mbTile in tiles) { var box = tile.ToBox(_projection); var nativeImage = _nativeImageCache.Obtain(mbTile.tile_data); var image2D = new Image2D(box.Min[0], box.Min[1], box.Max[1], box.Max[0], nativeImage); image2D.Layer = (uint)(_maxZoomLevel - tile.Zoom); lock (_cache) { // add the result to the cache. _cache.Add(tile, image2D); } } } } OsmSharp.Logging.Log.TraceEvent("LayerMBTile", Logging.TraceEventType.Information, "Cached tiles: {0}", _cache.Count); } }
/// <summary> /// Notifies this layer the mapview has changed. /// </summary> /// <param name="map"></param> /// <param name="zoomFactor"></param> /// <param name="center"></param> /// <param name="view"></param> internal override void ViewChanged(Map map, float zoomFactor, GeoCoordinate center, View2D view) { // calculate the current zoom level. var zoomLevel = (int)System.Math.Round(map.Projection.ToZoomLevel(zoomFactor), 0); // build the boundingbox. var viewBox = view.OuterBox; var box = new GeoCoordinateBox(map.Projection.ToGeoCoordinates(viewBox.Min [0], viewBox.Min [1]), map.Projection.ToGeoCoordinates(viewBox.Max [0], viewBox.Max [1])); // build the tile range. lock (_tileRange) { // make sure the tile range is not in use. _tileRange = TileRange.CreateAroundBoundingBox(box, zoomLevel); } }
/// <summary> /// Notifies this layer the mapview has changed. /// </summary> /// <param name="map"></param> /// <param name="zoomFactor"></param> /// <param name="center"></param> /// <param name="view"></param> public void ViewChanged(Map map, float zoomFactor, GeoCoordinate center, View2D view) { // calculate the current zoom level. var zoomLevel = (int)System.Math.Round(map.Projection.ToZoomLevel(zoomFactor), 0); // reset stack when zoom level changed. if (_previousZoomLevel != zoomLevel) { _previousZoomLevel = zoomLevel; _tilesStack.Clear(); } // build the boundingbox. // build the boundingbox. var viewBox = view.OuterBox; var box = new GeoCoordinateBox(map.Projection.ToGeoCoordinates(viewBox.Min [0], viewBox.Min [1]), map.Projection.ToGeoCoordinates(viewBox.Max [0], viewBox.Max [1])); // build the tile range. TileRange range = TileRange.CreateAroundBoundingBox(box, zoomLevel); DateTime now = DateTime.Now; foreach (var tile in range) { if (_primitivePerTile.ContainsKey(tile)) { // the tile is here already. _lastAccessed[tile] = now; } else { // queue the tile to be loaded. lock (_tilesStack) { _tilesStack.Push(tile); } } } if (_thread == null) { // the loading thread does not exist yet. _thread = new Thread(TilesLoading); _thread.Start(map.Projection); } }
/// <summary> /// Loads all vertices inside the given boundingbox. /// </summary> /// <param name="box"></param> /// <returns></returns> private List <uint> LoadVerticesIn(GeoCoordinateBox box) { List <uint> vertices = new List <uint>(); TileRange range = TileRange.CreateAroundBoundingBox(box, _zoom); foreach (Tile tile in range) { CHVertexRegion region; if (!_regions.TryGet(tile.Id, out region)) { region = this.DeserializeRegion(tile.Id); if (region != null) { _regions.Add(tile.Id, region); } } if (region != null) { vertices.AddRange(region.Vertices); } } return(vertices); }
/// <summary> /// Returns all data within the given bounding box and filtered by the given filter. /// </summary> /// <param name="box"></param> /// <param name="filter"></param> /// <returns></returns> public override IList <OsmGeo> Get(GeoCoordinateBox box, OsmSharp.Osm.Filters.Filter filter) { // initialize connection. NpgsqlConnection con = this.CreateConnection(); List <OsmGeo> res = new List <OsmGeo>(); // calculate bounding box parameters to query db. long latitude_min = (long)(box.MinLat * 10000000.0); long longitude_min = (long)(box.MinLon * 10000000.0); long latitude_max = (long)(box.MaxLat * 10000000.0); long longitude_max = (long)(box.MaxLon * 10000000.0); // calculate bounding box parameters to query db. TileRange range = TileRange.CreateAroundBoundingBox(box, 14); IList <long> boxes = new List <long>(); foreach (Tile tile in range) { boxes.Add((long)tile.Id); } // STEP 1: query nodes table. //id latitude longitude changeset_id visible timestamp tile version string sql = "SELECT id, latitude, longitude, changeset_id, visible, timestamp, tile, version, usr, usr_id FROM node WHERE (visible = true) AND (tile IN ({4})) AND (latitude >= {0} AND latitude < {1} AND longitude >= {2} AND longitude < {3})"; sql = string.Format(sql, latitude_min.ToString(), latitude_max.ToString(), longitude_min.ToString(), longitude_max.ToString(), this.ConstructIdList(boxes)); // TODO: parameters. NpgsqlCommand com = new NpgsqlCommand(sql); com.Connection = con; NpgsqlDataReader reader = com.ExecuteReader(); Node node = null; Dictionary <long, Node> nodes = new Dictionary <long, Node>(); List <long> nodeIds = new List <long>(); while (reader.Read()) { // load/parse data. long returned_id = reader.GetInt64(0); int latitude_int = reader.GetInt32(1); int longitude_int = reader.GetInt32(2); long? changeset_id = reader.IsDBNull(3) ? null : (long?)reader.GetInt64(3); bool? visible = reader.IsDBNull(4) ? null : (bool?)reader.GetBoolean(4); DateTime?timestamp = reader.IsDBNull(5) ? null : (DateTime?)reader.GetDateTime(5); long tile = reader.GetInt64(6); ulong? version = reader.IsDBNull(7) ? null : (ulong?)reader.GetInt32(7); string usr = reader.IsDBNull(8) ? null : reader.GetString(8); long? usr_id = reader.IsDBNull(9) ? null : (long?)reader.GetInt32(9); if (!nodes.ContainsKey(returned_id)) { // create node. node = new Node(); node.Id = returned_id; node.Version = version; node.UserId = usr_id; node.UserName = usr; node.TimeStamp = timestamp; node.ChangeSetId = changeset_id; node.Latitude = ((double)latitude_int) / 10000000.0; node.Longitude = ((double)longitude_int) / 10000000.0; node.Visible = visible; nodes.Add(node.Id.Value, node); nodeIds.Add(node.Id.Value); } } reader.Close(); // STEP2: Load all node tags. this.LoadNodeTags(nodes); res.AddRange(nodes.Values); // load all ways that contain the nodes that have been found. res.AddRange(this.GetWaysFor(nodeIds)); // get relations containing any of the nodes or ways in the current results-list. List <Relation> relations = new List <Relation>(); HashSet <long> relationIds = new HashSet <long>(); foreach (OsmGeo osmGeo in res) { IList <Relation> relationsFor = this.GetRelationsFor(osmGeo); foreach (Relation relation in relationsFor) { if (!relationIds.Contains(relation.Id.Value)) { relations.Add(relation); relationIds.Add(relation.Id.Value); } } } // recursively add all relations containing other relations as a member. do { res.AddRange(relations); // add previous relations-list. List <Relation> newRelations = new List <Relation>(); foreach (OsmGeo osmGeo in relations) { IList <Relation> relationsFor = this.GetRelationsFor(osmGeo); foreach (Relation relation in relationsFor) { if (!relationIds.Contains(relation.Id.Value)) { newRelations.Add(relation); relationIds.Add(relation.Id.Value); } } } relations = newRelations; } while (relations.Count > 0); if (filter != null) { var filtered = new List <OsmGeo>(); foreach (OsmGeo geo in res) { if (filter.Evaluate(geo)) { filtered.Add(geo); } } return(filtered); } return(res); }
/// <summary> /// Notifies this layer the mapview has changed. /// </summary> /// <param name="map"></param> /// <param name="zoomFactor"></param> /// <param name="center"></param> /// <param name="view"></param> /// <param name="extraView"></param> public override void ViewChanged(Map map, float zoomFactor, GeoCoordinate center, View2D view, View2D extraView) { if (_suspended) { // do not accept trigger changes if suspended. return; } if (!this.IsVisible) { // if the map is not visible also do not accept changes. return; } try { // calculate the current zoom level. var zoomLevel = (int)System.Math.Round(map.Projection.ToZoomLevel(zoomFactor), 0); if (zoomLevel >= _minZoomLevel && zoomLevel <= _maxZoomLevel) { // build the bounding box. var viewBox = view.OuterBox; var box = new GeoCoordinateBox(map.Projection.ToGeoCoordinates(viewBox.Min[0], viewBox.Min[1]), map.Projection.ToGeoCoordinates(viewBox.Max[0], viewBox.Max[1])); // build the tile range. lock (_stack) { // make sure the tile range is not in use. _stack.Clear(); lock (_cache) { var tileRange = TileRange.CreateAroundBoundingBox(box, zoomLevel); _currentZoom = zoomLevel; foreach (var tile in tileRange.EnumerateInCenterFirst().Reverse()) { if (tile.IsValid) { // make sure all tiles are valid. Image2D temp; if (!_cache.TryPeek(tile, out temp) && !_loading.Contains(tile)) { // not cached and not loading. _stack.Push(tile); OsmSharp.Logging.Log.TraceEvent("LayerTile", Logging.TraceEventType.Information, "Queued tile: " + tile.ToString()); } } } _timer.Change(0, 250); } if (_stack.Count > 0) { // reset the attempts. lock (_attempts) { _attempts.Clear(); } } } } } catch (Exception ex) { // don't worry about exceptions here. OsmSharp.Logging.Log.TraceEvent("LayerTile", Logging.TraceEventType.Error, ex.Message); } }
/// <summary> /// Returns all primitives from this layer visible for the given parameters. /// </summary> /// <param name="zoomFactor"></param> /// <param name="view"></param> /// <returns></returns> public override IEnumerable <Primitive2D> Get(float zoomFactor, View2D view) { var primitives = new List <Primitive2D>(); //if(_suspended) //{ // just return an empty primitives list if suspended. // return primitives; //} try { // calculate the current zoom level. var zoomLevel = (int)System.Math.Round(_projection.ToZoomLevel(zoomFactor), 0); if (zoomLevel >= _minZoomLevel && zoomLevel <= _maxZoomLevel) { // build the bounding box. var viewBox = view.OuterBox; var box = new GeoCoordinateBox(_projection.ToGeoCoordinates(viewBox.Min[0], viewBox.Min[1]), _projection.ToGeoCoordinates(viewBox.Max[0], viewBox.Max[1])); var tileRange = TileRange.CreateAroundBoundingBox(box, zoomLevel); var tileRangeIndex = new TileRangeIndex(tileRange); var primitivePerTile = new Dictionary <Tile, Primitive2D>(); lock (_cache) { Image2D temp; foreach (var tile in _cache) { if (tile.Value.IsVisibleIn(view)) { tileRangeIndex.Add(tile.Key); primitivePerTile.Add(tile.Key, tile.Value); var minZoom = _projection.ToZoomFactor(tile.Key.Zoom - _zoomMinOffset); var maxZoom = _projection.ToZoomFactor(tile.Key.Zoom + (1 - _zoomMinOffset)); if (zoomFactor < maxZoom && zoomFactor > minZoom) { // just hit the cache for tiles of this zoom level. _cache.TryGet(tile.Key, out temp); } } } // set the ascending flag. if (_previousZoomFactor != zoomFactor) { // only change flag when difference. _ascending = (_previousZoomFactor < zoomFactor); _previousZoomFactor = zoomFactor; } // get candidate tiles for every tile. var selectedTiles = new List <Tile>(); foreach (var tile in tileRange) { var best = tileRangeIndex.ChooseBest(tile, _ascending); foreach (var bestTile in best) { if (!selectedTiles.Contains(bestTile)) { // make sure no doubles are added! selectedTiles.Add(bestTile); } } } // sort according to the tiles index. selectedTiles.Sort(delegate(Tile x, Tile y) { return(TileRangeIndex.TileWeight(tileRange.Zoom, x.Zoom, !_ascending).CompareTo( TileRangeIndex.TileWeight(tileRange.Zoom, y.Zoom, !_ascending))); }); selectedTiles.Reverse(); // recursively remove tiles. for (int idx = selectedTiles.Count; idx > 0; idx--) { if (selectedTiles[selectedTiles.Count - idx].IsOverlappedBy( selectedTiles.GetRange(selectedTiles.Count - idx + 1, selectedTiles.Count - (selectedTiles.Count - idx + 1)))) { selectedTiles.RemoveAt(selectedTiles.Count - idx); } } // TODO: trim this collection so that only tiles remain close to the zoom level not overlapping. Image2D primitive; foreach (Tile tile in selectedTiles) { if (_cache.TryPeek(tile, out primitive)) { // add to the primitives list. primitives.Add(primitive); } } } } OsmSharp.Logging.Log.TraceEvent("LayerTile", Logging.TraceEventType.Information, string.Format("LayerTile returned {0} primitives.", primitives.Count)); return(primitives); } catch (Exception ex) { // don't worry about exceptions here. OsmSharp.Logging.Log.TraceEvent("LayerTile", Logging.TraceEventType.Error, ex.Message); } return(primitives); }
/// <summary> /// Returns all objects in the given bounding box and that pass the given filter. /// </summary> /// <param name="box"></param> /// <param name="filter"></param> /// <returns></returns> public override IList <OsmGeo> Get(GeoCoordinateBox box, OsmSharp.Osm.Filters.Filter filter) { List <OsmGeo> res = new List <OsmGeo>(); // create a range or tiles around the given bounding box. TileRange range = TileRange.CreateAroundBoundingBox(box, 14); // build all redis keys for the given boxes. var hashKeys = new List <string>(); foreach (Tile tile in range) { hashKeys.Add(tile.Id.ToString()); } byte[][] box_members = _client.SUnion(hashKeys.ToArray()); HashSet <string> nodeKeys = new HashSet <string>(); foreach (byte[] box_member in box_members) { long node_id = BitConverter.ToInt64(box_member, 0); string node_key = PrimitiveExtensions.BuildNodeRedisKey(node_id); nodeKeys.Add(node_key); } List <RedisNode> redisNodes = _clientNode.GetValues(new List <string>(nodeKeys)); var nodeIds = new List <long>(); foreach (RedisNode redisNode in redisNodes) { // test if the node is in the given bb. GeoCoordinate coordinate = new GeoCoordinate(redisNode.Latitude.Value, redisNode.Longitude.Value); if (box.IsInside(coordinate)) { res.Add(PrimitiveExtensions.ConvertFrom(redisNode)); nodeIds.Add(redisNode.Id.Value); } } // load all ways that contain the nodes that have been found. res.AddRange(this.GetWaysFor(nodeIds)); // get relations containing any of the nodes or ways in the current results-list. List <Relation> relations = new List <Relation>(); HashSet <long> relationIds = new HashSet <long>(); foreach (OsmGeo osmGeo in res) { IList <Relation> relationsFor = this.GetRelationsFor(osmGeo); foreach (Relation relation in relationsFor) { if (!relationIds.Contains(relation.Id.Value)) { relations.Add(relation); relationIds.Add(relation.Id.Value); } } } // recursively add all relations containing other relations as a member. do { res.AddRange(relations); // add previous relations-list. List <Relation> newRelations = new List <Relation>(); foreach (OsmGeo osmGeo in relations) { IList <Relation> relationsFor = this.GetRelationsFor(osmGeo); foreach (Relation relation in relationsFor) { if (!relationIds.Contains(relation.Id.Value)) { newRelations.Add(relation); relationIds.Add(relation.Id.Value); } } } relations = newRelations; } while (relations.Count > 0); if (filter != null) { List <OsmGeo> filtered = new List <OsmGeo>(); foreach (OsmGeo geo in res) { if (filter.Evaluate(geo)) { filtered.Add(geo); } } } return(res); }
/// <summary> /// Returns all objects with the given bounding box and valid for the given filter; /// </summary> /// <param name="box"></param> /// <param name="filter"></param> /// <returns></returns> public override IList <OsmGeo> Get(GeoCoordinateBox box, Filter filter) { // initialize connection. OracleConnection con = this.CreateConnection(); List <OsmGeo> res = new List <OsmGeo>(); // calculate bounding box parameters to query db. long latitudeMin = (long)(box.MinLat * 10000000.0); long longitudeMin = (long)(box.MinLon * 10000000.0); long latitudeMax = (long)(box.MaxLat * 10000000.0); long longitudeMax = (long)(box.MaxLon * 10000000.0); IList <long> boxes = new List <long>(); TileRange tileRange = TileRange.CreateAroundBoundingBox(box, 14); foreach (Tile tile in tileRange) { boxes.Add((long)tile.Id); } // STEP 1: query nodes table. //id latitude longitude changeset_id visible timestamp tile version //string sql // = "SELECT node.id, node.latitude, node.longitude, node.changeset_id, node.timestamp, node.version, " + // "node.usr, node.usr_id, node.visible FROM node WHERE (tile IN ({4})) AND (visible = 1) AND (latitude BETWEEN {0} AND {1} AND longitude BETWEEN {2} AND {3})"; // remove this nasty BETWEEN operation because it depends on the database (!) what results are returned (including or excluding bounds!!!) string sql = "SELECT id, latitude, longitude, changeset_id, visible, timestamp, tile, version, usr, usr_id " + "FROM node WHERE (tile IN ({4})) AND (visible = 1) AND (latitude >= {0} AND latitude < {1} AND longitude >= {2} AND longitude < {3})"; sql = string.Format(sql, latitudeMin.ToString(System.Globalization.CultureInfo.InvariantCulture), latitudeMax.ToString(System.Globalization.CultureInfo.InvariantCulture), longitudeMin.ToString(System.Globalization.CultureInfo.InvariantCulture), longitudeMax.ToString(System.Globalization.CultureInfo.InvariantCulture), this.ConstructIdList(boxes)); // TODO: parameters. var com = new OracleCommand(sql); com.Connection = con; OracleDataReader reader = com.ExecuteReader(); Node node = null; var nodes = new Dictionary <long, Node>(); var nodeIds = new List <long>(); while (reader.Read()) { // load/parse data. long returned_id = reader.GetInt64(0); int latitude_int = reader.GetInt32(1); int longitude_int = reader.GetInt32(2); long? changeset_id = reader.IsDBNull(3) ? null : (long?)reader.GetInt64(3); bool? visible = reader.IsDBNull(4) ? null : (bool?)(reader.GetInt32(4) == 1); DateTime?timestamp = reader.IsDBNull(5) ? null : (DateTime?)reader.GetDateTime(5); long tile = reader.GetInt64(6); ulong? version = reader.IsDBNull(7) ? null : (ulong?)(ulong)reader.GetInt64(7); string usr = reader.IsDBNull(8) ? null : reader.GetString(8); long? usr_id = reader.IsDBNull(9) ? null : (long?)reader.GetInt64(9); if (!nodes.ContainsKey(returned_id)) { // create node. node = new Node(); node.Id = returned_id; node.Version = version; node.UserId = usr_id; node.TimeStamp = timestamp; node.ChangeSetId = changeset_id; node.Visible = visible; node.Latitude = ((double)latitude_int) / 10000000.0; node.Longitude = ((double)longitude_int) / 10000000.0; node.UserName = usr; nodeIds.Add(node.Id.Value); nodes.Add(node.Id.Value, node); } } reader.Close(); // STEP2: Load all node tags. this.LoadNodeTags(nodes); res.AddRange(nodes.Values); // load all ways that contain the nodes that have been found. res.AddRange(this.GetWaysFor(nodeIds)); // get relations containing any of the nodes or ways in the current results-list. List <Relation> relations = new List <Relation>(); HashSet <long> relationIds = new HashSet <long>(); foreach (OsmGeo osmGeo in res) { IList <Relation> relationsFor = this.GetRelationsFor(osmGeo); foreach (Relation relation in relationsFor) { if (!relationIds.Contains(relation.Id.Value)) { relations.Add(relation); relationIds.Add(relation.Id.Value); } } } // recursively add all relations containing other relations as a member. do { res.AddRange(relations); // add previous relations-list. List <Relation> newRelations = new List <Relation>(); foreach (OsmGeo osmGeo in relations) { IList <Relation> relationsFor = this.GetRelationsFor(osmGeo); foreach (Relation relation in relationsFor) { if (!relationIds.Contains(relation.Id.Value)) { newRelations.Add(relation); relationIds.Add(relation.Id.Value); } } } relations = newRelations; } while (relations.Count > 0); if (filter != null) { List <OsmGeo> filtered = new List <OsmGeo>(); foreach (OsmGeo geo in res) { if (filter.Evaluate(geo)) { filtered.Add(geo); } } } return(res); }
static void Main(string[] args) { OsmSharp.Logging.Log.Enable(); OsmSharp.Logging.Log.RegisterListener(new OsmSharp.WinForms.UI.Logging.ConsoleTraceListener()); var outputDir = @"c:\temp\tiles"; var mbtilesFile = outputDir + "\\tiles.mbtiles"; SQLiteConnection.CreateFile(mbtilesFile); var mbtiles = new SQLiteConnection(string.Format("Data Source={0};Version=3;", mbtilesFile)); mbtiles.Open(); var query = new SQLiteCommand(mbtiles); query.CommandText = "CREATE TABLE metadata (name text, value text);"; query.ExecuteNonQuery(); new SQLiteCommand(mbtiles); query.CommandText = "CREATE TABLE tiles (zoom_level integer, tile_column integer, tile_row integer, tile_data blob);"; query.ExecuteNonQuery(); query = new SQLiteCommand(mbtiles); query.CommandText = "INSERT INTO metadata (name, value) VALUES ('name', 'tiles');" + "INSERT INTO metadata (name, value) VALUES ('type', 'baselayer');" + "INSERT INTO metadata (name, value) VALUES ('version', '1');" + "INSERT INTO metadata (name, value) VALUES ('minzoom', '5');" + "INSERT INTO metadata (name, value) VALUES ('maxzoom', '6');" + "INSERT INTO metadata (name, value) VALUES ('version', '1');" + "INSERT INTO metadata (name, value) VALUES ('description', 'A description of this layer');" + "INSERT INTO metadata (name, value) VALUES ('bounds', '-5.2294921875,42.195968776291780,8.50341796875,51.248163159055906');" + "INSERT INTO metadata (name, value) VALUES ('format', 'png');"; query.ExecuteNonQuery(); query = new SQLiteCommand(mbtiles); query.CommandText = "INSERT INTO tiles VALUES (:zoom_level, :tile_column, :tile_row, :tile_data) ;"; query.Parameters.Add(new SQLiteParameter(@"zoom_level", DbType.Int64)); query.Parameters.Add(new SQLiteParameter(@"tile_column", DbType.Int64)); query.Parameters.Add(new SQLiteParameter(@"tile_row", DbType.Int64)); query.Parameters.Add(new SQLiteParameter(@"tile_data", DbType.Binary)); var url = "http://localhost:1234/default/{z}/{x}/{y}.png"; var box = new GeoCoordinateBox( new GeoCoordinate(42.195968776291780, -5.2294921875), new GeoCoordinate(51.248163159055906, 8.50341796875)); var minZoom = 5; var maxZoom = 6; // download tiles. for (var zoom = maxZoom; zoom >= minZoom; zoom--) { var tileRange = TileRange.CreateAroundBoundingBox(box, zoom); OsmSharp.Logging.Log.TraceEvent(string.Empty, OsmSharp.Logging.TraceEventType.Information, string.Format("Downloading {0} tiles at zoom {1}.", tileRange.Count, zoom)); foreach (var tile in tileRange) { // download tile. var data = Download(url, tile); // save tile. var tileDir = new DirectoryInfo(Path.Combine(outputDir, tile.Zoom.ToString(), tile.X.ToString())); if (!tileDir.Exists) { // creates target dir. tileDir.Create(); } var tileFile = new FileInfo(Path.Combine(tileDir.ToString(), tile.Y.ToString() + ".png")); using (var outputStream = tileFile.OpenWrite()) { outputStream.Write(data, 0, data.Length); } var inverted = tile.InvertY(); query.Parameters[0].Value = zoom; query.Parameters[1].Value = tile.X; query.Parameters[2].Value = inverted.Y; query.Parameters[3].Value = data; query.ExecuteNonQuery(); Thread.Sleep(100); } } mbtiles.Close(); }