From 8581f9c9ef1dbc3f58dd4d3012a9471692e3bc35 Mon Sep 17 00:00:00 2001 From: Matteo V Date: Tue, 12 Mar 2024 15:44:00 +0100 Subject: [PATCH] Fix #9999 Measures distance and area now supports all operations as geodesics features (#10010) (#10058) --- .../map/openlayers/MeasurementSupport.jsx | 5 ++ .../Annotations/utils/AnnotationsUtils.js | 39 +++++++- .../utils/__tests__/AnnotationsUtils-test.js | 15 ++++ .../Annotations/utils/__tests__/resources.js | 5 ++ web/client/utils/MeasurementUtils.js | 23 ++++- .../utils/__tests__/MeasurementUtils-test.js | 90 ++++++++++++++++++- .../utils/styleparser/CesiumStyleParser.js | 10 ++- .../styleparser/GeometryFunctionsUtils.js | 18 +++- .../utils/styleparser/LeafletStyleParser.js | 14 ++- web/client/utils/styleparser/OLStyleParser.js | 3 + .../utils/styleparser/PrintStyleParser.js | 4 +- .../__tests__/LeafletStyleParser-test.js | 20 +---- 12 files changed, 215 insertions(+), 31 deletions(-) create mode 100644 web/client/plugins/Annotations/utils/__tests__/resources.js diff --git a/web/client/components/map/openlayers/MeasurementSupport.jsx b/web/client/components/map/openlayers/MeasurementSupport.jsx index 8028a0eed1..6b8a53b521 100644 --- a/web/client/components/map/openlayers/MeasurementSupport.jsx +++ b/web/client/components/map/openlayers/MeasurementSupport.jsx @@ -839,6 +839,11 @@ export default class MeasurementSupport extends React.Component { clonedNewFeature = set("geometry.coordinates", newCoords, clonedNewFeature); } else if (!this.props.measurement.disableLabels && this.props.measurement.areaMeasureEnabled) { // the one before the last is a dummy + let oldCoords = clonedNewFeature.geometry.coordinates; + let newCoords = transformLineToArcs(oldCoords[0]); + clonedNewFeature = set("geometry.coordinates", [newCoords], clonedNewFeature); + + // edit geom for drawing geodesic lines this.textLabels.splice(this.segmentOverlays.length - 2, 1); this.props.map.removeOverlay(this.segmentOverlays[this.segmentOverlays.length - 2]); this.segmentOverlayElements[this.segmentOverlays.length - 2].parentNode.removeChild( diff --git a/web/client/plugins/Annotations/utils/AnnotationsUtils.js b/web/client/plugins/Annotations/utils/AnnotationsUtils.js index 8380d4447a..334933fb28 100644 --- a/web/client/plugins/Annotations/utils/AnnotationsUtils.js +++ b/web/client/plugins/Annotations/utils/AnnotationsUtils.js @@ -7,9 +7,19 @@ */ import uuidv1 from 'uuid/v1'; -import { slice, head, last, get, isNaN, isEqual, isNumber } from 'lodash'; +import { slice, omit, head, last, get, isNaN, isEqual, isNumber } from 'lodash'; import turfBbox from '@turf/bbox'; -import { measureIcons } from '../../../utils/MeasureUtils'; +import { + MeasureTypes, + measureIcons +} from '../../../utils/MeasureUtils'; +import { + getMeasureType +} from '../../../utils/MeasurementUtils'; + +import { + transformLineToArcs +} from '../../../utils/CoordinatesUtils'; // legacy style export const STYLE_CIRCLE = { @@ -405,6 +415,9 @@ export const updateAnnotationsLayer = (layer = {}) => { } return []; }; + +export const isGeodesicMeasure = (measureType) => [MeasureTypes.LENGTH, MeasureTypes.AREA].includes(measureType); + /** * This function takes an annotations layer and converts it to valid GeoJSON Feature Collection usable for export * @param {array} annotations annotations layers @@ -415,10 +428,21 @@ export const annotationsToGeoJSON = (annotations) => { return [ ...acc, ...(annotation.features || []).map((feature) => { + const measureType = getMeasureType(feature); + const isGeodesic = isGeodesicMeasure(measureType); + let newGeom = feature.geometry; + if (isGeodesic) { + newGeom = { + type: feature.geometry.type, + coordinates: measureType === MeasureTypes.LENGTH ? transformLineToArcs(feature.geometry.coordinates) : feature.geometry.coordinates.map(transformLineToArcs) + }; + } return { ...feature, + geometry: newGeom, properties: { ...feature.properties, + ...(isGeodesic ? {originalGeom: feature.geometry} : {}), annotationLayerId: annotation.id, annotationLayerTitle: annotation.title, annotationLayerDescription: annotation.description @@ -452,7 +476,16 @@ export const geoJSONToAnnotations = (json) => { const layers = (json?.annotations || []) .map((annotation) => { const features = (json?.features || []) - .filter((feature) => feature?.properties?.annotationLayerId === annotation.id); + .filter((feature) => feature?.properties?.annotationLayerId === annotation.id) + .map(feature => { + const measureType = getMeasureType(feature); + const isGeodesic = isGeodesicMeasure(measureType); + return isGeodesic && feature.properties.originalGeom ? { + ...feature, + geometry: feature.properties.originalGeom, + properties: omit(feature.properties, "originalGeom") + } : feature; + }); const { annotationLayerTitle: title, annotationLayerDescription: description diff --git a/web/client/plugins/Annotations/utils/__tests__/AnnotationsUtils-test.js b/web/client/plugins/Annotations/utils/__tests__/AnnotationsUtils-test.js index f78c0a8eaf..c65b01f7a8 100644 --- a/web/client/plugins/Annotations/utils/__tests__/AnnotationsUtils-test.js +++ b/web/client/plugins/Annotations/utils/__tests__/AnnotationsUtils-test.js @@ -9,6 +9,7 @@ import expect from 'expect'; import { isAnnotationLayer, isAnnotation, + isGeodesicMeasure, createAnnotationId, validateCoords, coordToArray, @@ -24,8 +25,16 @@ import { applyDefaultCoordinates, getFeatureIcon } from '../AnnotationsUtils'; +import { annotationsTest, annotationsTestResult, annotationsTestFromGeoJson } from './resources'; + +import { MeasureTypes } from '../../../../utils/MeasureUtils'; describe('AnnotationsUtils', () => { + it('isGeodesicMeasure', () => { + expect(isGeodesicMeasure(MeasureTypes.LENGTH)).toBe(true); + expect(isGeodesicMeasure(MeasureTypes.AREA)).toBe(true); + expect(isGeodesicMeasure(MeasureTypes.BEARING)).toBe(false); + }); it('isAnnotationLayer', () => { expect(isAnnotationLayer({ id: 'annotations:01', rowViewer: 'annotations', features: [], type: 'vector' })).toBe(true); expect(isAnnotationLayer({ id: '01', features: [], type: 'vector' })).toBe(false); @@ -498,6 +507,9 @@ describe('AnnotationsUtils', () => { ] }); }); + it('annotationsToGeoJSON with length and area measures', () => { + expect(annotationsToGeoJSON(annotationsTest)).toEqual(annotationsTestResult); + }); it('geoJSONToAnnotations', () => { const geoJSON = { type: 'FeatureCollection', @@ -544,6 +556,9 @@ describe('AnnotationsUtils', () => { { id: 'annotations:2', visibility: true, rowViewer: 'annotations', title: 'Annotation02', description: '

description

