diff --git a/GameRealisticMap.Arma3.Test/ContextMock.cs b/GameRealisticMap.Arma3.Test/ContextMock.cs index 12ddd415..7839b57c 100644 --- a/GameRealisticMap.Arma3.Test/ContextMock.cs +++ b/GameRealisticMap.Arma3.Test/ContextMock.cs @@ -9,6 +9,13 @@ internal class ContextMock : Dictionary, IContext, IDisposable IHugeImageStorage IContext.HugeImageStorage => HugeImageStorage; + public ITerrainArea Area { get; } + + public ContextMock(ITerrainArea? area = null) + { + Area = area ?? new TerrainAreaUTM(new CoordinateSharp.UniversalTransverseMercator("Q", 14, 581943.5, 2111989.8), 1000, 1000); + } + public void Dispose() { HugeImageStorage.Dispose(); diff --git a/GameRealisticMap.Arma3/Arma3MapConfig.cs b/GameRealisticMap.Arma3/Arma3MapConfig.cs index b57bb820..20dce08a 100644 --- a/GameRealisticMap.Arma3/Arma3MapConfig.cs +++ b/GameRealisticMap.Arma3/Arma3MapConfig.cs @@ -74,6 +74,8 @@ public Arma3MapConfig(Arma3MapConfigJson arma3MapConfigJson) Satellite = arma3MapConfigJson.Satellite ?? new SatelliteImageOptions(); + IsPersisted = arma3MapConfigJson.IsPersisted; + Arma3ConfigHelper.ValidatePboPrefix(PboPrefix); Arma3ConfigHelper.ValidateWorldName(WorldName); } @@ -129,5 +131,7 @@ public static string GetAutomaticTargetModDirectory(string worldName) public int IdMapMultiplier { get; } public ISatelliteImageOptions Satellite { get; } + + public bool IsPersisted { get; } } } \ No newline at end of file diff --git a/GameRealisticMap.Arma3/Arma3MapConfigJson.cs b/GameRealisticMap.Arma3/Arma3MapConfigJson.cs index a1eea59e..482712be 100644 --- a/GameRealisticMap.Arma3/Arma3MapConfigJson.cs +++ b/GameRealisticMap.Arma3/Arma3MapConfigJson.cs @@ -39,6 +39,8 @@ public class Arma3MapConfigJson public SatelliteImageOptions? Satellite { get; set; } + public bool IsPersisted { get; set; } = true; + public Arma3MapConfig ToArma3MapConfig() { return new Arma3MapConfig(this); diff --git a/GameRealisticMap.Arma3/Arma3MapGenerator.cs b/GameRealisticMap.Arma3/Arma3MapGenerator.cs index ac3b9bf9..f101dfda 100644 --- a/GameRealisticMap.Arma3/Arma3MapGenerator.cs +++ b/GameRealisticMap.Arma3/Arma3MapGenerator.cs @@ -58,7 +58,7 @@ public Arma3MapGenerator(IArma3RegionAssets assets, ProjectDrive projectDrive, I protected virtual BuildContext CreateBuildContext(IProgressScope progress, Arma3MapConfig a3config, IOsmDataSource osmSource, IHugeImageStorage? hugeImageStorage = null) { var builders = new BuildersCatalog(assets, sources); - return new BuildContext(builders, progress, a3config.TerrainArea, osmSource, a3config.Imagery, hugeImageStorage); + return new BuildContext(builders, progress, a3config.TerrainArea, osmSource, a3config.Imagery, hugeImageStorage, PackageHelper.GetPackageWriter(a3config, projectDrive)); } [SupportedOSPlatform("windows")] diff --git a/GameRealisticMap.Arma3/Arma3TerrainBuilderGenerator.cs b/GameRealisticMap.Arma3/Arma3TerrainBuilderGenerator.cs index de37bf42..1f12c505 100644 --- a/GameRealisticMap.Arma3/Arma3TerrainBuilderGenerator.cs +++ b/GameRealisticMap.Arma3/Arma3TerrainBuilderGenerator.cs @@ -11,11 +11,11 @@ using GameRealisticMap.ManMade.Roads; using GameRealisticMap.Osm; using GameRealisticMap.Preview; +using Pmad.Cartography; +using Pmad.Cartography.DataCells.FileFormats; using Pmad.HugeImages; using Pmad.HugeImages.Processing; using Pmad.HugeImages.Storage; -using Pmad.Cartography; -using Pmad.Cartography.DataCells.FileFormats; using Pmad.ProgressTracking; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; @@ -42,7 +42,7 @@ public Arma3TerrainBuilderGenerator(IArma3RegionAssets assets, ProjectDrive proj private BuildContext CreateBuildContext(IProgressScope progress, Arma3MapConfig a3config, IOsmDataSource osmSource, IHugeImageStorage? hugeImageStorage = null) { var builders = new BuildersCatalog(assets, sources); - return new BuildContext(builders, progress, a3config.TerrainArea, osmSource, a3config.Imagery, hugeImageStorage); + return new BuildContext(builders, progress, a3config.TerrainArea, osmSource, a3config.Imagery, hugeImageStorage, PackageHelper.GetPackageWriter(a3config, projectDrive)); } public async Task GenerateTerrainBuilderFiles(IProgressScope progress, Arma3MapConfig a3config, string targetDirectory) diff --git a/GameRealisticMap.Arma3/PackageHelper.cs b/GameRealisticMap.Arma3/PackageHelper.cs new file mode 100644 index 00000000..b65f9ae8 --- /dev/null +++ b/GameRealisticMap.Arma3/PackageHelper.cs @@ -0,0 +1,17 @@ +using GameRealisticMap.Arma3.IO; +using GameRealisticMap.IO; + +namespace GameRealisticMap.Arma3 +{ + internal static class PackageHelper + { + internal static IPackageWriter? GetPackageWriter(Arma3MapConfig a3config, ProjectDrive projectDrive) + { + if (a3config.IsPersisted) + { + return new FileSystemPackage(Path.Combine(projectDrive.GetFullPath(a3config.PboPrefix), ".grm")); + } + return null; + } + } +} diff --git a/GameRealisticMap.Generic/GenericMapConfig.cs b/GameRealisticMap.Generic/GenericMapConfig.cs index cc5471b9..8689542e 100644 --- a/GameRealisticMap.Generic/GenericMapConfig.cs +++ b/GameRealisticMap.Generic/GenericMapConfig.cs @@ -33,6 +33,8 @@ public GenericMapConfig(GenericMapConfigJson genericMapConfigJson) PrivateServiceRoadThreshold = genericMapConfigJson.PrivateServiceRoadThreshold ?? MapProcessingOptions.Default.PrivateServiceRoadThreshold; Satellite = genericMapConfigJson.Satellite ?? new SatelliteImageOptions(); + + IsPersisted = genericMapConfigJson.IsPersisted; } public TerrainAreaUTM TerrainArea { get; } @@ -47,6 +49,8 @@ public GenericMapConfig(GenericMapConfigJson genericMapConfigJson) public ISatelliteImageOptions Satellite { get; } + public bool IsPersisted { get; } = false; + public static string GetAutomaticName(ITerrainArea area) { var coordinate = area.TerrainPointToLatLng(new TerrainPoint(area.SizeInMeters / 2, area.SizeInMeters / 2)); diff --git a/GameRealisticMap.Generic/GenericMapConfigJson.cs b/GameRealisticMap.Generic/GenericMapConfigJson.cs index 27ee104d..99eb1d51 100644 --- a/GameRealisticMap.Generic/GenericMapConfigJson.cs +++ b/GameRealisticMap.Generic/GenericMapConfigJson.cs @@ -26,6 +26,8 @@ public class GenericMapConfigJson public SatelliteImageOptions? Satellite { get; set; } + public bool IsPersisted { get; set; } + public GenericMapConfig ToMapConfig() { return new GenericMapConfig(this); diff --git a/GameRealisticMap.Generic/GenericMapGenerator.cs b/GameRealisticMap.Generic/GenericMapGenerator.cs index d084d304..232655a0 100644 --- a/GameRealisticMap.Generic/GenericMapGenerator.cs +++ b/GameRealisticMap.Generic/GenericMapGenerator.cs @@ -1,8 +1,8 @@ using GameRealisticMap.Configuration; using GameRealisticMap.Generic.Exporters; using GameRealisticMap.Generic.Profiles; +using GameRealisticMap.IO; using GameRealisticMap.Osm; -using GameRealisticMap.Reporting; using Pmad.HugeImages.Storage; using Pmad.ProgressTracking; @@ -38,10 +38,19 @@ protected virtual async Task LoadOsmData(IProgressScope progress return CreateBuildContext(progress, config, osmSource, hugeImageStorage); } + internal IPackageWriter? GetPackageWriter(GenericMapConfig config) + { + if (config.IsPersisted) + { + return new FileSystemPackage(Path.Combine(config.TargetDirectory, ".grm")); + } + return null; + } + protected virtual BuildContext CreateBuildContext(IProgressScope progress, GenericMapConfig config, IOsmDataSource osmSource, IHugeImageStorage? hugeImageStorage = null) { var builders = new BuildersCatalog(new DefaultBuildersConfig(), sources); - return new BuildContext(builders, progress, config.TerrainArea, osmSource, config, hugeImageStorage); + return new BuildContext(builders, progress, config.TerrainArea, osmSource, config, hugeImageStorage, GetPackageWriter(config)); } public async Task Generate(IProgressScope progress, GenericMapConfig config) diff --git a/GameRealisticMap/BuildContext.cs b/GameRealisticMap/BuildContext.cs index 60e060d3..7892d96b 100644 --- a/GameRealisticMap/BuildContext.cs +++ b/GameRealisticMap/BuildContext.cs @@ -1,4 +1,5 @@ -using GameRealisticMap.Osm; +using GameRealisticMap.IO; +using GameRealisticMap.Osm; using Pmad.HugeImages.Storage; using Pmad.ProgressTracking; @@ -17,6 +18,7 @@ public class BuildContext : IBuildContext private readonly Dictionary datas = new Dictionary(); private readonly IProgressScope rootScope; private readonly IBuidersCatalog catalog; + private readonly IPackageWriter? writer; /// /// Initialises a new with all required inputs. @@ -27,10 +29,11 @@ public class BuildContext : IBuildContext /// The OSM data source pre-loaded for the terrain area. /// Processing options (resolution, road thresholds, satellite settings). /// Optional huge-image storage; defaults to a temporary disk-backed store. - public BuildContext(IBuidersCatalog catalog, IProgressScope rootScope, ITerrainArea area, IOsmDataSource source, IMapProcessingOptions imagery, IHugeImageStorage? his = null) + public BuildContext(IBuidersCatalog catalog, IProgressScope rootScope, ITerrainArea area, IOsmDataSource source, IMapProcessingOptions imagery, IHugeImageStorage? his = null, IPackageWriter? writer = null) { this.rootScope = rootScope; this.catalog = catalog; + this.writer = writer; Area = area; OsmSource = source; Options = imagery; @@ -101,13 +104,25 @@ private Task CreateDataTask(IProgressScope? parentScope) where T : class var builder = catalog.Get(); return Task.Run(async () => { + var name = builder.GetType().Name.Replace("Builder", ""); + using (var scope = (parentScope ?? rootScope).CreateScope(builder.GetType().Name.Replace("Builder", ""))) { + T value; if (builder is IDataBuilderAsync asyncBuilder) { - return await asyncBuilder.BuildAsync(this, scope).ConfigureAwait(false); + value = await asyncBuilder.BuildAsync(this, scope).ConfigureAwait(false); + } + else + { + value = builder.Build(this, scope); + } + if (writer != null) + { + var serializer = ContextSerializer.GetSerializer(builder); + await serializer.Write(writer, value).ConfigureAwait(false); } - return builder.Build(this, scope); + return value; } }); } diff --git a/GameRealisticMap/Conditions/ConditionEvaluator.cs b/GameRealisticMap/Conditions/ConditionEvaluator.cs index c8a30689..0fabfc40 100644 --- a/GameRealisticMap/Conditions/ConditionEvaluator.cs +++ b/GameRealisticMap/Conditions/ConditionEvaluator.cs @@ -22,7 +22,7 @@ public class ConditionEvaluator : IConditionEvaluator internal const float MaxRoadBoxSearch = 75f; internal const float MaxRoadDistance = MaxRoadBoxSearch * 1.414f; // MaxRoadBoxSearch * sqrt(2) - public ConditionEvaluator(IBuildContext context) + public ConditionEvaluator(IContext context) { this.areas = context.GetData(); this.cities = context.GetData(); diff --git a/GameRealisticMap/Conditions/ConditionEvaluatorBuilder.cs b/GameRealisticMap/Conditions/ConditionEvaluatorBuilder.cs index e9159233..c268b872 100644 --- a/GameRealisticMap/Conditions/ConditionEvaluatorBuilder.cs +++ b/GameRealisticMap/Conditions/ConditionEvaluatorBuilder.cs @@ -1,12 +1,23 @@ -using Pmad.ProgressTracking; +using GameRealisticMap.IO; +using Pmad.ProgressTracking; namespace GameRealisticMap.Conditions { - internal class ConditionEvaluatorBuilder : IDataBuilder + internal class ConditionEvaluatorBuilder : IDataBuilder, IDataSerializer { public ConditionEvaluator Build(IBuildContext context, IProgressScope scope) { return new ConditionEvaluator(context); } + + public ValueTask Read(IPackageReader package, IContext context) + { + return ValueTask.FromResult(new ConditionEvaluator(context)); + } + + public Task Write(IPackageWriter package, ConditionEvaluator data) + { + return Task.CompletedTask; + } } } diff --git a/GameRealisticMap/ElevationModel/ElevationWithLakesBuilder.cs b/GameRealisticMap/ElevationModel/ElevationWithLakesBuilder.cs index e5290a22..3f2bdfcb 100644 --- a/GameRealisticMap/ElevationModel/ElevationWithLakesBuilder.cs +++ b/GameRealisticMap/ElevationModel/ElevationWithLakesBuilder.cs @@ -10,6 +10,7 @@ using GeoJSON.Text.Geometry; using Pmad.Cartography; using Pmad.Cartography.Contours; +using Pmad.Cartography.DataCells; using Pmad.Geometry; using Pmad.Geometry.Shapes; using Pmad.ProgressTracking; @@ -311,12 +312,21 @@ public async ValueTask Read(IPackageReader package, ICon { var lakes = await package.ReadJson>("LakesElevation.json"); - return new ElevationWithLakesData(context.GetData().Elevation, lakes); + using var stream = package.ReadFile("ElevationWithLakes.ddc"); + + var grid = new ElevationGrid(DemDataCell.Load(stream).To().AsPixelIsPoint()); + + return new ElevationWithLakesData(grid, lakes); } - public Task Write(IPackageWriter package, ElevationWithLakesData data) + public async Task Write(IPackageWriter package, ElevationWithLakesData data) { - return package.WriteJson("LakesElevation.json", data.Lakes); + await package.WriteJson("LakesElevation.json", data.Lakes); + + using (var stream = package.CreateFile("ElevationWithLakes.ddc")) + { + data.Elevation.ToDataCell().Save(stream); + } } } } diff --git a/GameRealisticMap/ElevationModel/RawElevationBuilder.cs b/GameRealisticMap/ElevationModel/RawElevationBuilder.cs index b731328e..f8bacd70 100644 --- a/GameRealisticMap/ElevationModel/RawElevationBuilder.cs +++ b/GameRealisticMap/ElevationModel/RawElevationBuilder.cs @@ -191,14 +191,24 @@ private static LatLngBounds CreateOutOfBounds(IBuildContext context) return new LatLngBounds(context.Area, wantedView.Shell); } - public ValueTask Read(IPackageReader package, IContext context) + public async ValueTask Read(IPackageReader package, IContext context) { - return ValueTask.FromResult(new RawElevationData(context.GetData().Elevation, new List(), new ElevationMinMax[0])); + using var stream = package.ReadFile("RawElevation.ddc"); + + var grid = new ElevationGrid(DemDataCell.Load(stream).To().AsPixelIsPoint()); + + var json = await package.ReadJson("RawElevation.json"); + + return new RawElevationData(grid, json.Credits, json.OutOfBounds); } - public Task Write(IPackageWriter package, RawElevationData data) + public async Task Write(IPackageWriter package, RawElevationData data) { - return Task.CompletedTask; + using (var stream = package.CreateFile("RawElevation.ddc")) + { + data.RawElevation.ToDataCell().Save(stream); + } + await package.WriteJson("RawElevation.json", new RawElevationJson(data.Credits, data.OutOfBounds)); } } } diff --git a/GameRealisticMap/ElevationModel/RawElevationJson.cs b/GameRealisticMap/ElevationModel/RawElevationJson.cs new file mode 100644 index 00000000..13370196 --- /dev/null +++ b/GameRealisticMap/ElevationModel/RawElevationJson.cs @@ -0,0 +1,15 @@ +namespace GameRealisticMap.ElevationModel +{ + public sealed class RawElevationJson + { + public RawElevationJson(List credits, ElevationMinMax[] outOfBounds) + { + Credits = credits; + OutOfBounds = outOfBounds; + } + + public List Credits { get; } + + public ElevationMinMax[] OutOfBounds { get; } + } +} diff --git a/GameRealisticMap/IBuildContext.cs b/GameRealisticMap/IBuildContext.cs index 43e5c314..f4d01e84 100644 --- a/GameRealisticMap/IBuildContext.cs +++ b/GameRealisticMap/IBuildContext.cs @@ -8,13 +8,6 @@ namespace GameRealisticMap /// public interface IBuildContext : IContext { - /// - /// The geographic area being processed. Provides coordinate conversion between - /// WGS-84 lat/lng and local terrain space (), - /// and exposes the terrain grid dimensions. - /// - ITerrainArea Area { get; } - /// /// The OpenStreetMap data source containing all OSM features (nodes, ways, relations) /// clipped to the terrain area. Used by all OSM-based builders. diff --git a/GameRealisticMap/IContext.cs b/GameRealisticMap/IContext.cs index 9f828f2d..38faaa16 100644 --- a/GameRealisticMap/IContext.cs +++ b/GameRealisticMap/IContext.cs @@ -9,6 +9,13 @@ namespace GameRealisticMap /// public interface IContext { + /// + /// The geographic area being processed. Provides coordinate conversion between + /// WGS-84 lat/lng and local terrain space (), + /// and exposes the terrain grid dimensions. + /// + ITerrainArea Area { get; } + /// /// Gets or builds data of type synchronously. /// If the data has already been built, returns the cached result. diff --git a/GameRealisticMap/IO/ContextReader.cs b/GameRealisticMap/IO/ContextReader.cs index 1626043c..cdd9f264 100644 --- a/GameRealisticMap/IO/ContextReader.cs +++ b/GameRealisticMap/IO/ContextReader.cs @@ -12,6 +12,8 @@ internal class ContextReader : IContext, IDataBuilderVisitor public IHugeImageStorage HugeImageStorage => throw new NotImplementedException(); + public ITerrainArea Area => throw new NotImplementedException(); + public ContextReader(IPackageReader package, IBuidersCatalog catalog) { this.package = package; diff --git a/GameRealisticMap/IO/ContextSerializer.cs b/GameRealisticMap/IO/ContextSerializer.cs index 3f748af4..7f5d4511 100644 --- a/GameRealisticMap/IO/ContextSerializer.cs +++ b/GameRealisticMap/IO/ContextSerializer.cs @@ -1,6 +1,4 @@ -using System.IO.Compression; - -namespace GameRealisticMap.IO +namespace GameRealisticMap.IO { public class ContextSerializer { @@ -16,26 +14,6 @@ internal static IDataSerializer GetSerializer(IDataBuilder return (builder as IDataSerializer) ?? new DefaultDataSerializer(); } - public async Task Write(IPackageWriter writer, IContext context) - { - foreach(var step in catalog.VisitAll(new ContextWriter(writer, context))) - { - await step; - } - } - - public Task WriteToDirectory(string path, IContext context) - { - return Write(new FileSystemPackage(path), context); - } - - public async Task WriteToZip(string path, IContext context) - { - using var archive = new ZipArchive(File.Create(path), ZipArchiveMode.Create); - - await Write(new ZipPackageWriter(archive), context); - } - public IContext ReadLazy(IPackageReader reader) { return new ContextReader(reader, catalog); diff --git a/GameRealisticMap/IO/ContextWriter.cs b/GameRealisticMap/IO/ContextWriter.cs deleted file mode 100644 index 3a4ce0cf..00000000 --- a/GameRealisticMap/IO/ContextWriter.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GameRealisticMap.IO -{ - internal class ContextWriter : IDataBuilderVisitor - { - private readonly IPackageWriter package; - private readonly IContext context; - - public ContextWriter(IPackageWriter package, IContext context) - { - this.package = package; - this.context = context; - } - - public Task Visit(IDataBuilder builder) where TData : class - { - return ContextSerializer.GetSerializer(builder).Write(package, context.GetData()); - } - } -} diff --git a/GameRealisticMap/IO/FileSystemPackage.cs b/GameRealisticMap/IO/FileSystemPackage.cs index fe0cc3fa..839ad54a 100644 --- a/GameRealisticMap/IO/FileSystemPackage.cs +++ b/GameRealisticMap/IO/FileSystemPackage.cs @@ -1,6 +1,6 @@ namespace GameRealisticMap.IO { - internal class FileSystemPackage : IPackageReader, IPackageWriter + public sealed class FileSystemPackage : IPackageReader, IPackageWriter { private readonly string basePath; @@ -13,6 +13,12 @@ public FileSystemPackage(string basePath) public Stream CreateFile(string filename) { + var target = Path.Combine(basePath, filename); + var targetDirectory = Path.GetDirectoryName(target); + if (!string.IsNullOrEmpty(targetDirectory) && !Directory.Exists(targetDirectory)) + { + Directory.CreateDirectory(targetDirectory); + } return File.Create(Path.Combine(basePath, filename)); } diff --git a/GameRealisticMap/IO/PackageHelper.cs b/GameRealisticMap/IO/PackageHelper.cs index 35e98898..fbbf9c4c 100644 --- a/GameRealisticMap/IO/PackageHelper.cs +++ b/GameRealisticMap/IO/PackageHelper.cs @@ -1,5 +1,9 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Pmad.HugeImages; +using Pmad.HugeImages.IO; +using Pmad.HugeImages.Storage; +using SixLabors.ImageSharp.PixelFormats; namespace GameRealisticMap.IO { @@ -31,5 +35,29 @@ public static async Task WriteJson(this IPackageWriter package, string filena await JsonSerializer.SerializeAsync(stream, data, options ?? DefaultOptions); } } + + + public static async Task WriteHugeImage(this IPackageWriter package, string filename, HugeImage data) + where TPixel : unmanaged, IPixel + { + using (var stream = package.CreateFile(filename)) + { + await data.SaveAsync(stream); + } + } + + public static async Task> ReadHugeImage(this IPackageReader package, string filename, IHugeImageStorage storage, string name) + where TPixel : unmanaged, IPixel + { + using (var stream = package.ReadFile(filename)) + { + var copyStorage = storage as IHugeImageStorageCanCopy; + if (copyStorage != null) + { + return await HugeImageIO.LoadCopyAsync(stream, copyStorage, name); + } + return await HugeImageIO.LoadCloneAsync(stream, storage, name); + } + } } } diff --git a/GameRealisticMap/IO/ZipPackageWriter.cs b/GameRealisticMap/IO/ZipPackageWriter.cs deleted file mode 100644 index c8466ee1..00000000 --- a/GameRealisticMap/IO/ZipPackageWriter.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.IO.Compression; - -namespace GameRealisticMap.IO -{ - internal class ZipPackageWriter : IPackageWriter - { - private readonly ZipArchive archive; - - public ZipPackageWriter(ZipArchive archive) - { - this.archive = archive; - } - - public Stream CreateFile(string filename) - { - return archive.CreateEntry(filename).Open(); - } - } -} \ No newline at end of file diff --git a/GameRealisticMap/Satellite/RawSatelliteImageBuilder.cs b/GameRealisticMap/Satellite/RawSatelliteImageBuilder.cs index 1e8b9a49..c1d5c23d 100644 --- a/GameRealisticMap/Satellite/RawSatelliteImageBuilder.cs +++ b/GameRealisticMap/Satellite/RawSatelliteImageBuilder.cs @@ -1,5 +1,4 @@ -using System.Numerics; -using GameRealisticMap.Configuration; +using GameRealisticMap.Configuration; using GameRealisticMap.Geometries; using GameRealisticMap.IO; using Pmad.HugeImages; @@ -21,16 +20,8 @@ public RawSatelliteImageBuilder(ISourceLocations sources) public async Task BuildAsync(IBuildContext context, IProgressScope scope) { - //Image image; - var totalSize = (int)Math.Ceiling(context.Area.SizeInMeters / context.Options.Resolution); - //using (var report = progress.CreateStep("S2C OLD", totalSize /*tileSize * tileCount * tileCount*/)) - //{ - // image = LoadImage(context, totalSize, report, Vector2.Zero, 0); - // image.SaveAsPng(@"c:\temp\test.png"); - //} - var himage = new HugeImage(context.HugeImageStorage, nameof(RawSatelliteImageBuilder), new Size(totalSize)); using (var report2 = scope.CreateInteger(SatelliteImageProvider.GetName(sources), himage.Parts.Sum(t => t.RealRectangle.Height))) { @@ -86,43 +77,12 @@ await Parallel.ForEachAsync(Enumerable.Range(0, parallel), async (dy, _) => public async ValueTask Read(IPackageReader package, IContext context) { - //var image = await Image.LoadAsync(package.ReadFile("RawSatellite.png"), new PngDecoder()); - //return new RawSatelliteImageData(image); - throw new NotImplementedException(); + return new RawSatelliteImageData(await package.ReadHugeImage("RawSatellite.himg.zip", context.HugeImageStorage, nameof(RawSatelliteImageBuilder))); } public async Task Write(IPackageWriter package, RawSatelliteImageData data) { - //using(var stream = package.CreateFile("RawSatellite.png")) - //{ - // await data.Image.SaveAsPngAsync(stream); - //} - throw new NotImplementedException(); - } - - private Image LoadImage(IBuildContext context, int tileSize, IProgressInteger report, Vector2 start, int done) - { - var imageryResolution = context.Options.Resolution; - using var src = new SatelliteImageProvider(report, sources); - var img = new Image(tileSize, tileSize); - var parallel = 16; - var dh = img.Height / parallel; - Parallel.For(0, parallel, dy => - { - var y1 = dy * dh; - var y2 = (dy + 1) * dh; - for (int y = y1; y < y2; y++) - { - for (int x = 0; x < img.Width; x++) - { - var latLong = context.Area.TerrainPointToLatLng(new TerrainPoint((float)(x * imageryResolution), (float)(y * imageryResolution)) + start); - img[x, img.Height - y - 1] = src.GetPixel(latLong).Result; - } - report.Report(Interlocked.Increment(ref done)); - } - }); - img.Mutate(d => d.GaussianBlur(1f)); - return img; + await package.WriteHugeImage("RawSatellite.himg.zip", data.Image); } } }