Skip to content

Commit

Permalink
Merge pull request #1072 from geoadmin/fix-PB-896-gpx-simplify-only-p…
Browse files Browse the repository at this point in the history
…rofile

PB-896 : show un-simplified GPX track
  • Loading branch information
pakb authored Sep 19, 2024
2 parents 874029c + 1d12658 commit 4da8a85
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 7 deletions.
31 changes: 31 additions & 0 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 @@ -61,6 +61,7 @@
"@turf/helpers": "^7.1.0",
"@turf/nearest-point": "^7.1.0",
"@turf/point-to-line-distance": "^7.1.0",
"@turf/simplify": "^7.1.0",
"animate.css": "^4.1.1",
"axios": "^1.7.5",
"bootstrap": "^5.3.3",
Expand Down
14 changes: 13 additions & 1 deletion src/modules/infobox/components/ShowGeometryProfileButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { toRefs } from 'vue'
import { useI18n } from 'vue-i18n'
import { useStore } from 'vuex'
import LayerFeature from '@/api/features/LayerFeature.class'
import SelectableFeature from '@/api/features/SelectableFeature.class'
import LayerTypes from '@/api/layers/LayerTypes.enum'
const dispatcher = { dispatcher: 'ShowGeometryProfileButton.vue' }
Expand All @@ -20,7 +22,17 @@ const i18n = useI18n()
const store = useStore()
function showProfile() {
store.dispatch('setProfileFeature', { feature: feature.value, ...dispatcher })
let simplifyGeometry = false
if (feature.value instanceof LayerFeature) {
// PB-800 : to avoid a coastline paradox we simplify the geometry of GPXs
// as they might be coming directly from a GPS device (meaning polluted with GPS uncertainty/error)
simplifyGeometry = feature.value.layer.type === LayerTypes.GPX
}
store.dispatch('setProfileFeature', {
feature: feature.value,
simplifyGeometry,
...dispatcher,
})
}
</script>

Expand Down
27 changes: 24 additions & 3 deletions src/store/modules/features.store.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import simplify from '@turf/simplify'
import { containsCoordinate } from 'ol/extent'
import { toRaw } from 'vue'

Expand All @@ -9,9 +10,11 @@ import getProfile from '@/api/profile/profile.api'
import {
DEFAULT_FEATURE_COUNT_RECTANGLE_SELECTION,
DEFAULT_FEATURE_COUNT_SINGLE_POINT,
GPX_GEOMETRY_SIMPLIFICATION_TOLERANCE,
} from '@/config/map.config'
import { flattenExtent } from '@/utils/coordinates/coordinateUtils'
import { allStylingColors, allStylingSizes } from '@/utils/featureStyleUtils'
import { transformIntoTurfEquivalent } from '@/utils/geoJsonUtils'
import log from '@/utils/logging'

/** @param {SelectableFeature} feature */
Expand Down Expand Up @@ -601,9 +604,14 @@ export default {
* @param {SelectableFeature | null} feature A feature which has a LineString or Polygon
* geometry, and for which we want to show a height profile (or `null` if the profile
* should be cleared/hidden)
* @param {Boolean} simplifyGeometry If set to true, the geometry of the feature will be
* simplified before being sent to the profile backend. This is useful in case the data
* comes from an unfiltered GPS source (GPX track), and not simplifying the track could
* lead to a coastal paradox (meaning the hiking time will be way of the charts because of
* all the small jumps due to GPS errors)
* @param dispatcher
*/
setProfileFeature(store, { feature = null, dispatcher }) {
setProfileFeature(store, { feature = null, simplifyGeometry = false, dispatcher }) {
const { state, commit, rootState } = store
if (feature === null) {
commit('setProfileFeature', { feature: null, dispatcher })
Expand All @@ -615,9 +623,22 @@ export default {
commit('setProfileFeature', { feature: feature, dispatcher })
commit('setProfileData', { data: null, dispatcher })
if (feature?.geometry) {
let coordinates = [...feature.geometry.coordinates]
let coordinates
if (simplifyGeometry) {
// using TurfJS instead of OL here, as we receive geometry as GeoJSON.
// Using OL would mean parsing all features as OL features once again.
// Both OL and TurfJS use a Ramer-Douglas-Peucker algorithm, so output will be very similar
const turfGeom = transformIntoTurfEquivalent(feature.geometry)
coordinates = [
...simplify(turfGeom, {
tolerance: GPX_GEOMETRY_SIMPLIFICATION_TOLERANCE,
}).geometry.coordinates,
]
} else {
coordinates = [...feature.geometry.coordinates]
}
// unwrapping the first set of coordinates if they come from a multi-feature type geometry
if (coordinates[0].some((coordinage) => Array.isArray(coordinage))) {
if (coordinates[0].some((coordinate) => Array.isArray(coordinate))) {
coordinates = coordinates[0]
}
getProfile(coordinates, rootState.position.projection)
Expand Down
3 changes: 0 additions & 3 deletions src/utils/gpxUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import bbox from '@turf/bbox'
import { isEmpty as isExtentEmpty } from 'ol/extent'
import GPX from 'ol/format/GPX'

import { GPX_GEOMETRY_SIMPLIFICATION_TOLERANCE } from '@/config/map.config'
import CoordinateSystem from '@/utils/coordinates/CoordinateSystem.class'
import { WGS84 } from '@/utils/coordinates/coordinateSystems'
import { gpxStyles } from '@/utils/styleUtils'
Expand Down Expand Up @@ -46,8 +45,6 @@ export function parseGpx(gpxData, projection) {
})
features.forEach((feature) => {
const geom = feature.getGeometry()
// PB-800 : to avoid a coastline paradox we simplify the geometry of GPXs
feature.setGeometry(geom.simplify(GPX_GEOMETRY_SIMPLIFICATION_TOLERANCE))
feature.setStyle(gpxStyles[geom.getType()])
})
return features
Expand Down

0 comments on commit 4da8a85

Please sign in to comment.