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 getAllowedOutgoing(self, vClass):
126        if vClass is None or vClass == "ignoring":
127            return self._outgoing
128        else:
129            result = {}
130            for e, conns in self._outgoing.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 getConnections(self, toEdge):
140        """Returns all connections to the given target edge"""
141        return self._outgoing.get(toEdge, [])
142
143    def getRawShape(self):
144        """Return the shape that was used in netconvert for building this edge (2D)."""
145        if self._shape is None:
146            self.rebuildShape()
147        return self._rawShape
148
149    def getRawShape3D(self):
150        """Return the shape that was used in netconvert for building this edge (3D)."""
151        if self._shape is None:
152            self.rebuildShape()
153        return self._rawShape3D
154
155    def getShape(self, includeJunctions=False):
156        """Return the 2D shape that is the average of all lane shapes (segment-wise)"""
157        if self._shape is None:
158            self.rebuildShape()
159        if includeJunctions:
160            return self._shapeWithJunctions
161        return self._shape
162
163    def getShape3D(self, includeJunctions=False):
164        if self._shape is None:
165            self.rebuildShape()
166        if includeJunctions:
167            return self._shapeWithJunctions3D
168        return self._shape3D
169
170    def getBoundingBox(self, includeJunctions=True):
171        xmin, ymin, xmax, ymax = sumolib.geomhelper.addToBoundingBox(self.getShape(includeJunctions))
172        assert xmin != xmax or ymin != ymax or self._function == "internal"
173        return (xmin, ymin, xmax, ymax)
174
175    def getClosestLanePosDist(self, point, perpendicular=False):
176        minDist = 1e400
177        minIdx = None
178        minPos = None
179        for i, l in enumerate(self._lanes):
180            pos, dist = l.getClosestLanePosAndDist(point, perpendicular)
181            if dist < minDist:
182                minDist = dist
183                minIdx = i
184                minPos = pos
185        return minIdx, minPos, minDist
186
187    def getSpeed(self):
188        return self._speed
189
190    def getLaneNumber(self):
191        return len(self._lanes)
192
193    def getLane(self, idx):
194        return self._lanes[idx]
195
196    def getLanes(self):
197        return self._lanes
198
199    def select(self, value=True):
200        self._selected = value
201
202    def isSelected(self):
203        return self._selected
204
205    def rebuildShape(self):
206        numLanes = len(self._lanes)
207        if numLanes % 2 == 1:
208            self._shape3D = self._lanes[int(numLanes / 2)].getShape3D()
209        else:
210            self._shape3D = []
211            minLen = -1
212            for _lane in self._lanes:
213                if minLen == -1 or minLen > len(_lane.getShape()):
214                    minLen = len(_lane.getShape())
215            for i in range(minLen):
216                x = 0.
217                y = 0.
218                z = 0.
219                for _lane in self._lanes:
220                    x += _lane.getShape3D()[i][0]
221                    y += _lane.getShape3D()[i][1]
222                    z += _lane.getShape3D()[i][2]
223                self._shape3D.append((x / float(numLanes), y / float(numLanes), z / float(numLanes)))
224
225        if self._function in ["crossing", "walkingarea"]:
226            self._shapeWithJunctions3D = self._shape3D
227            self._rawShape3D = self._shape3D
228        else:
229            self._shapeWithJunctions3D = addJunctionPos(self._shape3D,
230                                                        self._from.getCoord3D(), self._to.getCoord3D())
231            if self._rawShape3D == []:
232                self._rawShape3D = [self._from.getCoord3D(), self._to.getCoord3D()]
233
234        # 2d - versions
235        self._shape = [(x, y) for x, y, z in self._shape3D]  # noqa
236        self._shapeWithJunctions = [(x, y) for x, y, z in self._shapeWithJunctions3D]  # noqa
237        self._rawShape = [(x, y) for x, y, z in self._rawShape3D]  # noqa
238        shapeLength = sumolib.geomhelper.polyLength(self.getShape())
239        if shapeLength > 0:
240            self._lengthGeometryFactor = self.getLength() / shapeLength
241
242    def getLength(self):
243        return self._lanes[0].getLength()
244
245    def getLengthGeometryFactor(self):
246        return self._lengthGeometryFactor
247
248    def setTLS(self, tls):
249        self._tls = tls
250
251    def getFromNode(self):
252        return self._from
253
254    def getToNode(self):
255        return self._to
256
257    def getBidi(self):
258        return self._bidi
259
260    def is_fringe(self, connections=None, checkJunctions=False):
261        """true if this edge has no incoming or no outgoing connections (except turnarounds)
262           If connections is given, only those connections are considered"""
263        if connections is None:
264            return (self.is_fringe(self._incoming, checkJunctions) or
265                    self.is_fringe(self._outgoing, checkJunctions))
266        else:
267            if checkJunctions:
268                assert connections is not None
269                if connections == self._incoming:
270                    return self.getFromNode().getFringe() is not None
271                elif connections == self._outgoing:
272                    return self.getToNode().getFringe() is not None
273            cons = sum([c for c in connections.values()], [])
274            return len([c for c in cons if c._direction not in (
275                Connection.LINKDIR_TURN, Connection.LINKDIR_TURN_LEFTHAND)]) == 0
276
277    def getPermissions(self):
278        """return the allowed vehicle classes for all lanes"""
279        allowed = set()
280        for lane in self._lanes:
281            allowed.update(lane.getPermissions())
282        return list(allowed)
283
284    def allows(self, vClass):
285        """true if this edge has a lane which allows the given vehicle class"""
286        for lane in self._lanes:
287            if lane.allows(vClass):
288                return True
289        return False
290
291    def setParam(self, key, value):
292        self._params[key] = value
293
294    def getParam(self, key, default=None):
295        return self._params.get(key, default)
296
297    def getParams(self):
298        return self._params
299
300    def __repr__(self):
301        if self.getFunction() == '':
302            return '<edge id="%s" from="%s" to="%s"/>' % (self._id, self._from.getID(), self._to.getID())
303        else:
304            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 getAllowedOutgoing(self, vClass):
127        if vClass is None or vClass == "ignoring":
128            return self._outgoing
129        else:
130            result = {}
131            for e, conns in self._outgoing.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 getConnections(self, toEdge):
141        """Returns all connections to the given target edge"""
142        return self._outgoing.get(toEdge, [])
143
144    def getRawShape(self):
145        """Return the shape that was used in netconvert for building this edge (2D)."""
146        if self._shape is None:
147            self.rebuildShape()
148        return self._rawShape
149
150    def getRawShape3D(self):
151        """Return the shape that was used in netconvert for building this edge (3D)."""
152        if self._shape is None:
153            self.rebuildShape()
154        return self._rawShape3D
155
156    def getShape(self, includeJunctions=False):
157        """Return the 2D shape that is the average of all lane shapes (segment-wise)"""
158        if self._shape is None:
159            self.rebuildShape()
160        if includeJunctions:
161            return self._shapeWithJunctions
162        return self._shape
163
164    def getShape3D(self, includeJunctions=False):
165        if self._shape is None:
166            self.rebuildShape()
167        if includeJunctions:
168            return self._shapeWithJunctions3D
169        return self._shape3D
170
171    def getBoundingBox(self, includeJunctions=True):
172        xmin, ymin, xmax, ymax = sumolib.geomhelper.addToBoundingBox(self.getShape(includeJunctions))
173        assert xmin != xmax or ymin != ymax or self._function == "internal"
174        return (xmin, ymin, xmax, ymax)
175
176    def getClosestLanePosDist(self, point, perpendicular=False):
177        minDist = 1e400
178        minIdx = None
179        minPos = None
180        for i, l in enumerate(self._lanes):
181            pos, dist = l.getClosestLanePosAndDist(point, perpendicular)
182            if dist < minDist:
183                minDist = dist
184                minIdx = i
185                minPos = pos
186        return minIdx, minPos, minDist
187
188    def getSpeed(self):
189        return self._speed
190
191    def getLaneNumber(self):
192        return len(self._lanes)
193
194    def getLane(self, idx):
195        return self._lanes[idx]
196
197    def getLanes(self):
198        return self._lanes
199
200    def select(self, value=True):
201        self._selected = value
202
203    def isSelected(self):
204        return self._selected
205
206    def rebuildShape(self):
207        numLanes = len(self._lanes)
208        if numLanes % 2 == 1:
209            self._shape3D = self._lanes[int(numLanes / 2)].getShape3D()
210        else:
211            self._shape3D = []
212            minLen = -1
213            for _lane in self._lanes:
214                if minLen == -1 or minLen > len(_lane.getShape()):
215                    minLen = len(_lane.getShape())
216            for i in range(minLen):
217                x = 0.
218                y = 0.
219                z = 0.
220                for _lane in self._lanes:
221                    x += _lane.getShape3D()[i][0]
222                    y += _lane.getShape3D()[i][1]
223                    z += _lane.getShape3D()[i][2]
224                self._shape3D.append((x / float(numLanes), y / float(numLanes), z / float(numLanes)))
225
226        if self._function in ["crossing", "walkingarea"]:
227            self._shapeWithJunctions3D = self._shape3D
228            self._rawShape3D = self._shape3D
229        else:
230            self._shapeWithJunctions3D = addJunctionPos(self._shape3D,
231                                                        self._from.getCoord3D(), self._to.getCoord3D())
232            if self._rawShape3D == []:
233                self._rawShape3D = [self._from.getCoord3D(), self._to.getCoord3D()]
234
235        # 2d - versions
236        self._shape = [(x, y) for x, y, z in self._shape3D]  # noqa
237        self._shapeWithJunctions = [(x, y) for x, y, z in self._shapeWithJunctions3D]  # noqa
238        self._rawShape = [(x, y) for x, y, z in self._rawShape3D]  # noqa
239        shapeLength = sumolib.geomhelper.polyLength(self.getShape())
240        if shapeLength > 0:
241            self._lengthGeometryFactor = self.getLength() / shapeLength
242
243    def getLength(self):
244        return self._lanes[0].getLength()
245
246    def getLengthGeometryFactor(self):
247        return self._lengthGeometryFactor
248
249    def setTLS(self, tls):
250        self._tls = tls
251
252    def getFromNode(self):
253        return self._from
254
255    def getToNode(self):
256        return self._to
257
258    def getBidi(self):
259        return self._bidi
260
261    def is_fringe(self, connections=None, checkJunctions=False):
262        """true if this edge has no incoming or no outgoing connections (except turnarounds)
263           If connections is given, only those connections are considered"""
264        if connections is None:
265            return (self.is_fringe(self._incoming, checkJunctions) or
266                    self.is_fringe(self._outgoing, checkJunctions))
267        else:
268            if checkJunctions:
269                assert connections is not None
270                if connections == self._incoming:
271                    return self.getFromNode().getFringe() is not None
272                elif connections == self._outgoing:
273                    return self.getToNode().getFringe() is not None
274            cons = sum([c for c in connections.values()], [])
275            return len([c for c in cons if c._direction not in (
276                Connection.LINKDIR_TURN, Connection.LINKDIR_TURN_LEFTHAND)]) == 0
277
278    def getPermissions(self):
279        """return the allowed vehicle classes for all lanes"""
280        allowed = set()
281        for lane in self._lanes:
282            allowed.update(lane.getPermissions())
283        return list(allowed)
284
285    def allows(self, vClass):
286        """true if this edge has a lane which allows the given vehicle class"""
287        for lane in self._lanes:
288            if lane.allows(vClass):
289                return True
290        return False
291
292    def setParam(self, key, value):
293        self._params[key] = value
294
295    def getParam(self, key, default=None):
296        return self._params.get(key, default)
297
298    def getParams(self):
299        return self._params
300
301    def __repr__(self):
302        if self.getFunction() == '':
303            return '<edge id="%s" from="%s" to="%s"/>' % (self._id, self._from.getID(), self._to.getID())
304        else:
305            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 getAllowedOutgoing(self, vClass):
126    def getAllowedOutgoing(self, vClass):
127        if vClass is None or vClass == "ignoring":
128            return self._outgoing
129        else:
130            result = {}
131            for e, conns in self._outgoing.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 getConnections(self, toEdge):
140    def getConnections(self, toEdge):
141        """Returns all connections to the given target edge"""
142        return self._outgoing.get(toEdge, [])

