Skip to content

PB-114: Moved utils out of drawing modules #630

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions src/api/features.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ import { Icon as openlayersIcon } from 'ol/style'
import proj4 from 'proj4'

import { API_BASE_URL } from '@/config'
import {
extractOlFeatureCoordinates,
extractOlFeatureGeodesicCoordinates,
} from '@/modules/drawing/lib/drawingUtils'
import { LV95 } from '@/utils/coordinates/coordinateSystems'
import { projExtent } from '@/utils/coordinates/coordinateUtils'
import EventEmitter from '@/utils/EventEmitter.class'
Expand Down Expand Up @@ -349,6 +345,39 @@ export class EditableFeature extends SelectableFeature {
}
}

/**
* Extract OL feature coordinates in format that we support in our application
*
* @param {Feature} feature Openlayer kml feature
* @returns {[[lat, lon]]} Return the coordinate of the feature
*/
export function extractOlFeatureCoordinates(feature) {
let coordinates = feature.getGeometry().getCoordinates()
if (feature.getGeometry().getType() === 'Polygon') {
// in case of a polygon, the coordinates structure is
// [
// [ (poly1)
// [coord1],[coord2]
// ],
// [ (poly2) ...
// ]
// so as we will not have multipoly, we only keep what's defined as poly one
// (we remove the wrapping array that would enable us to have a second polygon)
coordinates = coordinates[0]
}
return coordinates
}

/**
* Extract geodesic coordinates from OL feature
*
* @param {Feature} feature OL feature
* @returns {[[lat, lon]]} Return the geodesic coordinate of the feature
*/
export function extractOlFeatureGeodesicCoordinates(feature) {
return feature.get('geodesic')?.getGeodesicGeom().getCoordinates()[0]
}

/**
* Describe a feature from the backend, so a feature linked to a backend layer (see
* {@link getFeature}) below
Expand Down
7 changes: 2 additions & 5 deletions src/modules/drawing/components/DrawingExporter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@ import { computed, inject, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useStore } from 'vuex'

import {
generateFilename,
generateGpxString,
generateKmlString,
} from '@/modules/drawing/lib/export-utils'
import { generateGpxString, generateKmlString } from '@/modules/drawing/lib/export-utils'
import DropdownButton, { DropdownItem } from '@/utils/components/DropdownButton.vue'
import { generateFilename } from '@/utils/utils'

const exportOptions = [new DropdownItem('kml', 'KML'), new DropdownItem('gpx', 'GPX')]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { computed, inject, nextTick, onBeforeUnmount, onMounted, ref } from 'vue
import { useStore } from 'vuex'

import { EditableFeature } from '@/api/features.api'
import { wrapXCoordinates } from '@/modules/drawing/lib/drawingUtils'
import { editingFeatureStyleFunction, featureStyleFunction } from '@/modules/drawing/lib/style'
import { editingFeatureStyleFunction } from '@/modules/drawing/lib/style'
import useSaveKmlOnChange from '@/modules/drawing/useKmlDataManagement.composable'
import { wrapXCoordinates } from '@/utils/coordinates/coordinateUtils'
import { featureStyleFunction } from '@/utils/featureStyleUtils'
import { GeodesicGeometries } from '@/utils/geodesicManager'
import log from '@/utils/logging'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import ModifyInteraction from 'ol/interaction/Modify'
import { inject, onBeforeUnmount, onMounted } from 'vue'
import { useStore } from 'vuex'

import { DRAWING_HIT_TOLERANCE } from '@/config'
import {
extractOlFeatureCoordinates,
extractOlFeatureGeodesicCoordinates,
} from '@/modules/drawing/lib/drawingUtils'
} from '@/api/features.api'
import { DRAWING_HIT_TOLERANCE } from '@/config'
import { editingVertexStyleFunction } from '@/modules/drawing/lib/style'
import useSaveKmlOnChange from '@/modules/drawing/useKmlDataManagement.composable'
import { segmentExtent, subsegments } from '@/utils/geodesicManager'
Expand Down
115 changes: 0 additions & 115 deletions src/modules/drawing/lib/__tests__/drawingUtils.spec.js

This file was deleted.

124 changes: 1 addition & 123 deletions src/modules/drawing/lib/drawingUtils.js
Original file line number Diff line number Diff line change
@@ -1,126 +1,4 @@
import { wrapX } from 'ol/coordinate'
import { LineString, Point, Polygon } from 'ol/geom'
import { get as getProjection } from 'ol/proj'
import proj4 from 'proj4'

import { LV95 } from '@/utils/coordinates/coordinateSystems'
import { format } from '@/utils/numberUtils'

export function toLv95(input, epsg) {
if (Array.isArray(input[0])) {
return input.map((si) => toLv95(si, epsg))
} else {
return proj4(epsg, LV95.epsg, [input[0], input[1]])
}
}

/**
* Wraps the provided coordinates in the world extents (i.e. the coordinate range that if equivalent
* to the wgs84 [-180, 180))
*
* @param {Array} coordinates The coordinates (or array of coordinates) to wrap
* @param {CoordinateSystem} projection Projection of the coordinates
* @param {boolean} inPlace If false, the original coordinates remain untouched and only a copy is
* modified
* @returns If "inPlace", then the same reference as "coords", else a reference to the modified copy
*/
export function wrapXCoordinates(coordinates, projection, inPlace = false) {
let wrappedCoords = coordinates
if (!inPlace) {
wrappedCoords = wrappedCoords.slice()
}
if (Array.isArray(wrappedCoords[0])) {
return wrappedCoords.map((c) => wrapXCoordinates(c, projection, inPlace))
}
return wrapX(wrappedCoords, getProjection(projection.epsg))
}

