Skip to content
We're currently creating a lot of content. Sign up to get notified when it's ready.

Map

The map API gives you access to Qatium’s map environment, enabling you to create custom visualizations, move the camera, highlight assets and more.

Accessing the map

Once Qatium has loaded, you can access the map by using the window.qatium.map object in your browser console:

const sdk = window.qatium
const map = sdk.map

Or by using the map object in the Plugin SDK

import type { SDK, PluginI } from '@qatium/plugin/engine'
class MyPlugin implements PluginI {
run(sdk: SDK) {
const map = sdk.map
}
}

In the following sections, we will refer to the Map object as map without the window.qatium prefix.

Map Queries

getCamera()

Returns the current state of the map camera.

Method signature

getCamera(): Camera;
Returns

An object containing:

  • zoom: number Zoom level
  • pitch: number Angle towards the horizon measured in degrees with a range between 0 and 85
  • bearing: number The direction the camera is facing, measured clockwise as an angle from true north on a compass. This can also be called a heading. In Qatium, north is 0°, east is 90°, south is 180°, and west is 270°
  • center: {lng: number, lat: number} The longitude and latitude at which the camera is pointed

getSelectedElement()

Returns a SelectedElement object representing the currently selected element in the map, or undefined if nothing is selected. The SelectedElement object contains the element ID and the type of element.

Example

const selectedElement = map.getSelectedElement()
selectedElement.id // The element ID
selectedElement.type // Type in "Pipe", "Junction", "Valve", "Pump", "SupplySource" or "Tank"

Map Actions

setHighlights()

Highlights the network elements passed as parameter (assets or zones) in elementIds (an array of element IDs). If the elementIds array is empty, all highlights are cleared (equivalent to using clearHighlights()).

Method signature

setHighlights(elementIds: string[]) : void
Parameters
  • elementIds: string[]: an array of asset / zone IDs to be highlighted

Example

Highlights two tanks in Magnetic Island:

map.setHighlights(['Nellybay', 'Horseshoebay'])

clearHighlights()

Clears all the highlights in the map.

fitTo()

Centers the map viewport, while fitting a set of destination network elements or bounds, using the animation options set in the optional options parameter.

Method signature

fitTo(boundsOrIds: ElementId[] | Bounds, options?: FlightOptions) : Promise<void>
Parameters
  • boundsOrIds: ElementId[] | Bounds Accepts an asset / zone id or bounds as destination.
  • options: FlightOptions Optional Options object that accepts:
    • padding: Bounds Optional Dimensions in pixels applied on each side of the viewport for shifting the vanishing point
    • flightDuration: number Optional The animation’s duration, measured in milliseconds
    • maxZoom: number Optional The max level of zoom allowed to perform the action
Returns

A promise with no value to allow async calls, resolved when the camera movement has finished.

Examples

Center the map to the Horseshoebay tank, using a slow animation (5 seconds), with a padding of 100 pixels on each side:

map.fitTo(['Horseshoebay'], {
flightDuration: 5000,
maxZoom: 20,
padding: {
top: 100,
right: 100,
bottom: 100,
left: 100
}
})

Fit a collection of assets in the viewport:

map.fitTo(['Horseshoebay', 'Nellybay', 'Cocklebay'], {
flightDuration: 1000,
padding: { top: 300, right: 300, bottom: 300, left: 300 }
})

Fitting to bounds:

map.fitTo({
top: 100,
right: 100,
bottom: 100,
left: 100
})

moveTo()

Method signature

Transitions the camera view, following a set of travel options.

moveTo(options: CameraOptions) : Promise<void>
Parameters

