Files
satellite-provider/SatelliteProvider.Services/TileService.cs
T
2025-10-28 12:04:09 +01:00

116 lines
4.2 KiB
C#

using Microsoft.Extensions.Logging;
using SatelliteProvider.Common.DTO;
using SatelliteProvider.Common.Interfaces;
using SatelliteProvider.DataAccess.Models;
using SatelliteProvider.DataAccess.Repositories;
namespace SatelliteProvider.Services;
public class TileService : ITileService
{
private readonly GoogleMapsDownloader _downloader;
private readonly ITileRepository _tileRepository;
private readonly ILogger<TileService> _logger;
public TileService(
GoogleMapsDownloader downloader,
ITileRepository tileRepository,
ILogger<TileService> logger)
{
_downloader = downloader;
_tileRepository = tileRepository;
_logger = logger;
}
public async Task<List<TileMetadata>> DownloadAndStoreTilesAsync(
double latitude,
double longitude,
double sizeMeters,
int zoomLevel,
CancellationToken cancellationToken = default)
{
var existingTiles = await _tileRepository.GetTilesByRegionAsync(latitude, longitude, sizeMeters, zoomLevel);
var existingTilesList = existingTiles.ToList();
_logger.LogInformation("Found {Count} existing tiles for region", existingTilesList.Count);
var centerPoint = new GeoPoint(latitude, longitude);
var downloadedTiles = await _downloader.GetTilesWithMetadataAsync(centerPoint, sizeMeters / 2, zoomLevel, cancellationToken);
var result = new List<TileMetadata>();
foreach (var downloadedTile in downloadedTiles)
{
var existingTile = existingTilesList.FirstOrDefault(t =>
Math.Abs(t.Latitude - downloadedTile.Latitude) < 0.0001 &&
Math.Abs(t.Longitude - downloadedTile.Longitude) < 0.0001 &&
t.ZoomLevel == downloadedTile.ZoomLevel);
if (existingTile != null)
{
_logger.LogDebug("Reusing existing tile at ({Lat}, {Lon})", downloadedTile.Latitude, downloadedTile.Longitude);
result.Add(MapToMetadata(existingTile));
}
else
{
var now = DateTime.UtcNow;
var tileEntity = new TileEntity
{
Id = Guid.NewGuid(),
ZoomLevel = downloadedTile.ZoomLevel,
Latitude = downloadedTile.Latitude,
Longitude = downloadedTile.Longitude,
TileSizeMeters = downloadedTile.TileSizeMeters,
TileSizePixels = 256,
ImageType = "jpg",
MapsVersion = $"downloaded_{now:yyyy-MM-dd}",
FilePath = downloadedTile.FilePath,
CreatedAt = now,
UpdatedAt = now
};
await _tileRepository.InsertAsync(tileEntity);
_logger.LogInformation("Saved new tile {Id} at ({Lat}, {Lon})", tileEntity.Id, tileEntity.Latitude, tileEntity.Longitude);
result.Add(MapToMetadata(tileEntity));
}
}
return result;
}
public async Task<TileMetadata?> GetTileAsync(Guid id)
{
var tile = await _tileRepository.GetByIdAsync(id);
return tile != null ? MapToMetadata(tile) : null;
}
public async Task<IEnumerable<TileMetadata>> GetTilesByRegionAsync(
double latitude,
double longitude,
double sizeMeters,
int zoomLevel)
{
var tiles = await _tileRepository.GetTilesByRegionAsync(latitude, longitude, sizeMeters, zoomLevel);
return tiles.Select(MapToMetadata);
}
private static TileMetadata MapToMetadata(TileEntity entity)
{
return new TileMetadata
{
Id = entity.Id,
ZoomLevel = entity.ZoomLevel,
Latitude = entity.Latitude,
Longitude = entity.Longitude,
TileSizeMeters = entity.TileSizeMeters,
TileSizePixels = entity.TileSizePixels,
ImageType = entity.ImageType,
MapsVersion = entity.MapsVersion,
FilePath = entity.FilePath,
CreatedAt = entity.CreatedAt,
UpdatedAt = entity.UpdatedAt
};
}
}