/** @param {[number, number]} coo Coordinates */
export function formatPointCoordinates(coo) {
return `${format(coo[0], 0)}, ${format(coo[1], 0)}`
}

export function formatMeters(value, { dim = 1, digits = 2, applyFormat = true } = {}) {
const factor = Math.pow(1000, dim)
let unit = dim === 1 ? 'm' : 'm²'
if (value >= factor) {
unit = dim === 1 ? 'km' : 'km²'
value /= factor
}
value = applyFormat ? format(value, digits) : value.toFixed(digits)
return `${value} ${unit}`
}

export function geometryInfo(type, coordinates, epsg) {
const coos95 = toLv95(coordinates, epsg)
const output = {
type,
}
if (type === Point) {
output.location = formatPointCoordinates(coos95)
} else {
if (type === Polygon) {
const poly = new Polygon(coos95)
output.area = formatMeters(poly.getArea(), { dim: 2 })
const line = new LineString(coos95[0])
output.perimeter = formatMeters(line.getLength())
} else {
const line = new LineString(coos95)
output.length = formatMeters(line.getLength())
}
}
return output
}

/**
* Formats minutes to hours and minutes (if more than one hour) e.g. 1230 -> '20h 30min', 55 ->
* '55min'
*
* @param {Number} minutes
* @returns {string}
*/
export function formatTime(minutes) {
if (isNaN(minutes) || minutes === null) {
return '-'
}
let result = ''
if (minutes >= 60) {
let hours = Math.floor(minutes / 60)
minutes = minutes - hours * 60
result += `${hours}h`
if (minutes > 0) {
result += ` ${minutes}min`
}
} else {
result += `${minutes}min`
}
return result
}

export function formatAngle(value, digits = 2) {
return `${value.toFixed(digits)}°`
}

export function extractOlFeatureCoordinates(feature) {
let coordinates = feature.getGeometry().getCoordinates()
if (feature.getGeometry().getType() === 'Polygon') {
// in case of a polygon, the coordinates structure is
// [
// [ (poly1)
// [coord1],[coord2]
// ],
// [ (poly2) ...
// ]
// so as we will not have multipoly, we only keep what's defined as poly one
// (we remove the wrapping array that would enable us to have a second polygon)
coordinates = coordinates[0]
}
return coordinates
}

export function extractOlFeatureGeodesicCoordinates(feature) {
return feature.get('geodesic')?.getGeodesicGeom().getCoordinates()[0]
}
import { LineString, Polygon } from 'ol/geom'

/**
* Checks if point is at target within tolerance.
Expand Down
13 changes: 1 addition & 12 deletions src/modules/drawing/lib/export-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { LineString, Polygon } from 'ol/geom'
import { Circle, Icon } from 'ol/style'
import Style from 'ol/style/Style'

import { featureStyleFunction } from '@/modules/drawing/lib/style'
import i18n from '@/modules/i18n/index'
import { WGS84 } from '@/utils/coordinates/coordinateSystems'
import { featureStyleFunction } from '@/utils/featureStyleUtils'
import log from '@/utils/logging'

const kmlFormat = new KML()
Expand Down Expand Up @@ -131,14 +131,3 @@ export function generateKmlString(projection, features = []) {
}
return kmlString
}

export function generateFilename(fileExtension) {
fileExtension = fileExtension.replace(/^\./, '')
const date = new Date()
.toISOString()
.split('.')[0]
.replaceAll('-', '')
.replaceAll(':', '')
.replace('T', '')
return `map.geo.admin.ch_${fileExtension.toUpperCase()}_${date}.${fileExtension.toLowerCase()}`
}
Loading