public bool ReadRelationDirect(long relationID, out OsmRelation osmRelation, out OsmWay[] osmWays, out OsmNode[] osmNodes) { var rels = pbfReader.ReadRelations(relationID); if (rels.Length == 0) { osmRelation = default(OsmRelation); osmWays = new OsmWay[0]; osmNodes = new OsmNode[0]; return(false); } osmRelation = rels.First(); osmWays = pbfReader.ReadWays(osmRelation.members.Where(x => x.type == MemberType.Way).Select(x => x.id).ToArray()); Array.Sort(osmWays, (x, y) => x.id.CompareTo(y.id)); int wayCount = 1; for (int i = 1; i < osmWays.Length; i++) { if (osmWays[i - 1].id == osmWays[i].id) { continue; } osmWays[wayCount++] = osmWays[i]; } Array.Resize(ref osmWays, wayCount); osmNodes = pbfReader.ReadNodes(osmWays.SelectMany(x => x.nodeIds).Concat(osmRelation.members.Where(x => x.type == MemberType.Node).Select(x => x.id)).ToArray()); Array.Sort(osmNodes, (x, y) => x.id.CompareTo(y.id)); int nodeCount = 1; for (int i = 1; i < osmNodes.Length; i++) { if (osmNodes[i - 1].id == osmNodes[i].id) { continue; } osmNodes[nodeCount++] = osmNodes[i]; } Array.Resize(ref osmNodes, nodeCount); return(true); }
static void ParseTest() { using (var pbf = new OsmPbfReader(PbfPath)) { //long testRelationID = 418713; // Herrnhut (Germany) //long testRelationID = 62422; // Berlin //long testRelationID = 62504; // Brandenburg (Germany) - https://www.openstreetmap.org/relation/62504 //long testRelationID = 1434381; // Insel Rügen (Germany) long testRelationID = 51477; // Germany //long testRelationID = 2214684; // La Gomera (Canarias) //long testRelationID = 2182003; // Menorca (Balearic Islands) //long testRelationID = 11775386; // La Palma (Canarias) var relations = pbf.ReadRelations(testRelationID); //var relations = pbf.ReadRelations(418713, 62422, 62504, 1434381, 51477, 2214684, 2182003, 11775386); for (; ;) // untergeordnete Relationen einlesen { var needRelations = new List <long>(); foreach (var r in relations) { foreach (var sub in r.members.Where(x => x.type == MemberType.Relation)) { if (relations.Any(x => x.id == sub.id)) { continue; } needRelations.Add(sub.id); } } if (needRelations.Count == 0) { break; } relations = relations.Concat(pbf.ReadRelations(needRelations.ToArray())).ToArray(relations.Length + needRelations.Count); break; } var ways = pbf.ReadWays(relations.SelectMany(r => r.members.Where(x => x.type == MemberType.Way).Select(x => x.id)).ToArray()); Array.Sort(ways, (x, y) => x.id.CompareTo(y.id)); var nodes = pbf.ReadNodes(relations.SelectMany(r => r.members.Where(x => x.type == MemberType.Node).Select(x => x.id)).Concat(ways.SelectMany(w => w.nodeIds)).ToArray()); Array.Sort(nodes, (x, y) => x.id.CompareTo(y.id)); Console.WriteLine("nodes: {0:N0}", nodes.Length); var knownNodes = new HashSet <long>(); Func <StreamWriter, long, string, int> writePath = null; writePath = (wdat, relationId, type) => { int count = 0; var rel = relations.FirstOrDefault(x => x.id == relationId); if (rel.id == 0) { return(0); } foreach (var member in rel.members) { switch (member.type) { case MemberType.Node: break; // skip case MemberType.Way: { if (member.role == type) { var way = ways.BinarySearchSingle(w => w.id - member.id); foreach (var nodeId in way.nodeIds) { if (knownNodes.Contains(nodeId)) { continue; } knownNodes.Add(nodeId); var node = nodes.BinarySearchSingle(n => n.id - nodeId); wdat.WriteLine(node.latCode + "," + node.lonCode); count++; } } } break; case MemberType.Relation: count += writePath(wdat, member.id, type); break; } } return(count); }; using (var wdat = new StreamWriter(testRelationID + "_outer.txt")) { writePath(wdat, testRelationID, "outer"); } using (var wdat = new StreamWriter(testRelationID + "_inner.txt")) { writePath(wdat, testRelationID, "inner"); } } }
static void MappingTest() { //long[] relIds = { 3920249L }; //long[] relIds = { 3459013L }; long[] relIds = { 62504L }; // Brandenburg //long[] relIds = { 51477L }; // Deutschland using (var pbf = new OsmPbfReader(PbfPath)) { foreach (long relId in relIds) { OsmNode[] nodesPath; if (File.Exists("path_cache_" + relId + ".dat")) { byte[] buf = File.ReadAllBytes("path_cache_" + relId + ".dat"); int len = ReadNodesPath(buf, 0, out nodesPath); if (len != buf.Length) { throw new IOException(); } } else { var rels = pbf.ReadRelations(relIds); var ways = pbf.ReadWays(rels.First().members.Where(x => x.type == MemberType.Way).Select(x => x.id).ToArray()); var nodes = pbf.ReadNodes(ways.SelectMany(x => x.nodeIds).ToArray()); nodesPath = GetPath(ways, nodes).ToArray(); byte[] buf = new byte[1048576 * 256]; int len = WriteNodesPath(buf, 0, nodesPath); Array.Resize(ref buf, len); File.WriteAllBytes("path_cache_" + relId + ".dat", buf); } var polyLines = new List <GpsLine>(); for (int i = 1; i < nodesPath.Length; i++) { if (nodesPath[i - 1].latCode >= nodesPath[i].latCode) { polyLines.Add(new GpsLine(new GpsPos(nodesPath[i - 1]), new GpsPos(nodesPath[i]))); } else { polyLines.Add(new GpsLine(new GpsPos(nodesPath[i]), new GpsPos(nodesPath[i - 1]))); } } polyLines.Sort((x, y) => x.pos1.posY.CompareTo(y.pos1.posY)); // --- init --- int maxLinesPerStripe = (int)(Math.Sqrt(nodesPath.Length) * 0.3) + 1; maxLinesPerStripe = 0; int limitStripes = polyLines.GroupBy(line => line.pos1.posY).Max(g => g.Count()); if (maxLinesPerStripe < limitStripes) { maxLinesPerStripe = limitStripes; } var firstLines = new List <GpsLine>(); foreach (var line in polyLines) { if (firstLines.Count >= maxLinesPerStripe && firstLines.Last().pos1.posY < line.pos1.posY) { break; } firstLines.Add(line); } var stripes = new List <Tuple <uint, uint, List <GpsLine> > > { new Tuple <uint, uint, List <GpsLine> >(firstLines.First().pos1.posY, firstLines.Last().pos1.posY, firstLines) }; for (; ;) { uint startY = stripes.Last().Item2; var nextLines = polyLines.Where(line => line.pos1.posY < startY && line.pos2.posY >= startY).ToList(); int maxCount = nextLines.Count + maxLinesPerStripe; foreach (var line in polyLines) { if (line.pos1.posY >= startY) { if (nextLines.Count > maxCount && nextLines.Last().pos1.posY < line.pos1.posY) { break; } nextLines.Add(line); } } stripes.Add(new Tuple <uint, uint, List <GpsLine> >(nextLines.First().pos1.posY, nextLines.Last().pos1.posY, nextLines)); if (Equals(nextLines.Last(), polyLines.Last())) { break; } } int sumStripes1 = stripes.Sum(s => s.Item3.Count); stripes.Add(new Tuple <uint, uint, List <GpsLine> >(stripes.Last().Item2 + 1, stripes.Last().Item2, new List <GpsLine>())); var fastStripes = stripes.Select((x, i) => new GpsStripe(i == 0 ? x.Item1 : stripes[i - 1].Item2, x.Item2, x.Item3.ToArray())).ToArray(); DrawTest(nodesPath, polyLines, fastStripes); } } }