Fixes after review
This commit is contained in:
parent
14e96bb806
commit
e64fbbee97
2 changed files with 51 additions and 38 deletions
|
@ -256,7 +256,11 @@ if __name__ == '__main__':
|
|||
try:
|
||||
c.extract_routes()
|
||||
except CriticalValidationError as e:
|
||||
logging.error("Critical validation error: %s", str(e))
|
||||
logging.error("Critical validation error while processing %s: %s", c.name, str(e))
|
||||
c.error(str(e))
|
||||
except AssertionError as e:
|
||||
logging.error("Validation logic error while processing %s: %s", c.name, str(e))
|
||||
c.error("Validation logic error: {}".format(str(e)))
|
||||
else:
|
||||
c.validate()
|
||||
if c.is_good():
|
||||
|
|
|
@ -27,7 +27,6 @@ ALL_MODES = MODES_RAPID | MODES_OVERGROUND
|
|||
RAILWAY_TYPES = set(('rail', 'light_rail', 'subway', 'narrow_gauge',
|
||||
'funicular', 'monorail', 'tram'))
|
||||
CONSTRUCTION_KEYS = ('construction', 'proposed', 'construction:railway', 'proposed:railway')
|
||||
NOWHERE_STOP = (0, 0) # too far away from any metro system
|
||||
|
||||
used_entrances = set()
|
||||
|
||||
|
@ -87,7 +86,7 @@ def project_on_line(p, line):
|
|||
# closest vertex of line to the point p. Fractional value means that
|
||||
# the projected point lies on a segment between two vertices. More than
|
||||
# one value can occur if a route follows the same tracks more than once.
|
||||
'positions_on_rails': None,
|
||||
'positions_on_line': None,
|
||||
'projected_point': None # (lon, lat)
|
||||
}
|
||||
|
||||
|
@ -99,13 +98,13 @@ def project_on_line(p, line):
|
|||
for i, vertex in enumerate(line):
|
||||
d = distance(p, vertex)
|
||||
if d < d_min:
|
||||
result['positions_on_rails'] = [i]
|
||||
result['positions_on_line'] = [i]
|
||||
result['projected_point'] = vertex
|
||||
d_min = d
|
||||
closest_to_vertex = True
|
||||
elif vertex == result['projected_point']:
|
||||
# Repeated occurrence of the track vertex in line, like Oslo Line 5
|
||||
result['positions_on_rails'].append(i)
|
||||
result['positions_on_line'].append(i)
|
||||
# And then calculate distances to each segment
|
||||
for seg in range(len(line)-1):
|
||||
# Check bbox for speed
|
||||
|
@ -122,14 +121,14 @@ def project_on_line(p, line):
|
|||
)
|
||||
d = distance(p, projected_point)
|
||||
if d < d_min:
|
||||
result['positions_on_rails'] = [seg + u]
|
||||
result['positions_on_line'] = [seg + u]
|
||||
result['projected_point'] = projected_point
|
||||
d_min = d
|
||||
closest_to_vertex = False
|
||||
elif projected_point == result['projected_point']:
|
||||
# Repeated occurrence of the track segment in line, like Oslo Line 5
|
||||
if not closest_to_vertex:
|
||||
result['positions_on_rails'].append(seg + u)
|
||||
result['positions_on_line'].append(seg + u)
|
||||
return result
|
||||
|
||||
|
||||
|
@ -581,27 +580,21 @@ class Route:
|
|||
|
||||
def project_stops_on_line(self):
|
||||
projected = [project_on_line(x.stop, self.tracks) for x in self.stops]
|
||||
|
||||
def is_stop_near_tracks(stop_index):
|
||||
return (
|
||||
projected[stop_index]['projected_point'] is not None and
|
||||
distance(
|
||||
self.stops[stop_index].stop,
|
||||
projected[stop_index]['projected_point']
|
||||
) <= MAX_DISTANCE_STOP_TO_LINE
|
||||
)
|
||||
|
||||
start = 0
|
||||
while (start < len(self.stops) and
|
||||
(
|
||||
projected[start]['projected_point'] is None or
|
||||
distance(
|
||||
self.stops[start].stop,
|
||||
projected[start]['projected_point']
|
||||
) > MAX_DISTANCE_STOP_TO_LINE
|
||||
)
|
||||
):
|
||||
while start < len(self.stops) and not is_stop_near_tracks(start):
|
||||
start += 1
|
||||
end = len(self.stops) - 1
|
||||
while (end > start and
|
||||
(
|
||||
projected[end]['projected_point'] is None or
|
||||
distance(
|
||||
self.stops[end].stop,
|
||||
projected[end]['projected_point']
|
||||
) > MAX_DISTANCE_STOP_TO_LINE
|
||||
)
|
||||
):
|
||||
while end > start and not is_stop_near_tracks(end):
|
||||
end -= 1
|
||||
tracks_start = []
|
||||
tracks_end = []
|
||||
|
@ -624,7 +617,7 @@ class Route:
|
|||
route_stop.stoparea.name, route_stop.stop, d), self.element)
|
||||
else:
|
||||
route_stop.stop = projected_point
|
||||
route_stop.positions_on_rails = projected[i]['positions_on_rails']
|
||||
route_stop.positions_on_rails = projected[i]['positions_on_line']
|
||||
stops_on_longest_line.append(route_stop)
|
||||
if start >= len(self.stops):
|
||||
self.tracks = tracks_start
|
||||
|
@ -758,12 +751,11 @@ class Route:
|
|||
|
||||
if k not in city.elements:
|
||||
if 'stop' in m['role'] or 'platform' in m['role']:
|
||||
city.error('{} {} {} for route relation is not in the dataset'.format(
|
||||
m['role'], m['type'], m['ref']), relation)
|
||||
raise CriticalValidationError(
|
||||
'Stop or platform {} {} in relation {} '
|
||||
'is not in the dataset for {}'.format(
|
||||
m['type'], m['ref'], relation['id'], city.name))
|
||||
'{} {} {} for route relation {} is not in the dataset'.format(
|
||||
m['role'], m['type'], m['ref'], relation['id']
|
||||
)
|
||||
)
|
||||
continue
|
||||
el = city.elements[k]
|
||||
if 'tags' not in el:
|
||||
|
@ -821,16 +813,33 @@ class Route:
|
|||
return disorder_warnings, disorder_errors
|
||||
|
||||
def check_stops_order_on_tracks_direct(self, stop_sequence):
|
||||
""" Checks stops order on tracks, following stop_sequence
|
||||
in direct order only.
|
||||
:param stops_sequence: list of RouteStop that belong to the
|
||||
"""Checks stops order on tracks, following stop_sequence
|
||||
in direct order only.
|
||||
:param stop_sequence: list of RouteStop that belong to the
|
||||
longest contiguous sequence of tracks in a route.
|
||||
:return: error message on the first order violation or None.
|
||||
"""
|
||||
def make_assertion_error_msg(route_stop, error_type):
|
||||
return (
|
||||
"stop_area {} '{}' has {} 'positions_on_rails' "
|
||||
"attribute in route {}".format(
|
||||
route_stop.stoparea.id,
|
||||
route_stop.stoparea.name,
|
||||
"no" if error_type == 1 else "empty",
|
||||
self.id
|
||||
)
|
||||
)
|
||||
|
||||
allowed_order_violations = 1 if self.is_circular else 0
|
||||
max_position_on_rails = -1
|
||||
for route_stop in stop_sequence:
|
||||
assert hasattr(route_stop, 'positions_on_rails'), \
|
||||
make_assertion_error_msg(route_stop, error_type=1)
|
||||
|
||||
positions_on_rails = route_stop.positions_on_rails
|
||||
assert positions_on_rails, \
|
||||
make_assertion_error_msg(route_stop, error_type=2)
|
||||
|
||||
suitable_occurrence = 0
|
||||
while (suitable_occurrence < len(positions_on_rails) and
|
||||
positions_on_rails[suitable_occurrence] < max_position_on_rails):
|
||||
|
@ -846,16 +855,16 @@ class Route:
|
|||
)
|
||||
max_position_on_rails = positions_on_rails[suitable_occurrence]
|
||||
|
||||
def check_stops_order_on_tracks(self, stops_sequence):
|
||||
def check_stops_order_on_tracks(self, stop_sequence):
|
||||
""" Checks stops order on tracks, trying direct and reversed
|
||||
order of stops in the stop_sequence.
|
||||
:param stops_sequence: list of RouteStop that belong to the
|
||||
:param stop_sequence: list of RouteStop that belong to the
|
||||
longest contiguous sequence of tracks in a route.
|
||||
:return: error message on the first order violation or None.
|
||||
"""
|
||||
error_message = self.check_stops_order_on_tracks_direct(stops_sequence)
|
||||
error_message = self.check_stops_order_on_tracks_direct(stop_sequence)
|
||||
if error_message:
|
||||
error_message_reversed = self.check_stops_order_on_tracks_direct(reversed(stops_sequence))
|
||||
error_message_reversed = self.check_stops_order_on_tracks_direct(reversed(stop_sequence))
|
||||
if error_message_reversed is None:
|
||||
error_message = None
|
||||
self.city.warn('Tracks seem to go in the opposite direction to stops', self.element)
|
||||
|
|
Loading…
Add table
Reference in a new issue