sumolib.net.edge

  1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
  2# Copyright (C) 2011-2026 German Aerospace Center (DLR) and others.
  3# This program and the accompanying materials are made available under the
  4# terms of the Eclipse Public License 2.0 which is available at
  5# https://www.eclipse.org/legal/epl-2.0/
  6# This Source Code may also be made available under the following Secondary
  7# Licenses when the conditions for such availability set forth in the Eclipse
  8# Public License 2.0 are satisfied: GNU General Public License, version 2
  9# or later which is available at
 10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
 11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
 12
 13# @file    edge.py
 14# @author  Daniel Krajzewicz
 15# @author  Laura Bieker
 16# @author  Karol Stosiek
 17# @author  Michael Behrisch
 18# @author  Jakob Erdmann
 19# @date    2011-11-28
 20
 21import sumolib.geomhelper
 22from .connection import Connection
 23from .lane import addJunctionPos
 24
 25
 26class Edge:
 27
 28    """ Edges from a sumo network """
 29
 30    def __init__(self, id, fromN, toN, prio, function, name, edgeType='', routingType=''):
 31        self._id = id
 32        self._from = fromN
 33        self._to = toN
 34        self._priority = prio
 35        if fromN:
 36            fromN.addOutgoing(self)
 37        if toN:
 38            toN.addIncoming(self)
 39        self._lanes = []
 40        self._speed = None
 41        self._length = None
 42        self._incoming = {}
 43        self._outgoing = {}
 44        self._crossingEdges = []
 45        self._shape = None
 46        self._shapeWithJunctions = None
 47        self._shape3D = None
 48        self._shapeWithJunctions3D = None
 49        self._rawShape = None
 50        self._rawShape3D = None
 51        self._function = function
 52        self._tls = None
 53        self._name = name
 54        self._type = edgeType
 55        self._routingType = routingType
 56        self._params = {}
 57        self._bidi = None
 58        self._selected = False
 59        self._lengthGeometryFactor = 1
 60
 61    def __lt__(self, other):
 62        return self.getID() < other.getID()
 63
 64    def getName(self):
 65        return self._name
 66
 67    def isSpecial(self):
 68        """ Check if the edge has a special function.
 69
 70        Returns False if edge's function is 'normal', else False, e.g. for
 71        internal edges or connector edges """
 72
 73        return self._function != ""
 74
 75    def getFunction(self):
 76        return self._function
 77
 78    def getPriority(self):
 79        return self._priority
 80
 81    def getType(self):
 82        return self._type
 83
 84    def getRoutingType(self):
 85        """ Return the effective routingType that would be used by duarouter or sumo"""
 86        return self._routingType if self._routingType != "" else self._type
 87
 88    def getTLS(self):
 89        return self._tls
 90
 91    def getCrossingEdges(self):
 92        return self._crossingEdges
 93
 94    def addLane(self, lane):
 95        self._lanes.append(lane)
 96        self._speed = lane.getSpeed()
 97        self._length = lane.getLength()
 98
 99    def addOutgoing(self, conn):
