url.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:28k
源码类别:

OpenGL

开发平台:

Visual C++

  1. /***************************************************************************
  2.                           url.cpp  -  description
  3.                              -------------------
  4.     begin                : Wed Aug 7 2002
  5.     copyright            : (C) 2002 by chris
  6.     email                : chris@tux.teyssier.org
  7.  ***************************************************************************/
  8. /***************************************************************************
  9.  *                                                                         *
  10.  *   This program is free software; you can redistribute it and/or modify  *
  11.  *   it under the terms of the GNU General Public License as published by  *
  12.  *   the Free Software Foundation; either version 2 of the License, or     *
  13.  *   (at your option) any later version.                                   *
  14.  *                                                                         *
  15.  ***************************************************************************/
  16. #include <string>
  17. #include <cstring>
  18. #include <cstdio>
  19. #include <cassert>
  20. #include <sstream>
  21. #include <iomanip>
  22. #include "celestiacore.h"
  23. #include "celutil/util.h"
  24. #include "celengine/astro.h"
  25. #include "url.h"
  26. using namespace std;
  27. const unsigned int Url::CurrentVersion = 3;
  28. const string getEncodedObjectName(const Selection& sel, const CelestiaCore* appCore);
  29. CelestiaState::CelestiaState() :
  30.     coordSys(ObserverFrame::Universal),
  31.     observerPosition(0.0, 0.0, 0.0),
  32.     observerOrientation(1.0f),
  33.     fieldOfView(45.0f),
  34.     tdb(0.0),
  35.     timeScale(1.0f),
  36.     pauseState(false),
  37.     lightTimeDelay(false),
  38.     labelMode(0),
  39.     renderFlags(0)
  40. {
  41. }
  42. void
  43. CelestiaState::captureState(CelestiaCore* appCore)
  44. {
  45.     Simulation *sim = appCore->getSimulation();
  46.     Renderer *renderer = appCore->getRenderer();
  47.     
  48.     const ObserverFrame* frame = sim->getFrame();
  49.     
  50.     coordSys = frame->getCoordinateSystem();
  51.     if (coordSys != ObserverFrame::Universal)
  52.     {
  53.         refBodyName = getEncodedObjectName(frame->getRefObject(), appCore);
  54.         if (coordSys == ObserverFrame::PhaseLock) 
  55.         {
  56.             targetBodyName = getEncodedObjectName(frame->getTargetObject(), appCore);
  57.         }
  58.     }
  59.     
  60.     tdb = sim->getTime();
  61.     
  62.     // Store the position and orientation of the observer in the current
  63.     // frame.
  64.     observerPosition = sim->getObserver().getPosition();
  65.     observerPosition = frame->convertFromUniversal(observerPosition, tdb);
  66.         
  67.     Quatd q = sim->getObserver().getOrientation();
  68.     q = frame->convertFromUniversal(q, tdb);
  69.     observerOrientation = Quatf((float) q.w, (float) q.x, (float) q.y, (float) q.z);
  70.         
  71.     Selection tracked = sim->getTrackedObject();
  72.     trackedBodyName = getEncodedObjectName(tracked, appCore);
  73.     Selection selected = sim->getSelection();
  74.     selectedBodyName = getEncodedObjectName(selected, appCore);
  75.     fieldOfView = radToDeg(sim->getActiveObserver()->getFOV());
  76.     timeScale = (float) sim->getTimeScale();
  77.     pauseState = sim->getPauseState();
  78.     lightTimeDelay = appCore->getLightDelayActive();
  79.     renderFlags = renderer->getRenderFlags();
  80.     labelMode = renderer->getLabelMode();
  81. }
  82. #if 0
  83. bool CelestiaState::loadState(std::map<std::string, std::string> params)
  84. {
  85.     sscanf(timeString.c_str(), "%d-%d-%dT%d:%d:%lf",
  86.            &date.year, &date.month, &date.day,
  87.            &date.hour, &date.minute, &date.seconds);
  88.     
  89.     observerPosition = UniversalCoord(BigFix(params["x"]),
  90.                                       BigFix(params["y"]),
  91.                                       BigFix(params["z"]));
  92.     
  93.     float ow = 0.0f;
  94.     float ox = 0.0f;
  95.     float oy = 0.0f;
  96.     float oz = 0.0f;
  97.     if (sscanf(params["ow"].c_str(), "%f", &ow) != 1 ||
  98.         sscanf(params["ox"].c_str(), "%f", &ox) != 1 ||
  99.         sscanf(params["oy"].c_str(), "%f", &oy) != 1 ||
  100.         sscanf(params["oz"].c_str(), "%f", &oz) != 1)
  101.     {
  102.         return false;
  103.     }
  104.     
  105.     orientation = Quatf(ow, ox, oy, oz);
  106.     
  107.     if (params["select"] != "")
  108.         selectedBodyName = params["select"];
  109.     if (params["track"] != "")
  110.         trackedBodyName = params["track"];
  111.     if (params["ltd"] != "")
  112.         lightTimeDelay = (strcmp(params["ltd"].c_str(), "1") == 0);
  113.     else
  114.         lightTimeDelay = false;
  115.     
  116.     if (params["fov"] != "")
  117.     {
  118.         if (sscanf(params["fov"].c_str(), "%f", &fieldOfView) != 1.0f)
  119.             return false;
  120.     }
  121.     
  122.     if (params["ts"] != "") 
  123.     {
  124.         if (sscanf(params["ts"].c_str(), "%f", &timeScale) != 1.0f)
  125.             return false;
  126.     }
  127.     
  128.     int paused = 0;
  129.     if (params["p"] != "")
  130.     {
  131.         if (sscanf(params["p"].c_str(), "%d", &paused) != 1)
  132.             return false;
  133.         if (paused != 0 && paused != 1)
  134.             return false;
  135.         pauseState = paused == 1;
  136.     }
  137.     
  138.     // Render settings
  139.     if (params["rf"] != "")
  140.     {
  141.         if (sscanf(params["rf"].c_str(), "%d", &renderFlags) != 1)
  142.             return false;
  143.     }
  144.     if (params["lm"] != "")
  145.     {
  146.         if (sscanf(params["lm"].c_str(), "%d", &labelMode) != 1)
  147.             return false;
  148.     }
  149. }
  150. #endif
  151. Url::Url()
  152. {};
  153. Url::Url(const std::string& str, CelestiaCore *core):
  154.     urlStr(str),
  155.     appCore(core),
  156.     pauseState(false),
  157.     timeSource(UseUrlTime),
  158.     version(2)
  159. {
  160.     std::string::size_type pos, endPrevious;
  161.     std::vector<Selection> bodies;
  162.     Simulation *sim = appCore->getSimulation();
  163.     std::map<std::string, std::string> params = parseUrlParams(urlStr);
  164.     if (urlStr.substr(0, 6) != "cel://")
  165.     {
  166.         urlStr = "";
  167.         return;
  168.     }
  169.     // Version labelling of cel URLs was only added in Celestia 1.5, cel URL
  170.     // version 2. Assume any URL without a version is version 1.
  171.     if (params["ver"] != "")
  172.     {
  173.         sscanf(params["ver"].c_str(), "%u", &version);
  174.     }
  175.     else
  176.     {
  177.         version = 1;
  178.     }
  179.     
  180.     pos = urlStr.find("/", 6);
  181.     if (pos == std::string::npos)
  182.         pos = urlStr.find("?", 6);
  183.     if (pos == std::string::npos)
  184.         modeStr = urlStr.substr(6);
  185.     else
  186.         modeStr = decodeString(urlStr.substr(6, pos - 6));
  187.     if (!compareIgnoringCase(modeStr, std::string("Freeflight")))
  188.     {
  189.         mode = ObserverFrame::Universal;
  190.         nbBodies = 0;
  191.     }
  192.     else if (!compareIgnoringCase(modeStr, std::string("Follow")))
  193.     {
  194.         mode = ObserverFrame::Ecliptical;
  195.         nbBodies = 1;
  196.     }
  197.     else if (!compareIgnoringCase(modeStr, std::string("SyncOrbit")))
  198.     {
  199.         mode = ObserverFrame::BodyFixed;
  200.         nbBodies = 1;
  201.     }
  202.     else if (!compareIgnoringCase(modeStr, std::string("Chase")))
  203.     {
  204.         mode = ObserverFrame::Chase;
  205.         nbBodies = 1;
  206.     }
  207.     else if (!compareIgnoringCase(modeStr, std::string("PhaseLock")))
  208.     {
  209.         mode = ObserverFrame::PhaseLock;
  210.         nbBodies = 2;
  211.     }
  212.     else if (!compareIgnoringCase(modeStr, std::string("Settings")))
  213.     {
  214.         type = Settings;
  215.         nbBodies = 0;
  216.     }
  217.     
  218.     if (nbBodies == -1)
  219.     {
  220.         urlStr = "";
  221.         return; // Mode not recognized
  222.     }
  223.     
  224.     endPrevious = pos;
  225.     int nb = nbBodies, i=1;
  226.     while (nb != 0 && endPrevious != std::string::npos) {
  227.         std::string bodyName="";
  228.         pos = urlStr.find("/", endPrevious + 1);
  229.         if (pos == std::string::npos) pos = urlStr.find("?", endPrevious + 1);
  230.         if (pos == std::string::npos) bodyName = urlStr.substr(endPrevious + 1);
  231.         else bodyName = urlStr.substr(endPrevious + 1, pos - endPrevious - 1);
  232.         endPrevious = pos;
  233.         
  234.         bodyName = decodeString(bodyName);
  235.         pos = 0;
  236.         if (i==1) body1 = bodyName;
  237.         if (i==2) body2 = bodyName;
  238.         while(pos != std::string::npos) {
  239.             pos = bodyName.find(":", pos + 1);
  240.             if (pos != std::string::npos) bodyName[pos]='/';
  241.         }
  242.         
  243.         bodies.push_back(sim->findObjectFromPath(bodyName));
  244.         
  245.         nb--;
  246.         i++;
  247.     }
  248.     
  249.     if (nb != 0) {
  250.         urlStr = "";
  251.         return; // Number of bodies in Url doesn't match Mode
  252.     }
  253.     
  254.     if (nbBodies == 0) ref = ObserverFrame();
  255.     if (nbBodies == 1) ref = ObserverFrame(mode, bodies[0]);
  256.     if (nbBodies == 2) ref = ObserverFrame(mode, bodies[0], bodies[1]);
  257.     fromString = true;
  258.         
  259.     std::string time="";
  260.     pos = urlStr.find("?", endPrevious + 1);
  261.     if (pos == std::string::npos)
  262.         time = urlStr.substr(endPrevious + 1);
  263.     else time = urlStr.substr(endPrevious + 1, pos - endPrevious -1);
  264.         time = decodeString(time);
  265.         
  266.     switch (version)
  267.     {
  268.     case 1:
  269.     case 2:
  270.         initVersion2(params, time);
  271.         break;
  272.     case 3:
  273.         initVersion3(params, time);
  274.         break;
  275.     default:
  276.         urlStr = "";
  277.         return;
  278.     }
  279.     evalName();
  280. }
  281. Url::Url(CelestiaCore* core, UrlType type)
  282. {
  283.     appCore = core;
  284.     version = 2;
  285.     timeSource = UseUrlTime;
  286.     
  287.     Simulation *sim = appCore->getSimulation();
  288.     Renderer *renderer = appCore->getRenderer();
  289.     this->type = type;
  290.     modeStr = getCoordSysName(sim->getFrame()->getCoordinateSystem());
  291.     if (type == Settings) modeStr = "Settings";
  292.     ref = *sim->getFrame();
  293.     urlStr += "cel://" + modeStr;
  294.     if (type != Settings && sim->getFrame()->getCoordinateSystem() != ObserverFrame::Universal) {
  295.         body1 = getEncodedObjectName(sim->getFrame()->getRefObject());
  296.         urlStr += "/" + body1;
  297.         if (sim->getFrame()->getCoordinateSystem() == ObserverFrame::PhaseLock) {
  298.             body2 = getEncodedObjectName(sim->getFrame()->getTargetObject());
  299.             urlStr += "/" + body2;
  300.         }
  301.     }
  302.     double simTime = sim->getTime();
  303.     
  304.     char date_str[50];
  305.     date = astro::Date(simTime);
  306.     char buff[255];
  307.     switch (type) {
  308.     case Absolute:
  309.         snprintf(date_str, sizeof(date_str), "%04d-%02d-%02dT%02d:%02d:%08.5f",
  310.             date.year, date.month, date.day, date.hour, date.minute, date.seconds);
  311.         coord = sim->getObserver().getPosition();
  312.         urlStr += std::string("/") + date_str + "?x=" + coord.x.toString();
  313.         urlStr += "&y=" +  coord.y.toString();
  314.         urlStr += "&z=" +  coord.z.toString();
  315.         orientation = sim->getObserver().getOrientationf();
  316.         sprintf(buff, "&ow=%f&ox=%f&oy=%f&oz=%f", orientation.w, orientation.x, orientation.y, orientation.z);
  317.         urlStr += buff;
  318.         break;
  319.     case Relative:
  320.         sim->getSelectionLongLat(distance, longitude, latitude);
  321.         sprintf(buff, "dist=%f&long=%f&lat=%f", distance, longitude, latitude);
  322.         urlStr += std::string("/?") + buff;
  323.         break;
  324.     case Settings:
  325.         urlStr += std::string("/?");
  326.         break;
  327.     }
  328.     switch (type) {
  329.     case Absolute: // Intentional Fall-Through
  330.     case Relative:
  331.         tracked = sim->getTrackedObject();
  332.         trackedStr = getEncodedObjectName(tracked);
  333.         if (trackedStr != "") urlStr += "&track=" + trackedStr;
  334.         selected = sim->getSelection();
  335.         selectedStr = getEncodedObjectName(selected);
  336.         if (selectedStr != "") urlStr += "&select=" + selectedStr;
  337.         fieldOfView = radToDeg(sim->getActiveObserver()->getFOV());
  338.         timeScale = (float) sim->getTimeScale();
  339.         pauseState = sim->getPauseState();
  340.         lightTimeDelay = appCore->getLightDelayActive();
  341.         sprintf(buff, "&fov=%f&ts=%f&ltd=%c&p=%c&", fieldOfView,
  342.             timeScale, lightTimeDelay?'1':'0', pauseState?'1':'0');
  343.         urlStr += buff;
  344.     case Settings: // Intentional Fall-Through
  345.         renderFlags = renderer->getRenderFlags();
  346.         labelMode = renderer->getLabelMode();
  347.         sprintf(buff, "rf=%d&lm=%d", renderFlags, labelMode);
  348.         urlStr += buff;
  349.         break;
  350.     }
  351.     // Append the Celestia URL version
  352.     {
  353.         char buf[32];
  354.         sprintf(buf, "&ver=%u", version);
  355.         urlStr += buf;
  356.     }
  357.     evalName();
  358. }
  359. /*! Construct a new cel URL from a saved CelestiaState object. This method may
  360.  *  may only be called to create a version 3 or later url.
  361.  */
  362. Url::Url(const CelestiaState& appState, unsigned int _version, TimeSource _timeSource)
  363. {
  364.     ostringstream u;
  365.     
  366.     appCore = NULL;
  367.     
  368.     assert(_version >= 3);
  369.     version = _version;
  370.     timeSource = _timeSource;
  371.     type = Absolute;
  372.     
  373.     modeStr      = getCoordSysName(appState.coordSys);
  374.     body1        = appState.refBodyName;
  375.     body2        = appState.targetBodyName;
  376.     selectedStr  = appState.selectedBodyName;
  377.     trackedStr   = appState.trackedBodyName;
  378.     
  379.     coord        = appState.observerPosition;
  380.     orientation  = appState.observerOrientation;
  381.     
  382.     //ref =
  383.     //selected =
  384.     //tracked =
  385.     nbBodies = 1;
  386.     if (appState.coordSys == ObserverFrame::Universal)
  387.         nbBodies = 0;
  388.     else if (appState.coordSys ==  ObserverFrame::PhaseLock)
  389.         nbBodies = 2;
  390.     
  391.     fieldOfView      = appState.fieldOfView;
  392.     renderFlags      = appState.renderFlags;
  393.     labelMode        = appState.labelMode;
  394.     
  395.     date             = astro::Date(appState.tdb);
  396.     timeScale        = appState.timeScale;
  397.     pauseState       = appState.pauseState;
  398.     lightTimeDelay   = appState.lightTimeDelay;    
  399.     
  400.     u << "cel://" << modeStr;
  401.     
  402.     if (appState.coordSys != ObserverFrame::Universal)
  403.     {
  404.         u << "/" << appState.refBodyName;
  405.         if (appState.coordSys == ObserverFrame::PhaseLock)
  406.         {
  407.             u << "/" << appState.targetBodyName;
  408.         }
  409.     }
  410.         
  411.     char date_str[50];
  412.     snprintf(date_str, sizeof(date_str), "%04d-%02d-%02dT%02d:%02d:%08.5f",
  413.              date.year, date.month, date.day, date.hour, date.minute, date.seconds);
  414.     u << "/" << date_str;
  415.         
  416.     // observer position
  417.     u << "?x=" << coord.x.toString() << "&y=" << coord.y.toString() << "&z=" << coord.z.toString();
  418.     
  419.     // observer orientation
  420.     u << "&ow=" << orientation.w
  421.       << "&ox=" << orientation.x
  422.       << "&oy=" << orientation.y
  423.       << "&oz=" << orientation.z;
  424.     
  425.     if (trackedStr != "") 
  426.         u << "&track=" << trackedStr;
  427.     if (selectedStr != "")
  428.         u << "&select=" << selectedStr;
  429.     u << "&fov=" << fieldOfView;
  430.     u << "&ts=" << timeScale;
  431.     u << "&ltd=" << (lightTimeDelay ? 1 : 0);
  432.     u << "&p=" << (pauseState ? 1 : 0);
  433.     u << "&rf=" << renderFlags;
  434.     u << "&lm=" << labelMode;
  435.     // Append the url settings: time source and version
  436.     u << "&tsrc=" << (int) timeSource;
  437.     u << "&ver=" << version;
  438.     urlStr = u.str();
  439.     evalName();
  440. }
  441. void Url::initVersion2(std::map<std::string, std::string>& params,
  442.                        const std::string& timeString) 
  443. {
  444.     if (type != Settings)
  445.     {
  446.         if (params["dist"] != "")
  447.             type = Relative;
  448.         else
  449.             type = Absolute;
  450.     }
  451.     
  452.     switch (type) {
  453.         case Absolute:
  454.             date = astro::Date(0.0);
  455.             sscanf(timeString.c_str(), "%d-%d-%dT%d:%d:%lf",
  456.                    &date.year, &date.month, &date.day,
  457.                    &date.hour, &date.minute, &date.seconds);
  458.             
  459.             coord = UniversalCoord(BigFix(params["x"]),
  460.                                    BigFix(params["y"]),
  461.                                    BigFix(params["z"]));
  462.             
  463.             float ow, ox, oy, oz;
  464.             sscanf(params["ow"].c_str(), "%f", &ow);
  465.             sscanf(params["ox"].c_str(), "%f", &ox);
  466.             sscanf(params["oy"].c_str(), "%f", &oy);
  467.             sscanf(params["oz"].c_str(), "%f", &oz);
  468.             
  469.             orientation = Quatf(ow, ox, oy, oz);
  470.             
  471.             // Intentional Fall-Through
  472.         case Relative:
  473.             if (params["dist"] != "") {
  474.                 sscanf(params["dist"].c_str(), "%lf", &distance);
  475.             }
  476.             if (params["long"] != "") {
  477.                 sscanf(params["long"].c_str(), "%lf", &longitude);
  478.             }
  479.             if (params["lat"] != "") {
  480.                 sscanf(params["lat"].c_str(), "%lf", &latitude);
  481.             }
  482.             if (params["select"] != "") {
  483.                 selectedStr = params["select"];
  484.             }
  485.             if (params["track"] != "") {
  486.                 trackedStr = params["track"];
  487.             }
  488.             if (params["ltd"] != "") {
  489.                 lightTimeDelay = (strcmp(params["ltd"].c_str(), "1") == 0);
  490.             } else {
  491.                 lightTimeDelay = false;
  492.             }
  493.             if (params["fov"] != "") {
  494.                 sscanf(params["fov"].c_str(), "%f", &fieldOfView);
  495.             }
  496.             if (params["ts"] != "") {
  497.                 sscanf(params["ts"].c_str(), "%f", &timeScale);
  498.             }
  499.             if (params["p"] != "") {
  500.                 int pauseInt = 0;
  501.                 sscanf(params["p"].c_str(), "%d", &pauseInt);
  502.                 pauseState = pauseInt == 1;
  503.             }
  504.             break;
  505.         case Settings:
  506.             break;
  507.     }
  508.     
  509.     if (params["rf"] != "") {
  510.         sscanf(params["rf"].c_str(), "%d", &renderFlags);
  511.     }
  512.     if (params["lm"] != "") {
  513.         sscanf(params["lm"].c_str(), "%d", &labelMode);
  514.     }
  515.     
  516. }
  517. void Url::initVersion3(std::map<std::string, std::string>& params,
  518.                        const std::string& timeString)
  519. {
  520.     // Type field not used for version 3 urls; position is always relative
  521.     // to the frame center. Time setting is controlled by the time source.
  522.     type = Absolute;
  523.     
  524.     date = astro::Date(0.0);
  525.     sscanf(timeString.c_str(), "%d-%d-%dT%d:%d:%lf",
  526.            &date.year, &date.month, &date.day,
  527.            &date.hour, &date.minute, &date.seconds);
  528.     
  529.     coord = UniversalCoord(BigFix(params["x"]),
  530.                            BigFix(params["y"]),
  531.                            BigFix(params["z"]));
  532.     
  533.     float ow, ox, oy, oz;
  534.     sscanf(params["ow"].c_str(), "%f", &ow);
  535.     sscanf(params["ox"].c_str(), "%f", &ox);
  536.     sscanf(params["oy"].c_str(), "%f", &oy);
  537.     sscanf(params["oz"].c_str(), "%f", &oz);
  538.     
  539.     orientation = Quatf(ow, ox, oy, oz);
  540.     
  541.     if (params["select"] != "")
  542.         selectedStr = params["select"];
  543.     if (params["track"] != "")
  544.         trackedStr = params["track"];
  545.     if (params["ltd"] != "")
  546.         lightTimeDelay = (strcmp(params["ltd"].c_str(), "1") == 0);
  547.     else
  548.         lightTimeDelay = false;
  549.     
  550.     if (params["fov"] != "")
  551.         sscanf(params["fov"].c_str(), "%f", &fieldOfView);
  552.     if (params["ts"] != "") 
  553.         sscanf(params["ts"].c_str(), "%f", &timeScale);
  554.     
  555.     int paused = 0;
  556.     if (params["p"] != "")
  557.         sscanf(params["p"].c_str(), "%d", &paused);
  558.     pauseState = paused == 1;
  559.     // Render settings
  560.     if (params["rf"] != "")
  561.         sscanf(params["rf"].c_str(), "%d", &renderFlags);
  562.     if (params["lm"] != "")
  563.         sscanf(params["lm"].c_str(), "%d", &labelMode);
  564.         
  565.     int timeSourceInt = 0;
  566.     if (params["tsrc"] != "")
  567.         sscanf(params["tsrc"].c_str(), "%d", &timeSourceInt);
  568.     if (timeSourceInt >= 0 && timeSourceInt < TimeSourceCount)
  569.         timeSource = (TimeSource) timeSourceInt;
  570.     else
  571.         timeSource = UseUrlTime;
  572. }
  573. std::string Url::getAsString() const
  574. {
  575.     return urlStr;
  576. }
  577. std::string Url::getName() const
  578. {
  579.     return name;
  580. }
  581. void Url::evalName()
  582. {
  583.     char buff[50];
  584.     double lo = longitude, la = latitude;
  585.     char los = 'E';
  586.     char las = 'N';
  587.     switch(type) {
  588.     case Absolute:
  589.         name = _(modeStr.c_str());
  590.         if (body1 != "") name += " " + std::string(_(getBodyShortName(body1).c_str()));
  591.         if (body2 != "") name += " " + std::string(_(getBodyShortName(body2).c_str()));
  592.         if (trackedStr != "") name += " -> " + std::string(_(getBodyShortName(trackedStr).c_str()));
  593.         if (selectedStr != "") name += " [" + std::string(_(getBodyShortName(selectedStr).c_str())) + "]";
  594.         break;
  595.     case Relative:
  596.         if (selectedStr != "") name = std::string(_(getBodyShortName(selectedStr).c_str())) + " ";
  597.         if (lo < 0) { lo = -lo; los = 'W'; }
  598.         if (la < 0) { la = -la; las = 'S'; }
  599.         sprintf(buff, "(%.1lf%c, %.1lf%c)", lo, los, la, las);
  600.         name += buff;
  601.         break;
  602.     case Settings:
  603.         name = _("Settings");
  604.         break;
  605.     }
  606. }
  607. std::string Url::getBodyShortName(const std::string& body) const
  608. {
  609.     std::string::size_type pos;
  610.     if (body != "") {
  611.         pos = body.rfind(":");
  612.         if (pos != std::string::npos) return body.substr(pos+1);
  613.         else return body;
  614.     }
  615.     return "";
  616. }
  617. std::map<std::string, std::string> Url::parseUrlParams(const std::string& url) const
  618. {
  619.     std::string::size_type pos, startName, startValue;
  620.     std::map<std::string, std::string> params;
  621.     pos = url.find("?");
  622.     while (pos != std::string::npos) {
  623.         startName = pos + 1;
  624.         startValue = url.find("=", startName);
  625.         pos = url.find("&", pos + 1);
  626.         if (startValue != std::string::npos) {
  627.              startValue++;
  628.              if (pos != std::string::npos)
  629.                  params[url.substr(startName, startValue - startName -1)] = decodeString(url.substr(startValue, pos - startValue));
  630.              else
  631.                  params[url.substr(startName, startValue - startName -1)] = decodeString(url.substr(startValue));
  632.         }
  633.     }
  634.     return params;
  635. }
  636. std::string Url::getCoordSysName(ObserverFrame::CoordinateSystem mode) const
  637. {
  638.     switch (mode)
  639.     {
  640.     case ObserverFrame::Universal:
  641.         return "Freeflight";
  642.     case ObserverFrame::Ecliptical:
  643.         return "Follow";
  644.     case ObserverFrame::BodyFixed:
  645.         return "SyncOrbit";
  646.     case ObserverFrame::Chase:
  647.         return "Chase";
  648.     case ObserverFrame::PhaseLock:
  649.         return "PhaseLock";
  650.     case ObserverFrame::Equatorial:
  651.         return "Unknown";
  652.     case ObserverFrame::ObserverLocal:
  653.         return "Unknown";
  654.     default:
  655.         return "Unknown";
  656.     }
  657. }
  658. static std::string getBodyName(Universe* universe, Body* body)
  659. {
  660.     std::string name = body->getName();
  661.     PlanetarySystem* parentSystem = body->getSystem();
  662.     const Body* parentBody = NULL;
  663.     if (parentSystem != NULL)
  664.         parentBody = parentSystem->getPrimaryBody();
  665.     else
  666.         assert(0);
  667.         // TODO: Figure out why the line below was added.
  668.         //parentBody = body->getOrbitBarycenter();  
  669.     while (parentBody != NULL)
  670.     {
  671.         name = parentBody->getName() + ":" + name;
  672.         parentSystem = parentBody->getSystem();
  673.         if (parentSystem == NULL)
  674.             parentBody = NULL;
  675.         else
  676.             parentBody = parentSystem->getPrimaryBody();
  677.     }
  678.     if (body->getSystem()->getStar() != NULL)
  679.     {
  680.         name = universe->getStarCatalog()->getStarName(*(body->getSystem()->getStar())) + ":" + name;
  681.     }
  682.     return name;
  683. }
  684. void Url::goTo()
  685. {
  686.     Selection sel;
  687.     if (urlStr == "")
  688.         return;
  689.     Simulation *sim = appCore->getSimulation();
  690.     Renderer *renderer = appCore->getRenderer();
  691.     std::string::size_type pos;
  692.     sim->update(0.0);
  693.     switch(type) {
  694.     case Absolute:// Intentional Fall-Through
  695.     case Relative:
  696.         sim->setFrame(ref.getCoordinateSystem(), ref.getRefObject(), ref.getTargetObject());
  697.         sim->getActiveObserver()->setFOV(degToRad(fieldOfView));
  698.         appCore->setZoomFromFOV();
  699.         sim->setTimeScale(timeScale);
  700.         sim->setPauseState(pauseState);
  701.         appCore->setLightDelayActive(lightTimeDelay);
  702.         if (selectedStr != "")
  703.         {
  704.             pos = 0;
  705.             while(pos != std::string::npos)
  706.             {
  707.                 pos = selectedStr.find(":", pos + 1);
  708.                 if (pos != std::string::npos) selectedStr[pos]='/';
  709.             }
  710.             sel = sim->findObjectFromPath(selectedStr);
  711.             sim->setSelection(sel);
  712.         }
  713.         else
  714.         {
  715.             sim->setSelection(Selection());
  716.         }
  717.         if (trackedStr != "")
  718.         {
  719.             pos = 0;
  720.             while(pos != std::string::npos)
  721.             {
  722.                 pos = trackedStr.find(":", pos + 1);
  723.                 if (pos != std::string::npos) trackedStr[pos]='/';
  724.             }
  725.             sel = sim->findObjectFromPath(trackedStr);
  726.             sim->setTrackedObject(sel);
  727.         }
  728.         else
  729.         {
  730.             if (!sim->getTrackedObject().empty())
  731.                 sim->setTrackedObject(Selection());
  732.         }
  733.         // Intentional Fall-Through
  734.     case Settings:
  735.         renderer->setRenderFlags(renderFlags);
  736.         renderer->setLabelMode(labelMode);
  737.         break;
  738.     }
  739.     if (version >= 3)
  740.     {
  741.         switch (timeSource)
  742.         {
  743.             case UseUrlTime:
  744.                 sim->setTime((double) date);
  745.                 break;
  746.             case UseSimulationTime:
  747.                 // Leave the current simulation time unmodified
  748.                 break;
  749.             case UseSystemTime:
  750.                 sim->setTime(astro::UTCtoTDB(astro::Date::systemDate()));
  751.                 break;
  752.             default:
  753.                 break;
  754.         }
  755.         
  756.         // Position and orientation stored in frame coordinates; convert them
  757.         // to universal and set the observer position.
  758.         double tdb = sim->getTime();
  759.         coord = sim->getObserver().getFrame()->convertToUniversal(coord, tdb);
  760.         Quatd q(orientation.w, orientation.x, orientation.y, orientation.z);
  761.         q = sim->getObserver().getFrame()->convertToUniversal(q, tdb);
  762.         sim->setObserverPosition(coord);
  763.         sim->setObserverOrientation(Quatf((float) q.w, (float) q.x, (float) q.y, (float) q.z));
  764.     }
  765.     else
  766.     {
  767.         switch(type) {
  768.         case Absolute:
  769.             sim->setTime((double) date);
  770.             sim->setObserverPosition(coord);
  771.             sim->setObserverOrientation(orientation);
  772.             break;
  773.         case Relative:
  774.             sim->gotoSelectionLongLat(0, astro::kilometersToLightYears(distance), (float) (longitude * PI / 180), (float) (latitude * PI / 180), Vec3f(0, 1, 0));
  775.             break;
  776.         case Settings:
  777.             break;
  778.         }
  779.     }
  780. }
  781. Url::~Url()
  782. {
  783. }
  784. std::string Url::decodeString(const std::string& str)
  785. {
  786.     std::string::size_type a=0, b;
  787.     std::string out = "";
  788.     b = str.find("%");
  789.     while (b != std::string::npos)
  790.     {
  791.         unsigned int c;
  792.         out += str.substr(a, b-a);
  793.         std::string c_code = str.substr(b+1, 2);
  794.         sscanf(c_code.c_str(), "%02x", &c);
  795.         out += (char) c;
  796.         a = b + 3;
  797.         b = str.find("%", a);
  798.     }
  799.     out += str.substr(a);
  800.     return out;
  801. }
  802. string Url::encodeString(const string& str)
  803. {
  804.     ostringstream enc;
  805.     for (string::const_iterator iter = str.begin(); iter != str.end(); iter++)
  806.     {
  807.         int ch = *iter;
  808.         bool encode = false;
  809.         if (ch <= 32 || ch >= 128)
  810.         {
  811.             encode = true;
  812.         }
  813.         else
  814.         {
  815.             switch (ch)
  816.             {
  817.             case '%':
  818.             case '?':
  819.             case '"':
  820.             case '#':
  821.             case '+':
  822.             case ',':
  823.             case '=':
  824.             case '@':
  825.             case '[':
  826.             case ']':
  827.                 encode = true;
  828.                 break;
  829.             }
  830.         }
  831.         if (encode)
  832.         {
  833.             enc << '%' << setw(2) << hex << (unsigned int) ch;
  834.         }
  835.         else
  836.         {
  837.             enc << *iter;
  838.         }
  839.     }
  840.     return enc.str();
  841. }
  842. // Utility function that returns the complete path for a selection.
  843. string
  844. Url::getEncodedObjectName(const Selection& selection)
  845. {
  846.     return ::getEncodedObjectName(selection, appCore);
  847. }
  848. const string
  849. getEncodedObjectName(const Selection& selection, const CelestiaCore* appCore)
  850. {
  851.     Universe *universe = appCore->getSimulation()->getUniverse();
  852.     string name;
  853.     
  854.     switch (selection.getType())
  855.     {
  856.         case Selection::Type_Body:
  857.             name = getBodyName(universe, selection.body());
  858.             break;
  859.             
  860.         case Selection::Type_Star:
  861.             name = universe->getStarCatalog()->getStarName(*selection.star());
  862.             break;
  863.         case Selection::Type_DeepSky:
  864.             name = universe->getDSOCatalog()->getDSOName(selection.deepsky());
  865.             break;
  866.         case Selection::Type_Location:
  867.             name = selection.location()->getName();
  868.             {
  869.                 Body* parentBody = selection.location()->getParentBody();
  870.                 if (parentBody != NULL)
  871.                     name = getBodyName(universe, parentBody) + ":" + name;
  872.             }
  873.             break;
  874.             
  875.         default:
  876.             return "";
  877.     }
  878.     return Url::encodeString(name);
  879. }