Ejemplo n.º 1
0
        /// <summary>
        /// Gets the node with given id.
        /// </summary>
        public Node GetNode(long id)
        {
            var tile  = new Tile(0, 0, 0);
            var index = LoadIndex(OsmGeoType.Node, tile);

            while (index != null &&
                   index.TryGetMask(id, out var mask))
            {
                var subTiles = tile.SubTilesForMask2(mask);
                var subTile  = subTiles.First();

                if (subTile.Zoom == _zoom)
                { // load data and find node.
                    var stream = DatabaseCommon.LoadTile(_path, OsmGeoType.Node, subTile, _compressed);
                    if (stream == null)
                    {
                        Log.Warning($"Could not find subtile, it should be there: {subTile}");
                        return(null);
                    }
                    using (stream)
                    {
                        var source = new OsmSharp.Streams.BinaryOsmStreamSource(stream);
                        while (source.MoveNext(false, true, true))
                        {
                            var current = source.Current();

                            if (current.Id == id)
                            {
                                return(current as Node);
                            }
                        }
                    }
                }

                tile  = subTile;
                index = LoadIndex(OsmGeoType.Node, tile);
            }

            return(null);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Gets a complete tile with complete ways and complete first level relations.
        /// </summary>
        internal IEnumerable <OsmGeo> GetRouteableTile(Tile tile, Stream stream)
        {
            // build a hashset of all nodes in the tile.
            var nodesInTile = new Dictionary <long, Node>();

            using (stream)
            {
                if (stream == null)
                {
                    yield break;
                }
                var source = new OsmSharp.Streams.BinaryOsmStreamSource(stream);
                while (source.MoveNext(false, true, true))
                {
                    var current = source.Current();

                    if (!(current is Node n))
                    {
                        continue;
                    }
                    if (n.Id == null)
                    {
                        continue;
                    }

                    nodesInTile.Add(n.Id.Value, n);
                }
            }

            // go over all ways and also include all nodes between the first/last node in the tile.
            // also include one node before or after the first/last node in the tile.
            var nodesToInclude = new SortedDictionary <long, Node>();

            using (stream = DatabaseCommon.LoadTile(_path, OsmGeoType.Way, tile, _compressed))
            {
                if (stream != null)
                {
                    var source = new OsmSharp.Streams.BinaryOsmStreamSource(stream);
                    while (source.MoveNext(true, false, true))
                    {
                        var current = source.Current();

                        var w = current as Way;
                        if (w?.Nodes == null)
                        {
                            continue;
                        }

                        var first = int.MaxValue;
                        var last  = -1;
                        for (var n = 0; n < w.Nodes.Length; n++)
                        {
                            var nodeId = w.Nodes[n];
                            if (!nodesInTile.ContainsKey(nodeId))
                            {
                                continue;
                            }

                            if (n < first)
                            {
                                first = n;
                            }
                            if (n > last)
                            {
                                last = n;
                            }
                        }

                        if (first == int.MaxValue)
                        {
                            continue;
                        }

                        if (first > 0)
                        {
                            first--;
                        }
                        if (last < w.Nodes.Length - 1)
                        {
                            last++;
                        }
                        for (var n = first; n < last + 1; n++)
                        {
                            var nodeId = w.Nodes[n];

                            // get node from the nodes in the tile.
                            if (nodesInTile.TryGetValue(nodeId, out var node))
                            { // node already there.
                                nodesToInclude[nodeId] = node;
                                continue;
                            }

                            // node is not in the tile, get it from the db if it's not included already..
                            if (!nodesToInclude.ContainsKey(nodeId))
                            { // not not yet there, get it.
                                node = this.GetNode(nodeId);
                                nodesToInclude[nodeId] = node;
                            }
                        }
                    }
                }
            }

            var hasData = nodesToInclude.Count > 0;

            if (!hasData)
            {
                yield break;
            }

            // return all the nodes.
            foreach (var node in nodesToInclude.Values)
            {
                yield return(node);
            }

            // returns all the ways that have at least one node.
            using (stream = DatabaseCommon.LoadTile(_path, OsmGeoType.Way, tile, _compressed))
            {
                if (stream != null)
                {
                    var source = new OsmSharp.Streams.BinaryOsmStreamSource(stream);
                    while (source.MoveNext(true, false, true))
                    {
                        var current = source.Current();

                        var w = current as Way;
                        if (w == null)
                        {
                            continue;
                        }

                        // trim nodes.
                        var trimmedNodes = new List <long>();
                        foreach (var n in w.Nodes)
                        {
                            if (!nodesToInclude.TryGetValue(n, out _))
                            {
                                continue;
                            }

                            trimmedNodes.Add(n);
                        }
                        w.Nodes = trimmedNodes.ToArray();

                        if (w.Nodes.Length == 0)
                        {
                            continue;
                        }

                        yield return(w);
                    }
                }
            }

            // return all relations.
            using (stream = DatabaseCommon.LoadTile(_path, OsmGeoType.Relation, tile, _compressed))
            {
                if (stream != null)
                {
                    var source = new OsmSharp.Streams.BinaryOsmStreamSource(stream);
                    while (source.MoveNext(true, true, false))
                    {
                        var current = source.Current();

                        var r = current as Relation;

                        yield return(r);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Builds the database and writes the structure to the given by by splitting the given zoom level.
        /// </summary>
        private static List <Tile> Build(string path, uint maxZoom, Tile tile, bool compressed = false)
        {
            // split nodes and return index and non-empty tiles.
            List <Tile> nonEmptyTiles = null;
            Index       nodeIndex     = null;

            var nodeFile = DatabaseCommon.BuildPathToTile(path, OsmGeoType.Node, tile, compressed);

            if (!FileSystemFacade.FileSystem.Exists(nodeFile))
            {
                Log.Logger.Warning("Tile {0}/{1}/{2} not found: {3}", tile.Zoom, tile.X, tile.Y,
                                   nodeFile);
                return(new List <Tile>());
            }
            using (var nodeStream = DatabaseCommon.LoadTile(path, OsmGeoType.Node, tile, compressed))
            {
                var nodeSource = new OsmSharp.Streams.BinaryOsmStreamSource(nodeStream);

                // split nodes and return nodes index and non-empty tiles.
                nodeIndex = NodeProcessor.Process(nodeSource, path, maxZoom, tile, out nonEmptyTiles,
                                                  out _, compressed);
            }

            // build the ways index.
            Index wayIndex = null;
            var   wayFile  = DatabaseCommon.BuildPathToTile(path, OsmGeoType.Way, tile, compressed);

            if (FileSystemFacade.FileSystem.Exists(wayFile))
            {
                using (var wayStream = DatabaseCommon.LoadTile(path, OsmGeoType.Way, tile, compressed))
                {
                    var waySource = new OsmSharp.Streams.BinaryOsmStreamSource(wayStream);
                    if (waySource.MoveNext())
                    {
                        wayIndex = WayProcessor.Process(waySource, path, maxZoom, tile, nodeIndex, compressed);
                    }
                }
            }

            // build the relations index.
            Index relationIndex = null;
            var   relationFile  = DatabaseCommon.BuildPathToTile(path, OsmGeoType.Relation, tile, compressed);

            if (FileSystemFacade.FileSystem.Exists(relationFile))
            {
                using (var relationStream = DatabaseCommon.LoadTile(path, OsmGeoType.Relation, tile, compressed))
                {
                    var relationSource = new OsmSharp.Streams.BinaryOsmStreamSource(relationStream);
                    if (relationSource.MoveNext())
                    {
                        relationIndex = RelationProcessor.Process(relationSource, path, maxZoom, tile, nodeIndex, wayIndex, compressed);
                    }
                }
            }

            // write the indexes to disk.
            nodeIndex.Write(FileSystemFacade.FileSystem.Combine(path, tile.Zoom.ToString(),
                                                                tile.X.ToString(), tile.Y.ToString() + ".nodes.idx"));
            wayIndex?.Write(FileSystemFacade.FileSystem.Combine(path, tile.Zoom.ToString(),
                                                                tile.X.ToString(), tile.Y.ToString() + ".ways.idx"));
            relationIndex?.Write(FileSystemFacade.FileSystem.Combine(path, tile.Zoom.ToString(),
                                                                     tile.X.ToString(), tile.Y.ToString() + ".relations.idx"));
//            var actions = new List<Action>
//            {
//                () => nodeIndex.Write(FileSystemFacade.FileSystem.Combine(path, tile.Zoom.ToString(),
//                    tile.X.ToString(), tile.Y.ToString() + ".nodes.idx")),
//                () => wayIndex?.Write(FileSystemFacade.FileSystem.Combine(path, tile.Zoom.ToString(),
//                    tile.X.ToString(), tile.Y.ToString() + ".ways.idx")),
//                () => relationIndex?.Write(FileSystemFacade.FileSystem.Combine(path, tile.Zoom.ToString(),
//                    tile.X.ToString(), tile.Y.ToString() + ".relations.idx"))
//            };
//            System.Threading.Tasks.Parallel.ForEach(actions, (a) => a());

            if (FileSystemFacade.FileSystem.Exists(nodeFile))
            {
                FileSystemFacade.FileSystem.Delete(nodeFile);
            }
            if (FileSystemFacade.FileSystem.Exists(wayFile))
            {
                FileSystemFacade.FileSystem.Delete(wayFile);
            }
            if (FileSystemFacade.FileSystem.Exists(relationFile))
            {
                FileSystemFacade.FileSystem.Delete(relationFile);
            }

            return(nonEmptyTiles);
        }