Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 NIImporter_VISUM.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Michael Behrisch
17 : /// @date Fri, 19 Jul 2002
18 : ///
19 : // A VISUM network importer
20 : /****************************************************************************/
21 : #pragma once
22 : #include <config.h>
23 :
24 : #include <string>
25 : #include <map>
26 : #include <vector>
27 : #include <netbuild/NBCapacity2Lanes.h>
28 : #include <utils/importio/LineHandler.h>
29 : #include <utils/importio/LineReader.h>
30 : #include <utils/importio/NamedColumnsParser.h>
31 : #include "NIVisumTL.h"
32 :
33 :
34 : // ===========================================================================
35 : // class declaration
36 : // ===========================================================================
37 : class OptionsCont;
38 : class NBNetBuilder;
39 : class NBNodeCont;
40 : class NBEdgeCont;
41 : class NBNode;
42 : class NBEdge;
43 :
44 :
45 : // ===========================================================================
46 : // class declaration
47 : // ===========================================================================
48 : /**
49 : * @class NIImporter_VISUM
50 : * @brief A VISUM network importer
51 : *
52 : * This class build an internal list of those VISUM-db entries which are
53 : * supported, first. This list is sorted in a way that the parsed dbs can
54 : * build upon each other as their related structures within the XML-input.
55 : * So, nodes are loaded first, then edges, etc.
56 : *
57 : * Because these structures may have a different order within the VISUM-file
58 : * than we need, at first the file is scanned and any occurrence of one of the
59 : * searched dbs is saved. That's where the "Found $XXX at YYY" are printed.
60 : * "YYY" is the character position within the file.
61 : *
62 : * In a second step, the dbs are parsed in the order we need. It is asked for
63 : * each subsequently whether it was found and if so, the proper parse_XXX()
64 : * method is called.
65 : */
66 : class NIImporter_VISUM {
67 : public:
68 : /** @brief Loads network definition from the assigned option and stores it in the given network builder
69 : *
70 : * If the option "visum" is set, the file stored therein is read and
71 : * the network definition stored therein is stored within the given network
72 : * builder.
73 : *
74 : * If the option "visum" is not set, this method simply returns.
75 : *
76 : * @param[in] oc The options to use
77 : * @param[in] nb The network builder to fill
78 : */
79 : static void loadNetwork(const OptionsCont& oc, NBNetBuilder& nb);
80 :
81 :
82 : protected:
83 : /** @brief constructor
84 : *
85 : * Builds the list of typed db parsers ("TypeParser") and stores them in
86 : * mySingleDataParsers in the order the according db values must be parsed.
87 : *
88 : * @param[in,out] nb the network builder (storage) to fill with parsed values
89 : * @param[in] file The name of the file to parse
90 : * @param[in] capacity2Lanes The converter from flow to lanes
91 : * @param[in] useVisumPrio Information whether the VISUM type's priority shall be used
92 : */
93 : NIImporter_VISUM(NBNetBuilder& nb, const std::string& file,
94 : NBCapacity2Lanes capacity2Lanes, bool useVisumPrio,
95 : const std::string& languageFile);
96 :
97 :
98 : /// @brief destructor
99 : ~NIImporter_VISUM();
100 :
101 :
102 : /** @brief Parses the VISUM-network file storing the parsed structures within myNetBuilder
103 : *
104 : * At first, it is checked whether the file can be opened. A ProcessError is thrown
105 : * if not. Otherwise, the file is scanned for occurrences of db table begins. For each found
106 : * db, its position within the file, and the column names are stored in the according
107 : * TypeParser. After this, the sorted list of type parsers is one through and each
108 : * found is used to parse the entries at the found positions using the found column names.
109 : *
110 : * @exception ProcessError If the file could not be opened
111 : */
112 : void load();
113 :
114 : private:
115 : /** @brief Returns the value from the named column as a float
116 : *
117 : * @param[in] fieldName Name of the column to extract the float from
118 : * @return The parsed real
119 : * @exception OutOfBoundsException If the current data line has less entries than the float's position
120 : * @exception NumberFormatException If the float is not numeric
121 : * @exception UnknownElement If the named data field is not in the line
122 : */
123 : double getNamedFloat(const std::string& fieldName);
124 :
125 : /** @brief The same, but two different names for the field are allowed
126 : *
127 : * @param[in] fieldName1 Name of the first column to extract the float from
128 : * @param[in] fieldName2 Name of the second column to extract the efloat from
129 : * @return The parsed real
130 : * @exception OutOfBoundsException If the current data line has less entries than the float's position
131 : * @exception NumberFormatException If the float is not numeric
132 : * @exception UnknownElement If the named data field is not in the line
133 : */
134 : double getNamedFloat(const std::string& fieldName1, const std::string& fieldName2);
135 :
136 :
137 : /** @brief Returns the value from the named column as a float or the default value if an error occurs
138 : *
139 : * @param[in] fieldName Name of the column to extract the float from
140 : * @param[in] defaultValue The default to return in the case of an error
141 : * @return The parsed real or the default value if an error while parsing occurred
142 : */
143 : double getNamedFloat(const std::string& fieldName, double defaultValue);
144 :
145 : /** @brief The same, but two different names for the field are allowed
146 : *
147 : * @param[in] fieldName1 Name of the first column to extract the float from
148 : * @param[in] fieldName2 Name of the second column to extract the efloat from
149 : * @param[in] defaultValue The default to return in the case of an error
150 : * @return The parsed real or the default value if an error while parsing occurred
151 : */
152 : double getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
153 : double defaultValue);
154 :
155 :
156 : /** @brief Returns the value from the named column as a normalised string
157 : *
158 : * "Normalised" means herein that the leading '0' (zeros) are prunned.
159 : *
160 : * @param[in] fieldName Name of the column to extract the string from
161 : * @return The parsed, normalised string
162 : * @exception OutOfBoundsException If the current data line has less entries than the string's position
163 : * @exception NumberFormatException If the string is not numeric
164 : * @exception UnknownElement If the named data field is not in the line
165 : */
166 : std::string getNamedString(const std::string& fieldName);
167 :
168 : /** @brief The same, but two different names for the field are allowed
169 : *
170 : * @param[in] fieldName1 Name of the first column to extract the string from
171 : * @param[in] fieldName2 Name of the second column to extract the string from
172 : * @return The parsed, normalised string
173 : * @exception OutOfBoundsException If the current data line has less entries than the string's position
174 : * @exception NumberFormatException If the string is not numeric
175 : * @exception UnknownElement If the named data field is not in the line
176 : */
177 : std::string getNamedString(const std::string& fieldName1, const std::string& fieldName2);
178 :
179 :
180 : /** @brief tries to get a double which is possibly assigned to a certain modality
181 : *
182 : * When the double cannot be extracted using the given name, "(IV)" is
183 : * appended to the begin of the name. Note that this function does not
184 : * yet support public traffic.
185 : *
186 : * @param[in] name Name of the column to extract the real from
187 : * @return The real stored under the named column, or if not found the one from name + suffix, or if not found -1
188 : */
189 : double getWeightedFloat(const std::string& name, const std::string& suffix);
190 :
191 : /// @brief as above but with two alternative names
192 : double getWeightedFloat2(const std::string& name, const std::string& name2, const std::string& suffix);
193 :
194 : /// @brief parse permissions
195 : SVCPermissions getPermissions(const std::string& name, const std::string& edgeType, SVCPermissions unknown);
196 :
197 : /** @brief tries to get a bool which is possibly assigned to a certain modality
198 : *
199 : * When the bool cannot be extracted using the given name, "IV" is
200 : * appended to the begin of the name. Note that this function does not
201 : * yet support public traffic.
202 : *
203 : * @param[in] name Name of the column to extract the bool from
204 : * @return The bool stored under the named column, or if not found the one from "(IV)"+name, or if not found false
205 : */
206 : bool getWeightedBool(const std::string& name);
207 :
208 :
209 : /** @brief Tries to get the node which name is stored in the given field
210 : *
211 : * If the field can not be parsed, an exception is thrown. Prints an error if the
212 : * node could not be found, returning 0. Otherwise, if the field could be parsed
213 : * and the node was found, this node is returned.
214 : *
215 : * @param[in] fieldName Name of the column to extract the node's name from
216 : * @return An already known node with the found name
217 : * @exception OutOfBoundsException If the current data line has less entries than the node id's position
218 : * @exception NumberFormatException If the node id is not numeric
219 : * @exception UnknownElement If the named data field is not in the line
220 : */
221 : NBNode* getNamedNode(const std::string& fieldName);
222 : NBNode* getNamedNodeSecure(const std::string& fieldName, NBNode* fallback = 0);
223 :
224 : /** @brief The same, but two different names for the field are allowed
225 : *
226 : * @param[in] fieldName1 Name of the first column to extract the node's name from
227 : * @param[in] fieldName2 Name of the second column to extract the node's name from
228 : * @return An already known node with the found name
229 : * @exception OutOfBoundsException If the current data line has less entries than the node id's position
230 : * @exception NumberFormatException If the node id is not numeric
231 : * @exception UnknownElement If the named data field is not in the line
232 : */
233 : NBNode* getNamedNode(const std::string& fieldName1, const std::string& fieldName2);
234 :
235 :
236 : /** @brief Tries to get the edge which name is stored in the given field
237 : *
238 : * If the field can not be parsed, an exception is thrown. Prints an error if the
239 : * edge could not be found, returning 0. Otherwise, if the field could be parsed
240 : * and the edge was found, this edge is returned.
241 : *
242 : * @param[in] fieldName Name of the column to extract the edge's name from
243 : * @return An already known edge with the found name
244 : * @exception OutOfBoundsException If the current data line has less entries than the edge id's position
245 : * @exception NumberFormatException If the edge id is not numeric
246 : * @exception UnknownElement If the named data field is not in the line
247 : */
248 : NBEdge* getNamedEdge(const std::string& fieldName);
249 :
250 : /** @brief The same, but two different names for the field are allowed
251 : *
252 : * @param[in] fieldName1 Name of the first column to extract the edge's name from
253 : * @param[in] fieldName2 Name of the second column to extract the edge's name from
254 : * @return An already known edge with the found name
255 : * @exception OutOfBoundsException If the current data line has less entries than the edge id's position
256 : * @exception NumberFormatException If the edge id is not numeric
257 : * @exception UnknownElement If the named data field is not in the line
258 : */
259 : NBEdge* getNamedEdge(const std::string& fieldName1, const std::string& fieldName2);
260 :
261 :
262 : /** @brief Tries to get the edge which name is stored in the given field
263 : * continuating the search for a subedge that ends at the given node
264 : *
265 : * If the field can not be parsed, an exception is thrown. Prints an error if the
266 : * edge could not be found, returning 0. Otherwise, if the field could be parsed
267 : * and the edge was found, this edge is returned.
268 : *
269 : * @param[in] fieldName Name of the column to extract the edge's name from
270 : * @param[in] node The node the consecutive edge must end at in order to be returned
271 : * @return The edge's continuation up to the given node, 0 if not found
272 : * @exception OutOfBoundsException If the current data line has less entries than the edge id's position
273 : * @exception NumberFormatException If the edge id is not numeric
274 : * @exception UnknownElement If the named data field is not in the line
275 : */
276 : NBEdge* getNamedEdgeContinuating(const std::string& fieldName, NBNode* node);
277 :
278 : /** @brief The same, but two different names for the field are allowed
279 : *
280 : * @param[in] fieldName1 Name of the first column to extract the edge's name from
281 : * @param[in] fieldName2 Name of the second column to extract the edge's name from
282 : * @param[in] node The node the consecutive edge must end at in order to be returned
283 : * @return The edge's continuation up to the given node, 0 if not found
284 : * @exception OutOfBoundsException If the current data line has less entries than the edge id's position
285 : * @exception NumberFormatException If the edge id is not numeric
286 : * @exception UnknownElement If the named data field is not in the line
287 : */
288 : NBEdge* getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
289 : NBNode* node);
290 :
291 : /** @brief The same, but for an already given edge
292 : *
293 : * @param[in] begin The edge to get the continuation of
294 : * @param[in] node The node the consecutive edge must end at in order to be returned
295 : * @return The edge's continuation up to the given node, 0 if not found
296 : */
297 : NBEdge* getNamedEdgeContinuating(NBEdge* begin, NBNode* node);
298 :
299 :
300 : /** @brief Returns the edge that connects both nodes
301 : *
302 : * @param[in] FromNode Name of the node the edge shall start at
303 : * @param[in] ToNode Name of the node the edge shall end at
304 : * @return The edge connecting both nodes, 0 if no such edge exists
305 : */
306 : NBEdge* getEdge(NBNode* FromNode, NBNode* ToNode);
307 :
308 :
309 : /** @brief Returns the opposite direction of the given edge
310 : *
311 : * Because the opposite direction edge may be split, not the plain opposite
312 : * edge, the one which name is obtained by adding/removing the leading '-', is returned,
313 : * but its continuation until the named node.
314 : *
315 : * @param[in] edge Name of the edge to find the opposite of
316 : * @param[in] node Name of the node the opposite edge's continuation must end at
317 : * @return The found opposite edge's continuation, 0 if not found
318 : */
319 : NBEdge* getReversedContinuating(NBEdge* edge, NBNode* node);
320 :
321 :
322 : /** @brief Builds a node for the given district and returns it
323 : *
324 : * If the district does not exist, an error is generated and 0 returned. Otherwise
325 : * a position for the new node is computed and the new node is built using a combination
326 : * of the district name and the node name as id. If Inserting this node into
327 : * the net builder fails, zero is returned.
328 : *
329 : * @param[in] id Name of the district
330 : * @param[in] dest Name of the according network node
331 : * @param[in] isSource Information whether this node will be used as a source
332 : * @return The built node, zero if an error occurred
333 : */
334 : NBNode* buildDistrictNode(const std::string& id, NBNode* dest, bool isSource);
335 :
336 :
337 : /** @brief Returns whether both nodes are a valid combination of from/to-nodes
338 : *
339 : * They are valid if both are !=0 and differ.
340 : *
341 : * @param[in] from The from-node
342 : * @param[in] from The to-node
343 : * @return Whether the nodes may be used
344 : */
345 : bool checkNodes(NBNode* from, NBNode* to);
346 :
347 :
348 : private:
349 : /**
350 : * @brief Definition of a function for parsing a single line from a certain db
351 : *
352 : * This function may assume that both the LineParser is initialised
353 : * with the current line.
354 : */
355 : typedef void (NIImporter_VISUM::*ParsingFunction)();
356 :
357 : /**
358 : * @struct TypeParser
359 : * @brief A complete call description for parsing a single db.
360 : */
361 819 : struct TypeParser {
362 : /** @brief The name of the db
363 : *
364 : * Initialised in the constructor */
365 : std::string name;
366 :
367 : /** @brief Pointer to the function used for parsing
368 : *
369 : * Initialised in the constructor */
370 : ParsingFunction function;
371 :
372 : /** @brief Position of the according db within the file
373 : *
374 : * Set to -1 in the constructor, and reset to the position while
375 : * scanning the file if the according db was found */
376 : long position;
377 :
378 : /** @brief The column names
379 : *
380 : * Set while scanning the file if the according db was found */
381 : std::string pattern;
382 :
383 : };
384 :
385 :
386 : /// @brief Parses meta data (i.e. projection)
387 : void parse_Network();
388 :
389 : /// @brief Parses VSYS
390 : void parse_VSysTypes();
391 :
392 : /// @brief Parses STRECKENTYP
393 : void parse_Types();
394 :
395 : /// @brief Parses KNOTEN
396 : void parse_Nodes();
397 :
398 : /// @brief Parses BEZIRK
399 : void parse_Districts();
400 :
401 : /// @brief Parses PUNKT
402 : void parse_Point();
403 :
404 :
405 : /// @brief Parses STRECKE/STRECKEN
406 : void parse_Edges();
407 :
408 : /// @brief Parses FLAECHENELEMENT
409 : void parse_PartOfArea();
410 :
411 : /// @brief Parses FLAECHENELEMENT
412 : void parse_Kante();
413 :
414 :
415 : /// @brief Parses ANBINDUNG
416 : void parse_Connectors();
417 : void parse_Connectors_legacy();
418 :
419 : /// @brief Parses ABBIEGEBEZIEHUNG/ABBIEGER
420 : void parse_Turns();
421 :
422 : /// @brief Parses STRECKENPOLY
423 : void parse_EdgePolys();
424 :
425 : /// @brief Parses FAHRSTREIFEN
426 : void parse_Lanes();
427 :
428 : /// @brief Parses LSA/SIGNALANLAGE
429 : void parse_TrafficLights();
430 :
431 : /// @brief Parses KNOTENZULSA/SIGNALANLAGEZUKNOTEN
432 : void parse_NodesToTrafficLights();
433 :
434 : /// @brief Parses LSASIGNALGRUPPE/SIGNALGRUPPE
435 : void parse_SignalGroups();
436 :
437 : /// @brief Parses ABBZULSASIGNALGRUPPE/SIGNALGRUPPEZUABBIEGER
438 : void parse_TurnsToSignalGroups();
439 :
440 : /// @brief Parses ABBZULSASIGNALGRUPPE/SIGNALGRUPPEZUABBIEGER
441 : void parse_AreaSubPartElement();
442 :
443 : /// @brief Parses LSAPHASE/PHASE
444 : void parse_Phases();
445 :
446 : /// @brief Parses LSASIGNALGRUPPEZULSAPHASE
447 : void parse_SignalGroupsToPhases();
448 :
449 : /// @brief Parses FAHRSTREIFENABBIEGER
450 : void parse_LanesConnections();
451 :
452 : /// @brief Parses HALTEPUNKT (public transport stop locations)
453 : void parse_stopPoints();
454 :
455 : /** @brief Adds a parser into the sorted list of parsers to use
456 : *
457 : * @param[in] name db name to assign the parser to
458 : * @param[in] function The function to use for parsing the named db
459 : */
460 : void addParser(const std::string& name, ParsingFunction function);
461 :
462 : private:
463 :
464 : /// @brief whether the edge id ends with _nodeID
465 : static bool isSplitEdge(NBEdge* edge, NBNode* node);
466 :
467 :
468 : private:
469 : /// @brief The network builder to fill with loaded values
470 : NBNetBuilder& myNetBuilder;
471 :
472 : /// @brief The name of the parsed file, for error reporting
473 : std::string myFileName;
474 :
475 : /// @brief The line reader to use to read from the file
476 : LineReader myLineReader;
477 :
478 : /** @brief the parser to parse the information from the data lines
479 : *
480 : * the order of columns within the visum format seems to vary, so a named parser is needed */
481 : NamedColumnsParser myLineParser;
482 :
483 : /// @brief The converter to compute the lane number of edges from their capacity
484 : NBCapacity2Lanes myCapacity2Lanes;
485 :
486 : /// @brief Definition of a storage for vsystypes
487 60 : struct VSysType {
488 120 : VSysType(const std::string& _type, const std::string& _name) : type(_type), name(_name) {}
489 : const std::string type;
490 : const std::string name;
491 : };
492 : typedef std::map<std::string, VSysType> VSysTypeNames;
493 : /// @brief The used vsystypes
494 : VSysTypeNames myVSysTypes;
495 :
496 : /// @brief Definition of the list of known parsers
497 : typedef std::vector<TypeParser> ParserVector;
498 : /// @brief List of known parsers
499 : ParserVector mySingleDataParsers;
500 :
501 : /// @brief Definition of a map for loaded traffic lights (id->tls)
502 : typedef std::map<std::string, NIVisumTL*> NIVisumTL_Map;
503 : /// @brief List of visum traffic lights
504 : NIVisumTL_Map myTLS;
505 :
506 : /// @brief Already read edges
507 : std::vector<std::string > myTouchedEdges;
508 :
509 : /// @brief Information whether VISUM priority information shall be used
510 : bool myUseVisumPrio;
511 :
512 : /// @brief The name of the currently parsed item used for error reporting
513 : std::string myCurrentID;
514 :
515 :
516 : /// @brief A map of point ids to positions
517 : std::map<long long int, Position> myPoints;
518 :
519 : /// @brief A map of edge (not road, but "edge" in this case) ids to from/to-points
520 : std::map<long long int, std::pair<long long int, long long int> > myEdges;
521 :
522 : /// @brief A map from district shape definition name to the district
523 : std::map<long long int, NBDistrict*> myShapeDistrictMap;
524 :
525 : /// @brief A map from area parts to area ids
526 : std::map<long long int, std::vector<long long int> > mySubPartsAreas;
527 :
528 : /// @brief A temporary storage for district shapes as they are filled incrementally
529 : std::map<NBDistrict*, PositionVector> myDistrictShapes;
530 :
531 : SVCPermissions myDefaultPermissions;
532 :
533 : protected:
534 : /**
535 : * @enum VISUM keys
536 : * @brief Numbers representing VISUM keywords
537 : */
538 : enum VISUM_KEY {
539 : VISUM_SYS,
540 : VISUM_LINKTYPE,
541 : VISUM_NODE,
542 : VISUM_DISTRICT,
543 : VISUM_POINT,
544 : VISUM_LINK,
545 : VISUM_V0,
546 : VISUM_TYPES,
547 : VISUM_RANK,
548 : VISUM_CAPACITY,
549 : VISUM_XCOORD,
550 : VISUM_YCOORD,
551 : VISUM_FROMNODE,
552 : VISUM_TONODE,
553 : VISUM_TYPE,
554 : VISUM_TYP,
555 : VISUM_ID,
556 : VISUM_CODE,
557 : VISUM_DISTRICT_CONNECTION,
558 : VISUM_SOURCE_DISTRICT,
559 : VISUM_FROMNODENO,
560 : VISUM_DIRECTION,
561 : VISUM_SURFACEID,
562 : VISUM_FACEID,
563 : VISUM_FROMPOINTID,
564 : VISUM_TOPOINTID,
565 : VISUM_EDGE,
566 : VISUM_VIANODENO,
567 : VISUM_NUMLANES,
568 : VISUM_TURN,
569 : VISUM_INDEX,
570 : VISUM_LINKPOLY,
571 : VISUM_SURFACEITEM,
572 : VISUM_FACEITEM,
573 : VISUM_EDGEID,
574 : VISUM_ORIGIN,
575 : VISUM_DESTINATION,
576 : VISUM_STOPPOINT,
577 : VISUM_NAME,
578 : VISUM_LINKNO,
579 : VISUM_RELPOS,
580 : // polyconvert keys added to avoid warnings
581 : VISUM_CATID,
582 : VISUM_EDGEITEM,
583 : VISUM_POICATEGORY,
584 : VISUM_NETWORK,
585 : VISUM_PROJECTIONDEFINITION,
586 : VISUM_PRT,
587 : VISUM_NO // must be the last one
588 : };
589 :
590 : /// Strings for the keywords
591 : static StringBijection<VISUM_KEY>::Entry KEYS_DE[];
592 :
593 : /// @brief link directions
594 : static StringBijection<VISUM_KEY> KEYS;
595 :
596 : void loadLanguage(const std::string& file);
597 : };
|