diff --git a/CHANGES.md b/CHANGES.md index a455d93..443cc8f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,12 @@ -# @geoblocks/mapfisprint changes +# @geoblocks/mapfishprint changes + +## 0.2.23 + +- Resolve a bug where a style with its own geometry as a Circle was transformed into a GeometryCollection resulting in an error + +Breaking changes: + +- VectorEncoder.featureCircleAsPolygon() was removed. ## 0.2.20 diff --git a/package-lock.json b/package-lock.json index e91bfb0..2111c7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@geoblocks/mapfishprint", - "version": "0.2.22", + "version": "0.2.23", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@geoblocks/mapfishprint", - "version": "0.2.22", + "version": "0.2.23", "license": "BSD-3-Clause", "devDependencies": { "@geoblocks/print": "0.7.9", diff --git a/package.json b/package.json index 9a66067..55e3bbf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geoblocks/mapfishprint", - "version": "0.2.22", + "version": "0.2.23", "publishConfig": { "access": "public" }, diff --git a/src/VectorEncoder.ts b/src/VectorEncoder.ts index bf4f2d5..5bfe210 100644 --- a/src/VectorEncoder.ts +++ b/src/VectorEncoder.ts @@ -167,8 +167,10 @@ export default class VectorEncoder { if (styleFunction) { styleData = styleFunction(feature, resolution) as null | Style | Style[]; } - if (feature.getGeometry().getType() === 'Circle') { - feature = this.featureCircleAsPolygon(feature as Feature); + + const featureGeometry = feature.getGeometry(); + if (featureGeometry.getType() === "Circle") { + feature.setGeometry(fromCircle(featureGeometry as Circle, Constants.CIRCLE_TO_POLYGON_SIDES)); } const origGeojsonFeature = this.geojsonFormat.writeFeatureObject(feature); @@ -186,13 +188,23 @@ export default class VectorEncoder { // FIXME: the return of the function is very complicate and would require // handling more cases than we actually do let geometry: any = style.getGeometry(); - let geojsonFeature; + // Fallback to the feature geometry if style doesn't give one. + if (geometry === null) { + geometry = featureGeometry; + } // In some cases, the geometries are objects, in other cases they're functions. // we need to ensure we're handling functions, wether they return an object or not. if (typeof geometry === 'function') { geometry = geometry(feature); } - if (geometry && typeof geometry === 'object') { + // no need to encode features with no geometry + if (!geometry) return; + + if (geometry.getType() === "Circle") { + geometry = fromCircle(geometry as Circle, Constants.CIRCLE_TO_POLYGON_SIDES); + } + let geojsonFeature; + if (typeof geometry === 'object') { // note that (typeof null === 'object') const styledFeature = feature.clone(); styledFeature.setGeometry(geometry); @@ -200,11 +212,6 @@ export default class VectorEncoder { geojsonFeatures.push(geojsonFeature); } else { geojsonFeature = origGeojsonFeature; - geometry = feature.getGeometry(); - // no need to encode features with no geometry - if (!geometry) { - return; - } if (!this.customizer_.geometryFilter(geometry)) { return; } @@ -598,15 +605,4 @@ export default class VectorEncoder { symbolizers.push(symbolizer); } } - - /** - * Converts a circle feature to a N sides polygon feature. - * Sides are defined in Constants.CIRCLE_TO_POLYGON_SIDES. - */ - protected featureCircleAsPolygon(feature: Feature) { - return new Feature({ - ...feature.getProperties(), - geometry: fromCircle(feature.getGeometry(), Constants.CIRCLE_TO_POLYGON_SIDES), - }); - } } diff --git a/test.js b/test.js index 4126fbe..a89a6b9 100644 --- a/test.js +++ b/test.js @@ -1,7 +1,7 @@ import test from 'node:test'; import assert from 'node:assert'; import Map from 'ol/Map.js'; -import {MFPEncoder, BaseCustomizer} from './lib/index.js'; +import {MFPEncoder, MFPVectorEncoder, BaseCustomizer} from './lib/index.js'; import TileLayer from 'ol/layer/Tile.js'; import OSM from 'ol/source/OSM.js'; import {View} from 'ol'; @@ -324,3 +324,46 @@ test('Vector features', async (t) => { }, }); }); + +test('MFPVectorEncoder can encode a circle with a circle in its style.geometry', async (t) => { + const geomStyleFn = () => { + return new Style({ + geometry: fCircle.getGeometry(), + fill, + stroke + }); + }; + fCircle.setStyle(geomStyleFn); + const vectorLayer = new VectorLayer({ + source: new VectorSource({ + features: [fCircle], + }), + }); + const customizer = new BaseCustomizer(); + const resolution = 1.0583354500042335; + const encodedSpecialLayer = new MFPVectorEncoder(vectorLayer.getLayerState(), customizer).encodeVectorLayer(resolution); + + assert.deepEqual(encodedSpecialLayer.geoJson.features[0], { + type: 'Feature', + geometry: { + type: 'Polygon', + coordinates: [ + [ + [796622, 5836960], + [796619.0710678119, 5836967.071067812], + [796612, 5836970], + [796604.9289321881, 5836967.071067812], + [796602, 5836960], + [796604.9289321881, 5836952.928932188], + [796612, 5836950], + [796619.0710678119, 5836952.928932188], + [796622, 5836960], + ], + ], + }, + properties: { + name: 'A circle', + _mfp_style: '1', + }, + }); +}); \ No newline at end of file