From 73a597c9ffdf4b43545975c27f858cbb60cf587a Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 5 May 2023 21:04:40 -0400 Subject: [PATCH] Expose methods for reading features from GeoJSON and WKT. #194 --- CHANGELOG.md | 1 + README.md | 30 +++++++++++++++++++++++++++++ src/instance/instance.js | 2 ++ src/instance/methods/features.js | 33 ++++++++++++++++++++++++++++++++ src/instance/methods/layer.js | 15 ++++----------- 5 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 src/instance/methods/features.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a149e4..ffe11c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Save dist folder to an artifact in run-build.yml workflow. #193 +- Expose methods for reading features from GeoJSON and WKT. #194 ## [v2.1.0] - 2022-11-15 diff --git a/README.md b/README.md index fab93df..18785dd 100644 --- a/README.md +++ b/README.md @@ -320,6 +320,36 @@ const xyzOpts = { const xyzLayer = myMap.addLayer('xyz', xyzOpts); ``` +### Reading Features + +A `readFeatures` method is provided to enable reading geometry features from +various formats like GeoJSON and WKT. It takes a format as its first parameter, +and the input data as its second parameter. + +For example: + +```js +// Reading features from GeoJSON. +const geojson = { + type: "Feature", + geometry: { + type: "Polygon", + coordinates: [ + [[30, 10], [40, 40], [20, 40], [10, 20], [30, 10]] + ] + }, + properties: { + name: "Property Boundary" + } +}; +const features = myMap.readFeatures('geojson', geojson); +features[0].get('name') === 'Property Boundary' + +// Reading features from Well-Known Text (WKT). +const wkt = "POLYGON ((-75.53643733263014 42.54424760416683, -75.5360350012779 42.54427527000766, -75.53589016199109 42.54412508386721, -75.53588747978209 42.54302634269183, -75.53643733263014 42.54424760416683))"; +const features = myMap.readFeatures('wkt', wkt); +``` + ### Controlling the zoom level There are two methods for controlling the zoom level. The first, `zoomToVectors`, diff --git a/src/instance/instance.js b/src/instance/instance.js index 11c90b1..b09fbf1 100644 --- a/src/instance/instance.js +++ b/src/instance/instance.js @@ -7,6 +7,7 @@ import defaults from './defaults'; // Import instance methods. import addLayer, { getLayerByName } from './methods/layer'; +import readFeatures from './methods/features'; import addPopup from './methods/popup'; import { zoomToVectors, zoomToLayer } from './methods/zoom'; import { addBehavior, attachBehavior, attachBehaviorsByWeight } from './methods/behavior'; @@ -51,6 +52,7 @@ const createInstance = ({ target, options = {} }) => { addLayer, addPopup, getLayerByName, + readFeatures, zoomToVectors, zoomToLayer, addBehavior, diff --git a/src/instance/methods/features.js b/src/instance/methods/features.js new file mode 100644 index 0000000..54e9df6 --- /dev/null +++ b/src/instance/methods/features.js @@ -0,0 +1,33 @@ +// Import formats. +import GeoJSON from 'ol/format/GeoJSON'; +import WKT from 'ol/format/WKT'; + +// Import the default projection configuration +import projection from '../../projection'; + +// Read features from Well Known Text (WKT). +function readFeaturesWKT(wkt) { + const isMultipart = wkt.includes('MULTIPOINT') + || wkt.includes('MULTILINESTRING') + || wkt.includes('MULTIPOLYGON') + || wkt.includes('GEOMETRYCOLLECTION'); + return isMultipart + ? new WKT({ splitCollection: true }).readFeatures(wkt, projection) + : [new WKT().readFeature(wkt, projection)]; +} + +// Read features from GeoJSON. +function readFeaturesGeoJSON(geojson) { + return (new GeoJSON()).readFeatures(geojson, projection); +} + +// Read features from various formats. +export default function readFeatures(type, input) { + if (type.toLowerCase() === 'geojson') { + return readFeaturesGeoJSON(input); + } + if (type.toLowerCase() === 'wkt') { + return readFeaturesWKT(input); + } + return undefined; +} diff --git a/src/instance/methods/layer.js b/src/instance/methods/layer.js index 0cc9bfb..f13c057 100644 --- a/src/instance/methods/layer.js +++ b/src/instance/methods/layer.js @@ -8,7 +8,6 @@ import LayerGroup from 'ol/layer/Group'; import VectorLayer from 'ol/layer/Vector'; import TileLayer from 'ol/layer/Tile'; import GeoJSON from 'ol/format/GeoJSON'; -import WKT from 'ol/format/WKT'; // Import setWithCredentials function. import { setWithCredentials } from 'ol/featureloader'; @@ -17,8 +16,8 @@ import { setWithCredentials } from 'ol/featureloader'; import * as Style from 'ol/style'; import colorStyles, { clusterStyle } from '../../styles'; -// Import the default projection configuration -import projection from '../../projection'; +// Import readFeatures function. +import readFeatures from './features'; // Set withCredentials to true for all XHR requests made via OpenLayers' // feature loader. Typically farmOS requires authentication in order to @@ -90,7 +89,7 @@ function addGeoJSONLayer({ }); } else { source = new VectorSource({ - features: (new GeoJSON()).readFeatures(geojson, projection), + features: readFeatures('geojson', geojson), format, attributions, }); @@ -130,13 +129,7 @@ function addWKTLayer({ const style = styleFunction ? (feature, resolution) => styleFunction(feature, resolution, Style) : colorStyles(color); - const isMultipart = wkt.includes('MULTIPOINT') - || wkt.includes('MULTILINESTRING') - || wkt.includes('MULTIPOLYGON') - || wkt.includes('GEOMETRYCOLLECTION'); - const features = isMultipart - ? new WKT({ splitCollection: true }).readFeatures(wkt, projection) - : [new WKT().readFeature(wkt, projection)]; + const features = readFeatures('wkt', wkt); const attributions = [attribution]; const source = new VectorSource({ features,