Read and write spatial data

The following table lists the spatial file formats that are supported for reading and writing operations with the Spatial IO module.

Data Format Read Write
GeoJSON
GeoRSS
GML
GPX
KML
KMZ
Spatial CSV
Well-Known Text

These next sections outline all the different tools for reading and writing spatial data using the Spatial IO module.

Read spatial data

The atlas.io.read function is the main function used to read common spatial data formats such as KML, GPX, GeoRSS, GeoJSON, and CSV files with spatial data. This function can also read compressed versions of these formats, as a zip file or a KMZ file. The KMZ file format is a compressed version of KML that can also include assets such as images. Alternatively, the read function can take in a URL that points to a file in any of these formats. URLs should be hosted on a CORS enabled endpoint, or a proxy service should be provided in the read options. The proxy service is used to load resources on domains that aren't CORS enabled. The read function returns a promise to add the image icons to the map, and processes data asynchronously to minimize impact to the UI thread.

When reading a compressed file, either as a zip or a KMZ, once unzipped it looks for the first valid file. For example, doc.kml, or a file with other valid extension, such as: .kml, .xml, geojson, .json, .csv, .tsv, or .txt. Then, images referenced in KML and GeoRSS files are preloaded to ensure they're accessible. Inaccessible image data can load an alternative fallback image or removed from the styles. Images extracted from KMZ files are converted to data URIs.

The result from the read function is a SpatialDataSet object. This object extends the GeoJSON FeatureCollection class. It can easily be passed into a DataSource as-is to render its features on a map. The SpatialDataSet not only contains feature information, but it can also include KML ground overlays, processing metrics, and other details as outlined in the following table.

Property name Type Description
bbox BoundingBox Bounding box of all the data in the data set.
features Feature[] GeoJSON features within the data set.
groundOverlays (atlas.layer.ImageLayer | atlas.layers.OgcMapLayer)[] An array of KML GroundOverlays.
icons Record<string, string> A set of icon URLs. Key = icon name, Value = URL.
properties any Property information provided at the document level of a spatial data set.
stats SpatialDataSetStats Statistics about the content and processing time of a spatial data set.
type 'FeatureCollection' Read-only GeoJSON type value.

Examples of reading spatial data

The Load spatial data sample shows how to read a spatial data set, and renders it on the map using the SimpleDataLayer class. The code uses a GPX file pointed to by a URL. For the source code of this sample, see Load spatial data source code.

A screenshot that shows the snap grid on map. A screenshot that shows a detailed description of the snap grid on map sample.

The next code demo shows how to read and load KML, or KMZ, to the map. KML can contain ground overlays, which is in the form of an ImageLayer or OgcMapLayer. These overlays must be added on the map separately from the features. Additionally, if the data set has custom icons, those icons need to be loaded to the maps resources before the features are loaded.

The Load KML onto map sample shows how to load KML or KMZ files onto the map. For the source code of this sample, see Load KML onto map source code.

A screenshot that shows a map with a KML ground overlay.

You can optionally provide a proxy service for accessing cross domain assets that don't have CORS enabled. The read function tries to access files on another domain using CORS first. The first time it fails to access any resource on another domain using CORS it only requests more files if a proxy service is provided. The read function appends the file URL to the end of the proxy URL provided. This snippet of code shows how to pass a proxy service into the read function:

//Read a file from a URL or pass in a raw data as a string.
atlas.io.read('https://nonCorsDomain.example.com/mySuperCoolData.xml', {
    //Provide a proxy service
    proxyService: window.location.origin + '/YourCorsEnabledProxyService.ashx?url='
}).then(async r => {
    if (r) {
        // Some code goes here . . .
    }
});

The following code snippet shows how to read a delimited file and render it on the map. In this case, the code uses a CSV file that has spatial data columns. You must add a reference to the Azure Maps Spatial IO module.

<!-- Add reference to the Azure Maps Spatial IO module. -->
<script src="https://atlas.microsoft.com/sdk/javascript/spatial/0/atlas-spatial.min.js"></script>

<script>
    var datasource, delimitedFileUrl = "Chicago_Police_Stations.csv";
    // Download CSV file (delimitedFileUrl) from:
    // https://github.com/Azure-Samples/AzureMapsCodeSamples/blob/main/Static/data/SpatialCSV/Chicago_Police_Stations.csv

    function GetMap() {

        //Instantiate a map object
        var map = new atlas.Map("myMap", {
            center: [-87.628899, 41.874693],
            zoom: 9,
            view: "Auto",
            // Replace <Your Azure Maps Subscription Key> with your Azure Maps subscription key. https://aka.ms/am-primaryKey
            authOptions: {
                authType: 'subscriptionKey',
                subscriptionKey: '{Your-Azure-Maps-Subscription-key}'
            }
        });
    
    //Wait until the map resources are ready.
      map.events.add('ready', function () {
        
        //Create a data source and add it to the map.
        datasource = new atlas.source.DataSource();
        map.sources.add(datasource);
        
        //Add a simple data layer for rendering the data.
        layer = new atlas.layer.SimpleDataLayer(datasource);
        map.layers.add(layer);
        
        //Read a CSV file from a URL or pass in a raw string.
        atlas.io.read(delimitedFileUrl).then(r => {
            if (r) {
                
                //Add the feature data to the data source.
                datasource.add(r);
                
                //If bounding box information is known for data, set the map view to it.
                if (r.bbox) {
                    map.setCamera({
                        bounds: r.bbox,
                        padding: 50
                    });
                }
            }
          });
        });
      }
