/// <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);
        }
Exemple #2
0
        /// <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);
            }
        }
Exemple #4
0
        /// <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);
        }
Exemple #5
0
        /// <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);
            }
        }
Exemple #6
0
        /// <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);
            }
        }
Exemple #7
0
        /// <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);
            }
        }
Exemple #8
0
        /// <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);
        }
Exemple #10
0
        /// <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);
            }
        }
Exemple #11
0
        /// <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);
        }
Exemple #14
0
        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();
        }