G3X Touch Electronic Charts
Introduction
The G3X Touch electronic charts feature allows the user to view terminal procedure charts directly within the avionics. The user may select and view charts (provided they are available) for any airport and associated instrument procedure.
By default, the electronic charts feature supports charts from the sim's built-in LIDO and FAA charts sources. Plugins can add additional sources or override the built-in sources with custom behavior. The following sections will describe how to use a plugin to define and add a custom charts source.
Defining a Charts Source
Charts sources for the G3X Touch are defined using the G3XChartsSource
interface. This interface represents an adapter layer between the SDK Charts API and the G3X Touch avionics. In other words, each charts source is responsible for interpreting its own charts data and presenting the results to the G3X Touch in a standardized manner.
Basic Setup
The first thing to do when creating a custom charts source is to give it a unique ID and name.
The source's unique ID is a string that uniquely identifies the source. It cannot be the empty string, but other than that it can be anything you wish as long as it does not conflict with the ID of another charts source. The ID is only used internally and is never displayed to the user.
In order to override and replace of the built-in charts sources with your own custom source, use the ID of the built-in source for your own source. These built-in IDs can be accessed from the G3XBuiltInChartsSourceIds
enum.
The source's name will be displayed to the user. Unlike the ID, the name does not have to be unique (but we recommend choosing a unique name for obvious reasons).
After you have chosen a suitable ID and name, you should have your charts source provide these via its uid
and name
properties, respectively.
import { G3XChartsSource } from '@microsoft/msfs-wtg3x';
export class MyChartsSource implements G3XChartsSource {
public readonly uid = 'my-charts-id';
public readonly name = 'MyCharts';
// ...
}
Chart Provider
All charts sources must be associated with a specific Charts API chart provider. When a charts source is used, the G3X Touch will request chart data using the source's associated provider. Any chart provider can be used. You can choose to use one of the sim's built-in chart providers or a custom chart provider. For more information on how to create a custom chart provider, please refer to this page.
Charts sources do not have to choose unique chart providers. Multiple sources are allowed to use the same provider.
Each charts source should provide the string ID of its associated chart provider via its provider
property.
import { BuiltInChartProvider } from '@microsoft/msfs-sdk';
import { G3XChartsSource } from '@microsoft/msfs-wtg3x';
class MyChartsSource implements G3XChartsSource {
// Use the built-in LIDO chart provider.
public readonly provider = BuiltInChartProvider.Lido;
// ...
}
In addition to specifying the provider, each charts source must also define how to retrieve chart data from the provider. The source does this using its getChartService()
and createChartImageSupplier()
methods.
The getChartService()
method returns an instance of ChartService
which retrieves chart index and chart page data. You may choose to have the method return a new instance of ChartService
every time it is called or return a single cached instance.
The createChartImageSupplier()
method creates and returns an instance of ChartImageSupplier
which supplies image URLs for loading and displaying chart images. This method must return a new instance of ChartImageSupplier
each time it is called.
import { ChartImageSupplier, ChartService } from '@microsoft/msfs-sdk';
import { G3XChartsSource } from '@microsoft/msfs-wtg3x';
class MyChartsSource implements G3XChartsSource {
public readonly provider = 'MyChartProvider';
public getChartService(): ChartService {
return new MyChartService();
}
public createChartImageSupplier(): ChartImageSupplier {
return new MyChartImageSupplier();
}
// ...
}
When using one of the sim's built-in providers, you can use the SimChartService
class as the source's chart service and the ChartView
class as the source's chart image supplier.
import {
ChartImageSupplier, ChartsClient, ChartService, ChartView, SimChartService
} from '@microsoft/msfs-sdk';
import { G3XChartsSource } from '@microsoft/msfs-wtg3x';
class MyChartsSource implements G3XChartsSource {
public getChartService(): ChartService {
return new SimChartService();
}
public createChartImageSupplier(): ChartImageSupplier {
const view = new ChartView();
ChartsClient.initializeChartView(view);
return view;
}
// ...
}
Selecting Charts
The most important thing that a charts source does is to analyze the charts that are made available from its provider and select those that are suitable for use by the G3X Touch. The G3X Touch supports displaying five types of charts:
- Airport Diagram: charts depicting the ground environment of an airport (including aprons, taxiways, runways, etc).
- Info: informational charts related to airport operations (excluding airport diagram charts).
- Departure: charts depicting departure procedures.
- Arrival: charts depicting arrival procedures.
- Approach: charts depicting approach procedures.
Charts are grouped by type and the groups are sorted in the following order - Airport Diagram, Approach, Arrival, Departure, Info - when they are presented in the Waypoint Info Charts tab selection dropdown list.
Charts sources select the charts that belong to each type via the getAirportDiagramCharts()
, getInfoCharts()
, getDepartureCharts()
, getArrivalCharts()
, and getApproachCharts()
methods. Each of these methods takes a ChartIndex
for a particular airport and returns an array of ChartMetadata
, where each ChartMetadata
object in the array represents a chart of the appropriate type that can be displayed. The order of the charts in the array determines the order in which the charts are presented (among charts of its type) in the Waypoint Info Charts tab selection dropdown list. If a chart has multiple pages, then each page of the chart will be presented as a separate item.
Charts sources may use any arbitrary logic for assigning charts to each type. The specific details will depend on how the charts data from the source's provider is organized.
The following example code shows how a custom charts source may select Departure charts from a hypothetical custom provider by including all charts organized in the Departures category.
import { ArrayUtils, ChartIndex, ChartMetadata } from '@microsoft/msfs-sdk';
import { G3XChartsSource } from '@microsoft/msfs-wtg3x';
class MyChartsSource implements G3XChartsSource {
public getDepartureCharts(chartIndex: ChartIndex<string>): ChartMetadata[] {
return ArrayUtils.flatMap(
chartIndex.charts.filter(category => {
return category.name === 'Departures'
}),
category => category.charts
);
}
// ...
}
In addition to selecting charts of the five major types, charts sources must also be able to select a chart page that depicts a default airport diagram for each airport as well as chart pages that depict individual instrument procedures.
The getAirportDiagramPage()
method takes an array of G3XChartsPageData
objects - each one representing a single chart page - and returns the single G3XChartsPageData
from the array that represents the default airport diagram, if such a page exists. The array passed to getAirportDiagramPage()
is guaranteed to contain all of the page data for the charts selected by getAirportDiagramCharts()
for a given airport and only those page data.
The getDeparturePage()
, getArrivalPage()
, and getApproachPage()
methods likewise take an array of G3XChartsPageData
and returns the page data from the array that represents a particular instrument approach procedure described by the other arguments passed to the methods. The array passed to getDeparturePage()
, getArrivalPage()
, and getApproachPage()
is guaranteed to contain all of the page data for the charts selected by getDepartureCharts()
, getArrivalCharts()
, and getApproachCharts()
, respectively, for a given airport and only those page data. It is perfectly acceptable for one of these methods to return the same page data for multiple different procedures if a single page depicts multiple procedures.
The following example code shows how a custom charts source may select a Departure chart page for a given departure procedure from a hypothetical custom provider by using the associated procedures data found in the chart metadata.
import { ArrayUtils, ChartIndex, ChartMetadata, ChartProcedureType, RunwayIdentifier } from '@microsoft/msfs-sdk';
import { G3XChartsPageData, G3XChartsSource } from '@microsoft/msfs-wtg3x';
class MyChartsSource implements G3XChartsSource {
public getDeparturePage(
pages: readonly G3XChartsPageData[],
departureName: string,
enrouteTransitionName: string,
runway: Readonly<RunwayIdentifier>
): G3XChartsPageData | undefined {
// Iterate through the candidate pages and return the first match.
for (const page of pages) {
// Search the page's associated procedures for a match to the requested procedure.
for (const procedure of page.metadata.procedures) {
if (
procedure.type === ChartProcedureType.Sid
&& procedure.ident === departureName
&& (
// If enrouteTransitionName is the empty string, then we will not filter for enroute transitions.
enrouteTransitionName === ''
// If the associated procedure's enrouteTransition prop is null, then it includes all enroute transitions.
|| procedure.enrouteTransition === null
// Otherwise match the enroute transition.
|| procedure.enrouteTransition === enrouteTransitionName
)
&& (
// If runway is the empty identifier, then we will not filter for runways.
runway.number === ''
// Otherwise match the runway.
|| procedure.runways.some(query => query.number === runway.number && query.designator === runway.designator)
)
) {
return page;
}
}
}
return undefined;
}
// ...
}
Chart Naming
Charts sources must provide a name for each chart page that can be displayed using the getChartName()
method. These names are displayed to the user and are the primary means by which the user will identify pages and distinguish between different pages. As such, it is recommended to choose descriptive, user-friendly names.
The following example shows how to choose page names based on the name assigned to each chart by the chart provider, with optional page numbering for multi-page charts.
import { G3XChartsPageData, G3XChartsSource } from '@microsoft/msfs-wtg3x';
class MyChartsSource implements G3XChartsSource {
public getChartName(pageData: G3XChartsPageData): string {
if (pageData.pageCount <= 1) {
return pageData.metadata.name;
} else {
return `${pageData.metadata.name} (pg ${pageData.pageIndex + 1}/${pageData.pageCount})`;
}
}
// ...
}
Chart URL Selection
Each ChartPage
sourced from a chart provider potentially has multiple associated URLs. Each URL is used to fetch a particular version or format of that page. Charts sources are responsible for selecting the appropriate URLs to display each chart page.
The G3X Touch supports displaying charts in either Day mode or Night mode. Day mode charts should have a light color scheme and Night mode charts should have a dark color scheme. Each charts source must support Day mode and can optionally support Night mode. If a charts source supports Night mode, then it should set its supportsNightMode
property to true
.
The getDayModeUrl()
and getNightModeUrl()
methods are used to select the appropriate URL to use for Day and Night modes, respectively. If a charts source does not support night mode, then getNightModeUrl()
can return undefined
for every page.
In the following example, Day and Night mode URLs are chosen by searching for URLs with specific names used by a hypothetical custom chart provider.
import { ChartUrl } from '@microsoft/msfs-sdk';
import { G3XChartsPageData, G3XChartsSource } from '@microsoft/msfs-wtg3x';
class MyChartsSource implements G3XChartsSource {
public getDayModeUrl(pageData: G3XChartsPageData): ChartUrl | undefined {
return pageData.page.urls.find(url => url.name === 'light_png');
}
public getNightModeUrl(pageData: G3XChartsPageData): ChartUrl | undefined {
return pageData.page.urls.find(url => url.name === 'dark_png');
}
// ...
}
Geo-Referenced Charts
Charts sources use the getGeoReferencedArea()
method to return an appropriate GeoReferencedChartArea
for each chart page that is geo-referenced. If a page is not geo-referenced, then getGeoReferencedArea()
should return undefined
.
A moving airplane icon will be overlaid on the geo-referenced charts within the geo-referenced area at the airplane's current location.
You can customize the airplane icon that is displayed on geo-referenced charts by using the airplane-icon-src
attribute on the <Charts>
panel.xml
tag. If a custom airplane icon is not specified, then a generic icon will be used instead.
Adding a Custom Charts Source to the G3X Touch
To add a custom charts source, a plugin that returns a factory for the custom charts source from its getChartsSources()
method must be added to the G3X Touch instrument. If an airplane has multiple G3X Touch instruments (GDUs), then plugins that return factories for the custom source should be added to every instrument.
The following set of examples shows a single custom charts source being defined and added to the G3X Touch.
import { G3XChartsSource, G3XChartsSourceFactory } from '@microsoft/msfs-wtg3x';
class MyChartsSource implements G3XChartsSource {
public readonly uid = 'my-charts-id';
// ...
}
export class MyChartsSourceFactory implements G3XChartsSourceFactory {
public readonly uid = 'my-charts-id';
public createSource(): G3XChartsSource {
return new MyChartsSource();
}
}
import { registerPlugin } from '@microsoft/msfs-sdk'
import { AbstractG3XTouchPlugin, G3XChartsSourceFactory } from '@microsoft/msfs-wtg3x';
import { MyChartsSourceFactory } from './MyChartsSource';
class MyPlugin extends AbstractG3XTouchPlugin {
public getChartsSources(): Iterable<G3XChartsSourceFactory> | undefined {
return [new MyChartsSourceFactory()];
}
// ...
}
registerPlugin(MyPlugin);
Each source factory must declare the correct unique ID of the source that it creates. If the unique ID of the source created by a factory is found to be different from the one declared by the factory, then a runtime error will be thrown during instrument initialization.
Charts sources from factories returned by all plugins are added to the G3X Touch. If plugins return two or more factories with the same declared unique ID, then the factory that is returned last (ordered first by plugin load order, then by order in each plugin's returned factory iterable) will be used and the others will be discarded. Factories returned from plugins with the same ID as one of the built-in sources will always override and replace the built-in source.