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 | import PolylineEncoder from '../core/lib/PolylineEncoder.js'; |
26 | import ItineraryPoint from '../data/ItineraryPoint.js'; |
27 | import Maneuver from '../data/Maneuver.js'; |
28 | import BaseRouteProvider from '../routeProviders/BaseRouteProvider.js'; |
29 | import theOsrmTextInstructions from '../routeProviders/OsrmTextInstructions.js'; |
30 | import { ICON_LIST } from '../routeProviders/IconList.js'; |
31 | import { ZERO, ONE, TWO, LAT_LNG, HTTP_STATUS_OK } from '../main/Constants.js'; |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | class MapboxRouteProvider extends BaseRouteProvider { |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | #providerKey; |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | #route; |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | static get #ROUND_VALUE ( ) { return 6; } |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | #parseResponse ( response, onOk, onError ) { |
72 | |
73 | if ( 'Ok' !== response.code ) { |
74 | onError ( new Error ( 'Response code not ok' ) ); |
75 | return; |
76 | } |
77 | |
78 | if ( ZERO === response.routes.length ) { |
79 | onError ( new Error ( 'Route not found' ) ); |
80 | return; |
81 | } |
82 | |
83 | const polylineEncoder = new PolylineEncoder ( ); |
84 | this.#route.itinerary.itineraryPoints.removeAll ( ); |
85 | this.#route.itinerary.maneuvers.removeAll ( ); |
86 | this.#route.itinerary.hasProfile = false; |
87 | this.#route.itinerary.ascent = ZERO; |
88 | this.#route.itinerary.descent = ZERO; |
89 | response.routes [ ZERO ].geometry = polylineEncoder.decode ( |
90 | response.routes [ ZERO ].geometry, [ MapboxRouteProvider.#ROUND_VALUE, MapboxRouteProvider.#ROUND_VALUE ] |
91 | ); |
92 | response.routes [ ZERO ].legs.forEach ( |
93 | leg => { |
94 | let lastPointWithDistance = ZERO; |
95 | leg.steps.forEach ( |
96 | step => { |
97 | step.geometry = polylineEncoder.decode ( |
98 | step.geometry, |
99 | [ MapboxRouteProvider.#ROUND_VALUE, MapboxRouteProvider.#ROUND_VALUE ] |
100 | ); |
101 | if ( |
102 | 'arrive' === step.maneuver.type |
103 | && |
104 | TWO === step.geometry.length |
105 | && |
106 | step.geometry [ ZERO ] [ ZERO ] === step.geometry [ ONE ] [ ZERO ] |
107 | && |
108 | step.geometry [ ZERO ] [ ONE ] === step.geometry [ ONE ] [ ONE ] |
109 | ) { |
110 | step.geometry.pop ( ); |
111 | } |
112 | |
113 | const maneuver = new Maneuver ( ); |
114 | maneuver.iconName = |
115 | ICON_LIST [ step.maneuver.type ] |
116 | ? |
117 | ICON_LIST [ step.maneuver.type ] [ step.maneuver.modifier ] |
118 | || |
119 | ICON_LIST [ step.maneuver.type ] [ 'default' ] |
120 | : |
121 | ICON_LIST [ 'default' ] [ 'default' ]; |
122 | maneuver.instruction = theOsrmTextInstructions.compile ( this.userLanguage, step ); |
123 | maneuver.duration = step.duration; |
124 | let distance = ZERO; |
125 | for ( |
126 | let geometryCounter = ZERO; |
127 | ( ONE === step.geometry.length ) |
128 | ? |
129 | ( ONE > geometryCounter ) |
130 | : |
131 | ( geometryCounter < step.geometry.length ); |
132 | geometryCounter ++ ) { |
133 | const itineraryPoint = new ItineraryPoint ( ); |
134 | itineraryPoint.latLng = [ |
135 | step.geometry [ geometryCounter ] [ ZERO ], |
136 | step.geometry [ geometryCounter ] [ ONE ] |
137 | ]; |
138 | |
139 | itineraryPoint.distance = |
140 | leg.annotation.distance [ lastPointWithDistance ] |
141 | ? |
142 | leg.annotation.distance [ lastPointWithDistance ] |
143 | : |
144 | ZERO; |
145 | this.#route.itinerary.itineraryPoints.add ( itineraryPoint ); |
146 | if ( geometryCounter !== step.geometry.length - ONE ) { |
147 | distance += itineraryPoint.distance; |
148 | lastPointWithDistance ++; |
149 | } |
150 | if ( ZERO === geometryCounter ) { |
151 | maneuver.itineraryPointObjId = itineraryPoint.objId; |
152 | } |
153 | } |
154 | maneuver.distance = distance; |
155 | this.#route.itinerary.maneuvers.add ( maneuver ); |
156 | } |
157 | ); |
158 | } |
159 | ); |
160 | |
161 | const wayPointsIterator = this.#route.wayPoints.iterator; |
162 | response.waypoints.forEach ( |
163 | wayPoint => { |
164 | if ( ! wayPointsIterator.done ) { |
165 | wayPointsIterator.value.latLng = [ wayPoint.location [ ONE ], wayPoint.location [ ZERO ] ]; |
166 | } |
167 | } |
168 | ); |
169 | |
170 | onOk ( this.#route ); |
171 | } |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | #getUrl ( ) { |
179 | let wayPointsString = null; |
180 | this.#route.wayPoints.forEach ( |
181 | wayPoint => { |
182 | wayPointsString = wayPointsString ? wayPointsString + ';' : ''; |
183 | wayPointsString += |
184 | wayPoint.lng.toFixed ( LAT_LNG.fixed ) + ',' + |
185 | wayPoint.lat.toFixed ( LAT_LNG.fixed ); |
186 | } |
187 | ); |
188 | |
189 | let profile = ''; |
190 | switch ( this.#route.itinerary.transitMode ) { |
191 | case 'car' : |
192 | profile = 'mapbox/driving/'; |
193 | break; |
194 | case 'bike' : |
195 | profile = 'mapbox/cycling/'; |
196 | break; |
197 | case 'pedestrian' : |
198 | profile = 'mapbox/walking/'; |
199 | break; |
200 | default : |
201 | return; |
202 | } |
203 | return 'https://api.mapbox.com/directions/v5/' + |
204 | profile + |
205 | wayPointsString + |
206 | '?geometries=polyline6&overview=full&steps=true&annotations=distance&access_token=' + |
207 | this.#providerKey; |
208 | } |
209 | |
210 | |
211 | |
212 | |
213 | |
214 | |
215 | |
216 | #getRoute ( onOk, onError ) { |
217 | fetch ( this.#getUrl ( ) ) |
218 | .then ( |
219 | response => { |
220 | if ( HTTP_STATUS_OK === response.status && response.ok ) { |
221 | response.json ( ) |
222 | .then ( result => this.#parseResponse ( result, onOk, onError ) ); |
223 | } |
224 | else { |
225 | onError ( new Error ( 'Invalid status ' + response.status ) ); |
226 | } |
227 | } |
228 | ) |
229 | .catch ( |
230 | |
231 | |
232 | ( ) => { onError ( ); } |
233 | ); |
234 | } |
235 | |
236 | |
237 | |
238 | |
239 | |
240 | constructor ( ) { |
241 | super ( ); |
242 | this.#providerKey = ''; |
243 | } |
244 | |
245 | |
246 | |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | getPromiseRoute ( route ) { |
253 | this.#route = route; |
254 | return new Promise ( ( onOk, onError ) => this.#getRoute ( onOk, onError ) ); |
255 | } |
256 | |
257 | |
258 | |
259 | |
260 | |
261 | |
262 | |
263 | get icon ( ) { |
264 | return '' + |
265 | 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWX' + |
266 | 'MAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AocEwcBrMn63AAAAk1JREFUSMftlj9oU1EUxn8neQ0thE6lgpO1TiptHhShJiIu2qHJA6' + |
267 | 'FudtBRUBcpouJUnRyqgpODVcG62LROHfzHexGiJWkEQbCr0IqVYKPStDkOpuYRfW1eTNCh33Tvufec717udz8ObOFfITqV3XA9Nj' + |
268 | 'n3W+xAMuO7pnhs7AQiwCqwpvBNVN47Vu8SQDSZwbFMqsexyUyHinQjtAEBwACyTiKyWM1heBzyMHDXdbplRCeiyexVCei8HTfpf5' + |
269 | 'gCwLFM9k/lEF3bpSIXgWNAm6vWceBercQrVfMwcBKhvVRcOwEst2zbXlldXQljGFeAoRpqbUjshSExgo9iM6kHLw7uUIDYTEr0ez' + |
270 | 'DuQeoJw7/8ZLRUCD/ZNz6/AFAqFDolWBr1WyVQh/C7JKgj6eFu0sPdSFBHgC6/RWq7sbCI0g60/gzoqWhy7v762LXzC/AR2NmQG6' + |
271 | 'tyE3jnCoUQHUN0DAi54m+BGw27sUAGyAOjZYUD9Fdty4vqLRX51Mg3bnUSkevAm6rc9XwFXtuWeafyHI0hDgCI6AXg8x/WlwTO+6' + |
272 | 'npS9V23HwKJMtW+ss+FCbsRORVU79TMdByFlhwhT60hELnmvqP+6dzpAf35BG9DBSBoqheej6w+2vsca55xC/jPei04sTN20AKsG' + |
273 | '3LHN87cg17sKe5ztXHbFnHclrgDEDHwFGa41wuzMb7iCbncKzeHEBsKsuzQ74dsy6vxrF6K0pPROrqdOoibgT+O+LQJvONUFOul7' + |
274 | 'hmgCNlhzKArA/i+nK92tvN2t6/zd1C0/ADiOy3l0UZHxAAAAAASUVORK5CYII='; |
275 | } |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | |
282 | |
283 | get name ( ) { return 'Mapbox'; } |
284 | |
285 | |
286 | |
287 | |
288 | |
289 | |
290 | |
291 | get title ( ) { return 'Mapbox'; } |
292 | |
293 | |
294 | |
295 | |
296 | |
297 | |
298 | |
299 | |
300 | get transitModes ( ) { return [ 'bike', 'pedestrian', 'car' ]; } |
301 | |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | get providerKeyNeeded ( ) { return true; } |
309 | |
310 | |
311 | |
312 | |
313 | |
314 | |
315 | set providerKey ( providerKey ) { this.#providerKey = providerKey; } |
316 | |
317 | |
318 | |
319 | |
320 | |
321 | |
322 | |
323 | get userLanguage ( ) { return super.userLanguage; } |
324 | set userLanguage ( userLanguage ) { |
325 | super.userLanguage = theOsrmTextInstructions.loadLanguage ( userLanguage ); |
326 | } |
327 | } |
328 | |
329 | window.TaN.addProvider ( MapboxRouteProvider ); |
330 | |
331 | |
332 | |