Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

url.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           url.cpp  -  description
00003                              -------------------
00004     begin                : Wed Aug 7 2002
00005     copyright            : (C) 2002 by chris
00006     email                : chris@tux.teyssier.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include <string>
00019 #include <stdio.h>
00020 #include "celestiacore.h"
00021 #include "celengine/astro.h"
00022 #include "url.h"
00023 
00024 Url::Url()
00025 {};
00026 
00027 Url::Url(const std::string& str, CelestiaCore *core)
00028 {
00029     urlStr = str;
00030     appCore = core;
00031     std::string::size_type pos, endPrevious;
00032     std::vector<Selection> bodies;
00033     Simulation *sim = appCore->getSimulation();
00034     std::map<std::string, std::string> params = parseUrlParams(urlStr);
00035 
00036     if (urlStr.substr(0, 6) != "cel://")
00037     {
00038         urlStr = "";
00039         return;
00040     }
00041     
00042     pos = urlStr.find("/", 6);
00043     if (pos == std::string::npos) pos = urlStr.find("?", 6);
00044 
00045     if (pos == std::string::npos) modeStr = urlStr.substr(6);
00046     else modeStr = decode_string(urlStr.substr(6, pos - 6));
00047 
00048 
00049     if (!compareIgnoringCase(modeStr, std::string("Freeflight")))
00050     {
00051         mode = astro::Universal;
00052         nbBodies = 0;
00053     }
00054     else if (!compareIgnoringCase(modeStr, std::string("Follow")))
00055     {
00056         mode = astro::Ecliptical;
00057         nbBodies = 1;
00058     }
00059     else if (!compareIgnoringCase(modeStr, std::string("SyncOrbit")))
00060     {
00061         mode = astro::Geographic;
00062         nbBodies = 1;
00063     }
00064     else if (!compareIgnoringCase(modeStr, std::string("Chase")))
00065     {
00066         mode = astro::Chase;
00067         nbBodies = 1;
00068     }
00069     else if (!compareIgnoringCase(modeStr, std::string("PhaseLock")))
00070     {
00071         mode = astro::PhaseLock;
00072         nbBodies = 2;
00073     }
00074     else if (!compareIgnoringCase(modeStr, std::string("Settings")))
00075     {
00076         type = Settings;
00077         nbBodies = 0;
00078     }
00079 
00080     if (nbBodies == -1)
00081     {
00082         urlStr = "";
00083         return; // Mode not recognized
00084     }
00085 
00086     endPrevious = pos;
00087     int nb = nbBodies, i=1;
00088     while (nb != 0 && endPrevious != std::string::npos) {
00089         std::string bodyName="";
00090         pos = urlStr.find("/", endPrevious + 1);
00091         if (pos == std::string::npos) pos = urlStr.find("?", endPrevious + 1);
00092         if (pos == std::string::npos) bodyName = urlStr.substr(endPrevious + 1);
00093         else bodyName = urlStr.substr(endPrevious + 1, pos - endPrevious - 1);
00094         endPrevious = pos;
00095 
00096         bodyName = decode_string(bodyName);
00097         pos = 0;
00098         if (i==1) body1 = bodyName;
00099         if (i==2) body2 = bodyName;
00100         while(pos != std::string::npos) {
00101             pos = bodyName.find(":", pos + 1);
00102             if (pos != std::string::npos) bodyName[pos]='/';
00103         }
00104 
00105         bodies.push_back(sim->findObjectFromPath(bodyName));
00106 
00107         nb--;
00108         i++;
00109     }
00110 
00111     if (nb != 0) {
00112         urlStr = "";
00113         return; // Number of bodies in Url doesn't match Mode
00114     }
00115 
00116     if (nbBodies == 0) ref = FrameOfReference();
00117     if (nbBodies == 1) ref = FrameOfReference(mode, bodies[0]);
00118     if (nbBodies == 2) ref = FrameOfReference(mode, bodies[0], bodies[1]);
00119     fromString = true;
00120 
00121     std::string time="";
00122     pos = urlStr.find("?", endPrevious + 1);
00123     if (pos == std::string::npos) time = urlStr.substr(endPrevious + 1);
00124     else time = urlStr.substr(endPrevious + 1, pos - endPrevious -1);
00125     time = decode_string(time);
00126     
00127     if (type != Settings)
00128     {
00129         if (params["dist"] != "")
00130             type = Relative;
00131         else
00132             type = Absolute;
00133     }
00134 
00135     switch (type) {
00136     case Absolute:
00137         date = astro::Date(0.0);
00138         sscanf(time.c_str(), "%d-%d-%dT%d:%d:%lf",
00139                &date.year, &date.month, &date.day,
00140                &date.hour, &date.minute, &date.seconds);
00141 
00142         coord = UniversalCoord(BigFix(params["x"]),
00143                                BigFix(params["y"]),
00144                                BigFix(params["z"]));
00145 
00146         float ow, ox, oy, oz;
00147         sscanf(params["ow"].c_str(), "%f", &ow);
00148         sscanf(params["ox"].c_str(), "%f", &ox);
00149         sscanf(params["oy"].c_str(), "%f", &oy);
00150         sscanf(params["oz"].c_str(), "%f", &oz);
00151 
00152         orientation = Quatf(ow, ox, oy, oz);
00153 
00154         // Intentional Fall-Through
00155     case Relative:
00156         if (params["dist"] != "") {
00157             sscanf(params["dist"].c_str(), "%lf", &distance);
00158         }
00159         if (params["long"] != "") {
00160             sscanf(params["long"].c_str(), "%lf", &longitude);
00161         }
00162         if (params["lat"] != "") {
00163             sscanf(params["lat"].c_str(), "%lf", &latitude);
00164         }
00165         if (params["select"] != "") {
00166                 selectedStr = params["select"];
00167         }
00168         if (params["track"] != "") {
00169             trackedStr = params["track"];
00170         }
00171         if (params["ltd"] != "") {
00172             lightTimeDelay = (strcmp(params["ltd"].c_str(), "1") == 0);
00173         } else {
00174             lightTimeDelay = false;
00175         }
00176         if (params["fov"] != "") {
00177             sscanf(params["fov"].c_str(), "%f", &fieldOfView);
00178         }
00179         if (params["ts"] != "") {
00180             sscanf(params["ts"].c_str(), "%f", &timeScale);
00181         }
00182         break;
00183     case Settings:
00184         break;
00185     }
00186 
00187     if (params["rf"] != "") {
00188         sscanf(params["rf"].c_str(), "%d", &renderFlags);
00189     }
00190     if (params["lm"] != "") {
00191         sscanf(params["lm"].c_str(), "%d", &labelMode);
00192     }
00193 
00194     evalName();
00195 }
00196 
00197 Url::Url(CelestiaCore* core, UrlType type)
00198 {
00199     appCore = core;
00200     Simulation *sim = appCore->getSimulation();
00201     Renderer *renderer = appCore->getRenderer();
00202 
00203     this->type = type;
00204 
00205     modeStr = getCoordSysName(sim->getFrame().coordSys);
00206     if (type == Settings) modeStr = "Settings";
00207     ref = sim->getFrame();
00208     urlStr += "cel://" + modeStr;
00209     if (type != Settings && sim->getFrame().coordSys != astro::Universal) {
00210         body1 = getSelectionName(sim->getFrame().refObject);
00211         urlStr += "/" + body1;
00212         if (sim->getFrame().coordSys == astro::PhaseLock) {
00213             body2 = getSelectionName(sim->getFrame().targetObject);
00214             urlStr += "/" + body2;
00215         }
00216     }
00217 
00218     char date_str[30];
00219     date = astro::Date(sim->getTime());
00220     char buff[255];
00221 
00222     switch (type) {
00223     case Absolute:
00224         sprintf(date_str, "%04d-%02d-%02dT%02d:%02d:%08.5f",
00225             date.year, date.month, date.day, date.hour, date.minute, date.seconds);
00226 
00227         coord = sim->getObserver().getPosition();
00228         urlStr += std::string("/") + date_str + "?x=" + coord.x.toString();
00229         urlStr += "&y=" +  coord.y.toString();
00230         urlStr += "&z=" +  coord.z.toString();
00231 
00232         orientation = sim->getObserver().getOrientation();
00233         sprintf(buff, "&ow=%f&ox=%f&oy=%f&oz=%f", orientation.w, orientation.x, orientation.y, orientation.z);
00234         urlStr += buff;
00235         break;
00236     case Relative:
00237         sim->getSelectionLongLat(distance, longitude, latitude);
00238         sprintf(buff, "dist=%f&long=%f&lat=%f", distance, longitude, latitude);
00239         urlStr += std::string("/?") + buff;
00240         break;
00241     case Settings:
00242         urlStr += std::string("/?");
00243         break;
00244     }
00245 
00246     switch (type) {
00247     case Absolute: // Intentional Fall-Through
00248     case Relative:
00249         tracked = sim->getTrackedObject();
00250         trackedStr = getSelectionName(tracked);
00251         if (trackedStr != "") urlStr += "&track=" + trackedStr;
00252 
00253         selected = sim->getSelection();
00254         selectedStr = getSelectionName(selected);
00255         if (selectedStr != "") urlStr += "&select=" + selectedStr;
00256 
00257         fieldOfView = radToDeg(sim->getActiveObserver()->getFOV());
00258         timeScale = sim->getTimeScale();
00259         lightTimeDelay = appCore->getLightDelayActive();
00260         sprintf(buff, "&fov=%f&ts=%f&ltd=%c&", fieldOfView,
00261             timeScale, lightTimeDelay?'1':'0');
00262         urlStr += buff;
00263     case Settings: // Intentional Fall-Through
00264         renderFlags = renderer->getRenderFlags();
00265         labelMode = renderer->getLabelMode();
00266         sprintf(buff, "rf=%d&lm=%d", renderFlags, labelMode);
00267         urlStr += buff;
00268         break;
00269     }
00270 
00271     evalName();
00272 }
00273 
00274 std::string Url::getAsString() const {
00275     return urlStr;
00276 }
00277 
00278 std::string Url::getName() const {
00279     return name;
00280 }
00281 
00282 void Url::evalName() {
00283     char buff[50];
00284     double lo = longitude, la = latitude;
00285     char los = 'E';
00286     char las = 'N';
00287     switch(type) {
00288     case Absolute:
00289         name = _(modeStr.c_str());
00290         if (body1 != "") name += " " + std::string(_(getBodyShortName(body1).c_str()));
00291         if (body2 != "") name += " " + std::string(_(getBodyShortName(body2).c_str()));
00292         if (trackedStr != "") name += " -> " + std::string(_(getBodyShortName(trackedStr).c_str()));
00293         if (selectedStr != "") name += " [" + std::string(_(getBodyShortName(selectedStr).c_str())) + "]";
00294         break;
00295     case Relative:
00296         if (selectedStr != "") name = std::string(_(getBodyShortName(selectedStr).c_str())) + " ";
00297         if (lo < 0) { lo = -lo; los = 'W'; }
00298         if (la < 0) { la = -la; las = 'S'; }
00299         sprintf(buff, "(%.1lf%c, %.1lf%c)", lo, los, la, las);
00300         name += buff;
00301         break;
00302     case Settings:
00303         name = _("Settings");
00304         break;
00305     }
00306 }
00307 
00308 std::string Url::getBodyShortName(const std::string& body) const {
00309     std::string::size_type pos;
00310     if (body != "") {
00311         pos = body.rfind(":");
00312         if (pos != std::string::npos) return body.substr(pos+1);
00313         else return body;
00314     }
00315     return "";
00316 }
00317 
00318 std::map<std::string, std::string> Url::parseUrlParams(const std::string& url) const{
00319     std::string::size_type pos, startName, startValue;
00320     std::map<std::string, std::string> params;
00321 
00322     pos = url.find("?");
00323     while (pos != std::string::npos) {
00324         startName = pos + 1;
00325         startValue = url.find("=", startName);
00326         pos = url.find("&", pos + 1);
00327         if (startValue != std::string::npos) {
00328              startValue++;
00329              if (pos != std::string::npos)
00330                  params[url.substr(startName, startValue - startName -1)] = decode_string(url.substr(startValue, pos - startValue));
00331              else
00332                  params[url.substr(startName, startValue - startName -1)] = decode_string(url.substr(startValue));
00333         }
00334     }
00335 
00336     return params;
00337 }
00338 
00339 std::string Url::getCoordSysName(astro::CoordinateSystem mode) const
00340 {
00341     switch (mode)
00342     {
00343     case astro::Universal:
00344         return "Freeflight";
00345     case astro::Ecliptical:
00346         return "Follow";
00347     case astro::Geographic:
00348         return "SyncOrbit";
00349     case astro::Chase:
00350         return "Chase";
00351     case astro::PhaseLock:
00352         return "PhaseLock";
00353     case astro::Equatorial:
00354         return "Unknown";
00355     case astro::ObserverLocal:
00356         return "Unknown";
00357     }
00358     return "Unknown";
00359 }
00360 
00361 
00362 std::string Url::getSelectionName(const Selection& selection) const
00363 {
00364     PlanetarySystem* parentSystem;
00365     Body* parentBody;
00366     Universe *universe = appCore->getSimulation()->getUniverse();
00367 
00368     switch (selection.getType())
00369     {
00370     case Selection::Type_Body:
00371         {
00372             std::string name = selection.body()->getName();
00373             parentSystem = selection.body()->getSystem();
00374             if (parentSystem != NULL && (parentBody = parentSystem->getPrimaryBody()) != NULL)
00375             {
00376                 while (parentSystem != NULL && parentBody != NULL)
00377                 {
00378                     name = parentSystem->getPrimaryBody()->getName() + ":" + name;
00379                     parentSystem = parentSystem->getPrimaryBody()->getSystem();
00380                     parentBody = parentSystem->getPrimaryBody();
00381                 }
00382                 if (selection.body()->getSystem()->getStar() != NULL)
00383                 {
00384                     name = universe->getStarCatalog()->getStarName(*(selection.body()->getSystem()->getStar())) + ":" + name;
00385                 }
00386             }
00387             return name;
00388         }
00389 
00390     case Selection::Type_Star:
00391         return universe->getStarCatalog()->getStarName(*selection.star());
00392 
00393     case Selection::Type_DeepSky:
00394         return universe->getDSOCatalog()->getDSOName(selection.deepsky());
00395 
00396     case Selection::Type_Location:
00397         return "";
00398 
00399     default:
00400         return "";
00401     }
00402 }
00403 
00404 void Url::goTo()
00405     {
00406     Selection sel;
00407 
00408     if (urlStr == "")
00409         return;
00410     Simulation *sim = appCore->getSimulation();
00411     Renderer *renderer = appCore->getRenderer();
00412     std::string::size_type pos;
00413 
00414     sim->update(0.0);
00415 
00416     switch(type) {
00417     case Absolute:// Intentional Fall-Through
00418     case Relative:
00419         sim->setFrame(ref);
00420         sim->getActiveObserver()->setFOV(degToRad(fieldOfView));
00421         appCore->setZoomFromFOV();
00422         sim->setTimeScale(timeScale);
00423         appCore->setLightDelayActive(lightTimeDelay);
00424 
00425         pos = 0;
00426         while(pos != std::string::npos)
00427         {
00428             pos = selectedStr.find(":", pos + 1);
00429             if (pos != std::string::npos) selectedStr[pos]='/';
00430         }
00431         sel = sim->findObjectFromPath(selectedStr);
00432         sim->setSelection(sel);
00433 
00434         pos = 0;
00435         while(pos != std::string::npos)
00436         {
00437             pos = trackedStr.find(":", pos + 1);
00438             if (pos != std::string::npos) trackedStr[pos]='/';
00439         }
00440         sel = sim->findObjectFromPath(trackedStr);
00441         sim->setTrackedObject(sel);
00442         // Intentional Fall-Through
00443     case Settings:
00444         renderer->setRenderFlags(renderFlags);
00445         renderer->setLabelMode(labelMode);
00446         break;
00447     }
00448 
00449     switch(type) {
00450     case Absolute:
00451         sim->setTime((double) date);
00452         sim->setObserverPosition(coord);
00453         sim->setObserverOrientation(orientation);
00454         break;
00455     case Relative:
00456         sim->gotoSelectionLongLat(0, astro::kilometersToLightYears(distance), longitude * PI / 180, latitude * PI / 180, Vec3f(0, 1, 0));
00457         break;
00458     case Settings:
00459         break;
00460     }
00461 }
00462 
00463 Url::~Url()
00464 {
00465 }
00466 
00467 std::string Url::decode_string(const std::string& str)
00468 {
00469     std::string::size_type a=0, b;
00470     std::string out = "";
00471 
00472     b = str.find("%");
00473     while (b != std::string::npos)
00474     {
00475         unsigned int c;
00476         out += str.substr(a, b-a);
00477         std::string c_code = str.substr(b+1, 2);
00478         sscanf(c_code.c_str(), "%02x", &c);
00479         out += c;
00480         a = b + 3;
00481         b = str.find("%", a);
00482     }
00483     out += str.substr(a);
00484                       
00485     return out;
00486 }
00487 
00488 
00489 
00490 
00491 

Generated on Sat Jan 14 22:30:31 2006 for Celestia by  doxygen 1.4.1