GeoOperations.distanceBetween now uses meters, fix GPS tracking

This commit is contained in:
pietervdvn 2021-11-12 18:39:38 +01:00
parent 79012c42ab
commit 680e56397d
10 changed files with 40 additions and 40 deletions

View file

@ -90,7 +90,7 @@ export class ExtraFunction {
private static readonly DistanceToFunc = new ExtraFunction( private static readonly DistanceToFunc = new ExtraFunction(
{ {
name: "distanceTo", name: "distanceTo",
doc: "Calculates the distance between the feature and a specified point in kilometer. The input should either be a pair of coordinates, a geojson feature or the ID of an object", doc: "Calculates the distance between the feature and a specified point in meter. The input should either be a pair of coordinates, a geojson feature or the ID of an object",
args: ["feature OR featureID OR longitude", "undefined OR latitude"] args: ["feature OR featureID OR longitude", "undefined OR latitude"]
}, },
(featuresPerLayer, feature) => { (featuresPerLayer, feature) => {

View file

@ -30,12 +30,12 @@ export class GeoOperations {
} }
/** /**
* Returns the distance between the two points in kilometers * Returns the distance between the two points in meters
* @param lonlat0 * @param lonlat0
* @param lonlat1 * @param lonlat1
*/ */
static distanceBetween(lonlat0: [number, number], lonlat1: [number, number]) { static distanceBetween(lonlat0: [number, number], lonlat1: [number, number]) {
return turf.distance(lonlat0, lonlat1) return turf.distance(lonlat0, lonlat1) * 1000
} }
/** /**

View file

@ -111,12 +111,12 @@ export default class CreateNewNodeAction extends OsmChangeAction {
// We check that it isn't close to an already existing point // We check that it isn't close to an already existing point
let reusedPointId = undefined; let reusedPointId = undefined;
const prev = <[number, number]>geojson.geometry.coordinates[index] const prev = <[number, number]>geojson.geometry.coordinates[index]
if (GeoOperations.distanceBetween(prev, <[number, number]>projected.geometry.coordinates) * 1000 < this._reusePointDistance) { if (GeoOperations.distanceBetween(prev, <[number, number]>projected.geometry.coordinates) < this._reusePointDistance) {
// We reuse this point instead! // We reuse this point instead!
reusedPointId = this._snapOnto.nodes[index] reusedPointId = this._snapOnto.nodes[index]
} }
const next = <[number, number]>geojson.geometry.coordinates[index + 1] const next = <[number, number]>geojson.geometry.coordinates[index + 1]
if (GeoOperations.distanceBetween(next, <[number, number]>projected.geometry.coordinates) * 1000 < this._reusePointDistance) { if (GeoOperations.distanceBetween(next, <[number, number]>projected.geometry.coordinates) < this._reusePointDistance) {
// We reuse this point instead! // We reuse this point instead!
reusedPointId = this._snapOnto.nodes[index + 1] reusedPointId = this._snapOnto.nodes[index + 1]
} }

View file

@ -225,7 +225,7 @@ export default class CreateWayWithPointReuseAction extends OsmChangeAction {
const coor = coordinates[i] const coor = coordinates[i]
// Check closeby (and probably identical) point further in the coordinate list, mark them as duplicate // Check closeby (and probably identical) point further in the coordinate list, mark them as duplicate
for (let j = i + 1; j < coordinates.length; j++) { for (let j = i + 1; j < coordinates.length; j++) {
if (1000 * GeoOperations.distanceBetween(coor, coordinates[j]) < 0.1) { if (GeoOperations.distanceBetween(coor, coordinates[j]) < 0.1) {
coordinateInfo[j] = { coordinateInfo[j] = {
lngLat: coor, lngLat: coor,
identicalTo: i identicalTo: i
@ -244,7 +244,7 @@ export default class CreateWayWithPointReuseAction extends OsmChangeAction {
}[] = [] }[] = []
for (const node of allNodes) { for (const node of allNodes) {
const center = node.geometry.coordinates const center = node.geometry.coordinates
const d = 1000 * GeoOperations.distanceBetween(coor, center) const d = GeoOperations.distanceBetween(coor, center)
if (d > maxDistance) { if (d > maxDistance) {
continue continue
} }

View file

@ -62,7 +62,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction {
continue continue
} }
for (let j = i + 1; j < coordinates.length; j++) { for (let j = i + 1; j < coordinates.length; j++) {
const d = 1000 * GeoOperations.distanceBetween(coordinates[i], coordinates[j]) const d = GeoOperations.distanceBetween(coordinates[i], coordinates[j])
if (d < 0.1) { if (d < 0.1) {
console.log("Identical coordinates detected: ", i, " and ", j, ": ", coordinates[i], coordinates[j], "distance is", d) console.log("Identical coordinates detected: ", i, " and ", j, ": ", coordinates[i], coordinates[j], "distance is", d)
this.identicalTo[j] = i this.identicalTo[j] = i

View file

@ -172,7 +172,7 @@ export class Changes {
return Math.min(...changedObjectCoordinates.map(coor => return Math.min(...changedObjectCoordinates.map(coor =>
Math.min(...recentLocationPoints.map(gpsPoint => { Math.min(...recentLocationPoints.map(gpsPoint => {
const otherCoor = GeoOperations.centerpointCoordinates(gpsPoint) const otherCoor = GeoOperations.centerpointCoordinates(gpsPoint)
return GeoOperations.distanceBetween(coor, otherCoor) * 1000 return GeoOperations.distanceBetween(coor, otherCoor)
})) }))
)) ))
} }

View file

@ -57,7 +57,7 @@ export default class MapState extends UserRelatedState {
/** /**
* The number of seconds that the GPS-locations are stored in memory * The number of seconds that the GPS-locations are stored in memory
*/ */
public gpsLocationHistoryRetentionTime = new UIEventSource(7 * 24 * 60 * 60, "gps_location_retention" ) public gpsLocationHistoryRetentionTime = new UIEventSource(7 * 24 * 60 * 60, "gps_location_retention")
public historicalUserLocationsTrack: FeatureSourceForLayer & Tiled; public historicalUserLocationsTrack: FeatureSourceForLayer & Tiled;
/** /**
@ -188,14 +188,14 @@ export default class MapState extends UserRelatedState {
} }
} }
private initGpsLocation(){ private initGpsLocation() {
// Initialize the gps layer data. This is emtpy for now, the actual writing happens in the Geolocationhandler // Initialize the gps layer data. This is emtpy for now, the actual writing happens in the Geolocationhandler
let gpsLayerDef: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "gps_location")[0] let gpsLayerDef: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "gps_location")[0]
this.currentUserLocation = new SimpleFeatureSource(gpsLayerDef, Tiles.tile_index(0, 0, 0)); this.currentUserLocation = new SimpleFeatureSource(gpsLayerDef, Tiles.tile_index(0, 0, 0));
} }
private initUserLocationTrail(){ private initUserLocationTrail() {
const features = LocalStorageSource.GetParsed<{feature: any, freshness: Date}[]>("gps_location_history", []) const features = LocalStorageSource.GetParsed<{ feature: any, freshness: Date }[]>("gps_location_history", [])
const now = new Date().getTime() const now = new Date().getTime()
features.data = features.data features.data = features.data
.map(ff => ({feature: ff.feature, freshness: new Date(ff.freshness)})) .map(ff => ({feature: ff.feature, freshness: new Date(ff.freshness)}))
@ -204,25 +204,29 @@ export default class MapState extends UserRelatedState {
const self = this; const self = this;
let i = 0 let i = 0
this.currentUserLocation.features.addCallbackAndRunD(([location]) => { this.currentUserLocation.features.addCallbackAndRunD(([location]) => {
if(location === undefined){ if (location === undefined) {
return; return;
} }
const previousLocation = features.data[features.data.length - 1] const previousLocation = features.data[features.data.length - 1]
if(previousLocation !== undefined){ if (previousLocation !== undefined) {
const d = GeoOperations.distanceBetween( const d = GeoOperations.distanceBetween(
previousLocation.feature.geometry.coordinates, previousLocation.feature.geometry.coordinates,
location.feature.geometry.coordinates location.feature.geometry.coordinates
) )
if(d < 20){ let timeDiff = Number.MAX_VALUE // in seconds
const olderLocation = features.data[features.data.length - 2]
if (olderLocation !== undefined) {
timeDiff = (previousLocation.freshness.getTime() - olderLocation.freshness.getTime()) / 1000
}
if (d < 20 && timeDiff < 60) {
// Do not append changes less then 20m - it's probably noise anyway // Do not append changes less then 20m - it's probably noise anyway
return; return;
} }
} }
const feature = JSON.parse(JSON.stringify(location.feature)) const feature = JSON.parse(JSON.stringify(location.feature))
feature.properties.id = "gps/"+features.data.length feature.properties.id = "gps/" + features.data.length
i++ i++
features.data.push({feature, freshness: new Date()}) features.data.push({feature, freshness: new Date()})
features.ping() features.ping()
@ -234,22 +238,18 @@ export default class MapState extends UserRelatedState {
this.changes.useLocationHistory(this) this.changes.useLocationHistory(this)
const asLine = features.map(allPoints => { const asLine = features.map(allPoints => {
if(allPoints === undefined || allPoints.length < 2){ if (allPoints === undefined || allPoints.length < 2) {
return [] return []
} }
const feature = { const feature = {
type: "Feature", type: "Feature",
properties:{ properties: {
"id":"location_track", "id": "location_track",
"_date:now": new Date().toISOString(), "_date:now": new Date().toISOString(),
}, },
geometry:{ geometry: {
type: "LineString", type: "LineString",
coordinates: allPoints.map(ff => ff.feature.geometry.coordinates) coordinates: allPoints.map(ff => ff.feature.geometry.coordinates)
} }
@ -286,7 +286,7 @@ export default class MapState extends UserRelatedState {
feature: { feature: {
"type": "Feature", "type": "Feature",
"properties": { "properties": {
"id":"home", "id": "home",
"user:home": "yes", "user:home": "yes",
"_lon": homeLonLat[0], "_lon": homeLonLat[0],
"_lat": homeLonLat[1] "_lat": homeLonLat[1]

View file

@ -136,7 +136,7 @@ export default class LengthInput extends InputElement<string> {
if (leaflet) { if (leaflet) {
const first = leaflet.layerPointToLatLng(firstClickXY) const first = leaflet.layerPointToLatLng(firstClickXY)
const last = leaflet.layerPointToLatLng([dx, dy]) const last = leaflet.layerPointToLatLng([dx, dy])
const geoDist = Math.floor(GeoOperations.distanceBetween([first.lng, first.lat], [last.lng, last.lat]) * 10000) / 10 const geoDist = Math.floor(GeoOperations.distanceBetween([first.lng, first.lat], [last.lng, last.lat]) * 10) / 10
self.value.setData("" + geoDist) self.value.setData("" + geoDist)
} }

View file

@ -93,7 +93,7 @@ export default class SplitRoadWizard extends Toggle {
function onMapClick(coordinates) { function onMapClick(coordinates) {
// First, we check if there is another, already existing point nearby // First, we check if there is another, already existing point nearby
const points = splitPoints.data.map((f, i) => [f.feature, i]) const points = splitPoints.data.map((f, i) => [f.feature, i])
.filter(p => GeoOperations.distanceBetween(p[0].geometry.coordinates, coordinates) * 1000 < 5) .filter(p => GeoOperations.distanceBetween(p[0].geometry.coordinates, coordinates) < 5)
.map(p => p[1]) .map(p => p[1])
.sort((a, b) => a - b) .sort((a, b) => a - b)
.reverse() .reverse()

View file

@ -34,7 +34,7 @@
"calculatedTags": [ "calculatedTags": [
"_closest_other_drinking_water=feat.closestn('drinking_water', 1, undefined, 5000).map(f => ({id: f.feat.id, distance: ''+f.distance}))[0]", "_closest_other_drinking_water=feat.closestn('drinking_water', 1, undefined, 5000).map(f => ({id: f.feat.id, distance: ''+f.distance}))[0]",
"_closest_other_drinking_water_id=JSON.parse(feat.properties._closest_other_drinking_water)?.id", "_closest_other_drinking_water_id=JSON.parse(feat.properties._closest_other_drinking_water)?.id",
"_closest_other_drinking_water_distance=Math.floor(Number(JSON.parse(feat.properties._closest_other_drinking_water)?.distance) * 1000)" "_closest_other_drinking_water_distance=Math.floor(Number(JSON.parse(feat.properties._closest_other_drinking_water)?.distance))"
], ],
"minzoom": 13, "minzoom": 13,
"presets": [ "presets": [