GeoOperations.distanceBetween now uses meters, fix GPS tracking
This commit is contained in:
parent
79012c42ab
commit
680e56397d
10 changed files with 40 additions and 40 deletions
|
@ -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) => {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}))
|
}))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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": [
|
||||||
|
|
Loading…
Reference in a new issue