Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 10 additions & 28 deletions MapToolkit.Test/Databases/WellKnownDatabasesTest.cs
Original file line number Diff line number Diff line change
@@ -1,57 +1,39 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Pmad.Cartography.Databases;

namespace Pmad.Cartography.Test.Databases
{
public class WellKnownDatabasesTest
{
private const string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0";

[Fact]
public async Task AW3D30_ContainsLondon()
{
var baseAddress = "https://cdn.dem.pmad.net/AW3D30/";
var database = WellKnownDatabases.GetAW3D30();

var storage = await CreateDatabaseAndLoadIndex(baseAddress);
await database.LoadIndexAsync();

Assert.NotNull(await storage.GetDataCellsAsync(new Coordinates(51, 0), new Coordinates(52, 1)));
Assert.NotNull(await database.GetDataCellsAsync(new Coordinates(51, 0), new Coordinates(52, 1)));
}

[Fact]
public async Task SRTM1_ContainsLondon()
{
var baseAddress = "https://cdn.dem.pmad.net/SRTM1/";
var database = WellKnownDatabases.GetSRTM1();

var storage = await CreateDatabaseAndLoadIndex(baseAddress);
await database.LoadIndexAsync();

Assert.NotNull(await storage.GetDataCellsAsync(new Coordinates(51, 0), new Coordinates(52, 1)));
Assert.NotNull(await database.GetDataCellsAsync(new Coordinates(51, 0), new Coordinates(52, 1)));
}


[Fact]
public async Task SRTM15Plus_ContainsLondon()
{
var baseAddress = "https://cdn.dem.pmad.net/SRTM15Plus/";

var storage = await CreateDatabaseAndLoadIndex(baseAddress);
var database = WellKnownDatabases.GetSRTM15Plus();

Assert.NotNull(await storage.GetDataCellsAsync(new Coordinates(51, 0), new Coordinates(52, 1)));
}
await database.LoadIndexAsync();

private static async Task<DemDatabase> CreateDatabaseAndLoadIndex(string baseAddress)
{
var localCache = Path.Combine(Path.GetTempPath(), "dem_test_wellknown");
var httpClient = new HttpClient { BaseAddress = new Uri(baseAddress) };
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(userAgent);
var storage = new DemDatabase(new DemHttpStorage(localCache, httpClient));
await storage.LoadIndexAsync();
return storage;
Assert.NotNull(await database.GetDataCellsAsync(new Coordinates(51, 0), new Coordinates(52, 1)));
}
}
}
10 changes: 6 additions & 4 deletions MapToolkit/Databases/DemHttpStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,26 @@ public class DemHttpStorage : IDemStorage
private readonly string localCache;
private readonly HttpClient client;

public DemHttpStorage (string localCache, HttpClient client)
public DemHttpStorage (string? localCache, HttpClient client)
{
this.localCache = localCache;
this.localCache = localCache ?? DefaultCacheLocation;
this.client = client;
}

public DemHttpStorage(string localCache, Uri baseAddress)
public DemHttpStorage(string? localCache, Uri baseAddress)
: this(localCache, new HttpClient() { BaseAddress = baseAddress })
{

}

public DemHttpStorage(Uri baseAddress)
: this(Path.Combine(Path.GetTempPath(),"dem"), baseAddress)
: this(null, baseAddress)
{

}

public static string DefaultCacheLocation => Path.Combine(Path.GetTempPath(), "dem");

