sumolib.net.node
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 node.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 21 22class Node: 23 24 """ Nodes from a sumo network """ 25 26 def __init__(self, id, type, coord, incLanes, intLanes=None): 27 self._id = id 28 self._type = type 29 self._coord = coord 30 self._incoming = [] 31 self._outgoing = [] 32 self._foes = {} 33 self._prohibits = {} 34 self._incLanes = incLanes 35 self._intLanes = intLanes 36 self._shape3D = None 37 self._shape = None 38 self._fringe = None 39 self._params = {} 40 self._selected = False 41 42 def getID(self): 43 return self._id 44 45 def getTLSID(self): 46 for e in self.getIncoming(): 47 for to, cons in e.getOutgoing().items(): 48 for c in cons: 49 if c.getTLSID(): 50 return c.getTLSID() 51 return None 52 53 def setShape(self, shape): 54 """Set the shape of the node. 55 56 Shape must be a list containing x,y,z coords as numbers 57 to represent the shape of the node. 58 """ 59 for pp in shape: 60 if len(pp) != 3: 61 raise ValueError('shape point must consist of x,y,z') 62 self._shape3D = shape 63 self._shape = [(x, y) for x, y, z in shape] 64 65 def getShape(self): 66 """Returns the shape of the node in 2d. 67 68 This function returns the shape of the node, as defined in the net.xml 69 file. The returned shape is a list containing numerical 70 2-tuples representing the x,y coordinates of the shape points. 71 72 If no shape is defined in the xml, an empty list will be returned. 73 """ 74 75 return self._shape 76 77 def getShape3D(self): 78 """Returns the shape of the node in 3d. 79 80 This function returns the shape of the node, as defined in the net.xml 81 file. The returned shape is a list containing numerical 82 3-tuples representing the x,y,z coordinates of the shape points. 83 84 If no shape is defined in the xml, an empty list will be returned. 85 """ 86 87 return self._shape3D 88 89 def addOutgoing(self, edge): 90 self._outgoing.append(edge) 91 92 def getOutgoing(self): 93 return self._outgoing 94 95 def addIncoming(self, edge): 96 self._incoming.append(edge) 97 98 def getIncoming(self): 99 return self._incoming 100 101 def getInternal(self): 102 """Returns the internal lanes starting at the border of the node. 103 104 This function returns the junction internal lanes as defined in the 105 "intLanes" attribute in net.xml. Note that this may not contain 106 all internal lanes because there may be internal junctions where 107 further internal lanes start. 108 109 The returned list contains string ids and no lane objects. 110 """ 111 return self._intLanes 112 113 def setFoes(self, index, foes, prohibits): 114 self._foes[index] = foes 115 self._prohibits[index] = prohibits 116 117 def areFoes(self, link1, link2): 118 return self._foes[link1][len(self._foes[link1]) - link2 - 1] == '1' 119 120 def hasFoes(self): 121 """whether there are any conflicting connections as this node""" 122 return any(['1' in foes for foes in self._foes.values()]) 123 124 def getLinkIndex(self, conn): 125 ret = 0 126 for lane_id in self._incLanes: 127 lastUnderscore = lane_id.rfind("_") 128 if lastUnderscore > 0: 129 edge_id = lane_id[:lastUnderscore] 130 index = lane_id[lastUnderscore+1:] 131 edge = [e for e in self._incoming if e.getID() == edge_id][0] 132 for candidate_conn in edge.getLane(int(index)).getOutgoing(): 133 fromFunction = candidate_conn.getFromLane().getEdge().getFunction() 134 toFunction = candidate_conn.getToLane().getEdge().getFunction() 135 if toFunction == "walkingarea" or (fromFunction == "walkingarea" and not toFunction == "crossing"): 136 continue 137 if candidate_conn == conn: 138 return ret 139 ret += 1 140 return -1 141 142 def forbids(self, possProhibitor, possProhibited): 143 possProhibitorIndex = self.getLinkIndex(possProhibitor) 144 possProhibitedIndex = self.getLinkIndex(possProhibited) 145 if possProhibitorIndex < 0 or possProhibitedIndex < 0: 146 return False 147 ps = self._prohibits[possProhibitedIndex] 148 return ps[-(possProhibitorIndex + 1)] == '1' 149 150 def getCoord(self): 151 return tuple(self._coord[:2]) 152 153 def getCoord3D(self): 154 return self._coord 155 156 def getType(self): 157 return self._type 158 159 def getFringe(self): 160 return self._fringe 161 162 def getConnections(self, source=None, target=None): 163 if source: 164 incoming = [source] 165 else: 166 incoming = list(self._incoming) 167 conns = [] 168 for e in incoming: 169 if hasattr(e, "getLanes"): 170 lanes = e.getLanes() 171 else: 172 # assuming source is a lane 173 lanes = [e] 174 for _lane in lanes: 175 all_outgoing = _lane.getOutgoing() 176 outgoing = [] 177 if target: 178 if hasattr(target, "getLanes"): 179 for o in all_outgoing: 180 if o.getTo() == target: 181 outgoing.append(o) 182 else: 183 # assuming target is a lane 184 for o in all_outgoing: 185 if o.getToLane() == target: 186 outgoing.append(o) 187 else: 188 outgoing = all_outgoing 189 conns.extend(outgoing) 190 return conns 191 192 def select(self, value=True): 193 self._selected = value 194 195 def isSelected(self): 196 return self._selected 197 198 def setParam(self, key, value): 199 self._params[key] = value 200 201 def getParam(self, key, default=None): 202 return self._params.get(key, default) 203 204 def getParams(self): 205 return self._params 206 207 def getNeighboringNodes(self, outgoingNodes=True, incomingNodes=True): 208 neighboring = [] 209 if incomingNodes: 210 edges = self._incoming 211 for e in edges: 212 if not (e.getFromNode() in neighboring) and not (e.getFromNode().getID() == self.getID()): 213 neighboring.append(e.getFromNode()) 214 if outgoingNodes: 215 edges = self._outgoing 216 for e in edges: 217 if not (e.getToNode() in neighboring) and not (e.getToNode().getID() == self.getID()): 218 neighboring.append(e.getToNode()) 219 return neighboring 220 221 def __repr__(self): 222 return '<junction id="%s"/>' % self._id 223 224 def getMaxTLLinkIndex(self): 225 idx = [] 226 if self.getType() == 'traffic_light': 227 for conn in self.getConnections(): 228 idx.append(conn.getTLLinkIndex()) 229 return (max(idx)) 230 else: 231 return None
23class Node: 24 25 """ Nodes from a sumo network """ 26 27 def __init__(self, id, type, coord, incLanes, intLanes=None): 28 self._id = id 29 self._type = type 30 self._coord = coord 31 self._incoming = [] 32 self._outgoing = [] 33 self._foes = {} 34 self._prohibits = {} 35 self._incLanes = incLanes 36 self._intLanes = intLanes 37 self._shape3D = None 38 self._shape = None 39 self._fringe = None 40 self._params = {} 41 self._selected = False 42 43 def getID(self): 44 return self._id 45 46 def getTLSID(self): 47 for e in self.getIncoming(): 48 for to, cons in e.getOutgoing().items(): 49 for c in cons: 50 if c.getTLSID(): 51 return c.getTLSID() 52 return None 53 54 def setShape(self, shape): 55 """Set the shape of the node. 56 57 Shape must be a list containing x,y,z coords as numbers 58 to represent the shape of the node. 59 """ 60 for pp in shape: 61 if len(pp) != 3: 62 raise ValueError('shape point must consist of x,y,z') 63 self._shape3D = shape 64 self._shape = [(x, y) for x, y, z in shape] 65 66 def getShape(self): 67 """Returns the shape of the node in 2d. 68 69 This function returns the shape of the node, as defined in the net.xml 70 file. The returned shape is a list containing numerical 71 2-tuples representing the x,y coordinates of the shape points. 72 73 If no shape is defined in the xml, an empty list will be returned. 74 """ 75 76 return self._shape 77 78 def getShape3D(self): 79 """Returns the shape of the node in 3d. 80 81 This function returns the shape of the node, as defined in the net.xml 82 file. The returned shape is a list containing numerical 83 3-tuples representing the x,y,z coordinates of the shape points. 84 85 If no shape is defined in the xml, an empty list will be returned. 86 """ 87 88 return self._shape3D 89 90 def addOutgoing(self, edge): 91 self._outgoing.append(edge) 92 93 def getOutgoing(self): 94 return self._outgoing 95 96 def addIncoming(self, edge): 97 self._incoming.append(edge) 98 99 def getIncoming(self): 100 return self._incoming 101 102 def getInternal(self): 103 """Returns the internal lanes starting at the border of the node. 104 105 This function returns the junction internal lanes as defined in the 106 "intLanes" attribute in net.xml. Note that this may not contain 107 all internal lanes because there may be internal junctions where 108 further internal lanes start. 109 110 The returned list contains string ids and no lane objects. 111 """ 112 return self._intLanes 113 114 def setFoes(self, index, foes, prohibits): 115 self._foes[index] = foes 116 self._prohibits[index] = prohibits 117 118 def areFoes(self, link1, link2): 119 return self._foes[link1][len(self._foes[link1]) - link2 - 1] == '1' 120 121 def hasFoes(self): 122 """whether there are any conflicting connections as this node""" 123 return any(['1' in foes for foes in self._foes.values()]) 124 125 def getLinkIndex(self, conn): 126 ret = 0 127 for lane_id in self._incLanes: 128 lastUnderscore = lane_id.rfind("_") 129 if lastUnderscore > 0: 130 edge_id = lane_id[:lastUnderscore] 131 index = lane_id[lastUnderscore+1:] 132 edge = [e for e in self._incoming if e.getID() == edge_id][0] 133 for candidate_conn in edge.getLane(int(index)).getOutgoing(): 134 fromFunction = candidate_conn.getFromLane().getEdge().getFunction() 135 toFunction = candidate_conn.getToLane().getEdge().getFunction() 136 if toFunction == "walkingarea" or (fromFunction == "walkingarea" and not toFunction == "crossing"): 137 continue 138 if candidate_conn == conn: 139 return ret 140 ret += 1 141 return -1 142 143 def forbids(self, possProhibitor, possProhibited): 144 possProhibitorIndex = self.getLinkIndex(possProhibitor) 145 possProhibitedIndex = self.getLinkIndex(possProhibited) 146 if possProhibitorIndex < 0 or possProhibitedIndex < 0: 147 return False 148 ps = self._prohibits[possProhibitedIndex] 149 return ps[-(possProhibitorIndex + 1)] == '1' 150 151 def getCoord(self): 152 return tuple(self._coord[:2]) 153 154 def getCoord3D(self): 155 return self._coord 156 157 def getType(self): 158 return self._type 159 160 def getFringe(self): 161 return self._fringe 162 163 def getConnections(self, source=None, target=None): 164 if source: 165 incoming = [source] 166 else: 167 incoming = list(self._incoming) 168 conns = [] 169 for e in incoming: 170 if hasattr(e, "getLanes"): 171 lanes = e.getLanes() 172 else: 173 # assuming source is a lane 174 lanes = [e] 175 for _lane in lanes: 176 all_outgoing = _lane.getOutgoing() 177 outgoing = [] 178 if target: 179 if hasattr(target, "getLanes"): 180 for o in all_outgoing: 181 if o.getTo() == target: 182 outgoing.append(o) 183 else: 184 # assuming target is a lane 185 for o in all_outgoing: 186 if o.getToLane() == target: 187 outgoing.append(o) 188 else: 189 outgoing = all_outgoing 190 conns.extend(outgoing) 191 return conns 192 193 def select(self, value=True): 194 self._selected = value 195 196 def isSelected(self): 197 return self._selected 198 199 def setParam(self, key, value): 200 self._params[key] = value 201 202 def getParam(self, key, default=None): 203 return self._params.get(key, default) 204 205 def getParams(self): 206 return self._params 207 208 def getNeighboringNodes(self, outgoingNodes=True, incomingNodes=True): 209 neighboring = [] 210 if incomingNodes: 211 edges = self._incoming 212 for e in edges: 213 if not (e.getFromNode() in neighboring) and not (e.getFromNode().getID() == self.getID()): 214 neighboring.append(e.getFromNode()) 215 if outgoingNodes: 216 edges = self._outgoing 217 for e in edges: 218 if not (e.getToNode() in neighboring) and not (e.getToNode().getID() == self.getID()): 219 neighboring.append(e.getToNode()) 220 return neighboring 221 222 def __repr__(self): 223 return '<junction id="%s"/>' % self._id 224 225 def getMaxTLLinkIndex(self): 226 idx = [] 227 if self.getType() == 'traffic_light': 228 for conn in self.getConnections(): 229 idx.append(conn.getTLLinkIndex()) 230 return (max(idx)) 231 else: 232 return None
Nodes from a sumo network
27 def __init__(self, id, type, coord, incLanes, intLanes=None): 28 self._id = id 29 self._type = type 30 self._coord = coord 31 self._incoming = [] 32 self._outgoing = [] 33 self._foes = {} 34 self._prohibits = {} 35 self._incLanes = incLanes 36 self._intLanes = intLanes 37 self._shape3D = None 38 self._shape = None 39 self._fringe = None 40 self._params = {} 41 self._selected = False
54 def setShape(self, shape): 55 """Set the shape of the node. 56 57 Shape must be a list containing x,y,z coords as numbers 58 to represent the shape of the node. 59 """ 60 for pp in shape: 61 if len(pp) != 3: 62 raise ValueError('shape point must consist of x,y,z') 63 self._shape3D = shape 64 self._shape = [(x, y) for x, y, z in 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.
66 def getShape(self): 67 """Returns the shape of the node in 2d. 68 69 This function returns the shape of the node, as defined in the net.xml 70 file. The returned shape is a list containing numerical 71 2-tuples representing the x,y coordinates of the shape points. 72 73 If no shape is defined in the xml, an empty list will be returned. 74 """ 75 76 return self._shape
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.
78 def getShape3D(self): 79 """Returns the shape of the node in 3d. 80 81 This function returns the shape of the node, as defined in the net.xml 82 file. The returned shape is a list containing numerical 83 3-tuples representing the x,y,z coordinates of the shape points. 84 85 If no shape is defined in the xml, an empty list will be returned. 86 """ 87 88 return self._shape3D
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.
102 def getInternal(self): 103 """Returns the internal lanes starting at the border of the node. 104 105 This function returns the junction internal lanes as defined in the 106 "intLanes" attribute in net.xml. Note that this may not contain 107 all internal lanes because there may be internal junctions where 108 further internal lanes start. 109 110 The returned list contains string ids and no lane objects. 111 """ 112 return self._intLanes
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.
121 def hasFoes(self): 122 """whether there are any conflicting connections as this node""" 123 return any(['1' in foes for foes in self._foes.values()])
whether there are any conflicting connections as this node
125 def getLinkIndex(self, conn): 126 ret = 0 127 for lane_id in self._incLanes: 128 lastUnderscore = lane_id.rfind("_") 129 if lastUnderscore > 0: 130 edge_id = lane_id[:lastUnderscore] 131 index = lane_id[lastUnderscore+1:] 132 edge = [e for e in self._incoming if e.getID() == edge_id][0] 133 for candidate_conn in edge.getLane(int(index)).getOutgoing(): 134 fromFunction = candidate_conn.getFromLane().getEdge().getFunction() 135 toFunction = candidate_conn.getToLane().getEdge().getFunction() 136 if toFunction == "walkingarea" or (fromFunction == "walkingarea" and not toFunction == "crossing"): 137 continue 138 if candidate_conn == conn: 139 return ret 140 ret += 1 141 return -1
143 def forbids(self, possProhibitor, possProhibited): 144 possProhibitorIndex = self.getLinkIndex(possProhibitor) 145 possProhibitedIndex = self.getLinkIndex(possProhibited) 146 if possProhibitorIndex < 0 or possProhibitedIndex < 0: 147 return False 148 ps = self._prohibits[possProhibitedIndex] 149 return ps[-(possProhibitorIndex + 1)] == '1'
163 def getConnections(self, source=None, target=None): 164 if source: 165 incoming = [source] 166 else: 167 incoming = list(self._incoming) 168 conns = [] 169 for e in incoming: 170 if hasattr(e, "getLanes"): 171 lanes = e.getLanes() 172 else: 173 # assuming source is a lane 174 lanes = [e] 175 for _lane in lanes: 176 all_outgoing = _lane.getOutgoing() 177 outgoing = [] 178 if target: 179 if hasattr(target, "getLanes"): 180 for o in all_outgoing: 181 if o.getTo() == target: 182 outgoing.append(o) 183 else: 184 # assuming target is a lane 185 for o in all_outgoing: 186 if o.getToLane() == target: 187 outgoing.append(o) 188 else: 189 outgoing = all_outgoing 190 conns.extend(outgoing) 191 return conns
208 def getNeighboringNodes(self, outgoingNodes=True, incomingNodes=True): 209 neighboring = [] 210 if incomingNodes: 211 edges = self._incoming 212 for e in edges: 213 if not (e.getFromNode() in neighboring) and not (e.getFromNode().getID() == self.getID()): 214 neighboring.append(e.getFromNode()) 215 if outgoingNodes: 216 edges = self._outgoing 217 for e in edges: 218 if not (e.getToNode() in neighboring) and not (e.getToNode().getID() == self.getID()): 219 neighboring.append(e.getToNode()) 220 return neighboring