NMPB08 Shared Libraries
|
00001 #include "../test_mem/safe_new.h" 00002 #include "RailwayDatabase.h" 00003 #include <math.h> 00004 00005 RailwayDatabase _shared_db ; 00006 00007 // -------------------------------------------------------------------------------------- 00008 // standard C interface to railway database functions 00009 // -------------------------------------------------------------------------------------- 00010 00011 int NMPB08_LoadRailwayDatabase (const char* filename, bool trace) 00012 { 00013 return _shared_db.LoadFile (filename, trace) ; 00014 } 00015 00016 int NMPB08_DumpRailwayDatabase (const char* filename) 00017 { 00018 return _shared_db.Dump(filename) ; 00019 } 00020 00021 int NMPB08_EnumRailwayDatabase (EnumRailwayEntities enumProc, 00022 unsigned int include_types, 00023 void* userdata) 00024 { 00025 return _shared_db.EnumEntities (enumProc, include_types, userdata) ; 00026 } 00027 00028 int NMPB08_EnumRailwaySources (EnumRailwaySources enumProc, 00029 const char* name, 00030 void* userdata) 00031 { 00032 std::string getID (const char *s) ; 00033 return _shared_db.EnumSources (enumProc, getID(name), userdata, 0.0) ; 00034 } 00035 00036 // -------------------------------------------------------------------------------------- 00037 00038 #define Printf if (trace_debug) printf 00039 00040 // -------------------------------------------------------------------------------------- 00041 00042 static inline double POW10 (double x) 00043 { 00044 return (x < -99) ? 0.0 : pow(10., x/10.) ; 00045 } 00046 00047 static inline double LOG10 (double x) 00048 { 00049 return (x <= 0) ? -99.9 : 10 * log10(x) ; 00050 } 00051 00052 template <class T> inline T MIN (T const& x, T const& y) 00053 { 00054 return (x < y) ? x : y ; 00055 } 00056 00057 template <class T> inline T MAX (T const& x, T const& y) 00058 { 00059 return (x > y) ? x : y ; 00060 } 00061 00062 // -------------------------------------------------------------------------------------- 00063 00064 std::string getID (const char *s) 00065 { 00066 std::string id ; 00067 if (s == 0) return id ; 00068 00069 while (*s != 0) 00070 { 00071 if (*s > 32) id.push_back(*s) ; 00072 s++ ; 00073 } 00074 return id ; 00075 } 00076 00077 // -------------------------------------------------------------------------------------- 00078 00079 static bool check_tag (XMLNode* node, const char* tag) 00080 { 00081 if (node == 0) 00082 { 00083 return false ; 00084 } 00085 else if (strcmp (node->GetName(), tag) != 0) 00086 { 00087 return false ; 00088 } 00089 return true ; 00090 } 00091 00092 // -------------------------------------------------------------------------------------- 00093 /* 00094 read a vector of double values 00095 input may be coded as text or as separated child items 00096 names of items and optional attributes are ignored 00097 */ 00098 00099 static bool is_whitespace (const char *s) 00100 { 00101 return (*s != 0 && *s <= ' ') ; 00102 } 00103 00104 static bool is_separator (const char *s) 00105 { 00106 return *s != 0 && (*s <= ' ' || *s == ',' || *s == ';') ; 00107 } 00108 00109 static bool get_values (XMLNode* node, Spectrum& data) 00110 { 00111 assert (data.size() == 18) ; 00112 00113 const char*s = node->GetText() ; 00114 if (s != 0) 00115 { 00116 while (is_whitespace(s)) s++ ; 00117 } 00118 00119 if (s != 0 && strlen(s) > 0) 00120 { 00121 for (int unsigned i = 0 ; i < 18 ; i++) 00122 { 00123 if (*s == 0) return false ; 00124 data[i] = strtod (s, (char**) &s) ; 00125 while (is_separator(s)) s++ ; 00126 } 00127 } 00128 else 00129 { 00130 node = node->GetFirstChild() ; 00131 for (int unsigned i = 0 ; i < 18 ; i++) 00132 { 00133 s = node->GetText() ; 00134 if (*s == 0) return false ; 00135 data[i] = strtod (s, (char**) &s) ; 00136 node = node->GetNextEntity(); 00137 } 00138 } 00139 return true ; 00140 } 00141 00142 // -------------------------------------------------------------------------------------- 00143 00144 int RailwayDatabase::LoadFile (const char* fileName, bool _trace) 00145 { 00146 trace_debug = _trace ; 00147 error_code = 0 ; 00148 00149 Printf ("Parse file <%s> \n", fileName) ; 00150 00151 XMLFileLoader cfg ; 00152 bool ok = cfg.ParseFile (fileName) ; 00153 if (!ok) 00154 { 00155 Printf (".ERROR:%s is not a valid XML file \n", fileName) ; 00156 return (error_code = ERROR_XML_PARSER) ; 00157 } 00158 00159 XMLNode* root = cfg.GetRoot() ; 00160 if (! check_tag (root, "train_data")) 00161 { 00162 Printf (".ERROR: %s is not a valid configuration file \n", fileName) ; 00163 return (error_code = ERROR_XML_SCHEMA) ; 00164 } 00165 00166 XMLNode* child = root->GetFirstChild() ; 00167 while (child) 00168 { 00169 Printf ("Parse section <%s> \n", child->GetName()) ; 00170 00171 if (check_tag (child, "unit")) 00172 { 00173 ParseUnit (child) ; 00174 } 00175 else if (check_tag (child, "train")) 00176 { 00177 ParseTrain (child) ; 00178 } 00179 else if (check_tag (child, "source")) 00180 { 00181 ParseSource (child) ; 00182 } 00183 else 00184 { 00185 Printf (".WARNING: tag <%s> ignored \n", child->GetName()) ; 00186 } 00187 child = child->GetNextEntity() ; 00188 } 00189 00190 UnitMap::iterator unit ; 00191 for (unit = unit_map.begin() ; unit != unit_map.end() ; ++unit) 00192 { 00193 for (unsigned int i = 0 ; i < unit->second.source.size() ; i++) 00194 { 00195 SourceMap::iterator source = source_map.find (unit->second.source[i].ref) ; 00196 if (source == source_map.end()) 00197 { 00198 Printf ("error : unit (%s) uses undefined source (%s) \n", 00199 unit->first.c_str(), unit->second.source[i].ref.c_str()) ; 00200 } 00201 } 00202 } 00203 00204 TrainMap::iterator train ; 00205 for (train = train_map.begin() ; train != train_map.end() ; ++train) 00206 { 00207 for (unsigned int i = 0 ; i < train->second.unit.size() ; i++) 00208 { 00209 UnitMap::iterator unit = unit_map.find (train->second.unit[i].ref) ; 00210 if (unit == unit_map.end()) 00211 { 00212 Printf ("error : train (%s) uses undefined unit (%s) \n", 00213 train->first.c_str(), train->second.unit[i].ref.c_str()) ; 00214 } 00215 } 00216 } 00217 00218 return error_code ; 00219 } 00220 00221 // -------------------------------------------------------------------------------------- 00222 00223 RailwaySource const* RailwayDatabase::getSource (IDREF ref) 00224 { 00225 SourceMap::const_iterator source = source_map.find (ref) ; 00226 if (source == source_map.end()) return 0 ; 00227 return &source->second ; 00228 } 00229 00230 // -------------------------------------------------------------------------------------- 00231 00232 RailwayUnit const* RailwayDatabase::getUnit (IDREF ref) 00233 { 00234 UnitMap::const_iterator unit = unit_map.find (ref) ; 00235 if (unit == unit_map.end()) return 0 ; 00236 return &unit->second ; 00237 } 00238 00239 // -------------------------------------------------------------------------------------- 00240 00241 RailwayTrain const* RailwayDatabase::getTrain (IDREF ref) 00242 { 00243 TrainMap::const_iterator train = train_map.find (ref) ; 00244 if (train == train_map.end()) return 0 ; 00245 return &train->second ; 00246 } 00247 00248 // -------------------------------------------------------------------------------------- 00249 00250 bool RailwayDatabase::ParseUnit (XMLNode* item) 00251 { 00252 IDREF id = getID (item->GetAttribute("id")) ; 00253 if (id.length() == 0) 00254 { 00255 Printf (".WARNING: missing ID, <unit> ignored \n") ; 00256 return false ; 00257 } 00258 00259 RailwayUnit unit ; 00260 00261 unit.cref = 1 ; 00262 unit.length = 20 ; 00263 unit.vmax = 100 ; 00264 00265 unit.part_of_train = getID(item->GetAttribute("part")) == "true" ; 00266 00267 XMLNode* child = item->GetFirstChild() ; 00268 while (child) 00269 { 00270 if (check_tag (child, "name")) 00271 { 00272 const char* s = child->GetText() ; 00273 unit.name = std::string(s) ; 00274 } 00275 else if (check_tag (child, "length")) 00276 { 00277 unit.length = atof (child->GetText()) ; 00278 } 00279 else if (check_tag (child, "image")) 00280 { 00281 unit.image = getID (child->GetAttribute("file")) ; 00282 } 00283 else if (check_tag (child, "vmax")) 00284 { 00285 unit.vmax = atof (child->GetText()) ; 00286 } 00287 else if (check_tag (child, "refl")) 00288 { 00289 unit.cref = atof (child->GetText()) ; 00290 } 00291 else if (check_tag (child, "sources")) 00292 { 00293 XMLNode* item = child->GetFirstChild() ; 00294 while (item) 00295 { 00296 if (check_tag (item, "source")) 00297 { 00298 RailwaySourcePosition pos ; 00299 if (ParseSourcePosition (item, pos)) 00300 { 00301 unit.source.push_back (pos) ; 00302 } 00303 } 00304 else 00305 { 00306 Printf (".WARNING: tag <%s> ignored \n", item->GetName()) ; 00307 } 00308 item = item->GetNextEntity() ; 00309 } 00310 } 00311 else 00312 { 00313 Printf (".WARNING: tag <%s> ignored \n", child->GetName()) ; 00314 } 00315 child = child->GetNextEntity() ; 00316 } 00317 00318 unit_map[id] = unit ; 00319 00320 return 0 ; 00321 } 00322 00323 // -------------------------------------------------------------------------------------- 00324 00325 bool RailwayDatabase::ParseTrain (XMLNode* item) 00326 { 00327 IDREF id = getID (item->GetAttribute("id")) ; 00328 if (id.length() == 0) 00329 { 00330 Printf (".WARNING: missing ID, <source> ignored \n") ; 00331 return false ; 00332 } 00333 00334 RailwayTrain train ; 00335 00336 XMLNode* child = item->GetFirstChild() ; 00337 while (child) 00338 { 00339 if (check_tag (child, "name")) 00340 { 00341 train.name = child->GetText() ; 00342 } 00343 else if (check_tag (child, "image")) 00344 { 00345 train.image = getID (child->GetAttribute("file")) ; 00346 } 00347 else if (check_tag (child, "units")) 00348 { 00349 XMLNode* item = child->GetFirstChild() ; 00350 while (item) 00351 { 00352 if (check_tag (item, "unit")) 00353 { 00354 RailwayTrainUnit unit ; 00355 if (ParseTrainUnit(item, unit)) 00356 { 00357 train.unit.push_back (unit) ; 00358 } 00359 } 00360 else 00361 { 00362 Printf (".WARNING: tag <%s> ignored \n", item->GetName()) ; 00363 } 00364 item = item->GetNextEntity() ; 00365 } 00366 } 00367 else 00368 { 00369 Printf (".WARNING: tag <%s> ignored \n", child->GetName()) ; 00370 } 00371 child = child->GetNextEntity() ; 00372 } 00373 00374 train_map[id] = train ; 00375 00376 return true ; 00377 } 00378 00379 // -------------------------------------------------------------------------------------- 00380 00381 bool RailwayDatabase::ParseTrainUnit (XMLNode* child, RailwayTrainUnit& unit) 00382 { 00383 unit.ref = getID(child->GetAttribute("ref")) ; 00384 if (unit.ref.length() == 0) return false ; 00385 00386 const char* attr ; 00387 00388 attr = child->GetAttribute ("nb") ; 00389 if (attr) 00390 unit.nb = atoi (attr) ; 00391 else 00392 unit.nb = 0 ; 00393 00394 return (unit.nb > 0) ; 00395 } 00396 00397 // -------------------------------------------------------------------------------------- 00398 00399 bool RailwayDatabase::ParseSource (XMLNode* item) 00400 { 00401 IDREF id = getID (item->GetAttribute("id")) ; 00402 if (id.length() == 0) 00403 { 00404 Printf (".WARNING: missing ID, <source> ignored \n") ; 00405 return false ; 00406 } 00407 00408 RailwaySource source ; 00409 assert (source.Lw.size() == 18) ; 00410 00411 XMLNode* child = item->GetFirstChild() ; 00412 while (child) 00413 { 00414 if (check_tag (child, "height")) 00415 { 00416 source.height = atof (child->GetText()) ; 00417 } 00418 else if (check_tag (child, "vref")) 00419 { 00420 source.vref = atof (child->GetText()) ; 00421 } 00422 else if (check_tag (child, "slope")) 00423 { 00424 source.slope = atof (child->GetText()) ; 00425 } 00426 else if (check_tag (child, "hdir")) 00427 { 00428 IDREF model = getID (child->GetAttribute("model")) ; 00429 source.hdir_model = (model == "nmpb" ? HDIR_NMPB : HDIR_OMNI) ; 00430 } 00431 else if (check_tag (child, "vdir")) 00432 { 00433 IDREF model = getID (child->GetAttribute("model")) ; 00434 source.vdir_model = (model == "nmpb" ? VDIR_NMPB : VDIR_OMNI) ; 00435 } 00436 else if (check_tag (child, "Lw")) 00437 { 00438 assert (source.Lw.size() == 18) ; 00439 get_values (child, source.Lw) ; 00440 } 00441 else 00442 { 00443 Printf (".WARNING: tag <%s> ignored \n", child->GetName()) ; 00444 } 00445 child = child->GetNextEntity() ; 00446 } 00447 00448 source_map[id] = source ; 00449 00450 return true ; 00451 } 00452 00453 // -------------------------------------------------------------------------------------- 00454 00455 bool RailwayDatabase::ParseSourcePosition (XMLNode* child, RailwaySourcePosition& pos) 00456 { 00457 pos.ref = getID(child->GetAttribute("ref")) ; 00458 if (pos.ref.length() == 0) return false ; 00459 00460 const char* attr ; 00461 00462 attr = child->GetAttribute ("nb") ; 00463 if (attr) 00464 pos.nb = atoi (attr) ; 00465 else 00466 pos.nb = 1 ; 00467 00468 attr = child->GetAttribute ("pos") ; 00469 if (attr) 00470 pos.pos = atof (attr) ; 00471 else 00472 pos.pos = 0 ; 00473 00474 attr = child->GetAttribute ("spacing") ; 00475 if (attr) 00476 pos.spacing = atof (attr) ; 00477 else 00478 pos.spacing = 0 ; 00479 00480 return true ; 00481 } 00482 00483 // -------------------------------------------------------------------------------------- 00484 00485 int RailwayDatabase::Dump (const char* file) 00486 { 00487 FILE *fp ; 00488 if (file == 0 || strlen(file) == 0) 00489 { 00490 fp = stdout ; 00491 } 00492 else 00493 { 00494 fp = fopen (file, "wt") ; 00495 if (fp == 0) return ERROR_OPEN_FILE ; 00496 } 00497 00498 SourceMap::const_iterator source_iter ; 00499 for (source_iter = source_map.begin() ; source_iter != source_map.end() ; ++source_iter) 00500 { 00501 //RailwaySource const& source = source_iter->second ; 00502 fprintf (fp, "SOURCE: %s\n", source_iter->first.c_str()) ; 00503 } 00504 00505 UnitMap::const_iterator unit_iter ; 00506 for (unit_iter = unit_map.begin() ; unit_iter != unit_map.end() ; ++unit_iter) 00507 { 00508 fprintf (fp, "UNIT: %s\n", unit_iter->first.c_str()) ; 00509 } 00510 00511 TrainMap::const_iterator train_iter ; 00512 for (train_iter = train_map.begin() ; train_iter != train_map.end() ; ++train_iter) 00513 { 00514 fprintf (fp, "TRAIN: %s\n", train_iter->first.c_str()) ; 00515 } 00516 00517 if (fp != stdout) fclose (fp) ; 00518 00519 return 0 ; 00520 } 00521 00522 // -------------------------------------------------------------------------------------- 00523 00524 int RailwayDatabase::EnumEntities (EnumRailwayEntities enumProc, 00525 unsigned int include_types, 00526 void *userdata) 00527 { 00528 RailwayEntity info ; 00529 int n = 0 ; 00530 00531 if ((include_types & ENTITY_UNIT) != 0) 00532 { 00533 UnitMap::const_iterator unit_iter ; 00534 for (unit_iter = unit_map.begin() ; unit_iter != unit_map.end() ; ++unit_iter) 00535 { 00536 RailwayUnit const& unit = unit_iter->second ; 00537 if (unit.part_of_train && (include_types & ENTITY_PARTIAL) == 0) continue ; 00538 info.id = unit_iter->first.c_str() ; 00539 info.name = unit.name.c_str() ; 00540 info.image = unit.image.c_str() ; 00541 info.length = unit.length ; 00542 info.vmax = unit.vmax ; 00543 info.type = ENTITY_UNIT ; 00544 if (unit.part_of_train) info.type |= ENTITY_PARTIAL ; 00545 n++ ; 00546 if (! enumProc (info, userdata)) return n ; 00547 } 00548 } 00549 00550 if ((include_types & ENTITY_TRAIN) != 0) 00551 { 00552 TrainMap::const_iterator train_iter ; 00553 for (train_iter = train_map.begin() ; train_iter != train_map.end() ; ++train_iter) 00554 { 00555 RailwayTrain const& train = train_iter->second ; 00556 info.id = train_iter->first.c_str() ; 00557 info.name = train.name.c_str() ; 00558 info.image = train.image.c_str() ; 00559 double length = 0 ; 00560 double vmax = 999 ; 00561 for (unsigned int i = 0 ; i < train.unit.size() ; i++) 00562 { 00563 RailwayUnit const* unit = getUnit (train.unit[i].ref) ; 00564 if (unit) 00565 { 00566 length += unit->length ; 00567 vmax = MIN (vmax, unit->vmax) ; 00568 } 00569 } 00570 info.length = length ; 00571 info.vmax = vmax ; 00572 info.type = ENTITY_TRAIN ; 00573 n++ ; 00574 if (! enumProc (info, userdata)) return n ; 00575 } 00576 } 00577 00578 return n ; 00579 } 00580 00581 // -------------------------------------------------------------------------------------- 00582 00583 int RailwayDatabase::EnumSources (EnumRailwaySources enumProc, 00584 IDREF id, 00585 void* userdata, 00586 double pos_unit) 00587 { 00588 int n = 0 ; 00589 if (id.size() == 0) return n ; 00590 00591 TrainMap::const_iterator train_iter ; 00592 train_iter = train_map.find (id) ; 00593 if (train_iter != train_map.end()) 00594 { 00595 RailwayTrain const& train = train_iter->second ; 00596 for (unsigned int i = 0 ; i < train.unit.size() ; i++) 00597 { 00598 RailwayUnit const* unit = getUnit (train.unit[i].ref) ; 00599 if (unit) 00600 { 00601 for (int j = 0 ; j < train.unit[i].nb ; j++) 00602 { 00603 n += EnumSources (enumProc, train.unit[i].ref, userdata, pos_unit) ; 00604 pos_unit += unit->length ; 00605 } 00606 } 00607 } 00608 return n ; 00609 } 00610 00611 UnitMap::const_iterator unit_iter ; 00612 unit_iter = unit_map.find (id) ; 00613 if (unit_iter != unit_map.end()) 00614 { 00615 RailwayUnit const& unit = unit_iter->second ; 00616 for (unsigned int i = 0 ; i < unit.source.size() ; i++) 00617 { 00618 double pos = pos_unit + unit.source[i].pos ; 00619 int nb = unit.source[i].nb ; 00620 double spacing = unit.source[i].spacing ; 00621 RailwaySource const* source = getSource (unit.source[i].ref) ; 00622 if (source) 00623 { 00624 for (int j = 0 ; j < nb ; j++) 00625 { 00626 RailwayElementarySource info ; 00627 00628 info.id = unit.source[i].ref.c_str() ; 00629 info.pos = pos ; 00630 info.height = source->height ; 00631 info.hdir_model = source->hdir_model ; 00632 info.vdir_model = source->vdir_model ; 00633 info.vref = source->vref ; 00634 info.slope = source->slope ; 00635 info.Lw = &source->Lw[0] ; 00636 00637 if (!enumProc (info, userdata)) return n ; 00638 00639 pos += spacing ; 00640 n++ ; 00641 } 00642 } 00643 } 00644 } 00645 00646 return n ; 00647 }