public static int ReadBinary(byte[] buf, int ofs, out OsmRelation relation) { int p = 0; ulong tmp; p += ProtoBuf.ReadVarInt(buf, ofs + p, out tmp); long id = (long)tmp; p += ProtoBuf.ReadVarInt(buf, ofs + p, out tmp); var values = new KeyValuePair <string, string> [tmp]; for (int i = 0; i < values.Length; i++) { string key, val; p += ProtoBuf.ReadString(buf, ofs + p, out key); p += ProtoBuf.ReadString(buf, ofs + p, out val); values[i] = new KeyValuePair <string, string>(key, val); } p += ProtoBuf.ReadVarInt(buf, ofs + p, out tmp); var members = new OsmRelationMember[tmp]; for (int i = 0; i < members.Length; i++) { p += OsmRelationMember.ReadBinary(buf, ofs + p, out members[i]); } relation = new OsmRelation(id, values, members); return(p); }
/// <summary> /// liest ein oder mehrere OSM-Relationen ein und gibt die Ergebnisse in entsprechender Reihenfolge zurück /// </summary> /// <param name="relationIds">Relations-IDs, welche abgefragt werden sollen</param> /// <returns>abgefragte Relationen</returns> public OsmRelation[] ReadRelations(params long[] relationIds) { var result = new OsmRelation[relationIds.Length]; var searchRelations = Enumerable.Range(0, relationIds.Length).Select(i => new KeyValuePair <long, int>(relationIds[i], i)).ToArray(relationIds.Length); Array.Sort(searchRelations, (x, y) => x.Key.CompareTo(y.Key)); var needBlobs = new List <OsmBlob>(); var lastBlob = nodeIndex[0]; foreach (var relationId in searchRelations.Select(x => x.Key)) { if (relationId > lastBlob.maxRelationId || relationId < lastBlob.minRelationId) { lastBlob = relationIndex.BinarySearchSingle(x => relationId >= x.minRelationId && relationId <= x.maxRelationId ? 0L : x.minRelationId - relationId); needBlobs.Add(lastBlob); } } var blobDecoder = BlobSmtDecoder(needBlobs, (blob, buf) => { try { OsmRelation[] tmp; int len = PbfFast.DecodePrimitiveBlock(buf, 0, blob, out tmp); if (len != blob.rawSize) { throw new PbfParseException(); } return(tmp); } catch { return(null); } }).GetEnumerator(); OsmRelation[] relations = null; var tmpRelations = new List <OsmRelation[]>(); for (int r = 0; r < searchRelations.Length; r++) { long relationId = searchRelations[r].Key; if (relations == null || relations[relations.Length - 1].id < relationId) { relations = null; for (int i = 0; i < tmpRelations.Count; i++) { if (relationId >= tmpRelations[i].First().id&& relationId <= tmpRelations[i].Last().id) { relations = tmpRelations[i]; tmpRelations.RemoveAt(i); break; } } while (relations == null) { blobDecoder.MoveNext(); relations = blobDecoder.Current; if (relationId < relations.First().id || relationId > relations.Last().id) { tmpRelations.Add(relations); relations = null; } } Console.WriteLine("read relations: {0:N0} / {1:N0}", r + 1, searchRelations.Length); } result[searchRelations[r].Value] = relations.BinarySearchSingle(x => x.id - relationId); } return(result); }