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
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 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

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 getTLSID(self):
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
def setShape(self, shape):
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.

def getShape(self):
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.

def getShape3D(self):
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.

def addOutgoing(self, edge):
90    def addOutgoing(self, edge):
91        self._outgoing.append(edge)
def getOutgoing(self):
93    def getOutgoing(self):
94        return self._outgoing
def addIncoming(self, edge):
96    def addIncoming(self, edge):
97        self._incoming.append(edge)
def getIncoming(self):
 99    def getIncoming(self):
100        return self._incoming
def getInternal(self):
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.

def setFoes(self, index, foes, prohibits):
114    def setFoes(self, index, foes, prohibits):
115        self._foes[index] = foes
116        self._prohibits[index] = prohibits
def areFoes(self, link1, link2):
118    def areFoes(self, link1, link2):
119        return self._foes[link1][len(self._foes[link1]) - link2 - 1] == '1'
def hasFoes(self):
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

def getLinkIndex(self, conn):
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
def forbids(self, possProhibitor, possProhibited):
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'
def getCoord(self):
151    def getCoord(self):
152        return tuple(self._coord[:2])
def getCoord3D(self):
154    def getCoord3D(self):
155        return self._coord
def getType(self):
157    def getType(self):
158        return self._type
def getFringe(self):
160    def getFringe(self):
161        return self._fringe
def getConnections(self, source=None, target=None):
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
def select(self, value=True):
193    def select(self, value=True):
194        self._selected = value
def isSelected(self):
196    def isSelected(self):
197        return self._selected
def setParam(self, key, value):
199    def setParam(self, key, value):
200        self._params[key] = value
def getParam(self, key, default=None):
202    def getParam(self, key, default=None):
203        return self._params.get(key, default)
def getParams(self):
205    def getParams(self):
206        return self._params
def getNeighboringNodes(self, outgoingNodes=True, incomingNodes=True):
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
def getMaxTLLinkIndex(self):
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