|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00010 // A reader of pois and polygons stored in VISUM-format 00011 /****************************************************************************/ 00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00014 /****************************************************************************/ 00015 // 00016 // This file is part of SUMO. 00017 // SUMO is free software: you can redistribute it and/or modify 00018 // it under the terms of the GNU General Public License as published by 00019 // the Free Software Foundation, either version 3 of the License, or 00020 // (at your option) any later version. 00021 // 00022 /****************************************************************************/ 00023 00024 00025 // =========================================================================== 00026 // included modules 00027 // =========================================================================== 00028 #ifdef _MSC_VER 00029 #include <windows_config.h> 00030 #else 00031 #include <config.h> 00032 #endif 00033 00034 #include <string> 00035 #include <map> 00036 #include <fstream> 00037 #include <utils/common/StringTokenizer.h> 00038 #include <utils/common/UtilExceptions.h> 00039 #include <utils/common/MsgHandler.h> 00040 #include <utils/common/StringUtils.h> 00041 #include <utils/common/TplConvert.h> 00042 #include <utils/common/ToString.h> 00043 #include <utils/common/FileHelpers.h> 00044 #include <utils/options/OptionsCont.h> 00045 #include <utils/options/Option.h> 00046 #include <utils/importio/LineReader.h> 00047 #include <utils/common/StdDefs.h> 00048 #include <polyconvert/PCPolyContainer.h> 00049 #include "PCLoaderVisum.h" 00050 #include <utils/common/RGBColor.h> 00051 #include <utils/geom/GeomHelper.h> 00052 #include <utils/geom/Boundary.h> 00053 #include <utils/geom/Position.h> 00054 #include <utils/geom/GeoConvHelper.h> 00055 #include <utils/importio/NamedColumnsParser.h> 00056 00057 #ifdef CHECK_MEMORY_LEAKS 00058 #include <foreign/nvwa/debug_new.h> 00059 #endif // CHECK_MEMORY_LEAKS 00060 00061 00062 // =========================================================================== 00063 // method definitions 00064 // =========================================================================== 00065 void 00066 PCLoaderVisum::loadIfSet(OptionsCont& oc, PCPolyContainer& toFill, 00067 PCTypeMap& tm) { 00068 if (!oc.isSet("visum-files")) { 00069 return; 00070 } 00071 // parse file(s) 00072 std::vector<std::string> files = oc.getStringVector("visum-files"); 00073 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { 00074 if (!FileHelpers::exists(*file)) { 00075 throw ProcessError("Could not open visum-file '" + *file + "'."); 00076 } 00077 PROGRESS_BEGIN_MESSAGE("Parsing from visum-file '" + *file + "'"); 00078 load(*file, oc, toFill, tm); 00079 PROGRESS_DONE_MESSAGE(); 00080 } 00081 } 00082 00083 00084 00085 void 00086 PCLoaderVisum::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill, 00087 PCTypeMap& tm) { 00088 GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing(); 00089 std::string what; 00090 std::map<long, Position> punkte; 00091 std::map<long, PositionVector> kanten; 00092 std::map<long, PositionVector> teilflaechen; 00093 std::map<long, long> flaechenelemente; 00094 NamedColumnsParser lineParser; 00095 LineReader lr(file); 00096 while (lr.hasMore()) { 00097 std::string line = lr.readLine(); 00098 // reset if current is over 00099 if (line.length() == 0 || line[0] == '*' || line[0] == '$') { 00100 what = ""; 00101 } 00102 // read items 00103 if (what == "$PUNKT") { 00104 lineParser.parseLine(line); 00105 long id = TplConvert<char>::_2long(lineParser.get("ID").c_str()); 00106 SUMOReal x = TplConvert<char>::_2SUMOReal(lineParser.get("XKOORD").c_str()); 00107 SUMOReal y = TplConvert<char>::_2SUMOReal(lineParser.get("YKOORD").c_str()); 00108 Position pos(x, y); 00109 if (!geoConvHelper.x2cartesian(pos)) { 00110 WRITE_WARNING("Unable to project coordinates for point '" + toString(id) + "'."); 00111 } 00112 punkte[id] = pos; 00113 continue; 00114 } else if (what == "$KANTE") { 00115 lineParser.parseLine(line); 00116 long id = TplConvert<char>::_2long(lineParser.get("ID").c_str()); 00117 long fromID = TplConvert<char>::_2long(lineParser.get("VONPUNKTID").c_str()); 00118 long toID = TplConvert<char>::_2long(lineParser.get("NACHPUNKTID").c_str()); 00119 PositionVector vec; 00120 vec.push_back(punkte[fromID]); 00121 vec.push_back(punkte[toID]); 00122 kanten[id] = vec; 00123 continue; 00124 } else if (what == "$ZWISCHENPUNKT") { 00125 lineParser.parseLine(line); 00126 long id = TplConvert<char>::_2long(lineParser.get("KANTEID").c_str()); 00127 int index = TplConvert<char>::_2int(lineParser.get("INDEX").c_str()); 00128 SUMOReal x = TplConvert<char>::_2SUMOReal(lineParser.get("XKOORD").c_str()); 00129 SUMOReal y = TplConvert<char>::_2SUMOReal(lineParser.get("YKOORD").c_str()); 00130 Position pos(x, y); 00131 if (!geoConvHelper.x2cartesian(pos)) { 00132 WRITE_WARNING("Unable to project coordinates for edge '" + toString(id) + "'."); 00133 } 00134 kanten[id].insertAt(index, pos); 00135 continue; 00136 } else if (what == "$TEILFLAECHENELEMENT") { 00137 lineParser.parseLine(line); 00138 long id = TplConvert<char>::_2long(lineParser.get("TFLAECHEID").c_str()); 00139 int index = TplConvert<char>::_2int(lineParser.get("INDEX").c_str()); 00140 index = 0; 00141 long kid = TplConvert<char>::_2long(lineParser.get("KANTEID").c_str()); 00142 int dir = TplConvert<char>::_2int(lineParser.get("RICHTUNG").c_str()); 00143 if (teilflaechen.find(id) == teilflaechen.end()) { 00144 teilflaechen[id] = PositionVector(); 00145 } 00146 if (dir == 0) { 00147 for (int i = 0; i < (int) kanten[kid].size(); ++i) { 00148 teilflaechen[id].push_back_noDoublePos(kanten[kid][i]); 00149 } 00150 } else { 00151 for (int i = (int) kanten[kid].size() - 1; i >= 0; --i) { 00152 teilflaechen[id].push_back_noDoublePos(kanten[kid][i]); 00153 } 00154 } 00155 continue; 00156 } else if (what == "$FLAECHENELEMENT") { 00157 lineParser.parseLine(line); 00158 long id = TplConvert<char>::_2long(lineParser.get("FLAECHEID").c_str()); 00159 long tid = TplConvert<char>::_2long(lineParser.get("TFLAECHEID").c_str()); 00160 int enklave = TplConvert<char>::_2int(lineParser.get("ENKLAVE").c_str()); // !!! unused 00161 enklave = 0; 00162 flaechenelemente[id] = tid; 00163 continue; 00164 } 00165 // set if read 00166 if (line[0] == '$') { 00167 what = ""; 00168 if (line.find("$PUNKT") == 0) { 00169 what = "$PUNKT"; 00170 } else if (line.find("$KANTE") == 0) { 00171 what = "$KANTE"; 00172 } else if (line.find("$ZWISCHENPUNKT") == 0) { 00173 what = "$ZWISCHENPUNKT"; 00174 } else if (line.find("$TEILFLAECHENELEMENT") == 0) { 00175 what = "$TEILFLAECHENELEMENT"; 00176 } else if (line.find("$FLAECHENELEMENT") == 0) { 00177 what = "$FLAECHENELEMENT"; 00178 } 00179 if (what != "") { 00180 lineParser.reinit(line.substr(what.length() + 1)); 00181 } 00182 } 00183 } 00184 00185 // do some more sane job... 00186 RGBColor c = RGBColor::parseColor(oc.getString("color")); 00187 std::map<std::string, std::string> typemap; 00188 // load the pois/polys 00189 lr.reinit(); 00190 bool parsingCategories = false; 00191 bool parsingPOIs = false; 00192 bool parsingDistrictsDirectly = false; 00193 PositionVector vec; 00194 std::string polyType, lastID; 00195 bool first = true; 00196 while (lr.hasMore()) { 00197 std::string line = lr.readLine(); 00198 // do not parse empty lines 00199 if (line.length() == 0) { 00200 continue; 00201 } 00202 // do not parse comment lines 00203 if (line[0] == '*') { 00204 continue; 00205 } 00206 00207 if (line[0] == '$') { 00208 // reset parsing on new entry type 00209 parsingCategories = false; 00210 parsingPOIs = false; 00211 parsingDistrictsDirectly = false; 00212 polyType = ""; 00213 } 00214 00215 if (parsingCategories) { 00216 // parse the category 00217 StringTokenizer st(line, ";"); 00218 std::string catid = st.next(); 00219 std::string catname = st.next(); 00220 typemap[catid] = catname; 00221 } 00222 if (parsingPOIs) { 00223 // parse the poi 00224 // $POI:Nr;CATID;CODE;NAME;Kommentar;XKoord;YKoord; 00225 StringTokenizer st(line, ";"); 00226 std::string num = st.next(); 00227 std::string catid = st.next(); 00228 std::string code = st.next(); 00229 std::string name = st.next(); 00230 std::string comment = st.next(); 00231 std::string xpos = st.next(); 00232 std::string ypos = st.next(); 00233 // process read values 00234 SUMOReal x = TplConvert<char>::_2SUMOReal(xpos.c_str()); 00235 SUMOReal y = TplConvert<char>::_2SUMOReal(ypos.c_str()); 00236 Position pos(x, y); 00237 if (!geoConvHelper.x2cartesian(pos)) { 00238 WRITE_WARNING("Unable to project coordinates for POI '" + num + "'."); 00239 } 00240 std::string type = typemap[catid]; 00241 // check the poi 00242 name = num; 00243 // patch the values 00244 bool discard = oc.getBool("discard"); 00245 int layer = oc.getInt("layer"); 00246 RGBColor color; 00247 if (tm.has(type)) { 00248 const PCTypeMap::TypeDef& def = tm.get(type); 00249 name = def.prefix + name; 00250 type = def.id; 00251 color = RGBColor::parseColor(def.color); 00252 discard = def.discard; 00253 layer = def.layer; 00254 } else { 00255 name = oc.getString("prefix") + name; 00256 type = oc.getString("type"); 00257 color = c; 00258 } 00259 if (!discard) { 00260 PointOfInterest* poi = new PointOfInterest(name, type, pos, color); 00261 if (!toFill.insert(name, poi, layer)) { 00262 WRITE_ERROR("POI '" + name + "' could not been added."); 00263 delete poi; 00264 } 00265 } 00266 } 00267 00268 // poly 00269 if (polyType != "") { 00270 StringTokenizer st(line, ";"); 00271 std::string id = st.next(); 00272 std::string type; 00273 if (!first && lastID != id) { 00274 // we have parsed a polygon completely 00275 RGBColor color; 00276 int layer = oc.getInt("layer"); 00277 bool discard = oc.getBool("discard"); 00278 if (tm.has(polyType)) { 00279 const PCTypeMap::TypeDef& def = tm.get(polyType); 00280 id = def.prefix + id; 00281 type = def.id; 00282 color = RGBColor::parseColor(def.color); 00283 discard = def.discard; 00284 layer = def.layer; 00285 } else { 00286 id = oc.getString("prefix") + id; 00287 type = oc.getString("type"); 00288 color = c; 00289 } 00290 if (!discard) { 00291 Polygon* poly = new Polygon(id, type, color, vec, false); 00292 if (!toFill.insert(id, poly, 1)) { 00293 WRITE_ERROR("Polygon '" + id + "' could not been added."); 00294 delete poly; 00295 } 00296 } 00297 vec.clear(); 00298 } 00299 lastID = id; 00300 first = false; 00301 // parse current poly 00302 std::string index = st.next(); 00303 std::string xpos = st.next(); 00304 std::string ypos = st.next(); 00305 Position pos2D((SUMOReal) atof(xpos.c_str()), (SUMOReal) atof(ypos.c_str())); 00306 if (!geoConvHelper.x2cartesian(pos2D)) { 00307 WRITE_WARNING("Unable to project coordinates for polygon '" + id + "'."); 00308 } 00309 vec.push_back(pos2D); 00310 } 00311 00312 // district refering a shape 00313 if (parsingDistrictsDirectly) { 00314 //$BEZIRK:NR CODE NAME TYPNR XKOORD YKOORD FLAECHEID BEZART IVANTEIL_Q IVANTEIL_Z OEVANTEIL METHODEANBANTEILE ZWERT1 ZWERT2 ZWERT3 ISTINAUSWAHL OBEZNR NOM_COM COD_COM 00315 StringTokenizer st(line, ";"); 00316 std::string num = st.next(); 00317 std::string code = st.next(); 00318 std::string name = st.next(); 00319 st.next(); // typntr 00320 std::string xpos = st.next(); 00321 std::string ypos = st.next(); 00322 long id = TplConvert<char>::_2long(st.next().c_str()); 00323 // patch the values 00324 std::string type = "district"; 00325 name = num; 00326 bool discard = oc.getBool("discard"); 00327 int layer = oc.getInt("layer"); 00328 RGBColor color; 00329 if (tm.has(type)) { 00330 const PCTypeMap::TypeDef& def = tm.get(type); 00331 name = def.prefix + name; 00332 type = def.id; 00333 color = RGBColor::parseColor(def.color); 00334 discard = def.discard; 00335 layer = def.layer; 00336 } else { 00337 name = oc.getString("prefix") + name; 00338 type = oc.getString("type"); 00339 color = c; 00340 } 00341 if (!discard) { 00342 if (teilflaechen[flaechenelemente[id]].size() > 0) { 00343 Polygon* poly = new Polygon(name, type, color, teilflaechen[flaechenelemente[id]], false); 00344 if (!toFill.insert(name, poly, layer)) { 00345 WRITE_ERROR("Polygon '" + name + "' could not been added."); 00346 delete poly; 00347 } 00348 } else { 00349 SUMOReal x = TplConvert<char>::_2SUMOReal(xpos.c_str()); 00350 SUMOReal y = TplConvert<char>::_2SUMOReal(ypos.c_str()); 00351 Position pos(x, y); 00352 if (!geoConvHelper.x2cartesian(pos)) { 00353 WRITE_WARNING("Unable to project coordinates for POI '" + name + "'."); 00354 } 00355 PointOfInterest* poi = new PointOfInterest(name, type, pos, color); 00356 if (!toFill.insert(name, poi, layer)) { 00357 WRITE_ERROR("POI '" + name + "' could not been added."); 00358 delete poi; 00359 } 00360 } 00361 } 00362 } 00363 00364 00365 if (line.find("$POIKATEGORIEDEF:") == 0 || line.find("$POIKATEGORIE:") == 0) { 00366 // ok, got categories, begin parsing from next line 00367 parsingCategories = true; 00368 } 00369 if (line.find("$POI:") == 0) { 00370 // ok, got pois, begin parsing from next line 00371 parsingPOIs = true; 00372 } 00373 if (line.find("$BEZIRK") == 0 && line.find("FLAECHEID") != std::string::npos) { 00374 // ok, have a district header, and it seems like districts would reference shapes... 00375 parsingDistrictsDirectly = true; 00376 } 00377 00378 00379 if (line.find("$BEZIRKPOLY") != std::string::npos) { 00380 polyType = "district"; 00381 } 00382 if (line.find("$GEBIETPOLY") != std::string::npos) { 00383 polyType = "area"; 00384 } 00385 00386 } 00387 } 00388 00389 00390 00391 /****************************************************************************/ 00392