35
35
from math import sqrt
36
36
from .helper_utils import get_max_fallback_duration
37
37
from jormungandr .street_network .street_network import StreetNetworkPathType
38
- from jormungandr import new_relic
38
+ from jormungandr import new_relic , excluded_zones_manager
39
39
from jormungandr .fallback_modes import FallbackModes
40
40
import logging
41
41
from .helper_utils import timed_logger
44
44
from jormungandr .exceptions import GeoveloTechnicalError
45
45
from .helper_exceptions import StreetNetworkException
46
46
from jormungandr .scenarios .utils import include_poi_access_points
47
+ from jormungandr .scenarios .helper_classes .places_free_access import FreeAccessObject
48
+ import functools
49
+ import itertools
47
50
48
51
# The basic element stored in fallback_durations.
49
52
# in DurationElement. can be found:
@@ -189,16 +192,27 @@ def _update_free_access_with_free_radius(self, free_access, proximities_by_crowf
189
192
free_radius_distance = self ._request .free_radius_to
190
193
if free_radius_distance is not None :
191
194
free_access .free_radius .update (
192
- p .uri for p in proximities_by_crowfly if p .distance < free_radius_distance
195
+ FreeAccessObject (p .uri , p .stop_point .coord .lon , p .stop_point .coord .lat )
196
+ for p in proximities_by_crowfly
197
+ if p .distance < free_radius_distance
193
198
)
194
199
195
200
def _get_all_free_access (self , proximities_by_crowfly ):
196
201
free_access = self ._places_free_access .wait_and_get ()
197
202
self ._update_free_access_with_free_radius (free_access , proximities_by_crowfly )
198
203
all_free_access = free_access .crowfly | free_access .odt | free_access .free_radius
204
+ if self ._request ['_use_excluded_zones' ] and all_free_access :
205
+ # the mode is hardcoded to walking because we consider that we access to all free_access places
206
+ # by walking
207
+ is_excluded = functools .partial (
208
+ excluded_zones_manager .ExcludedZonesManager .is_excluded ,
209
+ mode = 'walking' ,
210
+ timestamp = self ._request ['datetime' ],
211
+ )
212
+ all_free_access = set (itertools .filterfalse (is_excluded , all_free_access ))
199
213
return all_free_access
200
214
201
- def _build_places_isochrone (self , proximities_by_crowfly , all_free_access ):
215
+ def _build_places_isochrone (self , proximities_by_crowfly , all_free_access_uris ):
202
216
places_isochrone = []
203
217
stop_points = []
204
218
# in this map, we store all the information that will be useful where we update the final result
@@ -207,16 +221,17 @@ def _build_places_isochrone(self, proximities_by_crowfly, all_free_access):
207
221
# - stop_point_uri: to which stop point the access point is attached
208
222
# - access_point: the actual access_point, of type pt_object
209
223
access_points_map = defaultdict (list )
224
+
210
225
if self ._mode == FallbackModes .car .name or self ._request ['_access_points' ] is False :
211
226
# if a place is freely accessible, there is no need to compute it's access duration in isochrone
212
- places_isochrone .extend (p for p in proximities_by_crowfly if p .uri not in all_free_access )
213
- stop_points .extend (p for p in proximities_by_crowfly if p .uri not in all_free_access )
227
+ places_isochrone .extend (p for p in proximities_by_crowfly if p .uri not in all_free_access_uris )
228
+ stop_points .extend (p for p in proximities_by_crowfly if p .uri not in all_free_access_uris )
214
229
places_isochrone = self ._streetnetwork_service .filter_places_isochrone (places_isochrone )
215
230
else :
216
231
proximities_by_crowfly = self ._streetnetwork_service .filter_places_isochrone (proximities_by_crowfly )
217
232
for p in proximities_by_crowfly :
218
233
# if a place is freely accessible, there is no need to compute it's access duration in isochrone
219
- if p .uri in all_free_access :
234
+ if p .uri in all_free_access_uris :
220
235
continue
221
236
# what we are looking to compute, is not the stop_point, but the entrance and exit of a stop_point
222
237
# if any of them are existent
@@ -231,14 +246,14 @@ def _build_places_isochrone(self, proximities_by_crowfly, all_free_access):
231
246
232
247
return places_isochrone , access_points_map , stop_points
233
248
234
- def _fill_fallback_durations_with_free_access (self , fallback_durations , all_free_access ):
249
+ def _fill_fallback_durations_with_free_access (self , fallback_durations , all_free_access_uris ):
235
250
# Since we have already places that have free access, we add them into the result
236
251
from collections import deque
237
252
238
253
deque (
239
254
(
240
255
fallback_durations .update ({uri : DurationElement (0 , response_pb2 .reached , None , 0 , None , None )})
241
- for uri in all_free_access
256
+ for uri in all_free_access_uris
242
257
),
243
258
maxlen = 1 ,
244
259
)
@@ -343,6 +358,8 @@ def _do_request(self):
343
358
344
359
all_free_access = self ._get_all_free_access (proximities_by_crowfly )
345
360
361
+ all_free_access_uris = set ((free_access .uri for free_access in all_free_access ))
362
+
346
363
# places_isochrone: a list of pt_objects selected from proximities_by_crowfly that will be sent to street
347
364
# network service to compute the routing matrix
348
365
# access_points_map: a map of access_point.uri vs a list of tuple whose elements are stop_point.uri, length and
@@ -353,15 +370,15 @@ def _do_request(self):
353
370
# "stop_point:2", by walking (42 meters, 41 sec) and (43 meters, 44sec) respectively
354
371
# it is a temporary storage that will be used later to update fallback_durations
355
372
places_isochrone , access_points_map , stop_points = self ._build_places_isochrone (
356
- proximities_by_crowfly , all_free_access
373
+ proximities_by_crowfly , all_free_access_uris
357
374
)
358
375
359
376
centers_isochrone = self ._determine_centers_isochrone ()
360
377
result = []
361
378
for center_isochrone in centers_isochrone :
362
379
result .append (
363
380
self .build_fallback_duration (
364
- center_isochrone , all_free_access , places_isochrone , access_points_map
381
+ center_isochrone , all_free_access_uris , places_isochrone , access_points_map
365
382
)
366
383
)
367
384
if len (result ) == 1 :
@@ -393,14 +410,16 @@ def _async_request(self):
393
410
def wait_and_get (self ):
394
411
return self ._value .wait_and_get () if self ._value else None
395
412
396
- def build_fallback_duration (self , center_isochrone , all_free_access , places_isochrone , access_points_map ):
413
+ def build_fallback_duration (
414
+ self , center_isochrone , all_free_access_uris , places_isochrone , access_points_map
415
+ ):
397
416
logger = logging .getLogger (__name__ )
398
417
399
418
# the final result to be returned, which is a map of stop_points.uri vs DurationElement
400
419
fallback_durations = defaultdict (lambda : DurationElement (float ('inf' ), None , None , 0 , None , None ))
401
420
402
421
# Since we have already places that have free access, we add them into the fallback_durations
403
- self ._fill_fallback_durations_with_free_access (fallback_durations , all_free_access )
422
+ self ._fill_fallback_durations_with_free_access (fallback_durations , all_free_access_uris )
404
423
405
424
# There are two cases that places_isochrone maybe empty:
406
425
# 1. The duration of direct_path is very small that we cannot find any proximities by crowfly
0 commit comments