100        if conn._to not in self._outgoing:
101            self._outgoing[conn._to] = []
102        self._outgoing[conn._to].append(conn)
103
104    def _addIncoming(self, conn):
105        if conn._from not in self._incoming:
106            self._incoming[conn._from] = []
107        self._incoming[conn._from].append(conn)
108
109    def _addCrossingEdge(self, edge):
110        if edge not in self._crossingEdges:
111            self._crossingEdges.append(edge)
112
113    def setRawShape(self, shape):
114        self._rawShape3D = shape
115
116    def getID(self):
117        return self._id
118
119    def getIncoming(self):
120        return self._incoming
121
122    def getOutgoing(self):
123        return self._outgoing
124
125    def getAllowedIncoming(self, vClass):
126        if vClass is None or vClass == "ignoring":
127            return self._incoming
128        else:
129            result = {}
130            for e, conns in self._incoming.items():
131                allowedConns = [c for c in conns if
132                                c.getFromLane().allows(vClass) and
133                                c.getToLane().allows(vClass) and
134                                c.allows(vClass)]
135                if allowedConns:
136                    result[e] = allowedConns
137            return result
138
139    def getAllowedOutgoing(self, vClass):
140        if vClass is None or vClass == "ignoring":
141            return self._outgoing
142        else:
143            result = {}
144            for e, conns in self._outgoing.items():
145                allowedConns = [c for c in conns if
146                                c.getFromLane().allows(vClass) and
147                                c.getToLane().allows(vClass) and
148                                c.allows(vClass)]
149                if allowedConns:
150                    result[e] = allowedConns
151            return result
152
153    def getConnections(self, toEdge):
154        """Returns all connections to the given target edge"""
155        return self._outgoing.get(toEdge, [])
156
157    def getRawShape(self):
158        """Return the shape that was used in netconvert for building this edge (2D)."""
159        if self._shape is None:
160            self.rebuildShape()
161        return self._rawShape
162
163    def getRawShape3D(self):
164        """Return the shape that was used in netconvert for building this edge (3D)."""
165        if self._shape is None:
166            self.rebuildShape()
167        return self._rawShape3D
168
169    def getShape(self, includeJunctions=False):
170        """Return the 2D shape that is the average of all lane shapes (segment-wise)"""
171        if self._shape is None:
172            self.rebuildShape()
173        if includeJunctions:
174            return self._shapeWithJunctions
175        return self._shape
176
177    def getShape3D(self, includeJunctions=False):
178        if self._shape is None:
179            self.rebuildShape()
180        if includeJunctions:
181            return self._shapeWithJunctions3D
182        return self._shape3D
183
184    def getBoundingBox(self, includeJunctions=True):
185        xmin, ymin, xmax, ymax = sumolib.geomhelper.addToBoundingBox(self.getShape(includeJunctions))
186        assert xmin != xmax or ymin != ymax or self._function == "internal"
187        return (xmin, ymin, xmax, ymax)
188
189    def getClosestLanePosDist(self, point, perpendicular=False):
190        minDist = 1e400
191        minIdx = None
192        minPos = None
193        for i, l in enumerate(self._lanes):
194            pos, dist = l.getClosestLanePosAndDist(point, perpendicular)
195            if dist < minDist:
196                minDist = dist
197                minIdx = i
198                minPos = pos
199        return minIdx, minPos, minDist
200
201    def getSpeed(self):
202        return self._speed
203
204    def getLaneNumber(self):
205        return len(self._lanes)
206
207    def getLane(self, idx):
208        return self._lanes[idx]
209
210    def getLanes(self):
211        return self._lanes
212
213    def select(self, value=True):
214        self._selected = value
215
216    def isSelected(self):
217        return self._selected
218
219    def rebuildShape(self):
220        numLanes = len(self._lanes)
221        if numLanes % 2 == 1:
222            self._shape3D = self._lanes[int(numLanes / 2)].getShape3D()
223        else:
224            self._shape3D = []
225            minLen = -1
226            for _lane in self._lanes:
227                if minLen == -1 or minLen > len(_lane.getShape()):
228                    minLen = len(_lane.getShape())
229            for i in range(minLen):
230                x = 0.
231                y = 0.
232                z = 0.
233                for _lane in self._lanes:
234                    x += _lane.getShape3D()[i][0]
235                    y += _lane.getShape3D()[i][1]
236                    z += _lane.getShape3D()[i][2]
237                self._shape3D.append((x / float(numLanes), y / float(numLanes), z / float(numLanes)))
238
239        if self._function in ["crossing", "walkingarea"]:
240            self._shapeWithJunctions3D = self._shape3D
241            self._rawShape3D = self._shape3D
242        else:
243            self._shapeWithJunctions3D = addJunctionPos(self._shape3D,
244                                                        self._from.getCoord3D(), self._to.getCoord3D())
245            if self._rawShape3D == []:
246                self._rawShape3D = [self._from.getCoord3D(), self._to.getCoord3D()]
247
248        # 2d - versions
249        self._shape = [(x, y) for x, y, z in self._shape3D]  # noqa
250        self._shapeWithJunctions = [(x, y) for x, y, z in self._shapeWithJunctions3D]  # noqa
251        self._rawShape = [(x, y) for x, y, z in self._rawShape3D]  # noqa
252        shapeLength = sumolib.geomhelper.polyLength(self.getShape())
253        if shapeLength > 0:
254            self._lengthGeometryFactor = self.getLength() / shapeLength
255
256    def getLength(self):
257        return self._lanes[0].getLength()
258
259    def getLengthGeometryFactor(self):
260        return self._lengthGeometryFactor
261
262    def setTLS(self, tls):
263        self._tls = tls
264
265    def getFromNode(self):
266        return self._from
267
268    def getToNode(self):
269        return self._to
270
271    def getBidi(self):
272        return self._bidi
273
274    def is_fringe(self, connections=None, checkJunctions=False):
275        """true if this edge has no incoming or no outgoing connections (except turnarounds)
276           If connections is given, only those connections are considered"""
277        if connections is None:
278            return (self.is_fringe(self._incoming, checkJunctions) or
279                    self.is_fringe(self._outgoing, checkJunctions))
280        else:
281            if checkJunctions:
282                assert connections is not None
283                if connections == self._incoming:
284                    return self.getFromNode().getFringe() is not None
285                elif connections == self._outgoing:
286                    return self.getToNode().getFringe() is not None
287            cons = sum([c for c in connections.values()], [])
288            return len([c for c in cons if c._direction not in (
289                Connection.LINKDIR_TURN, Connection.LINKDIR_TURN_LEFTHAND)]) == 0
290
291    def getPermissions(self):
292        """return the allowed vehicle classes for all lanes"""
293        allowed = set()
294        for lane in self._lanes:
295            allowed.update(lane.getPermissions())
296        return list(allowed)
297
298    def allows(self, vClass):
299        """true if this edge has a lane which allows the given vehicle class"""
300        for lane in self._lanes:
301            if lane.allows(vClass):
302                return True
303        return False
304
305    def setParam(self, key, value):
306        self._params[key] = value
307
308    def getParam(self, key, default=None):
309        return self._params.get(key, default)
310
311    def getParams(self):
312        return self._params
313
314    def __repr__(self):
315        if self.getFunction() == '':
316            return '<edge id="%s" from="%s" to="%s"/>' % (self._id, self._from.getID(), self._to.getID())
317        else:
318            return '<edge id="%s" function="%s"/>' % (self._id, self.getFunction())
class Edge:
 27class Edge:
 28
 29    """ Edges from a sumo network """
 30
 31    def __init__(self, id, fromN, toN, prio, function, name, edgeType='', routingType=''):
 32        self._id = id
 33        self._from = fromN
 34        self._to = toN
 35        self._priority = prio
 36        if fromN:
 37            fromN.addOutgoing(self)
 38        if toN:
 39            toN.addIncoming(self)
 40        self._lanes = []
 41        self._speed = None
 42        self._length = None
 43        self._incoming = {}
 44        self._outgoing = {}
 45        self._crossingEdges = []
 46        self._shape = None
 47        self._shapeWithJunctions = None
 48        self._shape3D = None
 49        self._shapeWithJunctions3D = None
 50        self._rawShape = None
 51        self._rawShape3D = None
 52        self._function = function
 53        self._tls = None
 54        self._name = name
 55        self._type = edgeType
 56        self._routingType = routingType
 57        self._params = {}
 58        self._bidi = None
 59        self._selected = False
 60        self._lengthGeometryFactor = 1
 61
 62    def __lt__(self, other):
 63        return self.getID() < other.getID()
 64
 65    def getName(self):
 66        return self._name
 67
 68    def isSpecial(self):
 69        """ Check if the edge has a special function.
 70
 71        Returns False if edge's function is 'normal', else False, e.g. for
 72        internal edges or connector edges """
 73
 74        return self._function != ""
 75
 76    def getFunction(self):
 77        return self._function
 78
 79    def getPriority(self):
 80        return self._priority
 81
 82    def getType(self):
 83        return self._type
 84
 85    def getRoutingType(self):
 86        """ Return the effective routingType that would be used by duarouter or sumo"""
 87        return self._routingType if self._routingType != "" else self._type
 88
 89    def getTLS(self):
 90        return self._tls
 91
 92    def getCrossingEdges(self):
 93        return self._crossingEdges
 94
 95    def addLane(self, lane):
 96        self._lanes.append(lane)
 97        self._speed = lane.getSpeed()
 98        self._length = lane.getLength()
 99
