Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/shapes/poi_alongRoads.py
194341 views
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
4
# Copyright (C) 2009-2026 German Aerospace Center (DLR) and others.
5
# This program and the accompanying materials are made available under the
6
# terms of the Eclipse Public License 2.0 which is available at
7
# https://www.eclipse.org/legal/epl-2.0/
8
# This Source Code may also be made available under the following Secondary
9
# Licenses when the conditions for such availability set forth in the Eclipse
10
# Public License 2.0 are satisfied: GNU General Public License, version 2
11
# or later which is available at
12
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
14
15
# @file poi_alongRoads.py
16
# @author Ronald Nippold
17
# @author Daniel Krajzewicz
18
# @author Michael Behrisch
19
# @date 2009-20-10
20
21
"""
22
Usage: poi_alongRoads.py <NET> <EDGE_ID>[,<EDGE_ID>]* <DISTANCE>
23
24
Spatial distribute of POIs along given edges on a given network.
25
Edges are separated with comma and without spaces in between.
26
The distance between POIs may be any positive real number
27
28
So far POIs are situated in the middle on all edges without regard to the type of the edge (street, junction).
29
Edges may be given in arbitrary order, connected edges are found automatically
30
Therefore: crossing chains of connected edges are not allowed -> this needs two different runs of this script
31
Output is written in file 'pois.add.xml'
32
"""
33
from __future__ import absolute_import
34
from __future__ import print_function
35
36
import os
37
import sys
38
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
39
import sumolib.net # noqa
40
41
if len(sys.argv) < 4:
42
print("Usage: " +
43
sys.argv[0] + " <NET> <EDGE_ID>[,<EDGE_ID>]* <DISTANCE>", file=sys.stderr)
44
sys.exit()
45
edgeList = sys.argv[2].split(',')
46
POIdist = float(sys.argv[3])
47
48
49
def findPred(connEdgesTmp, edgeList, success=0):
50
for edge in edgeList:
51
# check first element of connEdgesTmp for predecessor
52
if connEdgesTmp[0][1] == edge[2]:
53
connEdgesTmp.insert(0, edge)
54
edgeList.remove(edge)
55
success = 1
56
return success
57
return success
58
59
60
def findSucc(connEdgesTmp, edgeList, success=0):
61
for edge in edgeList:
62
# check last element of connEdgesTmp for successor
63
if connEdgesTmp[len(connEdgesTmp) - 1][2] == edge[1]:
64
connEdgesTmp.append(edge)
65
edgeList.remove(edge)
66
success = 1
67
return success
68
return success
69
70
71
def poiAppend(poi_edge, poi_nr, poi_x, poi_y, poi_buf):
72
poi_buf.append(' <poi id="%s-%s" type="default" color="1,0,0" layer="0" x="%.2f" y="%.2f"/>' %
73
(poi_edge, poi_nr, poi_x, poi_y))
74
75
76
print("Reading net ...")
77
net = sumolib.net.readNet(sys.argv[1])
78
79
# find all predecessor/successor nodes for the given edges
80
nodeList = []
81
for edge in net._edges:
82
for elm in sys.argv[2].split(','):
83
if str(edge._id) == elm:
84
data = []
85
data.append(edge._id)
86
data.append(edge._from._id)
87
data.append(edge._to._id)
88
data.append(edge.getShape())
89
nodeList.append(data)
90
91
# find connected edges
92
connEdges = []
93
connEdgesTmp = []
94
pred = 1
95
succ = 1
96
# real copy, not just reference because of loop in nodeList
97
tmpList = nodeList[:]
98
for elm in nodeList:
99
if elm in tmpList: # Has this edge already been processed?
100
while pred == 1: # search for predecessor
101
if elm in tmpList:
102
# don't look up the current edge in search list
103
tmpList.remove(elm)
104
if elm not in connEdgesTmp:
105
# for the first element when searching for connected edges
106
connEdgesTmp.append(elm)
107
pred = findPred(connEdgesTmp, tmpList)
108
while succ == 1: # search for successor
109
# all other things already done in predecessor
110
succ = findSucc(connEdgesTmp, tmpList)
111
connEdges.append(connEdgesTmp)
112
connEdgesTmp = [] # clean up
113
pred = 1 # reset
114
succ = 1
115
116
# prepare output
117
POIbuf = []
118
POIbuf.append("<?xml version=\"1.0\"?>\n")
119
POIbuf.append("<!--\n\nPOIs for edges:\n\t" +
120
str(sys.argv[2]) + "\n\non network:\n\t" + str(sys.argv[1]) + "\n-->\n")
121
POIbuf.append("<POIs>")
122
# space out POIs on the found (connected) edges
123
for elm in connEdges:
124
# tmp array for storing all shape coordinate of connected edges
125
shapes = []
126
offset = 0 # Anything left from the edge before?
127
for edge in elm:
128
for p in edge[3]:
129
# shapes.append(p)
130
# collect all shapes of connected edges
131
shapes.append([p[0], p[1], edge[0]])
132
for i in range(0, len(shapes) - 1):
133
x1 = shapes[i][0] # point at the beginning of the current edge
134
y1 = shapes[i][1]
135
x2 = shapes[i + 1][0] # point at the end of the current edge
136
y2 = shapes[i + 1][1]
137
dX = x2 - x1
138
dY = y2 - y1
139
eucDist = pow(pow(dX, 2) + pow(dY, 2), 0.5) # Euclidean distance
140
# normalized Euclidean distance in x
141
normAscX = 0 if dX == 0 else dX / eucDist
142
# normalized Euclidean distance in y
143
normAscY = 0 if dY == 0 else dY / eucDist
144
xCur = x1 # the current POI position
145
yCur = y1
146
if i == 0:
147
POIid = 1
148
poiAppend(shapes[i][2], POIid, xCur, yCur, POIbuf)
149
POIid = POIid + 1
150
POIpos = POIdist
151
else:
152
if shapes[i][2] != shapes[i - 1][2]: # begin of new edge
153
POIid = 1
154
# reset POI-position at the beginning of an edge
155
POIpos = offset
156
# check if first (new) point is on current edge, consider possible
157
# offset from the edge before
158
if eucDist + offset > POIdist:
159
xCur = xCur + normAscX * (POIdist - offset)
160
yCur = yCur + normAscY * (POIdist - offset)
161
poiAppend(shapes[i][2], POIid, xCur, yCur, POIbuf)
162
POIid = POIid + 1
163
# always add POIdist, reset to current offset when changing the
164
# edge
165
POIpos = POIpos + POIdist
166
offset = 0 # reset offset
167
# other points - if possible - with normal spacing in between
168
while pow(pow((x2 - xCur), 2) + pow((y2 - yCur), 2), 0.5) > POIdist:
169
xCur = xCur + normAscX * POIdist
170
yCur = yCur + normAscY * POIdist
171
poiAppend(shapes[i][2], POIid, xCur, yCur, POIbuf)
172
POIid = POIid + 1
173
# always add POIdist, reset to current offset when changing the
174
# edge
175
POIpos = POIpos + POIdist
176
# calculate offset (residual) for the next connected edge
177
offset = offset + pow(pow((x2 - xCur), 2) + pow((y2 - yCur), 2), 0.5)
178
POIbuf.append("</POIs>")
179
180
print("writing output")
181
# finally write output in file
182
outfile = open('pois.add.xml', 'w')
183
for POIs in POIbuf:
184
outfile.write(POIs + "\n")
185
outfile.close()
186
print("done")
187
188