SUNDIAL a Developing Today project

SUNDIAL

A WebGL2 GIS library that measures on the ellipsoid: Karney geodesy on WGS84, its own State Plane projections checked against NGS and Karney, true circular arcs, decluttered labels, id-buffer picking, and topology editing that keeps parcel fabrics sealed. 44 KB on the wire.

npm i @devtomorrow/sundial
Projection error
23 nm worst
its own transverse Mercator over the board's sample of Karney's 80-digit test set the one accuracy figure here that is Sundial's own arithmetic; the whole set runs in the unit suite (55 nm at the λ = 90° singularity, under 5 nm within 20° of the central meridian). Distances and areas come from GeographicLib, the same build the benchmark grades against
Benchmark
RANK 1 96.0 / 100 · of 7
house entry · the full board

Demos

Every button draws on the map. Keep an eye on it.

Geodesy

Distances and areas come from GeographicLib's Karney solver on the WGS84 ellipsoid, the same mathematics the benchmark checks every library against.

True curves

County deeds carry circular-arc boundaries; classic GeoJSON cannot express them. Sundial speaks every open format that can: OGC JSON-FG (the circular-arcs class), SQL/MM WKT as spatial databases emit it, and Esri JSON curveRings. One recorded arc stays one arc in all three, tessellated only for the screen at two centimeters, and exports back out the same way: byte-identical for any arc you have not edited, which the round-trip tests pin.

Labels

Sundial rasterizes its own signed-distance glyphs and declutters with a typed-column collision pass. Ten thousand labels, timed on your machine.

Picking

An id-buffer renders every feature's identity off-screen; hover reads it back asynchronously through a fence ring. Load the county fabric and point.

Camera

A fourteen-second scripted world tour with frame deltas sampled the whole way. Watch the map fly it and read your average.

Quick start

A map
import { SundialMap } from '@devtomorrow/sundial';

const map = new SundialMap({
  container: document.getElementById('map'),
  center: [-103.2497, 44.0525],
  zoom: 16,
});
await map.whenSettled();
Data, labels, picking
const deeds = map.addGeoJson(parcels, {
  fill: { color: '#c9a13b', opacity: 0.2 },
  outline: { color: '#c9a13b', widthPx: 1.5 },
});

const { addLabels } =
  await import('@devtomorrow/sundial/labels');
addLabels(map, points.map((p, i) =>
  ({ lngLat: p, text: names[i], priority: 1 })));

map.on('click', (ev) => console.log(ev.feature));
Measure & edit
const { whenGeodesyReady } =
  await import('@devtomorrow/sundial');
const geo = await whenGeodesyReady();
geo.Inverse(34.05, -118.24, 51.5, -0.13);

const { EditWorkspace, curveFeaturesToInputs } =
  await import('@devtomorrow/sundial/edit');
const ws = new EditWorkspace(
  curveFeaturesToInputs(deeds), 44.08);
// moving a shared corner moves every deed on it
ws.moveVertex(ws.snap(lngLat, 6).node, target);
Edit with a server
import { EditSession, SundialBackend, FeatureServiceBackend, DocumentBackend } from '@devtomorrow/sundial/sync';
import { createEditor, mountPeers } from '@devtomorrow/sundial/editor';

// Live, multi-user, with presence: the Sundial companion server.
const live = new EditSession(SundialBackend.open(base, datasetId, { peer, name }), { name });
const editor = createEditor(map, await live.open(), { session: live });
mountPeers(editor, document.getElementById('peers')!);

// Save-based: an OGC API Features collection, an ArcGIS layer, or one file.
const ogc = new EditSession(FeatureServiceBackend.ogcApi({ collectionUrl }));
const arcgis = new EditSession(FeatureServiceBackend.arcgis({ layerUrl, token }));
const file = new EditSession(new DocumentBackend({ url, format: 'json-fg' }));
@devtomorrow/sundial
map, layers, projections, picking · 34.7 KB gz, plus Sundial's own 10.7 KB Karney solver on demand
…/labels
SDF text + declutter, loaded on first use
…/edit
DCEL topology, snapping, rules, undo; never in the map payload
…/tess-worker
earcut worker for stress-scale fills (3.3 KB gz)

The benchmark

Sundial competes on the Frontend GIS Benchmark as a house entry. Every figure above comes from the published methodology: same fixtures, same ladder, and a Karney reference computed live.

Rendering tests

The pages the e2e suite drives, each case on a stage of its own, runnable by hand: ink truth (geometry reaches pixels), engine lifecycle (context loss, the device pool, resizing, picking, the settle contract) and arc ink (the GPU arc layer against an analytic circle, every device pixel).

Raw harness (used by the test probes)
Sundial dev
Edit Lab 6 m · Hover to snap · Shift-drag moves a vertex · U/Y undo/redo

          

Private alpha

Sundial installs from a private registry while it hardens. For access (the npm scope, the source, and a hand from the team), write to us and say what you're building.

support@developingtoday.net

Request access