', type: 'vector', style: { format: 'geostyler', body: { name: '', rules: [{ name: '', filter: ['==', 'id', 'feature-02'], symbolizers: [{ kind: 'Icon' }] }] } }, features: [{ type: 'Feature', id: 'feature-02', geometry: { type: 'Point', coordinates: [0, 0] }, properties: { id: 'feature-02', annotationType: 'Point' } }] } ]); }); + it('geoJSONToAnnotations with geodesic measures in input', () => { + expect(geoJSONToAnnotations(annotationsTestResult)).toEqual(annotationsTestFromGeoJson); + }); it('importJSONToAnnotations invalid', () => { expect(importJSONToAnnotations({})).toEqual([]); }); diff --git a/web/client/plugins/Annotations/utils/__tests__/resources.js b/web/client/plugins/Annotations/utils/__tests__/resources.js new file mode 100644 index 0000000000..93737b7b8c --- /dev/null +++ b/web/client/plugins/Annotations/utils/__tests__/resources.js @@ -0,0 +1,5 @@ +export const annotationsTest = [{"id": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "type": "vector", "title": "Measure", "description": "Annotations created from measurements", "features": [{"type": "Feature", "geometry": {"type": "LineString", "coordinates": [[9.866636363994022, 61.527248291386314], [17.249448863994022, 63.09907980217878]]}, "properties": {"label": "419.255,7 m", "geodesic": true, "originalGeom": {"type": "LineString", "coordinates": [[9.866636363994022, 61.527248291386314], [17.249448863994022, 63.09907980217878]]}, "length": 419255.701, "lengthUom": "m", "lengthTargetUom": "m", "type": "measurement", "measureType": "length", "id": "f9af08e1-d7be-11ee-b078-79069145e96a", "annotationType": "LineString", "name": "length"}, "id": "f9af08e1-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [13.498714228074927, 62.37000869405188]}, "properties": {"type": "segment", "label": "419.255,7 m", "id": "f9af08e2-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e1-d7be-11ee-b078-79069145e96a"}, "id": "f9af08e2-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[15.403745738994022, 59.98178361056085], [22.91839417649402, 61.67355626132541], [24.017026988994022, 59.4722594114112], [15.403745738994022, 59.98178361056085]]]}, "properties": {"label": "55.842.129.407,55 m²", "geodesic": true, "originalGeom": {"type": "Polygon", "coordinates": [[[15.403745738994022, 59.98178361056085], [22.91839417649402, 61.67355626132541], [24.017026988994022, 59.4722594114112], [15.403745738994022, 59.98178361056085]]]}, "length": 1186095.99, "lengthUom": "m", "lengthTargetUom": "m", "area": 55842129407.55051, "areaUom": "sqm", "areaTargetUom": "sqm", "type": "measurement", "measureType": "area", "id": "f9af08e3-d7be-11ee-b078-79069145e96a", "annotationType": "Polygon", "name": "area"}, "id": "f9af08e3-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [19.16106995774402, 60.838858130180036]}, "properties": {"type": "segment", "label": "448.297,68 m", "id": "f9af08e4-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a"}, "id": "f9af08e4-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.46771058274402, 60.59165716667119]}, "properties": {"type": "segment", "label": "252.015,03 m", "id": "f9af08e5-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a"}, "id": "f9af08e5-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [19.710386363994022, 59.727991846805935]}, "properties": {"type": "segment", "label": "485.783,29 m", "id": "f9af08e6-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a"}, "id": "f9af08e6-d7be-11ee-b078-79069145e96a"}], "rowViewer": "annotations", "style": {"format": "geostyler", "body": {"name": "", "rules": [{"ruleId": "f9af08e7-d7be-11ee-b078-79069145e96a", "name": "Start position", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08e8-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "startPoint"}, "wellKnownName": "Circle", "color": "#008000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08e9-d7be-11ee-b078-79069145e96a", "name": "End position", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08ea-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "endPoint"}, "wellKnownName": "Circle", "color": "#ff0000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08eb-d7be-11ee-b078-79069145e96a", "name": "", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08ec-d7be-11ee-b078-79069145e96a", "kind": "Line", "msGeometry": {"name": "lineToArc"}, "color": "#FF9548", "width": 3, "opacity": 1, "cap": "round", "join": "round", "msClampToGround": false}]}, {"ruleId": "f9af08ed-d7be-11ee-b078-79069145e96a", "name": "Segment labels", "filter": ["==", "measureId", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08ee-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 10, "fontStyle": "italic", "fontWeight": "normal", "haloColor": "#444444", "haloWidth": 0.5, "allowOverlap": true, "offset": [0, 0], "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1}]}, {"ruleId": "f9af08ef-d7be-11ee-b078-79069145e96a", "name": "Measurement label", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f0-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 13, "fontStyle": "normal", "fontWeight": "bold", "haloColor": "#FFFFFF", "haloWidth": 3, "allowOverlap": true, "anchor": "bottom", "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1, "offset": [0, 0], "msGeometry": {"name": "endPoint"}}]}, {"ruleId": "f9af08f1-d7be-11ee-b078-79069145e96a", "name": "Start position", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08f2-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "startPoint"}, "wellKnownName": "Circle", "color": "#008000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08f3-d7be-11ee-b078-79069145e96a", "name": "End position", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08f4-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "endPoint"}, "wellKnownName": "Circle", "color": "#ff0000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08f5-d7be-11ee-b078-79069145e96a", "name": "Area measurement", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f6-d7be-11ee-b078-79069145e96a", "kind": "Fill", "msGeometry": {"name": "lineToArc"}, "color": "#ffffff", "fillOpacity": 0.5, "outlineColor": "#33A8FF", "outlineOpacity": 1, "outlineWidth": 3, "msClassificationType": "both", "msClampToGround": false}]}, {"ruleId": "f9af08f7-d7be-11ee-b078-79069145e96a", "name": "Segment labels", "filter": ["==", "measureId", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f8-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 10, "fontStyle": "italic", "fontWeight": "normal", "haloColor": "#444444", "haloWidth": 0.5, "allowOverlap": true, "offset": [0, 0], "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1}]}, {"ruleId": "f9af08f9-d7be-11ee-b078-79069145e96a", "name": "Measurement label", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08fa-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 13, "fontStyle": "normal", "fontWeight": "bold", "haloColor": "#FFFFFF", "haloWidth": 3, "allowOverlap": true, "anchor": "bottom", "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1, "offset": [0, 0], "msGeometry": {"name": "endPoint"}}]}]}}, "visibility": true, "invalidFeatures": null}]; + +export const annotationsTestResult = {"type": "FeatureCollection", "msType": "annotations", "features": [{"type": "Feature", "geometry": {"type": "LineString", "coordinates": [[9.866636363994024, 61.527248291386314], [9.937306136596643, 61.54502622192236], [10.008056795281842, 61.56276759642072], [10.078888325494344, 61.58047234600065], [10.149800711799918, 61.598140401752374], [10.220793937881306, 61.61577169473785], [10.291867986534163, 61.63336615599165], [10.363022839663028, 61.65092371652158], [10.434258478277236, 61.66844430730972], [10.505574882486929, 61.6859278593131], [10.576972031498975, 61.70337430346456], [10.648449903612958, 61.72078357067361], [10.72000847621716, 61.73815559182723], [10.791647725784523, 61.75549029779069], [10.863367627868653, 61.772787619408525], [10.935168157099795, 61.79004748750515], [11.007049287180871, 61.80726983288598], [11.079010990883452, 61.82445458633809], [11.151053240043781, 61.8416016786312], [11.223176005558814, 61.858711040518486], [11.295379257382239, 61.87578260273749], [11.367662964520509, 61.89281629601098], [11.440027095028904, 61.90981205104784], [11.51247161600758, 61.92676979854399], [11.584996493597636, 61.943689469183276], [11.657601692977185, 61.9605709936383], [11.730287178357454, 61.97741430257146], [11.803052912978853, 61.99421932663578], [11.875898859107101, 62.01098599647581], [11.94882497802933, 62.027714242728614], [12.021831230050214, 62.044403996024656], [12.094917574488107, 62.06105518698876], [12.168083969671175, 62.07766774624103], [12.241330372933579, 62.094241604397794], [12.314656740611628, 62.1107766920726], [12.38806302803997, 62.127272939877095], [12.461549189547775, 62.143730278422034], [12.535115178454964, 62.160148638318255], [12.608760947068404, 62.1765279501776], [12.68248644667816, 62.192868144613975], [12.756291627553734, 62.209169152244215], [12.830176438940326, 62.2254309036892], [12.904140829055104, 62.24165332957473], [12.978184745083508, 62.2578363605326], [13.052308133175544, 62.273979927201566], [13.12651093844209, 62.290083960228365], [13.200793104951261, 62.30614839026872], [13.275154575724729, 62.32217314798836], [13.349595292734094, 62.33815816406404], [13.424115196897283, 62.35410336918458], [13.498714228074927, 62.37000869405188], [13.573392325066791, 62.38587406938196], [13.648149425608192, 62.40169942590602], [13.72298546636646, 62.417484694371446], [13.797900382937403, 62.43322980554293], [13.872894109841774, 62.44893469020346], [13.947966580521806, 62.464599279155436], [14.023117727337707, 62.48022350322167], [14.098347481564215, 62.495807293246536], [14.17365577338715, 62.511350580097], [14.249042531899995, 62.5268532946637], [14.324507685100508, 62.542315367862074], [14.400051159887319, 62.55773673063338], [14.47567288205659, 62.573117313945886], [14.551372776298662, 62.58845704879588], [14.62715076619475, 62.60375586620885], [14.703006774213645, 62.61901369724054], [14.778940721708413, 62.6342304729781], [14.854952528913202, 62.64940612454119], [14.931042114939945, 62.66454058308311], [15.007209397775195, 62.67963377979194], [15.083454294276931, 62.69468564589166], [15.159776720171397, 62.709696112643286], [15.23617659004996, 62.724665111346056], [15.312653817366007, 62.73959257333851], [15.38920831443186, 62.75447842999971], [15.46583999241569, 62.76932261275034], [15.542548761338514, 62.78412505305392], [15.619334530071153, 62.798885682417946], [15.69619720633126, 62.813604432395046], [15.773136696680348, 62.828281234584225], [15.850152906520874, 62.84291602063194], [15.927245740093328, 62.857508722233376], [16.004415100473317, 62.8720592711336], [16.081660889568777, 62.88656759912877], [16.158983008117097, 62.901033638067275], [16.236381355682322, 62.915457319851036], [16.313855830652436, 62.929838576436644], [16.39140633023656, 62.94417733983657], [16.46903275046227, 62.958473542120416], [16.546734986172936, 62.97272711541613], [16.624512931025034, 62.98693799191119], [16.70236647748554, 63.001106103853886], [16.780295516829348, 63.01523138355452], [16.85829993913671, 63.02931376338665], [16.936379633290688, 63.043353175788326], [17.014534486974675, 63.05734955326335], [17.09276438666993, 63.07130282838249], [17.17106921765314, 63.085212933784796], [17.249448863994022, 63.09907980217878]]}, "properties": {"label": "419.255,7 m", "geodesic": true, "originalGeom": {"type": "LineString", "coordinates": [[9.866636363994022, 61.527248291386314], [17.249448863994022, 63.09907980217878]]}, "length": 419255.701, "lengthUom": "m", "lengthTargetUom": "m", "type": "measurement", "measureType": "length", "id": "f9af08e1-d7be-11ee-b078-79069145e96a", "annotationType": "LineString", "name": "length", "annotationLayerId": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "annotationLayerTitle": "Measure", "annotationLayerDescription": "Annotations created from measurements"}, "id": "f9af08e1-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [13.498714228074927, 62.37000869405188]}, "properties": {"type": "segment", "label": "419.255,7 m", "id": "f9af08e2-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e1-d7be-11ee-b078-79069145e96a", "annotationLayerId": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "annotationLayerTitle": "Measure", "annotationLayerDescription": "Annotations created from measurements"}, "id": "f9af08e2-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[15.403745738994026, 59.98178361056085], [15.475634219328231, 60.000908164939965], [15.5476057882022, 60.01999361807935], [15.619660435072765, 60.03903989468272], [15.69179814848937, 60.05804691941746], [15.764018916089684, 60.07701461691539], [15.836322724595236, 60.09594291177378], [15.908709559807072, 60.11483172855609], [15.981179406601386, 60.133680991793], [16.053732248925176, 60.152490625983155], [16.12636806979191, 60.17126055559423], [16.199086851277173, 60.18999070506369], [16.27188857451433, 60.20868099879979], [16.344773219690214, 60.22733136118245], [16.417740766040783, 60.245941716564225], [16.490791191846814, 60.264511989271156], [16.563924474429587, 60.283042103603805], [16.637140590146583, 60.30153198383813], [16.71043951438718, 60.31998155422642], [16.78382122156836, 60.33839073899838], [16.857285685130446, 60.356759462361836], [16.930832877532797, 60.37508764850399], [17.00446277024955, 60.393375221592194], [17.078175333765365, 60.41162210577502], [17.151970537571167, 60.42982822518317], [17.22584835015991, 60.44799350393057], [17.299808739022325, 60.466117866115276], [17.37385167064272, 60.48420123582049], [17.44797711049473, 60.50224353711564], [17.522185023037157, 60.52024469405728], [17.59647537170973, 60.53820463069019], [17.670848118928955, 60.5561232710484], [17.745303226083905, 60.574000539156145], [17.8198406535321, 60.59183635902903], [17.89446036059531, 60.60963065467495], [17.969162305555447, 60.627383350095236], [18.04394644565043, 60.64509436928557], [18.11881273707006, 60.66276363623728], [18.19376113495191, 60.680391074938164], [18.26879159337727, 60.6979766093737], [18.343904065367035, 60.715520163528105], [18.419098502877645, 60.73302166138538], [18.494374856797055, 60.750481026930466], [18.569733076940683, 60.767898184150255], [18.64517311204739, 60.785273057034786], [18.720694909775478, 60.80260556957829], [18.796298416698708, 60.819895645780306], [18.871983578302295, 60.83714320964683], [18.947750338978985, 60.85434818519145], [19.023598642025092, 60.871510496436414], [19.099528429636564, 60.888630067413835], [19.175539642905086, 60.905706822166806], [19.251632221814187, 60.92274068475054], [19.327806105235357, 60.93973157923355], [19.40406123092419, 60.95667942969879], [19.48039753551654, 60.973584160244826], [19.556814954524725, 60.990445694987024], [19.63331342233368, 61.007263958058665], [19.709892872197223, 61.02403887361225], [19.786553236234255, 61.040770365820556], [19.863294445425016, 61.057458358877916], [19.940116429607407, 61.07410277700141], [20.017019117473215, 61.090703544432], [20.0940024365645, 61.10726058543588], [20.171066313269886, 61.12377382430554], [20.24821067282095, 61.14024318536109], [20.325435439288565, 61.15666859295145], [20.40274053557938, 61.17304997145561], [20.480125883432155, 61.18938724528385], [20.557591403414285, 61.20568033887894], [20.635137014918225, 61.22192917671751], [20.712762636158033, 61.23813368331118], [20.790468184165846, 61.25429378320792], [20.868253574788447, 61.270409400993245], [20.946118722683856, 61.28648046129151], [21.02406354131787, 61.302506888767205], [21.102087942960754, 61.31848860812623], [21.18019183868384, 61.334425544117174], [21.25837513835621, 61.35031762153262], [21.33663775064141, 61.366164765210414], [21.414979582994174, 61.38196690003504], [21.493400541657145, 61.39772395093884], [21.57190053165771, 61.413435842903404], [21.650479456804792, 61.42910250096083], [21.72913721968565, 61.44472385019508], [21.807873721662816, 61.46029981574334], [21.88668886287092, 61.475830322797286], [21.96558254221367, 61.49131529660446], [22.04455465736079, 61.506754662469646], [22.123605104745, 61.522148345756165], [22.20273377955904, 61.53749627188725], [22.281940575752706, 61.55279836634743], [22.36122538602996, 61.568054554683854], [22.440588101846004, 61.583264762507724], [22.520028613404452, 61.59842891549556], [22.599546809654484, 61.61354693939073], [22.679142578288076, 61.62861876000466], [22.758815805737232, 61.64364430321841], [22.838566377171233, 61.65862349498391], [22.91839417649402, 61.67355626132541], [22.91839417649402, 61.67355626132541], [22.930267890545213, 61.65136768002424], [22.94212457131332, 61.629178071914076], [22.95396425818876, 61.60698743941681], [22.965786990444098, 61.58479578494694], [22.977592807234455, 61.562603110911475], [22.98938174759796, 61.54040941971012], [23.001153850456163, 61.51821471373515], [23.01290915461444, 61.49601899537158], [23.02464769876249, 61.473822266997075], [23.036369521474647, 61.451624530982045], [23.048074661210425, 61.42942578968965], [23.059763156314823, 61.407226045475845], [23.071435045018813, 61.385025300689406], [23.08309036543973, 61.362823557671895], [23.094729155581696, 61.340620818757785], [23.10635145333603, 61.31841708627441], [23.117957296481627, 61.29621236254203], [23.129546722685426, 61.27400664987386], [23.141119769502758, 61.251799950576086], [23.152676474377795, 61.22959226694787], [23.164216874643916, 61.2073836012814], [23.175741007524135, 61.18517395586193], [23.187248910131494, 61.16296333296776], [23.198740619469458, 61.14075173487032], [23.2102161724323, 61.118539163834164], [23.221675605805522, 61.096325622116964], [23.233118956266242, 61.07411111196961], [23.24454626038354, 61.051895635636164], [23.255957554618913, 61.02967919535394], [23.267352875326633, 61.00746179335351], [23.27873225875412, 60.98524343185867], [23.29009574104235, 60.963024113086576], [23.301443358226233, 60.94080383924772], [23.312775146234983, 60.91858261254588], [23.324091140892506, 60.89636043517829], [23.335391377917777, 60.87413730933553], [23.346675892925223, 60.85191323720162], [23.357944721425085, 60.82968822095407], [23.3691978988238, 60.807462262763785], [23.380435460424373, 60.78523536479527], [23.391657441426737, 60.763007529206455], [23.40286387692815, 60.74077875814888], [23.414054801923534, 60.718549053767646], [23.42523025130583, 60.696318418201436], [23.43639025986642, 60.674086853582565], [23.44753486229541, 60.65185436203695], [23.458664093182062, 60.62962094568425], [23.469777987015117, 60.607386606637746], [23.480876578183157, 60.58515134700444], [23.49195990097496, 60.5629151688851], [23.503027989579863, 60.54067807437424], [23.514080878088134, 60.51844006556013], [23.525118600491265, 60.49620114452487], [23.536141190682393, 60.473961313344375], [23.547148682456598, 60.45172057408841], [23.558141109511283, 60.42947892882063], [23.569118505446486, 60.407236379598544], [23.580080903765282, 60.38499292847362], [23.591028337874054, 60.362748577491224], [23.601960841082892, 60.34050332869074], [23.612878446605915, 60.318257184105455], [23.623781187561594, 60.29601014576272], [23.63466909697312, 60.27376221568392], [23.645542207768706, 60.251513395884416], [23.65640055278197, 60.22926368837371], [23.667244164752212, 60.20701309515538], [23.6780730763248, 60.1847616182271], [23.688887320051446, 60.16250925958069], [23.69968692839058, 60.14025602120209], [23.710471933707662, 60.1180019050715], [23.721242368275522, 60.095746913163225], [23.731998264274647, 60.07349104744584], [23.742739653793553, 60.05123430988214], [23.753466568829076, 60.02897670242922], [23.764179041286706, 60.006718227038384], [23.77487710298091, 59.9844588856553], [23.785560785635436, 59.96219868021993], [23.796230120883646, 59.939937612666576], [23.80688514026882, 59.91767568492392], [23.817525875244495, 59.89541289891502], [23.828152357174748, 59.87314925655734], [23.838764617334515, 59.850884759762764], [23.849362686909924, 59.82861941043761], [23.85994659699858, 59.80635321048268], [23.870516378609878, 59.78408616179325], [23.88107206266534, 59.76181826625909], [23.891613679998866, 59.7395495257645], [23.90214126135709, 59.71727994218834], [23.912654837399643, 59.69500951740398], [23.923154438699505, 59.67273825327948], [23.933640095743254, 59.65046615167735], [23.944111838931384, 59.62819321445485], [23.95456969857863, 59.6059194434638], [23.965013704914213, 59.58364484055073], [23.9754438880822, 59.56136940755682], [23.985860278141732, 59.53909314631793], [23.99626290506739, 59.5168160586647], [24.006651798749402, 59.49453814642243], [24.017026988994022, 59.4722594114112], [24.017026988994022, 59.4722594114112], [23.93155910710788, 59.480198672076405], [23.846051178091507, 59.488082131675476], [23.76050345343448, 59.49590974658783], [23.674916185475794, 59.503681473457334], [23.589289627399783, 59.511397269193516], [23.503624033232033, 59.5190570909726], [23.417919657835235, 59.526660896238766], [23.332176756905003, 59.534208642705124], [23.24639558696565, 59.54170028835489], [23.16057640536592, 59.549135791442524], [23.07471947027465, 59.55651511049478], [22.98882504067647, 59.56383820431184], [22.902893376367373, 59.57110503196839], [22.81692473795027, 59.5783155528147], [22.730919386830543, 59.585469726477726], [22.64487758521151, 59.59256751286216], [22.558799596089873, 59.599608872151514], [22.47268568325109, 59.606593764809176], [22.386536111264768, 59.61352215157952], [22.300351145479976, 59.62039399348885], [22.214131052020488, 59.62720925184654], [22.127876097780053, 59.63396788824607], [22.041586550417577, 59.64066986456596], [21.95526267835229, 59.64731514297098], [21.868904750758848, 59.65390368591296], [21.782513037562403, 59.66043545613198], [21.696087809433656, 59.66691041665728], [21.60962933778386, 59.6733285308083], [21.523137894759746, 59.67968976219567], [21.436613753238472, 59.685994074722224], [21.350057186822486, 59.69224143258393], [21.26346846983437, 59.69843180027091], [21.176847877311655, 59.70456514256841], [21.090195685001557, 59.71064142455772], [21.003512169355737, 59.71666061161721], [20.916797607524952, 59.72262266942321], [20.830052277353754, 59.72852756395097], [20.743276457375057, 59.734375261475634], [20.656470426804727, 59.740165728573096], [20.56963446553614, 59.745898932121015], [20.48276885413467, 59.75157483929964], [20.39587387383214, 59.75719341759279], [20.308949806521277, 59.7627546347887], [20.2219969347501, 59.76825845898095], [20.135015541716257, 59.773704858569374], [20.04800591126138, 59.77909380226083], [19.960968327865352, 59.78442525907021], [19.87390307664056, 59.78969919832121], [19.786810443326114, 59.794915589647246], [19.699690714282028, 59.800074402992216], [19.612544176483393, 59.80517560861146], [19.52537111751443, 59.810219177072476], [19.438171825562662, 59.81520507925586], [19.350946589412864, 59.82013328635601], [19.263695698441158, 59.82500376988202], [19.176419442608946, 59.829816501658435], [19.089118112456877, 59.83457145382607], [19.001791999098764, 59.83926859884277], [18.914441394215466, 59.84390790948424], [18.827066590048737, 59.84848935884473], [18.73966787939507, 59.85301292033787], [18.65224555559944, 59.85747856769738], [18.564799912549123, 59.86188627497788], [18.477331244667376, 59.866236016555504], [18.38983984690718, 59.87052776712877], [18.302326014744864, 59.87476150171917], [18.214790044173792, 59.878937195671995], [18.12723223169792, 59.883054824656945], [18.03965287432544, 59.88711436466887], [17.952052269562284, 59.891115792028465], [17.86443071540567, 59.89505908338292], [17.7767885103376, 59.898944215706564], [17.689125953318324, 59.902771166301605], [17.60144334377979, 59.90653991279868], [17.513740981619048, 59.9102504331576], [17.426019167191654, 59.913902705667894], [17.338278201305027, 59.91749670894948], [17.250518385211777, 59.92103242195326], [17.162740020603035, 59.92450982396171], [17.07494340960172, 59.92792889458956], [16.98712885475582, 59.931289613784266], [16.89929665903163, 59.934591961826655], [16.811447125806936, 59.9378359193315], [16.723580558864242, 59.94102146724803], [16.635697262383918, 59.944148586860535], [16.547797540937342, 59.947217259788864], [16.459881699480036, 59.95022746798901], [16.371950043344743, 59.95317919375355], [16.284002878234524, 59.95607241971224], [16.196040510215813, 59.95890712883248], [16.108063245711442, 59.96168330441982], [16.020071391493648, 59.964400930118416], [15.9320652546771, 59.96705998991153], [15.844045142711838, 59.969660468122015], [15.756011363376244, 59.97220234941274], [15.667964224769982, 59.974685618787035], [15.579904035306898, 59.977110261589125], [15.491831103707938, 59.979476263504644], [15.403745738994026, 59.98178361056085]]]}, "properties": {"label": "55.842.129.407,55 m²", "geodesic": true, "originalGeom": {"type": "Polygon", "coordinates": [[[15.403745738994022, 59.98178361056085], [22.91839417649402, 61.67355626132541], [24.017026988994022, 59.4722594114112], [15.403745738994022, 59.98178361056085]]]}, "length": 1186095.99, "lengthUom": "m", "lengthTargetUom": "m", "area": 55842129407.55051, "areaUom": "sqm", "areaTargetUom": "sqm", "type": "measurement", "measureType": "area", "id": "f9af08e3-d7be-11ee-b078-79069145e96a", "annotationType": "Polygon", "name": "area", "annotationLayerId": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "annotationLayerTitle": "Measure", "annotationLayerDescription": "Annotations created from measurements"}, "id": "f9af08e3-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [19.16106995774402, 60.838858130180036]}, "properties": {"type": "segment", "label": "448.297,68 m", "id": "f9af08e4-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a", "annotationLayerId": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "annotationLayerTitle": "Measure", "annotationLayerDescription": "Annotations created from measurements"}, "id": "f9af08e4-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.46771058274402, 60.59165716667119]}, "properties": {"type": "segment", "label": "252.015,03 m", "id": "f9af08e5-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a", "annotationLayerId": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "annotationLayerTitle": "Measure", "annotationLayerDescription": "Annotations created from measurements"}, "id": "f9af08e5-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [19.710386363994022, 59.727991846805935]}, "properties": {"type": "segment", "label": "485.783,29 m", "id": "f9af08e6-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a", "annotationLayerId": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "annotationLayerTitle": "Measure", "annotationLayerDescription": "Annotations created from measurements"}, "id": "f9af08e6-d7be-11ee-b078-79069145e96a"}], "annotations": [{"id": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "style": {"format": "geostyler", "body": {"name": "", "rules": [{"ruleId": "f9af08e7-d7be-11ee-b078-79069145e96a", "name": "Start position", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08e8-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "startPoint"}, "wellKnownName": "Circle", "color": "#008000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08e9-d7be-11ee-b078-79069145e96a", "name": "End position", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08ea-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "endPoint"}, "wellKnownName": "Circle", "color": "#ff0000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08eb-d7be-11ee-b078-79069145e96a", "name": "", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08ec-d7be-11ee-b078-79069145e96a", "kind": "Line", "msGeometry": {"name": "lineToArc"}, "color": "#FF9548", "width": 3, "opacity": 1, "cap": "round", "join": "round", "msClampToGround": false}]}, {"ruleId": "f9af08ed-d7be-11ee-b078-79069145e96a", "name": "Segment labels", "filter": ["==", "measureId", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08ee-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 10, "fontStyle": "italic", "fontWeight": "normal", "haloColor": "#444444", "haloWidth": 0.5, "allowOverlap": true, "offset": [0, 0], "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1}]}, {"ruleId": "f9af08ef-d7be-11ee-b078-79069145e96a", "name": "Measurement label", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f0-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 13, "fontStyle": "normal", "fontWeight": "bold", "haloColor": "#FFFFFF", "haloWidth": 3, "allowOverlap": true, "anchor": "bottom", "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1, "offset": [0, 0], "msGeometry": {"name": "endPoint"}}]}, {"ruleId": "f9af08f1-d7be-11ee-b078-79069145e96a", "name": "Start position", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08f2-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "startPoint"}, "wellKnownName": "Circle", "color": "#008000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08f3-d7be-11ee-b078-79069145e96a", "name": "End position", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08f4-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "endPoint"}, "wellKnownName": "Circle", "color": "#ff0000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08f5-d7be-11ee-b078-79069145e96a", "name": "Area measurement", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f6-d7be-11ee-b078-79069145e96a", "kind": "Fill", "msGeometry": {"name": "lineToArc"}, "color": "#ffffff", "fillOpacity": 0.5, "outlineColor": "#33A8FF", "outlineOpacity": 1, "outlineWidth": 3, "msClassificationType": "both", "msClampToGround": false}]}, {"ruleId": "f9af08f7-d7be-11ee-b078-79069145e96a", "name": "Segment labels", "filter": ["==", "measureId", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f8-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 10, "fontStyle": "italic", "fontWeight": "normal", "haloColor": "#444444", "haloWidth": 0.5, "allowOverlap": true, "offset": [0, 0], "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1}]}, {"ruleId": "f9af08f9-d7be-11ee-b078-79069145e96a", "name": "Measurement label", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08fa-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 13, "fontStyle": "normal", "fontWeight": "bold", "haloColor": "#FFFFFF", "haloWidth": 3, "allowOverlap": true, "anchor": "bottom", "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1, "offset": [0, 0], "msGeometry": {"name": "endPoint"}}]}]}}}]}; + +export const annotationsTestFromGeoJson = [{"id": "annotations:f9af08e0-d7be-11ee-b078-79069145e96a", "style": {"format": "geostyler", "body": {"name": "", "rules": [{"ruleId": "f9af08e7-d7be-11ee-b078-79069145e96a", "name": "Start position", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08e8-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "startPoint"}, "wellKnownName": "Circle", "color": "#008000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08e9-d7be-11ee-b078-79069145e96a", "name": "End position", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08ea-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "endPoint"}, "wellKnownName": "Circle", "color": "#ff0000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08eb-d7be-11ee-b078-79069145e96a", "name": "", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08ec-d7be-11ee-b078-79069145e96a", "kind": "Line", "msGeometry": {"name": "lineToArc"}, "color": "#FF9548", "width": 3, "opacity": 1, "cap": "round", "join": "round", "msClampToGround": false}]}, {"ruleId": "f9af08ed-d7be-11ee-b078-79069145e96a", "name": "Segment labels", "filter": ["==", "measureId", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08ee-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 10, "fontStyle": "italic", "fontWeight": "normal", "haloColor": "#444444", "haloWidth": 0.5, "allowOverlap": true, "offset": [0, 0], "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1}]}, {"ruleId": "f9af08ef-d7be-11ee-b078-79069145e96a", "name": "Measurement label", "filter": ["==", "id", "f9af08e1-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f0-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 13, "fontStyle": "normal", "fontWeight": "bold", "haloColor": "#FFFFFF", "haloWidth": 3, "allowOverlap": true, "anchor": "bottom", "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1, "offset": [0, 0], "msGeometry": {"name": "endPoint"}}]}, {"ruleId": "f9af08f1-d7be-11ee-b078-79069145e96a", "name": "Start position", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08f2-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "startPoint"}, "wellKnownName": "Circle", "color": "#008000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08f3-d7be-11ee-b078-79069145e96a", "name": "End position", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "symbolizers": [{"symbolizerId": "f9af08f4-d7be-11ee-b078-79069145e96a", "kind": "Mark", "msGeometry": {"name": "endPoint"}, "wellKnownName": "Circle", "color": "#ff0000", "fillOpacity": 1, "radius": 3, "rotate": 0, "msBringToFront": true, "msHeightReference": "none"}]}, {"ruleId": "f9af08f5-d7be-11ee-b078-79069145e96a", "name": "Area measurement", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f6-d7be-11ee-b078-79069145e96a", "kind": "Fill", "msGeometry": {"name": "lineToArc"}, "color": "#ffffff", "fillOpacity": 0.5, "outlineColor": "#33A8FF", "outlineOpacity": 1, "outlineWidth": 3, "msClassificationType": "both", "msClampToGround": false}]}, {"ruleId": "f9af08f7-d7be-11ee-b078-79069145e96a", "name": "Segment labels", "filter": ["==", "measureId", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08f8-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 10, "fontStyle": "italic", "fontWeight": "normal", "haloColor": "#444444", "haloWidth": 0.5, "allowOverlap": true, "offset": [0, 0], "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1}]}, {"ruleId": "f9af08f9-d7be-11ee-b078-79069145e96a", "name": "Measurement label", "filter": ["==", "id", "f9af08e3-d7be-11ee-b078-79069145e96a"], "mandatory": true, "symbolizers": [{"symbolizerId": "f9af08fa-d7be-11ee-b078-79069145e96a", "kind": "Text", "color": "#000000", "size": 13, "fontStyle": "normal", "fontWeight": "bold", "haloColor": "#FFFFFF", "haloWidth": 3, "allowOverlap": true, "anchor": "bottom", "msBringToFront": true, "msHeightReference": "none", "label": "{{label}}", "font": ["Arial"], "opacity": 1, "offset": [0, 0], "msGeometry": {"name": "endPoint"}}]}]}}, "title": "Measure", "description": "Annotations created from measurements", "type": "vector", "visibility": true, "rowViewer": "annotations", "features": [{"type": "Feature", "geometry": {"type": "LineString", "coordinates": [[9.866636363994022, 61.527248291386314], [17.249448863994022, 63.09907980217878]]}, "properties": {"label": "419.255,7 m", "geodesic": true, "length": 419255.701, "lengthUom": "m", "lengthTargetUom": "m", "type": "measurement", "measureType": "length", "id": "f9af08e1-d7be-11ee-b078-79069145e96a", "annotationType": "LineString", "name": "length"}, "id": "f9af08e1-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [13.498714228074927, 62.37000869405188]}, "properties": {"type": "segment", "label": "419.255,7 m", "id": "f9af08e2-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e1-d7be-11ee-b078-79069145e96a"}, "id": "f9af08e2-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[15.403745738994022, 59.98178361056085], [22.91839417649402, 61.67355626132541], [24.017026988994022, 59.4722594114112], [15.403745738994022, 59.98178361056085]]]}, "properties": {"label": "55.842.129.407,55 m²", "geodesic": true, "length": 1186095.99, "lengthUom": "m", "lengthTargetUom": "m", "area": 55842129407.55051, "areaUom": "sqm", "areaTargetUom": "sqm", "type": "measurement", "measureType": "area", "id": "f9af08e3-d7be-11ee-b078-79069145e96a", "annotationType": "Polygon", "name": "area"}, "id": "f9af08e3-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [19.16106995774402, 60.838858130180036]}, "properties": {"type": "segment", "label": "448.297,68 m", "id": "f9af08e4-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a"}, "id": "f9af08e4-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.46771058274402, 60.59165716667119]}, "properties": {"type": "segment", "label": "252.015,03 m", "id": "f9af08e5-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a"}, "id": "f9af08e5-d7be-11ee-b078-79069145e96a"}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [19.710386363994022, 59.727991846805935]}, "properties": {"type": "segment", "label": "485.783,29 m", "id": "f9af08e6-d7be-11ee-b078-79069145e96a", "measureId": "f9af08e3-d7be-11ee-b078-79069145e96a"}, "id": "f9af08e6-d7be-11ee-b078-79069145e96a"}]}]; diff --git a/web/client/utils/MeasurementUtils.js b/web/client/utils/MeasurementUtils.js index e41fba4a00..630cbed1ef 100644 --- a/web/client/utils/MeasurementUtils.js +++ b/web/client/utils/MeasurementUtils.js @@ -183,7 +183,7 @@ export const getGeomTypeSelected = (features = []) =>{ })); }; -const getMeasureType = (feature) => { +export const getMeasureType = (feature) => { if (feature?.properties?.measureType) { return feature.properties.measureType; } @@ -257,7 +257,7 @@ const convertMeasureToFeatureCollection = (geometricFeatures, textLabels = [], u properties: { ...properties, label: infoLabelText, - geodesic: measureType === MeasureTypes.LENGTH, + geodesic: measureType === MeasureTypes.LENGTH || measureType === MeasureTypes.AREA, ...parseProperties(values, uom), type: [MeasureTypes.POINT_COORDINATES].includes(measureType) ? 'position' @@ -422,6 +422,9 @@ export const convertMeasuresToAnnotation = (geometricFeatures, textLabels, uom, { symbolizerId: uuidv1(), kind: 'Fill', + msGeometry: { + name: 'lineToArc' + }, color: '#ffffff', fillOpacity: 0.5, outlineColor: '#33A8FF', @@ -543,7 +546,21 @@ export const convertMeasuresToGeoJSON = (geometricFeatures, textLabels = [], uom return { type: 'FeatureCollection', - features, + msType: MEASURE_TYPE, + features: features.map(ft => { + const measureType = getMeasureType(ft); + return measureType === MeasureTypes.LENGTH || measureType === MeasureTypes.AREA ? { + ...ft, + geometry: { + ...ft.geometry, + coordinates: measureType === MeasureTypes.LENGTH ? transformLineToArcs(ft.geometry.coordinates) : ft.geometry.coordinates.map(transformLineToArcs) + }, + properties: { + ...ft.properties, + ...(measureType === MeasureTypes.LENGTH || measureType === MeasureTypes.AREA ? { originalGeom: ft.geometry} : {}) + } + } : ft; + }), style: { metadata: { editorType: 'visual' }, format: 'geostyler', diff --git a/web/client/utils/__tests__/MeasurementUtils-test.js b/web/client/utils/__tests__/MeasurementUtils-test.js index 2a26646f6b..d8b3e8c735 100644 --- a/web/client/utils/__tests__/MeasurementUtils-test.js +++ b/web/client/utils/__tests__/MeasurementUtils-test.js @@ -7,10 +7,12 @@ */ import expect from 'expect'; +import find from 'lodash/find'; import { convertMeasuresToAnnotation, getGeomTypeSelected, - convertMeasuresToGeoJSON + convertMeasuresToGeoJSON, + getMeasureType } from '../MeasurementUtils'; import { MeasureTypes, defaultUnitOfMeasure } from '../MeasureUtils'; @@ -57,6 +59,49 @@ describe('MeasurementUtils', () => { ] } }]; + it('getMeasureType', () => { + const tests = [ + { + source: {}, + expectedValue: null + }, + { + source: { + properties: { + measureType: "measureType" + } + }, + expectedValue: "measureType" + }, + { + source: { + properties: { + values: [{type: "bearing"}] + } + }, + expectedValue: MeasureTypes.BEARING + }, + { + source: { + properties: { + values: [{type: "length"}] + } + }, + expectedValue: MeasureTypes.LENGTH + }, + { + source: { + properties: { + values: [{type: "length"}, {type: "area"}] + } + }, + expectedValue: MeasureTypes.AREA + } + + ]; + tests.forEach(t => expect(getMeasureType(t.source)).toEqual(t.expectedValue)); + + }); it('convertMeasuresToAnnotation with LineString', () => { const layer = convertMeasuresToAnnotation(features, [], testUom, 'id'); expect(layer).toBeTruthy(); @@ -86,6 +131,45 @@ describe('MeasurementUtils', () => { 'Mark', 'Mark', 'Line', 'Text', 'Text' ]); }); + it('convertMeasuresToAnnotation with Polygon', () => { + const fts = [{"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[10.042417613994017, 53.9617045912569], [21.29241761399402, 57.23667168428492], [22.522886363994022, 53.17884325605559], [10.042417613994017, 53.9617045912569]]], "textLabels": [{"text": "793.737,01 m", "position": [15.667417613994019, 55.633387330220785]}, {"text": "457.894,01 m", "position": [21.90765198899402, 55.25951976945266]}, {"text": "827.598,36 m", "position": [16.28265198899402, 53.57208559899865]}]}, "properties": {"values": [{"value": 175074750490.87378, "formattedValue": "175.074.750.490,87 m²", "position": [18.148330256039472, 55.25951976945266], "type": "area"}, {"value": 2079229.382, "formattedValue": "2.079.229,38 m", "position": [10.042417613994017, 53.9617045912569], "uom": {"length": {"unit": "m", "label": "m", "value": "m"}, "area": {"unit": "sqm", "label": "m²", "value": "sqm"}, "bearing": {"unit": "deg", "label": "°", "value": "deg"}, "POLYLINE_DISTANCE_3D": {"unit": "m", "label": "m", "value": "m"}, "AREA_3D": {"unit": "sqm", "label": "m²", "value": "sqm"}, "POINT_COORDINATES": {"unit": "m", "label": "m", "value": "m"}, "HEIGHT_FROM_TERRAIN": {"unit": "m", "label": "m", "value": "m"}, "SLOPE": {"unit": "deg", "label": "°", "value": "deg"}, "ANGLE_3D": {"unit": "deg", "label": "°", "value": "deg"}}, "type": "length"}]}}]; + const layer = convertMeasuresToAnnotation(fts, [{"text": "793.737,01 m", "position": [15.667417613994019, 55.633387330220785], "type": "Polygon", "textId": 0}, {"text": "457.894,01 m", "position": [21.90765198899402, 55.25951976945266], "type": "Polygon", "textId": 0}, {"text": "827.598,36 m", "position": [16.28265198899402, 53.57208559899865], "type": "Polygon", "textId": 0}], testUom, 'id'); + expect(layer).toBeTruthy(); + expect(layer.id).toBe('annotations:id'); + expect(layer.type).toBe('vector'); + expect(layer.title).toBe('Measure'); + expect(layer.rowViewer).toBe('annotations'); + expect(layer.features.length).toBe(4); + expect(layer.features[0].type).toBe('Feature'); + expect(layer.features[0].geometry).toBeTruthy(); + expect(layer.features[0].geometry.type).toBe('Polygon'); + expect(layer.features[0].geometry.coordinates).toEqual([ [ [ 10.042417613994017, 53.9617045912569 ], [ 21.29241761399402, 57.23667168428492 ], [ 22.522886363994022, 53.17884325605559 ], [ 10.042417613994017, 53.9617045912569 ] ] ]); + const { id, ...properties } = layer.features[0].properties; + expect(properties).toEqual({ + label: '175.074.750.490,87 m²', + geodesic: true, + length: 2079229.382, + lengthUom: 'm', + lengthTargetUom: 'm', + area: 175074750490.87378, + areaUom: 'sqm', + areaTargetUom: 'sqm', + type: 'measurement', + measureType: 'area', + annotationType: 'Polygon', + name: 'area' } + ); + expect(layer.style.body.rules.length).toBe(5); + expect(layer.style.body.rules.map(({ symbolizers }) => symbolizers[0].kind)).toEqual([ 'Mark', 'Mark', 'Fill', 'Text', 'Text' ]); + layer.style.body.rules.forEach(rule => { + const fill = find(rule.symbolizers, symb => symb.kind === "Fill"); + if (fill) { + expect(fill.msGeometry).toEqual({ + name: 'lineToArc' + }); + } + }); + }); it('getGeomTypeSelected', ()=>{ const geomTypeSelected = getGeomTypeSelected(features); @@ -607,6 +691,7 @@ describe('MeasurementUtils', () => { label: '1,953.32 m', geodesic: true, length: 1953.316, + originalGeom: { type: 'LineString', coordinates: [ [ 9.194719791412354, 45.47215472687304 ], [ 9.1780686378479, 45.45903193872102 ] ] }, lengthUom: 'm', lengthTargetUom: 'm', type: 'measurement', @@ -794,7 +879,8 @@ describe('MeasurementUtils', () => { const { id, ...measurementProperties } = measureFeature.properties; expect(measurementProperties).toEqual({ label: '1,644,850.69 m²', - geodesic: false, + geodesic: true, + originalGeom: { type: 'Polygon', coordinates: [ [ [ 9.193453788757324, 45.479723019275006 ], [ 9.164185523986816, 45.46196677235737 ], [ 9.20529842376709, 45.47394532919275 ], [ 9.193453788757324, 45.479723019275006 ] ] ] }, length: 7614.5289999999995, lengthUom: 'm', lengthTargetUom: 'm', diff --git a/web/client/utils/styleparser/CesiumStyleParser.js b/web/client/utils/styleparser/CesiumStyleParser.js index 479e6c0fd3..654a9b4034 100644 --- a/web/client/utils/styleparser/CesiumStyleParser.js +++ b/web/client/utils/styleparser/CesiumStyleParser.js @@ -849,8 +849,10 @@ const symbolizerToPrimitives = { }] : []) ]; }, - Fill: ({ parsedSymbolizer, globalOpacity }) => { + Fill: ({ parsedSymbolizer, feature, globalOpacity }) => { const isExtruded = !parsedSymbolizer.msClampToGround && !!parsedSymbolizer.msExtrudedHeight; + const geometryFunction = getGeometryFunction(parsedSymbolizer); + const additionalOptions = geometryFunction ? geometryFunction(feature) : {}; return [ { type: 'polygon', @@ -870,7 +872,8 @@ const symbolizerToPrimitives = { Cesium.ClassificationType.BOTH} ), arcType: parsedSymbolizer.msClampToGround ? Cesium.ArcType.GEODESIC - : undefined + : undefined, + ...additionalOptions } } }, @@ -902,7 +905,8 @@ const symbolizerToPrimitives = { Cesium.ClassificationType.BOTH} ), arcType: parsedSymbolizer.msClampToGround ? Cesium.ArcType.GEODESIC - : Cesium.ArcType.NONE + : Cesium.ArcType.NONE, + ...additionalOptions } } } diff --git a/web/client/utils/styleparser/GeometryFunctionsUtils.js b/web/client/utils/styleparser/GeometryFunctionsUtils.js index b5a7303531..342edb7aa4 100644 --- a/web/client/utils/styleparser/GeometryFunctionsUtils.js +++ b/web/client/utils/styleparser/GeometryFunctionsUtils.js @@ -101,7 +101,7 @@ export const geometryFunctionsLibrary = { }; }, lineToArc: () => { - return { arcType: Cesium.ArcType.GEODESIC }; + return { arcType: Cesium.ArcType.GEODESIC, perPositionHeight: undefined }; }, startPoint: (feature) => { const { positions } = getPositions(feature); @@ -125,6 +125,7 @@ export const geometryFunctionsLibrary = { * @param {object} options * @param {class} options.Point ol/geom/Point class * @param {class} options.LineString ol/geom/LineString class + * @param {class} options.Polygon ol/geom/Polygon class * @param {class} options.GeoJSON ol/format/GeoJSON class * @param {function} options.getCenter from ol/extent * @returns {function} geometry function utils for OpenLayers @@ -132,6 +133,7 @@ export const geometryFunctionsLibrary = { openlayers: ({ Point, LineString, + Polygon, GeoJSON, getCenter }) => { @@ -176,6 +178,17 @@ export const geometryFunctionsLibrary = { return [point.x, point .y]; })); } + if (type === 'Polygon') { + let coordinates = feature.getGeometry().getCoordinates()[0]; // not managing holes + coordinates = transformLineToArcs(coordinates.map(c => { + const point = reproject(c, mapProjection, 'EPSG:4326'); + return [point.x, point .y]; + })); + return new Polygon([coordinates.map(c => { + const point = reproject(c, 'EPSG:4326', mapProjection); + return [point.x, point .y]; + })]); + } return feature.getGeometry(); }, startPoint: () => (feature) => { @@ -232,6 +245,9 @@ export const geometryFunctionsLibrary = { if (feature.geometry.type === 'LineString') { return transformLineToArcs(feature.geometry.coordinates); } + if (feature.geometry.type === 'Polygon') { + return feature.geometry.coordinates.map(transformLineToArcs); + } return null; }, startPoint: (feature) => { diff --git a/web/client/utils/styleparser/LeafletStyleParser.js b/web/client/utils/styleparser/LeafletStyleParser.js index 32aceba0e3..fdaa72b2b5 100644 --- a/web/client/utils/styleparser/LeafletStyleParser.js +++ b/web/client/utils/styleparser/LeafletStyleParser.js @@ -300,7 +300,8 @@ function getStyleFuncFromRules({ rules: geoStylerStyleRules = [] }) { return style; } if (firstValidSymbolizer.kind === 'Fill') { - return { + const geometryFunction = getGeometryFunction(firstValidSymbolizer); + const style = { fill: true, stroke: true, fillColor: firstValidSymbolizer.color, @@ -310,6 +311,17 @@ function getStyleFuncFromRules({ rules: geoStylerStyleRules = [] }) { weight: firstValidSymbolizer.outlineWidth ?? 0, ...(firstValidSymbolizer.outlineDasharray && { dashArray: firstValidSymbolizer.outlineDasharray.join(' ') }) }; + if (geometryFunction && feature.geometry.type === 'Polygon') { + const coordinates = geometryFunction(feature); + const geoJSONLayer = L.geoJSON({ ...feature, geometry: { type: 'Polygon', coordinates }}); + geoJSONLayer.setStyle(style); + layer._msAdditionalLayers.push(geoJSONLayer); + layer.addLayer(geoJSONLayer); + return { + stroke: false, + fill: false + }; + } } return { stroke: false, diff --git a/web/client/utils/styleparser/OLStyleParser.js b/web/client/utils/styleparser/OLStyleParser.js index d6906b8dae..c6a5d6cb2a 100644 --- a/web/client/utils/styleparser/OLStyleParser.js +++ b/web/client/utils/styleparser/OLStyleParser.js @@ -69,6 +69,7 @@ import { geometryFunctionsLibrary } from './GeometryFunctionsUtils'; const getGeometryFunction = geometryFunctionsLibrary.openlayers({ Point: OlGeomPoint, LineString: OlGeomLineString, + Polygon: OlGeomPolygon, GeoJSON, getCenter }); @@ -716,6 +717,7 @@ export class OlStyleParser { symbolizer[key] = expressionsUtils.evaluateFunction(symbolizer[key], feat); } } + const geometryFunc = getGeometryFunction(symbolizer, feat, this._getMap()); const color = symbolizer.color; // fillOpacity is needed for legacy support @@ -741,6 +743,7 @@ export class OlStyleParser { }) : undefined; const olStyle = new this.OlStyleConstructor({ + ...geometryFunc, fill, stroke }); diff --git a/web/client/utils/styleparser/PrintStyleParser.js b/web/client/utils/styleparser/PrintStyleParser.js index 7e6369b62b..97981556c3 100644 --- a/web/client/utils/styleparser/PrintStyleParser.js +++ b/web/client/utils/styleparser/PrintStyleParser.js @@ -215,9 +215,9 @@ export const getPrintStyleFuncFromRules = (geoStylerStyle) => { let geometry = feature.geometry; const geometryFunction = getGeometryFunction(symbolizer); - if (geometryFunction && geometryType === 'LineString') { + if (geometryFunction && (geometryType === 'LineString' || geometryType === 'Polygon')) { geometry = { - type: 'LineString', + type: geometryType, coordinates: geometryFunction(feature) }; } diff --git a/web/client/utils/styleparser/__tests__/LeafletStyleParser-test.js b/web/client/utils/styleparser/__tests__/LeafletStyleParser-test.js index 38377fc0b4..4185686ebf 100644 --- a/web/client/utils/styleparser/__tests__/LeafletStyleParser-test.js +++ b/web/client/utils/styleparser/__tests__/LeafletStyleParser-test.js @@ -62,14 +62,8 @@ describe('LeafletStyleParser', () => { } }; expect(leafletStyleFunc(feature)).toEqual({ - fill: true, - stroke: true, - fillColor: '#ff0000', - fillOpacity: 0.5, - color: '#00ff00', - opacity: 0.25, - weight: 2, - dashArray: '10 10' + fill: false, + stroke: false }); done(); }).catch(done); @@ -403,14 +397,8 @@ describe('LeafletStyleParser', () => { } }; expect(leafletStyleFunc(feature)).toEqual({ - fill: true, - stroke: true, - fillColor: '#ff0000', - fillOpacity: 0.5, - color: '#00ff00', - opacity: 0.25, - weight: 2, - dashArray: '10 10' + fill: false, + stroke: false }); done(); }).catch(done);