Skip to content

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 → resolved MapStyle (palette thresholds used for banding)
    • crsmust be "EPSG:3857" (Web Mercator). Anything else throws.
    • bbox → render extent (in EPSG:3857 meters)
    • width/height → output pixel size
    • sourceIdDFS file (see “File sourcing” below)
    • dateTime → timestep; absent ⇒ first timestep
    • itemitem 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>).
  • Performance

    • The base class implements parallel GetMaps(...) (time stack fan-out + ordered aggregation).

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" }});

DfsuMapSource supports the same two modes; if you pass a file path to the ctor, call with sourceId: "". If you pass a directory root, call with sourceId: "<mesh>.dfsu" (relative to that root).


3) Styling (palettes, contours & vectors)

The MIKECore contouring pipeline honors the MapStyle palette thresholds (if provided):

  • If your MapService has a MapStyleService, the style string is a repo id (e.g. "rain").
  • If you pass no style service, the style string 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 missingnull Optional data scale (null = auto)
coloringtype enum DiscreteColoring DiscreteColoring or GradientColoring
shadingtype enum ShadedContour ShadedContour or FlatFill

item can 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.
  • bbox must be meters in EPSG:3857 (x,y order).
  • Choose width/height appropriate 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
        &timestamp=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 item name/number doesn’t exist, the underlying ItemInfo lookup 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. Use GetDateTimes(id) to pick valid values.
  • Large images: Dispose your SKBitmap promptly. For stacks, wrap each bmp in using.
  • 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
    • MapServiceGetMap(...), GetMaps(...), GetDateTimes(...)
  • Providers
    • Dfs2MapSource, DfsuMapSource
      • Ctors: (string connectionString) or (IFileSource fileSource, string filePathOrPrefix = null, Parameters parameters = null)
      • GetDateTimes(id), GetMap(...), GetLayerInfo(..)
  • 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.