</script>

A screenshot that shows a map created from a CSV file.

Write spatial data

There are two main write functions in the spatial IO module. The atlas.io.write function generates a string, while the atlas.io.writeCompressed function generates a compressed zip file. The compressed zip file would contain a text-based file with the spatial data in it. Both of these functions return a promise to add the data to the file. And, they both can write any of the following data: SpatialDataSet, DataSource, ImageLayer, OgcMapLayer, feature collection, feature, geometry, or an array of any combination of these data types. When writing using either functions, you can specify the wanted file format. If the file format isn't specified, then the data is written as KML.

The Spatial data write options sample is a tool that demonstrates most the write options that can be used with the atlas.io.write function. For the source code of this sample, see Spatial data write options source code.

A screenshot that shows The Spatial data write options sample that demonstrates most of the write options used with the atlas.io.write function.

Example of writing spatial data

The Drag and drop spatial files onto map sample allows you to drag and drop one or more KML, KMZ, GeoRSS, GPX, GML, GeoJSON or CSV files onto the map. For the source code of this sample, see Drag and drop spatial files onto map source code.

A screenshot that shows a map with a panel to the left of the map that enables you to drag and drop one or more KML, KMZ, GeoRSS, GPX, GML, GeoJSON or CSV files onto the map.

You can optionally provide a proxy service for accessing cross domain assets that don't have CORS enabled. This snippet of code shows you could incorporate a proxy service:

atlas.io.read(data, {
    //Provide a proxy service
    proxyService: window.location.origin + '/YourCorsEnabledProxyService.ashx?url='
}).then(
    //Success
    function(r) {
        //some code goes here ...
    }
);

Read and write Well-Known Text (WKT)

Well-Known Text (WKT) is an Open Geospatial Consortium (OGC) standard for representing spatial geometries as text. Many geospatial systems support WKT, such as Azure SQL and Azure PostgreSQL using the PostGIS plugin. Like most OGC standards, coordinates are formatted as "longitude latitude" to align with the "x y" convention. As an example, a point at longitude -110 and latitude 45 can be written as POINT(-110 45) using the WKT format.

Well-known text can be read using the atlas.io.ogc.WKT.read function, and written using the atlas.io.ogc.WKT.write function.

Examples of reading and writing Well-Known Text (WKT)

The Read Well Known Text sample shows how to read the well-known text string POINT(-122.34009 47.60995) and render it on the map using a bubble layer. For the source code of this sample, see Read Well Known Text source code.

A screenshot that shows how to read Well Known Text (WKT) as GeoJSON and render it on a map using a bubble layer.

The Read and write Well Known Text sample demonstrates how to read and write Well Known Text (WKT) strings as GeoJSON. For the source code of this sample, see Read and write Well Known Text source code.

A screenshot showing the sample that demonstrates how to read and write Well Known Text (WKT) strings as GeoJSON.

Read and write GML

GML is a spatial XML file specification often used as an extension to other XML specifications. GeoJSON data can be written as XML with GML tags using the atlas.io.core.GmlWriter.write function. The XML that contains GML can be read using the atlas.io.core.GmlReader.read function. The read function has two options:

  • The isAxisOrderLonLat option - The axis order of coordinates "latitude, longitude" or "longitude, latitude" can vary between data sets, and it isn't always well defined. By default the GML reader reads the coordinate data as "latitude, longitude", but setting this option to true reads it as "longitude, latitude".
  • The propertyTypes option - This option is a key value lookup table where the key is the name of a property in the data set. The value is the object type to cast the value to when parsing. The supported type values are: string, number, boolean, and date. If a property isn't in the lookup table or the type isn't defined, the property is parsed as a string.

The atlas.io.read function defaults to the atlas.io.core.GmlReader.read function when it detects that the input data is XML, but the data isn't one of the other support spatial XML formats.

The GmlReader parses coordinates that have one of the following SRIDs:

  • EPSG:4326 (Preferred)
  • EPSG:4269, EPSG:4283, EPSG:4258, EPSG:4308, EPSG:4230, EPSG:4272, EPSG:4271, EPSG:4267, EPSG:4608, EPSG:4674 possibly with a small margin of error.
  • EPSG:3857, EPSG:102100, EPSG:3785, EPSG:900913, EPSG:102113, EPSG:41001, EPSG:54004

More resources

Learn more about the classes and methods used in this article:

atlas.io static functions

SpatialDataSet

SpatialDataSetStats

GmlReader

GmlWriter

atlas.io.ogc.WKT functions

Connect to a WFS service

Leverage core operations

Supported data format details

Next steps

See the following articles for more code samples to add to your maps:

Add an OGC map layer