1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    NIImporter_VISUM.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Michael Behrisch
13 /// @date    Fri, 19 Jul 2002
14 /// @version $Id$
15 ///
16 // A VISUM network importer
17 /****************************************************************************/
18 #ifndef NIImporter_VISUM_h
19 #define NIImporter_VISUM_h
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <string>
28 #include <map>
29 #include <vector>
30 #include <netbuild/NBCapacity2Lanes.h>
31 #include <utils/importio/LineHandler.h>
32 #include <utils/importio/LineReader.h>
33 #include <utils/importio/NamedColumnsParser.h>
34 #include "NIVisumTL.h"
35 
36 
37 // ===========================================================================
38 // class declaration
39 // ===========================================================================
40 class OptionsCont;
41 class NBNetBuilder;
42 class NBNodeCont;
43 class NBEdgeCont;
44 class NBNode;
45 class NBEdge;
46 
47 
48 // ===========================================================================
49 // class declaration
50 // ===========================================================================
51 /**
52  * @class NIImporter_VISUM
53  * @brief A VISUM network importer
54  *
55  * This class build an internal list of those VISUM-db entries which are
56  *  supported, first. This list is sorted in a way that the parsed dbs can
57  *  build upon each other as their related structures within the XML-input.
58  *  So, nodes are loaded first, then edges, etc.
59  *
60  * Because these structures may have a different order within the VISUM-file
61  *  than we need, at first the file is scanned and any occurence of one of the
62  *  searched dbs is saved. That's where the "Found $XXX at YYY" are printed.
63  *  "YYY" is the character position within the file.
64  *
65  * In a second step, the dbs are parsed in the order we need. It is asked for
66  *  each subsequently whether it was found and if so, the proper parse_XXX()
67  *  method is called.
68  */
69 class NIImporter_VISUM {
70 public:
71     /** @brief Loads network definition from the assigned option and stores it in the given network builder
72      *
73      * If the option "visum" is set, the file stored therein is read and
74      *  the network definition stored therein is stored within the given network
75      *  builder.
76      *
77      * If the option "visum" is not set, this method simply returns.
78      *
79      * @param[in] oc The options to use
80      * @param[in] nb The network builder to fill
81      */
82     static void loadNetwork(const OptionsCont& oc, NBNetBuilder& nb);
83 
84 
85 protected:
86     /** @brief constructor
87      *
88      * Builds the list of typed db parsers ("TypeParser") and stores them in
89      *  mySingleDataParsers in the order the according db values must be parsed.
90      *
91      * @param[in,out] nb the network builder (storage) to fill with parsed values
92      * @param[in] file The name of the file to parse
93      * @param[in] capacity2Lanes The converter from flow to lanes
94      * @param[in] useVisumPrio Information whether the VISUM type's priority shall be used
95      */
96     NIImporter_VISUM(NBNetBuilder& nb, const std::string& file,
97                      NBCapacity2Lanes capacity2Lanes, bool useVisumPrio);
98 
99 
100     /// @brief destructor
101     ~NIImporter_VISUM();
102 
103 
104     /** @brief Parses the VISUM-network file storing the parsed structures within myNetBuilder
105      *
106      * At first, it is checked whether the file can be opened. A ProcessError is thrown
107      *  if not. Otherwise, the file is scanned for occurences of db table begins. For each found
108      *  db, its position within the file, and the column names are stored in the according
109      *  TypeParser. After this, the sorted list of type parsers is one through and each
110      *  found is used to parse the entries at the found positions using the found column names.
111      *
112      * @exception ProcessError If the file could not be opened
113      */
114     void load();
115 
116 private:
117     /** @brief Returns the value from the named column as a float
118      *
119      * @param[in] fieldName Name of the column to extract the float from
120      * @return The parsed real
121      * @exception OutOfBoundsException If the current data line has less entries than the float's position
122      * @exception NumberFormatException If the float is not numeric
123      * @exception UnknownElement If the named data field is not in the line
124      */
125     double getNamedFloat(const std::string& fieldName);
126 
127     /** @brief The same, but two different names for the field are allowed
128      *
129      * @param[in] fieldName1 Name of the first column to extract the float from
130      * @param[in] fieldName2 Name of the second column to extract the efloat from
131      * @return The parsed real
132      * @exception OutOfBoundsException If the current data line has less entries than the float's position
133      * @exception NumberFormatException If the float is not numeric
134      * @exception UnknownElement If the named data field is not in the line
135      */
136     double getNamedFloat(const std::string& fieldName1, const std::string& fieldName2);
137 
138 
139     /** @brief Returns the value from the named column as a float or the default value if an error occurs
140      *
141      * @param[in] fieldName Name of the column to extract the float from
142      * @param[in] defaultValue The default to return in the case of an error
143      * @return The parsed real or the default value if an error while parsing occurred
144      */
145     double getNamedFloat(const std::string& fieldName, double defaultValue);
146 
147     /** @brief The same, but two different names for the field are allowed
148      *
149      * @param[in] fieldName1 Name of the first column to extract the float from
150      * @param[in] fieldName2 Name of the second column to extract the efloat from
151      * @param[in] defaultValue The default to return in the case of an error
152      * @return The parsed real or the default value if an error while parsing occurred
153      */
154     double getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
155                          double defaultValue);
156 
157 
158     /** @brief Returns the value from the named column as a normalised string
159      *
160      * "Normalised" means herein that the leading '0' (zeros) are prunned.
161      *
162      * @param[in] fieldName Name of the column to extract the string from
163      * @return The parsed, normalised string
164      * @exception OutOfBoundsException If the current data line has less entries than the string's position
165      * @exception NumberFormatException If the string is not numeric
166      * @exception UnknownElement If the named data field is not in the line
167      */
168     std::string getNamedString(const std::string& fieldName);
169 
170     /** @brief The same, but two different names for the field are allowed
171      *
172      * @param[in] fieldName1 Name of the first column to extract the string from
173      * @param[in] fieldName2 Name of the second column to extract the string from
174      * @return The parsed, normalised string
175      * @exception OutOfBoundsException If the current data line has less entries than the string's position
176      * @exception NumberFormatException If the string is not numeric
177      * @exception UnknownElement If the named data field is not in the line
178      */
179     std::string getNamedString(const std::string& fieldName1, const std::string& fieldName2);
180 
181 
182     /** @brief tries to get a double which is possibly assigned to a certain modality
183      *
184      * When the double cannot be extracted using the given name, "(IV)" is
185      * appended to the begin of the name. Note that this function does not
186      * yet support public traffic.
187      *
188      * @param[in] name Name of the column to extract the real from
189      * @return The real stored under the named column, or if not found the one from name + suffix, or if not found -1
190      */
191     double getWeightedFloat(const std::string& name, const std::string& suffix);
192 
193     /// @brief as above but with two alternative names
194     double getWeightedFloat2(const std::string& name, const std::string& name2, const std::string& suffix);
195 
196     /// @brief parse permissions
197     SVCPermissions getPermissions(const std::string& name, bool warn = false, SVCPermissions unknown = SVCAll);
198 
199     /** @brief tries to get a bool which is possibly assigned to a certain modality
200      *
201      * When the bool cannot be extracted using the given name, "IV" is
202      * appended to the begin of the name. Note that this function does not
203      * yet support public traffic.
204      *
205      * @param[in] name Name of the column to extract the bool from
206      * @return The bool stored under the named column, or if not found the one from "(IV)"+name, or if not found false
207      */
208     bool getWeightedBool(const std::string& name);
209 
210 
211     /** @brief Tries to get the node which name is stored in the given field
212      *
213      * If the field can not be parsed, an exception is thrown. Prints an error if the
214      *  node could not be found, returning 0. Otherwise, if the field could be parsed
215      *  and the node was found, this node is returned.
216      *
217      * @param[in] fieldName Name of the column to extract the node's name from
218      * @return An already known node with the found name
219      * @exception OutOfBoundsException If the current data line has less entries than the node id's position
220      * @exception NumberFormatException If the node id is not numeric
221      * @exception UnknownElement If the named data field is not in the line
222      */
223     NBNode* getNamedNode(const std::string& fieldName);
224     NBNode* getNamedNodeSecure(const std::string& fieldName, NBNode* fallback = 0);
225 
226     /** @brief The same, but two different names for the field are allowed
227      *
228      * @param[in] fieldName1 Name of the first column to extract the node's name from
229      * @param[in] fieldName2 Name of the second column to extract the node's name from
230      * @return An already known node with the found name
231      * @exception OutOfBoundsException If the current data line has less entries than the node id's position
232      * @exception NumberFormatException If the node id is not numeric
233      * @exception UnknownElement If the named data field is not in the line
234      */
235     NBNode* getNamedNode(const std::string& fieldName1, const std::string& fieldName2);
236 
237 
238     /** @brief Tries to get the edge which name is stored in the given field
239      *
240      * If the field can not be parsed, an exception is thrown. Prints an error if the
241      *  edge could not be found, returning 0. Otherwise, if the field could be parsed
242      *  and the edge was found, this edge is returned.
243      *
244      * @param[in] fieldName Name of the column to extract the edge's name from
245      * @return An already known edge with the found name
246      * @exception OutOfBoundsException If the current data line has less entries than the edge id's position
247      * @exception NumberFormatException If the edge id is not numeric
248      * @exception UnknownElement If the named data field is not in the line
249      */
250     NBEdge* getNamedEdge(const std::string& fieldName);
251 
252     /** @brief The same, but two different names for the field are allowed
253      *
254      * @param[in] fieldName1 Name of the first column to extract the edge's name from
255      * @param[in] fieldName2 Name of the second column to extract the edge's name from
256      * @return An already known edge with the found name
257      * @exception OutOfBoundsException If the current data line has less entries than the edge id's position
258      * @exception NumberFormatException If the edge id is not numeric
259      * @exception UnknownElement If the named data field is not in the line
260      */
261     NBEdge* getNamedEdge(const std::string& fieldName1, const std::string& fieldName2);
262 
263 
264     /** @brief Tries to get the edge which name is stored in the given field
265      * continuating the search for a subedge that ends at the given node
266      *
267      * If the field can not be parsed, an exception is thrown. Prints an error if the
268      *  edge could not be found, returning 0. Otherwise, if the field could be parsed
269      *  and the edge was found, this edge is returned.
270      *
271      * @param[in] fieldName Name of the column to extract the edge's name from
272      * @param[in] node The node the consecutive edge must end at in order to be returned
273      * @return The edge's continuation up to the given node, 0 if not found
274      * @exception OutOfBoundsException If the current data line has less entries than the edge id's position
275      * @exception NumberFormatException If the edge id is not numeric
276      * @exception UnknownElement If the named data field is not in the line
277      */
278     NBEdge* getNamedEdgeContinuating(const std::string& fieldName, NBNode* node);
279 
280     /** @brief The same, but two different names for the field are allowed
281      *
282      * @param[in] fieldName1 Name of the first column to extract the edge's name from
283      * @param[in] fieldName2 Name of the second column to extract the edge's name from
284      * @param[in] node The node the consecutive edge must end at in order to be returned
285      * @return The edge's continuation up to the given node, 0 if not found
286      * @exception OutOfBoundsException If the current data line has less entries than the edge id's position
287      * @exception NumberFormatException If the edge id is not numeric
288      * @exception UnknownElement If the named data field is not in the line
289      */
290     NBEdge* getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
291                                      NBNode* node);
292 
293     /** @brief The same, but for an already given edge
294      *
295      * @param[in] begin The edge to get the continuation of
296      * @param[in] node The node the consecutive edge must end at in order to be returned
297      * @return The edge's continuation up to the given node, 0 if not found
298      */
299     NBEdge* getNamedEdgeContinuating(NBEdge* begin, NBNode* node);
300 
301 
302     /** @brief Returns the edge that connects both nodes
303      *
304      * @param[in] FromNode Name of the node the edge shall start at
305      * @param[in] ToNode Name of the node the edge shall end at
306      * @return The edge connecting both nodes, 0 if no such edge exists
307      */
308     NBEdge* getEdge(NBNode* FromNode, NBNode* ToNode);
309 
310 
311     /** @brief Returns the opposite direction of the given edge
312      *
313      * Because the opposite direction edge may be split, not the the plain opposite
314      *  edge, the one which name is obtained by adding/removing the leading '-', is returned,
315      *  but its continuation until the named node.
316      *
317      * @param[in] edge Name of the edge to find the opposite of
318      * @param[in] node Name of the node the opposite edge's continuation must end at
319      * @return The found opposite edge's continuation, 0 if not found
320      */
321     NBEdge* getReversedContinuating(NBEdge* edge, NBNode* node);
322 
323 
324     /** @brief Builds a node for the given district and returns it
325      *
326      * If the district does not exist, an error is generated and 0 returned. Otherwise
327      *  a position for the new node is computed and the new node is built using a combination
328      *  of the district name and the node name as id. If Inserting this node into
329      *  the net builder fails, zero is returned.
330      *
331      * @param[in] id Name of the district
332      * @param[in] dest Name of the according network node
333      * @param[in] isSource Information whether this node will be used as a source
334      * @return The built node, zero if an error occurred
335      */
336     NBNode* buildDistrictNode(const std::string& id, NBNode* dest, bool isSource);
337 
338 
339     /** @brief Returns whether both nodes are a valid combination of from/to-nodes
340      *
341      * They are valid if both are !=0 and differ.
342      *
343      * @param[in] from The from-node
344      * @param[in] from The to-node
345      * @return Whether the nodes may be used
346      */
347     bool checkNodes(NBNode* from, NBNode* to);
348 
349 
350 private:
351     /**
352      * @brief Definition of a function for parsing a single line from a certain db
353      *
354      * This function may assume that both the LineParser is initialised
355      *  with the current line.
356      */
357     typedef void (NIImporter_VISUM::*ParsingFunction)();
358 
359     /**
360      * @struct TypeParser
361      * @brief A complete call description for parsing a single db.
362      */
363     struct TypeParser {
364         /** @brief The name of the db
365          *
366          * Initialised in the constructor */
367         std::string name;
368 
369         /** @brief  Pointer to the function used for parsing
370          *
371          * Initialised in the constructor */
372         ParsingFunction function;
373 
374         /** @brief Position of the according db within the file
375          *
376          * Set to -1 in the constructor, and reset to the position while
377          *  scaning the file if the according db was found */
378         long position;
379 
380         /** @brief The column names
381          *
382          * Set while scaning the file if the according db was found */
383         std::string pattern;
384 
385     };
386 
387 
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 
418     /// @brief Parses ABBIEGEBEZIEHUNG/ABBIEGER
419     void parse_Turns();
420 
421     /// @brief Parses STRECKENPOLY
422     void parse_EdgePolys();
423 
424     /// @brief Parses FAHRSTREIFEN
425     void parse_Lanes();
426 
427     /// @brief Parses LSA/SIGNALANLAGE
428     void parse_TrafficLights();
429 
430     /// @brief Parses KNOTENZULSA/SIGNALANLAGEZUKNOTEN
431     void parse_NodesToTrafficLights();
432 
433     /// @brief Parses LSASIGNALGRUPPE/SIGNALGRUPPE
434     void parse_SignalGroups();
435 
436     /// @brief Parses ABBZULSASIGNALGRUPPE/SIGNALGRUPPEZUABBIEGER
437     void parse_TurnsToSignalGroups();
438 
439     /// @brief Parses ABBZULSASIGNALGRUPPE/SIGNALGRUPPEZUABBIEGER
440     void parse_AreaSubPartElement();
441 
442     /// @brief Parses LSAPHASE/PHASE
443     void parse_Phases();
444 
445     /// @brief Parses LSASIGNALGRUPPEZULSAPHASE
446     void parse_SignalGroupsToPhases();
447 
448     /// @brief Parses FAHRSTREIFENABBIEGER
449     void parse_LanesConnections();
450 
451 
452     /** @brief Adds a parser into the sorted list of parsers to use
453      *
454      * @param[in] name db name to assign the parser to
455      * @param[in] function The function to use for parsing the named db
456      */
457     void addParser(const std::string& name, ParsingFunction function);
458 
459 private:
460 
461     /// @brief whether the edge id ends with _nodeID
462     static bool isSplitEdge(NBEdge* edge, NBNode* node);
463 
464 
465 private:
466     /// @brief The network builder to fill with loaded values
467     NBNetBuilder& myNetBuilder;
468 
469     /// @brief The name of the parsed file, for error reporting
470     std::string myFileName;
471 
472     /// @brief The line reader to use to read from the file
473     LineReader myLineReader;
474 
475     /** @brief the parser to parse the information from the data lines
476      *
477      * the order of columns within the visum format seems to vary, so a named parser is needed */
478     NamedColumnsParser myLineParser;
479 
480     /// @brief The converter to compute the lane number of edges from their capacity
481     NBCapacity2Lanes myCapacity2Lanes;
482 
483     /// @brief Definition of a storage for vsystypes
484     typedef std::map<std::string, std::string> VSysTypeNames;
485     /// @brief The used vsystypes
486     VSysTypeNames myVSysTypes;
487 
488     /// @brief Definition of the list of known parsers
489     typedef std::vector<TypeParser> ParserVector;
490     /// @brief List of known parsers
491     ParserVector mySingleDataParsers;
492 
493     /// @brief Definition of a map for loaded traffic lights (id->tls)
494     typedef std::map<std::string, NIVisumTL*> NIVisumTL_Map;
495     /// @brief List of visum traffic lights
496     NIVisumTL_Map myTLS;
497 
498     /// @brief Already read edges
499     std::vector<std::string > myTouchedEdges;
500 
501     /// @brief Information whether VISUM priority information shall be used
502     bool myUseVisumPrio;
503 
504     /// @brief The name of the currently parsed item used for error reporting
505     std::string myCurrentID;
506 
507 
508     /// @brief A map of point ids to positions
509     std::map<long long int, Position> myPoints;
510 
511     /// @brief A map of edge (not road, but "edge" in this case) ids to from/to-points
512     std::map<long long int, std::pair<long long int, long long int> > myEdges;
513 
514     /// @brief A map from district shape definition name to the district
515     std::map<long long int, NBDistrict*> myShapeDistrictMap;
516 
517     /// @brief A map from area parts to area ids
518     std::map<long long int, std::vector<long long int> > mySubPartsAreas;
519 
520     /// @brief A temporary storage for district shapes as they are filled incrementally
521     std::map<NBDistrict*, PositionVector> myDistrictShapes;
522 
523 
524 };
525 
526 
527 #endif
528 
529 /****************************************************************************/
530 
531