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