100    def addOutgoing(self, conn):
101        if conn._to not in self._outgoing:
102            self._outgoing[conn._to] = []
103        self._outgoing[conn._to].append(conn)
104
105    def _addIncoming(self, conn):
106        if conn._from not in self._incoming:
107            self._incoming[conn._from] = []
108        self._incoming[conn._from].append(conn)
109
110    def _addCrossingEdge(self, edge):
111        if edge not in self._crossingEdges:
112            self._crossingEdges.append(edge)
113
114    def setRawShape(self, shape):
115        self._rawShape3D = shape
116
117    def getID(self):
118        return self._id
119
120    def getIncoming(self):
121        return self._incoming
122
123    def getOutgoing(self):
124        return self._outgoing
125
126    def getAllowedIncoming(self, vClass):
127        if vClass is None or vClass == "ignoring":
128            return self._incoming
129        else:
130            result = {}
131            for e, conns in self._incoming.items():
132                allowedConns = [c for c in conns if
133                                c.getFromLane().allows(vClass) and
134                                c.getToLane().allows(vClass) and
135                                c.allows(vClass)]
136                if allowedConns:
137                    result[e] = allowedConns
138            return result
139
140    def getAllowedOutgoing(self, vClass):
141        if vClass is None or vClass == "ignoring":
142            return self._outgoing
143        else:
144            result = {}
145            for e, conns in self._outgoing.items():
146                allowedConns = [c for c in conns if
147                                c.getFromLane().allows(vClass) and
148                                c.getToLane().allows(vClass) and
149                                c.allows(vClass)]
150                if allowedConns:
151                    result[e] = allowedConns
152            return result
153
154    def getConnections(self, toEdge):
155        """Returns all connections to the given target edge"""
156        return self._outgoing.get(toEdge, [])
157
158    def getRawShape(self):
159        """Return the shape that was used in netconvert for building this edge (2D)."""
160        if self._shape is None:
161            self.rebuildShape()
162        return self._rawShape
163
164    def getRawShape3D(self):
165        """Return the shape that was used in netconvert for building this edge (3D)."""
166        if self._shape is None:
167            self.rebuildShape()
168        return self._rawShape3D
169
170    def getShape(self, includeJunctions=False):
171        """Return the 2D shape that is the average of all lane shapes (segment-wise)"""
172        if self._shape is None:
173            self.rebuildShape()
174        if includeJunctions:
175            return self._shapeWithJunctions
176        return self._shape
177
178    def getShape3D(self, includeJunctions=False):
179        if self._shape is None:
180            self.rebuildShape()
181        if includeJunctions:
182            return self._shapeWithJunctions3D
183        return self._shape3D
184
185    def getBoundingBox(self, includeJunctions=True):
186        xmin, ymin, xmax, ymax = sumolib.geomhelper.addToBoundingBox(self.getShape(includeJunctions))
187        assert xmin != xmax or ymin != ymax or self._function == "internal"
188        return (xmin, ymin, xmax, ymax)
189
190    def getClosestLanePosDist(self, point, perpendicular=False):
191        minDist = 1e400
192        minIdx = None
193        minPos = None
194        for i, l in enumerate(self._lanes):
195            pos, dist = l.getClosestLanePosAndDist(point, perpendicular)
196            if dist < minDist:
197                minDist = dist
198                minIdx = i
199                minPos = pos
200        return minIdx, minPos, minDist
201
202    def getSpeed(self):
203        return self._speed
204
205    def getLaneNumber(self):
206        return len(self._lanes)
207
208    def getLane(self, idx):
209        return self._lanes[idx]
210
211    def getLanes(self):
212        return self._lanes
213
214    def select(self, value=True):
215        self._selected = value
216
217    def isSelected(self):
218        return self._selected
219
220    def rebuildShape(self):
221        numLanes = len(self._lanes)
222        if numLanes % 2 == 1:
223            self._shape3D = self._lanes[int(numLanes / 2)].getShape3D()
224        else:
225            self._shape3D = []
226            minLen = -1
227            for _lane in self._lanes:
228                if minLen == -1 or minLen > len(_lane.getShape()):
229                    minLen = len(_lane.getShape())
230            for i in range(minLen):
231                x = 0.
232                y = 0.
233                z = 0.
234                for _lane in self._lanes:
235                    x += _lane.getShape3D()[i][0]
236                    y += _lane.getShape3D()[i][1]
237                    z += _lane.getShape3D()[i][2]
238                self._shape3D.append((x / float(numLanes), y / float(numLanes), z / float(numLanes)))
239
240        if self._function in ["crossing", "walkingarea"]:
241            self._shapeWithJunctions3D = self._shape3D
242            self._rawShape3D = self._shape3D
243        else:
244            self._shapeWithJunctions3D = addJunctionPos(self._shape3D,
245                                                        self._from.getCoord3D(), self._to.getCoord3D())
246            if self._rawShape3D == []:
247                self._rawShape3D = [self._from.getCoord3D(), self._to.getCoord3D()]
248
249        # 2d - versions
250        self._shape = [(x, y) for x, y, z in self._shape3D]  # noqa
251        self._shapeWithJunctions = [(x, y) for x, y, z in self._shapeWithJunctions3D]  # noqa
252        self._rawShape = [(x, y) for x, y, z in self._rawShape3D]  # noqa
253        shapeLength = sumolib.geomhelper.polyLength(self.getShape())
254        if shapeLength > 0:
255            self._lengthGeometryFactor = self.getLength() / shapeLength
256
257    def getLength(self):
258        return self._lanes[0].getLength()
259
260    def getLengthGeometryFactor(self):
261        return self._lengthGeometryFactor
262
263    def setTLS(self, tls):
264        self._tls = tls
265
266    def getFromNode(self):
267        return self._from
268
269    def getToNode(self):
270        return self._to
271
272    def getBidi(self):
273        return self._bidi
274
275    def is_fringe(self, connections=None, checkJunctions=False):
276        """true if this edge has no incoming or no outgoing connections (except turnarounds)
277           If connections is given, only those connections are considered"""
278        if connections is None:
279            return (self.is_fringe(self._incoming, checkJunctions) or
280                    self.is_fringe(self._outgoing, checkJunctions))
281        else:
282            if checkJunctions:
283                assert connections is not None
284                if connections == self._incoming:
285                    return self.getFromNode().getFringe() is not None
286                elif connections == self._outgoing:
287                    return self.getToNode().getFringe() is not None
288            cons = sum([c for c in connections.values()], [])
289            return len([c for c in cons if c._direction not in (
290                Connection.LINKDIR_TURN, Connection.LINKDIR_TURN_LEFTHAND)]) == 0
291
292    def getPermissions(self):
293        """return the allowed vehicle classes for all lanes"""
294        allowed = set()
295        for lane in self._lanes:
296            allowed.update(lane.getPermissions())
297        return list(allowed)
298
299    def allows(self, vClass):
300        """true if this edge has a lane which allows the given vehicle class"""
301        for lane in self._lanes:
302            if lane.allows(vClass):
303                return True
304        return False
305
306    def setParam(self, key, value):
307        self._params[key] = value
308
309    def getParam(self, key, default=None):
310        return self._params.get(key, default)
311
312    def getParams(self):
313        return self._params
314
315    def __repr__(self):
316        if self.getFunction() == '':
317            return '<edge id="%s" from="%s" to="%s"/>' % (self._id, self._from.getID(), self._to.getID())
318        else:
319            return '<edge id="%s" function="%s"/>' % (self._id, self.getFunction())

