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

Nodes from a sumo network

Node(id, type, coord, incLanes, intLanes=None)
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
def getID(self):
43    def getID(self):
44        return self._id
def setShape(self, shape):
46    def setShape(self, shape):
47        """Set the shape of the node.
48
49        Shape must be a list containing x,y,z coords as numbers
50        to represent the shape of the node.
51        """
52        for pp in shape:
53            if len(pp) != 3:
54                raise ValueError('shape point must consist of x,y,z')
55        self._shape3D = shape
56        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.

def getShape(self):
58    def getShape(self):
59        """Returns the shape of the node in 2d.
60
61        This function returns the shape of the node, as defined in the net.xml
62        file. The returned shape is a list containing numerical
63        2-tuples representing the x,y coordinates of the shape points.
64
65        If no shape is defined in the xml, an empty list will be returned.
66        """
67
68        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.

def getShape3D(self):
70    def getShape3D(self):
71        """Returns the shape of the node in 3d.
72
73        This function returns the shape of the node, as defined in the net.xml
74        file. The returned shape is a list containing numerical
75        3-tuples representing the x,y,z coordinates of the shape points.
76
77        If no shape is defined in the xml, an empty list will be returned.
78        """
79
80        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.

def addOutgoing(self, edge):
82    def addOutgoing(self, edge):
83        self._outgoing.append(edge)
def getOutgoing(self):
85    def getOutgoing(self):
86        return self._outgoing
def addIncoming(self, edge):
88    def addIncoming(self, edge):
89        self._incoming.append(edge)
def getIncoming(self):
91    def getIncoming(self):
92        return self._incoming
def getInternal(self):
 94    def getInternal(self):
 95        """Returns the internal lanes starting at the border of the node.
 96
 97        This function returns the junction internal lanes as defined in the
 98        "intLanes" attribute in net.xml. Note that this may not contain
 99        all internal lanes because there may be internal junctions where
100        further internal lanes start.
101
102        The returned list contains string ids and no lane objects.
103        """
104        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.

def setFoes(self, index, foes, prohibits):
106    def setFoes(self, index, foes, prohibits):
107        self._foes[index] = foes
108        self._prohibits[index] = prohibits
def areFoes(self, link1, link2):
110    def areFoes(self, link1, link2):
111        return self._foes[link1][len(self._foes[link1]) - link2 - 1] == '1'
def hasFoes(self):
113    def hasFoes(self):
114        """whether there are any conflicting connections as this node"""
115        return any(['1' in foes for foes in self._foes.values()])

whether there are any conflicting connections as this node

def getLinkIndex(self, conn):
117    def getLinkIndex(self, conn):
118        ret = 0
119        for lane_id in self._incLanes:
120            lastUnderscore = lane_id.rfind("_")
121            if lastUnderscore > 0:
122                edge_id = lane_id[:lastUnderscore]
123                index = lane_id[lastUnderscore+1:]
124                edge = [e for e in self._incoming if e.getID() == edge_id][0]
125                for candidate_conn in edge.getLane(int(index)).getOutgoing():
126                    fromFunction = candidate_conn.getFromLane().getEdge().getFunction()
127                    toFunction = candidate_conn.getToLane().getEdge().getFunction()
128                    if toFunction == "walkingarea" or (fromFunction == "walkingarea" and not toFunction == "crossing"):
129                        continue
130                    if candidate_conn == conn:
131                        return ret
132                    ret += 1
133        return -1
def forbids(self, possProhibitor, possProhibited):
135    def forbids(self, possProhibitor, possProhibited):
136        possProhibitorIndex = self.getLinkIndex(possProhibitor)
137        possProhibitedIndex = self.getLinkIndex(possProhibited)
138        if possProhibitorIndex < 0 or possProhibitedIndex < 0:
139            return False
140        ps = self._prohibits[possProhibitedIndex]
141        return ps[-(possProhibitorIndex + 1)] == '1'
def getCoord(self):
143    def getCoord(self):
144        return tuple(self._coord[:2])
def getCoord3D(self):
146    def getCoord3D(self):
147        return self._coord
def getType(self):
149    def getType(self):
150        return self._type
def getFringe(self):
152    def getFringe(self):
153        return self._fringe
def getConnections(self, source=None, target=None):
155    def getConnections(self, source=None, target=None):
156        if source:
157            incoming = [source]
158        else:
159            incoming = list(self._incoming)
160        conns = []
161        for e in incoming:
162            if hasattr(e, "getLanes"):
163                lanes = e.getLanes()
164            else:
165                # assuming source is a lane
166                lanes = [e]
167            for _lane in lanes:
168                all_outgoing = _lane.getOutgoing()
169                outgoing = []
170                if target:
171                    if hasattr(target, "getLanes"):
172                        for o in all_outgoing:
173                            if o.getTo() == target:
174                                outgoing.append(o)
175                    else:
176                        # assuming target is a lane
177                        for o in all_outgoing:
178                            if o.getToLane() == target:
179                                outgoing.append(o)
180                else:
181                    outgoing = all_outgoing
182                conns.extend(outgoing)
183        return conns
def select(self, value=True):
185    def select(self, value=True):
186        self._selected = value
def isSelected(self):
188    def isSelected(self):
189        return self._selected
def setParam(self, key, value):
191    def setParam(self, key, value):
192        self._params[key] = value
def getParam(self, key, default=None):
194    def getParam(self, key, default=None):
195        return self._params.get(key, default)
def getParams(self):
197    def getParams(self):
198        return self._params
def getNeighboringNodes(self, outgoingNodes=True, incomingNodes=True):
200    def getNeighboringNodes(self, outgoingNodes=True, incomingNodes=True):
201        neighboring = []
202        if incomingNodes:
203            edges = self._incoming
204            for e in edges:
205                if not (e.getFromNode() in neighboring) and not (e.getFromNode().getID() == self.getID()):
206                    neighboring.append(e.getFromNode())
207        if outgoingNodes:
208            edges = self._outgoing
209            for e in edges:
210                if not (e.getToNode() in neighboring) and not (e.getToNode().getID() == self.getID()):
211                    neighboring.append(e.getToNode())
212        return neighboring
def getMaxTLLinkIndex(self):
217    def getMaxTLLinkIndex(self):
218        idx = []
219        if self.getType() == 'traffic_light':
220            for conn in self.getConnections():
221                idx.append(conn.getTLLinkIndex())
222            return (max(idx))
223        else:
224            return None