-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
node.py
210 lines (171 loc) · 7.04 KB
/
node.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
# Copyright (C) 2011-2023 German Aerospace Center (DLR) and others.
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0/
# This Source Code may also be made available under the following Secondary
# Licenses when the conditions for such availability set forth in the Eclipse
# Public License 2.0 are satisfied: GNU General Public License, version 2
# or later which is available at
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
# @file node.py
# @author Daniel Krajzewicz
# @author Laura Bieker
# @author Karol Stosiek
# @author Michael Behrisch
# @author Jakob Erdmann
# @date 2011-11-28
class Node:
""" Nodes from a sumo network """
def __init__(self, id, type, coord, incLanes, intLanes=None):
self._id = id
self._type = type
self._coord = coord
self._incoming = []
self._outgoing = []
self._foes = {}
self._prohibits = {}
self._incLanes = incLanes
self._intLanes = intLanes
self._shape3D = None
self._shape = None
self._fringe = None
self._params = {}
self._selected = False
def getID(self):
return self._id
def setShape(self, shape):
"""Set the shape of the node.
Shape must be a list containing x,y,z coords as numbers
to represent the shape of the node.
"""
for pp in shape:
if len(pp) != 3:
raise ValueError('shape point must consist of x,y,z')
self._shape3D = shape
self._shape = [(x, y) for x, y, z in shape]
def getShape(self):
"""Returns the shape of the node in 2d.
This function returns the shape of the node, as defined in the net.xml
file. The returned shape is a list containing numerical
2-tuples representing the x,y coordinates of the shape points.
If no shape is defined in the xml, an empty list will be returned.
"""
return self._shape
def getShape3D(self):
"""Returns the shape of the node in 3d.
This function returns the shape of the node, as defined in the net.xml
file. The returned shape is a list containing numerical
3-tuples representing the x,y,z coordinates of the shape points.
If no shape is defined in the xml, an empty list will be returned.
"""
return self._shape3D
def addOutgoing(self, edge):
self._outgoing.append(edge)
def getOutgoing(self):
return self._outgoing
def addIncoming(self, edge):
self._incoming.append(edge)
def getIncoming(self):
return self._incoming
def getInternal(self):
"""Returns the internal lanes starting at the border of the node.
This function returns the junction internal lanes as defined in the
"intLanes" attribute in net.xml. Note that this may not contain
all internal lanes because there may be internal junctions where
further internal lanes start.
The returned list contains string ids and no lane objects.
"""
return self._intLanes
def setFoes(self, index, foes, prohibits):
self._foes[index] = foes
self._prohibits[index] = prohibits
def areFoes(self, link1, link2):
return self._foes[link1][len(self._foes[link1]) - link2 - 1] == '1'
def getLinkIndex(self, conn):
ret = 0
for lane_id in self._incLanes:
lastUnderscore = lane_id.rfind("_")
if lastUnderscore > 0:
edge_id = lane_id[:lastUnderscore]
index = lane_id[lastUnderscore+1:]
edge = [e for e in self._incoming if e.getID() == edge_id][0]
for candidate_conn in edge.getLane(int(index)).getOutgoing():
fromFunction = candidate_conn.getFromLane().getEdge().getFunction()
toFunction = candidate_conn.getToLane().getEdge().getFunction()
if toFunction == "walkingarea" or (fromFunction == "walkingarea" and not toFunction == "crossing"):
continue
if candidate_conn == conn:
return ret
ret += 1
return -1
def forbids(self, possProhibitor, possProhibited):
possProhibitorIndex = self.getLinkIndex(possProhibitor)
possProhibitedIndex = self.getLinkIndex(possProhibited)
if possProhibitorIndex < 0 or possProhibitedIndex < 0:
return False
ps = self._prohibits[possProhibitedIndex]
return ps[-(possProhibitorIndex + 1)] == '1'
def getCoord(self):
return tuple(self._coord[:2])
def getCoord3D(self):
return self._coord
def getType(self):
return self._type
def getFringe(self):
return self._fringe
def getConnections(self, source=None, target=None):
if source:
incoming = [source]
else:
incoming = list(self._incoming)
conns = []
for e in incoming:
if hasattr(e, "getLanes"):
lanes = e.getLanes()
else:
# assuming source is a lane
lanes = [e]
for _lane in lanes:
all_outgoing = _lane.getOutgoing()
outgoing = []
if target:
if hasattr(target, "getLanes"):
for o in all_outgoing:
if o.getTo() == target:
outgoing.append(o)
else:
# assuming target is a lane
for o in all_outgoing:
if o.getToLane() == target:
outgoing.append(o)
else:
outgoing = all_outgoing
conns.extend(outgoing)
return conns
def select(self, value=True):
self._selected = value
def isSelected(self):
return self._selected
def setParam(self, key, value):
self._params[key] = value
def getParam(self, key, default=None):
return self._params.get(key, default)
def getParams(self):
return self._params
def getNeighboringNodes(self, outgoingNodes=True, incomingNodes=True):
neighboring = []
if incomingNodes:
edges = self._incoming
for e in edges:
if not (e.getFromNode() in neighboring) and not (e.getFromNode().getID() == self.getID()):
neighboring.append(e.getFromNode())
if outgoingNodes:
edges = self._outgoing
for e in edges:
if not (e.getToNode() in neighboring) and not (e.getToNode().getID() == self.getID()):
neighboring.append(e.getToNode())
return neighboring
def __repr__(self):
return '<junction id="%s"/>' % self._id