Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

ArMap.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ariaInternal.h"
00029 #include "ArMap.h"
00030 #include "ArFileParser.h"
00031 #include "ArArgumentBuilder.h"
00032 #include "ArLog.h"
00033 #include <ctype.h>
00034 
00035 
00036 const char *ArMap::ourInfoNames[INFO_COUNT] = 
00037 {
00038   "MetaInfo:",
00039     "TaskInfo:",
00040     "RouteInfo:",
00041   "SchedTaskInfo:",
00042   "SchedInfo:"
00043 };
00044 
00051 AREXPORT ArMap::ArMap(const char *baseDirectory, bool addToGlobalConfig,
00052               const char *configSection, const char *configParam,
00053               const char *configDesc, bool ignoreEmptyFileName) :
00054   myNumInfos(INFO_COUNT), // Consider adding this to the ctor so subclasses could increase...
00055   my2DMapCB(this, &ArMap::handle2DMap),
00056   myMinPosCB(this, &ArMap::handleMinPos),
00057   myMaxPosCB(this, &ArMap::handleMaxPos),
00058   myNumPointsCB(this, &ArMap::handleNumPoints),
00059   myLineMinPosCB(this, &ArMap::handleLineMinPos),
00060   myLineMaxPosCB(this, &ArMap::handleLineMaxPos),
00061   myNumLinesCB(this, &ArMap::handleNumLines),
00062   myResolutionCB(this, &ArMap::handleResolution),
00063   myMapObjectCB(this, &ArMap::handleMapObject),
00064   myMapInfoCB(this, &ArMap::handleMapInfo),
00065   myInfoCBArray(),
00069   myDataCB(this, &ArMap::handleData),
00070   myLinesCB(this, &ArMap::handleLines),
00071   myPointCB(this, &ArMap::handlePoint),
00072   myLineCB(this, &ArMap::handleLine),
00073   myProcessFileCB(this, &ArMap::processFile)
00074 {
00075   // Allocate the arrays in which to store data for the Info lines
00076   myLoadingInfoArray = new std::list<ArArgumentBuilder *>[myNumInfos];
00077   myInfoArray = new std::list<ArArgumentBuilder *> [myNumInfos];
00078   myInfoChangedArray = new ArTime[myNumInfos];
00079   myMapChangedInfoArray = new ArTime[myNumInfos];
00080   myInfoCBArray = new ArRetFunctor2C<bool, ArMap, ArArgumentBuilder *, int> *[myNumInfos];
00081   myResolution = -1;
00082 
00083   // Create the callbacks for the Info lines
00084   for (int i = 0; i < myNumInfos; i++) {
00085     myInfoCBArray[i] = new ArRetFunctor2C<bool, ArMap, ArArgumentBuilder *, int>
00086                                (this,
00087                                 &ArMap::handleInfo,
00088                                 NULL, i);
00089   }
00090 
00091   myProcessFileCB.setName("ArMap");
00092   myMapChangedLogLevel = ArLog::Verbose;
00093   myConfigParam = configParam;
00094   myIgnoreEmptyFileName = ignoreEmptyFileName;
00095 
00096 #ifndef ARINTERFACE
00097   if (addToGlobalConfig)
00098   {
00099     myConfigMapName[0] = '\0';
00100     myConfigProcessedBefore = false;
00101     
00102     const char *displayHint = "RobotFile:Map Files (*.map)|*.map";
00103 
00104     Aria::getConfig()->addParam(ArConfigArg(configParam, 
00105                                             myConfigMapName, 
00106                                                       configDesc,
00107                                                       sizeof(myConfigMapName)), 
00108                                         configSection, 
00109                                         ArPriority::IMPORTANT,
00110                                 displayHint);
00111     Aria::getConfig()->addProcessFileWithErrorCB(&myProcessFileCB, 100);
00112   }
00113 #endif //ARINTERFACE
00114   myLoadingParser = NULL;
00115   setBaseDirectory(baseDirectory);
00116   reset();
00117 
00118 }
00119 
00120 AREXPORT ArMap::~ArMap()
00121 {
00122   /*
00123   delete [] myLoadingInfoArray;
00124   delete [] myInfoArray;
00125   delete [] myInfoChangedArray;
00126   delete [] myMapChangedInfoArray;
00127   for (int i = 0; i < myNumInfos; i++) {
00128     delete myInfoCBArray[i];
00129   }
00130   delete [] myInfoCBArray;
00131   */
00132 
00133 
00134   ArUtil::deleteSet(myMapObjects.begin(), myMapObjects.end());
00135   ArUtil::deleteSet(myMapInfo.begin(), myMapInfo.end());
00136   if(myLoadingParser) delete myLoadingParser;
00137 }
00138 
00139 bool ArMap::processFile(char *errorBuffer, size_t errorBufferLen)
00140 {
00141 
00142   ArUtil::fixSlashes(myConfigMapName, MAX_MAP_NAME_LENGTH);
00143 
00144   struct stat mapFileStat;
00145   stat(myConfigMapName, &mapFileStat);
00146   
00147   // If file name is empty, clear out all current information
00148   if (myIgnoreEmptyFileName && myConfigMapName[0] == '\0')
00149   {
00150     ArLog::log(ArLog::Normal, "Using an empty map since empty map file name");
00151     lock();
00152     reset();
00153     myFileName = "";
00154     setMapObjects(NULL);
00155     setPoints(NULL);
00156     setLines(NULL);
00157     setMapInfo(NULL);
00158     // Clear all of the Info information
00159     for (int i = 0; i < myNumInfos; i++) {
00160       setInfo(i, NULL);
00161     }
00162 
00163     myResolution = -1;
00164     mapChanged();
00165     unlock();
00166     return true;
00167   }
00168 
00169   // Reload map if this is the first time, or we need to use a new file, or the
00170   // existing file has changed.
00171   if (!myConfigProcessedBefore || 
00172       ArUtil::strcmp(myConfigMapName, myFileName.c_str()) != 0 ||
00173       mapFileStat.st_mtime != myReadFileStat.st_mtime)
00174   {
00175     ArLog::log(ArLog::Verbose, "ArMap: LOADINGMAP because configProcessedBefore %d myFileName \"%s\" configFileName \"%s\" mapFileTime %lu readFileTime %lu (Diff %ld)", 
00176            myConfigProcessedBefore, myFileName.c_str(), myConfigMapName,
00177            mapFileStat.st_mtime, myReadFileStat.st_mtime, mapFileStat.st_mtime - myReadFileStat.st_mtime);
00178     myConfigProcessedBefore = true; 
00179 
00180     if(readFile(myConfigMapName, errorBuffer, errorBufferLen))
00181     {
00182       return true;
00183     }
00184     else
00185     {
00186       ArLog::log(ArLog::Terse, "ArMap: failed to read new map file \"%s\": %s.", myConfigMapName, errorBuffer);
00187       // TODO: if !myConfigProcessedBefore then the intial map file name was
00188       // invalid; should we now clear the map file name in ArConfig?
00189       return false;
00190     }
00191   }
00192 
00193   // Otherwise, nothing to do.
00194   return true;
00195 }
00196 
00197 AREXPORT const char *ArMap::getBaseDirectory(void) const
00198 {
00199   return myBaseDirectory.c_str();
00200 }
00201 
00202 AREXPORT const char *ArMap::getFileName(void) const 
00203 {
00204   return myFileName.c_str();
00205 }
00206 
00207 AREXPORT void ArMap::setBaseDirectory(const char *baseDirectory)
00208 {
00209   if (baseDirectory != NULL && strlen(baseDirectory) > 0)
00210     myBaseDirectory = baseDirectory;
00211   else
00212     myBaseDirectory = "";  
00213   if (myLoadingParser != NULL)
00214     myLoadingParser->setBaseDirectory(myBaseDirectory.c_str());
00215 }
00216 
00217 AREXPORT std::list<ArArgumentBuilder *> *ArMap::getInfo(int infoType) 
00218 { 
00219     if ((infoType >= 0) && (infoType < myNumInfos) && (myInfoArray != NULL)) {
00220         return &myInfoArray[infoType]; 
00221     }
00222     else {
00223         return NULL;
00224     }
00225 }
00226 
00232 AREXPORT void ArMap::addMapChangedCB(ArFunctor *functor, ArListPos::Pos position)
00233 {
00234   if (position == ArListPos::FIRST)
00235     myMapChangedCBList.push_front(functor);
00236   else if (position == ArListPos::LAST)
00237     myMapChangedCBList.push_back(functor);
00238   else
00239     ArLog::log(ArLog::Terse, 
00240            "ArMap::addMapChangedCB: Invalid position.");
00241 }
00242 
00243 AREXPORT void ArMap::remMapChangedCB(ArFunctor *functor)
00244 {
00245   myMapChangedCBList.remove(functor);
00246 }
00247 
00248 
00257 AREXPORT void ArMap::addPreMapChangedCB(ArFunctor *functor, ArListPos::Pos position)
00258 {
00259   if (position == ArListPos::FIRST)
00260     myPreMapChangedCBList.push_front(functor);
00261   else if (position == ArListPos::LAST)
00262     myPreMapChangedCBList.push_back(functor);
00263   else
00264     ArLog::log(ArLog::Terse, 
00265            "ArMap::addPreMapChangedCB: Invalid position.");
00266 }
00267 
00268 AREXPORT void ArMap::remPreMapChangedCB(ArFunctor *functor)
00269 {
00270   myPreMapChangedCBList.remove(functor);
00271 }
00272 
00273 AREXPORT bool ArMap::reset(void)
00274 {
00275 
00276   // clear out the reading in copy
00277 
00278   // get rid of the old parser (cleaner than trying to clear it up)
00279   if (myLoadingParser != NULL)
00280     delete myLoadingParser;
00281   myLoadingParser = new ArFileParser;
00282   myLoadingParser->setBaseDirectory(myBaseDirectory.c_str());
00283   myLoadingGotMaxPos = false;
00284   myLoadingGotMinPos = false;
00285   myLoadingGot2DMap = false;
00286   myLoadingNumPoints = -1;
00287   myLoadingResolution = -1;
00288   myLoadingPointsRead = 0;
00289   myLoadingLinesRead = 0;
00290   myLoadingMax.setX(INT_MIN);
00291   myLoadingMax.setY(INT_MIN);
00292   myLoadingMin.setX(INT_MAX);
00293   myLoadingMin.setY(INT_MAX);
00294   ArUtil::deleteSet(myLoadingMapObjects.begin(), myLoadingMapObjects.end());
00295   myLoadingMapObjects.clear();
00296   myLoadingPoints.clear();
00297   myLoadingLines.clear();
00298   ArUtil::deleteSet(myLoadingMapInfo.begin(), myLoadingMapInfo.end());
00299   myLoadingMapInfo.clear();
00300 
00301   for (int i = 0; i < myNumInfos; i++) {
00302       
00303     ArUtil::deleteSet(myLoadingInfoArray[i].begin(), myLoadingInfoArray[i].end());
00304     myLoadingInfoArray[i].clear();
00305   }
00306 /***
00307   ArUtil::deleteSet(myLoadingRouteInfo.begin(), myLoadingRouteInfo.end());
00308   myLoadingRouteInfo.clear();
00309 ***/
00310 
00311   // ??
00312   myLoadingDataStarted = false;
00313   myLoadingLinesAndDataStarted = false;
00314 
00315   if (!myLoadingParser->addHandler("2D-Map", &my2DMapCB))
00316   {
00317     ArLog::log(ArLog::Terse, "ArMap::reset: could not add 2D-Map");
00318     return false;
00319   }
00320 
00321   return true;
00322 }
00323 
00324 bool ArMap::handle2DMap(ArArgumentBuilder *arg)
00325 {
00326   ArLog::log(ArLog::Verbose, "ArMap: got 2D-Map");
00327   // make sure we can add all our handlers
00328   if (!myLoadingParser->addHandler("MinPos:", &myMinPosCB) ||
00329       !myLoadingParser->addHandler("MaxPos:", &myMaxPosCB) ||
00330       !myLoadingParser->addHandler("NumPoints:", &myNumPointsCB) ||
00331       !myLoadingParser->addHandler("LineMinPos:", &myMinPosCB) ||
00332       !myLoadingParser->addHandler("LineMaxPos:", &myMaxPosCB) ||
00333       !myLoadingParser->addHandler("NumLines:", &myNumPointsCB) ||
00334       !myLoadingParser->addHandler("Resolution:", &myResolutionCB) ||
00335       !myLoadingParser->addHandler("Cairn:", &myMapObjectCB) ||
00336       !myLoadingParser->addHandler("MapInfo:", &myMapInfoCB) ||
00337 
00338       // !myLoadingParser->addHandler("RouteInfo:", &myRouteInfoCB) ||
00339       !myLoadingParser->addHandler("LINES", &myLinesCB) ||
00340       !myLoadingParser->addHandler("DATA", &myDataCB))      
00341   {
00342     ArLog::log(ArLog::Terse, "ArMap::handle2DMap: could not add handlers");
00343     return false;
00344   }  
00345 
00346   for (int i = 0; i < myNumInfos; i++) {
00347     if (!myLoadingParser->addHandler(getInfoName(i), 
00348                                                      myInfoCBArray[i])) {
00349       ArLog::log(ArLog::Terse, "ArMap::handle2DMap: could not add info handlers");
00350       return false;
00351     }
00352   }
00353 
00354   // we added 'em all, remove the 2D-Map handler and return
00355   myLoadingParser->remHandler("2D-Map");
00356   myLoadingGot2DMap = true;
00357   return true;
00358   
00359 }
00360 
00361 bool ArMap::handleMinPos(ArArgumentBuilder *arg)
00362 {
00363   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00364   {
00365     ArLog::log(ArLog::Terse, 
00366            "ArMap: 'MinPos:' bad arguments, should be two integers x y");
00367     return false;
00368   }
00369   myLoadingMinFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00370   myLoadingGotMinPos = true;
00371   return true;
00372 }
00373 
00374 bool ArMap::handleMaxPos(ArArgumentBuilder *arg)
00375 {
00376   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00377   {
00378     ArLog::log(ArLog::Terse, 
00379            "ArMap: 'MaxPos:' bad arguments, should be two integers x y");
00380     return false;
00381   }
00382   myLoadingMaxFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00383   myLoadingGotMaxPos = true;
00384   return true;
00385 }
00386 
00387 bool ArMap::handleNumPoints(ArArgumentBuilder *arg)
00388 {
00389   if (arg->getArgc() != 1 || !arg->isArgInt(0))
00390   {
00391     ArLog::log(ArLog::Terse, 
00392            "ArMap: 'NumPoints:' bad argument, should be one integer (number of data points)");
00393     return false;
00394   }
00395   myLoadingNumPoints = arg->getArgInt(0);
00396 
00397   if (myLoadingNumPoints >= 0) {
00398       myLoadingPoints.reserve(myLoadingNumPoints);
00399   }
00400 
00401   return true;
00402 }
00403 
00404 bool ArMap::handleLineMinPos(ArArgumentBuilder *arg)
00405 {
00406   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00407   {
00408     ArLog::log(ArLog::Terse, 
00409        "ArMap: 'LineMinPos:' bad arguments, should be two integers x y");
00410     return false;
00411   }
00412   myLoadingLineMinFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00413   myLoadingGotLineMinPos = true;
00414   return true;
00415 }
00416 
00417 bool ArMap::handleLineMaxPos(ArArgumentBuilder *arg)
00418 {
00419   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00420   {
00421     ArLog::log(ArLog::Terse, 
00422        "ArMap: 'LineMaxPos:' bad arguments, should be two integers x y");
00423     return false;
00424   }
00425   myLoadingLineMaxFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00426   myLoadingGotLineMaxPos = true;
00427   return true;
00428 }
00429 
00430 bool ArMap::handleNumLines(ArArgumentBuilder *arg)
00431 {
00432   if (arg->getArgc() != 1 || !arg->isArgInt(0))
00433   {
00434     ArLog::log(ArLog::Terse, 
00435            "ArMap: 'NumPoints:' bad argument, should be one integer (number of data points)");
00436     return false;
00437   }
00438   myLoadingNumLines = arg->getArgInt(0);
00439 
00440   if (myLoadingNumLines >= 0) {
00441       myLoadingLines.reserve(myLoadingNumPoints);
00442   }
00443 
00444   return true;
00445 }
00446 
00447 bool ArMap::handleResolution(ArArgumentBuilder *arg)
00448 {
00449   if (arg->getArgc() != 1 || !arg->isArgInt(0))
00450   {
00451     ArLog::log(ArLog::Terse, 
00452            "ArMap: 'Resolution:' bad argument, should be one integer (resolution in mm)");
00453     return false;
00454   }
00455   myLoadingResolution = arg->getArgInt(0);
00456   return true;
00457 }
00458 
00459 bool ArMap::handleMapObject(ArArgumentBuilder *arg)
00460 {
00461   ArMapObject *object;
00462   ArPose pose;
00463   bool hasFromTo = false;
00464   ArPose fromPose;
00465   ArPose toPose;
00466 
00467   if (arg->getArgc() < 7 || !arg->isArgDouble(1) || !arg->isArgDouble(2) ||
00468       !arg->isArgDouble(3))
00469   {
00470     ArLog::log(ArLog::Terse, 
00471            "ArMap: 'Cairn:' bad format '%s'", arg->getFullString());
00472     return false;
00473   }
00474   // this next block strips out the end quotes of the name
00475   /*
00476   char *nameBuffer;
00477   const char *namePtr;
00478   size_t nameLen;
00479   namePtr = arg->getArg(6);
00480   nameLen = strlen(namePtr);
00481   nameBuffer = new char[strlen(arg->getArg(6)) + 1];
00482   strncpy(nameBuffer, &namePtr[1], nameLen - 1);
00483   nameBuffer[nameLen - 1] = '\0';
00484   */
00485   arg->compressQuoted();
00486 
00487   
00488   size_t fileLen = strlen(arg->getArg(4)) + 1;
00489   char *fileBuffer = new char[fileLen];
00490   
00491   //char *fileBuffer = NULL;
00492 /***/
00493   if (!ArUtil::stripQuotes(fileBuffer, arg->getArg(4), fileLen))
00494   {
00495     ArLog::log(ArLog::Terse, 
00496            "ArMap: 'Cairn:' couldn't strip quotes from fileName '%s'", 
00497            arg->getArg(4));
00498     delete[] fileBuffer;
00499     return false;
00500   }
00501 
00502 
00503   size_t nameLen = strlen(arg->getArg(6)) + 1;
00504   char *nameBuffer = new char[nameLen];
00505   if (!ArUtil::stripQuotes(nameBuffer, arg->getArg(6), nameLen))
00506   {
00507     ArLog::log(ArLog::Terse, 
00508            "ArMap: 'Cairn:' couldn't strip quotes from name '%s'", 
00509            arg->getArg(6));
00510     delete[] fileBuffer;
00511     delete[] nameBuffer;
00512     return false;
00513   }
00514   
00515   if (arg->getArgc() == 11 && arg->isArgInt(7) && arg->isArgInt(8) && 
00516       arg->isArgInt(9) && arg->isArgInt(10))
00517   {
00518     hasFromTo = true;
00519     fromPose.setPose(arg->getArgInt(7), arg->getArgInt(8));
00520     toPose.setPose(arg->getArgInt(9), arg->getArgInt(10));
00521              
00522   }
00523   pose.setPose(arg->getArgDouble(1), arg->getArgDouble(2), 
00524            arg->getArgDouble(3));
00525   object = new ArMapObject(arg->getArg(0), pose, fileBuffer,
00526                arg->getArg(5), nameBuffer, hasFromTo, fromPose, 
00527                toPose);
00528   delete [] fileBuffer;
00529   delete [] nameBuffer;
00530   myLoadingMapObjects.push_back(object);
00531   //object->log();
00532   //arg->log();
00533   return true;
00534 }
00535 
00536 bool ArMap::handleMapInfo(ArArgumentBuilder *arg)
00537 {
00538   ArArgumentBuilder *mapInfo = NULL;
00539   mapInfo = new ArArgumentBuilder(*arg);
00540   myLoadingMapInfo.push_back(mapInfo);
00541   return true;
00542 }
00543 
00544 bool ArMap::handleInfo(ArArgumentBuilder *arg, int info) 
00545 {
00546   arg->compressQuoted();
00547   
00548   if ((info < 0) || (info >= myNumInfos)) {
00549     return false;
00550   }
00551   ArArgumentBuilder *infoBuilder = new ArArgumentBuilder(*arg);
00552   myLoadingInfoArray[info].push_back(infoBuilder);
00553 
00554   ArLog::log(ArLog::Verbose,
00555              "ArMap::handleInfo(%i) = %s",
00556              info, 
00557              ((arg != NULL) ? arg->getFullString() : "NULL"));
00558 
00559   return true;
00560 }
00561 
00572 bool ArMap::handleData(ArArgumentBuilder *arg)
00573 {
00574   // make sure we got all the important data
00575   if (!myLoadingGotMinPos || !myLoadingGotMaxPos || myLoadingNumPoints == -1)
00576   {
00577     ArLog::log(ArLog::Verbose, "ArMap: got to DATA but didn't get all the important information, using our own anyways, but something is probably wrong");
00578   }
00579   // get rid of the old handlers
00580   myLoadingParser->remHandler(&myMinPosCB);
00581   myLoadingParser->remHandler(&myMaxPosCB);
00582   myLoadingParser->remHandler(&myNumPointsCB);
00583   myLoadingParser->remHandler(&myLineMinPosCB);
00584   myLoadingParser->remHandler(&myLineMaxPosCB);
00585   myLoadingParser->remHandler(&myNumLinesCB);
00586   myLoadingParser->remHandler(&myResolutionCB);
00587   myLoadingParser->remHandler(&myMapObjectCB);
00588   myLoadingParser->remHandler(&myMapInfoCB);
00589 
00590   for (int i = 0; i < myNumInfos; i++) {
00591       myLoadingParser->remHandler(myInfoCBArray[i]);
00592   }
00593   // myLoadingParser->remHandler(&myRouteInfoCB);
00594   myLoadingParser->remHandler(&myResolutionCB);
00595 
00596   //myLoadingParser->remHandler(&myDataCB);
00597   //myLoadingParser->remHandler(&myLinesCB);
00598   myLoadingParser->remHandler(&myLineCB);
00599   myLoadingParser->remHandler(&myPointCB);
00600 
00601   // now we add our handler for the points
00602   if (!myLoadingParser->addHandler(NULL, &myPointCB))
00603   {
00604     ArLog::log(ArLog::Terse, "ArMap: could not add handler for data points");
00605     return false;
00606   }
00607   myLoadingDataStarted = true;
00608   myLoadingLinesAndDataStarted = false;
00609   return false;
00610 
00611   // return true;
00612 }
00613 
00614 bool ArMap::handleLines(ArArgumentBuilder *arg)
00615 {
00616   // make sure we got all the important data
00617   if (!myLoadingGotMinPos || !myLoadingGotMaxPos || myLoadingNumPoints == -1)
00618   {
00619     ArLog::log(ArLog::Verbose, "ArMap: got to DATA but didn't get all the important information, using our own anyways, but something is probably wrong");
00620   }
00621   // get rid of the old handlers
00622   myLoadingParser->remHandler(&myMinPosCB);
00623   myLoadingParser->remHandler(&myMaxPosCB);
00624   myLoadingParser->remHandler(&myNumPointsCB);
00625   myLoadingParser->remHandler(&myLineMinPosCB);
00626   myLoadingParser->remHandler(&myLineMaxPosCB);
00627   myLoadingParser->remHandler(&myNumLinesCB);
00628   myLoadingParser->remHandler(&myResolutionCB);
00629   myLoadingParser->remHandler(&myMapObjectCB);
00630   myLoadingParser->remHandler(&myResolutionCB);
00631 
00632   for (int i = 0; i < myNumInfos; i++) {
00633       myLoadingParser->remHandler(myInfoCBArray[i]);
00634   }
00635 
00636   // Don't remove the data cb because the points follow...
00637   //myLoadingParser->remHandler(&myDataCB);
00638   //myLoadingParser->remHandler(&myLinesCB); 
00639 
00640   myLoadingParser->remHandler(&myPointCB);  
00641   myLoadingParser->remHandler(&myLineCB);  
00642 
00643   // now we add our handler for the points
00644   if (!myLoadingParser->addHandler(NULL, &myLineCB))
00645   {
00646     ArLog::log(ArLog::Terse, "ArMap: could not add handler for data lines");
00647     return false;
00648   }
00649   myLoadingLinesAndDataStarted = true;
00650   myLoadingDataStarted = false;
00651   return false;
00652 
00653   // return true;
00654 }
00655 
00656 bool ArMap::handlePoint(ArArgumentBuilder *arg)
00657 {
00658   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00659   {
00660     ArLog::log(ArLog::Terse, 
00661        "ArMap::handlePoint: map point wrong, should be x and y int coords (in mm) but is %s", arg->getFullString());
00662     return false;
00663   }
00664 
00665   int x = arg->getArgInt(0);
00666   int y = arg->getArgInt(1);
00667 
00668   loadDataPoint(x, y);
00669   return true;
00670 
00671 }
00672 
00673 
00674 bool ArMap::handleLine(ArArgumentBuilder *arg)
00675 {
00676   if (arg->getArgc() != 4 || !arg->isArgInt(0) || !arg->isArgInt(1) || 
00677       !arg->isArgInt(2) || !arg->isArgInt(3))
00678   {
00679     ArLog::log(ArLog::Verbose, 
00680        "ArMap::handleLine: line wrong, should be 2 x, y points (in mm) but is %s", arg->getFullString());
00681     return false;
00682   }
00683 
00684   int x1 = arg->getArgInt(0);
00685   int y1 = arg->getArgInt(1);
00686   int x2 = arg->getArgInt(2);
00687   int y2 = arg->getArgInt(3);
00688 
00689   loadLineSegment(x1, y1, x2, y2);
00690   return true;
00691 
00692 }
00693 
00694 
00695 AREXPORT ArTime ArMap::getInfoChanged(int infoType)
00696 {
00697   if ((infoType >= 0) && (infoType < myNumInfos) && (myInfoChangedArray != NULL)) {
00698     return myInfoChangedArray[infoType]; 
00699   }
00700   else { // invalid info type
00701     // ArTime is initialized to now.  Set the secs and msecs to 0 for default value.
00702     ArTime defaultTime;
00703     defaultTime.setSec(0);
00704     defaultTime.setMSec(0);
00705     return defaultTime;
00706   }
00707 }
00708 
00715 AREXPORT void ArMap::setMapObjects(const std::list<ArMapObject *> *mapObjects)
00716 {
00717   std::list<ArMapObject *>::const_iterator it;
00718   ArUtil::deleteSet(myMapObjects.begin(), myMapObjects.end());
00719   myMapObjects.clear();
00720   myMapObjectsChanged.setToNow();
00721   if (mapObjects == NULL)
00722     return;
00723   for (it = mapObjects->begin(); it != mapObjects->end(); it++)
00724   {
00725     myMapObjects.push_back(new ArMapObject(*(*it)));
00726   }
00727 }
00728 
00735 AREXPORT void ArMap::setPoints(const std::vector<ArPose> *points)
00736 {
00737   std::vector<ArPose>::const_iterator it;
00738   ArPose pose;
00739   /***/
00740   myPoints.clear();
00741   myMax.setX(INT_MIN);
00742   myMax.setY(INT_MIN);
00743   myMin.setX(INT_MAX);
00744   myMin.setY(INT_MAX);
00745   myNumPoints = 0;
00746 
00747 
00748   myPointsChanged.setToNow();
00749   if (points == NULL) {
00750     return;
00751   }
00752 
00753 
00754   myPoints.reserve(points->size());
00755 
00756   for (it = points->begin(); it != points->end(); it++)
00757   {
00758     pose = (*it);
00759     if (pose.getX() > myMax.getX())
00760       myMax.setX(pose.getX());
00761     if (pose.getY() > myMax.getY())
00762       myMax.setY(pose.getY());
00763 
00764     if (pose.getX() < myMin.getX())
00765       myMin.setX(pose.getX());
00766     if (pose.getY() < myMin.getY())
00767       myMin.setY(pose.getY());
00768     
00769     myNumPoints++;
00770     myPoints.push_back(pose);
00771   }
00772   
00773 
00774 }
00775 
00776 
00782 AREXPORT void ArMap::setLines(const std::vector<ArLineSegment> *lines)
00783 {
00784   std::vector<ArLineSegment>::const_iterator it;
00785   ArLineSegment line;
00786   /***/
00787   myLines.clear();
00788   myLineMax.setX(INT_MIN);
00789   myLineMax.setY(INT_MIN);
00790   myLineMin.setX(INT_MAX);
00791   myLineMin.setY(INT_MAX);
00792   myNumLines = 0;
00793 
00794 
00795   myLinesChanged.setToNow();
00796   if (lines == NULL) {
00797     return;
00798   }
00799 
00800 
00801   myLines.reserve(lines->size());
00802 
00803   for (it = lines->begin(); it != lines->end(); it++)
00804   {
00805     line = (*it);
00806 
00807 
00808     if (line.getX1() > myLineMax.getX())
00809       myLineMax.setX(line.getX1());
00810     if (line.getY1() > myLineMax.getY())
00811       myLineMax.setY(line.getY1());
00812 
00813     if (line.getX1() < myLineMin.getX())
00814       myLineMin.setX(line.getX1());
00815     if (line.getY1() < myLineMin.getY())
00816       myLineMin.setY(line.getY1());
00817 
00818 
00819     if (line.getX2() > myLineMax.getX())
00820       myLineMax.setX(line.getX2());
00821     if (line.getY2() > myLineMax.getY())
00822       myLineMax.setY(line.getY2());
00823 
00824     if (line.getX2() < myLineMin.getX())
00825       myLineMin.setX(line.getX2());
00826     if (line.getY2() < myLineMin.getY())
00827       myLineMin.setY(line.getY2());
00828     
00829     myNumLines++;
00830     myLines.push_back(line);
00831   }
00832   
00833 
00834 }
00835 
00842 AREXPORT void ArMap::setMapInfo(const std::list<ArArgumentBuilder *> *mapInfo)
00843 {
00844   std::list<ArArgumentBuilder *>::const_iterator it;
00845   ArUtil::deleteSet(myMapInfo.begin(), myMapInfo.end());
00846   myMapInfo.clear();
00847   myMapInfoChanged.setToNow();
00848   if (mapInfo == NULL)
00849     return;
00850   for (it = mapInfo->begin(); it != mapInfo->end(); it++)
00851   {
00852     myMapInfo.push_back(new ArArgumentBuilder(*(*it)));
00853   }  
00854 }
00855 
00856 AREXPORT bool ArMap::setInfo(int infoType,
00857                              const std::list<ArArgumentBuilder *> *infoList)
00858 {
00859   if ((infoType < 0) || (infoType >= myNumInfos)) {
00860     return false;
00861   }
00862   // Should never happen, but check just in case...
00863   if ((myInfoArray == NULL) || (myInfoChangedArray == NULL)) {
00864       return false;
00865   }
00866   std::list<ArArgumentBuilder *>::const_iterator it;
00867   ArUtil::deleteSet(myInfoArray[infoType].begin(), myInfoArray[infoType].end());
00868   myInfoArray[infoType].clear();
00869   myInfoChangedArray[infoType].setToNow();
00870 
00871   if (infoList == NULL)
00872     return true;
00873 
00874   for (it = infoList->begin(); it != infoList->end(); it++)
00875   {
00876     myInfoArray[infoType].push_back(new ArArgumentBuilder(*(*it)));
00877   }
00878   return true;
00879 }
00880 
00881 AREXPORT void ArMap::setResolution(int resolution)
00882 {
00883     myResolution = resolution;
00884 }
00885 
00886 
00893 /***
00894 AREXPORT void ArMap::setRouteInfo(const std::list<ArArgumentBuilder *> *routeInfo)
00895 {
00896   std::list<ArArgumentBuilder *>::const_iterator it;
00897   ArUtil::deleteSet(myRouteInfo.begin(), myRouteInfo.end());
00898   myRouteInfo.clear();
00899   myRouteInfoChanged.setToNow();
00900   if (routeInfo == NULL)
00901     return;
00902   for (it = routeInfo->begin(); it != routeInfo->end(); it++)
00903   {
00904     myRouteInfo.push_back(new ArArgumentBuilder(*(*it)));
00905   }  
00906 }
00907 **/
00908 
00919 AREXPORT bool ArMap::readFile(const char *fileName, 
00920                   char *errorBuffer, size_t errorBufferLen)
00921 {
00922  
00923   lock();
00924   stat(fileName, &myReadFileStat);
00925   FILE *file;
00926 
00927   char line[10000];
00928   std::string realFileName;
00929   if (fileName[0] == '/' || fileName[0] == '\\' || 
00930       fileName[0] == '.')
00931   {
00932     realFileName = fileName;
00933   }
00934   else
00935   {
00936     realFileName = myBaseDirectory;
00937     realFileName += fileName;
00938   }
00939 
00940   ArLog::log(ArLog::Verbose, "Opening file %s from fileName given %s", realFileName.c_str(), fileName);
00941     
00942   if ((file = fopen(realFileName.c_str(), "r")) == NULL)
00943   {
00944     ArLog::log(ArLog::Terse, "Cannot open file '%s'", realFileName.c_str());
00945     if (errorBuffer != NULL)
00946       snprintf(errorBuffer, errorBufferLen, 
00947            "%s invalid: cannot open file '%s'",
00948            myConfigParam.c_str(), fileName);
00949     //printf("!     %s\n", errorBuffer);
00950 
00951     unlock();
00952     return false;
00953   }
00954 
00955   if (!reset() || !myLoadingParser->parseFile(file, line, 10000, false))
00956   {
00957     
00958     if (!myLoadingDataStarted && !myLoadingLinesAndDataStarted) 
00959     {
00960       reset();
00961       if (errorBuffer != NULL)
00962     snprintf(errorBuffer, errorBufferLen, 
00963          "%s invalid: '%s' not a valid map",
00964          myConfigParam.c_str(), fileName);
00965       unlock();
00966       ArLog::log(ArLog::Terse, "Could not load map file '%s'", fileName);
00967       
00968       return false;
00969     }
00970   } // end if parse success
00971   
00972   if (!myLoadingGot2DMap)
00973   {
00974     reset();
00975     if (errorBuffer != NULL)
00976       snprintf(errorBuffer, errorBufferLen, 
00977            "%s invalid, '%s' was not a map file",
00978            myConfigParam.c_str(), fileName);
00979     
00980     unlock();
00981     ArLog::log(ArLog::Terse, 
00982            "Could not load map file '%s' it was not a 2D-map", fileName);
00983     return false;
00984   }
00985 
00986   // if we're on the lines, read until the end of lines or end of file
00987   if (myLoadingLinesAndDataStarted)
00988   {
00989     //printf("Reading lines\n");
00990     while (fgets(line, sizeof(line), file) != NULL)
00991     {
00992       if (strncasecmp(line, "DATA", strlen("DATA")) == 0)
00993       {
00994     myLoadingDataStarted = true;
00995     break;
00996       }
00997       if (!readLineSegment(line))
00998       {
00999     continue;
01000       }
01001     }
01002   }
01003 
01004   //printf("reading data\n");
01005   // read until the end of the file
01006   while (fgets(line, sizeof(line), file) != NULL)
01007   {
01008     if (!readDataPoint(line))
01009     {
01010       continue;
01011     }
01012   }
01013   
01014   fclose(file);
01015   
01016   // move the stuff over from reading to new
01017   myFileName = fileName;
01018   setMapObjects(&myLoadingMapObjects);
01019   setPoints(&myLoadingPoints);
01020   setLines(&myLoadingLines);
01021   setMapInfo(&myLoadingMapInfo);
01022   
01023   for (int i = 0; i < myNumInfos; i++) {
01024       setInfo(i, &myLoadingInfoArray[i]);
01025   }
01026   // setRouteInfo(&myLoadingRouteInfo);
01027 
01028   myResolution = myLoadingResolution;
01029   // call our callbacks
01030   ArLog::log(ArLog::Terse, "Loaded map file '%s'", fileName);
01031 
01032   reset();
01033   
01034   mapChanged();
01035   unlock();
01036   return true;
01037 }
01038 
01039 bool ArMap::readDataPoint(char *line) 
01040 {
01041   if (line == NULL) {
01042     return false;
01043   }
01044   
01045   bool isNumber = true;
01046   int firstSpace = -1;
01047   
01048   unsigned int startNum = 0;
01049   
01050   for (unsigned int i = 0; i < strlen(line); i++) {
01051     if (!isdigit(line[i]) && !(i == startNum && line[i] == '-')) {
01052       
01053       if (isspace(line[i])) {
01054     line[i] = '\0';
01055     if (firstSpace < 0) {
01056       firstSpace = i;
01057       startNum = i + 1;
01058     }
01059     else {
01060       break;
01061     }
01062       }
01063       else {
01064     isNumber = false;
01065       }
01066       break;
01067     }
01068   } // end for each
01069   
01070   int x = atoi(line);
01071   int y = atoi(&line[firstSpace + 1]);
01072   
01073   loadDataPoint(x, y);
01074 
01075   return true;
01076 
01077 } // end method readDataPoint
01078 
01079 
01080 
01081 
01082 void ArMap::loadDataPoint(double x, double y)
01083 {
01084   if (x > myLoadingMax.getX())
01085     myLoadingMax.setX(x);
01086   if (y > myLoadingMax.getY())
01087     myLoadingMax.setY(y);
01088   
01089   if (x < myLoadingMin.getX())
01090     myLoadingMin.setX(x);
01091   if (y < myLoadingMin.getY())
01092     myLoadingMin.setY(y);
01093   
01094   myLoadingPoints.push_back(ArPose(x, y));
01095   myLoadingPointsRead++;
01096   
01097 } // end method loadDataPoint
01098 
01099 
01100 bool ArMap::readLineSegment(char *line) 
01101 {
01102   if (line == NULL) {
01103     return false;
01104   }
01105   
01106   /* MPL optomize this like kathleen did above, later */
01107   ArArgumentBuilder builder;
01108   builder.add(line);
01109   
01110   if (builder.getArgc() < 4)
01111     return false;
01112 
01113   loadLineSegment(builder.getArgInt(0), builder.getArgInt(1),
01114           builder.getArgInt(2), builder.getArgInt(3));
01115 
01116   return true;
01117 
01118 } 
01119 
01120 void ArMap::loadLineSegment(double x1, double y1, double x2, double y2)
01121 {
01122   if (x1 > myLoadingLineMax.getX())
01123     myLoadingLineMax.setX(x1);
01124   if (y1 > myLoadingLineMax.getY())
01125     myLoadingLineMax.setY(y1);
01126   
01127   if (x1 < myLoadingLineMin.getX())
01128     myLoadingLineMin.setX(x1);
01129   if (y1 < myLoadingLineMin.getY())
01130     myLoadingMin.setY(y1);
01131 
01132   if (x2 > myLoadingLineMax.getX())
01133     myLoadingLineMax.setX(x2);
01134   if (y2 > myLoadingLineMax.getY())
01135     myLoadingLineMax.setY(y2);
01136   
01137   if (x2 < myLoadingLineMin.getX())
01138     myLoadingLineMin.setX(x2);
01139   if (y2 < myLoadingLineMin.getY())
01140     myLoadingMin.setY(y2);
01141   
01142   myLoadingLines.push_back(ArLineSegment(x1, y1, x2, y2));
01143   myLoadingLinesRead++;
01144   
01145 } 
01146 
01152 AREXPORT void ArMap::parsingComplete(void)
01153 {
01154   lock();
01155   setMapObjects(&myLoadingMapObjects);
01156   setPoints(&myLoadingPoints);
01157   setLines(&myLoadingLines);
01158   setMapInfo(&myLoadingMapInfo);
01159 
01160   for (int i = 0; i < myNumInfos; i++) {
01161       setInfo(i, &myLoadingInfoArray[i]);
01162   }
01163   //setRouteInfo(&myLoadingRouteInfo);
01164 
01165   myResolution = myLoadingResolution;
01166   ArLog::log(ArLog::Normal, "Loaded map from parsing");
01167   myFileName = "";
01168 
01169   reset();
01170 
01171   mapChanged();
01172   unlock();
01173 }
01174 
01175 AREXPORT void ArMap::mapChanged(void)
01176 {
01177   std::list<ArFunctor *>::iterator it;
01178 
01179   ArLog::LogLevel level = myMapChangedLogLevel;
01180   ArFunctor *functor;
01181 
01182   bool isAnyInfoChanged = false;
01183   for (int i = 0; i < myNumInfos; i++) {
01184       if (abs(myMapChangedInfoArray[i].mSecSince(myInfoChangedArray[i])) > 0) {
01185           isAnyInfoChanged = true;
01186           break;
01187       }
01188   }
01189   ArLog::log(level, "ArMap: Calling mapChanged callbacks");
01190   if (abs(myMapChangedMapObjects.mSecSince(myMapObjectsChanged)) > 0 || 
01191       abs(myMapChangedPoints.mSecSince(myPointsChanged)) > 0 || 
01192       abs(myMapChangedMapInfo.mSecSince(myMapInfoChanged)) > 0 ||
01193       isAnyInfoChanged) 
01194       //abs(myMapChangedRouteInfo.mSecSince(myRouteInfoChanged)) > 0)
01195   {
01196     for (it = myPreMapChangedCBList.begin(); 
01197      it != myPreMapChangedCBList.end(); 
01198      it++)
01199     {
01200       functor = (*it);
01201       if (functor->getName() != NULL && functor->getName()[0] != '\0')
01202     ArLog::log(level, "ArMap: Calling preMapChanged functor '%s'", 
01203            functor->getName());
01204       else
01205     ArLog::log(level, "ArMap: Calling unnamed preMapChanged functor");
01206       
01207       functor->invoke();
01208     }
01209 
01210     for (it = myMapChangedCBList.begin(); it != myMapChangedCBList.end(); it++)
01211     {
01212       functor = (*it);
01213       if (functor->getName() != NULL && functor->getName()[0] != '\0')
01214     ArLog::log(level, "ArMap: Calling mapChanged functor '%s'", 
01215            functor->getName());
01216       else
01217     ArLog::log(level, "ArMap: Calling unnamed mapChanged functor");
01218       
01219       functor->invoke();
01220     }
01221   }
01222   myMapChangedMapObjects = myMapObjectsChanged;
01223   myMapChangedPoints = myPointsChanged;
01224   myMapChangedMapInfo = myMapInfoChanged;
01225   //myMapChangedRouteInfo = myRouteInfoChanged;
01226   for (int i = 0; i < myNumInfos; i++) {
01227       myMapChangedInfoArray[i] = myInfoChangedArray[i];
01228   }
01229   ArLog::log(level, "ArMap: Done calling mapChanged callbacks");
01230 }
01231 
01232 
01237 AREXPORT void ArMap::writeToFunctor(ArFunctor1<const char *> *functor,
01238                     const char *endOfLineChars)
01239 {
01240   // Write the header information and Cairn objects...
01241   writeObjectsToFunctor(functor, endOfLineChars);
01242 
01243   if (myLines.begin() != myLines.end())
01244   {
01245     // Write the map data points in text format....
01246     std::vector<ArLineSegment>::iterator lineIt;
01247     
01248     ArUtil::functorPrintf(functor, "LINES%s", endOfLineChars);
01249     
01250     for (lineIt = myLines.begin(); 
01251      lineIt != myLines.end();
01252      lineIt++)
01253     {
01254       ArUtil::functorPrintf(functor, "%.0f %.0f %.0f %.0f%s", 
01255                 (*lineIt).getX1(), (*lineIt).getY1(), 
01256                 (*lineIt).getX2(), (*lineIt).getY2(),
01257                 endOfLineChars);
01258     }
01259   }
01260   
01261   ArUtil::functorPrintf(functor, "DATA%s", endOfLineChars);
01262   
01263   if (myPoints.begin() != myPoints.end())
01264   {
01265     // Write the map data points in text format....
01266     std::vector<ArPose>::iterator pointIt;
01267     
01268     for (pointIt = myPoints.begin(); 
01269      pointIt != myPoints.end();
01270      pointIt++)
01271     {
01272       ArUtil::functorPrintf(functor, "%.0f %.0f%s", (*pointIt).getX(), 
01273                 (*pointIt).getY(), endOfLineChars);
01274     }
01275   }
01276 }
01277 
01278 
01279 void ArMap::writeObjectsToFunctor
01280                 (ArFunctor1<const char *> *functor, 
01281                     const char *endOfLineChars)
01282 {
01283   std::list<ArMapObject *>::iterator mapObjectIt;
01284   //std::vector<ArPose>::iterator pointIt;
01285   std::list<ArArgumentBuilder *>::iterator mapInfoIt;
01286   //std::list<ArArgumentBuilder *>::iterator routeInfoIt;
01287 
01288   // toss out the general data
01289   ArUtil::functorPrintf(functor, "2D-Map%s", endOfLineChars);
01290   if (myNumPoints != 0)
01291   {
01292     ArUtil::functorPrintf(functor, "MinPos: %.0f %.0f%s", 
01293               myMin.getX(), myMin.getY(),  endOfLineChars);
01294     ArUtil::functorPrintf(functor, "MaxPos: %.0f %.0f%s", 
01295               myMax.getX(), myMax.getY(),  endOfLineChars);
01296     ArUtil::functorPrintf(functor, "NumPoints: %d%s", 
01297               myNumPoints, endOfLineChars);
01298   }
01299   if (myResolution != -1)
01300     ArUtil::functorPrintf(functor, "Resolution: %d%s", myResolution, 
01301               endOfLineChars);
01302   if (myNumLines != 0)
01303   {
01304     ArUtil::functorPrintf(functor, "LineMinPos: %.0f %.0f%s", 
01305               myLineMin.getX(), myLineMin.getY(),  endOfLineChars);
01306     ArUtil::functorPrintf(functor, "LineMaxPos: %.0f %.0f%s", 
01307               myLineMax.getX(), myLineMax.getY(),  endOfLineChars);
01308     ArUtil::functorPrintf(functor, "NumLines: %d%s", 
01309               myNumLines, endOfLineChars);
01310   }
01311   for (mapInfoIt = myMapInfo.begin(); 
01312        mapInfoIt != myMapInfo.end(); 
01313        mapInfoIt++)
01314     ArUtil::functorPrintf(functor, "MapInfo: %s%s", 
01315               (*mapInfoIt)->getFullString(), 
01316         endOfLineChars);
01317 
01318   for (int i = 0; i < myNumInfos; i++) {
01319       const char *infoName = getInfoName(i);
01320       if (infoName == NULL) {
01321         ArLog::log(ArLog::Normal, "ArMap: Cannot find Info tag for index %i, not saving...",
01322                    i);
01323         continue;
01324       }
01325 
01326       for (std::list<ArArgumentBuilder *>::iterator infoIt = myInfoArray[i].begin();
01327            infoIt != myInfoArray[i].end();
01328            infoIt++) {
01329 
01330         ArUtil::functorPrintf(functor, "%s %s%s", 
01331                               infoName,
01332                               (*infoIt)->getFullString(), 
01333                               endOfLineChars);
01334 
01335       } // end for each info in list
01336   } // end for each info type
01337 
01347   for (mapObjectIt = myMapObjects.begin(); 
01348        mapObjectIt != myMapObjects.end(); 
01349        mapObjectIt++)
01350   {
01351     ArMapObject *object = (*mapObjectIt);
01352     if (object->hasFromTo())
01353       ArUtil::functorPrintf(functor, 
01354           "Cairn: %s %g %g %g \"%s\" %s \"%s\" %.0f %.0f %.0f %.0f%s",
01355           object->getType(), object->getPose().getX(), 
01356           object->getPose().getY(), object->getPose().getTh(), 
01357           object->getFileName(), object->getIconName(), 
01358           object->getName(), object->getFromPose().getX(),
01359           object->getFromPose().getY(),
01360           object->getToPose().getX(), object->getToPose().getY(), 
01361           endOfLineChars);
01362     else
01363       ArUtil::functorPrintf(functor, 
01364           "Cairn: %s %g %g %g \"%s\" %s \"%s\"%s",
01365           object->getType(), object->getPose().getX(), 
01366           object->getPose().getY(), object->getPose().getTh(), 
01367           object->getFileName(), object->getIconName(), 
01368           object->getName(), endOfLineChars);
01369   }
01370  
01371 }
01372 
01373 
01374 void ArMap::writePointsToFunctor
01375 (ArFunctor2<int, std::vector<ArPose> *> *functor)
01376 {
01377     functor->invoke(myNumPoints, &myPoints);
01378 }
01379 
01380 void ArMap::writeLinesToFunctor
01381 (ArFunctor2<int, std::vector<ArLineSegment> *> *functor)
01382 {
01383     functor->invoke(myNumLines, &myLines);
01384 }
01385 
01386 
01387 
01396 AREXPORT bool ArMap::writeFile(const char *fileName, 
01397                    bool internalCall)
01398 {
01399   FILE *file;
01400   if (!internalCall)
01401     lock();
01402   // later this'll have a prefix
01403   std::string realFileName;
01404 
01405   if (fileName[0] == '/' || fileName[0] == '\\')
01406   {
01407     realFileName = fileName;
01408   }
01409   else
01410   {
01411     realFileName = myBaseDirectory;
01412     realFileName += fileName;
01413   }
01414   
01415   // make sure its there
01416   if ((file = fopen(realFileName.c_str(), "w")) == NULL)
01417   {
01418     ArLog::log(ArLog::Terse, "ArMap: Cannot open file '%s' for writing",
01419            realFileName.c_str());
01420     if (!internalCall)
01421       unlock();
01422     return false;
01423   }
01424 
01425   ArGlobalFunctor2<const char *, FILE *> functor(&ArUtil::writeToFile, "", file);
01426   writeToFunctor(&functor, "\n");
01427   
01428   fclose(file);
01429   ArLog::log(ArLog::Normal, "Saved map file %s", fileName);
01430   if (!internalCall)
01431     unlock();
01432   return true;
01433 }
01434 
01435 AREXPORT bool ArMap::parseLine(char *line)
01436 {
01437   return myLoadingParser->parseLine(line);
01438 }
01439 
01441 
01448 AREXPORT ArMapObject *ArMap::findMapObject(const char *name, 
01449                        const char *type)
01450 {
01451   std::list<ArMapObject *>::iterator objIt;
01452   ArMapObject* obj;
01453 
01454   for (objIt = getMapObjects()->begin(); 
01455        objIt != getMapObjects()->end(); 
01456        objIt++)
01457   {
01458     obj = (*objIt);
01459     if(obj == NULL)
01460       return NULL;
01461     // if we're searching any type or its the right type then check the name
01462     if (type == NULL || strcasecmp(obj->getType(), type) == 0)
01463     {
01464       if(name == NULL || strcasecmp(obj->getName(), name) == 0)
01465       {
01466     return obj;
01467       }
01468     }
01469   }
01470 
01471   // if we get down here we didn't find it
01472   return NULL;
01473 }
01474 
01475 const char *ArMap::getInfoName(int infoType)
01476 {
01477     if ((infoType >= 0) && (infoType < INFO_COUNT)) {
01478         return ourInfoNames[infoType];
01479     }
01480     else {
01481         return NULL;
01482     }
01483 }
01484 
01493 AREXPORT ArMapObject *ArMap::findFirstMapObject(const char *name, 
01494                        const char *type)
01495 {
01496   std::list<ArMapObject *>::iterator objIt;
01497   ArMapObject* obj;
01498 
01499   for (objIt = getMapObjects()->begin(); 
01500        objIt != getMapObjects()->end(); 
01501        objIt++)
01502   {
01503     obj = (*objIt);
01504     if(obj == NULL)
01505       return NULL;
01506     // if we're searching any type or its the right type then check the name
01507     if (type == NULL || strcasecmp(obj->getType(), type) == 0)
01508     {
01509       if(name == NULL || strcasecmp(obj->getName(), name) == 0)
01510       {
01511         return obj;
01512       }
01513     }
01514   }
01515 
01516   // if we get down here we didn't find it
01517   return NULL;
01518 }

Generated on Tue Feb 20 10:51:40 2007 for Aria by  doxygen 1.4.0