options: CameraOptions Transition object that accepts:

  • zoom: number Optional Target zoom level
  • pitch: number Optional Angle towards the horizon measured in degrees with a range between 0 and 85
  • transitionDuration: number Optional The animation’s duration, measured in milliseconds
  • latitude: number Optional Geographic latitude following the decimal degrees format, ranging from -90 to 90
  • longitude: number Optional Geographic longitude following the decimal degrees format, ranging from -180 to 180
  • bearing: number Optional The direction the camera is facing, measured clockwise as an angle from true north on a compass. This can also be called a heading. In Qatium, north is 0°, east is 90°, south is 180°, and west is 270°.
  • padding: Padding Optional Dimensions in pixels applied on each side of the viewport for shifting the vanishing point.
Returns

A promise with no value to allow async calls, it resolves when the camera movement has finished

Examples

Move the camera to Mandalay in Magnetic Island, AU:

map.moveTo({
latitude: -19.157,
longitude: 146.849
})

Do a tilted camera travel to the same location:

map.moveTo({
zoom: 18,
pitch: 45,
transitionDuration: 2000,
latitude: -19.157,
longitude: 146.849
})

Animate the camera and rotate around the viewpoint:

await map.moveTo({
zoom: 18,
pitch: 45,
transitionDuration: 2000,
latitude: -19.157,
longitude: 146.849
})
await map.moveTo({ transitionDuration: 3000, bearing: 90 })
await map.moveTo({ transitionDuration: 3000, bearing: 180 })
await map.moveTo({ transitionDuration: 3000, bearing: 270 })
await map.moveTo({ transitionDuration: 3000, bearing: 0 })

addOverlay()

Adds a custom visual overlay on top of the map.

Method signature

addOverlay(layers: Layer[]): void
Parameters

layers: List of Layer List of layer objects containing all data and styling, from any of the supported layer types.

Where Layer is

export type Layer = {
type: 'ScatterplotLayer' | 'PolygonLayer' | 'IconLayer' | 'HeatmapLayer' // ...
id: string
data: Feature[]
tooltip?: GetTooltipData,
popover?: GetTooltipData
// ... properties specific to the layer type
}

Tooltips and Popovers

You can associate a tooltip and/or a popover with your layer. To do that you need to provide the optional tooltip and/or popover properties.

The main differences are that:

  • Popovers appear on click and are visible until they are closed or another popover is open.
  • Tooltips appear on hover and disappear on blur.
  • User can see 1 popover and 1 tooltip max at the same time.
  • Tooltips should be small and popovers may be a bit larger.

The property value must be a function that receives a MapItem and returns TooltipData

export type GetTooltipData = (mapItem: MapItem) => TooltipData
export type MapItem = {
source?: string
id?: string
ids?: string[]
coordinates?: { lng: number; lat: number }
}
export type TooltipData = {
title: string
type: string
icon: QatiumIcon | Base64Image
sections: TooltipSection[]
}
export type TooltipSection = TooltipProperty[]
export type TooltipProperty = {
label: string
value: TooltipPropertyValue
unit?: string
reading?: TooltipPropertyReading
warning?: TooltipPropertyWarning
}

You can also return a Promise for Section, TooltipPropery, TooltipPropery.value, TooltipPropery.reading, and TooltipPropery.warning

Examples

Highlight all hydrants in red:

Highlight all hydrants in red

const data = sdk.network.getJunctions((j) => j.group === JunctionGroups.Hydrant).map((j) => ({
type: "Feature",
geometry: j.geometry,
properties: {}
}));
sdk.map.addOverlay([{
id: 'hydrants',
type: "ScatterplotLayer",
data,
stroked: true,
getPosition: (d: Feature) => d.geometry.coordinates,
getRadius: () => 2,
getFillColor: [255, 0, 0],
getLineColor: [0, 0, 0],
getLineWidth: 2,
radiusScale: 6
}})

Hydrants mean pressure density with a heatmap:

Hydrants mean pressure density