Edges from a sumo network

Edge(id, fromN, toN, prio, function, name, edgeType='', routingType='')
31    def __init__(self, id, fromN, toN, prio, function, name, edgeType='', routingType=''):
32        self._id = id
33        self._from = fromN
34        self._to = toN
35        self._priority = prio
36        if fromN:
37            fromN.addOutgoing(self)
38        if toN:
39            toN.addIncoming(self)
40        self._lanes = []
41        self._speed = None
42        self._length = None
43        self._incoming = {}
44        self._outgoing = {}
45        self._crossingEdges = []
46        self._shape = None
47        self._shapeWithJunctions = None
48        self._shape3D = None
49        self._shapeWithJunctions3D = None
50        self._rawShape = None
51        self._rawShape3D = None
52        self._function = function
53        self._tls = None
54        self._name = name
55        self._type = edgeType
56        self._routingType = routingType
57        self._params = {}
58        self._bidi = None
59        self._selected = False
60        self._lengthGeometryFactor = 1
def getName(self):
65    def getName(self):
66        return self._name
def isSpecial(self):
68    def isSpecial(self):
69        """ Check if the edge has a special function.
70
71        Returns False if edge's function is 'normal', else False, e.g. for
72        internal edges or connector edges """
73
74        return self._function != ""

Check if the edge has a special function.

