Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2011-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 NGFrame.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date 06.05.2011
19 : ///
20 : // Sets and checks options for netgen
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <string>
25 : #include "NGFrame.h"
26 : #include <netbuild/NBNetBuilder.h>
27 : #include <utils/options/Option.h>
28 : #include <utils/options/OptionsCont.h>
29 : #include <utils/common/MsgHandler.h>
30 : #include <utils/common/SystemFrame.h>
31 : #include <utils/common/ToString.h>
32 :
33 :
34 : // ===========================================================================
35 : // method definitions
36 : // ===========================================================================
37 : void
38 120 : NGFrame::fillOptions() {
39 120 : OptionsCont& oc = OptionsCont::getOptions();
40 120 : oc.doRegister("type-files", 't', new Option_FileName());
41 240 : oc.addDescription("type-files", "Input", TL("Read edge-type defs from FILE"));
42 :
43 120 : oc.doRegister("alphanumerical-ids", new Option_Bool(true));
44 240 : oc.addDescription("alphanumerical-ids", "Output", TL("The Ids of generated nodes use an alphanumerical code for easier readability when possible"));
45 :
46 : // register processing options
47 120 : oc.doRegister("turn-lanes", new Option_Integer(0));
48 240 : oc.addDescription("turn-lanes", "Processing", TL("Generate INT left-turn lanes"));
49 120 : oc.doRegister("turn-lanes.length", new Option_Float(20));
50 240 : oc.addDescription("turn-lanes.length", "Processing", TL("Set the length of generated turning lanes to FLOAT"));
51 :
52 240 : oc.doRegister("perturb-x", new Option_String("0"));
53 240 : oc.addDescription("perturb-x", "Processing", TL("Apply random spatial perturbation in x direction according to the given distribution"));
54 240 : oc.doRegister("perturb-y", new Option_String("0"));
55 240 : oc.addDescription("perturb-y", "Processing", TL("Apply random spatial perturbation in y direction according to the given distribution"));
56 240 : oc.doRegister("perturb-z", new Option_String("0"));
57 240 : oc.addDescription("perturb-z", "Processing", TL("Apply random spatial perturbation in z direction according to the given distribution"));
58 :
59 120 : oc.doRegister("bidi-probability", new Option_Float(1));
60 240 : oc.addSynonyme("bidi-probability", "rand-bidi-probability", true);
61 240 : oc.addSynonyme("bidi-probability", "rand.bidi-probability");
62 240 : oc.addSynonyme("bidi-probability", "bidi");
63 240 : oc.addDescription("bidi-probability", "Processing", TL("Defines the probability to build a reverse edge"));
64 :
65 120 : oc.doRegister("random-lanenumber", new Option_Bool(false));
66 240 : oc.addSynonyme("random-lanenumber", "rand.random-lanenumber", false);
67 240 : oc.addDescription("random-lanenumber", "Processing", TL("Draw lane numbers randomly from [1,default.lanenumber]"));
68 :
69 120 : oc.doRegister("random-priority", new Option_Bool(false));
70 240 : oc.addSynonyme("random-priority", "rand.random-priority", false);
71 240 : oc.addDescription("random-priority", "Processing", TL("Draw edge priority randomly from [1,default.priority]"));
72 :
73 120 : oc.doRegister("random-type", new Option_Bool(false));
74 240 : oc.addDescription("random-type", "Processing", TL("Draw edge type randomly from all loaded types"));
75 :
76 :
77 : // register grid-net options
78 120 : oc.doRegister("grid", 'g', new Option_Bool(false));
79 240 : oc.addSynonyme("grid", "grid-net", true);
80 240 : oc.addDescription("grid", "Grid Network", TL("Forces NETGEN to build a grid-like network"));
81 :
82 120 : oc.doRegister("grid.number", new Option_Integer(5));
83 240 : oc.addSynonyme("grid.number", "grid-number", true);
84 240 : oc.addSynonyme("grid.number", "number");
85 240 : oc.addDescription("grid.number", "Grid Network", TL("The number of junctions in both dirs"));
86 :
87 120 : oc.doRegister("grid.length", new Option_Float(100));
88 240 : oc.addSynonyme("grid.length", "grid-length", true);
89 240 : oc.addSynonyme("grid.length", "length");
90 240 : oc.addDescription("grid.length", "Grid Network", TL("The length of streets in both dirs"));
91 :
92 120 : oc.doRegister("grid.x-number", new Option_Integer(5));
93 240 : oc.addSynonyme("grid.x-number", "grid-x-number", true);
94 240 : oc.addSynonyme("grid.x-number", "x-no");
95 240 : oc.addDescription("grid.x-number", "Grid Network", TL("The number of junctions in x-dir; Overrides --grid-number"));
96 :
97 120 : oc.doRegister("grid.y-number", new Option_Integer(5));
98 240 : oc.addSynonyme("grid.y-number", "grid-y-number", true);
99 240 : oc.addSynonyme("grid.y-number", "y-no");
100 240 : oc.addDescription("grid.y-number", "Grid Network", TL("The number of junctions in y-dir; Overrides --grid-number"));
101 :
102 120 : oc.doRegister("grid.x-length", new Option_Float(100));
103 240 : oc.addSynonyme("grid.x-length", "grid-x-length", true);
104 240 : oc.addSynonyme("grid.x-length", "x-length");
105 240 : oc.addDescription("grid.x-length", "Grid Network", TL("The length of horizontal streets; Overrides --grid-length"));
106 :
107 120 : oc.doRegister("grid.y-length", new Option_Float(100));
108 240 : oc.addSynonyme("grid.y-length", "grid-y-length", true);
109 240 : oc.addSynonyme("grid.y-length", "y-length");
110 240 : oc.addDescription("grid.y-length", "Grid Network", TL("The length of vertical streets; Overrides --grid-length"));
111 :
112 120 : oc.doRegister("grid.attach-length", new Option_Float(0));
113 240 : oc.addSynonyme("grid.attach-length", "attach-length", true);
114 240 : oc.addDescription("grid.attach-length", "Grid Network", TL("The length of streets attached at the boundary; 0 means no streets are attached"));
115 :
116 120 : oc.doRegister("grid.x-attach-length", new Option_Float(0));
117 240 : oc.addDescription("grid.x-attach-length", "Grid Network", TL("The length of streets attached at the boundary in x direction; 0 means no streets are attached"));
118 120 : oc.doRegister("grid.y-attach-length", new Option_Float(0));
119 240 : oc.addDescription("grid.y-attach-length", "Grid Network", TL("The length of streets attached at the boundary in y direction; 0 means no streets are attached"));
120 :
121 : // register spider-net options
122 120 : oc.doRegister("spider", 's', new Option_Bool(false));
123 240 : oc.addSynonyme("spider", "spider-net", true);
124 240 : oc.addDescription("spider", "Spider Network", TL("Forces NETGEN to build a spider-net-like network"));
125 :
126 120 : oc.doRegister("spider.arm-number", new Option_Integer(7));
127 240 : oc.addSynonyme("spider.arm-number", "spider-arm-number", true);
128 240 : oc.addSynonyme("spider.arm-number", "arms");
129 240 : oc.addDescription("spider.arm-number", "Spider Network", TL("The number of axes within the net"));
130 :
131 120 : oc.doRegister("spider.circle-number", new Option_Integer(5));
132 240 : oc.addSynonyme("spider.circle-number", "spider-circle-number", true);
133 240 : oc.addSynonyme("spider.circle-number", "circles");
134 240 : oc.addDescription("spider.circle-number", "Spider Network", TL("The number of circles of the net"));
135 :
136 120 : oc.doRegister("spider.space-radius", new Option_Float(100));
137 240 : oc.addSynonyme("spider.space-radius", "spider-space-rad", true);
138 240 : oc.addSynonyme("spider.space-radius", "radius");
139 240 : oc.addDescription("spider.space-radius", "Spider Network", TL("The distances between the circles"));
140 :
141 120 : oc.doRegister("spider.omit-center", new Option_Bool(false));
142 240 : oc.addSynonyme("spider.omit-center", "spider-omit-center", true);
143 240 : oc.addSynonyme("spider.omit-center", "nocenter");
144 240 : oc.addDescription("spider.omit-center", "Spider Network", TL("Omit the central node of the network"));
145 :
146 120 : oc.doRegister("spider.attach-length", new Option_Float(0));
147 240 : oc.addDescription("spider.attach-length", "Spider Network", TL("The length of streets attached at the boundary; 0 means no streets are attached"));
148 :
149 : // register random-net options
150 120 : oc.doRegister("rand", 'r', new Option_Bool(false));
151 240 : oc.addSynonyme("rand", "random-net", true);
152 240 : oc.addDescription("rand", "Random Network", TL("Forces NETGEN to build a random network"));
153 :
154 120 : oc.doRegister("rand.iterations", new Option_Integer(100));
155 240 : oc.addSynonyme("rand.iterations", "rand-iterations", true);
156 240 : oc.addSynonyme("rand.iterations", "iterations");
157 240 : oc.addDescription("rand.iterations", "Random Network", TL("Describes how many times an edge shall be added to the net"));
158 :
159 120 : oc.doRegister("rand.max-distance", new Option_Float(250));
160 240 : oc.addSynonyme("rand.max-distance", "rand-max-distance", true);
161 240 : oc.addSynonyme("rand.max-distance", "max-dist");
162 240 : oc.addDescription("rand.max-distance", "Random Network", TL("The maximum distance for each edge"));
163 :
164 120 : oc.doRegister("rand.min-distance", new Option_Float(100));
165 240 : oc.addSynonyme("rand.min-distance", "rand-min-distance", true);
166 240 : oc.addSynonyme("rand.min-distance", "min-dist");
167 240 : oc.addDescription("rand.min-distance", "Random Network", TL("The minimum distance for each edge"));
168 :
169 120 : oc.doRegister("rand.min-angle", new Option_Float(45.0));
170 240 : oc.addSynonyme("rand.min-angle", "rand-min-anglee", true);
171 240 : oc.addSynonyme("rand.min-angle", "min-angle");
172 240 : oc.addDescription("rand.min-angle", "Random Network", TL("The minimum angle for each pair of (bidirectional) roads in DEGREES"));
173 :
174 120 : oc.doRegister("rand.num-tries", new Option_Integer(50));
175 240 : oc.addSynonyme("rand.num-tries", "rand-num-tries", true);
176 240 : oc.addSynonyme("rand.num-tries", "num-tries");
177 240 : oc.addDescription("rand.num-tries", "Random Network", TL("The number of tries for creating each node"));
178 :
179 120 : oc.doRegister("rand.connectivity", new Option_Float((double) 0.95));
180 240 : oc.addSynonyme("rand.connectivity", "rand-connectivity", true);
181 240 : oc.addSynonyme("rand.connectivity", "connectivity");
182 240 : oc.addDescription("rand.connectivity", "Random Network", TL("Probability for roads to continue at each node"));
183 :
184 120 : oc.doRegister("rand.neighbor-dist1", new Option_Float(0));
185 240 : oc.addSynonyme("rand.neighbor-dist1", "rand-neighbor-dist1", true);
186 240 : oc.addSynonyme("rand.neighbor-dist1", "dist1");
187 240 : oc.addDescription("rand.neighbor-dist1", "Random Network", TL("Probability for a node having at most 1 neighbor"));
188 :
189 120 : oc.doRegister("rand.neighbor-dist2", new Option_Float(0));
190 240 : oc.addSynonyme("rand.neighbor-dist2", "rand-neighbor-dist2", true);
191 240 : oc.addSynonyme("rand.neighbor-dist2", "dist2");
192 240 : oc.addDescription("rand.neighbor-dist2", "Random Network", TL("Probability for a node having at most 2 neighbors"));
193 :
194 120 : oc.doRegister("rand.neighbor-dist3", new Option_Float(10));
195 240 : oc.addSynonyme("rand.neighbor-dist3", "rand-neighbor-dist3", true);
196 240 : oc.addSynonyme("rand.neighbor-dist3", "dist3");
197 240 : oc.addDescription("rand.neighbor-dist3", "Random Network", TL("Probability for a node having at most 3 neighbors"));
198 :
199 120 : oc.doRegister("rand.neighbor-dist4", new Option_Float(10));
200 240 : oc.addSynonyme("rand.neighbor-dist4", "rand-neighbor-dist4", true);
201 240 : oc.addSynonyme("rand.neighbor-dist4", "dist4");
202 240 : oc.addDescription("rand.neighbor-dist4", "Random Network", TL("Probability for a node having at most 4 neighbors"));
203 :
204 120 : oc.doRegister("rand.neighbor-dist5", new Option_Float(2));
205 240 : oc.addSynonyme("rand.neighbor-dist5", "rand-neighbor-dist5", true);
206 240 : oc.addSynonyme("rand.neighbor-dist5", "dist5");
207 240 : oc.addDescription("rand.neighbor-dist5", "Random Network", TL("Probability for a node having at most 5 neighbors"));
208 :
209 120 : oc.doRegister("rand.neighbor-dist6", new Option_Float(1));
210 240 : oc.addSynonyme("rand.neighbor-dist6", "rand-neighbor-dist6", true);
211 240 : oc.addSynonyme("rand.neighbor-dist6", "dist6");
212 240 : oc.addDescription("rand.neighbor-dist6", "Random Network", TL("Probability for a node having at most 6 neighbors"));
213 :
214 120 : oc.doRegister("rand.grid", new Option_Bool(false));
215 240 : oc.addDescription("rand.grid", "Random Network", TL("Place nodes on a regular grid with spacing rand.min-distance"));
216 120 : }
217 :
218 :
219 : bool
220 112 : NGFrame::checkOptions() {
221 112 : OptionsCont& oc = OptionsCont::getOptions();
222 : bool ok = true;
223 : // check whether exactly one type of a network to build was wished
224 : int no = 0;
225 224 : if (oc.getBool("spider")) {
226 : no++;
227 : }
228 224 : if (oc.getBool("grid")) {
229 59 : no++;
230 : }
231 224 : if (oc.getBool("rand")) {
232 30 : no++;
233 : }
234 112 : if (no == 0) {
235 0 : WRITE_ERROR(TL("You have to specify the type of network to generate."));
236 : ok = false;
237 : }
238 112 : if (no > 1) {
239 8 : WRITE_ERROR(TL("You may specify only one type of network to generate at once."));
240 : ok = false;
241 : }
242 : // check whether the junction type to use is properly set
243 224 : if (oc.isSet("default-junction-type")) {
244 17 : std::string type = oc.getString("default-junction-type");
245 47 : if (type != toString(SumoXMLNodeType::TRAFFIC_LIGHT) &&
246 43 : type != toString(SumoXMLNodeType::TRAFFIC_LIGHT_NOJUNCTION) &&
247 43 : type != toString(SumoXMLNodeType::TRAFFIC_LIGHT_RIGHT_ON_RED) &&
248 40 : type != toString(SumoXMLNodeType::PRIORITY) &&
249 37 : type != toString(SumoXMLNodeType::PRIORITY_STOP) &&
250 37 : type != toString(SumoXMLNodeType::ALLWAY_STOP) &&
251 37 : type != toString(SumoXMLNodeType::ZIPPER) &&
252 37 : type != toString(SumoXMLNodeType::NOJUNCTION) &&
253 37 : type != toString(SumoXMLNodeType::RAIL_SIGNAL) &&
254 37 : type != toString(SumoXMLNodeType::RAIL_CROSSING) &&
255 54 : type != toString(SumoXMLNodeType::LEFT_BEFORE_RIGHT) &&
256 37 : type != toString(SumoXMLNodeType::RIGHT_BEFORE_LEFT)) {
257 91 : WRITE_ERROR("Only the following junction types are known: " +
258 : toString(SumoXMLNodeType::TRAFFIC_LIGHT) + ", " +
259 : toString(SumoXMLNodeType::TRAFFIC_LIGHT_NOJUNCTION) + ", " +
260 : toString(SumoXMLNodeType::TRAFFIC_LIGHT_RIGHT_ON_RED) + ", " +
261 : toString(SumoXMLNodeType::PRIORITY) + ", " +
262 : toString(SumoXMLNodeType::PRIORITY_STOP) + ", " +
263 : toString(SumoXMLNodeType::ALLWAY_STOP) + ", " +
264 : toString(SumoXMLNodeType::ZIPPER) + ", " +
265 : toString(SumoXMLNodeType::NOJUNCTION) + ", " +
266 : toString(SumoXMLNodeType::RAIL_SIGNAL) + ", " +
267 : toString(SumoXMLNodeType::RAIL_CROSSING) + ", " +
268 : toString(SumoXMLNodeType::LEFT_BEFORE_RIGHT) + ", " +
269 : toString(SumoXMLNodeType::RIGHT_BEFORE_LEFT));
270 : ok = false;
271 : }
272 : }
273 114 : if (oc.getBool("random-type") && !oc.isSet("type-files")) {
274 0 : WRITE_WARNING(TL("Option 'random-type' takes no effect unless 'type-files' are loaded"));
275 : }
276 224 : if (oc.getFloat("rand.connectivity") > 0.999) {
277 2 : WRITE_ERROR(TL("Option 'rand.connectivity' requires a value below 0.999"));
278 : ok = false;
279 : }
280 112 : return ok;
281 : }
282 :
283 :
284 : /****************************************************************************/
|