added stitching

This commit is contained in:
Anton Martynenko
2025-10-29 11:21:59 +01:00
parent bbb112940d
commit 72eea71507
4 changed files with 179 additions and 48 deletions
@@ -144,5 +144,71 @@ public class GoogleMapsDownloaderV2
var metersPerPixel = (EARTH_CIRCUMFERENCE_METERS * Math.Cos(latRad)) / (Math.Pow(2, zoomLevel) * TILE_SIZE_PIXELS);
return metersPerPixel * TILE_SIZE_PIXELS;
}
public async Task<List<DownloadedTileInfoV2>> GetTilesWithMetadataAsync(GeoPoint centerGeoPoint, double radiusM, int zoomLevel, CancellationToken token = default)
{
if (!ALLOWED_ZOOM_LEVELS.Contains(zoomLevel))
{
throw new ArgumentException($"Zoom level {zoomLevel} is not allowed. Allowed zoom levels are: {string.Join(", ", ALLOWED_ZOOM_LEVELS)}", nameof(zoomLevel));
}
var (latMin, latMax, lonMin, lonMax) = GeoUtils.GetBoundingBox(centerGeoPoint, radiusM);
var (xMin, yMin) = GeoUtils.WorldToTilePos(new GeoPoint(latMax, lonMin), zoomLevel);
var (xMax, yMax) = GeoUtils.WorldToTilePos(new GeoPoint(latMin, lonMax), zoomLevel);
_logger.LogInformation("Downloading tiles for region: center=({Lat}, {Lon}), radius={Radius}m, zoom={Zoom}",
centerGeoPoint.Lat, centerGeoPoint.Lon, radiusM, zoomLevel);
_logger.LogInformation("Tile range: X=[{XMin}, {XMax}], Y=[{YMin}, {YMax}]", xMin, xMax, yMin, yMax);
var sessionToken = await GetSessionToken();
var downloadedTiles = new List<DownloadedTileInfoV2>();
for (var y = yMin; y <= yMax; y++)
{
for (var x = xMin; x <= xMax; x++)
{
token.ThrowIfCancellationRequested();
var tileCenter = GeoUtils.TileToWorldPos(x, y, zoomLevel);
var tileSizeMeters = CalculateTileSizeInMeters(zoomLevel, tileCenter.Lat);
var server = (x + y) % 4;
var url = string.Format(TILE_URL_TEMPLATE, server, x, y, zoomLevel, sessionToken);
Directory.CreateDirectory(_tilesDirectory);
var timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
var fileName = $"tile_{zoomLevel}_{x}_{y}_{timestamp}.jpg";
var filePath = Path.Combine(_tilesDirectory, fileName);
try
{
using var httpClient = _httpClientFactory.CreateClient();
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(USER_AGENT);
var response = await httpClient.GetAsync(url, token);
response.EnsureSuccessStatusCode();
var imageBytes = await response.Content.ReadAsByteArrayAsync(token);
await File.WriteAllBytesAsync(filePath, imageBytes, token);
_logger.LogInformation("Downloaded tile ({X}, {Y}) to {FilePath}, center=({Lat:F6}, {Lon:F6}), size={Size:F2}m",
x, y, filePath, tileCenter.Lat, tileCenter.Lon, tileSizeMeters);
downloadedTiles.Add(new DownloadedTileInfoV2(
x, y, zoomLevel, tileCenter.Lat, tileCenter.Lon, filePath, tileSizeMeters));
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to download tile ({X}, {Y})", x, y);
throw;
}
}
}
_logger.LogInformation("Downloaded {Count} tiles for region", downloadedTiles.Count);
return downloadedTiles;
}
}