Returns False if edge's function is 'normal', else False, e.g. for internal edges or connector edges

def getFunction(self):
76    def getFunction(self):
77        return self._function
def getPriority(self):
79    def getPriority(self):
80        return self._priority
def getType(self):
82    def getType(self):
83        return self._type
def getRoutingType(self):
85    def getRoutingType(self):
86        """ Return the effective routingType that would be used by duarouter or sumo"""
87        return self._routingType if self._routingType != "" else self._type

Return the effective routingType that would be used by duarouter or sumo

def getTLS(self):
89    def getTLS(self):
90        return self._tls
def getCrossingEdges(self):
92    def getCrossingEdges(self):
93        return self._crossingEdges
def addLane(self, lane):
95    def addLane(self, lane):
96        self._lanes.append(lane)
97        self._speed = lane.getSpeed()
98        self._length = lane.getLength()
def addOutgoing(self, conn):
100    def addOutgoing(self, conn):
101        if conn._to not in self._outgoing:
102            self._outgoing[conn._to] = []
103        self._outgoing[conn._to].append(conn)
def setRawShape(self, shape):
114    def setRawShape(self, shape):
115        self._rawShape3D = shape
def getID(self):
117    def getID(self):
118        return self._id
def getIncoming(self):
120    def getIncoming(self):
121        return self._incoming
def getOutgoing(self):
123    def getOutgoing(self):
124        return self._outgoing
def getAllowedIncoming(self, vClass):
126    def getAllowedIncoming(self, vClass):
127        if vClass is None or vClass == "ignoring":
128            return self._incoming
129        else:
130            result = {}
131            for e, conns in self._incoming.items():
132                allowedConns = [c for c in conns if
133                                c.getFromLane().allows(vClass) and
134                                c.getToLane().allows(vClass) and
135                                c.allows(vClass)]
136                if allowedConns:
137                    result[e] = allowedConns
138            return result
def getAllowedOutgoing(self, vClass):
140    def getAllowedOutgoing(self, vClass):
141        if vClass is None or vClass == "ignoring":
142            return self._outgoing
143        else:
144            result = {}
145            for e, conns in self._outgoing.items():
146                allowedConns = [c for c in conns if
147                                c.getFromLane().allows(vClass) and
148                                c.getToLane().allows(vClass) and
149                                c.allows(vClass)]
150                if allowedConns:
151                    result[e] = allowedConns
152            return result
def getConnections(self, toEdge):
154    def getConnections(self, toEdge):
155        """Returns all connections to the given target edge"""
156        return self._outgoing.get(toEdge, [])