Returns all connections to the given target edge

def getRawShape(self):
144    def getRawShape(self):
145        """Return the shape that was used in netconvert for building this edge (2D)."""
146        if self._shape is None:
147            self.rebuildShape()
148        return self._rawShape

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

def getRawShape3D(self):
150    def getRawShape3D(self):
151        """Return the shape that was used in netconvert for building this edge (3D)."""
152        if self._shape is None:
153            self.rebuildShape()
154        return self._rawShape3D

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

def getShape(self, includeJunctions=False):
156    def getShape(self, includeJunctions=False):
157        """Return the 2D shape that is the average of all lane shapes (segment-wise)"""
158        if self._shape is None:
159            self.rebuildShape()
160        if includeJunctions:
161            return self._shapeWithJunctions
162        return self._shape

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

def getShape3D(self, includeJunctions=False):
164    def getShape3D(self, includeJunctions=False):
165        if self._shape is None:
166            self.rebuildShape()
167        if includeJunctions:
168            return self._shapeWithJunctions3D
169        return self._shape3D
def getBoundingBox(self, includeJunctions=True):
171    def getBoundingBox(self, includeJunctions=True):
172        xmin, ymin, xmax, ymax = sumolib.geomhelper.addToBoundingBox(self.getShape(includeJunctions))
173        assert xmin != xmax or ymin != ymax or self._function == "internal"
174        return (xmin, ymin, xmax, ymax)
def getClosestLanePosDist(self, point, perpendicular=False):
176    def getClosestLanePosDist(self, point, perpendicular=False):
177        minDist = 1e400
178        minIdx = None
179        minPos = None
180        for i, l in enumerate(self._lanes):
181            pos, dist = l.getClosestLanePosAndDist(point, perpendicular)
182            if dist < minDist:
183                minDist = dist
184                minIdx = i
185                minPos = pos
186        return minIdx, minPos, minDist
def getSpeed(self):
188    def getSpeed(self):
189        return self._speed
def getLaneNumber(self):
191    def getLaneNumber(self):
192        return len(self._lanes)
def getLane(self, idx):
194    def getLane(self, idx):
195        return self._lanes[idx]
def getLanes(self):
197    def getLanes(self):
198        return self._lanes
def select(self, value=True):
200    def select(self, value=True):
201        self._selected = value
def isSelected(self):
203    def isSelected(self):
204        return self._selected
def rebuildShape(self):
206    def rebuildShape(self):
207        numLanes = len(self._lanes)
208        if numLanes % 2 == 1:
209            self._shape3D = self._lanes[int(numLanes / 2)].getShape3D()
210        else:
211            self._shape3D = []
212            minLen = -1
213            for _lane in self._lanes:
214                if minLen == -1 or minLen > len(_lane.getShape()):
215                    minLen = len(_lane.getShape())
216            for i in range(minLen):
217                x = 0.
218                y = 0.
219                z = 0.
220                for _lane in self._lanes:
221                    x += _lane.getShape3D()[i][0]
222                    y += _lane.getShape3D()[i][1]
223                    z += _lane.getShape3D()[i][2]
224                self._shape3D.append((x / float(numLanes), y / float(numLanes), z / float(numLanes)))
225
226        if self._function in ["crossing", "walkingarea"]:
227            self._shapeWithJunctions3D = self._shape3D
228            self._rawShape3D = self._shape3D
229        else:
230            self._shapeWithJunctions3D = addJunctionPos(self._shape3D,
231                                                        self._from.getCoord3D(), self._to.getCoord3D())
232            if self._rawShape3D == []:
233                self._rawShape3D = [self._from.getCoord3D(), self._to.getCoord3D()]
234
235        # 2d - versions
236        self._shape = [(x, y) for x, y, z in self._shape3D]  # noqa
237        self._shapeWithJunctions = [(x, y) for x, y, z in self._shapeWithJunctions3D]  # noqa
238        self._rawShape = [(x, y) for x, y, z in self._rawShape3D]  # noqa
239        shapeLength = sumolib.geomhelper.polyLength(self.getShape())
240        if shapeLength > 0:
241            self._lengthGeometryFactor = self.getLength() / shapeLength
def getLength(self):
243    def getLength(self):
244        return self._lanes[0].getLength()
def getLengthGeometryFactor(self):
246    def getLengthGeometryFactor(self):
247        return self._lengthGeometryFactor
def setTLS(self, tls):
249    def setTLS(self, tls):
250        self._tls = tls
def getFromNode(self):
252    def getFromNode(self):
253        return self._from
def getToNode(self):
255    def getToNode(self):
256        return self._to
def getBidi(self):
258    def getBidi(self):
259        return self._bidi
def is_fringe(self, connections=None, checkJunctions=False):
261    def is_fringe(self, connections=None, checkJunctions=False):
262        """true if this edge has no incoming or no outgoing connections (except turnarounds)
263           If connections is given, only those connections are considered"""
264        if connections is None:
265            return (self.is_fringe(self._incoming, checkJunctions) or
266                    self.is_fringe(self._outgoing, checkJunctions))
267        else:
268            if checkJunctions:
269                assert connections is not None
270                if connections == self._incoming:
271                    return self.getFromNode().getFringe() is not None
272                elif connections == self._outgoing:
273                    return self.getToNode().getFringe() is not None
274            cons = sum([c for c in connections.values()], [])
275            return len([c for c in cons if c._direction not in (
276                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):
278    def getPermissions(self):
279        """return the allowed vehicle classes for all lanes"""
280        allowed = set()
281        for lane in self._lanes:
282            allowed.update(lane.getPermissions())
283        return list(allowed)

return the allowed vehicle classes for all lanes

def allows(self, vClass):
285    def allows(self, vClass):
286        """true if this edge has a lane which allows the given vehicle class"""
287        for lane in self._lanes:
288            if lane.allows(vClass):
289                return True
290        return False

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

def setParam(self, key, value):
292    def setParam(self, key, value):
293        self._params[key] = value
def getParam(self, key, default=None):
295    def getParam(self, key, default=None):
296        return self._params.get(key, default)
def getParams(self):
298    def getParams(self):
299        return self._params