Merge pull request #8615 from tschaub/geojson-types

Use GeoJSON types from @types/geojson
This commit is contained in:
Tim Schaub
2018-09-11 09:57:31 -06:00
committed by GitHub
2 changed files with 159 additions and 106 deletions
+1
View File
@@ -40,6 +40,7 @@
}, },
"devDependencies": { "devDependencies": {
"@openlayers/eslint-plugin": "^4.0.0-beta.1", "@openlayers/eslint-plugin": "^4.0.0-beta.1",
"@types/geojson": "^7946.0.4",
"buble": "^0.19.3", "buble": "^0.19.3",
"buble-loader": "^0.5.1", "buble-loader": "^0.5.1",
"chaikin-smooth": "^1.0.4", "chaikin-smooth": "^1.0.4",
+158 -106
View File
@@ -1,8 +1,6 @@
/** /**
* @module ol/format/GeoJSON * @module ol/format/GeoJSON
*/ */
// TODO: serialize dataProjection as crs member when writing
// see https://github.com/openlayers/openlayers/issues/2078
import {assert} from '../asserts.js'; import {assert} from '../asserts.js';
import Feature from '../Feature.js'; import Feature from '../Feature.js';
@@ -17,6 +15,21 @@ import Point from '../geom/Point.js';
import Polygon from '../geom/Polygon.js'; import Polygon from '../geom/Polygon.js';
import {assign, isEmpty} from '../obj.js'; import {assign, isEmpty} from '../obj.js';
import {get as getProjection} from '../proj.js'; import {get as getProjection} from '../proj.js';
import GeometryType from '../geom/GeometryType.js';
/**
* @typedef {import("geojson").GeoJSON} GeoJSONObject
* @typedef {import("geojson").Feature} GeoJSONFeature
* @typedef {import("geojson").FeatureCollection} GeoJSONFeatureCollection
* @typedef {import("geojson").Geometry} GeoJSONGeometry
* @typedef {import("geojson").Point} GeoJSONPoint
* @typedef {import("geojson").LineString} GeoJSONLineString
* @typedef {import("geojson").Polygon} GeoJSONPolygon
* @typedef {import("geojson").MultiPoint} GeoJSONMultiPoint
* @typedef {import("geojson").MultiLineString} GeoJSONMultiLineString
* @typedef {import("geojson").MultiPolygon} GeoJSONMultiPolygon
* @typedef {import("geojson").GeometryCollection} GeoJSONGeometryCollection
*/
/** /**
@@ -84,28 +97,31 @@ class GeoJSON extends JSONFeature {
* @type {GeoJSONFeature} * @type {GeoJSONFeature}
*/ */
let geoJSONFeature = null; let geoJSONFeature = null;
if (object.type === 'Feature') { if (object['type'] === 'Feature') {
geoJSONFeature = /** @type {GeoJSONFeature} */ (object); geoJSONFeature = /** @type {GeoJSONFeature} */ (object);
} else { } else {
geoJSONFeature = /** @type {GeoJSONFeature} */ ({ geoJSONFeature = {
type: 'Feature', 'type': 'Feature',
geometry: /** @type {GeoJSONGeometry|GeoJSONGeometryCollection} */ (object) 'geometry': /** @type {GeoJSONGeometry} */ (object),
}); 'properties': null
};
} }
const geometry = readGeometry(geoJSONFeature.geometry, opt_options); const geometry = readGeometry(geoJSONFeature['geometry'], opt_options);
const feature = new Feature(); const feature = new Feature();
if (this.geometryName_) { if (this.geometryName_) {
feature.setGeometryName(this.geometryName_); feature.setGeometryName(this.geometryName_);
} else if (this.extractGeometryName_ && geoJSONFeature.geometry_name !== undefined) { } else if (this.extractGeometryName_ && 'geometry_name' in geoJSONFeature !== undefined) {
feature.setGeometryName(geoJSONFeature.geometry_name); feature.setGeometryName(geoJSONFeature['geometry_name']);
} }
feature.setGeometry(geometry); feature.setGeometry(geometry);
if (geoJSONFeature.id !== undefined) {
feature.setId(geoJSONFeature.id); if ('id' in geoJSONFeature) {
feature.setId(geoJSONFeature['id']);
} }
if (geoJSONFeature.properties) {
feature.setProperties(geoJSONFeature.properties); if (geoJSONFeature['properties']) {
feature.setProperties(geoJSONFeature['properties']);
} }
return feature; return feature;
} }
@@ -117,10 +133,10 @@ class GeoJSON extends JSONFeature {
const geoJSONObject = /** @type {GeoJSONObject} */ (object); const geoJSONObject = /** @type {GeoJSONObject} */ (object);
/** @type {Array<import("../Feature.js").default>} */ /** @type {Array<import("../Feature.js").default>} */
let features = null; let features = null;
if (geoJSONObject.type === 'FeatureCollection') { if (geoJSONObject['type'] === 'FeatureCollection') {
const geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */ (object); const geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */ (object);
features = []; features = [];
const geoJSONFeatures = geoJSONFeatureCollection.features; const geoJSONFeatures = geoJSONFeatureCollection['features'];
for (let i = 0, ii = geoJSONFeatures.length; i < ii; ++i) { for (let i = 0, ii = geoJSONFeatures.length; i < ii; ++i) {
features.push(this.readFeatureFromObject(geoJSONFeatures[i], opt_options)); features.push(this.readFeatureFromObject(geoJSONFeatures[i], opt_options));
} }
@@ -141,12 +157,11 @@ class GeoJSON extends JSONFeature {
* @inheritDoc * @inheritDoc
*/ */
readProjectionFromObject(object) { readProjectionFromObject(object) {
const geoJSONObject = /** @type {GeoJSONObject} */ (object); const crs = object['crs'];
const crs = geoJSONObject.crs;
let projection; let projection;
if (crs) { if (crs) {
if (crs.type == 'name') { if (crs['type'] == 'name') {
projection = getProjection(crs.properties.name); projection = getProjection(crs['properties']['name']);
} else { } else {
assert(false, 36); // Unknown SRS type assert(false, 36); // Unknown SRS type
} }
@@ -170,25 +185,27 @@ class GeoJSON extends JSONFeature {
writeFeatureObject(feature, opt_options) { writeFeatureObject(feature, opt_options) {
opt_options = this.adaptOptions(opt_options); opt_options = this.adaptOptions(opt_options);
const object = /** @type {GeoJSONFeature} */ ({ /** @type {GeoJSONFeature} */
'type': 'Feature' const object = {
}); 'type': 'Feature',
geometry: null,
properties: null
};
const id = feature.getId(); const id = feature.getId();
if (id !== undefined) { if (id !== undefined) {
object.id = id; object.id = id;
} }
const geometry = feature.getGeometry(); const geometry = feature.getGeometry();
if (geometry) { if (geometry) {
object.geometry = writeGeometry(geometry, opt_options); object.geometry = writeGeometry(geometry, opt_options);
} else {
object.geometry = null;
} }
const properties = feature.getProperties(); const properties = feature.getProperties();
delete properties[feature.getGeometryName()]; delete properties[feature.getGeometryName()];
if (!isEmpty(properties)) { if (!isEmpty(properties)) {
object.properties = properties; object.properties = properties;
} else {
object.properties = null;
} }
return object; return object;
} }
@@ -208,10 +225,10 @@ class GeoJSON extends JSONFeature {
for (let i = 0, ii = features.length; i < ii; ++i) { for (let i = 0, ii = features.length; i < ii; ++i) {
objects.push(this.writeFeatureObject(features[i], opt_options)); objects.push(this.writeFeatureObject(features[i], opt_options));
} }
return /** @type {GeoJSONFeatureCollection} */ ({ return {
type: 'FeatureCollection', type: 'FeatureCollection',
features: objects features: objects
}); };
} }
/** /**
@@ -229,37 +246,6 @@ class GeoJSON extends JSONFeature {
} }
/**
* @const
* @type {Object<string, function(GeoJSONObject): import("../geom/Geometry.js").default>}
*/
const GEOMETRY_READERS = {
'Point': readPointGeometry,
'LineString': readLineStringGeometry,
'Polygon': readPolygonGeometry,
'MultiPoint': readMultiPointGeometry,
'MultiLineString': readMultiLineStringGeometry,
'MultiPolygon': readMultiPolygonGeometry,
'GeometryCollection': readGeometryCollectionGeometry
};
/**
* @const
* @type {Object<string, function(import("../geom/Geometry.js").default, import("./Feature.js").WriteOptions=): (GeoJSONGeometry|GeoJSONGeometryCollection)>}
*/
const GEOMETRY_WRITERS = {
'Point': writePointGeometry,
'LineString': writeLineStringGeometry,
'Polygon': writePolygonGeometry,
'MultiPoint': writeMultiPointGeometry,
'MultiLineString': writeMultiLineStringGeometry,
'MultiPolygon': writeMultiPolygonGeometry,
'GeometryCollection': writeGeometryCollectionGeometry,
'Circle': writeEmptyGeometryCollectionGeometry
};
/** /**
* @param {GeoJSONGeometry|GeoJSONGeometryCollection} object Object. * @param {GeoJSONGeometry|GeoJSONGeometryCollection} object Object.
* @param {import("./Feature.js").ReadOptions=} opt_options Read options. * @param {import("./Feature.js").ReadOptions=} opt_options Read options.
@@ -269,10 +255,45 @@ function readGeometry(object, opt_options) {
if (!object) { if (!object) {
return null; return null;
} }
const geometryReader = GEOMETRY_READERS[object.type];
return ( /**
/** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometryReader(object), false, opt_options)) * @type {import("../geom/Geometry.js").default}
); */
let geometry;
switch (object['type']) {
case GeometryType.POINT: {
geometry = readPointGeometry(/** @type {GeoJSONPoint} */ (object));
break;
}
case GeometryType.LINE_STRING: {
geometry = readLineStringGeometry(/** @type {GeoJSONLineString} */ (object));
break;
}
case GeometryType.POLYGON: {
geometry = readPolygonGeometry(/** @type {GeoJSONPolygon} */ (object));
break;
}
case GeometryType.MULTI_POINT: {
geometry = readMultiPointGeometry(/** @type {GeoJSONMultiPoint} */ (object));
break;
}
case GeometryType.MULTI_LINE_STRING: {
geometry = readMultiLineStringGeometry(/** @type {GeoJSONMultiLineString} */ (object));
break;
}
case GeometryType.MULTI_POLYGON: {
geometry = readMultiPolygonGeometry(/** @type {GeoJSONMultiPolygon} */ (object));
break;
}
case GeometryType.GEOMETRY_COLLECTION: {
geometry = readGeometryCollectionGeometry(/** @type {GeoJSONGeometryCollection} */ (object));
break;
}
default: {
throw new Error('Unsupported GeoJSON type: ' + object.type);
}
}
return transformWithOptions(geometry, false, opt_options);
} }
@@ -282,7 +303,7 @@ function readGeometry(object, opt_options) {
* @return {import("../geom/GeometryCollection.js").default} Geometry collection. * @return {import("../geom/GeometryCollection.js").default} Geometry collection.
*/ */
function readGeometryCollectionGeometry(object, opt_options) { function readGeometryCollectionGeometry(object, opt_options) {
const geometries = object.geometries.map( const geometries = object['geometries'].map(
/** /**
* @param {GeoJSONGeometry} geometry Geometry. * @param {GeoJSONGeometry} geometry Geometry.
* @return {import("../geom/Geometry.js").default} geometry Geometry. * @return {import("../geom/Geometry.js").default} geometry Geometry.
@@ -295,80 +316,111 @@ function readGeometryCollectionGeometry(object, opt_options) {
/** /**
* @param {GeoJSONGeometry} object Object. * @param {GeoJSONPoint} object Object.
* @return {import("../geom/Point.js").default} Point. * @return {import("../geom/Point.js").default} Point.
*/ */
function readPointGeometry(object) { function readPointGeometry(object) {
return new Point(object.coordinates); return new Point(object['coordinates']);
} }
/** /**
* @param {GeoJSONGeometry} object Object. * @param {GeoJSONLineString} object Object.
* @return {import("../geom/LineString.js").default} LineString. * @return {import("../geom/LineString.js").default} LineString.
*/ */
function readLineStringGeometry(object) { function readLineStringGeometry(object) {
return new LineString(object.coordinates); return new LineString(object['coordinates']);
} }
/** /**
* @param {GeoJSONGeometry} object Object. * @param {GeoJSONMultiLineString} object Object.
* @return {import("../geom/MultiLineString.js").default} MultiLineString. * @return {import("../geom/MultiLineString.js").default} MultiLineString.
*/ */
function readMultiLineStringGeometry(object) { function readMultiLineStringGeometry(object) {
return new MultiLineString(object.coordinates); return new MultiLineString(object['coordinates']);
} }
/** /**
* @param {GeoJSONGeometry} object Object. * @param {GeoJSONMultiPoint} object Object.
* @return {import("../geom/MultiPoint.js").default} MultiPoint. * @return {import("../geom/MultiPoint.js").default} MultiPoint.
*/ */
function readMultiPointGeometry(object) { function readMultiPointGeometry(object) {
return new MultiPoint(object.coordinates); return new MultiPoint(object['coordinates']);
} }
/** /**
* @param {GeoJSONGeometry} object Object. * @param {GeoJSONMultiPolygon} object Object.
* @return {import("../geom/MultiPolygon.js").default} MultiPolygon. * @return {import("../geom/MultiPolygon.js").default} MultiPolygon.
*/ */
function readMultiPolygonGeometry(object) { function readMultiPolygonGeometry(object) {
return new MultiPolygon(object.coordinates); return new MultiPolygon(object['coordinates']);
} }
/** /**
* @param {GeoJSONGeometry} object Object. * @param {GeoJSONPolygon} object Object.
* @return {import("../geom/Polygon.js").default} Polygon. * @return {import("../geom/Polygon.js").default} Polygon.
*/ */
function readPolygonGeometry(object) { function readPolygonGeometry(object) {
return new Polygon(object.coordinates); return new Polygon(object['coordinates']);
} }
/** /**
* @param {import("../geom/Geometry.js").default} geometry Geometry. * @param {import("../geom/Geometry.js").default} geometry Geometry.
* @param {import("./Feature.js").WriteOptions=} opt_options Write options. * @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry|GeoJSONGeometryCollection} GeoJSON geometry. * @return {GeoJSONGeometry} GeoJSON geometry.
*/ */
function writeGeometry(geometry, opt_options) { function writeGeometry(geometry, opt_options) {
const geometryWriter = GEOMETRY_WRITERS[geometry.getType()]; geometry = transformWithOptions(geometry, true, opt_options);
return geometryWriter(/** @type {import("../geom/Geometry.js").default} */ ( const type = geometry.getType();
transformWithOptions(geometry, true, opt_options)), opt_options);
}
/** @type {GeoJSONGeometry} */
/** let geoJSON;
* @param {import("../geom/Geometry.js").default} geometry Geometry. switch (type) {
* @return {GeoJSONGeometryCollection} Empty GeoJSON geometry collection. case GeometryType.POINT: {
*/ geoJSON = writePointGeometry(/** @type {import("../geom/Point.js").default} */ (geometry), opt_options);
function writeEmptyGeometryCollectionGeometry(geometry) { break;
return /** @type {GeoJSONGeometryCollection} */ ({ }
type: 'GeometryCollection', case GeometryType.LINE_STRING: {
geometries: [] geoJSON = writeLineStringGeometry(/** @type {import("../geom/LineString.js").default} */ (geometry), opt_options);
}); break;
}
case GeometryType.POLYGON: {
geoJSON = writePolygonGeometry(/** @type {import("../geom/Polygon.js").default} */ (geometry), opt_options);
break;
}
case GeometryType.MULTI_POINT: {
geoJSON = writeMultiPointGeometry(/** @type {import("../geom/MultiPoint.js").default} */ (geometry), opt_options);
break;
}
case GeometryType.MULTI_LINE_STRING: {
geoJSON = writeMultiLineStringGeometry(/** @type {import("../geom/MultiLineString.js").default} */ (geometry), opt_options);
break;
}
case GeometryType.MULTI_POLYGON: {
geoJSON = writeMultiPolygonGeometry(/** @type {import("../geom/MultiPolygon.js").default} */ (geometry), opt_options);
break;
}
case GeometryType.GEOMETRY_COLLECTION: {
geoJSON = writeGeometryCollectionGeometry(/** @type {import("../geom/GeometryCollection.js").default} */ (geometry), opt_options);
break;
}
case GeometryType.CIRCLE: {
geoJSON = {
type: 'GeometryCollection',
geometries: []
};
break;
}
default: {
throw new Error('Unsupported geometry type: ' + type);
}
}
return geoJSON;
} }
@@ -383,10 +435,10 @@ function writeGeometryCollectionGeometry(geometry, opt_options) {
delete options.featureProjection; delete options.featureProjection;
return writeGeometry(geometry, options); return writeGeometry(geometry, options);
}); });
return /** @type {GeoJSONGeometryCollection} */ ({ return {
type: 'GeometryCollection', type: 'GeometryCollection',
geometries: geometries geometries: geometries
}); };
} }
@@ -396,10 +448,10 @@ function writeGeometryCollectionGeometry(geometry, opt_options) {
* @return {GeoJSONGeometry} GeoJSON geometry. * @return {GeoJSONGeometry} GeoJSON geometry.
*/ */
function writeLineStringGeometry(geometry, opt_options) { function writeLineStringGeometry(geometry, opt_options) {
return /** @type {GeoJSONGeometry} */ ({ return {
type: 'LineString', type: 'LineString',
coordinates: geometry.getCoordinates() coordinates: geometry.getCoordinates()
}); };
} }
@@ -409,10 +461,10 @@ function writeLineStringGeometry(geometry, opt_options) {
* @return {GeoJSONGeometry} GeoJSON geometry. * @return {GeoJSONGeometry} GeoJSON geometry.
*/ */
function writeMultiLineStringGeometry(geometry, opt_options) { function writeMultiLineStringGeometry(geometry, opt_options) {
return /** @type {GeoJSONGeometry} */ ({ return {
type: 'MultiLineString', type: 'MultiLineString',
coordinates: geometry.getCoordinates() coordinates: geometry.getCoordinates()
}); };
} }
@@ -422,10 +474,10 @@ function writeMultiLineStringGeometry(geometry, opt_options) {
* @return {GeoJSONGeometry} GeoJSON geometry. * @return {GeoJSONGeometry} GeoJSON geometry.
*/ */
function writeMultiPointGeometry(geometry, opt_options) { function writeMultiPointGeometry(geometry, opt_options) {
return /** @type {GeoJSONGeometry} */ ({ return {
type: 'MultiPoint', type: 'MultiPoint',
coordinates: geometry.getCoordinates() coordinates: geometry.getCoordinates()
}); };
} }
@@ -439,10 +491,10 @@ function writeMultiPolygonGeometry(geometry, opt_options) {
if (opt_options) { if (opt_options) {
right = opt_options.rightHanded; right = opt_options.rightHanded;
} }
return /** @type {GeoJSONGeometry} */ ({ return {
type: 'MultiPolygon', type: 'MultiPolygon',
coordinates: geometry.getCoordinates(right) coordinates: geometry.getCoordinates(right)
}); };
} }
@@ -452,10 +504,10 @@ function writeMultiPolygonGeometry(geometry, opt_options) {
* @return {GeoJSONGeometry} GeoJSON geometry. * @return {GeoJSONGeometry} GeoJSON geometry.
*/ */
function writePointGeometry(geometry, opt_options) { function writePointGeometry(geometry, opt_options) {
return /** @type {GeoJSONGeometry} */ ({ return {
type: 'Point', type: 'Point',
coordinates: geometry.getCoordinates() coordinates: geometry.getCoordinates()
}); };
} }
@@ -469,10 +521,10 @@ function writePolygonGeometry(geometry, opt_options) {
if (opt_options) { if (opt_options) {
right = opt_options.rightHanded; right = opt_options.rightHanded;
} }
return /** @type {GeoJSONGeometry} */ ({ return {
type: 'Polygon', type: 'Polygon',
coordinates: geometry.getCoordinates(right) coordinates: geometry.getCoordinates(right)
}); };
} }