DHI.Services.MIKECore for GIS Maps — Internal Developer Guide¶
This document is for DHI developers wanting to wire MIKECore raster rendering into the GIS Maps stack (Core + optional WebApi). This guide covers capabilities, configuration, parameters, and production usage patterns for:
Dfs2MapSource(structured grids, DFS2)DfsuMapSource(unstructured meshes, DFSU)
For the deeper MIKECore domain details (DFS file structure, items, projections, etc.), see MIKECore Providers.
1) What the MIKECore providers do¶
Both providers implement IMapSource (via BaseMapSource) and produce raster maps (SKBitmap) using the MIKECore contouring pipeline:
-
Inputs per request
style→ resolvedMapStyle(palette thresholds used for banding)crs→ must be"EPSG:3857"(Web Mercator). Anything else throws.bbox→ render extent (in EPSG:3857 meters)width/height→ output pixel sizesourceId→ DFS file (see “File sourcing” below)dateTime→ timestep; absent ⇒ first timestepitem→ item name or item number (string like"3")parameters→ contour/vector rendering knobs (see cheat-sheet)
-
Outputs
- A rendered
SKBitmap. Dispose it when done. GetDateTimes(id)returns available timesteps (SortedSet<DateTime>).
- A rendered
-
Performance
- The base class implements parallel
GetMaps(...)(time stack fan-out + ordered aggregation).
- The base class implements parallel
2) File sourcing & connection patterns¶
The providers read from local disk via an IFileSource (default FileSource). You can point them at:
2.1 A single file¶
var dfs2 = new Dfs2MapSource(@"C:\data\dfs2\R20141001.dfs2");
var bmp = new MapService(dfs2, styleSvc).GetMap(
style: "rain", crs: "EPSG:3857", bbox, 1280, 720,
sourceId: "", // ← unused when ctor got the file
dateTime: new DateTime(2014,10,1,10,0,0, DateTimeKind.Utc),
item: "Water Level",
parameters: Parameters.Empty);
2.2 A directory (select the file at call time)¶
var dfs2 = new Dfs2MapSource(@"C:\data\dfs2"); // directory
var bmp = new MapService(dfs2, styleSvc).GetMap(
style: "rain", crs: "EPSG:3857", bbox, 1280, 720,
sourceId: "R20141001.dfs2", // ← choose the file
dateTime: null, item: "3",
parameters: new Parameters { { "isoline", "Contour" }});
DfsuMapSourcesupports the same two modes; if you pass a file path to the ctor, call withsourceId: "". If you pass a directory root, call withsourceId: "<mesh>.dfsu"(relative to that root).
3) Styling (palettes, contours & vectors)¶
The MIKECore contouring pipeline honors the MapStyle palette thresholds (if provided):
- If your
MapServicehas aMapStyleService, thestylestring is a repo id (e.g."rain"). - If you pass no style service, the
stylestring is treated as a StyleCode (e.g."0~10:#0000FF,#00FFFF,#00FF00,#FFFF00,#FF0000").
Thresholds flow into ChartOptions.Thresholds as (float lower, SKColor) pairs. If you don’t provide a palette, MIKECore will fall back to its internal coloring mode (ColoringType + ShadingType).
Legend: use MapStyle.ToBitmapHorizontal/Vertical from core to generate consistent legends.
4) Time axis¶
var times = dfs2.GetDateTimes("R20141001.dfs2");
var t = times.First();
var bmp = new MapService(dfs2, styleSvc).GetMap("rain","EPSG:3857", bbox, 1200, 900,
"R20141001.dfs2", t, "Water Level", Parameters.Empty);
For batches, prefer the service-level parallel fan-out:
var steps = new Dictionary<DateTime,string> {
[new(2014,10,1,10,0,0, DateTimeKind.Utc)] = "R20141001.dfs2",
[new(2014,10,1,11,0,0, DateTimeKind.Utc)] = "R20141001.dfs2"
};
var frames = mapService.GetMaps("rain", bbox, new SKSizeI(1024,768), steps, "Water Level", Parameters.Empty);
5) Rendering knobs (parameters)¶
Both Dfs2MapSource and DfsuMapSource accept the same optional parameters:
| Key | Type | Default | Meaning |
|---|---|---|---|
includevector |
bool | false |
Draw vectors |
isoline |
enum | None |
None, Contour, IsoLine |
vectorcolor |
hex | #000000 |
Vector color |
usevectorfixedlength |
bool | false |
Fixed vector length |
vectormaxlength |
int | 10 |
Max vector length |
vectornumberhorizontal |
int | 0 |
Vector density |
scale |
double | missing → null |
Optional data scale (null = auto) |
coloringtype |
enum | DiscreteColoring |
DiscreteColoring or GradientColoring |
shadingtype |
enum | ShadedContour |
ShadedContour or FlatFill |
itemcan be an item name or the item number as string (e.g.,"3"). The provider resolves either.
6) CRS, bbox & size (important)¶
- CRS must be
"EPSG:3857". The provider throws otherwise. bboxmust be meters in EPSG:3857 (x,y order).- Choose
width/heightappropriate to your client DPI; for web tiles, 512–1024 wide is typical.
7) Layer info helpers¶
Each provider exposes a convenience probe:
var layerInfo = new Dfs2MapSource(@"C:\data\dfs2\R20141001.dfs2").GetLayerInfo();
Console.WriteLine($"{layerInfo.Name} bbox:{layerInfo.BoundingBox} crs:{layerInfo.CoordinateSystem}");
Useful for surfacing the data area and projection without a render.
8) Wiring it up¶
You can wire MIKECore providers either via connections.json (WebApi hosts) or programmatically.
A) Using the Connections module (WebApi hosts)¶
Add these entries to connections.json:
"dfs2-map": {
"$type": "DHI.Services.GIS.WebApi.MapServiceConnection, DHI.Services.GIS.WebApi",
"MapSourceConnectionString": "[AppData]dfs2\\R20141001.dfs2",
"MapSourceType": "DHI.Services.Provider.MIKECore.Dfs2MapSource, DHI.Services.Provider.MIKECore",
"MapStyleConnectionString": "[AppData]styles.json",
"MapStyleRepositoryType": "DHI.Services.GIS.Maps.MapStyleRepository, DHI.Services.GIS",
"Name": "DFS2",
"Id": "dfs2-map"
},
"dfsu-map": {
"$type": "DHI.Services.GIS.WebApi.MapServiceConnection, DHI.Services.GIS.WebApi",
"MapSourceConnectionString": "[AppData]dfsu",
"MapSourceType": "DHI.Services.Provider.MIKECore.DfsuMapSource, DHI.Services.Provider.MIKECore",
"MapStyleConnectionString": "[AppData]styles.json",
"MapStyleRepositoryType": "DHI.Services.GIS.Maps.MapStyleRepository, DHI.Services.GIS",
"Name": "DFSU",
"Id": "dfsu-map"
},
"dfs2-map-cached": {
"$type": "DHI.Services.GIS.WebApi.CachedMapServiceConnection, DHI.Services.GIS.WebApi",
"MapSourceConnectionString": "[AppData]dfs2\\R20141001.dfs2",
"MapSourceProperties": {
"$type": "DHI.Services.Parameters, DHI.Services",
"CachedImageWidth": 1024,
"NumberOfCachedZoomLevels": 5,
"CacheExpirationInMinutes": 20
},
"MapSourceType": "DHI.Services.Provider.MIKECore.Dfs2MapSource, DHI.Services.Provider.MIKECore",
"MapStyleConnectionString": "[AppData]styles.json",
"MapStyleRepositoryType": "DHI.Services.GIS.Maps.MapStyleRepository, DHI.Services.GIS",
"Name": "DFS2 (cached)",
"Id": "dfs2-map-cached"
}
What you get via WebApi:
- WMS-like map
GET /api/maps?request=GetMap&service=wms&version=1.3.0 &width=1280&height=720 &styles=rain &layers=dfs2-map // or dfsu-map &crs=EPSG:3857 &bbox=1110000,6400000,1130000,6420000 &item=Water%20Level ×tamp=2014-10-01T10:00:00Z - Batch render
POST /api/maps/dfs2-map?width=1024&height=768&style=rain&item=3&bbox=1110000,6400000,1130000,6420000 Body: { "2014-10-01T10:00:00Z":"R20141001.dfs2","2014-10-01T11:00:00Z":"R20141001.dfs2" } - Timesteps
GET /api/maps/dfs2-map/datetimes/R20141001.dfs2
Caching: the cached connection tiles + stores images and requires
"EPSG:3857"(enforced). Great for frequently requested extents.
B) Programmatic registration¶
using DHI.Services;
using DHI.Services.GIS.Maps;
using DHI.Services.Provider.MIKECore;
// [AppData] roots & style repo (JSON)
var appData = Path.Combine(env.ContentRootPath, "App_Data");
var styles = Path.Combine(appData, "styles.json");
var styleSvc = new MapStyleService(new DHI.Services.GIS.Maps.MapStyleRepository(styles));
// DFS2: single file
ServiceLocator.Register(
new MapService(
new Dfs2MapSource(Path.Combine(appData, "dfs2", "R20141001.dfs2")),
styleSvc),
"dfs2-map");
// DFSU: directory + choose file at call time
ServiceLocator.Register(
new MapService(
new DfsuMapSource(Path.Combine(appData, "dfsu")),
styleSvc),
"dfsu-map");
// Example call later
var bbox = BoundingBox.Parse("1110000,6400000,1130000,6420000");
using var img = ServiceLocator.Resolve<MapService>("dfsu-map").GetMap(
style: "0~10:#0000FF,#00FFFF,#00FF00,#FFFF00,#FF0000",
crs: "EPSG:3857",
boundingBox: bbox, width: 1200, height: 900,
sourceId: "mesh01.dfsu", // choose which file in the dfsu folder
dateTime: null,
item: "U velocity",
parameters: new Parameters { { "includevector", "true" }, { "isoline", "Contour" } });
9) End-to-end examples¶
9.1 DFS2 quick render (style code)¶
var mapSvc = new MapService(new Dfs2MapSource(@"C:\dfs2\R20141001.dfs2"), mapStyleService: null);
using var img = mapSvc.GetMap(
style: "0~10:#0000FF,#00FFFF,#00FF00,#FFFF00,#FF0000", // StyleCode
crs: "EPSG:3857",
boundingBox: BoundingBox.Parse("1110000,6400000,1130000,6420000"),
width: 1024, height: 768,
sourceId: "", // ctor had the file
dateTime: new DateTime(2014,10,1,10,0,0, DateTimeKind.Utc),
item: "3",
parameters: new Parameters { { "isoline", "IsoLine" } });
using var fs = File.OpenWrite("dfs2-map.png");
img.Encode(SKEncodedImageFormat.Png, 95).SaveTo(fs);
9.2 DFSU time stack¶
var styleSvc = new MapStyleService(new MapStyleRepository(@"C:\styles\styles.json"));
var mapSvc = new MapService(new DfsuMapSource(@"C:\dfsu"), styleSvc);
var times = new Dictionary<DateTime,string> {
[new(2020,10,21,10,0,0, DateTimeKind.Utc)] = "mesh01.dfsu",
[new(2020,10,21,11,0,0, DateTimeKind.Utc)] = "mesh01.dfsu"
};
var frames = mapSvc.GetMaps("wl", BoundingBox.Parse("1110000,6400000,1130000,6420000"),
new SKSizeI(800,600), times, "Water Level", Parameters.Empty);
foreach (var (t, bmp) in frames)
{
using (bmp) using var fs = File.OpenWrite($"dfsu-{t:yyyyMMdd-HHmm}.png");
bmp.Encode(SKEncodedImageFormat.Png, 95).SaveTo(fs);
}
10) Troubleshooting¶
- CRS error: The providers strictly enforce
"EPSG:3857". Convert upstream if necessary. - Item not found: If
itemname/number doesn’t exist, the underlyingItemInfolookup returns null and the call will fail. Verify available items in the file (see MIKECore Providers doc). - Timestep mismatch:
GetTimestepIndex(dateTime)expects an existing timestamp. UseGetDateTimes(id)to pick valid values. - Large images: Dispose your
SKBitmappromptly. For stacks, wrap eachbmpinusing. - Caching: When using the cached connection, remember it tiles/stitches and requires 3857; invalid CRSs will throw early.
11) What you’ll actually touch¶
- Services
MapService→GetMap(...),GetMaps(...),GetDateTimes(...)
- Providers
Dfs2MapSource,DfsuMapSource- Ctors:
(string connectionString)or(IFileSource fileSource, string filePathOrPrefix = null, Parameters parameters = null) GetDateTimes(id),GetMap(...),GetLayerInfo(..)
- Ctors:
- Style
MapStyle,MapStyleService,MapStyleRepository(JSON or other repos)
- Parameters
DHI.Services.Parameters: pass strings; strongly typed getters on provider side
With MIKECore providers wired, you can render DFS2 gridded and DFSU unstructured rasters directly into Web Mercator bitmaps, layer them on web base maps, and serve them via the WebApi using either connections.json or programmatic registration.