The Charts API
Introduction
The SDK provides the Charts API to allow consumers to work with terminal charts in a unified and consistent manner. The Charts API consists of three main pillars:
- It defines a set of data structures to use to represent chart data.
- It defines interfaces to use to retrieve chart data.
- It provides classes that can be used to retrieve built-in chart data from the sim.
Pillars #1 and #2 allow all chart providers and chart consumers to agree on a common contract to use when working with charts. This reduces the amount code that must be written on the consumer side to deal with different chart providers. The classes provided by pillar #3 conform to the aforementioned contract.
The rest of this page describes the contract defined by pillars #1 and #2 in more detail. See this page for more information on the sim's built-in chart providers and how to use the classes provided by pillar #3. Finally, see this page for a guide on how to create your own chart provider that conforms to the Charts API.
Chart Data Structure
Chart Index
The Charts API applies to terminal charts - charts related to an airport or terminal procedures (SIDs, STARs, and approaches). As such, the top-level structure defined by the API is an index of charts associated with a single airport: ChartIndex
. A chart index is organized into zero or more named chart categories (ChartIndexCategory
). Each category in turn contains a list of zero or more charts belonging to that category, which each chart represented by a metadata object.
The API does not define any specific set of chart categories that must be used. Each chart provider is free to use its own set of categories. The type parameters on ChartIndex
and ChartIndexCategory
are used to define the possible chart category names that can be used. If you don't know all the possible category names, then use string
for the type parameters.
Chart Metadata
The ChartMetadata
object provides metadata describing a chart. Refer to the linked type documentation for details on each property defined on ChartMetadata
.
Each chart metadata object is associated with a single chart (a chart may have multiple pages - see the next section) and is assigned a GUID. The GUID is unique to its associated chart and is used to reference the chart in various places.
Chart Pages
Charts may have an arbitrary number of pages. The ChartPages
object represents an ordered collection of pages for a single chart. The ChartPage
object contains information describing a single page.
Each chart page must be rectangular and is assigned a width and height. The units used to measure a page's width and height can be arbitrary (they do not have to pixels). Additionally, each chart page can define zero or more areas (ChartArea
). An area is a rectangular region of a page. Areas can take up the entire page and can overlap with one another. Areas can optionally be georeferenced. Each georeferenced area is assigned a Lambert conformal conic projection with specific parameters such that the projection describes how geographic coordinates (latitude/longitude) are mapped to the chart image within the georeferenced area.
Finally, each chart page defines a list of URLs (ChartUrl
) that correspond to images or documents that display the page's contents. Each URL corresponds to a single image or document and is assigned a descriptive name. The URL's name allows it to be disambiguated from other URLs associated with the same page.
The API does not define any specific set of names that must be used for chart URLs. Each chart provider is free to use its own set of names.
Retrieving Chart Data
Retrieving Chart Indexes and Pages
The Charts API defines the ChartService
interface to be used to retrieve chart index and chart page data. Consumers can use this interface to get chart data in a consistent way without having to worry about the details of how or from where the data are retrieved.
The getIndexForAirport()
method can be used to get a chart index from a provider for an airport using the airport's ICAO value. Meanwhile, the getChartPages()
method can be used to get page data for a chart given the chart's GUID. Both methods are asynchronous and return Promises which either resolve with the requested data or reject with an error code describing what went wrong.
The basic flow for retrieving chart data using ChartService
will look something like the following:
import { ChartPage, ChartService, IcaoValue } from '@microsoft/msfs-sdk';
const chartService: ChartService = ...;
// The following function gets the first listed chart page for an airport.
async function getFirstChartPage(service: ChartService, provider: string, airportIcao: IcaoValue): Promise<ChartPage | null> {
try {
// Gets the chart index for the airport.
const chartIndex = await service.getIndexForAirport(provider, airportIcao);
// Gets the first category in the index.
const firstChartCategory = chartIndex.charts[0];
if (!firstChartCategory) {
return null;
}
// Gets the metadata for the first chart in the category.
const firstChartMetadata = firstChartCategory.charts[0];
if (!firstChartMetadata) {
return null;
}
// Gets the pages for the chart.
const chartPages = await service.getChartPages(firstChartMetadata.guid);
// Gets the first page.
return chartPages.pages[0] ?? null;
} catch (code) {
console.warn(`Something went wrong while retrieving chart page. Error code: ${code}`);
return null;
}
}
Retrieving Chart Images
Getting data describing charts is not very useful without the ability to display the actual chart. In JS/HTML instruments, images are usually displayed by referencing a URL from which the image data in an appropriate place (the src
attribute of an <img>
element, for example). The Charts API adopts this strategy and defines ChartImageSupplier
to provide an interface that consumers can use to retrieve chart image URLs.
A ChartImageSupplier
instance does not directly display or load chart images itself. Instead, it provides image URLs for chart pages. These image URLs can then be referenced to load and display the chart image.
Chart image URLs are provided by ChartImageSupplier
from chart page URLs. Despite both being named "URL", the two are distinct. Chart page URLs are used to uniquely identify chart image or document assets. These URLs are stored in ChartUrl
objects, which are in turn stored in ChartPage
objects. On the other hand, chart image URLs describe a location from which the content of a chart image asset can be retrieved. The image URL for an asset is not necessarily the same as the chart page URL for the same asset.
To use ChartImageSupplier
, set the chart page whose image you wish to display by passing the page URL to showChartImage()
. Then subscribe to the supplier's image
property to get the image URL. The value provided by image
also contains the page URL used to retrieve the current image URL as well as an error code that can be used to diagnose problems or display error messages when the supplier fails to retrieve an image URL for a page.
The following code shows an example of how to use ChartImageSupplier
and a display component to display chart images.
import {
ChartImageSupplier, ChartUrl, ComponentProps, DisplayComponent, FSComponent, VNode
} from '@microsoft/msfs-sdk';
interface ChartDisplayProps extends ComponentProps {
createImageSupplier: () => ChartImageSupplier;
}
class ChartDisplay extends DisplayComponent<ChartDisplayProps> {
private readonly imageSupplier = this.props.createImageSupplier();
public setPageUrl(url: ChartUrl): void {
this.imageSupplier.showChartImage(url.url);
}
public render(): VNode {
return (
<img src={this.imageSupplier.image.imageUrl} />
);
}
public destroy(): void {
this.imageSupplier.destroy();
super.destroy();
}
}
Chart image URLs are not guaranteed to be stable or unique. In other words, the image URL used to load a given chart asset can change over time, and the same image URL can be used to load more than one chart asset (at different times). Because of this, it is generally not safe to cache chart image URLs. Always use the most up-to-date image URL provided by ChartImageSupplier
for any given chart page URL. This also means that you must use a separate instance of ChartImageSupplier
for each independent chart display.