Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/generateParkingLots.py
169659 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2010-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file generateParkingLots.py
15
# @author Yun-Pang Floetteroed
16
# @date 2017-10-13
17
18
"""
19
generate parking lots
20
"""
21
22
from __future__ import absolute_import
23
from __future__ import print_function
24
25
import os
26
import sys
27
import optparse
28
import math
29
30
if 'SUMO_HOME' in os.environ:
31
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
32
sys.path.append(tools)
33
import sumolib # noqa
34
from sumolib.geomhelper import isWithin
35
else:
36
sys.exit("please declare environment variable 'SUMO_HOME'")
37
38
39
def get_options(args=None):
40
optParser = optparse.OptionParser()
41
optParser.add_option("-i", "--parking-id", dest="parkId",
42
default="parkingLot", help="define the name/id of the parking lot")
43
optParser.add_option("-x", "--x-axis", dest="xaxis", type="int",
44
help="define x-position of the parking lot")
45
optParser.add_option("-y", "--y-axis", dest="yaxis", type="int",
46
help="define y-position of the parking lot")
47
optParser.add_option("-b", "--bounding-box", dest="bbox",
48
help="define the xmin, ymin, xmax, ymax of the parking lot")
49
optParser.add_option("--shape", dest="shape",
50
help="define the boundary shape of the parking lot")
51
optParser.add_option("-n", "--parking-spaces", dest="spaces", type="int",
52
default=5, help="define the number of the parking spaces")
53
optParser.add_option("-c", "--connecting-edge", dest="connEdge",
54
help="define the connecting edge of the parking lot")
55
optParser.add_option("-s", "--start-position", dest="start", type="int",
56
default=0, help="define the begin position of the entrance/exit of the parking lot")
57
optParser.add_option("-e", "--end-position", dest="end", type="int",
58
default=2, help="define the end position of the entrance/exit of the parking lot")
59
optParser.add_option("-l", "--space-length", dest="length", type="int",
60
default=5, help="define the length of each parking space")
61
optParser.add_option("-a", "--space-angle", dest="angle", type="int",
62
default=315, help="define the angle of each parking space")
63
optParser.add_option("--x-space-distance", dest="xdist", type="float",
64
default=5, help="define the lateral distance (x-direction) between the locations of two " +
65
"parking spaces")
66
optParser.add_option("--y-space-distance", dest="ydist", type="float",
67
default=5, help="define the longitudinal (y-direction) distance between the locations of " +
68
"two parking spaces")
69
optParser.add_option("-r", "--rotation-degree", dest="rotation", type="int",
70
default=0, help="define the rotation degree of the parking lot")
71
optParser.add_option("--adjustrate-x", dest="factorX", type="float",
72
default=0.28, help="define the modification rate of x-axis if the rotation exists")
73
optParser.add_option("--adjustrate-y", dest="factorY", type="float",
74
default=0.7, help="define the modification rate of y-axis if the rotation exists")
75
optParser.add_option("--output-suffix", dest="suffix", help="output suffix", default="")
76
optParser.add_option("--fullname", dest="fullname", help="full name of parking area", default=None)
77
optParser.add_option("-v", "--verbose", dest="verbose", action="store_true",
78
default=False, help="tell me what you are doing")
79
(options, args) = optParser.parse_args(args=args)
80
81
if not options.bbox and not options.shape and (not options.xaxis or not options.yaxis) or not options.connEdge:
82
optParser.print_help()
83
sys.exit()
84
85
return options
86
87
88
def main(options):
89
movingX = options.xdist
90
movingY = options.ydist
91
factorX = 0.
92
factorY = 1.
93
row = 0
94
xmax = None
95
ymax = None
96
97
if options.shape:
98
if ' ' in options.shape:
99
options.shape = [tuple(map(float, xy.split(','))) for xy in options.shape.split(' ')]
100
else:
101
numbers = list(map(float, options.shape.split(',')))
102
options.shape = [(numbers[i], numbers[i+1]) for i in range(0, len(numbers), 2)]
103
xmin = min([x for x, y in options.shape])
104
xmax = max([x for x, y in options.shape])
105
ymin = min([y for x, y in options.shape])
106
ymax = max([y for x, y in options.shape])
107
if options.shape[0] != options.shape[-1]:
108
# close shape
109
options.shape.append(options.shape[0])
110
x = xmin
111
y = ymin
112
elif options.bbox:
113
xmin, ymin, xmax, ymax = map(float, options.bbox.split(','))
114
x = xmin
115
y = ymin
116
else:
117
x = options.xaxis
118
y = options.yaxis
119
120
if options.rotation != 0:
121
movingX = options.xdist * (math.cos(options.rotation * math.pi / 180.))
122
movingY = options.ydist * (math.sin(options.rotation * math.pi / 180.))
123
factorX = options.factorX
124
factorY = options.factorY
125
126
if options.suffix:
127
outfile = 'parking_%s.add.xml' % options.suffix
128
else:
129
outfile = 'parking_%s.add.xml' % options.parkId
130
131
with open(outfile, 'w') as outf:
132
outf.write('<?xml version="1.0" encoding="UTF-8"?>\n')
133
outf.write('<additional>\n')
134
name = ' name="%s"' % options.fullname if options.fullname is not None else ""
135
outf.write(' <parkingArea id="%s" lane="%s" startPos="%s" endPos="%s"%s>\n' %
136
(options.parkId, options.connEdge, options.start, options.end, name))
137
lots = 0
138
i = 0
139
while lots < options.spaces:
140
if not options.shape or isWithin((x, y), options.shape):
141
outf.write(
142
' <space x="%.2f" y="%.2f" length="%s" angle="%s"/>\n' %
143
(x, y, options.length, options.angle))
144
lots += 1
145
if xmax is not None:
146
if x > xmax:
147
row += 1
148
if y < ymax:
149
y = ymin + row * options.ydist * factorY
150
else:
151
print("Warning: The area has been filed and only %s of %s lots were written" % (
152
lots, options.spaces), file=sys.stderr)
153
break
154
x = xmin + row * movingX * factorX
155
else:
156
x += movingX
157
if options.rotation != 0:
158
y += movingY
159
else:
160
# No rotation degree is considered
161
x += options.xdist
162
y += options.ydist
163
i += 1
164
outf.write(' </parkingArea>\n')
165
outf.write('</additional>\n')
166
167
168
if __name__ == "__main__":
169
options = get_options(sys.argv)
170
main(options)
171
172