Skip to content

Commit

Permalink
PB-875: select kml gpx and geojson features with drag box
Browse files Browse the repository at this point in the history
  • Loading branch information
sommerfe committed Oct 14, 2024
1 parent f477497 commit 09ad88e
Show file tree
Hide file tree
Showing 4 changed files with 268 additions and 7 deletions.
187 changes: 185 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"@turf/area": "^7.1.0",
"@turf/bbox": "^7.1.0",
"@turf/boolean-contains": "^7.1.0",
"@turf/boolean-intersects": "^7.1.0",
"@turf/boolean-point-in-polygon": "^7.1.0",
"@turf/buffer": "^7.1.0",
"@turf/centroid": "^7.1.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { booleanIntersects } from '@turf/boolean-intersects'
import { lineString, point, polygon } from '@turf/helpers'
import { platformModifierKeyOnly } from 'ol/events/condition'
import GeoJSON from 'ol/format/GeoJSON'
import { LineString, Point, Polygon } from 'ol/geom'
import { DragBox } from 'ol/interaction'
import { useStore } from 'vuex'

import LayerTypes from '@/api/layers/LayerTypes.enum'
import { ClickInfo } from '@/store/modules/map.store'
import { parseGpx } from '@/utils/gpxUtils'
import { parseKml } from '@/utils/kmlUtils'
import { createLayerFeature } from '@/utils/layerUtils'

const dispatcher = {
dispatcher: 'useDragBoxSelect.composable',
Expand All @@ -20,16 +28,56 @@ export function useDragBoxSelect() {
)
dragBoxSelect.on('boxend', () => {
const selectExtent = dragBoxSelect.getGeometry()?.getExtent()
if (selectExtent?.length !== 4) return

if (selectExtent?.length === 4) {
store.dispatch('click', {
clickInfo: new ClickInfo({ coordinate: selectExtent }),
...dispatcher,
const dragBox = polygon(dragBoxSelect.getGeometry()?.getCoordinates())
const visibleLayers = store.getters.visibleLayers.filter((layer) =>
[LayerTypes.GEOJSON, LayerTypes.GPX, LayerTypes.KML].includes(layer.type)
)
const features = visibleLayers
.flatMap((layer) => {
if (layer.type === LayerTypes.KML) {
const kmlFeatures = parseKml(layer, store.state.position.projection, [])
return kmlFeatures.map((feature) => ({ feature: feature, layer }))
}
if (layer.type === LayerTypes.GPX) {
const gpxFeatures = parseGpx(layer.gpxData, store.state.position.projection, [])
return gpxFeatures.map((feature) => ({ feature: feature, layer }))
}
if (layer.type === LayerTypes.GEOJSON) {
const geojsonFormat = new GeoJSON()
const olFeatures = geojsonFormat.readFeatures(layer.geoJsonData, {
featureProjection: store.state.position.projection.epsg,
})
return olFeatures.map((feature) => ({ feature: feature, layer }))
}
})
}
.filter((result) => {
const geometry = fromOlGeometryToTurfGeometry(result.feature.getGeometry())
return geometry && dragBox && booleanIntersects(dragBox, geometry)
})
.map(({ feature, layer }) => createLayerFeature(feature, layer))

store.dispatch('click', {
clickInfo: new ClickInfo({ coordinate: selectExtent, features: features }),
...dispatcher,
})
})

return {
dragBoxSelect,
}
}

function fromOlGeometryToTurfGeometry(olGeometry) {
if (olGeometry instanceof Point) {
return point(olGeometry.getCoordinates())
}
if (olGeometry instanceof Polygon) {
return polygon(olGeometry.getCoordinates())
}
if (olGeometry instanceof LineString) {
return lineString(olGeometry.getCoordinates())
}
return null
}
29 changes: 29 additions & 0 deletions src/utils/layerUtils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import GeoJSON from 'ol/format/GeoJSON'

import LayerFeature from '@/api/features/LayerFeature.class'
import ExternalWMTSLayer from '@/api/layers/ExternalWMTSLayer.class'
import GeoAdminWMTSLayer from '@/api/layers/GeoAdminWMTSLayer.class'
import LayerTypes from '@/api/layers/LayerTypes.enum.js'
import { getBaseUrlOverride } from '@/config/baseUrl.config'
import { normalizeExtent } from '@/utils/coordinates/coordinateUtils'

/**
* Minimalist description of an active layer. Is useful when parsing layers from the URL, but we do
Expand Down Expand Up @@ -97,3 +101,28 @@ export function indexOfMaxResolution(projection, layerMaxResolution) {
}
return indexOfResolution
}

export function createLayerFeature(olFeature, layer) {
if (!olFeature?.getGeometry()) return null
return new LayerFeature({
layer: layer,
id: olFeature.getId(),
name:
olFeature.get('label') ??
// exception for MeteoSchweiz GeoJSONs, we use the station name instead of the ID
// some of their layers are
// - ch.meteoschweiz.messwerte-niederschlag-10min
// - ch.meteoschweiz.messwerte-lufttemperatur-10min
olFeature.get('station_name') ??
// GPX track feature don't have an ID but have a name !
olFeature.get('name') ??
olFeature.getId(),
data: {
title: olFeature.get('name'),
description: olFeature.get('description'),
},
coordinates: olFeature.getGeometry().getCoordinates(),
geometry: new GeoJSON().writeGeometryObject(olFeature.getGeometry()),
extent: normalizeExtent(olFeature.getGeometry().getExtent()),
})
}

0 comments on commit 09ad88e

Please sign in to comment.