Returns all connections to the given target edge

def getRawShape(self):
158    def getRawShape(self):
159        """Return the shape that was used in netconvert for building this edge (2D)."""
160        if self._shape is None:
161            self.rebuildShape()
162        return self._rawShape

Return the shape that was used in netconvert for building this edge (2D).

def getRawShape3D(self):
164    def getRawShape3D(self):
165        """Return the shape that was used in netconvert for building this edge (3D)."""
166        if self._shape is None:
167            self.rebuildShape()
168        return self._rawShape3D

Return the shape that was used in netconvert for building this edge (3D).

def getShape(self, includeJunctions=False):
170    def getShape(self, includeJunctions=False):
171        """Return the 2D shape that is the average of all lane shapes (segment-wise)"""
172        if self._shape is None:
173            self.rebuildShape()
174        if includeJunctions:
175            return self._shapeWithJunctions
176        return self._shape

Return the 2D shape that is the average of all lane shapes (segment-wise)

def getShape3D(self, includeJunctions=False):
178    def getShape3D(self, includeJunctions=False):
179        if self._shape is None:
180            self.rebuildShape()
181        if includeJunctions:
182            return self._shapeWithJunctions3D
183        return self._shape3D
def getBoundingBox(self, includeJunctions=True):
185    def getBoundingBox(self, includeJunctions=True):
186        xmin, ymin, xmax, ymax = sumolib.geomhelper.addToBoundingBox(self.getShape(includeJunctions))
187        assert xmin != xmax or ymin != ymax or self._function == "internal"
188        return (xmin, ymin, xmax, ymax)
def getClosestLanePosDist(self, point, perpendicular=False):
190    def getClosestLanePosDist(self, point, perpendicular=False):
191        minDist = 1e400
192        minIdx = None
193        minPos = None
194        for i, l in enumerate(self._lanes):
195            pos, dist = l.getClosestLanePosAndDist(point, perpendicular)
196            if dist < minDist:
197                minDist = dist
198                minIdx = i
199                minPos = pos
200        return minIdx, minPos, minDist
def getSpeed(self):
202    def getSpeed(self):
203        return self._speed
def getLaneNumber(self):
205    def getLaneNumber(self):
206        return len(self._lanes)
def getLane(self, idx):
208    def getLane(self, idx):
209        return self._lanes[idx]
def getLanes(self):
211    def getLanes(self):
212        return self._lanes
def select(self, value=True):
214    def select(self, value=True):
215        self._selected = value
def isSelected(self):
217    def isSelected(self):
218        return self._selected
def rebuildShape(self):
220    def rebuildShape(self):
221        numLanes = len(self._lanes)
222        if numLanes % 2 == 1:
223            self._shape3D = self._lanes[int(numLanes / 2)].getShape3D()
224        else:
225            self._shape3D = []
226            minLen = -1
227            for _lane in self._lanes:
228                if minLen == -1 or minLen > len(_lane.getShape()):
229                    minLen = len(_lane.getShape())
230            for i in range(minLen):
231                x = 0.
232                y = 0.
233                z = 0.
234                for _lane in self._lanes:
235                    x += _lane.getShape3D()[i][0]
236                    y += _lane.getShape3D()[i][1]
237                    z += _lane.getShape3D()[i][2]
238                self._shape3D.append((x / float(numLanes), y / float(numLanes), z / float(numLanes)))
239
240        if self._function in ["crossing", "walkingarea"]:
241            self._shapeWithJunctions3D = self._shape3D
242            self._rawShape3D = self._shape3D
243        else:
244            self._shapeWithJunctions3D = addJunctionPos(self._shape3D,
245                                                        self._from.getCoord3D(), self._to.getCoord3D())
246            if self._rawShape3D == []:
247                self._rawShape3D = [self._from.getCoord3D(), self._to.getCoord3D()]
248
249        # 2d - versions
250        self._shape = [(x, y) for x, y, z in self._shape3D]  # noqa
251        self._shapeWithJunctions = [(x, y) for x, y, z in self._shapeWithJunctions3D]  # noqa
252        self._rawShape = [(x, y) for x, y, z in self._rawShape3D]  # noqa
253        shapeLength = sumolib.geomhelper.polyLength(self.getShape())
254        if shapeLength > 0:
255            self._lengthGeometryFactor = self.getLength() / shapeLength
def getLength(self):
257    def getLength(self):
258        return self._lanes[0].getLength()
def getLengthGeometryFactor(self):
260    def getLengthGeometryFactor(self):
261        return self._lengthGeometryFactor
def setTLS(self, tls):
263    def setTLS(self, tls):
264        self._tls = tls
def getFromNode(self):
266    def getFromNode(self):
267        return self._from
def getToNode(self):
269    def getToNode(self):
270        return self._to
def getBidi(self):
272    def getBidi(self):
273        return self._bidi
def is_fringe(self, connections=None, checkJunctions=False):
275    def is_fringe(self, connections=None, checkJunctions=False):
276        """true if this edge has no incoming or no outgoing connections (except turnarounds)
277           If connections is given, only those connections are considered"""
278        if connections is None:
279            return (self.is_fringe(self._incoming, checkJunctions) or
280                    self.is_fringe(self._outgoing, checkJunctions))
281        else:
282            if checkJunctions:
283                assert connections is not None
284                if connections == self._incoming:
285                    return self.getFromNode().getFringe() is not None
286                elif connections == self._outgoing:
287                    return self.getToNode().getFringe() is not None
288            cons = sum([c for c in connections.values()], [])
289            return len([c for c in cons if c._direction not in (
290                Connection.LINKDIR_TURN, Connection.LINKDIR_TURN_LEFTHAND)]) == 0

true if this edge has no incoming or no outgoing connections (except turnarounds) If connections is given, only those connections are considered

def getPermissions(self):
292    def getPermissions(self):
293        """return the allowed vehicle classes for all lanes"""
294        allowed = set()
295        for lane in self._lanes:
296            allowed.update(lane.getPermissions())
297        return list(allowed)

return the allowed vehicle classes for all lanes

def allows(self, vClass):
299    def allows(self, vClass):
300        """true if this edge has a lane which allows the given vehicle class"""
301        for lane in self._lanes:
302            if lane.allows(vClass):
303                return True
304        return False

true if this edge has a lane which allows the given vehicle class

def setParam(self, key, value):
306    def setParam(self, key, value):
307        self._params[key] = value
def getParam(self, key, default=None):
309    def getParam(self, key, default=None):
310        return self._params.get(key, default)
def getParams(self):
312    def getParams(self):
313        return self._params