Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can't access 'coordinates' member of geojson feature collection

I have a GeoJSON feature collection in my Angular app that is an array of features, each containing a geometry object and properties object. Structure looks like this:

import { FeatureCollection, Feature } from 'geojson';

staticBreadcrumbs: GeoJSON.FeatureCollection<GeoJSON.Geometry>;

this.staticBreadcrumbs = {
    type : 'FeatureCollection',
    features: [
    {
        type: 'Feature',
        properties: {
            property1:  'property1',
            property2:  'property2'
        },
        geometry: {
            type: 'Point',
            coordinates: [-117.14024305343628, 32.81294345855713]
        }
    },
    {
        type: 'Feature',
        properties: {
        ...

I'm trying to create a mapboxgl marker for each feature in the collection and need to get the coordinates from each GeoJSON object, the compiler is telling me that the coordinates aren't part of the feature. The specific error is: Property 'coordinates' does not exist on type 'Geometry'. Property 'coordinates' does not exist on type 'GeometryCollection'.

console.log('this.staticBreadcrumbs.features[0]', this.staticBreadcrumbs.features[0]);

var marker = new Marker(el)
    .setLngLat([
        this.staticBreadcrumbs.features[0].geometry.coordinates[0],
        this.staticBreadcrumbs.features[0].geometry.coordinates[1]
    ])
    .addTo(this.map);

My console.log displays

 this.staticBreadcrumbs.features[0]
 {type: "Feature", properties: {…}, geometry: {…}}
 1.  geometry:
     1.  coordinates: Array(2)
         1.  0: -117.14024305343628
         2.  1: 32.81294345855713
         3.  length: 2
         4.  __proto__: Array(0)
     2.  type: "Point"
   2. __proto__: Object
2. properties: {deviceID: "CAP498", altitude: 401.6721913312, autonomous: 0, azimuth: 0, batteryStatusLabel: "Nominal", …}
3. type: "Feature"
4. __proto__: Object

The coordinates are exactly where I expect them to be, but I can't get to them. I have tried all sort of different ways to declare the Feature collection, but I can't find the right combination.

What do I need to do in order to access the coordinates?

Thanks.....

like image 738
cpeddie Avatar asked Apr 10 '19 21:04

cpeddie


People also ask

How do I access GeoJSON properties?

GeoJSON object properties are in OL accessible through . get(propertyName) method. For example, if your GeoJSON has property named otherParameter , you can access it in OL with geojsonLayer. get('otherParameter') .

What is Feature in GeoJSON?

GeoJSON supports the following feature types: Point (including addresses and locations) Line string (including streets, highways, and boundaries) Polygon (including countries, provinces, and tracts of land) Multipart collections of point, line string, or polygon features.

Can a GeoJSON FeatureCollection have properties?

The specification does not forbid it explicitly, but feature collections do not have properties. GeoJSON spec only mentions the following keys for FeatureCollection: type - must be `FeatureCollection. features - array of feaures.

What is CRS GeoJSON?

The coordinate reference system (CRS) of a GeoJSON object is determined by its. "crs" member (referred to as the CRS object below). If an object has no crs.


1 Answers

What do I need to do in order to access the coordinates?

Short Answer

Check that geometry is a Point before trying to access its coordinates property.

if (staticBreadcrumbs.features[0].geometry.type === 'Point') {

    var marker = new Marker(el)
        .setLngLat([
            this.staticBreadcrumbs.features[0].geometry.coordinates[0],
            this.staticBreadcrumbs.features[0].geometry.coordinates[1]
        ])
        .addTo(this.map);

}

Explanation

The problem you're experiencing happens because Geometry is a union type.

A union type describes a value that can be one of several types. We use the vertical bar (|) to separate each type...

This is the Geometry union type definition:

export type Geometry = 
    Point |
    MultiPoint | 
    LineString | 
    MultiLineString | 
    Polygon | 
    MultiPolygon | 
    GeometryCollection;

As you can see, the Geometry type is a union of seven types. Unfortunately, not all of those types include the coordinates property.

If we have a value that has a union type, we can only access members that are common to all types in the union.

That is why we are only able to access the coordinates property after we have narrowed the type.

Some Other Options

If you're using only Point types in your FeatureCollection, then use the Point type as the generic parameter:

let staticBreadcrumbs: FeatureCollection<Point>;

If you're using a variety of types in your FeatureCollection, then use a cast to tell the type checker that you're sure you have a Point:

(staticBreadcrumbs.features[0].geometry as Point).coordinates[0]

As shown in the Short Answer, instead of using a cast, you can use a conditional statement to narrow the type:

const geometry = staticBreadcrumbs.features[0].geometry;

if (geometry.type === 'Point') {
    const coordinates00 = geometry.coordinates[0];
    const coordinates01 = geometry.coordinates[1];
}

There is a short demo of that last example here.

like image 94
Shaun Luttin Avatar answered Sep 27 '22 02:09

Shaun Luttin