NMPB08 Shared Libraries
RailwayDatabase.cpp
Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines