/// <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 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> /// 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); } }