-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
pointsRequest.js
96 lines (85 loc) · 3.42 KB
/
pointsRequest.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import booleanContains from '@turf/boolean-contains'
import center from '@turf/center'
import { polygon } from '@turf/helpers'
import point from 'turf-point'
import { createTurfPointCollection } from './cyclingGeoStudio'
import { shuffleArray } from './utils'
const APIUrl = 'http://localhost:' + (process.env.PORT || 3000)
export const pointsRequest = async (city, randomFilter = 100) => {
const townhallUrl = `${APIUrl}/points/${city}/townhalls`
const transportUrl = APIUrl + `/points/${city}/stops`
try {
const townhallResponse = await fetch(townhallUrl),
townhallPoints = await townhallResponse.json()
const townhalls = clusterTownhallBorders(townhallPoints.elements)
const transportStopsResponse = await fetch(transportUrl),
transportStopsRaw = await transportStopsResponse.json()
const transportStops = shuffleArray(transportStopsRaw.elements).slice(
0,
randomFilter
)
const points = [...townhalls, ...transportStops]
return points
} catch (e) {
console.log(transportUrl)
console.log(townhallUrl)
throw new Error('Problème de téléchargement des points cyclables' + e)
}
}
// the Paris query can return points in the united states ! Hence we test the containment.
// Hack, breaks Corsica and Outre mer :/
// (bikes don't exist in Corsica anyway yet)
const metropolitanFrance = [
[-5.353852828534542, 48.42923941831151],
[2.5964340170922924, 51.97021507483498],
[8.734619911467632, 49.03027507341659],
[10.345413967223578, 41.03091304244174],
[-2.447427130244762, 42.92290589918966],
]
const isSafeFrenchName = (name) =>
[
...['Guadeloupe', 'La Réunion', 'Martinique', 'Guyane', 'Mayotte'],
...['Basse-Terre', 'Fort-de-France', 'Cayenne', 'Mamoudzou', 'Nouméa'].map(
(el) => el + '.8'
),
].includes(name)
export const pointsProcess = async (ville, randomFilter) => {
const worldPoints = await pointsRequest(ville, randomFilter)
const points =
/^\d+$/.test(ville) || isSafeFrenchName(ville) // If it's an ID, it's unique, we don't need to filter for points only present in France
? //TODO this should be changed to handle famous names like "Oslo" for example directly by URL. But for nos the /recherche URL helps find the id without hassle
worldPoints
: console.log(
'Points will be filtered to only metropolitan France, see pointsRequest.js for info',
ville
) ||
worldPoints.filter((p) =>
booleanContains(
polygon([[...metropolitanFrance, metropolitanFrance.at(0)]]),
point([p.lon, p.lat])
)
)
console.log({ worldPoints: worldPoints.length, points: points.length })
return points
}
export const computePointsCenter = (points) =>
center(createTurfPointCollection(points))
export const clusterTownhallBorders = (elements) =>
elements
.filter((element) => element.tags && element.tags['amenity'] === 'townhall')
.map((element) => {
if (element.type === 'way') {
const firstNode = elements.find((node) => node.id === element.nodes[0])
return { ...element, lat: firstNode.lat, lon: firstNode.lon }
}
if (element.type === 'relation') {
const firstRef = elements.find(
(node) => node.id === element.members[0].ref
)
if (!firstRef.nodes) return null // Exception introduces for Loir-et-Cher element. Dunno why such a rare event, didn't investigate
const firstNode = elements.find((node) => node.id === firstRef.nodes[0])
return { ...element, lat: firstNode.lat, lon: firstNode.lon }
}
return element
})
.filter(Boolean)