/// <summary> /// Converts a PBF way into an OsmSharp-way. /// </summary> public static OsmSharp.Way DecodeWay(PrimitiveBlock block, OsmSharp.IO.PBF.Way pbfWay) { var way = new OsmSharp.Way(); Encoder.DecodeWay(block, pbfWay, way); return(way); }
/// <summary> /// Encodes an OsmSharp-node into a PBF-node. /// </summary> public static OsmSharp.IO.PBF.Node EncodeNode(PrimitiveBlock block, Dictionary <string, int> reverseStringTable, OsmSharp.Node node) { var pbfNode = new OsmSharp.IO.PBF.Node(); Encoder.EncodeNode(block, reverseStringTable, pbfNode, node); return(pbfNode); }
/// <summary> /// Converts a PBF-way into an OsmSharp-way. /// </summary> public static void DecodeWay(PrimitiveBlock block, OsmSharp.IO.PBF.Way pbfWay, OsmSharp.Way way) { // make sure old data is gone. if (way.Nodes != null && way.Nodes.Length > 0) { // clear nodes list. way.Nodes = new long[pbfWay.refs.Count]; } if (way.Tags != null) { // clear the tags collection. way.Tags.Clear(); } if (way.Nodes == null) { // create nodes list. way.Nodes = new long[pbfWay.refs.Count]; } if (way.Tags == null) { // create tags collection. way.Tags = new TagsCollection(pbfWay.keys.Count); } // set new stuff. way.Id = pbfWay.id; if (pbfWay.refs.Count > 0) { // fill nodes-list. long nodeId = 0; for (int i = 0; i < pbfWay.refs.Count; i++) { nodeId = nodeId + pbfWay.refs[i]; way.Nodes[i] = nodeId; } } if (pbfWay.keys.Count > 0) { for (var i = 0; i < pbfWay.keys.Count; i++) { var key = System.Text.Encoding.UTF8.GetString(block.stringtable.s[(int)pbfWay.keys[i]]); var value = System.Text.Encoding.UTF8.GetString(block.stringtable.s[(int)pbfWay.vals[i]]); if (!way.Tags.TryAdd(key, value)) { // Addition of the tag failed Logger.Log("invalid tag", TraceEventType.Error, $"Could not add tag `{key}={value}` to the tagscollection of osm.org/way/{way.Id} - possible duplicate keys?"); } } } if (pbfWay.info != null) { // add the metadata if any. way.ChangeSetId = pbfWay.info.changeset; way.TimeStamp = Encoder.DecodeTimestamp(pbfWay.info.timestamp, block.date_granularity); way.UserId = pbfWay.info.uid; way.UserName = null; if (block.stringtable != null) { way.UserName = System.Text.Encoding.UTF8.GetString(block.stringtable.s[pbfWay.info.user_sid]); } way.Version = pbfWay.info.version; } way.Visible = true; }
/// <summary> /// Encodes a string. /// </summary> /// <returns></returns> public static int EncodeString(PrimitiveBlock block, Dictionary <string, int> reverseStringTable, string value) { if (value == null) { return(0); } if (block.stringtable == null) { block.stringtable = new StringTable(); block.stringtable.s.Add(System.Text.Encoding.UTF8.GetBytes(string.Empty)); reverseStringTable.Add(string.Empty, 0); } int id; if (reverseStringTable.TryGetValue(value, out id)) { return(id); } block.stringtable.s.Add(System.Text.Encoding.UTF8.GetBytes(value)); reverseStringTable.Add(value, block.stringtable.s.Count - 1); return(block.stringtable.s.Count - 1); }
/// <summary> /// Converts the PBF node into an OsmSharp-node. /// </summary> public static OsmSharp.Node DecodeNode(PrimitiveBlock block, OsmSharp.IO.PBF.Node pbfNode) { var node = new OsmSharp.Node(); Encoder.DecodeNode(block, pbfNode, node); return(node); }
/// <summary> /// Converts a PBF way into an OsmSharp-relation. /// </summary> public static OsmSharp.Relation DecodeRelation(PrimitiveBlock block, OsmSharp.IO.PBF.Relation pbfRelation) { var relation = new OsmSharp.Relation(); Encoder.DecodeRelation(block, pbfRelation, relation); return(relation); }
/// <summary> /// Encodes an OsmSharp-node into a PBF-node. /// </summary> public static OsmSharp.IO.PBF.Node EncodeNode(PrimitiveBlock block, Dictionary <string, int> reverseStringTable, OsmSharp.IO.PBF.Node pbfNode, OsmSharp.Node node) { pbfNode.id = node.Id.Value; pbfNode.info = new Info(); pbfNode.info.version = 0; if (node.ChangeSetId.HasValue) { pbfNode.info.changeset = node.ChangeSetId.Value; } else { pbfNode.info.changeset = 0; } if (node.TimeStamp.HasValue) { pbfNode.info.timestamp = Encoder.EncodeTimestamp(node.TimeStamp.Value, block.date_granularity); } else { pbfNode.info.timestamp = 0; } if (node.UserId.HasValue) { pbfNode.info.uid = (int)node.UserId.Value; } else { pbfNode.info.uid = 0; } pbfNode.info.user_sid = Encoder.EncodeString(block, reverseStringTable, node.UserName); if (node.Version.HasValue) { pbfNode.info.version = (int)node.Version.Value; } else { pbfNode.info.version = 0; } pbfNode.lat = Encoder.EncodeLatLon(node.Latitude.Value, block.lat_offset, block.granularity); pbfNode.lon = Encoder.EncodeLatLon(node.Longitude.Value, block.lon_offset, block.granularity); if (node.Tags != null) { foreach (var tag in node.Tags) { pbfNode.keys.Add((uint)Encoder.EncodeString(block, reverseStringTable, tag.Key)); pbfNode.vals.Add((uint)Encoder.EncodeString(block, reverseStringTable, tag.Value)); } } else { pbfNode.keys.Clear(); pbfNode.vals.Clear(); } return(pbfNode); }
/// <summary> /// Writes one PBF primitive block. /// </summary> /// <param name="block">The block to write.</param> public void ReadAll(PrimitiveBlock block) { // check parameters. if (block == null) { throw new ArgumentNullException("block"); } // TODO: all the important stuff! }
/// <summary> /// Encodes an OsmSharp-way into a PBF-way. /// </summary> public static OsmSharp.IO.PBF.Way EncodeWay(PrimitiveBlock block, Dictionary <string, int> reverseStringTable, OsmSharp.Way way) { var pbfWay = new OsmSharp.IO.PBF.Way(); pbfWay.id = way.Id.Value; pbfWay.info = new Info(); if (way.ChangeSetId.HasValue) { pbfWay.info.changeset = way.ChangeSetId.Value; } if (way.TimeStamp.HasValue) { pbfWay.info.timestamp = Encoder.EncodeTimestamp(way.TimeStamp.Value, block.date_granularity); } if (way.UserId.HasValue) { pbfWay.info.uid = (int)way.UserId.Value; } pbfWay.info.user_sid = Encoder.EncodeString(block, reverseStringTable, way.UserName); pbfWay.info.version = 0; if (way.Version.HasValue) { pbfWay.info.version = (int)way.Version.Value; } if (way.Tags != null) { foreach (var tag in way.Tags) { pbfWay.keys.Add((uint)Encoder.EncodeString(block, reverseStringTable, tag.Key)); pbfWay.vals.Add((uint)Encoder.EncodeString(block, reverseStringTable, tag.Value)); } } if (way.Nodes != null && way.Nodes.Length > 0) { pbfWay.refs.Add(way.Nodes[0]); for (var i = 1; i < way.Nodes.Length; i++) { pbfWay.refs.Add(way.Nodes[i] - way.Nodes[i - 1]); } } return(pbfWay); }
/// <summary> /// Converts the PBF node into an OsmSharp-node. /// </summary> /// <returns></returns> public static OsmSharp.Node DecodeNode(PrimitiveBlock block, OsmSharp.IO.PBF.Node pbfNode, OsmSharp.Node node) { // clear old data. if (node.Tags != null) { // clear tags. node.Tags.Clear(); } if (node.Tags == null) { // create tags collection. node.Tags = new TagsCollection(0); } // set new stuff. node.ChangeSetId = pbfNode.info.changeset; node.Id = pbfNode.id; node.Latitude = Encoder.DecodeLatLon(pbfNode.lat, block.lat_offset, block.granularity); node.Longitude = Encoder.DecodeLatLon(pbfNode.lon, block.lon_offset, block.granularity); for (var i = 0; i < pbfNode.keys.Count; i++) { var key = System.Text.Encoding.UTF8.GetString(block.stringtable.s[(int)pbfNode.keys[i]]); var value = System.Text.Encoding.UTF8.GetString(block.stringtable.s[(int)pbfNode.vals[i]]); if (!node.Tags.TryAdd(key, value)) { // Addition of the tag failed Logger.Log("invalid tag", TraceEventType.Error, $"Could not add tag `{key}={value}` to the tagscollection of osm.org/node/{node.Id} - possible duplicate keys?"); } } if (pbfNode.info != null) { // add the metadata if any. node.TimeStamp = Encoder.DecodeTimestamp(pbfNode.info.timestamp, block.date_granularity); node.Visible = true; node.Version = pbfNode.info.version; node.UserId = pbfNode.info.uid; node.UserName = null; if (block.stringtable != null) { node.UserName = System.Text.Encoding.UTF8.GetString(block.stringtable.s[pbfNode.info.user_sid]); } } node.Visible = true; return(node); }
private static void EncodeDenseNode(PrimitiveBlock block, Dictionary <string, int> reverseStringTable, DenseNodes groupDense, OsmSharp.Node current, OsmSharp.Node previous) { groupDense.id.Add(current.Id.Value - previous.Id.Value); var currentLat = Encoder.EncodeLatLon(current.Latitude.Value, block.lat_offset, block.granularity); var currentLon = Encoder.EncodeLatLon(current.Longitude.Value, block.lon_offset, block.granularity); var previousLat = Encoder.EncodeLatLon(previous.Latitude.Value, block.lat_offset, block.granularity); var previousLon = Encoder.EncodeLatLon(previous.Longitude.Value, block.lon_offset, block.granularity); // Note that the offsets are actually cancelled out by the subtraction below // LatDiff equals (current.Latitude - previous.Latitude) * 100000000 / granularity var latDiff = currentLat - previousLat; var lonDiff = currentLon - previousLon; groupDense.lat.Add(latDiff); groupDense.lon.Add(lonDiff); if (current.Tags != null) { foreach (var nodeTag in current.Tags) { groupDense.keys_vals.Add(Encoder.EncodeString(block, reverseStringTable, nodeTag.Key)); groupDense.keys_vals.Add(Encoder.EncodeString(block, reverseStringTable, nodeTag.Value)); } groupDense.keys_vals.Add(0); } if (groupDense.denseinfo != null) { groupDense.denseinfo.changeset.Add(current.ChangeSetId.Value - previous.ChangeSetId.Value); var currentTimeStamp = Encoder.EncodeTimestamp(current.TimeStamp.Value, block.date_granularity); var previousTimeStamp = previous.TimeStamp == null ? 0 : Encoder.EncodeTimestamp(previous.TimeStamp.Value, block.date_granularity); groupDense.denseinfo.timestamp.Add(currentTimeStamp - previousTimeStamp); groupDense.denseinfo.uid.Add((int)(current.UserId.Value - previous.UserId.Value)); groupDense.denseinfo.version.Add((int)(current.Version.Value - previous.Version.Value)); var previousUserNameId = previous.UserName == null ? 0 : Encoder.EncodeString(block, reverseStringTable, previous.UserName); var currentUserNameId = Encoder.EncodeString(block, reverseStringTable, current.UserName); groupDense.denseinfo.user_sid.Add(currentUserNameId - previousUserNameId); } }
/// <summary> /// Converts the PBF node into an OsmSharp-node. /// </summary> /// <returns></returns> public static OsmSharp.Node DecodeNode(PrimitiveBlock block, OsmSharp.IO.PBF.Node pbfNode, OsmSharp.Node node) { // clear old data. if (node.Tags != null) { // clear tags. node.Tags.Clear(); } if (node.Tags == null) { // create tags collection. node.Tags = new TagsCollection(); } // set new stuff. node.ChangeSetId = pbfNode.info.changeset; node.Id = pbfNode.id; node.Latitude = Encoder.DecodeLatLon(pbfNode.lat, block.lat_offset, block.granularity); node.Longitude = Encoder.DecodeLatLon(pbfNode.lon, block.lon_offset, block.granularity); for (var i = 0; i < pbfNode.keys.Count; i++) { node.Tags.Add(new Tag() { Key = System.Text.Encoding.UTF8.GetString(block.stringtable.s[(int)pbfNode.keys[i]]), Value = System.Text.Encoding.UTF8.GetString(block.stringtable.s[(int)pbfNode.vals[i]]) }); } if (pbfNode.info != null) { // add the metadata if any. node.TimeStamp = Encoder.DecodeTimestamp(pbfNode.info.timestamp, block.date_granularity); node.Visible = true; node.Version = pbfNode.info.version; node.UserId = pbfNode.info.uid; node.UserName = null; if (block.stringtable != null) { node.UserName = System.Text.Encoding.UTF8.GetString(block.stringtable.s[pbfNode.info.user_sid]); } } node.Visible = true; return(node); }
/// <summary> /// Converts a PBF way into an OsmSharp-relation. /// </summary> public static OsmSharp.Relation DecodeRelation(PrimitiveBlock block, OsmSharp.IO.PBF.Relation pbfRelation, OsmSharp.Relation relation) { // make sure old data is gone. if (relation.Members != null && relation.Members.Length > 0) { // clear members. relation.Members = new RelationMember[pbfRelation.memids.Count]; } if (relation.Tags != null) { // clear the tags collection. relation.Tags.Clear(); } if (relation.Members == null) { // clear members. relation.Members = new RelationMember[pbfRelation.memids.Count]; } if (relation.Tags == null) { // create tags collection. relation.Tags = new TagsCollection(pbfRelation.keys.Count); } // add nex stuff. relation.Id = pbfRelation.id; long memberId = 0; for (var i = 0; i < pbfRelation.types.Count; i++) { memberId = memberId + pbfRelation.memids[i]; var role = System.Text.Encoding.UTF8.GetString( block.stringtable.s[pbfRelation.roles_sid[i]]); var member = new OsmSharp.RelationMember(); member.Id = memberId; member.Role = role; switch (pbfRelation.types[i]) { case Relation.MemberType.NODE: member.Type = OsmSharp.OsmGeoType.Node; break; case Relation.MemberType.WAY: member.Type = OsmSharp.OsmGeoType.Way; break; case Relation.MemberType.RELATION: member.Type = OsmSharp.OsmGeoType.Relation; break; } relation.Members[i] = member; } for (int i = 0; i < pbfRelation.keys.Count; i++) { string key = System.Text.Encoding.UTF8.GetString(block.stringtable.s[(int)pbfRelation.keys[i]]); string value = System.Text.Encoding.UTF8.GetString(block.stringtable.s[(int)pbfRelation.vals[i]]); relation.Tags.Add(new Tag(key, value)); } if (pbfRelation.info != null) { // read metadata if any. relation.ChangeSetId = pbfRelation.info.changeset; relation.TimeStamp = Encoder.DecodeTimestamp(pbfRelation.info.timestamp, block.date_granularity); relation.UserId = pbfRelation.info.uid; relation.UserName = null; if (block.stringtable != null) { relation.UserName = System.Text.Encoding.UTF8.GetString(block.stringtable.s[pbfRelation.info.user_sid]); } relation.Version = pbfRelation.info.version; } relation.Visible = true; return(relation); }
/// <summary> /// Encodes the nodes into the given block. /// </summary> public static void Encode(this PrimitiveBlock block, Dictionary <string, int> reverseStringTable, List <OsmGeo> osmGeos, bool compressed) { var groupIdx = 0; var i = 0; if (block.stringtable != null && block.stringtable.s != null) { block.stringtable.s.Clear(); } while (i < osmGeos.Count) { PrimitiveGroup group = null; if (groupIdx < block.primitivegroup.Count) { // get the existing group and clear it's data. group = block.primitivegroup[groupIdx]; if (group == null) { group = new PrimitiveGroup(); } if (group.dense != null) { if (group.dense.denseinfo != null) { if (group.dense.denseinfo.changeset != null) { group.dense.denseinfo.changeset.Clear(); } if (group.dense.denseinfo.timestamp != null) { group.dense.denseinfo.timestamp.Clear(); } if (group.dense.denseinfo.uid != null) { group.dense.denseinfo.uid.Clear(); } if (group.dense.denseinfo.user_sid != null) { group.dense.denseinfo.user_sid.Clear(); } if (group.dense.denseinfo.version != null) { group.dense.denseinfo.version.Clear(); } } if (group.dense.id != null) { group.dense.id.Clear(); } if (group.dense.keys_vals != null) { group.dense.keys_vals.Clear(); } if (group.dense.lat != null) { group.dense.lat.Clear(); } if (group.dense.lon != null) { group.dense.lon.Clear(); } } if (group.changesets != null) { group.changesets.Clear(); } //if (group.nodes != null) { group.nodes.Clear(); } if (group.ways != null) { group.ways.Clear(); } if (group.relations != null) { group.relations.Clear(); } } else { // add a new group. group = new PrimitiveGroup(); block.primitivegroup.Add(group); } // build group. var currentNodeCount = 0; var groupType = osmGeos[i].Type; var previousNode = new OsmSharp.Node { Id = 0, Longitude = 0, Latitude = 0, ChangeSetId = 0, TimeStamp = null, UserId = 0, UserName = null, Version = 0 }; if (groupType == OsmGeoType.Node && compressed && group.dense == null) { group.dense = new DenseNodes { denseinfo = new DenseInfo() }; } while (i < osmGeos.Count && osmGeos[i].Type == groupType) { switch (groupType) { case OsmGeoType.Node: if (compressed) { var currentNode = osmGeos[i] as OsmSharp.Node; Encoder.EncodeDenseNode(block, reverseStringTable, group.dense, currentNode, previousNode); previousNode = currentNode; } else { if (currentNodeCount < group.nodes.Count) { // overwrite existing. Encoder.EncodeNode(block, reverseStringTable, group.nodes[currentNodeCount], osmGeos[i] as OsmSharp.Node); } else { // write new. group.nodes.Add(Encoder.EncodeNode(block, reverseStringTable, osmGeos[i] as OsmSharp.Node)); } currentNodeCount++; } break; case OsmGeoType.Way: group.ways.Add(Encoder.EncodeWay(block, reverseStringTable, osmGeos[i] as OsmSharp.Way)); break; case OsmGeoType.Relation: group.relations.Add(Encoder.EncodeRelation(block, reverseStringTable, osmGeos[i] as OsmSharp.Relation)); break; } i++; } // remove obsolete nodes. if (group.nodes != null) { while (currentNodeCount < group.nodes.Count) { group.nodes.RemoveAt(currentNodeCount); } } // move to the next group. groupIdx++; } while (groupIdx < block.primitivegroup.Count) { block.primitivegroup.RemoveAt(groupIdx); } }
/// <summary> /// Moves to the next primitive block, returns null at the end. /// </summary> /// <returns></returns> public PrimitiveBlock MoveNext() { // make sure previous block data is removed. if (_block.primitivegroup != null) { _block.primitivegroup.Clear(); } if (_block.stringtable != null) { _block.stringtable.s.Clear(); } // read next block. PrimitiveBlock block = null; int length; bool notFoundBut = true; while (notFoundBut) { // continue if there is still data but not a primitiveblock. notFoundBut = false; // not found. if (Serializer.TryReadLengthPrefix(_stream, PrefixStyle.Fixed32BigEndian, out length)) { // TODO: remove some of the v1 specific code. // TODO: this means also to use the built-in capped streams. // code borrowed from: http://stackoverflow.com/questions/4663298/protobuf-net-deserialize-open-street-maps // I'm just being lazy and re-using something "close enough" here // note that v2 has a big-endian option, but Fixed32 assumes little-endian - we // actually need the other way around (network byte order): // length = IntLittleEndianToBigEndian((uint)length); BlobHeader header; // again, v2 has capped-streams built in, but I'm deliberately // limiting myself to v1 features using (var tmp = new LimitedStream(_stream, length)) { header = _runtimeTypeModel.Deserialize(tmp, null, _blockHeaderType) as BlobHeader; } Blob blob; using (var tmp = new LimitedStream(_stream, header.datasize)) { blob = _runtimeTypeModel.Deserialize(tmp, null, _blobType) as Blob; } // construct the source stream, compressed or not. Stream sourceStream = null; if (blob.zlib_data == null) { // use a regular uncompressed stream. sourceStream = new MemoryStream(blob.raw); } else { // construct a compressed stream. var ms = new MemoryStream(blob.zlib_data); sourceStream = new ZLibStreamWrapper(ms); } // use the stream to read the block. using (sourceStream) { if (header.type == Encoder.OSMHeader) { _runtimeTypeModel.Deserialize(sourceStream, null, _headerBlockType); notFoundBut = true; } if (header.type == Encoder.OSMData) { block = _runtimeTypeModel.Deserialize(sourceStream, _block, _primitiveBlockType) as PrimitiveBlock; } } } } return(block); }
/// <summary> /// Encodes the nodes into the given block. /// </summary> public static void Encode(this PrimitiveBlock block, Dictionary <string, int> reverseStringTable, List <OsmGeo> osmGeos) { var groupIdx = 0; var i = 0; var nodeCount = 0; if (block.stringtable != null && block.stringtable.s != null) { block.stringtable.s.Clear(); } while (i < osmGeos.Count) { PrimitiveGroup group = null; if (groupIdx < block.primitivegroup.Count) { // get the existing group and clear it's data. group = block.primitivegroup[groupIdx]; if (group == null) { group = new PrimitiveGroup(); } if (group.dense != null) { if (group.dense.denseinfo != null) { if (group.dense.denseinfo.changeset != null) { group.dense.denseinfo.changeset.Clear(); } if (group.dense.denseinfo.timestamp != null) { group.dense.denseinfo.timestamp.Clear(); } if (group.dense.denseinfo.uid != null) { group.dense.denseinfo.uid.Clear(); } if (group.dense.denseinfo.user_sid != null) { group.dense.denseinfo.user_sid.Clear(); } if (group.dense.denseinfo.version != null) { group.dense.denseinfo.version.Clear(); } } if (group.dense.id != null) { group.dense.id.Clear(); } if (group.dense.keys_vals != null) { group.dense.keys_vals.Clear(); } if (group.dense.lat != null) { group.dense.lat.Clear(); } if (group.dense.lon != null) { group.dense.lon.Clear(); } } if (group.changesets != null) { group.changesets.Clear(); } //if (group.nodes != null) { group.nodes.Clear(); } if (group.ways != null) { group.ways.Clear(); } if (group.relations != null) { group.relations.Clear(); } } else { // add a new group. group = new PrimitiveGroup(); block.primitivegroup.Add(group); } // build group. var groupType = osmGeos[i].Type; var current = osmGeos[i]; while (i < osmGeos.Count && osmGeos[i].Type == groupType) { switch (groupType) { case OsmGeoType.Node: if (group.nodes.Count > nodeCount) { // overwrite existing. Encoder.EncodeNode(block, reverseStringTable, group.nodes[nodeCount], osmGeos[i] as OsmSharp.Node); } else { // write new. group.nodes.Add(Encoder.EncodeNode(block, reverseStringTable, osmGeos[i] as OsmSharp.Node)); } nodeCount++; break; case OsmGeoType.Way: group.ways.Add(Encoder.EncodeWay(block, reverseStringTable, osmGeos[i] as OsmSharp.Way)); break; case OsmGeoType.Relation: group.relations.Add(Encoder.EncodeRelation(block, reverseStringTable, osmGeos[i] as OsmSharp.Relation)); break; } i++; } // remove obsolete nodes. if (group.nodes != null) { while (nodeCount < group.nodes.Count) { group.nodes.RemoveAt(nodeCount); } } // move to the next group. groupIdx++; } while (groupIdx < block.primitivegroup.Count) { block.primitivegroup.RemoveAt(groupIdx); } }
/// <summary> /// Encodes an OsmSharp-relation into a PBF-relation. /// </summary> /// <returns></returns> public static OsmSharp.IO.PBF.Relation EncodeRelation(PrimitiveBlock block, Dictionary <string, int> reverseStringTable, OsmSharp.Relation relation) { var pbfRelation = new OsmSharp.IO.PBF.Relation(); pbfRelation.id = relation.Id.Value; pbfRelation.info = new Info(); if (relation.ChangeSetId.HasValue) { pbfRelation.info.changeset = relation.ChangeSetId.Value; } if (relation.TimeStamp.HasValue) { pbfRelation.info.timestamp = Encoder.EncodeTimestamp(relation.TimeStamp.Value, block.date_granularity); } if (relation.UserId.HasValue) { pbfRelation.info.uid = (int)relation.UserId.Value; } pbfRelation.info.user_sid = Encoder.EncodeString(block, reverseStringTable, relation.UserName); pbfRelation.info.version = 0; if (relation.Version.HasValue) { pbfRelation.info.version = (int)relation.Version.Value; } if (relation.Tags != null) { foreach (var tag in relation.Tags) { pbfRelation.keys.Add((uint)Encoder.EncodeString(block, reverseStringTable, tag.Key)); pbfRelation.vals.Add((uint)Encoder.EncodeString(block, reverseStringTable, tag.Value)); } } if (relation.Members != null && relation.Members.Length > 0) { pbfRelation.memids.Add(relation.Members[0].Id); pbfRelation.roles_sid.Add(Encoder.EncodeString(block, reverseStringTable, relation.Members[0].Role)); switch (relation.Members[0].Type) { case OsmGeoType.Node: pbfRelation.types.Add(Relation.MemberType.NODE); break; case OsmGeoType.Way: pbfRelation.types.Add(Relation.MemberType.WAY); break; case OsmGeoType.Relation: pbfRelation.types.Add(Relation.MemberType.RELATION); break; } for (var i = 1; i < relation.Members.Length; i++) { pbfRelation.memids.Add(relation.Members[i].Id - relation.Members[i - 1].Id); pbfRelation.roles_sid.Add(Encoder.EncodeString(block, reverseStringTable, relation.Members[i].Role)); switch (relation.Members[i].Type) { case OsmGeoType.Node: pbfRelation.types.Add(Relation.MemberType.NODE); break; case OsmGeoType.Way: pbfRelation.types.Add(Relation.MemberType.WAY); break; case OsmGeoType.Relation: pbfRelation.types.Add(Relation.MemberType.RELATION); break; } } } return(pbfRelation); }
/// <summary> /// Decodes the block. /// </summary> public static bool Decode(this PrimitiveBlock block, IPBFOsmPrimitiveConsumer primitivesConsumer, bool ignoreNodes, bool ignoreWays, bool ignoreRelations, out bool hasNodes, out bool hasWays, out bool hasRelations) { var success = false; hasNodes = false; hasWays = false; hasRelations = false; if (block.primitivegroup != null) { foreach (var primitivegroup in block.primitivegroup) { if (primitivegroup.dense != null && primitivegroup.dense.id.Count > 0) { hasNodes = true; if (!ignoreNodes) { int keyValsIdx = 0; long currentId = 0; long currentLat = 0; long currentLon = 0; long currentChangeset = 0; long currentTimestamp = 0; int currentUid = 0; int currentUserSid = 0; int currentVersion = 0; for (int idx = 0; idx < primitivegroup.dense.id.Count; idx++) { // do the delta decoding stuff. currentId = currentId + primitivegroup.dense.id[idx]; currentLat = currentLat + primitivegroup.dense.lat[idx]; currentLon = currentLon + primitivegroup.dense.lon[idx]; if (primitivegroup.dense.denseinfo != null) { // add all the metadata. currentChangeset = currentChangeset + primitivegroup.dense.denseinfo.changeset[idx]; currentTimestamp = currentTimestamp + primitivegroup.dense.denseinfo.timestamp[idx]; currentUid = currentUid + primitivegroup.dense.denseinfo.uid[idx]; currentUserSid = currentUserSid + primitivegroup.dense.denseinfo.user_sid[idx]; currentVersion = currentVersion + primitivegroup.dense.denseinfo.version[idx]; } var node = new Node(); node.id = currentId; node.info = new Info(); node.info.changeset = currentChangeset; node.info.timestamp = (int)currentTimestamp; node.info.uid = currentUid; node.info.user_sid = currentUserSid; node.info.version = currentVersion; node.lat = currentLat; node.lon = currentLon; // get the keys/vals. var keyVals = primitivegroup.dense.keys_vals; while (keyVals.Count > keyValsIdx && keyVals[keyValsIdx] != 0) { node.keys.Add((uint)keyVals[keyValsIdx]); keyValsIdx++; node.vals.Add((uint)keyVals[keyValsIdx]); keyValsIdx++; } keyValsIdx++; success = true; hasNodes = true; primitivesConsumer.ProcessNode(block, node); } } } else { if (primitivegroup.nodes != null && primitivegroup.nodes.Count > 0) { hasNodes = true; if (!ignoreNodes) { foreach (var node in primitivegroup.nodes) { success = true; primitivesConsumer.ProcessNode(block, node); } } } if (primitivegroup.ways != null && primitivegroup.ways.Count > 0) { hasWays = true; if (!ignoreWays) { foreach (var way in primitivegroup.ways) { success = true; primitivesConsumer.ProcessWay(block, way); } } } if (primitivegroup.relations != null && primitivegroup.relations.Count > 0) { hasRelations = true; if (!ignoreRelations) { foreach (var relation in primitivegroup.relations) { success = true; primitivesConsumer.ProcessRelation(block, relation); } } } } } } return(success); }