|
13 | 13 | using System.IO;
|
14 | 14 | using System.Web;
|
15 | 15 | using Microsoft.Extensions.Logging;
|
| 16 | +using OsmSharp.Db; |
16 | 17 |
|
17 | 18 | namespace OsmSharp.IO.API
|
18 | 19 | {
|
@@ -342,19 +343,57 @@ public async Task<Relation[]> GetRelations(IEnumerable<KeyValuePair<long, long?>
|
342 | 343 | return await GetElements<Relation>(idVersions);
|
343 | 344 | }
|
344 | 345 |
|
| 346 | + public async Task<OsmGeo[]> GetElements(params OsmGeoKey[] elementKeys) |
| 347 | + { |
| 348 | + return await GetElements(elementKeys.ToDictionary(ek => ek, ek => (long?)null)); |
| 349 | + } |
| 350 | + |
| 351 | + public async Task<OsmGeo[]> GetElements(Dictionary<OsmGeoKey, long?> elementKeyVersions) |
| 352 | + { |
| 353 | + var elements = new List<OsmGeo>(); |
| 354 | + |
| 355 | + foreach (var typeGroup in elementKeyVersions.GroupBy(kvp => kvp.Key.Type)) |
| 356 | + { |
| 357 | + var chunkAsDictionary = typeGroup.ToDictionary(kvp => kvp.Key.Id, kvp => kvp.Value); |
| 358 | + if(typeGroup.Key == OsmGeoType.Node) |
| 359 | + elements.AddRange(await GetElements<Node>(chunkAsDictionary)); |
| 360 | + else if (typeGroup.Key == OsmGeoType.Way) |
| 361 | + elements.AddRange(await GetElements<Way>(chunkAsDictionary)); |
| 362 | + else if (typeGroup.Key == OsmGeoType.Relation) |
| 363 | + elements.AddRange(await GetElements<Relation>(chunkAsDictionary)); |
| 364 | + } |
| 365 | + |
| 366 | + return elements.ToArray(); |
| 367 | + } |
| 368 | + |
345 | 369 | /// <summary>
|
346 | 370 | /// Elements Multifetch
|
347 | 371 | /// <see href="https://wiki.openstreetmap.org/wiki/API_v0.6#Multi_fetch:_GET_.2Fapi.2F0.6.2F.5Bnodes.7Cways.7Crelations.5D.3F.23parameters">
|
348 | 372 | /// GET /api/0.6/[nodes|ways|relations]?#parameters</see>.
|
349 | 373 | /// </summary>
|
350 | 374 | private async Task<TOsmGeo[]> GetElements<TOsmGeo>(IEnumerable<KeyValuePair<long, long?>> idVersions) where TOsmGeo : OsmGeo, new()
|
351 | 375 | {
|
352 |
| - var type = new TOsmGeo().Type.ToString().ToLower(); |
353 |
| - // For exmple: "12,13,14v1,15v1" |
354 |
| - var parameters = string.Join(",", idVersions.Select(e => e.Value.HasValue ? $"{e.Key}v{e.Value}" : e.Key.ToString())); |
355 |
| - var address = BaseAddress + $"0.6/{type}s?{type}s={parameters}"; |
356 |
| - var elements = await GetOfType<TOsmGeo>(address); |
357 |
| - return elements.ToArray(); |
| 376 | + var tasks = new List<Task<IEnumerable<TOsmGeo>>>(); |
| 377 | + |
| 378 | + foreach (var chunk in Chunks(idVersions, 400)) // to avoid http error code 414, UIR too long. |
| 379 | + { |
| 380 | + var type = new TOsmGeo().Type.ToString().ToLower(); |
| 381 | + // For exmple: "12,13,14v1,15v1" |
| 382 | + var parameters = string.Join(",", idVersions.Select(e => e.Value.HasValue ? $"{e.Key}v{e.Value}" : e.Key.ToString())); |
| 383 | + var address = BaseAddress + $"0.6/{type}s?{type}s={parameters}"; |
| 384 | + tasks.Add(GetOfType<TOsmGeo>(address)); |
| 385 | + } |
| 386 | + |
| 387 | + await Task.WhenAll(tasks); |
| 388 | + |
| 389 | + return tasks.SelectMany(t => t.Result).ToArray(); |
| 390 | + } |
| 391 | + |
| 392 | + private IEnumerable<T[]> Chunks<T>(IEnumerable<T> elements, int chunkSize) |
| 393 | + { |
| 394 | + return elements.Select((e, i) => new { e, i }) |
| 395 | + .GroupBy(ei => ei.i / chunkSize) // Intentional integer division |
| 396 | + .Select(g => g.Select(ei => ei.e).ToArray()); |
358 | 397 | }
|
359 | 398 |
|
360 | 399 | /// <summary>
|
|
0 commit comments