/// <summary> /// Processes the relations in the given stream. Assumed the current stream position already contains a relation. /// </summary> /// <param name="source">The source stream.</param> /// <param name="path">The based path of the db.</param> /// <param name="maxZoom">The maximum zoom.</param> /// <param name="tile">The tile being split.</param> /// <param name="nodeIndex">The node index.</param> /// <param name="wayIndex">The way index.</param> /// <param name="compressed">A flag to allow compression of target files.</param> /// <returns>The indexed node id's with a masked zoom.</returns> public static Index Process(OsmStreamSource source, string path, uint maxZoom, Tile tile, Index nodeIndex, Index wayIndex, bool compressed = false) { try { // split relations. var subtiles = new Dictionary <ulong, Stream>(); foreach (var subTile in tile.GetSubtilesAt(tile.Zoom + 2)) { subtiles.Add(subTile.LocalId, null); } // build the relations index. var relationIndex = new Index(); do { var current = source.Current(); if (current.Type != OsmGeoType.Relation) { break; } // calculate tile. var r = (current as Relation); if (r?.Members == null) { continue; } int?mask = 0; foreach (var member in r.Members) { if (member == null) { Log.Warning($"Member of relation {r.Id} is null!"); continue; } switch (member.Type) { case OsmGeoType.Node: if (nodeIndex != null && nodeIndex.TryGetMask(member.Id, out var nodeMask)) { mask |= nodeMask; } break; case OsmGeoType.Way: if (wayIndex != null && wayIndex.TryGetMask(member.Id, out var wayMask)) { mask |= wayMask; } break; case OsmGeoType.Relation: //mask = null; break; default: throw new ArgumentOutOfRangeException(); } if (mask == null) { // fail fast. break; } } if (mask == null) { // could not determine mask. continue; } // add relation to output(s). foreach (var relationTile in tile.SubTilesForMask2(mask.Value)) { // is tile a subtile. if (!subtiles.TryGetValue(relationTile.LocalId, out var stream)) { continue; } // initialize stream if needed. if (stream == null) { stream = DatabaseCommon.CreateTile(path, OsmGeoType.Relation, relationTile, compressed); subtiles[relationTile.LocalId] = stream; } // write way. stream.Append(r); } // add way to index. relationIndex.Add(r.Id.Value, mask.Value); } while (source.MoveNext()); // flush/dispose all subtile streams. foreach (var subtile in subtiles) { if (subtile.Value == null) { continue; } subtile.Value.Flush(); subtile.Value.Dispose(); } return(relationIndex); } catch (Exception ex) { Console.WriteLine($"Unhandled exception in {nameof(RelationProcessor)}.{nameof(Process)}: {ex}"); throw; } }
/// <summary> /// Processes the nodes in the given stream until the first on-node object is reached. /// </summary> /// <param name="source">The source stream.</param> /// <param name="path">The based path of the db.</param> /// <param name="maxZoom">The maximum zoom.</param> /// <param name="tile">The tile being split.</param> /// <param name="nonEmptyTiles">The subtiles that have data in them.</param> /// <param name="hasNext">A flag indicating if there is still more data.</param> /// <param name="compressed">A flag to allow compression of target files.</param> /// <returns>The indexed node id's with a masked zoom.</returns> public static Index Process(OsmStreamSource source, string path, uint maxZoom, Tile tile, out List <Tile> nonEmptyTiles, out bool hasNext, bool compressed = false) { try { // build the set of possible subtiles. var subtiles = new Dictionary <ulong, Stream>(); foreach (var subTile in tile.GetSubtilesAt(tile.Zoom + 2)) { subtiles.Add(subTile.LocalId, null); } // go over all nodes. var nodeIndex = new Index(); hasNext = false; while (source.MoveNext()) { var current = source.Current(); if (current.Type != OsmGeoType.Node) { hasNext = true; break; } // calculate tile. var n = (current as Node); var nodeTile = Tiles.Tile.WorldToTileIndex(n.Latitude.Value, n.Longitude.Value, tile.Zoom + 2); // is tile a subtile. if (!subtiles.TryGetValue(nodeTile.LocalId, out var stream)) { continue; } // initialize stream if needed. if (stream == null) { stream = DatabaseCommon.CreateTile(path, OsmGeoType.Node, nodeTile, compressed); subtiles[nodeTile.LocalId] = stream; } // write node. stream.Append(n); // add node to index. nodeIndex.Add(n.Id.Value, nodeTile.BuildMask2()); } // flush/dispose all subtile streams. // keep all non-empty tiles. nonEmptyTiles = new List <Tile>(); foreach (var subtile in subtiles) { if (subtile.Value == null) { continue; } subtile.Value.Flush(); subtile.Value.Dispose(); if (tile.Zoom + 2 < maxZoom) { nonEmptyTiles.Add(Tile.FromLocalId(tile.Zoom + 2, subtile.Key)); } } return(nodeIndex); } catch (Exception ex) { Console.WriteLine($"Unhandled exception in {nameof(NodeProcessor)}.{nameof(Process)}: {ex}"); throw; } }
/// <summary> /// Processes the ways in the given stream until the first on-way object is reached. Assumed the current stream position already contains a way. /// </summary> /// <param name="source">The source stream.</param> /// <param name="path">The based path of the db.</param> /// <param name="maxZoom">The maximum zoom.</param> /// <param name="tile">The tile being split.</param> /// <param name="nodeIndex">The node index.</param> /// <param name="compressed">A flag to allow compression of target files.</param> /// <returns>The indexed node id's with a masked zoom.</returns> public static Index Process(OsmStreamSource source, string path, uint maxZoom, Tile tile, Index nodeIndex, bool compressed = false) { try { // split ways. var subtiles = new Dictionary <ulong, Stream>(); foreach (var subTile in tile.GetSubtilesAt(tile.Zoom + 2)) { subtiles.Add(subTile.LocalId, null); } // build the ways index. var wayIndex = new Index(); do { var current = source.Current(); if (current.Type != OsmGeoType.Way) { break; } // calculate tile. var w = (current as Way); if (w.Nodes == null) { continue; } var mask = 0; foreach (var node in w.Nodes) { if (nodeIndex.TryGetMask(node, out var nodeMask)) { mask |= nodeMask; } } // add way to output(s). foreach (var wayTile in tile.SubTilesForMask2(mask)) { // is tile a subtile. if (!subtiles.TryGetValue(wayTile.LocalId, out var stream)) { continue; } // initialize stream if needed. if (stream == null) { stream = DatabaseCommon.CreateTile(path, OsmGeoType.Way, wayTile, compressed); subtiles[wayTile.LocalId] = stream; } // write way. stream.Append(w); } // add way to index. wayIndex.Add(w.Id.Value, mask); } while (source.MoveNext()); // flush/dispose all subtile streams. foreach (var subtile in subtiles) { if (subtile.Value == null) { continue; } subtile.Value.Flush(); subtile.Value.Dispose(); } return(wayIndex); } catch (Exception ex) { Console.WriteLine($"Unhandled exception in {nameof(WayProcessor)}.{nameof(Process)}: {ex}"); throw; } }