1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
2# Copyright (C) 2016-2019 German Aerospace Center (DLR) and others.
3# SUMOPy module
4# Copyright (C) 2012-2017 University of Bologna - DICAM
5# This program and the accompanying materials
6# are made available under the terms of the Eclipse Public License v2.0
7# which accompanies this distribution, and is available at
8# http://www.eclipse.org/legal/epl-v20.html
9# SPDX-License-Identifier: EPL-2.0
10
11# @file    networkxtools.py
12# @author  Joerg Schweizer
13# @date
14# @version $Id$
15
16import sys
17reload(sys)
18sys.setdefaultencoding('utf8')
19
20import os
21import pickle
22from copy import deepcopy
23try:
24    import networkx as nx
25    IS_NX = True
26except:
27    IS_NX = False
28
29import numpy as np
30
31import agilepy.lib_base.classman as cm
32import agilepy.lib_base.arrayman as am
33import agilepy.lib_base.xmlman as xm
34from agilepy.lib_base.processes import Process
35from agilepy.lib_base.misc import filepathstring_to_filepathlist, filepathlist_to_filepathstring
36from agilepy.lib_base.geometry import get_length_polypoints, get_dist_point_to_segs, get_diff_angle_clockwise
37
38from coremodules.network.network import MODES, ID_MODE_PED, ID_MODE_BIKE, ID_MODE_CAR
39from coremodules.network.netconvert import *
40from coremodules.misc.shapeformat import guess_utm_from_coord
41
42import json
43
44try:
45    import pyproj
46except:
47    from mpl_toolkits.basemap import pyproj
48
49
50LANEATTRS_DEFAULT = {'is_rightside': False, 'is_leftside': False, 'n_lane': 0,
51                     'ids_modes_disallow': [], 'ids_modes_allow': []}
52
53LANEATTRS = ('lane', 'track')
54
55
56def load_objfile(filepath):
57    f = open(filepath, 'rb')
58    try:
59        f = open(filepath, 'rb')
60    except:
61        print 'WARNING in load_obj: could not open', filepath
62        return None
63
64    # try:
65    # print '  pickle.load...'
66    obj = pickle.load(f)
67    f.close()
68    return obj
69
70
71def print_attrs(attrs):
72    for key, val in attrs.iteritems():
73        print '    %s=\t%s' % (key, val)
74    print
75
76
77class Road:
78    def __init__(self, element, parent):
79        # edges_osm[id_way]= {}#{'nodes':(element['nodes'][0],element['nodes'][1])}# not needed {'nodes': element['nodes']}
80
81        self.parent = parent
82
83        self._osmattrs = element.get('tags', {})
84
85        self.highway = self._osmattrs.get('highway', 'road')
86        # if element.has_key('tags'):
87        #    self._attrs.update(element['tags'])
88
89        # is_one is a scpecial one way detection
90        #self._is_oneway = self.is_oneway_osm()
91        # self.is_oneway_osm()
92
93        #self._id_osm = id_osm
94        #osmattrs = self._osmattrs
95        # if not self._is_oneway:
96        #    self._id_osm_opp = -id_osm
97        # else:
98        #    self._id_osm_opp = -1
99
100        self._lanes = []
101        self._lanes_opp = []
102        self.make_oneway()
103        self.config()
104        self.make_lanestructure()
105        self.make_sumoattrs()
106        self.make_road()
107        # get from parent
108        # self._width_bikelane = 1.5 #m
109        # self.parent.width_sidewalk = 1.0 #m
110        #self._modes_reserved_lane = ['bus', 'taxi','emergency']
111
112    def config(self):
113        """
114        Make defaults to be overridden
115        """
116        print 'config'
117        # pass here either road type specific defaults
118        # or global defaults from parent process
119
120        self.n_lane = self.parent.n_lane
121        self.id_mode = ID_MODE_CAR
122        self.lanewidth = self.parent.lanewidth
123        self.lanewidth_bike = self.parent.lanewidth_bike
124        self.lanewidth_bus = self.parent.lanewidth_bus
125        self.width_sidewalk = self.parent.width_sidewalk
126        #self.width_footpath = self.parent.width_footpath
127
128        self.ids_modes_pt_shared = self.parent.ids_modes_pt_shared
129        self.ids_modes_bike = self.parent.ids_modes_bike
130        self.ids_modes_allow = []
131        self.ids_modes_disallow = []
132
133        self.make_speed(self.parent.speed_max)
134        self.speed_max_bus = self.parent.speed_max_bus
135        self.speed_max_bike = self.parent.speed_max_bike
136        self.speed_max_ped = self.parent.speed_max_ped
137
138    def make_laneattrs_main(self):
139        self._laneattrs_main = {'speed_max': self.speed_max,
140                                'width': self.lanewidth,
141                                'ids_modes_allow': self.ids_modes_allow,
142                                'ids_modes_disallow': self.ids_modes_disallow,
143                                # 'ids_mode': MODES["passenger"],
144                                'is_rightside': True,
145                                'is_leftside': False,
146                                'width_rightside': self.lanewidth,
147                                }
148
149    def get_osmattr(self, key, is_int=False, is_float=False, default=None):
150        valstr = self._osmattrs.get(key, '')
151        if valstr.find(',') > -1:
152            v = valstr.split(',')[0]
153        elif valstr.find(';') > -1:
154            v = valstr.split(';')[0]
155        else:
156            v = valstr
157        if is_int:
158            try:
159                return int(v)
160            except:
161                return default
162        if is_float:
163            try:
164                return float(v)
165            except:
166                return default
167
168        else:
169            return v
170
171    def make_sumoattrs(self):
172
173        osmattrs = self._osmattrs
174        print 'make_sumoattrs'
175        print_attrs(osmattrs)
176        #self._highway = osmattrs.get('highway','road')
177
178        self.make_laneattrs_main()
179        self.make_sidewalkattrs()
180        self.make_buswayattrs()
181        self.make_bikewayattrs()
182
183    def make_lanestructure(self):
184        osmattrs = self._osmattrs
185        is_oneway_osm = osmattrs.get('oneway', 'no') == 'yes'
186
187        n_lane_forward_osm = -1
188        n_lane_backward_osm = -1
189        is_lanes_forward_rigid = False
190        is_lanes_backward_rigid = False
191        if osmattrs.has_key('lanes'):
192            # total number of lanes provided
193            n_lane_osm_str = osmattrs['lanes']
194            # if type(n_lane_osm_str) in cm.STRINGTYPES:
195            if n_lane_osm_str.count(';') > 0:
196                n_lane_osm = 1
197                for n_lane_osm_elem in n_lane_osm_str.split(';'):
198                    if int(n_lane_osm_elem) > n_lane_osm:
199                        n_lane_osm = int(n_lane_osm_elem)
200            elif n_lane_osm_str.count(',') > 0:
201                n_lane_osm = 1
202                for n_lane_osm_elem in n_lane_osm_str.split(','):
203                    if int(n_lane_osm_elem) > n_lane_osm:
204                        n_lane_osm = int(n_lane_osm_elem)
205            else:
206                n_lane_osm = int(osmattrs['lanes'])
207
208            if is_oneway_osm:
209                # in cas of oneway
210                n_lane_backward_osm = 0
211                n_lane_forward_osm = n_lane_osm
212                is_lanes_forward_rigid = True
213
214            else:
215                # in case of bidir
216                if osmattrs.has_key('lanes:forward'):
217                    n_lane_forward_osm = int(osmattrs['lanes:forward'])
218                    is_lanes_forward_rigid = True
219                    if osmattrs.has_key('lanes:backward'):
220                        n_lane_backward_osm = int(osmattrs['lanes:backward'])
221                        is_lanes_backward_rigid = True
222                    else:
223                        n_lane_backward_osm = n_lane_osm-n_lane_forward_osm
224                        # correct if necessary
225                        if n_lane_backward_osm <= 0:
226                            n_lane_backward_osm = 1
227                        n_lane_osm = n_lane_forward_osm+n_lane_backward_osm
228
229                elif osmattrs.has_key('lanes:backward'):
230                    n_lane_backward_osm = int(osmattrs['lanes:backward'])
231                    n_lane_forward_osm = n_lane_osm-n_lane_backward_osm
232                    is_lanes_backward_rigid = True
233
234                    # correct if necessary
235                    if n_lane_forward_osm <= 0:
236                        n_lane_forward_osm = 1
237                    n_lane_osm = n_lane_forward_osm+n_lane_backward_osm
238
239                else:
240                    # symmetric dist
241                    if n_lane_osm < 2:
242                        n_lane_osm = 2
243
244                    n_lane_forward_osm = int(0.5*n_lane_osm+0.5)
245                    n_lane_backward_osm = n_lane_forward_osm
246        else:
247            # no information on total of lanes
248            if is_oneway_osm:
249                # in cas of oneway
250                n_lane_backward_osm = 0
251                if osmattrs.has_key('lanes:forward'):
252                    n_lane_forward_osm = int(osmattrs['lanes:forward'])
253                    is_lanes_forward_rigid = True
254                else:
255                    n_lane_forward_osm = self.n_lane  # default
256            else:
257                # bidir
258                if osmattrs.has_key('lanes:forward'):
259                    n_lane_forward_osm = int(osmattrs['lanes:forward'])
260                    is_lanes_forward_rigid = True
261                    if osmattrs.has_key('lanes:backward'):
262                        n_lane_backward_osm = int(osmattrs['lanes:backward'])
263                        is_lanes_backward_rigid = True
264                    else:
265                        n_lane_backward_osm = self.n_lane  # default
266
267                elif osmattrs.has_key('lanes:backward'):
268                    n_lane_backward_osm = int(osmattrs['lanes:backward'])
269                    is_lanes_backward_rigid = True
270                    n_lane_forward_osm = self.n_lane  # default
271
272                else:
273                    # no lane information
274                    n_lane_forward_osm = self.n_lane  # default
275                    n_lane_backward_osm = self.n_lane  # default
276
277            n_lane_osm = n_lane_forward_osm+n_lane_backward_osm
278
279        self._is_lanes_backward_rigid = is_lanes_backward_rigid
280        self._is_lanes_forward_rigid = is_lanes_forward_rigid
281
282        self._n_lane_forward_osm = n_lane_forward_osm
283        self._n_lane_backward_osm = n_lane_backward_osm
284        self._n_lane_osm = n_lane_osm
285        print '  lane numbers: n_lane_forward_osm=%d, n_lane_backward_osm=%d n_default=%d' % (
286            n_lane_forward_osm, n_lane_backward_osm, self.n_lane)
287
288    def _get_access(self, access_str):
289        access_data = np.array(access_str.split('|'), dtype=np.object)[::-1]
290        return access_data == 'designated', access_data == 'no'
291
292    def get_laneaccess(self, vname, is_opp=False):
293        if is_opp:
294            if self._is_lanes_backward_rigid:
295                osmattrs = self._osmattrs
296                access_str = osmattrs.get(vname+':lanes', '')
297                if access_str != '':
298                    allowed, disallowed = self._get_access(access_str)
299                    return allowed[:self._n_lane_backward_osm], disallowed[:self._n_lane_backward_osm]
300
301                else:
302                    access_str = osmattrs.get(vname+':lanes:backward', '')
303                    if access_str != '':
304                        allowed, disallowed = self._get_access(access_str)
305                        return allowed, disallowed
306
307                    else:
308                        return [], []
309
310            else:
311                return [], []
312
313        else:
314            if self._is_lanes_forward_rigid:
315                osmattrs = self._osmattrs
316                access_str = osmattrs.get(vname+':lanes', '')
317                if access_str != '':
318                    allowed, disallowed = self._get_access(access_str)
319                    return allowed[self._n_lane_backward_osm:], disallowed[self._n_lane_backward_osm:]
320
321                else:
322                    access_str = osmattrs.get(vname+':lanes:forward', '')
323                    if access_str != '':
324                        allowed, disallowed = self._get_access(access_str)
325                        return allowed, disallowed
326
327                    else:
328                        return [], []
329
330            else:
331                return [], []
332
333    def make_road(self):
334        """
335        Makes road lanes in both directions
336        """
337
338        #lanes = []
339        #lanes_opp = []
340        print '  realoneway', self.is_oneway()
341
342        #self._lanes = []
343        #self._lanes_opp = []
344
345        print '  Main Dir ^^^^^^^^^^^'
346        if self._is_lanes_forward_rigid:
347            self.make_lanes_rigid(is_opp=False, n_lane_osm=self._n_lane_forward_osm)
348        else:
349            self.make_lanes(is_opp=False, n_lane_osm=self._n_lane_forward_osm)
350
351        if not self.is_oneway():
352
353            print '  Opp  Dir vvvvvvvvvvv'
354            if self._is_lanes_backward_rigid:
355                self.make_lanes_rigid(is_opp=True, n_lane_osm=self._n_lane_backward_osm)
356            else:
357                self.make_lanes(is_opp=True, n_lane_osm=self._n_lane_backward_osm)
358
359        print '  id', id(self)
360        print '  len(self._lanes)', len(self._lanes)
361        print '  len(self._lanes_opp)', len(self._lanes_opp)
362
363    def _get_speedinfo(self, speed_max_str):
364        speed_max_data = speed_max_str.split(' ')
365        if len(speed_max_data) == 1:
366            #speed_max_data = speed_max_data[0].split(';')
367            # TODO: here we could do a per lane assignment
368            return float(speed_max_data[0])/3.6
369        else:
370
371            # todo
372            # maxspeed=60
373            # maxspeed=50 mph
374            # maxspeed=10 knots
375            unit = speed_max_data[1]
376            if unit == 'mph':
377                return float(speed_max_data[0])/3.6*1.609344
378
379            elif unit == 'knots':
380                return float(speed_max_data[0])/3.6*1.852
381
382    def make_speed(self, speed_max_default):
383        # estimate speed max in m/s
384        if self._osmattrs.has_key('maxspeed'):
385            speed_max_str = self._osmattrs['maxspeed']
386            if speed_max_str.count(';') > 0:
387                speed_max = np.inf
388                for v_str in speed_max_str.split(';'):
389                    v = self._get_speedinfo(v_str)
390                    if v < speed_max:
391                        speed_max = v
392
393            else:
394                speed_max = self._get_speedinfo(speed_max_str)
395        else:
396            speed_max = speed_max_default
397
398        self.speed_max = speed_max
399
400    def _is_opposite(self, osmattrs, tag):
401        if osmattrs.has_key(tag):
402            elems = osmattrs[tag].split('_')
403            return elems[0] == 'opposite'
404        else:
405            return False
406
407    def is_oneway(self):
408        return self._is_oneway
409
410    def make_oneway(self):
411        # print 'make_oneway'
412        osmattrs = self._osmattrs
413
414        if osmattrs.get('junction', '') == 'roundabout':
415            self._is_oneway = True
416
417        elif osmattrs.has_key('oneway'):
418            if osmattrs['oneway'] == 'no':
419                self._is_oneway = False
420
421            else:
422                if self._is_opposite(osmattrs, 'busway'):
423                    self._is_oneway = False
424
425                elif self._is_opposite(osmattrs, 'busway:right'):
426                    self._is_oneway = False
427
428                elif osmattrs.has_key('lanes:bus:backward'):
429                    self._is_oneway = False
430
431                elif osmattrs.has_key('trolley_wire:both'):
432                    self._is_oneway = False
433
434                elif osmattrs.has_key('lanes:psv:backward'):
435                    self._is_oneway = False
436
437                elif self._is_opposite(osmattrs, 'cycleway'):
438                    self._is_oneway = False
439
440                elif self._is_opposite(osmattrs, 'busway'):
441                    self._is_oneway = False
442
443                elif osmattrs.get('cycleway', '') == 'both':
444                    self._is_oneway = False
445
446                # elif osmattrs.get('busway','') == 'both':
447                #    self._is_oneway = False
448
449                # sidewalks on both sides go in the same direction
450                # elif osmattrs.get('sidewalk','') == 'both':
451                #    self._is_oneway = False
452
453                elif osmattrs.has_key('oneway:bicycle'):
454                    if osmattrs['oneway:bicycle'] == 'no':
455                        self._is_oneway = False
456
457                    else:
458                        self._is_oneway = True
459
460                else:
461                    self._is_oneway = True
462
463        else:
464            self._is_oneway = False
465
466    def add_sidewalk(self, road, is_opp=False):
467        """
468        Method to explicitely add sidewalks with the given road attributes
469        """
470        osmattrs = self._osmattrs
471
472        if is_opp:
473            ind = 0
474        else:
475            ind = 1
476
477        print 'add_sidewalk', is_opp, self._sidewalkattrs[ind]['n_lane'], self._sidewalkattrs[ind]['n_lane'] == 0
478        if self._sidewalkattrs[ind]['n_lane'] == 0:
479            self.make_sidewalk(is_opp=is_opp, is_rightside=True, width=road.lanewidth)
480            self.make_road()
481
482        # if self._is_oneway:
483        #    # generate sidewalks in both directions
484        #    ind = 1
485        #    if self._sidewalkattrs[ind]['n_lane'] == 1:
486        #        self.make_sidewalk(is_opp = False, is_rightside = False, width = road.lanewidth)
487
488    def make_sidewalk(self, is_opp=False, is_rightside=True,
489                      ids_modes_allow=[], width=1.0, n_lane=1):
490
491        if is_opp:
492            ind = 0
493        else:
494            ind = 1
495        #  !!!!foot=use_sidepath may be applied on the street
496        #  to mark that sidewalks are mapped separately.
497        # Also, sidewalk=separate
498
499        print 'make_sidewalk', ind, is_rightside
500        # needed to merge access?
501        self._sidewalkattrs[ind]['is_share'] = len(ids_modes_allow) > 0
502
503        ids_allowed_set = [ID_MODE_PED]
504        for id_mode in ids_modes_allow:
505            if id_mode not in ids_allowed_set:
506                ids_allowed_set.append(id_mode)
507
508        self._sidewalkattrs[ind]['ids_modes_allow'] = list(ids_allowed_set)
509        self._sidewalkattrs[ind]['ids_modes_disallow'] = []
510        if is_rightside:
511            self._sidewalkattrs[ind]['is_rightside'] = True
512            self._sidewalkattrs[ind]['width_rightside'] = width
513            self._sidewalkattrs[ind]['n_lane'] += n_lane
514        else:
515            self._sidewalkattrs[ind]['is_leftside'] = True
516            self._sidewalkattrs[ind]['width_leftside'] = width
517            self._sidewalkattrs[ind]['n_lane'] += n_lane
518
519        self._sidewalkattrs[ind]['speed_max'] = self.speed_max_ped
520        # print '  sidewalkattr=',self._sidewalkattrs[ind]
521        print_attrs(self._sidewalkattrs[ind])
522
523    def make_sidewalkattrs(self):
524        print 'make_sidewalkattrs'
525        osmattrs = self._osmattrs
526        self._sidewalkattrs = (deepcopy(LANEATTRS_DEFAULT),
527                               deepcopy(LANEATTRS_DEFAULT))
528
529        sidewalk = osmattrs.get('sidewalk', 'auto')
530
531        if sidewalk not in ['no', 'none', 'auto']:
532            # there is a sidewalk, make sure there is at least one
533
534            if osmattrs.has_key('sidewalk:width'):
535                width_left = float(osmattrs['sidewalk:width'])
536                width_right = width_left
537
538            elif osmattrs.has_key('sidewalk:both:width'):
539                width_left = float(osmattrs['sidewalk:both:width'])
540                width_right = width_left
541            else:
542                width_left = float(osmattrs.get('sidewalk:left:width', self.width_sidewalk))
543                width_right = float(osmattrs.get('sidewalk:right:width', self.width_sidewalk))
544
545            if osmattrs.get('oneway', 'no') == 'no':
546                # bidirecional
547
548                if sidewalk == 'both':
549                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
550                    self.make_sidewalk(is_opp=True, is_rightside=True, width=width_left)
551
552                elif sidewalk == 'left':
553                    self.make_sidewalk(is_opp=True, is_rightside=True, width=width_left)
554
555                elif sidewalk == 'right':
556                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
557
558                else:
559                    # no indication means both
560                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
561                    self.make_sidewalk(is_opp=True, is_rightside=True, width=width_left)
562
563            else:
564                # oneway
565                if sidewalk == 'both':
566                    # both sidewalks go in the same direction
567                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
568                    self.make_sidewalk(is_opp=False, is_rightside=False, width=width_left)
569
570                elif sidewalk == 'left':
571                    self.make_sidewalk(is_opp=False, is_rightside=False, width=width_left)
572
573                elif sidewalk == 'right':
574                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
575
576                else:
577                    # no indication means both
578                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
579                    self.make_sidewalk(is_opp=False, is_rightside=False, width=width_left)
580
581        # if no siedewalk width_sidewalk = -1
582        #self.width_sidewalk = max(widths)
583        # print '  sidewalkattr='#,self._sidewalkattrs
584        # for attrs in self._sidewalkattrs:
585        #    if attrs['n_lane']>0:
586        #        print_attrs(attrs)
587
588    def make_bikelane(self, is_opp=False, is_rightside=True,
589                      ids_modes_allow=[], width=1.5, n_lane=1):
590        print 'make_bikelane', is_opp, is_rightside, ids_modes_allow
591        if is_opp:
592            ind = 0
593        else:
594            ind = 1
595
596        # needed to merge access?
597        self._bikewayattrs[ind]['is_share'] = len(ids_modes_allow) > 0
598
599        ids_allowed_set = deepcopy(self.ids_modes_bike)
600        for id_mode in ids_modes_allow:
601            if id_mode not in ids_allowed_set:
602                ids_allowed_set.append(id_mode)
603
604        self._bikewayattrs[ind]['ids_modes_allow'] = list(ids_allowed_set)
605        self._bikewayattrs[ind]['ids_modes_disallow'] = []
606        if is_rightside:
607            self._bikewayattrs[ind]['is_rightside'] = True
608            self._bikewayattrs[ind]['width_rightside'] = width
609            self._bikewayattrs[ind]['n_lane'] += n_lane
610        else:
611            self._bikewayattrs[ind]['is_leftside'] = True
612            self._bikewayattrs[ind]['width_leftside'] = width
613            self._bikewayattrs[ind]['n_lane'] += n_lane
614
615        self._bikewayattrs[ind]['speed_max'] = self.speed_max_bike
616
617        print_attrs(self._bikewayattrs[ind])
618
619    def make_bikewayattrs(self):
620        """ Returns a tuple with attribute dictionaries for bikeways
621            on left and right side of the road.
622                Dictionary with the following keys:
623                widths:  is a tuple with sidewalk widths of left and right sidewalk.
624                if values are less than 0 means no sidewalk.
625        """
626        print 'make_bikewayattrs'
627        self._bikewayattrs = (deepcopy(LANEATTRS_DEFAULT),
628                              deepcopy(LANEATTRS_DEFAULT))
629
630        osmattrs = self._osmattrs
631        cycleway = osmattrs.get('cycleway', '')
632        cycleway_left = osmattrs.get('cycleway:left', '')
633        cycleway_right = osmattrs.get('cycleway:right', '')
634
635        if osmattrs.has_key('cycleway:width'):
636            width_left = float(osmattrs['cycleway:width'])
637            width_right = width_left
638
639        elif osmattrs.has_key('cycleway:both:width'):
640            width_left = float(osmattrs['cycleway:both:width'])
641            width_right = width_left
642
643        else:
644            width_left = float(osmattrs.get('cycleway:left:width', self.lanewidth_bike))
645            width_right = float(osmattrs.get('cycleway:right:width', self.lanewidth_bike))
646
647        if osmattrs.get('oneway', 'no') == 'no':
648            # cycle lanes on bidir road
649
650            if cycleway in LANEATTRS:
651                self.make_bikelane(is_opp=False, width=width_right)
652                self.make_bikelane(is_opp=True, width=width_left)
653                return
654
655            elif cycleway in OSMKEYS_SHARED:
656                self.make_bikelane(is_opp=False, ids_modes_allow=self.ids_modes_pt_shared, width=width_right)
657                self.make_bikelane(is_opp=True, ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
658                return
659
660            elif cycleway in OSMKEYS_SHARED_OPP:
661                self.make_bikelane(is_opp=False, width=width_right)
662                self.make_bikelane(is_opp=True, ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
663                return
664
665            cycleway = osmattrs.get('cycleway:both', '')
666            if cycleway in LANEATTRS:
667                self.make_bikelane(is_opp=False, width=width_right)
668                self.make_bikelane(is_opp=True, width=width_left)
669                return
670
671            elif cycleway in OSMKEYS_SHARED:
672                self.make_bikelane(is_opp=False, ids_modes_allow=self.ids_modes_pt_shared, width=width_right)
673                self.make_bikelane(is_opp=True, ids_modes_allow=self.ids_modes_pt_shared, width=width_right)
674                return
675
676            #cycleway = osmattrs.get('cycleway:left','')
677            if (cycleway_left != '') & (cycleway_right != ''):
678                # also both sides
679                if cycleway_left in LANEATTRS:
680                    self.make_bikelane(is_opp=True, is_rightside=False, width=width_left)
681                elif cycleway_left in OSMKEYS_SHARED:
682                    self.make_bikelane(is_opp=True, ids_modes_allow=self.ids_modes_pt_shared)
683
684                if cycleway_right in LANEATTRS:
685                    self.make_bikelane(is_opp=False, is_rightside=False, width=width_left)
686                elif cycleway_right in OSMKEYS_SHARED:
687                    self.make_bikelane(is_opp=False, ids_modes_allow=self.ids_modes_pt_shared)
688
689            # check left only
690            elif cycleway_left in LANEATTRS:
691                self.make_bikelane(is_opp=True, is_rightside=False, width=width_left)
692                return
693
694            elif cycleway_left in OSMKEYS_SHARED:
695                self.make_bikelane(is_opp=True, ids_modes_allow=self.ids_modes_pt_shared)
696                # if osmattrs.get('bicycle','no') == 'yes':
697                #    self.make_bikelane(is_opp = False, is_rightside = True,width = width_right)
698
699            # check right only
700            elif cycleway_right in LANEATTRS:
701                self.make_bikelane(is_opp=False, is_rightside=True)
702
703            elif cycleway_right == 'opposite_share_busway':
704                self.make_bikelane(is_opp=True, ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
705                # if osmattrs.get('bicycle','no') == 'yes':
706                #    self.make_bikelane(is_opp = False, is_rightside = True,width = width_right)
707
708            # general bicycle tag if all from abive fails but share with pedestrians
709            elif osmattrs.get('bicycle', 'no') == 'yes':
710                # check if there are cycle lanes already
711                if (self._bikewayattrs[0]['n_lane'] == 0) & (self._bikewayattrs[1]['n_lane'] == 0):
712                    self.make_bikelane(is_opp=False, is_rightside=True,
713                                       width=width_right, ids_modes_allow=[ID_MODE_PED, ])
714                    self.make_bikelane(is_opp=True, is_rightside=True, width=width_left,
715                                       ids_modes_allow=[ID_MODE_PED, ])
716
717        else:
718            # cycle lanes on oneway road
719
720            if cycleway in LANEATTRS:
721
722                self.make_bikelane(is_opp=False)
723
724                if osmattrs.get('oneway:bicycle', 'yes') == 'no':
725                    self.make_bikelane(is_opp=True, width=width_left)
726                # else:
727                #    self.make_bikelane(is_opp = False, width = width_right)
728                return
729
730            elif cycleway == 'opposite':
731                self.make_bikelane(is_opp=True, is_rightside=True, width=width_left)
732                # if osmattrs.get('bicycle','no') == 'yes':
733                #    self.make_bikelane(is_opp = False, is_rightside = True, width = width_right)
734                return
735
736            elif cycleway == 'opposite_share_busway':
737                self.make_bikelane(is_opp=True, is_rightside=True,
738                                   ids_modes_allow=self.ids_modes_pt_shared, width=width_right)
739                # if osmattrs.get('bicycle','no') == 'yes':
740                #    self.make_bikelane(is_opp = False, is_rightside = True,width = width_right)
741                return
742
743            if cycleway == 'both':
744                # attention with  this key a cycle lane in the opposite direction
745                # will be created as it makes no sense to have bikelanes
746                # in the smae direction on both sides
747                self.make_bikelane(is_opp=False, is_rightside=True, width=width_right)
748                self.make_bikelane(is_opp=True, is_rightside=True, width=width_left)
749
750            elif cycleway_right in LANEATTRS:
751                self.make_bikelane(is_opp=False, width=width_right)
752
753            elif cycleway_left in LANEATTRS:
754                self.make_bikelane(is_opp=False, is_rightside=False, width=width_right)
755
756            elif cycleway_left == 'opposite_lane':
757                self.make_bikelane(is_opp=True, is_rightside=True, width=width_left)
758                # if osmattrs.get('bicycle','no') == 'yes':
759                #    self.make_bikelane(is_opp = False, is_rightside = True,width = width_right)
760
761            elif osmattrs.get('oneway:bicycle', '') == 'no':
762                self.make_bikelane(is_opp=True, is_rightside=False, width=width_right)
763                # if (osmattrs.get('bicycle','no') == 'yes'):
764                #    # check if there are cycle lanes already
765                #    if (self._bikewayattrs[1]['n_lane'] == 0):
766                #        self.make_bikelane(is_opp = False, is_rightside = True, width = width_right)
767
768            # if (osmattrs.get('bicycle','no') == 'yes'):
769            #    # check if there are cycle lanes already
770            #    if (self._bikewayattrs[1]['n_lane'] == 0):
771            #        self.make_bikelane(is_opp = False, is_rightside = True, width = width_right)
772
773        # print '  bikewayattrs='#,self._bikewayattrs
774        # for attrs in self._bikewayattrs:
775        #    if attrs['n_lane']>0:
776        #        print_attrs(attrs)
777
778    def make_buslane(self, is_opp=False, is_rightside=True,
779                     ids_modes_allow=[], width=3.5, n_lane=1):
780        print 'make_buslane', is_opp, is_rightside, width
781        if is_opp:
782            ind = 0
783        else:
784            ind = 1
785
786        #self._buswayattrs[ind]['is_share'] = len(ids_modes_allow)>0
787
788        ids_allowed_set = deepcopy(self.ids_modes_pt_shared)
789        for id_mode in ids_modes_allow:
790            if id_mode not in ids_allowed_set:
791                ids_allowed_set.append(id_mode)
792
793        self._buswayattrs[ind]['ids_modes_allow'] = list(ids_allowed_set)
794        self._buswayattrs[ind]['ids_modes_disallow'] = []
795
796        if is_rightside:
797            self._buswayattrs[ind]['is_rightside'] = True
798            self._buswayattrs[ind]['width_rightside'] = width
799            self._buswayattrs[ind]['n_lane'] += n_lane
800        else:
801            self._buswayattrs[ind]['is_leftside'] = True
802            self._buswayattrs[ind]['width_leftside'] = width
803            self._buswayattrs[ind]['n_lane'] += n_lane
804        # print '  buswayattr',self._buswayattrs[ind]
805        self._buswayattrs[ind]['speed_max'] = self.speed_max_bus
806        print_attrs(self._buswayattrs[ind])
807
808    def make_buswayattrs(self):
809        print 'make_buswayattrs'
810        self._buswayattrs = (deepcopy(LANEATTRS_DEFAULT),
811                             deepcopy(LANEATTRS_DEFAULT))
812
813        osmattrs = self._osmattrs
814
815        if osmattrs.has_key('busway:width'):
816            width_left = float(osmattrs['busway:width'])
817            width_right = width_left
818
819        elif osmattrs.has_key('busway:both:width'):
820            width_left = float(osmattrs['busway:both:width'])
821            width_right = width_left
822        else:
823            width_left = float(osmattrs.get('busway:left:width', self.lanewidth_bus))
824            width_right = float(osmattrs.get('busway:right:width', self.lanewidth_bus))
825
826        busway = osmattrs.get('busway', '')
827
828        if busway is not "":
829            # busway scheme
830            if osmattrs.get('oneway', 'no') == 'no':
831                # bidir
832                print '  buslane bidir', busway
833                if busway == 'lane':
834                    self.make_buslane(is_opp=False)
835                    self.make_buslane(is_opp=True)
836                    return
837
838                elif busway in OSMKEYS_SHARED:
839                    self.make_buslane(is_opp=False, ids_modes_allow=self.ids_modes_pt_shared, width=width_right)
840                    self.make_buslane(is_opp=True, ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
841                    return
842
843                busway = osmattrs.get('busway:both', '')
844                if busway == 'lane':
845                    self.make_buslane(is_opp=False)
846                    self.make_buslane(is_opp=True)
847                    return
848
849                elif busway in OSMKEYS_SHARED:
850                    self.make_buslane(is_opp=False, ids_modes_allow=self.ids_modes_pt_shared, width=width_right)
851                    self.make_buslane(is_opp=True, ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
852
853                # elif busway in OSMKEYS_SHARED_OPP :
854                #    self.make_buslane(is_opp = True, ids_modes_allow = self.ids_modes_pt_shared)
855
856                busway = osmattrs.get('busway:left', '')
857                if busway == 'lane':
858                    self.make_buslane(is_opp=True, is_rightside=False, width=width_left)
859
860                elif busway in OSMKEYS_SHARED:
861                    self.make_buslane(is_opp=True,  is_rightside=False,
862                                      ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
863
864                elif busway in OSMKEYS_SHARED_OPP:
865                    self.make_buslane(is_opp=True,  is_rightside=False,
866                                      ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
867
868                busway = osmattrs.get('busway:right', '')
869                if busway == 'lane':
870                    self.make_buslane(is_opp=False)
871
872                elif busway in OSMKEYS_SHARED:
873                    self.make_buslane(is_opp=False, ids_modes_allow=self.ids_modes_pt_shared, width=width_right)
874
875                elif busway in OSMKEYS_SHARED_OPP:
876                    self.make_buslane(is_opp=True,  ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
877
878                return
879
880            else:
881                # cycle lanes on oneway road
882                print '  buslane oneway', busway, busway in ('opposite', 'opposite_lane')
883                if busway == 'lane':
884                    self.make_buslane(is_opp=False, width=width_right)
885
886                    if osmattrs.get('oneway:bus', 'yes') == 'no':
887                        self.make_buslane(is_opp=True, width=width_left)
888                    return
889
890                elif busway in ('opposite', 'opposite_lane'):
891                    self.make_buslane(is_opp=True, is_rightside=False, width=width_left)
892
893                elif busway == 'opposite_share_busway':
894                    self.make_buslane(is_opp=True, is_rightside=False,
895                                      ids_modes_allow=self.ids_modes_pt_shared, width=width_left)
896
897                elif self._osmattrs.get('busway:right', '') == 'lane':
898                    self.make_buslane(is_opp=False, width=width_right)
899
900                elif self._osmattrs.get('busway:left', '') == 'lane':
901                    self.make_buslane(is_opp=False, is_rightside=False, width=width_right)
902
903                elif self._osmattrs.get('busway:left', '') == 'opposite_lane':
904                    self.make_buslane(is_opp=True, width=width_left)
905
906                return
907
908        elif osmattrs.has_key('lanes:psv'):
909            # lanes:psv=* scheme
910            if osmattrs.get('oneway', 'no') == 'no':
911                # bidir
912                pvs = int(osmattrs.get('lanes:psv', '1'))
913                if pvs/2 > 1:
914                    self.make_buslane(is_opp=True, n_lane=pvs/2, width=width_right)
915                    self.make_buslane(is_opp=False, n_lane=pvs/2, width=width_left)
916                else:
917                    self.make_buslane(is_opp=False, n_lane=1, width=width_right)
918            else:
919                # oneway
920                pvs = int(osmattrs.get('lanes:psv', '1'))
921                self.make_buslane(is_opp=False, n_lane=pvs, width=width_right)
922            return
923
924        elif osmattrs.has_key('lanes:bus'):
925            # lanes:psv=* scheme
926            if osmattrs.get('oneway', 'no') == 'no':
927                # bidir
928                pvs = int(osmattrs.get('lanes:bus', '1'))
929                if pvs/2 > 1:
930                    self.make_buslane(is_opp=True, n_lane=pvs/2, width=width_right)
931                    self.make_buslane(is_opp=False, n_lane=pvs/2, width=width_left)
932                else:
933                    self.make_buslane(is_opp=False, n_lane=1, width=width_right)
934            else:
935                # oneway
936                pvs = int(osmattrs.get('lanes:bus', '1'))
937                self.make_buslane(is_opp=False, n_lane=pvs, width=width_right)
938            return
939
940        if osmattrs.has_key('lanes:psv:forward'):
941            self.make_buslane(is_opp=False, n_lane=int(osmattrs['lanes:psv:forward']), width=width_right)
942
943        if osmattrs.has_key('lanes:psv:backward'):
944            self.make_buslane(is_opp=True, n_lane=int(osmattrs['lanes:psv:backward']), width=width_left)
945
946        if osmattrs.has_key('lanes:bus:forward'):
947            self.make_buslane(is_opp=False, n_lane=int(osmattrs['lanes:bus:forward']), width=width_right)
948
949        if osmattrs.has_key('lanes:bus:backward'):
950            self.make_buslane(is_opp=True, n_lane=int(osmattrs['lanes:bus:backward']), width=width_left)
951
952        if osmattrs.get('oneway', 'no') == 'yes':
953            # special check of opposite bus lane
954            if osmattrs.has_key('trolley_wire:both') | osmattrs.has_key('trolley_wire:backward'):
955                    # if way is oneway withot reserved access,
956                    # but there are wires in both ways,
957                    # then there is probably a reserved bus lane in opposite
958                    # direction
959                if self._buswayattrs[0]['n_lane'] == 0:
960                    self.make_buslane(is_opp=True, width=width_right)
961
962        # print '  buswayattrs=',self._buswayattrs
963        # for attrs in self._buswayattrs:
964        #    if attrs['n_lane']>0:
965        #        print_attrs(attrs)
966
967    def get_priority(self, is_opp=False):
968        """
969        Returns priority of road.
970
971        To be overridden.
972        """
973        if is_opp:
974            lanes = self._lanes_opp
975        else:
976            lanes = self._lanes
977
978        speed_max = self.get_speed_max()
979        n_lane = len(lanes)
980        # is_residential =...
981        if n_lane == 0:
982            return 0
983
984        if n_lane == 1:
985            if speed_max < 11.0/3.6:
986                return 1
987            elif speed_max <= 31.0/3.6:
988                return 2
989            elif speed_max <= 51.0/3.6:
990                return 3
991            else:
992                return 4
993
994        elif n_lane == 2:
995            if speed_max < 11.0/3.6:
996                return 4
997            elif speed_max <= 31.0/3.6:
998                return 5
999            elif speed_max <= 51.0/3.6:
1000                return 6
1001            else:
1002                return 7
1003
1004        elif n_lane == 3:
1005            if speed_max < 11.0/3.6:
1006                return 5
1007            elif speed_max <= 31.0/3.6:
1008                return 6
1009            elif speed_max <= 51.0/3.6:
1010                return 7
1011            elif speed_max <= 111.0/3.6:
1012                return 8
1013            else:
1014                return 9
1015
1016        elif n_lane > 3:
1017            if speed_max < 11.0/3.6:
1018                return 6
1019            elif speed_max <= 51.0/3.6:
1020                return 7
1021            elif speed_max <= 91.0/3.6:
1022                return 8
1023            elif speed_max <= 111.0/3.6:
1024                return 9
1025            else:
1026                return 10
1027
1028    def merge_laneattrs(self, laneattrs_dest, laneattrs_merge, is_rightside=False, is_leftside=False):
1029        print 'merge_laneattrs'
1030        # print '  laneattrs_dest',laneattrs_dest
1031        # print '  laneattrs_merge',laneattrs_merge
1032        #self._buswayattrs[ind]['ids_modes_allow'] = ids_allowed
1033        #self._buswayattrs[ind]['width'] = width
1034        #self._buswayattrs[ind]['is_rightside'] = is_rightside
1035        # if laneattrs_merge['width']>laneattrs_dest['width']:
1036        width_dest = 0.0
1037        if laneattrs_dest.has_key('width'):
1038            width_dest = laneattrs_dest['width']
1039        else:
1040            if is_rightside:
1041                width_dest = laneattrs_dest['width_rightside']
1042            else:
1043                width_dest = laneattrs_dest['width_leftside']
1044
1045        if laneattrs_merge.has_key('width'):
1046            width_merge = laneattrs_merge['width']
1047        else:
1048            if is_rightside:
1049                width_merge = laneattrs_merge['width_rightside']
1050            else:
1051                width_merge = laneattrs_merge['width_leftside']
1052
1053        # if width_dest<width_merge:
1054        #    laneattrs_dest['width'] = width_merge
1055        # else:
1056        laneattrs_dest['width'] = width_dest
1057
1058        if laneattrs_dest['speed_max'] > laneattrs_merge['speed_max']:
1059            laneattrs_dest['speed_max'] = laneattrs_merge['speed_max']
1060
1061        self.disallow_on_lane(laneattrs_dest, laneattrs_merge['ids_modes_disallow'])
1062        self.allow_on_lane(laneattrs_dest, laneattrs_merge['ids_modes_allow'])
1063
1064    def append_lane(self, lanes, laneattrs, is_rightside=False, is_leftside=False):
1065        if is_rightside:
1066            lanes.insert(0, deepcopy(laneattrs))
1067            lanes[0]['width'] = laneattrs['width_rightside']
1068
1069        elif is_leftside:
1070            lanes.append(deepcopy(laneattrs))
1071            lanes[-1]['width'] = laneattrs['width_leftside']
1072
1073    def set_lane(self, lanes, laneattrs, ind):
1074        lanes[ind] = deepcopy(laneattrs)
1075        if not laneattrs.has_key('width'):
1076            if laneattrs.has_key('width_rightside'):
1077                lanes[ind]['width'] = laneattrs['width_rightside']
1078            else:
1079                lanes[ind]['width'] = laneattrs['width_rightside']
1080
1081    def disallow_on_lane(self, laneattrs, ids_disallow):
1082        # print 'disallow_on_lane ids_disallow',ids_disallow
1083        for id_disallow in ids_disallow:
1084            if id_disallow in laneattrs['ids_modes_allow']:
1085                laneattrs['ids_modes_allow'].remove(id_disallow)
1086
1087        if len(laneattrs['ids_modes_allow']) == 0:
1088            for id_disallow in ids_disallow:
1089                if id_disallow not in laneattrs['ids_modes_disallow']:
1090                    laneattrs['ids_modes_disallow'].append(id_disallow)
1091        else:
1092            laneattrs['ids_modes_disallow'] = []
1093
1094    def allow_on_lane(self, laneattrs, ids_allow):
1095        laneattrs['ids_modes_disallow'] = []
1096
1097        for id_allow in ids_allow:
1098            if id_allow not in laneattrs['ids_modes_allow']:
1099                laneattrs['ids_modes_allow'].append(id_allow)
1100
1101    def make_lanes_rigid(self, is_opp=False, n_lane_osm=0):
1102        print 'make_lanes_rigid', is_opp, n_lane_osm
1103        osmattrs = self._osmattrs
1104
1105        if is_opp:
1106            ind = 0
1107            if self._is_oneway:
1108                self._lanes_opp = []
1109                return False
1110        else:
1111            ind = 1
1112
1113        lanes = []
1114        for i in range(n_lane_osm):
1115            lanes.append(deepcopy(self._laneattrs_main))
1116
1117        # if is_lanes_rigid:
1118        #    # respect given lane numbers for main modes, except footpath
1119        #    pass
1120        # else:
1121
1122        # do busways
1123        attrs = self._buswayattrs[ind]
1124
1125        if attrs['n_lane'] > 0:
1126            print '  busways n_lane', attrs['n_lane']
1127
1128            n_lane = len(lanes)
1129
1130            allowed, disallowed = self.get_laneaccess('bus', is_opp=is_opp)
1131            if len(allowed) == 0:
1132                allowed, disallowed = self.get_laneaccess('psv', is_opp=is_opp)
1133
1134            n_allow = len(allowed)
1135            if n_allow > 0:
1136                for i, a, d in zip(xrange(n_allow), allowed, disallowed):
1137                    if ind < n_lane:
1138                        if a & (i < n_lane):
1139                            self.set_lane(lanes, attrs, i)
1140                        if d:
1141                            self.disallow_on_lane(lanes[i], attrs['ids_modes_disallow'])
1142
1143            else:
1144                n_lane_assig = attrs['n_lane']
1145                for i in range(n_lane):
1146                    if n_lane_assig > 0:
1147                        if attrs['is_rightside']:
1148                            self.merge_laneattrs(lanes[i], attrs, is_rightside=True)
1149                            n_lane_assig -= 1
1150
1151                        if attrs['is_leftside']:
1152                            self.merge_laneattrs(lanes[n_lane-i-1], attrs, is_leftside=True)
1153                            n_lane_assig -= 1
1154
1155        # do bikeways
1156        attrs = self._bikewayattrs[ind]
1157        if attrs['n_lane'] > 0:
1158            print '  bikeways n_lane', attrs['n_lane']
1159
1160            n_lane = len(lanes)
1161
1162            allowed, disallowed = self.get_laneaccess('bicycle', is_opp=is_opp)
1163
1164            n_allow = len(allowed)
1165            if n_allow > 0:
1166                for i, a, d in zip(xrange(n_allow), allowed, disallowed):
1167                    if i < n_lane:
1168                        if a & i < n_lane:
1169                            self.set_lane(lanes, attrs, i)
1170                        if d:
1171                            self.disallow_on_lane(lanes[i], attrs['ids_modes_disallow'])
1172
1173            else:
1174                n_lane_assig = attrs['n_lane']
1175                for i in range(n_lane):
1176                    if n_lane_assig > 0:
1177                        if attrs['is_rightside']:
1178                            self.merge_laneattrs(lanes[i], attrs, is_rightside=True)
1179                            n_lane_assig -= 1
1180
1181                        if attrs['is_leftside']:
1182                            self.merge_laneattrs(lanes[n_lane-i-1], attrs, is_leftside=True)
1183                            n_lane_assig -= 1
1184
1185        # do sidewalks
1186        attrs = self._sidewalkattrs[ind]
1187        if attrs['n_lane'] > 0:
1188            print '  sidewalks n_lane', attrs['n_lane']
1189            n_lane_assig = attrs['n_lane']
1190            n_lane = len(lanes)
1191            # sidewalks are not considered lanes in osm
1192            # so we append/prepend them
1193            while n_lane_assig > 0:
1194                if attrs['is_rightside']:
1195                    if attrs['is_share'] & (len(lanes) > 0):
1196                        self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
1197                    else:
1198                        self.append_lane(lanes, attrs, is_rightside=True)
1199                    n_lane_assig -= 1
1200                if attrs['is_leftside']:
1201                    if attrs['is_share'] & (len(lanes) > 0):
1202                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
1203                    else:
1204                        self.append_lane(lanes, attrs, is_leftside=True)
1205                    n_lane_assig -= 1
1206
1207            # disallow pedestrians on other lanes
1208            #
1209            for laneattrs in lanes:
1210                if ID_MODE_PED not in laneattrs['ids_modes_allow']:
1211                    self.disallow_on_lane(laneattrs, [ID_MODE_PED])
1212
1213        if is_opp:
1214            self._lanes_opp = lanes
1215        else:
1216            self._lanes = lanes
1217        print '  created %d lanes' % len(lanes)
1218        # print '  lanes', lanes
1219        for laneattrs in lanes:
1220            print_attrs(laneattrs)
1221        return True
1222
1223    def make_lanes(self, is_opp=False, n_lane_osm=0):
1224        print 'make_lanes', is_opp, n_lane_osm
1225        osmattrs = self._osmattrs
1226        is_lanes_rigid = False
1227
1228        if is_opp:
1229            ind = 0
1230            if self._is_oneway:
1231                self._lanes_opp = []
1232                return False
1233        else:
1234            ind = 1
1235
1236        lanes = []
1237        for i in range(n_lane_osm):
1238            lanes.append(deepcopy(self._laneattrs_main))
1239
1240        # do busways
1241        attrs = self._buswayattrs[ind]
1242        if attrs['n_lane'] > 0:
1243            print '  busways n_lane', attrs['n_lane']
1244            n_lane_assig = attrs['n_lane']
1245            n_lane = len(lanes)
1246
1247            while n_lane_assig > 0:
1248                if attrs['is_rightside']:
1249                    self.append_lane(lanes, attrs, is_rightside=True)
1250                    n_lane_assig -= 1
1251                if attrs['is_leftside']:
1252                    self.append_lane(lanes, attrs, is_leftside=True)
1253                    n_lane_assig -= 1
1254
1255        # do bikeways
1256        attrs = self._bikewayattrs[ind]
1257        if attrs['n_lane'] > 0:
1258            print '  bikeways n_lane', attrs['n_lane']
1259            n_lane_assig = attrs['n_lane']
1260            n_lane = len(lanes)
1261
1262            while n_lane_assig > 0:
1263                if attrs['is_rightside']:
1264                    if attrs['is_share'] & (len(lanes) > 0):
1265                        self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
1266                    else:
1267                        self.append_lane(lanes, attrs, is_rightside=True)
1268                    n_lane_assig -= 1
1269
1270                if attrs['is_leftside']:
1271                    if attrs['is_share'] & (len(lanes) > 0):
1272                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
1273                    else:
1274                        self.append_lane(lanes, attrs, is_leftside=True)
1275                    n_lane_assig -= 1
1276
1277        # do sidewalks
1278        attrs = self._sidewalkattrs[ind]
1279        if attrs['n_lane'] > 0:
1280            print '  sidewalks n_lane', attrs['n_lane']
1281            n_lane_assig = attrs['n_lane']
1282            n_lane = len(lanes)
1283            # sidewalks are not considered lanes in osm
1284            # so we append/prepend them
1285            while n_lane_assig > 0:
1286                if attrs['is_rightside']:
1287                    if attrs['is_share'] & (len(lanes) > 0):
1288                        self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
1289                    else:
1290                        self.append_lane(lanes, attrs, is_rightside=True)
1291                    n_lane_assig -= 1
1292                if attrs['is_leftside']:
1293                    if attrs['is_share'] & (len(lanes) > 0):
1294                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
1295                    else:
1296                        self.append_lane(lanes, attrs, is_leftside=True)
1297                    n_lane_assig -= 1
1298
1299            # disallow pedestrians on other lanes
1300            #
1301            for laneattrs in lanes:
1302                if ID_MODE_PED not in laneattrs['ids_modes_allow']:
1303                    self.disallow_on_lane(laneattrs, [ID_MODE_PED])
1304
1305        if is_opp:
1306            self._lanes_opp = lanes
1307        else:
1308            self._lanes = lanes
1309        print '  created %d lanes' % len(lanes)
1310        # print '  lanes', lanes
1311        for laneattrs in lanes:
1312            print_attrs(laneattrs)
1313        return True
1314
1315    def get_speed_max(self, is_opp=False):
1316        # TODO: go through lanes and get speed max
1317        return self.speed_max
1318
1319    def is_roundabout(self):
1320        return self._osmattrs.get('junction', '') == 'roundabout'
1321
1322    def configure_edge(self, id_edge, net, is_opp=False):
1323        print 'configure_edge', id_edge, net.edges.ids_sumo[id_edge], is_opp
1324        # print '  id',id(self)
1325        # print '  len(self._lanes)',len(self._lanes)
1326        # print '  len(self._lanes_opp)',len(self._lanes_opp)
1327
1328        osmattrs = self._osmattrs
1329        edges = net.edges
1330        if is_opp:
1331            ind = 0
1332            lanes = self._lanes_opp
1333        else:
1334            ind = 1
1335            lanes = self._lanes
1336
1337        if self._is_oneway:  # & (not self.is_roundabout()):
1338            type_spread = 1  # centered
1339        else:
1340            type_spread = 0  # right spread
1341
1342        wayattrs = self._sidewalkattrs[ind]
1343        if wayattrs['n_lane'] > 0:
1344            width_sidewalk = max(wayattrs.get('width_leftside', -1), wayattrs.get('width_rightside', -1))
1345        else:
1346            width_sidewalk = -1.0
1347
1348        # get max lane width
1349        lanewidth = 0.0
1350        for laneattrs in lanes:
1351            if laneattrs['width'] > lanewidth:
1352                lanewidth = laneattrs['width']
1353
1354        edges.types[id_edge] = self.highway
1355        edges.nums_lanes[id_edge] = len(lanes)
1356        edges.types_spread[id_edge] = type_spread
1357        edges.speeds_max[id_edge] = self.get_speed_max(is_opp)
1358        edges.priorities[id_edge] = self.get_priority(is_opp)
1359        edges.names[id_edge] = osmattrs.get('name', '')
1360        edges.widths_lanes_default[id_edge] = lanewidth
1361        edges.widths_sidewalk[id_edge] = width_sidewalk
1362        # edges.[id_edge] =
1363
1364        # net.edges.set_row(  id_edge,
1365        #                types_spread = type_spread,
1366        #                speeds_max = self.get_speed_max(is_opp),
1367        #                priorities = self.get_priority(is_opp),
1368        #                #'widths'=# will be done during update
1369        #                names = osmattrs.get('name',''),
1370        #                widths_lanes_default = lanewidth,
1371        #                widths_sidewalk = width_sidewalk,
1372        #                )
1373
1374        # add lanes
1375        n_lane = len(lanes)
1376        if n_lane == 0:
1377            print 'WARNING: no lane for this direction!!'
1378        ids_lane = net.lanes.add_rows(n_lane)
1379
1380        for id_lane, ind_lane, laneattrs in zip(ids_lane, xrange(n_lane), lanes):
1381            if len(laneattrs['ids_modes_allow']) == 0:
1382                id_mode_main = self.id_mode
1383            else:
1384                id_mode_main = laneattrs['ids_modes_allow'][0]
1385            net.lanes.set_row(id_lane,
1386                              indexes=ind_lane,
1387                              widths=laneattrs['width'],
1388                              speeds_max=laneattrs['speed_max'],
1389                              #offsets_end = kwargs['offsets_end'],
1390                              #ids_modes_allow = laneattrs['ids_modes_allow'],
1391                              #ids_modes_disallow = laneattrs['ids_modes_disallow'],
1392                              ids_mode=id_mode_main,
1393                              ids_edge=id_edge,
1394                              )
1395            # must be done seperately!!
1396            net.lanes.ids_modes_allow[id_lane] = laneattrs['ids_modes_allow']
1397            net.lanes.ids_modes_disallow[id_lane] = laneattrs['ids_modes_disallow']
1398
1399        edges.ids_lanes[id_edge] = list(ids_lane)
1400
1401
1402class Primary(Road):
1403
1404    def config(self):
1405        """
1406        Make defaults to be overridden
1407        """
1408        Road.config(self)
1409        self.highway = self._osmattrs.get('highway', 'primary')
1410        # put 50km/h default speed limit
1411        self.make_speed(50.0/3.6)
1412
1413        self.n_lane = 2
1414        self.id_mode = ID_MODE_CAR
1415        self.lanewidth = 3.5
1416
1417    def get_priority(self, is_opp=False):
1418        """
1419        Returns priority of road.
1420
1421        To be overridden.
1422        """
1423        if is_opp:
1424            lanes = self._lanes_opp
1425        else:
1426            lanes = self._lanes
1427
1428        speed_max = self.get_speed_max()
1429        n_lane = len(lanes)
1430        # is_residential =...
1431        if n_lane == 0:
1432            return 0
1433
1434        elif n_lane <= 2:
1435            if speed_max <= 51.0/3.6:
1436                return 7
1437            elif speed_max <= 111.0/3.6:
1438                return 8
1439            else:
1440                return 9
1441
1442        elif n_lane == 3:
1443            if speed_max <= 51.0/3.6:
1444                return 7
1445            elif speed_max <= 91.0/3.6:
1446                return 8
1447            elif speed_max <= 111.0/3.6:
1448                return 9
1449            else:
1450                return 10
1451
1452        elif n_lane > 3:
1453            return 10
1454
1455    def make_lanes_rigid(self, is_opp=False, n_lane_osm=0):
1456        print 'make_lanes_rigid', is_opp, n_lane_osm
1457        osmattrs = self._osmattrs
1458
1459        if is_opp:
1460            ind = 0
1461            if self._is_oneway:
1462                self._lanes_opp = []
1463                return False
1464        else:
1465            ind = 1
1466
1467        lanes = []
1468        for i in range(n_lane_osm):
1469            lanes.append(deepcopy(self._laneattrs_main))
1470
1471        # if is_lanes_rigid:
1472        #    # respect given lane numbers for main modes, except footpath
1473        #    pass
1474        # else:
1475
1476        # do busways
1477        attrs = self._buswayattrs[ind]
1478
1479        if attrs['n_lane'] > 0:
1480            print '  busways n_lane', attrs['n_lane']
1481
1482            n_lane = len(lanes)
1483
1484            allowed, disallowed = self.get_laneaccess('bus', is_opp=is_opp)
1485            if len(allowed) == 0:
1486                allowed, disallowed = self.get_laneaccess('psv', is_opp=is_opp)
1487
1488            n_allow = len(allowed)
1489            if n_allow > 0:
1490                for i, a, d in zip(xrange(n_allow), allowed, disallowed):
1491                    if ind < n_lane:
1492                        if a & (i < n_lane):
1493                            self.set_lane(lanes, attrs, i)
1494                        if d:
1495                            self.disallow_on_lane(lanes[i], attrs['ids_modes_disallow'])
1496
1497            else:
1498                n_lane_assig = attrs['n_lane']
1499                for i in range(n_lane):
1500                    if n_lane_assig > 0:
1501                        if attrs['is_rightside']:
1502                            self.merge_laneattrs(lanes[i], attrs, is_rightside=True)
1503                            n_lane_assig -= 1
1504
1505                        if attrs['is_leftside']:
1506                            self.merge_laneattrs(lanes[n_lane-i-1], attrs, is_leftside=True)
1507                            n_lane_assig -= 1
1508
1509        # do bikeways
1510        attrs = self._bikewayattrs[ind]
1511        if attrs['n_lane'] > 0:
1512            print '  bikeways n_lane', attrs['n_lane']
1513
1514            n_lane = len(lanes)
1515
1516            allowed, disallowed = self.get_laneaccess('bicycle', is_opp=is_opp)
1517
1518            n_allow = len(allowed)
1519            if n_allow > 0:
1520                for i, a, d in zip(xrange(n_allow), allowed, disallowed):
1521                    if i < n_lane:
1522                        if a & i < n_lane:
1523                            self.set_lane(lanes, attrs, i)
1524                        if d:
1525                            self.disallow_on_lane(lanes[i], attrs['ids_modes_disallow'])
1526
1527            else:
1528                n_lane_assig = attrs['n_lane']
1529                for i in range(n_lane):
1530                    if n_lane_assig > 0:
1531                        if attrs['is_rightside']:
1532                            if is_opp:
1533                                self.merge_laneattrs(lanes[i], attrs, is_rightside=True)
1534                            else:
1535                                # in a primary link require 2 lanes for cars
1536                                if n_lane_osm > 2:
1537                                    self.merge_laneattrs(lanes[i], attrs, is_rightside=True)
1538                                else:
1539                                    self.append_lane(lanes, attrs, is_rightside=True)
1540                            n_lane_assig -= 1
1541
1542                        if attrs['is_leftside']:
1543                            self.merge_laneattrs(lanes[n_lane-i-1], attrs, is_leftside=True)
1544                            n_lane_assig -= 1
1545
1546        # do sidewalks
1547        attrs = self._sidewalkattrs[ind]
1548        if attrs['n_lane'] > 0:
1549            print '  sidewalks n_lane', attrs['n_lane']
1550            n_lane_assig = attrs['n_lane']
1551            n_lane = len(lanes)
1552            # sidewalks are not considered lanes in osm
1553            # so we append/prepend them
1554            while n_lane_assig > 0:
1555                if attrs['is_rightside']:
1556                    if attrs['is_share'] & (len(lanes) > 0):
1557                        self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
1558                    else:
1559                        self.append_lane(lanes, attrs, is_rightside=True)
1560                    n_lane_assig -= 1
1561
1562                if attrs['is_leftside']:
1563                    if attrs['is_share'] & (len(lanes) > 0):
1564                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
1565                    else:
1566                        self.append_lane(lanes, attrs, is_leftside=True)
1567                    n_lane_assig -= 1
1568
1569            # disallow pedestrians on other lanes
1570            #
1571            for laneattrs in lanes:
1572                if ID_MODE_PED not in laneattrs['ids_modes_allow']:
1573                    self.disallow_on_lane(laneattrs, [ID_MODE_PED])
1574
1575        if is_opp:
1576            self._lanes_opp = lanes
1577        else:
1578            self._lanes = lanes
1579        print '  created %d lanes' % len(lanes)
1580        # print '  lanes', lanes
1581        for laneattrs in lanes:
1582            print_attrs(laneattrs)
1583        return True
1584
1585    def make_lanes(self, is_opp=False, n_lane_osm=0):
1586        print 'make_lanes primary', is_opp, n_lane_osm
1587        osmattrs = self._osmattrs
1588        #is_lanes_rigid = False
1589
1590        if is_opp:
1591            ind = 0
1592            if self._is_oneway:
1593                self._lanes_opp = []
1594                return False
1595        else:
1596            ind = 1
1597
1598        lanes = []
1599        for i in range(n_lane_osm):
1600            lanes.append(deepcopy(self._laneattrs_main))
1601
1602        # do busways
1603        attrs = self._buswayattrs[ind]
1604        if attrs['n_lane'] > 0:
1605            print '  busways n_lane', attrs['n_lane']
1606            n_lane_assig = attrs['n_lane']
1607            n_lane = len(lanes)
1608
1609            while n_lane_assig > 0:
1610                if attrs['is_rightside']:
1611                    self.append_lane(lanes, attrs, is_rightside=True)
1612                    n_lane_assig -= 1
1613                if attrs['is_leftside']:
1614                    self.append_lane(lanes, attrs, is_leftside=True)
1615                    n_lane_assig -= 1
1616
1617        # do bikeways
1618        attrs = self._bikewayattrs[ind]
1619        if attrs['n_lane'] > 0:
1620            print '  bikeways n_lane', attrs['n_lane']
1621            n_lane_assig = attrs['n_lane']
1622            n_lane = len(lanes)
1623
1624            while n_lane_assig > 0:
1625                if attrs['is_rightside']:
1626                    if is_opp:
1627                        if attrs['is_share'] & (len(lanes) > 0):
1628                            self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
1629                        else:
1630                            self.append_lane(lanes, attrs, is_rightside=True)
1631                    else:
1632                        # primary link specific: only merge if more than 2 lanes
1633                        if attrs['is_share'] & (len(lanes) > 2):
1634                            self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
1635                        else:
1636                            self.append_lane(lanes, attrs, is_rightside=True)
1637                    n_lane_assig -= 1
1638
1639                if attrs['is_leftside']:
1640                    # primary link specific: only merge if more than 2 lanes
1641                    if attrs['is_share'] & (len(lanes) > 0):
1642                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
1643                    else:
1644                        self.append_lane(lanes, attrs, is_leftside=True)
1645                    n_lane_assig -= 1
1646
1647        # do sidewalks
1648        attrs = self._sidewalkattrs[ind]
1649        if attrs['n_lane'] > 0:
1650            print '  sidewalks n_lane', attrs['n_lane']
1651            n_lane_assig = attrs['n_lane']
1652            n_lane = len(lanes)
1653            # sidewalks are not considered lanes in osm
1654            # so we append/prepend them
1655            while n_lane_assig > 0:
1656                if attrs['is_rightside']:
1657                    if attrs['is_share'] & (len(lanes) > 0):
1658                        self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
1659                    else:
1660                        self.append_lane(lanes, attrs, is_rightside=True)
1661                    n_lane_assig -= 1
1662                if attrs['is_leftside']:
1663                    if attrs['is_share'] & (len(lanes) > 0):
1664                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
1665                    else:
1666                        self.append_lane(lanes, attrs, is_leftside=True)
1667                    n_lane_assig -= 1
1668
1669            # disallow pedestrians on other lanes
1670            #
1671            for laneattrs in lanes:
1672                if ID_MODE_PED not in laneattrs['ids_modes_allow']:
1673                    self.disallow_on_lane(laneattrs, [ID_MODE_PED])
1674
1675        if is_opp:
1676            self._lanes_opp = lanes
1677        else:
1678            self._lanes = lanes
1679        print '  created %d lanes' % len(lanes)
1680        # print '  lanes', lanes
1681        for laneattrs in lanes:
1682            print_attrs(laneattrs)
1683        return True
1684
1685
1686class Residential(Road):
1687
1688    def config(self):
1689        """
1690        Make defaults to be overridden
1691        """
1692        Road.config(self)
1693        # put 30km/h default speed limit
1694        self.make_speed(30.0/3.6)
1695
1696    def get_priority(self, is_opp=False):
1697        """
1698        Returns priority of road.
1699
1700        To be overridden.
1701        """
1702        if is_opp:
1703            lanes = self._lanes_opp
1704        else:
1705            lanes = self._lanes
1706
1707        speed_max = self.get_speed_max()
1708        n_lane = len(lanes)
1709        return 3
1710
1711    def make_sidewalkattrs(self):
1712        print 'make_sidewalkattrs'
1713        osmattrs = self._osmattrs
1714        self._sidewalkattrs = (deepcopy(LANEATTRS_DEFAULT),
1715                               deepcopy(LANEATTRS_DEFAULT))
1716
1717        sidewalk = osmattrs.get('sidewalk', 'auto')
1718
1719        if sidewalk not in ['no', 'none', 'auto']:
1720            # there is a sidewalk, make sure there is at least one
1721
1722            if osmattrs.has_key('sidewalk:width'):
1723                width_left = float(osmattrs['sidewalk:width'])
1724                width_right = width_left
1725
1726            elif osmattrs.has_key('sidewalk:both:width'):
1727                width_left = float(osmattrs['sidewalk:both:width'])
1728                width_right = width_left
1729            else:
1730                width_left = float(osmattrs.get('sidewalk:left:width', self.width_sidewalk))
1731                width_right = float(osmattrs.get('sidewalk:right:width', self.width_sidewalk))
1732
1733            if osmattrs.get('oneway', 'no') == 'no':
1734                # bidirecional
1735
1736                if sidewalk == 'both':
1737                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
1738                    self.make_sidewalk(is_opp=True, is_rightside=True, width=width_left)
1739
1740                elif sidewalk == 'left':
1741                    self.make_sidewalk(is_opp=True, is_rightside=True, width=width_left)
1742
1743                elif sidewalk == 'right':
1744                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
1745
1746                else:
1747                    # no indication means both
1748                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
1749                    self.make_sidewalk(is_opp=True, is_rightside=True, width=width_left)
1750
1751            else:
1752                # oneway
1753                if sidewalk == 'both':
1754                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
1755                    self.make_sidewalk(is_opp=False, is_rightside=False, width=width_left)
1756
1757                elif sidewalk == 'left':
1758                    self.make_sidewalk(is_opp=False, is_rightside=False, width=width_left)
1759
1760                elif sidewalk == 'right':
1761                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
1762
1763                else:
1764                    # no indication means both
1765                    self.make_sidewalk(is_opp=False, is_rightside=True, width=width_right)
1766                    self.make_sidewalk(is_opp=False, is_rightside=False, width=width_left)
1767
1768        elif sidewalk == 'auto':
1769            # automatic sidewalk generation for residential roads
1770            if self.is_oneway():
1771                # put a sidewalk on both sides of the oneway
1772                self.make_sidewalk(is_opp=False, is_rightside=True, width=self.width_sidewalk)
1773                self.make_sidewalk(is_opp=False, is_rightside=False, width=self.width_sidewalk)
1774            else:
1775                # put a sidewalk on both sides of the road
1776                self.make_sidewalk(is_opp=False, is_rightside=True, width=self.width_sidewalk)
1777                self.make_sidewalk(is_opp=True, is_rightside=True, width=self.width_sidewalk)
1778
1779
1780class Footpath(Road):
1781    def config(self):
1782        """
1783        Make defaults to be overridden
1784        """
1785        print 'config'
1786        # pass here either road type specific defaults
1787        # or global defaults from parent process
1788        self.id_mode = ID_MODE_PED
1789        # highway=footway|path
1790        self.highway = self._osmattrs.get('highway', 'footway')
1791
1792        # Use footway=crossing for places where the footway crosses a street.
1793        # Use footway=sidewalk
1794
1795        self.footway = self._osmattrs.get('footway', '')
1796        self.n_lane = 1
1797
1798        if self.footway == 'sidewalk':
1799            lanewidth = self.parent.width_sidewalk
1800        else:
1801            lanewidth = self.parent.width_footpath
1802
1803        # half lanewidth if segregated
1804        if self._osmattrs.get('segregated', '') == 'yes':
1805            lanewidth /= 2
1806
1807        self.lanewidth = lanewidth
1808        self.lanewidth_bike = lanewidth
1809        #self.lanewidth_bus = self.parent.lanewidth_bus
1810        #self.width_sidewalk = self.parent.width_sidewalk
1811        #self.width_footpath = self.parent.width_footpath
1812
1813        #self.ids_modes_pt_shared = self.parent.ids_modes_pt_shared
1814        self.ids_modes_bike = self.parent.ids_modes_bike
1815        self.ids_modes_allow = [ID_MODE_PED]
1816        self.ids_modes_disallow = []
1817        self.make_speed(self.parent.speed_max_ped)
1818
1819        #self.speed_max_bus = self.parent.speed_max_bus
1820        self.speed_max_bike = self.parent.speed_max_bike
1821        #self.speed_max_ped = self.parent.speed_max_ped
1822
1823    def get_priority(self, is_opp=False):
1824        """
1825        Returns priority of road.
1826
1827        To be overridden.
1828        """
1829        if is_opp:
1830            lanes = self._lanes_opp
1831        else:
1832            lanes = self._lanes
1833
1834        speed_max = self.get_speed_max()
1835        n_lane = len(lanes)
1836        return 1
1837
1838    def make_oneway(self):
1839        # print 'make_oneway'
1840        osmattrs = self._osmattrs
1841
1842        # default for footpath is oneway = yes
1843        if osmattrs.get('oneway', 'yes') == 'no':
1844            self._is_oneway = False
1845
1846        else:
1847            # check if really oneway
1848            # we make oneway if only pedestrians use this edge
1849            if (osmattrs.get('bicycle', '') in ('yes', 'designated')) | (osmattrs.get('route', '') == 'bicycle'):
1850                self._is_oneway = False
1851            else:
1852                self._is_oneway = True
1853
1854    def make_buswayattrs(self):
1855        # print 'make_buswayattrs'
1856        # self._buswayattrs = (LANEATTRS_DEFAULT.copy(),
1857        #                        LANEATTRS_DEFAULT.copy())
1858        pass
1859
1860    def make_sidewalkattrs(self):
1861        self._sidewalkattrs = (deepcopy(LANEATTRS_DEFAULT),
1862                               deepcopy(LANEATTRS_DEFAULT))
1863        # pass
1864
1865    def make_bikewayattrs(self):
1866        print 'make_bikewayattrs'
1867        osmattrs = self._osmattrs
1868        self._bikewayattrs = (deepcopy(LANEATTRS_DEFAULT),
1869                              deepcopy(LANEATTRS_DEFAULT))
1870
1871        width_left = self.lanewidth_bike
1872        width_right = self.lanewidth_bike
1873
1874        # if osmattrs.get('oneway','no')=='no':
1875        # cycle lanes on bidir road
1876        if (osmattrs.get('bicycle', '') in ('yes', 'designated')) | (osmattrs.get('route', '') == 'bicycle'):
1877            if osmattrs.get('segregated', '') == 'yes':
1878                # bike lanes to the left of the footpath
1879                self.make_bikelane(is_opp=False, is_rightside=False, width=width_right)
1880                self.make_bikelane(is_opp=True, is_rightside=False, width=width_left)
1881            else:
1882                # bike lanes will be merged with the footpath
1883                self.make_bikelane(is_opp=False, width=width_right, ids_modes_allow=[ID_MODE_PED])
1884                self.make_bikelane(is_opp=True, width=width_left, ids_modes_allow=[ID_MODE_PED])
1885
1886    def make_lanes_rigid(self, is_opp=False, n_lane_osm=0):
1887        print 'make_lanes_rigid ped', is_opp, n_lane_osm
1888        osmattrs = self._osmattrs
1889
1890        if is_opp:
1891            ind = 0
1892            if self._is_oneway:
1893                self._lanes_opp = []
1894                return False
1895        else:
1896            ind = 1
1897
1898        lanes = []
1899        for i in range(n_lane_osm):
1900            lanes.append(deepcopy(self._laneattrs_main))
1901
1902        # if is_lanes_rigid:
1903        #    # respect given lane numbers for main modes, except footpath
1904        #    pass
1905        # else:
1906
1907        # do bikeways
1908        attrs = self._bikewayattrs[ind]
1909        if attrs['n_lane'] > 0:
1910            print '  bikeways n_lane', attrs['n_lane']
1911
1912            n_lane = len(lanes)
1913
1914            allowed, disallowed = self.get_laneaccess('bicycle', is_opp=is_opp)
1915
1916            n_allow = len(allowed)
1917            if n_allow > 0:
1918                for i, a, d in zip(xrange(n_allow), allowed, disallowed):
1919                    if i < n_lane:
1920                        if a & i < n_lane:
1921                            self.set_lane(lanes, attrs, i)
1922                        if d:
1923                            self.disallow_on_lane(lanes[i], attrs['ids_modes_disallow'])
1924
1925            else:
1926                n_lane_assig = attrs['n_lane']
1927                for i in range(n_lane):
1928                    if n_lane_assig > 0:
1929                        if attrs['is_rightside']:
1930                            self.merge_laneattrs(lanes[i], attrs, is_rightside=True)
1931                            n_lane_assig -= 1
1932
1933                        if attrs['is_leftside']:
1934                            self.merge_laneattrs(lanes[n_lane-i-1], attrs, is_leftside=True)
1935                            n_lane_assig -= 1
1936
1937    def make_lanes(self, is_opp=False, n_lane_osm=0):
1938        print 'make_lanes ped', is_opp, n_lane_osm
1939        osmattrs = self._osmattrs
1940
1941        print '  main lane attrs'
1942        print_attrs(self._laneattrs_main)
1943
1944        if is_opp:
1945            ind = 0
1946            if self._is_oneway:
1947                self._lanes_opp = []
1948                return False
1949        else:
1950            ind = 1
1951
1952        lanes = []
1953        for i in range(n_lane_osm):
1954            lanes.append(deepcopy(self._laneattrs_main))
1955
1956        # do bikeways
1957        attrs = self._bikewayattrs[ind]
1958        if attrs['n_lane'] > 0:
1959            print '  bikeways n_lane', attrs['n_lane']
1960            n_lane_assig = attrs['n_lane']
1961            n_lane = len(lanes)
1962
1963            while n_lane_assig > 0:
1964                if attrs['is_rightside']:
1965                    if attrs['is_share'] & (len(lanes) > 0):
1966                        self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
1967                    else:
1968                        self.append_lane(lanes, attrs, is_rightside=True)
1969                    n_lane_assig -= 1
1970
1971                if attrs['is_leftside']:
1972                    if attrs['is_share'] & (len(lanes) > 0):
1973                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
1974                    else:
1975                        self.append_lane(lanes, attrs, is_leftside=True)
1976                    n_lane_assig -= 1
1977
1978        if is_opp:
1979            self._lanes_opp = lanes
1980        else:
1981            self._lanes = lanes
1982
1983        print '  created %d lanes' % len(lanes)
1984        # print '  lanes', lanes
1985        for laneattrs in lanes:
1986            print_attrs(laneattrs)
1987        return True
1988
1989
1990class Cycleway(Road):
1991
1992    def config(self):
1993        """
1994        Make defaults to be overridden
1995        """
1996        print 'config cycleway'
1997        # pass here either road type specific defaults
1998        # or global defaults from parent process
1999
2000        self.highway = self._osmattrs.get('highway', 'cycleway')
2001
2002        self.id_mode = ID_MODE_BIKE
2003        self.n_lane = 1
2004
2005        # print '  width',self._osmattrs.get('width',self.parent.lanewidth_bike)
2006        if self.is_oneway():
2007            width_default = self.parent.lanewidth_bike
2008        else:
2009            width_default = 2*self.parent.lanewidth_bike
2010
2011        self.lanewidth = self.get_osmattr('width', is_float=True, default=width_default)
2012
2013        # half lane width if bidir
2014        if not self.is_oneway():
2015            self.lanewidth *= 0.5
2016
2017        #self.lanewidth_bike = self.parent.lanewidth_bike
2018        #self.lanewidth_bus = self.parent.lanewidth_bus
2019        self.width_sidewalk = self.parent.width_sidewalk
2020        self.width_footpath = self.parent.width_footpath
2021
2022        #self.ids_modes_pt_shared = self.parent.ids_modes_pt_shared
2023        #self.ids_modes_bike = self.parent.ids_modes_bike
2024        self.ids_modes_allow = self.parent.ids_modes_bike
2025        self.ids_modes_disallow = []
2026        self.make_speed(self.parent.speed_max_bike)
2027
2028        print '  ids_modes_allow', self.ids_modes_allow
2029        #self.speed_max_bus = self.parent.speed_max_bus
2030        #self.speed_max_bike = self.parent.speed_max_bike
2031        self.speed_max_ped = self.parent.speed_max_ped
2032
2033    def make_oneway(self):
2034        # print 'make_oneway'
2035        osmattrs = self._osmattrs
2036
2037        # default for bikeway is oneway = no
2038        if osmattrs.get('oneway', 'no') == 'no':
2039            self._is_oneway = False
2040
2041        else:
2042            self._is_oneway = True
2043
2044    def make_buswayattrs(self):
2045        # print 'make_buswayattrs'
2046        # self._buswayattrs = (LANEATTRS_DEFAULT.copy(),
2047        #                        LANEATTRS_DEFAULT.copy())
2048        pass
2049
2050    # def make_sidewalkattrs(self):
2051    #    self._sidewalkattrs = (deepcopy(LANEATTRS_DEFAULT),
2052    #                            deepcopy(LANEATTRS_DEFAULT))
2053    #    #pass
2054
2055    def make_bikewayattrs(self):
2056        pass
2057
2058    def make_lanes_rigid(self, is_opp=False, n_lane_osm=0):
2059        print 'make_lanes_rigid cycle', is_opp, n_lane_osm
2060        osmattrs = self._osmattrs
2061
2062        if is_opp:
2063            ind = 0
2064            if self._is_oneway:
2065                self._lanes_opp = []
2066                return False
2067        else:
2068            ind = 1
2069
2070        lanes = []
2071        for i in range(n_lane_osm):
2072            lanes.append(deepcopy(self._laneattrs_main))
2073
2074        # do sidewalks
2075        attrs = self._sidewalkattrs[ind]
2076        if attrs['n_lane'] > 0:
2077            print '  sidewalks n_lane', attrs['n_lane']
2078            n_lane_assig = attrs['n_lane']
2079            n_lane = len(lanes)
2080            # sidewalks are not considered lanes in osm
2081            # so we append/prepend them
2082            while n_lane_assig > 0:
2083                if attrs['is_rightside']:
2084                    if attrs['is_share'] & (len(lanes) > 0):
2085                        self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
2086                    else:
2087                        self.append_lane(lanes, attrs, is_rightside=True)
2088                    n_lane_assig -= 1
2089                if attrs['is_leftside']:
2090                    if attrs['is_share'] & (len(lanes) > 0):
2091                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
2092                    else:
2093                        self.append_lane(lanes, attrs, is_leftside=True)
2094                    n_lane_assig -= 1
2095
2096            # disallow pedestrians on other lanes
2097            #
2098            for laneattrs in lanes:
2099                if ID_MODE_PED not in laneattrs['ids_modes_allow']:
2100                    self.disallow_on_lane(laneattrs, [ID_MODE_PED])
2101
2102        if is_opp:
2103            self._lanes_opp = lanes
2104        else:
2105            self._lanes = lanes
2106        print '  created %d lanes' % len(lanes)
2107        # print '  lanes', lanes
2108        for laneattrs in lanes:
2109            print_attrs(laneattrs)
2110        return True
2111
2112    def make_lanes(self, is_opp=False, n_lane_osm=0):
2113        print 'make_lanes cycle', is_opp, n_lane_osm
2114        osmattrs = self._osmattrs
2115        is_lanes_rigid = False
2116
2117        if is_opp:
2118            ind = 0
2119            if self._is_oneway:
2120                self._lanes_opp = []
2121                return False
2122        else:
2123            ind = 1
2124
2125        lanes = []
2126        for i in range(n_lane_osm):
2127            lanes.append(deepcopy(self._laneattrs_main))
2128
2129        # do sidewalks
2130        attrs = self._sidewalkattrs[ind]
2131        if attrs['n_lane'] > 0:
2132            print '  sidewalks n_lane', attrs['n_lane']
2133            n_lane_assig = attrs['n_lane']
2134            n_lane = len(lanes)
2135            # sidewalks are not considered lanes in osm
2136            # so we append/prepend them
2137            while n_lane_assig > 0:
2138                if attrs['is_rightside']:
2139                    if attrs['is_share'] & (len(lanes) > 0):
2140                        self.merge_laneattrs(lanes[0], attrs, is_rightside=True)
2141                    else:
2142                        self.append_lane(lanes, attrs, is_rightside=True)
2143                    n_lane_assig -= 1
2144                if attrs['is_leftside']:
2145                    if attrs['is_share'] & (len(lanes) > 0):
2146                        self.merge_laneattrs(lanes[-1], attrs, is_leftside=True)
2147                    else:
2148                        self.append_lane(lanes, attrs, is_leftside=True)
2149                    n_lane_assig -= 1
2150
2151            # disallow pedestrians on other lanes
2152            #
2153            for laneattrs in lanes:
2154                if ID_MODE_PED not in laneattrs['ids_modes_allow']:
2155                    self.disallow_on_lane(laneattrs, [ID_MODE_PED])
2156
2157        if is_opp:
2158            self._lanes_opp = lanes
2159        else:
2160            self._lanes = lanes
2161        print '  created %d lanes' % len(lanes)
2162        # print '  lanes', lanes
2163        for laneattrs in lanes:
2164            print_attrs(laneattrs)
2165        return True
2166
2167    def get_priority(self, is_opp=False):
2168        """
2169        Returns priority of road.
2170
2171        To be overridden.
2172        """
2173        if is_opp:
2174            lanes = self._lanes_opp
2175        else:
2176            lanes = self._lanes
2177
2178        speed_max = self.get_speed_max()
2179        n_lane = len(lanes)
2180        return 2
2181
2182
2183ROADCLASSES = {'road': Road,
2184               'path': Footpath,
2185               'pedestrian': Footpath,
2186               'footway': Footpath,
2187               'stairs': Footpath,
2188               'steps': Footpath,
2189               'platform': Footpath,
2190               'cycleway': Cycleway,
2191               'residential': Residential,
2192               'living_street': Residential,
2193               'primary': Primary,
2194               'primary_link': Primary,
2195               'motorway': Primary,
2196               'trunk': Primary,
2197               'motorway_link': Primary,
2198               'trunk_link': Primary,
2199               'primary_link': Primary,
2200               }
2201OSMKEYS_SHARED = ('shared', 'share_lane', 'share_busway', 'share_cycleway')
2202OSMKEYS_SHARED_OPP = ('opposite_shared', 'opposite_share_lane', 'opposite_share_busway', 'opposite_share_cycleway')
2203
2204
2205class OxImporter(Process):
2206    def __init__(self,  scenario,
2207                 ident='oximporter',
2208                 name='OSMnx importer',
2209                 info='Import of network imported with the help of osmnx.',
2210                 logger=None, **kwargs):
2211
2212        print 'OxImporter.__init__'
2213
2214        self._init_common(ident,
2215                          parent=scenario,
2216                          name=name,
2217                          logger=logger,
2218                          info=info,
2219                          )
2220
2221        attrsman = self.set_attrsman(cm.Attrsman(self))
2222
2223        # self.id_mode = attrsman.add(am.AttrConf('id_mode',  modechoices['bicycle'],
2224        #                                groupnames = ['options'],
2225        #                                choices = modechoices,
2226        #                                name = 'Mode',
2227        #                                info = 'Transport mode to be matched.',
2228        #                                ))
2229
2230        self.osmdatafilepaths = attrsman.add(
2231            cm.AttrConf('osmdatafilepaths', kwargs.get('osmdatafilepaths', scenario.get_rootfilepath()),
2232                        groupnames=['options'],
2233                        perm='rw',
2234                        name='OSM data file(s)',
2235                        wildcards='Jason file (*.json)|*.json',
2236                        metatype='filepaths',
2237                        info="""One or several jason filepaths holding OSM related information.""",
2238                        ))
2239
2240        self.nxnetworkpaths = attrsman.add(
2241            cm.AttrConf('nxnetworkpaths', kwargs.get('nxnetworkpaths', scenario.get_rootfilepath()),
2242                        groupnames=['options'],
2243                        perm='rw',
2244                        name='Networkx file(s)',
2245                        wildcards='NetworkX file (*.obj)|*.obj',
2246                        metatype='filepaths',
2247                        info="""One or several network X filepaths containing topological information of simplified network.""",
2248                        ))
2249
2250        self.n_lane = attrsman.add(cm.AttrConf('n_lane', 1,
2251                                               groupnames=['options', 'osm'],
2252                                               name='Default lane number',
2253                                               info="Default lane number.",
2254                                               ))
2255
2256        self.speed_max = attrsman.add(cm.AttrConf('speed_max', 50.0/3.6,
2257                                                  groupnames=['options', 'osm'],
2258                                                  name='Default Max. speed',
2259                                                  info="General default maximum speed.",
2260                                                  unit='m/s',
2261                                                  ))
2262
2263        self.speed_max_bus = attrsman.add(cm.AttrConf('speed_max_bus', 50.0/3.6,
2264                                                      groupnames=['options', 'osm'],
2265                                                      name='Default Max. bus speed',
2266                                                      info="Default maximum speed on busways.",
2267                                                      unit='m/s',
2268                                                      ))
2269
2270        self.speed_max_bike = attrsman.add(cm.AttrConf('speed_max_bike', 20.0/3.6,
2271                                                       groupnames=['options', 'osm'],
2272                                                       name='Default Max. bike speed',
2273                                                       info="Default maximum speed on bikeways.",
2274                                                       unit='m/s',
2275                                                       ))
2276
2277        self.speed_max_ped = attrsman.add(cm.AttrConf('speed_max_ped', 3.0/3.6,
2278                                                      groupnames=['options', 'osm'],
2279                                                      name='Default Max. ped. speed',
2280                                                      info="Default maximum speed on footpath or sidewalks.",
2281                                                      unit='m/s',
2282                                                      ))
2283
2284        self.lanewidth = attrsman.add(cm.AttrConf('lanewidth', 3.25,
2285                                                  groupnames=['options', 'osm'],
2286                                                  name='Default lane',
2287                                                  info="Default lane width for standard lane.",
2288                                                  unit='m',
2289                                                  ))
2290
2291        self.lanewidth_bike = attrsman.add(cm.AttrConf('lanewidth_bike', 1.5,
2292                                                       groupnames=['options', 'osm'],
2293                                                       name='Default bikeway width',
2294                                                       info="Default bikeway width.",
2295                                                       unit='m',
2296                                                       ))
2297
2298        self.lanewidth_bus = attrsman.add(cm.AttrConf('lanewidth_bus', 3.5,
2299                                                      groupnames=['options', 'osm'],
2300                                                      name='Default busway width',
2301                                                      info="Default busway width.",
2302                                                      unit='m',
2303                                                      ))
2304
2305        self.width_footpath = attrsman.add(cm.AttrConf('width_footpath', 1.5,
2306                                                       groupnames=['options', 'osm'],
2307                                                       name='Default footpath width',
2308                                                       info="Default footpath width.",
2309                                                       unit='m',
2310                                                       ))
2311
2312        self.width_sidewalk = attrsman.add(cm.AttrConf('width_sidewalk', 1.0,
2313                                                       groupnames=['options', 'osm'],
2314                                                       name='Default sidewalk width',
2315                                                       info="Default sidewalk width.",
2316                                                       unit='m',
2317                                                       ))
2318
2319        self.modes_pt_shared = attrsman.add(cm.AttrConf('modes_pt_shared', ['bus', 'taxi', 'emergency', 'bicycle'],
2320                                                        groupnames=['options', 'osm'],
2321                                                        name='Modes on PT reserved lanes',
2322                                                        info="Modes that are allowed on reserved lanes for public transport.",
2323                                                        perm='r',
2324                                                        ))
2325
2326        self.modes_bike = attrsman.add(cm.AttrConf('modes_bike', ['bicycle', ],
2327                                                   groupnames=['options', 'osm'],
2328                                                   name='Modes on dedicated bike lanes',
2329                                                   info="Modes that are allowed on dedicated bike lanes.",
2330                                                   perm='r',
2331                                                   ))
2332
2333        self.ids_modes_bike = []
2334        for mode in self.modes_bike:
2335            self.ids_modes_bike.append(MODES[mode])
2336
2337        self.ids_modes_pt_shared = []
2338        for mode in self.modes_pt_shared:
2339            self.ids_modes_pt_shared.append(MODES[mode])
2340
2341        # def import_xnet(net, nodeshapefilepath, edgeshapefilepath, polyshapefilepath):
2342        #import_nodeshapes(net, nodeshapefilepath)
2343
2344    def get_scenario(self):
2345        return self.parent
2346
2347    def do(self):
2348        print self.ident+'.do'
2349
2350        print '   osmdatafilepaths', self.osmdatafilepaths
2351        print '   nxnetworkpaths', self.nxnetworkpaths
2352        net = self.get_scenario().net
2353        self._net = net
2354        self._map_id_edge_sumo_to_doubles = {}
2355        self.edges_osm = {}
2356        self.nodes_osm = {}
2357
2358        projparams_target = net.get_projparams()
2359        if projparams_target in ("", "!"):
2360            projparams_target = None
2361
2362        for filepath in self.osmdatafilepaths.split(','):
2363            self.import_osmdata(json.loads(open(filepath).read()))
2364
2365        for filepath in self.nxnetworkpaths.split(','):  # filepathstring_to_filepathlist(self.nxnetworkpaths):
2366            graphx = load_objfile(filepath.strip())
2367            self.import_nx(graphx, projparams=projparams_target)
2368
2369        net.edges.update(is_update_lanes=True)
2370
2371        return True
2372
2373    def import_osmdata(self, osmdata):
2374        edges_osm = self.edges_osm
2375        nodes_osm = self.nodes_osm
2376        for element in osmdata['elements']:
2377            # {u'nodes': [5340543333L, 5340543332L], u'type': u'way', u'id': 553233159, u'tags': {u'highway': u'service', u'oneway': u'no', u'service': u'driveway', u'surface': u'asphalt', u'incline': u'up'}}
2378            # {u'lat': 47.6038005, u'type': u'node', u'lon': 7.6006465, u'id': 453208, u'tags': {u'ref': u'69', u'name': u'Weil am Rhein / H\xfcningen', u'highway': u'motorway_junction'}}
2379            # print '  parse element',element['id'],element['type']
2380            if element['type'] == 'way':
2381                if element.has_key('tags'):
2382                    highway = element['tags'].get('highway', 'road')
2383                else:
2384                    highway = 'road'
2385                print '  '+70*'-'
2386                print '  way', element['id'], type(element['id']), highway
2387                edges_osm[str(element['id'])] = ROADCLASSES.get(highway, Road)(element, self)
2388                print '  done with way', element['id'], id(self.edges_osm[str(element['id'])])
2389
2390            if element['type'] == 'node':
2391                nodes_osm[element['id']] = element.get('tags', {})
2392
2393        print '   import_osmdata:done'
2394
2395    # def get_id_edge_sumo(self, osmid):
2396    #    idmap = self._map_id_edge_sumo_to_doubles
2397    #    if idmap.has_key(osmid):
2398    #        idmap[osmid] +=1
2399    #    else:
2400    #        idmap[osmid] = 0
2401    #    return (osmid, idmap[osmid])
2402    #    #return str(osmid)+'#'+str(idmap[osmid])
2403
2404    def get_edgenumber(self, osmid_dir):
2405        idmap = self._map_id_edge_sumo_to_doubles
2406        if idmap.has_key(osmid_dir):
2407            idmap[osmid_dir] += 1
2408        else:
2409            idmap[osmid_dir] = 0
2410        return idmap[osmid_dir]
2411
2412    def get_id_edge_sumo(self, osmid_dir):
2413        edgenumber = self.get_edgenumber(osmid_dir)
2414        return osmid_dir+'#'+str(edgenumber)
2415
2416    def get_id_edge_osm_from_id_sumo(self, id_sumo):
2417        """
2418        Returns from id_sumo:
2419            (id_osm, is_opp, num)
2420        """
2421        data = id_sumo.split('#')
2422        if data[0][0] == '-':
2423            return data[0][1:], True, int(data[1])
2424        else:
2425            return data[0], False, int(data[1])
2426
2427    def is_edge_eligible(self, id_osm, id_fromnode_sumo, id_tonode_sumo):
2428
2429        print 'is_edge_eligible', id_osm, type(id_osm), id_fromnode_sumo, id_tonode_sumo, self.edges_osm.has_key(
2430            id_osm), self._edgelookup.has_key(id_osm)
2431        if not self.edges_osm.has_key(id_osm):
2432            # foe some reason, nx network has edges that are not in jason
2433            return False
2434
2435        edgelookup = self._edgelookup
2436
2437        if edgelookup.has_key(id_osm):
2438            # is reverse already in database
2439            # print '  check',edgelookup[id_osm], (id_tonode_sumo, id_fromnode_sumo) in edgelookup[id_osm]
2440            edgelookup[id_osm].add((id_fromnode_sumo, id_tonode_sumo))
2441            if (id_tonode_sumo, id_fromnode_sumo) in edgelookup[id_osm]:
2442                return False
2443            else:
2444                return True
2445
2446        else:
2447            edgelookup[id_osm] = set([(id_fromnode_sumo, id_tonode_sumo)])
2448            return True
2449
2450    def make_segment_edge_map(self):
2451        """
2452        Generates a vertex matrix with line segments of all edges
2453        and a map that maps each line segment to edge index.
2454        """
2455        polylines = self._edgeshapes
2456        n_edges = len(polylines)
2457        inds = np.arange(n_edges)
2458        #ids = inds+1
2459        print 'make_linevertices', n_edges
2460
2461        linevertices = np.zeros((0, 2, 3), np.float32)
2462        vertexinds = np.zeros((0, 2), np.int32)
2463        polyinds = []
2464
2465        lineinds = []
2466        linebeginstyles = []
2467        lineendstyles = []
2468
2469        i = 0
2470        ind_line = 0
2471
2472        for ind in inds:
2473
2474            # if is_laneshapes:
2475            #    polyline = laneshapes[ids_lanes[ind][0]]
2476            # else:
2477            polyline = polylines[ind]
2478
2479            n_seg = len(polyline)
2480            # print '  =======',n_seg#,polyline
2481
2482            if n_seg > 1:
2483                polyvinds = range(n_seg)
2484                # print '  polyvinds\n',polyvinds
2485                vi = np.zeros((2*n_seg-2), np.int32)
2486                vi[0] = polyvinds[0]
2487                vi[-1] = polyvinds[-1]
2488
2489                # Important type conversion!!
2490                v = np.zeros((2*n_seg-2, 3), np.float32)
2491                v[0] = polyline[0]
2492                v[-1] = polyline[-1]
2493                if len(v) > 2:
2494
2495                    v[1:-1] = np.repeat(polyline[1:-1], 2, 0)
2496                    vi[1:-1] = np.repeat(polyvinds[1:-1], 2)
2497
2498                n_lines = len(v)/2
2499                # print '  v\n',v
2500                polyinds += n_lines*[ind]
2501                lineinds.append(np.arange(ind_line, ind_line+n_lines))
2502                ind_line += n_lines
2503
2504            else:
2505                # empty polygon treatment
2506                v = np.zeros((0, 3), np.float32)
2507                vi = np.zeros((0), np.int32)
2508
2509            linevertices = np.concatenate((linevertices, v.reshape((-1, 2, 3))))
2510            vertexinds = np.concatenate((vertexinds, vi.reshape((-1, 2))))
2511            # print '  linevertex\n',linevertices
2512            i += 1
2513
2514        #self._segvertices = linevertices
2515        self._edgeinds = np.array(polyinds, np.int32)
2516        self._seginds = lineinds
2517        self._segvertexinds = np.array(vertexinds, np.int32)
2518
2519        self._x1 = linevertices[:, 0, 0]
2520        self._y1 = linevertices[:, 0, 1]
2521
2522        self._x2 = linevertices[:, 1, 0]
2523        self._y2 = linevertices[:, 1, 1]
2524
2525    def get_closest_edge_dist(self, p, ind_shape, n_best=0, d_min=0.5, alpha_min=1.0*np.pi/180, d_max=None):
2526        """
2527        Returns edge id which is closest to point p.
2528        Requires execution of make_segment_edge_map
2529        """
2530        # print '  x1', x1
2531        # print '  x2', x2
2532        #halfwidths = 0.5*self.get_widths_array()[self._polyinds]
2533        x1, y1, x2, y2 = self._x1, self._y1, self._x2, self._y2
2534        d2 = get_dist_point_to_segs(p[0:2], x1, y1, x2, y2, is_ending=True)
2535        # print '  min(d2)=',np.min(d2),'argmin=',np.argmin(d2),self.get_ids(self._edgeinds[np.argmin(d2)])
2536
2537        d2[self._seginds[ind_shape]] = np.inf
2538        #d2[d2<0.5] = np.inf
2539
2540        # check side
2541        v1 = np.concatenate(((x2-x1).reshape(1, -1), (y2-y1).reshape(1, -1)), 0)
2542        v2 = np.concatenate(((p[0]-x1).reshape(1, -1), (p[1]-y1).reshape(1, -1)), 0)
2543        angles = get_diff_angle_clockwise(v1, v2)
2544        #d2[angles<alpha_min] = np.inf
2545
2546        if n_best == 0:
2547            ind = np.argmin(d2)
2548            return self._edgeinds[ind], np.sqrt(d2[ind])
2549
2550        elif d_max is None:
2551            dists2_min = np.zeros(n_best, dtype=np.float32)
2552            inds_min = np.zeros(n_best, dtype=np.int)
2553            for i in xrange(n_best):
2554                ind = np.argmin(d2)
2555                inds_min[i] = ind
2556                dists2_min[i] = d2[ind]
2557                d2[ind] = np.inf
2558
2559            return self._edgeinds[inds_min], np.sqrt(dists2_min), angles[inds_min]
2560
2561        else:
2562            ind = np.argmin(d2)
2563            dist2_min = d2[ind]
2564            dists2_min = [dist2_min]
2565            inds_min = [ind]
2566            while (dist2_min < d_max**2) & (len(dists2_min) < n_best):
2567                d2[ind] = np.inf
2568                ind = np.argmin(d2)
2569                dist2_min = d2[ind]
2570                dists2_min.append(dist2_min)
2571                inds_min.append(ind)
2572
2573            return self._edgeinds[inds_min], np.sqrt(dists2_min), angles[inds_min]
2574
2575    def configure_roundabouts(self):
2576        print 'configure_roundabouts'
2577        nodes = self._net.nodes
2578        roundabouts = []
2579        edges_osm = self.edges_osm
2580        ids_edge_osm = self._ids_edge_osm
2581        ids_edge_sumo = self._ids_edge_sumo
2582        ids_tonode = self._ids_tonode
2583        ids_fromnode = self._ids_fromnode
2584        shapes = self._edgeshapes
2585
2586        alpha_crit = 90.0*np.pi/180.0
2587
2588        graph = nx.Graph()
2589        digraph = nx.DiGraph()
2590        #junctionnet = {}
2591        for ind, id_edge_osm, shape, id_fromnode, id_tonode in zip(np.arange(len(ids_edge_osm)), ids_edge_osm, self._edgeshapes, ids_fromnode, ids_tonode):
2592            road = edges_osm[id_edge_osm]
2593            if road.is_roundabout():  # & (len(shape)>2):
2594                graph.add_edge(id_fromnode, id_tonode, ind=ind)
2595                digraph.add_edge(id_fromnode, id_tonode, ind=ind)
2596
2597        # print '  graph.nodes()',graph.nodes()
2598        #ids_node_junctions = [[]]
2599
2600        for ids_node_junction_list in nx.cycle_basis(graph):
2601            if len(ids_node_junction_list) > 2:
2602                # print '    ids_node_junction_list',ids_node_junction_list
2603                ids_node_junction = np.array(ids_node_junction_list, dtype=np.int32)
2604
2605                coords = nodes.coords[ids_node_junction]
2606                center = np.mean(coords, 0)
2607                deltas = coords-center
2608                angles = np.arctan2(deltas[:, 0], deltas[:, 1])
2609                inds = np.argsort(angles, axis=0)[::-1]  # reverse order
2610                # print '    inds',inds
2611                # print '    angels',angles[inds]
2612                # print '    ids_node_junction',ids_node_junction[inds]
2613                # print '    len(graph)',len(graph)
2614                ids_node_ok = list(ids_node_junction[inds])
2615                ids_node_ok.append(ids_node_ok[0])
2616                #n_node = len(ids_node_ok)
2617                # for ind in xrange(len(ids_node_ok)):
2618                #    if digraph.has_edge()
2619
2620                ids_rbsedges_sumo = []
2621                for id_fromnode, id_tonode in zip(ids_node_ok[:-1], ids_node_ok[1:]):
2622
2623                    ind = graph[id_tonode][id_fromnode]['ind']
2624                    if not digraph.has_edge(id_fromnode, id_tonode):
2625                        # print '  flip',ids_edge_sumo[ind]
2626                        # print '    shapes',shapes[ind]
2627                        # print '    shapes',shapes[ind][::-1]
2628                        ids_tonode[ind] = id_tonode
2629                        ids_fromnode[ind] = id_fromnode
2630                        shapes[ind][:] = shapes[ind][::-1]
2631
2632                    ids_rbsedges_sumo.append(ids_edge_sumo[ind])
2633
2634                roundabouts.append((ids_rbsedges_sumo, ids_node_ok))
2635
2636                #data = np.concatenate((angles.reshape(-1,1), ids_node_junction).reshape(-1,1),0)
2637                # graph.remove_nodes_from(ids_node_junction)
2638                self._roundabouts = roundabouts
2639
2640    def get_id_osm_maindir(self, id_osm):
2641        if id_osm[0] == '-':
2642            return id_osm[1:]
2643        else:
2644            return id_osm
2645
2646    def check_consistency(self):
2647        print 'check_consistency'
2648        nodelookup = {}
2649
2650        for ind, id_fromnode,  id_tonode, id_edge_sumo in zip(np.arange(len(self._ids_edge_sumo)), self._ids_fromnode, self._ids_tonode, self._ids_edge_sumo):
2651            ids_fromtonode = (id_fromnode, id_tonode)
2652            if nodelookup.has_key(ids_fromtonode):
2653                print '  WARNING: %s double edge to %s detected' % (
2654                    id_edge_sumo, nodelookup[ids_fromtonode]), 'from', id_fromnode, 'to', id_tonode
2655                self._are_edge_valid[ind] = False
2656
2657            nodelookup[ids_fromtonode] = id_edge_sumo
2658
2659    def configure_footpath(self):
2660
2661        are_edge_valid = self._are_edge_valid
2662        edges_osm = self.edges_osm
2663        ids_edge_osm = self._ids_edge_osm
2664        ids_edge_sumo = self._ids_edge_sumo
2665        footpath_condig = ('footway', 'path', 'pedestrian')
2666        footpath_nomerge = ('footway', 'path', 'pedestrian', 'stairs', 'steps',
2667                            'platform', 'primary_link', 'secondary_link')
2668        footpath_merge_cross = ('cycleway',)
2669        prio_max = 7
2670        dist_min_detect = 15.0
2671        dist_min_detect_cross = 3.0
2672        dist_min_remove = 0.0
2673
2674        n_best = 10
2675
2676        length_max_cross = 30.0
2677
2678        alpha_crit = 30.0*np.pi/180.0
2679        alpha_crit_cross = 30.0*np.pi/180.0
2680        print 'configure_footpath alpha_crit', alpha_crit
2681        #self.id_mode = ID_MODE_PED
2682        # highway=footway|path
2683        #self.highway = self._osmattrs.get('highway','footway')
2684
2685        # Use footway=crossing for places where the footway crosses a street.
2686        # Use footway=sidewalk
2687        for ind, id_edge_osm, shape, length in zip(np.arange(len(ids_edge_osm)), ids_edge_osm, self._edgeshapes, self._length):
2688            road = edges_osm[id_edge_osm]
2689
2690            if road.highway in footpath_condig:
2691                print '  check edge', ids_edge_sumo[ind], road.footway, (road.get_osmattr(
2692                    'tunnel') != 'yes'), (length > dist_min_remove), length
2693                #(road.footway != 'crossing') (road.footway != 'sidewalk')
2694                ids_osm_main = set()
2695                is_remove = True
2696                ip = 0
2697
2698                if (road.footway == 'sidewalk'):
2699                    # spacial sidewal merge. Sidewalks must be merged
2700                    # to a main road
2701                    for i in range(0, len(shape)):
2702                        point = shape[i]
2703                        is_foundmatch = False
2704                        inds_edge_main, dists, angles = self.get_closest_edge_dist(
2705                            point, ind, n_best=20, d_max=dist_min_detect)
2706                        #matchdata = {}
2707                        print '   check sidewalk point (%d/%d)' % (i+1, len(shape))
2708                        for ind_edge_main, dist, angle in zip(inds_edge_main, dists, angles):
2709                            id_edge_osm_main, is_opp, nr = self.get_id_edge_osm_from_id_sumo(
2710                                ids_edge_sumo[ind_edge_main])
2711                            road_main = edges_osm[id_edge_osm_main]
2712                            prio = road_main.get_priority(is_opp)
2713                            print '    check medge %s d=%.1fm al=%.1f' % (ids_edge_sumo[ind_edge_main], dist, angle/np.pi*180), prio, road_main.highway, (
2714                                angle < alpha_crit), (dist < 2*dist_min_detect), (road_main.highway not in footpath_nomerge)
2715                            # print '   p1',shape[i-1],'pc',point,'p2',shape[i]
2716                            if (angle < 2*alpha_crit) & (dist < dist_min_detect) & (road_main.highway not in footpath_nomerge):
2717                                print '     add edge main edge %s' % ids_edge_sumo[ind_edge_main], (
2718                                    id_edge_osm_main, is_opp)
2719                                ids_osm_main.add((id_edge_osm_main, is_opp))
2720                                is_foundmatch = True
2721                                break
2722
2723                        is_remove = len(ids_osm_main) > 0
2724
2725                elif (road.footway != 'crossing') | (length > length_max_cross):
2726                    # normal footpath merge
2727
2728                    if (road.get_osmattr('tunnel') != 'yes') & (length > dist_min_remove):
2729
2730                        for i in range(1, len(shape)):
2731                            point = shape[i-1]+0.5*(shape[i]-shape[i-1])
2732                            is_foundmatch = False
2733                            inds_edge_main, dists, angles = self.get_closest_edge_dist(
2734                                point, ind, n_best=20, d_max=dist_min_detect)
2735                            print '  check footpath point (%d/%d)' % (i+1, len(shape))
2736                            for ind_edge_main, dist, angle in zip(inds_edge_main, dists, angles):
2737                                id_edge_osm_main, is_opp, nr = self.get_id_edge_osm_from_id_sumo(
2738                                    ids_edge_sumo[ind_edge_main])
2739                                road_main = edges_osm[id_edge_osm_main]
2740                                prio = road_main.get_priority(is_opp)
2741                                print '   check medge %s d=%.1fm al=%.1f,%.2f' % (ids_edge_sumo[ind_edge_main], dist, angle/np.pi*180, angle), prio, road_main.highway, (
2742                                    angle < alpha_crit), (dist < dist_min_detect), (road_main.highway not in footpath_nomerge)
2743                                # print '   p1',shape[i-1],'pc',point,'p2',shape[i]
2744                                if (prio <= prio_max) & (angle < alpha_crit) & (dist < dist_min_detect) & (road_main.highway not in footpath_nomerge):
2745                                    print '       add edge main edge %s' % ids_edge_sumo[ind_edge_main], (
2746                                        id_edge_osm_main, is_opp)
2747                                    ids_osm_main.add((id_edge_osm_main, is_opp))
2748                                    is_foundmatch = True
2749                                    break
2750
2751                            if not is_foundmatch:
2752                                ids_osm_main = set()
2753                                is_remove = False
2754                                break
2755                    else:
2756                        is_remove = False
2757
2758                else:
2759                    # special merge at crossings
2760                    if (road.get_osmattr('tunnel') != 'yes'):
2761
2762                        for i in range(1, len(shape)):
2763                            point = shape[i-1]+0.5*(shape[i]-shape[i-1])
2764                            is_foundmatch = False
2765                            inds_edge_main, dists, angles = self.get_closest_edge_dist(
2766                                point, ind, n_best=20, d_max=dist_min_detect_cross)
2767                            print '  check crossing point (%d/%d)' % (i+1, len(shape))
2768                            for ind_edge_main, dist, angle in zip(inds_edge_main, dists, angles):
2769                                id_edge_osm_main, is_opp, nr = self.get_id_edge_osm_from_id_sumo(
2770                                    ids_edge_sumo[ind_edge_main])
2771                                road_main = edges_osm[id_edge_osm_main]
2772                                prio = road_main.get_priority(is_opp)
2773                                print '   check medge %s d=%.1fm al=%.1f' % (ids_edge_sumo[ind_edge_main], dist, angle/np.pi*180), prio, road_main.highway, (
2774                                    angle < alpha_crit_cross), (dist < dist_min_detect_cross), (road_main.highway in footpath_merge_cross)
2775                                # print '   p1',shape[i-1],'pc',point,'p2',shape[i]
2776                                # if (prio<=prio_max)&(((angle<alpha_crit_cross)&(dist < dist_min_detect))|(dist < dist_min_detect_cross))& (road_main.highway in footpath_merge_cross):
2777                                if (prio <= prio_max) & (angle < alpha_crit_cross) & (dist < dist_min_detect_cross) & (road_main.highway in footpath_merge_cross):
2778                                    print '       add edge main edge %s' % ids_edge_sumo[ind_edge_main], (
2779                                        id_edge_osm_main, is_opp)
2780                                    ids_osm_main.add((id_edge_osm_main, is_opp))
2781                                    is_foundmatch = True
2782                                    break
2783
2784                            if not is_foundmatch:
2785                                ids_osm_main = set()
2786                                is_remove = False
2787                                break
2788
2789                    else:
2790                        is_remove = False
2791
2792                if is_remove:
2793                    # footpath can be matched to main roads
2794
2795                    for id_osm_main, is_opp in ids_osm_main:
2796                        print '    found', id_edge_osm, 'match with', id_osm_main, 'is_opp', is_opp
2797                        edges_osm[id_osm_main].add_sidewalk(road, is_opp=is_opp)
2798
2799                    # make sure footpath is invalid
2800                    print '  eliminate edge', ids_edge_sumo[ind]
2801                    are_edge_valid[ind] = False
2802
2803    def _get_osmid_from_attr(self, attrs):
2804        id_osm_str = attrs['osmid']
2805
2806        if type(id_osm_str) in cm.STRINGTYPES:
2807            if id_osm_str.count(';') > 0:
2808                return int(id_osm_str.split(';')[0])
2809            else:
2810                return int(id_osm_str)
2811        else:
2812            return id_osm_str
2813
2814    def _get_osmid_from_nxattr(self, attrs):
2815        id_osm_data = attrs['osmid']
2816
2817        if hasattr(id_osm_data, '__iter__'):
2818            return str(id_osm_data[0])
2819        else:
2820            return str(id_osm_data)
2821
2822    def import_nx(self, graphx, projparams=None, offset=None, highway_bidir=['rail', ]):
2823        """
2824        Import an networkx graph into net
2825        """
2826        print 'import_nx'
2827        net = self._net
2828        edges_osm = self.edges_osm
2829        nodes_osm = self.nodes_osm
2830        idmap = self._map_id_edge_sumo_to_doubles
2831        get_id_mode = net.modes.get_id_mode
2832
2833        if not hasattr(graphx, 'adj'):
2834            graphx.adj = graphx._adj
2835
2836        if not hasattr(graphx, 'node'):
2837            graphx.node = graphx._node
2838
2839        # initialize main vectors
2840        #n_nodes = len(graphx.adj)
2841        #ids_nodes_sumo = np.zeros(n_nodes, dtype = np.object)
2842        #ids_nodes_sumo = np.array(graphx.adj.keys(), dtype = np.int32)
2843        gxnodes = graphx.node
2844        nodes = net.nodes
2845        edges = net.edges
2846        n_node = len(graphx.adj)
2847        ids_node = net.nodes.add_rows(n_node)
2848
2849        id_sumonodetypes = nodes.types.choices
2850        id_nodetype_default = id_sumonodetypes['priority']
2851        id_nodetype_tl = id_sumonodetypes['traffic_light']
2852        nodetypemap = {'motorway_junction': id_sumonodetypes['zipper'],
2853                       'traffic_signals': id_sumonodetypes['traffic_light'],
2854                       'crossing': id_sumonodetypes['priority'],
2855                       'turning_circle': id_sumonodetypes['dead_end'],
2856                       'turning_loop': id_sumonodetypes['dead_end'],
2857                       'miniroundabout': id_sumonodetypes['priority'],
2858                       'stop': id_sumonodetypes['allway_stop'],
2859                       }
2860
2861        lonlats_node = np.zeros((n_node, 2), dtype=np.float32)
2862        ids_node_sumo = np.zeros(n_node, dtype=np.object)
2863        nodetypes = np.zeros(n_node, dtype=np.int32)
2864        elevation = np.zeros(n_node, dtype=np.float32)
2865        #nodetype = np.zeros(n_node, dtype = np.object)
2866
2867        # for id_sumo, nodedict in zip(nodes.ids_sumo[ids_node],:
2868
2869        #ids_node_sumo = np.zeros(n_node, dtype = np.int32)
2870
2871        i_node = -1
2872        for id_fromnode, id_fromnode_sumo, outgoingdicts in zip(ids_node, graphx.adj.keys(), graphx.adj.values()):
2873            i_node += 1
2874            #ids_node_sumo[i_node] = id_fromnode_sumo
2875            print '  ', id_fromnode, id_fromnode_sumo, gxnodes[id_fromnode_sumo]  # nodes.ids_sumo[id_fromnode]
2876            lonlats_node[i_node] = [gxnodes[id_fromnode_sumo]['x'], gxnodes[id_fromnode_sumo]['y']]
2877            ids_node_sumo[i_node] = str(id_fromnode_sumo)
2878            elevation[i_node] = float(gxnodes[id_fromnode_sumo].get('elevation', 0.0))
2879            nxnodetype = gxnodes[id_fromnode_sumo].get('highway', 'default')
2880            # if nxnodetype == 'crossing':...
2881            # if nxnodetype = 'bus_stop'
2882            nodetypes[i_node] = nodetypemap.get(nxnodetype, id_nodetype_default)
2883
2884        nodes.ids_sumo[ids_node] = ids_node_sumo
2885        nodes.types[ids_node] = nodetypes
2886        nodes.types_tl[ids_node[nodetypes == id_nodetype_tl]] = nodes.types_tl.choices['static']
2887
2888        if projparams is None:
2889            print '  take first node to estimate projection', (lonlats_node[0][0], lonlats_node[0][1])
2890            projparams = guess_utm_from_coord([lonlats_node[0][0], lonlats_node[0][1]])
2891        print '  projparams', projparams
2892        proj = pyproj.Proj(projparams)
2893        net.set_projparams(projparams)
2894
2895        xx, yy = proj(lonlats_node[:, 0], lonlats_node[:, 1])
2896        zz = elevation
2897        if offset == None:
2898            offset = np.array([-np.min(xx), -np.min(yy)], dtype=np.float32)
2899            offset3d = np.array([-np.min(xx), -np.min(yy), 0.0], dtype=np.float32)
2900        net.set_offset(offset)
2901
2902        # Format of Boundary box [MinX, MinY ,MaxX, MaxY ]
2903        net.set_boundaries([0, 0, np.max(xx)+offset[0], np.max(yy)+offset[1]],
2904                           [np.min(lonlats_node[:, 0]), np.min(lonlats_node[:, 1]), np.max(lonlats_node[:, 0]), np.max(lonlats_node[:, 1])])
2905
2906        # print '  nodes.coords[ids_node].shape', nodes.coords[ids_node].shape
2907        # print '  (xx+offset[0]).shape', (xx+offset[0]).shape
2908
2909        #nodes.coords[ids_node][:,0] = xx+offset[0]
2910        #nodes.coords[ids_node][:,1] = yy+offset[1]
2911
2912        # print '  xx',np.array(xx, dtype = np.float32).reshape(-1,1).shape
2913        # print '  yy',np.array(yy, dtype = np.float32).reshape(-1,1).shape
2914        # print '  zz.reshape(-1,1)',zz.reshape(-1,1).shape
2915        nodes.coords[ids_node] = np.concatenate((np.array(xx, dtype=np.float32).reshape(-1, 1),
2916                                                 np.array(yy, dtype=np.float32).reshape(-1, 1),
2917                                                 zz.reshape(-1, 1)), 1) + offset3d
2918
2919        ids_edge_sumo = []  # np.zeros(n_edge, dtype = np.object)
2920        ids_edge_osm = []  # np.zeros(n_edge, dtype = np.int32)
2921        inds_edge_opp = []  # -1*np.ones(n_edge, dtype = np.int32)
2922
2923        ids_fromnode = []  # np.zeros(n_edge, dtype = np.int32)
2924        ids_tonode = []  # np.zeros(n_edge, dtype = np.int32)
2925        #lengths = np.zeros(n_edge, dtype = np.float32)
2926        shapes = []  # np.zeros(n_edge, dtype = np.object)
2927        #names = np.zeros(n_edge, dtype = np.object)
2928        # types_spread = np.zeros(n_edge, dtype = np.object)  # 0=center, 1 = right
2929        get_id_node = nodes.ids_sumo.get_id_from_index
2930        i_edge = -1
2931        i_node = -1
2932
2933        # dictionary with id_osm as key and (id_fromnode,id_tonode) as value
2934        # this is to prevent, that a return way with the same id_osm
2935        # is being created
2936        self._edgelookup = {}
2937
2938        # debug
2939        self._nodelookup = {}
2940
2941        for id_fromnode, id_fromnode_sumo, outgoingdicts in zip(ids_node, graphx.adj.keys(), graphx.adj.values()):
2942            i_node += 1
2943            # print '  id_fromnode_sumo',i_node, id_fromnode, id_fromnode_sumo
2944            for id_tonode_sumo, edgedatalist in outgoingdicts.iteritems():
2945
2946                edgeattrs = edgedatalist[0]
2947
2948                id_osm = self._get_osmid_from_nxattr(edgeattrs)
2949
2950                if self.is_edge_eligible(id_osm, id_fromnode_sumo, id_tonode_sumo):
2951
2952                    id_tonode = get_id_node(str(id_tonode_sumo))
2953
2954                    if edgeattrs.has_key('geometry'):
2955                        # print '    geometry',edgeattrs['geometry']
2956                        lonlats = edgeattrs['geometry'].xy
2957                        xx, yy = proj(lonlats[0], lonlats[1])
2958                        zz = np.zeros((len(xx), 1),  dtype=np.float32)
2959                        # print '    xx',xx
2960                        # print '    yy',yy
2961                        # print '    zz',zz
2962                        shape1 = np.concatenate((np.array(xx, dtype=np.float32).reshape(-1, 1),
2963                                                 np.array(yy, dtype=np.float32).reshape(-1, 1),
2964                                                 zz), 1) + offset3d
2965
2966                        # elevation interpolation
2967                        # print '  shape1',shape1
2968                        # print '  dists',np.sqrt(np.sum((shape1[1:,:]-shape1[:-1,:])**2,1))
2969                        cumlength = np.cumsum(np.sqrt(np.sum((shape1[1:, :]-shape1[:-1, :])**2, 1)))
2970                        # print '  cumlength',cumlength
2971                        length = cumlength[-1]
2972                        vfrom, vto = nodes.coords[[id_fromnode, id_tonode]]
2973                        height_delta = vto[2]-vfrom[2]
2974                        height_offset = vfrom[2]
2975                        height = height_offset+cumlength/length*height_delta
2976
2977                        # print '  cumlength.shape',cumlength.shape
2978                        # print '  height_offset',height_offset
2979                        # print '  height_delta',height_delta
2980
2981                        # print '  height',height.shape,height
2982                        shape1[0, 2] = height_offset
2983                        shape1[1:, 2] = height
2984
2985                    else:
2986                        shape1 = nodes.coords[[id_fromnode, id_tonode]]
2987
2988                    #
2989                    # make foreward edge
2990
2991                    # print '    shape=\n',list(shape)
2992                    i_edge += 1
2993                    shapes.append(list(shape1))
2994                    ids_fromnode.append(id_fromnode)
2995                    ids_tonode.append(id_tonode)
2996
2997                    ids_edge_osm.append(id_osm)
2998                    #edgenum = get_edgenumber(id_osm)
2999                    ids_edge_sumo.append(self.get_id_edge_sumo(id_osm))
3000
3001                    road = edges_osm[id_osm]
3002                    print '    created edge %s from' % ids_edge_sumo[-1], id_fromnode_sumo, 'to', id_tonode_sumo
3003                    # print '    id_osm,id(road)', id_osm, id(road), ids_edge_osm[i_edge]
3004
3005                    if not road.is_oneway():
3006                        # set edge for opposite direction
3007                        inds_edge_opp.append(i_edge + 1)  # index of opposite edge
3008                        i_edge += 1
3009                        shapes.append(list(shape1)[::-1])
3010                        ids_fromnode.append(id_tonode)
3011                        ids_tonode.append(id_fromnode)
3012                        ids_edge_sumo.append(self.get_id_edge_sumo('-'+id_osm))
3013                        ids_edge_osm.append(id_osm)
3014                        inds_edge_opp.append(-2)  # mark that this is the opposite edge
3015                        print '    created reverse ids_edge_sumo', ids_edge_sumo[i_edge]
3016
3017                    else:
3018                        inds_edge_opp.append(-1)
3019
3020        self._are_edge_valid = np.ones(len(ids_edge_sumo), dtype=np.bool)
3021
3022        # print '  inds_valid before',inds_valid
3023        self._edgeshapes = np.array(shapes, dtype=np.object)
3024        self._ids_edge_osm = np.array(ids_edge_osm, dtype=np.object)
3025        self._ids_edge_sumo = np.array(ids_edge_sumo, dtype=np.object)
3026        self._length = get_length_polypoints(self._edgeshapes)
3027
3028        self._ids_fromnode = np.array(ids_fromnode, dtype=np.int32)
3029        self._ids_tonode = np.array(ids_tonode, dtype=np.int32)
3030        self.make_segment_edge_map()
3031
3032        self.check_consistency()
3033        self.configure_roundabouts()
3034        self.configure_footpath()
3035
3036        inds_valid = np.flatnonzero(self._are_edge_valid)
3037        n_edge = len(inds_valid)
3038        # print '  n_edge',n_edge,'of',len(ids_edge_sumo)
3039        # print '  inds_valid',inds_valid
3040        # print '  shapes',  shapes
3041        ids_edges = edges.multimake(self._ids_edge_sumo[inds_valid],
3042                                    ids_fromnode=self._ids_fromnode[inds_valid],
3043                                    ids_tonode=self._ids_tonode[inds_valid],
3044                                    #lengths = lengths,
3045                                    shapes=self._edgeshapes[inds_valid],
3046                                    #names = names,
3047                                    )
3048
3049        roundabouts = net.roundabouts
3050        for ids_rbedge_sumo, ids_rbnode in self._roundabouts:
3051            # print '    ',
3052            roundabouts.make(ids_edge=edges.ids_sumo.get_ids_from_indices(ids_rbedge_sumo),
3053                             ids_node=ids_rbnode,
3054                             )
3055
3056        # print '  shapes[0:9]',shapes[0:9]
3057        # print '  edges.shapes[1:10]',edges.shapes[1:10]
3058        # print '  edges.shapes.get_value()[0:9]',edges.shapes.get_value()[0:9]
3059        #net.edges.update(is_update_lanes = False)
3060        # enrich edges with osmattributes
3061        # print '  ids_edge_osm',ids_edge_osm
3062        for id_edge, id_edge_osm, ind_edge_opp in zip(ids_edges, self._ids_edge_osm[inds_valid], np.array(inds_edge_opp, dtype=np.int32)[inds_valid]):
3063            id_sumo = edges.ids_sumo[id_edge]
3064
3065            if id_sumo[0] > '-':  # it is not an opposite edge
3066                road = edges_osm[id_edge_osm]
3067                # print '  configure way',id_edge_osm,id(self.edges_osm[id_edge_osm]),id(road)
3068                road.configure_edge(id_edge, net)
3069                #id_edge_opp = self.get_id_edge_opp
3070                id_sumo_opp = '-'+id_sumo
3071                if edges.ids_sumo.has_index(id_sumo_opp):  # there is an opposite edge
3072                    road.configure_edge(edges.ids_sumo.get_id_from_index(id_sumo_opp), net, is_opp=True)
3073
3074        # make roundabouts
3075