const data = sdk.network.getJunctions((j) => j.group === JunctionGroups.Hydrant).map((p) => ({
type: "Feature",
geometry: j.geometry,
properties: { pressure: j.simulation.pressure }
}));
qatium.map.addOverlay([
{
id: "HeatmapLayer",
type: "HeatmapLayer",
data,
visible: true,
aggregation: "MEAN",
radiusPixels: 25,
opacity: 0.4,
getPosition: (f) => f.geometry.coordinates,
getWeight: (f) => f.properties.pressure,
}
])

Arc layer showing source and target pressures at the connections of pipes

Arc layer

const data = sdk.network.getPipes().map((p) => ({
type: "Feature",
geometry: p.geometry,
properties: {
sourcePressure: sdk.network.getNeighborAssets(p.id)[0].simulation.pressure,
targetPressure: sdk.network.getNeighborAssets(p.id)[1].simulation.pressure
}
}));
sdk.map.addOverlay([{
id: 'pressures',
data,
type: "ArcLayer",
getSourcePosition: (d) => d.geometry.coordinates[0],
getTargetPosition: (d) => d.geometry.coordinates[d.geometry.coordinates.length - 1],
getSourceColor: (f) => [f.properties.sourcePressure * 2, 0, 255, 255],
getTargetColor: (f) => [f.properties.targetPressure * 2, 0, 130, 255],
getHeight: 1,
getWidth: 4
}])

Show tank IDs on the map

Text layer

const data = sdk.network.getTanks().map((p) => ({
type: "Feature",
geometry: p.geometry,
properties: { id: p.id }
}));
sdk.map.addOverlay([{
id: "TextLayer",
type: "TextLayer",
data,
getPosition: (f) => f.geometry.coordinates,
getText: (f) => f.properties.id,
getSize: () => 24,
getColor: () => [255, 255, 255, 255],
fontFamily: "Arial"
} as OverlayLayer<"TextLayer">])

Tooltip:

export const PressuresTooltip = (mapItem: MapItem): TooltipData => {
const { min, max, mean, total, avgHeight } = getJunctionPressures(mapItem.ids)
const { pressure, elevation } = sdk.network.getUnits()
return {
title: `${total} Customer points`,
icon: {
media: 'image/svg+xml',
charset: 'utf-8',
data: btoa(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path></svg>'
)
},
type: 'Customer point pressuer',
sections: [
[
{ label: 'Minimum', unit: pressure, value: min },
{ label: 'Mean', unit: pressure, value: mean },
{ label: 'Maximum', unit: pressure, value: max }
],
[
{ label: 'Average height', unit: elevation, value: avgHeight }
]
]
}
}

Tooltip and the code that generates it with pointing arrows

Supported layers

You can refer to the DeckGL documentation to find a list of all available layers and how to declare them.

We support all available layer types except for BitmapLayer and GeohashLayer or custom layers.

For each layer, you’ll need to provide an object with a type parameter with the name of the type of layer and all the relevant parameters for that specific the type of layer.

hideOverlay()

Hides/removes all the layers of the overlay

Method signature

hideOverlay(): void

showOverlay()

Forces all the layers in the overlay to be shown.

showOverlay(): void

addSytles()

Method signature

Allows you to change the styles of elements on the map.

addStyles(styles: Styles) : void
Parameters

styles: Styles Transition object that needs:

  • assetId: string;
  • Style properties:
    • isShadowVisible?: boolean: Whether the feature halo is visible. Default: false
    • shadowColor?: string: Color of the feature halo. Default: theme.colors.primary.light. Accepted values are tied to mapbox color specification
    • outlineOpacity?: number: Value used to show an outline around features. Default: 0
sdk.map.addStyles({
"Horseshoebay": {
isShadowVisible: true,
outlineOpacity: 1,
shadowColor: "yellow"
},
"Nellybay": {
isShadowVisible: true,
outlineOpacity: 0,
shadowColor: "red"
}
})

Examples

Highlight all hydrants in yellow:

Highlight all tanks in yellow

removeSytles()

Method signature

Allows you to delete the styles applied with the addStyles method.

removeStyles() : void
sdk.map.removeStyles()