diff --git a/web/client/plugins/SidebarMenu.jsx b/web/client/plugins/SidebarMenu.jsx index d9f8ccee36..538b93b823 100644 --- a/web/client/plugins/SidebarMenu.jsx +++ b/web/client/plugins/SidebarMenu.jsx @@ -194,7 +194,7 @@ class SidebarMenu extends React.Component { }; renderExtraItems = (items) => { - const dummySelector = () => {}; + const dummySelector = () => ({}); const menuItems = items.map((item) => { if (item.tool) { const CustomMenuItem = item.tool; diff --git a/web/client/utils/ogc/WKT/__tests__/index-test.js b/web/client/utils/ogc/WKT/__tests__/index-test.js new file mode 100644 index 0000000000..1577dcf7b0 --- /dev/null +++ b/web/client/utils/ogc/WKT/__tests__/index-test.js @@ -0,0 +1,126 @@ +/* + * Copyright 2023, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +import expect from 'expect'; +import toGeoJSON from '../toGeoJSON'; +import toWKT from '../toWKT'; +const WKT_TESTS = [{ + wkt: 'POINT(30 10)', + geojson: { + type: 'Point', + coordinates: [30, 10] + } +}, { + wkt: 'LINESTRING(30 10, 10 30, 40 40)', + geojson: { + type: 'LineString', + coordinates: [[30, 10], [10, 30], [40, 40]] + } +}, { + wkt: 'POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))', + geojson: { + type: 'Polygon', + coordinates: [[[30, 10], [40, 40], [20, 40], [10, 20], [30, 10]]] + } +}, +{ + wkt: 'MULTIPOINT(10 40, 40 30, 20 20, 30 10)', + geojson: { + type: 'MultiPoint', + coordinates: [[10, 40], [40, 30], [20, 20], [30, 10]] + } +}, +{ + + wkt: 'MULTILINESTRING((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10))', + geojson: { + type: 'MultiLineString', + coordinates: [[[10, 10], [20, 20], [10, 40]], [[40, 40], [30, 30], [40, 20], [30, 10]]] + } +}, +{ + wkt: 'MULTIPOLYGON(((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))', + geojson: { + type: 'MultiPolygon', + coordinates: [ + [[[30, 20], [45, 40], [10, 40], [30, 20]]], + [[[15, 5], [40, 10], [10, 20], [5, 10], [15, 5] + ]] + ] + } +}, { + wkt: 'GEOMETRYCOLLECTION(POINT(4 6), LINESTRING(4 6, 7 10))', + geojson: { + type: 'GeometryCollection', + geometries: [{ + type: 'Point', + coordinates: [4, 6] + }, { + type: 'LineString', + coordinates: [[4, 6], [7, 10]] + }] + } +}]; + + +// alternative syntax to check parsing +const ALTERNATIVE_SYNTAX_TESTS = [ + // MULTIPOINT HAS 2 EQUIVALENT FORMS + { + wkt: 'MULTIPOINT((10 40), (40 30), (20 20), (30 10))', + geojson: { + type: 'MultiPoint', + coordinates: [[10, 40], [40, 30], [20, 20], [30, 10]] + } + }, + // spaces after comma are optional + { + wkt: 'GEOMETRYCOLLECTION(POINT(4 6), LINESTRING(4 6,7 10))', + geojson: { + type: 'GeometryCollection', + geometries: [{ + type: 'Point', + coordinates: [4, 6] + }, { + type: 'LineString', + coordinates: [[4, 6], [7, 10]] + }] + } + }, + // space after geometry name is allowed + { + wkt: 'GEOMETRYCOLLECTION (POINT (4 6), LINESTRING (4 6, 7 10))', + geojson: { + type: 'GeometryCollection', + geometries: [{ + type: 'Point', + coordinates: [4, 6] + }, { + type: 'LineString', + coordinates: [[4, 6], [7, 10]] + }] + } + } +]; + +describe('WKT convert to geoJSON (toGeoJSON)', function() { + [...WKT_TESTS, ...ALTERNATIVE_SYNTAX_TESTS].forEach((test) => { + it(test.wkt, () => { + expect(toGeoJSON(test.wkt)).toEqual(test.geojson); + }); + }); + +}); + +describe('geoJSON convert to WKT (toWKT)', function() { + WKT_TESTS.forEach((test) => { + it(test.wkt, () => { + expect(toWKT(test.geojson)).toEqual(test.wkt); + }); + }); +}); diff --git a/web/client/utils/ogc/WKT/__tests__/toGeoJSON-test.js b/web/client/utils/ogc/WKT/__tests__/toGeoJSON-test.js deleted file mode 100644 index bdbe0d53a6..0000000000 --- a/web/client/utils/ogc/WKT/__tests__/toGeoJSON-test.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2023, GeoSolutions Sas. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. - */ - -import expect from 'expect'; -import toGeoJSON from '../toGeoJSON'; -const WKT_TESTS = [{ - wkt: 'POINT(30 10)', - geojson: { - type: 'Point', - coordinates: [30, 10] - } -}, { - wkt: 'LINESTRING(30 10, 10 30, 40 40)', - geojson: { - type: 'LineString', - coordinates: [[30, 10], [10, 30], [40, 40]] - } -}, { - wkt: 'POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))', - geojson: { - type: 'Polygon', - coordinates: [[[30, 10], [40, 40], [20, 40], [10, 20], [30, 10]]] - } -}, -// MULTIPOINT HAS 2 EQUIVALENT FORMS -{ - wkt: 'MULTIPOINT((10 40), (40 30), (20 20), (30 10))', - geojson: { - type: 'MultiPoint', - coordinates: [[10, 40], [40, 30], [20, 20], [30, 10]] - } -}, -{ - wkt: 'MULTIPOINT(10 40, 40 30, 20 20, 30 10)', - geojson: { - type: 'MultiPoint', - coordinates: [[10, 40], [40, 30], [20, 20], [30, 10]] - } -}, -{ - - wkt: 'MULTILINESTRING ((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10))', - geojson: { - type: 'MultiLineString', - coordinates: [[[10, 10], [20, 20], [10, 40]], [[40, 40], [30, 30], [40, 20], [30, 10]]] - } -}, -{ - wkt: 'MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))', - geojson: { - type: 'MultiPolygon', - coordinates: [ - [[[30, 20], [45, 40], [10, 40], [30, 20]]], - [[[15, 5], [40, 10], [10, 20], [5, 10], [15, 5] - ]] - ] - } -}, { - wkt: 'GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))', - geojson: { - type: 'GeometryCollection', - geometries: [{ - type: 'Point', - coordinates: [4, 6] - }, { - type: 'LineString', - coordinates: [[4, 6], [7, 10]] - }] - } -}]; -describe('WKT convertion to geoJSON (toGeoJSON)', function() { - WKT_TESTS.forEach((test) => { - it(test.wkt, () => { - expect(toGeoJSON(test.wkt)).toEqual(test.geojson); - }); - }); -}); diff --git a/web/client/utils/ogc/WKT/index.js b/web/client/utils/ogc/WKT/index.js index 075e85df7f..5d5f55e077 100644 --- a/web/client/utils/ogc/WKT/index.js +++ b/web/client/utils/ogc/WKT/index.js @@ -1 +1,2 @@ export {default as toGeoJSON} from './toGeoJSON'; +export {default as toWKT} from './toWKT'; diff --git a/web/client/utils/ogc/WKT/toWKT.js b/web/client/utils/ogc/WKT/toWKT.js new file mode 100644 index 0000000000..8851861a4f --- /dev/null +++ b/web/client/utils/ogc/WKT/toWKT.js @@ -0,0 +1,125 @@ +const coordinateArrayToWKT = (coordinates) => { + const [x, y] = coordinates; + return `${x} ${y}`; +}; + +/** + * Convert a geoJSON Point to a WKT Point + * @private + * @param {object} point the geoJSON Point + * @returns {string} WKT string + */ +const pointToWKT = (point) => { + const {coordinates} = point; + return `POINT(${coordinateArrayToWKT(coordinates)})`; +}; + +/** + * Convert a geoJSON MultiPoint to a WKT MultiPoint + * @private + * @param {object} multiPoint the geoJSON MultiPoint + * @returns {string} WKT string + * + */ +const multiPointToWKT = (multiPoint) => { + const {coordinates} = multiPoint; + const points = coordinates.map(coordinateArrayToWKT); + return `MULTIPOINT(${points.join(', ')})`; +}; + +/** + * Convert a geoJSON LineString to a WKT LineString + * @private + * @param {object} lineString the geoJSON LineString + * @returns {string} WKT string + */ +const lineStringToWKT = (lineString) => { + const {coordinates} = lineString; + const points = coordinates.map(coordinateArrayToWKT); + return `LINESTRING(${points.join(', ')})`; +}; + +/** + * Convert a geoJSON MultiLineString to a WKT MultiLineString + * @private + * @param {object} multiLineString the geoJSON MultiLineString + * @returns {string} WKT string + */ +const multiLineStringToWKT = (multiLineString) => { + const {coordinates} = multiLineString; + const lines = coordinates.map(line => `(${line.map(coordinateArrayToWKT).join(', ')})`); + return `MULTILINESTRING(${lines.join(', ')})`; +}; + +/** + * Convert a geoJSON Polygon to a WKT Polygon + * @private + * @param {object} polygon the geoJSON Polygon + * @returns {string} WKT string + */ +const polygonToWKT = (polygon) => { + const {coordinates} = polygon; + const rings = coordinates.map(ring => `(${ring.map(coordinateArrayToWKT).join(', ')})`); + return `POLYGON(${rings.join(', ')})`; +}; + +/** + * Convert a geoJSON MultiPolygon to a WKT MultiPolygon + * @private + * @param {object} multiPolygon the geoJSON MultiPolygon + * @returns {string} WKT string + */ +const multiPolygonToWKT = (multiPolygon) => { + const {coordinates} = multiPolygon; + const polygons = coordinates.map(polygon => `(${polygon.map(ring => `(${ring.map(coordinateArrayToWKT).join(', ')})`).join(', ')})`); + return `MULTIPOLYGON(${polygons.join(', ')})`; +}; + +let toWKT; + +/** + * Convert a geoJSON GeometryCollection to a WKT GeometryCollection + * @private + * @param {object} geometryCollection the geoJSON GeometryCollection + * @returns {string} WKT string + */ +const geometryCollectionToWKT = (geometryCollection) => { + const {geometries} = geometryCollection; + const geometriesWKT = geometries.map(geoJSON => toWKT(geoJSON)); + return `GEOMETRYCOLLECTION(${geometriesWKT.join(', ')})`; +}; + +/** + * Converts a geoJSON geometry to a WKT geometry + * @param {object} geoJSON the geoJSON geometry + * @returns {string} WKT string + * @example + * const geoJSON = { + * type: 'Point', + * coordinates: [30, 10] + * }; + * const wkt = toWKT(geoJSON); + * // wkt = 'POINT(30 10)' + */ +toWKT = (geoJSON) => { + switch (geoJSON.type) { + case 'Point': + return pointToWKT(geoJSON); + case 'MultiPoint': + return multiPointToWKT(geoJSON); + case 'LineString': + return lineStringToWKT(geoJSON); + case 'MultiLineString': + return multiLineStringToWKT(geoJSON); + case 'Polygon': + return polygonToWKT(geoJSON); + case 'MultiPolygon': + return multiPolygonToWKT(geoJSON); + case 'GeometryCollection': + return geometryCollectionToWKT(geoJSON); + default: + return ''; + } +}; + +export default toWKT;