public async Task<IDemDataCell> Load(string path)
{
var uri = new Uri(client.BaseAddress!, path);
Expand Down
112 changes: 112 additions & 0 deletions MapToolkit/Databases/WellKnownDatabases.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Data;
using System.Net.Http;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace Pmad.Cartography.Databases
{
public static class WellKnownDatabases
{
private const string DefaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0";

internal static HttpClient CreateClient(string baseAddress)
{
var httpClient = new HttpClient { BaseAddress = new Uri(baseAddress) };
// OVH CDN Requires a user agent
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(DefaultUserAgent);
return httpClient;
}

/// <summary>
/// Get the AW3D 30 data hosted on cdn.dem.pmad.net:
/// Japan Aerospace Exploration Agency (2021). ALOS World 3D 30 meter DEM. V3.2, Jan 2021.
/// </summary>
/// <param name="localCache">Cache location. If null, will use <see cref="DemHttpStorage.DefaultCacheLocation"/>.</param>
/// <returns></returns>
/// <remarks>
/// This dataset is available to use with no charge under the following conditions.
/// When the user provide or publish the products and services to a third party using this dataset, it is necessary to display that the original data is provided by JAXA.
/// You are kindly requested to show the copyright (© JAXA) and the source of data When you publish the fruits using this dataset.
/// JAXA does not guarantee the quality and reliability of this dataset and JAXA assume no responsibility whatsoever for any direct or indirect damage and loss caused by use of this dataset.Also, JAXA will not be responsible for any damages of users due to changing, deleting or terminating the provision of this dataset.
/// </remarks>
public static DemHttpStorage GetAW3D30Storage(string? localCache = null)
{
return new DemHttpStorage(localCache, CreateClient("https://cdn.dem.pmad.net/AW3D30/"));
}

/// <summary>
/// Get the SRTM 1 data hosted on cdn.dem.pmad.net:
/// NASA Shuttle Radar Topography Mission (SRTM)(2013). Shuttle Radar Topography Mission (SRTM) Global.
/// </summary>
/// <param name="localCache">Cache location. If null, will use <see cref="DemHttpStorage.DefaultCacheLocation"/>.</param>
/// <returns></returns>
/// <remarks>
/// Public domain.
/// </remarks>
public static DemHttpStorage GetSRTM1Storage(string? localCache = null)
{
return new DemHttpStorage(localCache, CreateClient("https://cdn.dem.pmad.net/SRTM1/"));
}

/// <summary>
/// Get the SRTM 15+ data hosted on cdn.dem.pmad.net:
/// GLOBAL BATHYMETRY AND TOPOGRAPHY AT 15 ARCSECONDS. SRTM15+V2.5.5 - March 20, 2023
/// </summary>
/// <param name="localCache">Cache location. If null, will use <see cref="DemHttpStorage.DefaultCacheLocation"/>.</param>
/// <returns></returns>
/// <remarks>
/// Reference: Tozer, B. , D. T. Sandwell, W. H. F. Smith, C. Olson, J. R. Beale, and P. Wessel, Global bathymetry and topography at 15 arc seconds: SRTM15+, Accepted Earth and Space Science, August 3, 2019.
/// Public domain.
/// </remarks>
public static DemHttpStorage GetSRTM15PlusStorage(string? localCache = null)
{
return new DemHttpStorage(localCache, CreateClient("https://cdn.dem.pmad.net/SRTM15Plus/"));
}

/// <summary>
/// Get the AW3D 30 database hosted on cdn.dem.pmad.net:
/// Japan Aerospace Exploration Agency (2021). ALOS World 3D 30 meter DEM. V3.2, Jan 2021.
/// </summary>
/// <param name="localCache">Cache location. If null, will use <see cref="DemHttpStorage.DefaultCacheLocation"/>.</param>
/// <returns></returns>
/// <remarks>
/// This dataset is available to use with no charge under the following conditions.
/// When the user provide or publish the products and services to a third party using this dataset, it is necessary to display that the original data is provided by JAXA.
/// You are kindly requested to show the copyright (© JAXA) and the source of data When you publish the fruits using this dataset.
/// JAXA does not guarantee the quality and reliability of this dataset and JAXA assume no responsibility whatsoever for any direct or indirect damage and loss caused by use of this dataset.Also, JAXA will not be responsible for any damages of users due to changing, deleting or terminating the provision of this dataset.
/// </remarks>
public static DemDatabase GetAW3D30(string? localCache = null)
{
return new DemDatabase(GetAW3D30Storage(localCache));
}

/// <summary>
/// Get the SRTM 1 database hosted on cdn.dem.pmad.net:
/// NASA Shuttle Radar Topography Mission (SRTM)(2013). Shuttle Radar Topography Mission (SRTM) Global.
/// </summary>
/// <param name="localCache">Cache location. If null, will use <see cref="DemHttpStorage.DefaultCacheLocation"/>.</param>
/// <returns></returns>
/// <remarks>
/// Public domain.
/// </remarks>
public static DemDatabase GetSRTM1(string? localCache = null)
{
return new DemDatabase(GetSRTM1Storage(localCache));
}

/// <summary>
/// Get the SRTM 15+ database hosted on cdn.dem.pmad.net:
/// GLOBAL BATHYMETRY AND TOPOGRAPHY AT 15 ARCSECONDS. SRTM15+V2.5.5 - March 20, 2023
/// </summary>
/// <param name="localCache">Cache location. If null, will use <see cref="DemHttpStorage.DefaultCacheLocation"/>.</param>
/// <returns></returns>
/// <remarks>
/// Reference: Tozer, B. , D. T. Sandwell, W. H. F. Smith, C. Olson, J. R. Beale, and P. Wessel, Global bathymetry and topography at 15 arc seconds: SRTM15+, Accepted Earth and Space Science, August 3, 2019.
/// Public domain.
/// </remarks>
public static DemDatabase GetSRTM15Plus(string? localCache = null)
{
return new DemDatabase(GetSRTM15PlusStorage(localCache));
}
}
}
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,62 @@
## Pmad.Cartography
A simple and read-to-use Digital Elevation Model for everyone based on Open Data with minimalist credits

### Digital Elevation Model sources

| Source | Resolution | License | URL | Credits |
| ------ | ------------- | ------------- | --- | --- |
| SRTM1 | 1 arc second | Public Domain | https://cdn.dem.pmad.net/SRTM1/ | NASA |
| SRTM15+| 15 arc second | Public Domain | https://cdn.dem.pmad.net/SRTM15Plus/ | Tozer, B. , D. T. Sandwell, W. H. F. Smith, C. Olson, J. R. Beale, and P. Wessel |
| AW3D30 | 1 arc second | [See terms](https://cdn.dem.pmad.net/README.txt) | https://cdn.dem.pmad.net/AW3D30/ | � JAXA |

```csharp
var database = WellKnownDatabases.GetSRTM1();

// Singe point
var elevation = await database.GetElevationAsync(new Coordinates(51.509865, -0.118092), DefaultInterpolation.Instance);

// Area
var area = await demDatabase.CreateView<float>(new Coordinates(51, -1), new Coordinates(52, 0));
```

### Elevation contours

```csharp
var contour = new ContourGraph();
contour.Add(area, new ContourLevelGenerator(10, 10)); // 10 meters elevation interval from 10
```

### Hillshading

```csharp
var img = new HillshaderFast(new Vector2D(10, 10)) // Assume each pixel of area is 10x10 meters
.GetPixelsAlphaBelowFlat(area);
```

### File formats

#### Supported data formats

| Format | Read | Write | Remarks |
| ---------- | ---- | ----- | ----------------------------------- |
| ESRI ASCII | Yes | Yes | float only |
| DDC | Yes | Yes | Format specific to Pmad.Cartography |
| GeoTIFF | Yes | No | WSG84 projection Only |
| SRTM | Yes | No | 3 and 1 arc second |

#### Supported compression formats

Most DEM files requires a lot of disk space. To reduce the size of the files, the following compression formats are supported:

| Format | Read | Write | Remarks |
| ---------- | ---- | ----- | ----------------------------------- |
| ZSTD | Yes | Yes | Best compromise storage/CPU cost |
| GZIP | Yes | Yes | Lowest CPU cost |
| Brotli | Yes | Yes | Best compression |
| Zip | Yes | No | Zip must contains only one file |

## Pmad.Cartography.Drawing

A simple topographic map rendering toolkit.

Drawing API is still in development, it may change in the future.
Loading