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

parseobject.cpp

Go to the documentation of this file.
00001 // parseobject.cpp
00002 //
00003 // Copyright (C) 2004 Chris Laurel <claurel@shatters.net>
00004 //
00005 // Functions for parsing objects common to star, solar system, and
00006 // deep sky catalogs.
00007 //
00008 // This program is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU General Public License
00010 // as published by the Free Software Foundation; either version 2
00011 // of the License, or (at your option) any later version.
00012 
00013 #include <celutil/debug.h>
00014 #include "parseobject.h"
00015 #include "customorbit.h"
00016 #include "trajmanager.h"
00017 
00018 
00019 using namespace std;
00020 
00021 
00022 bool
00023 ParseDate(Hash* hash, const string& name, double& jd)
00024 {
00025     // Check first for a number value representing a Julian date
00026     if (hash->getNumber(name, jd))
00027         return true;
00028 
00029     string dateString;
00030     if (hash->getString(name, dateString))
00031     {
00032         astro::Date date(1, 1, 1);
00033         if (astro::parseDate(dateString, date))
00034         {
00035             jd = (double) date;
00036             return true;
00037         }
00038     }
00039 
00040     return false;
00041 }
00042 
00043 
00044 static EllipticalOrbit*
00045 CreateEllipticalOrbit(Hash* orbitData,
00046                       bool usePlanetUnits)
00047 {
00048     // SemiMajorAxis and Period are absolutely required; everything
00049     // else has a reasonable default.
00050     double pericenterDistance = 0.0;
00051     double semiMajorAxis = 0.0;
00052     if (!orbitData->getNumber("SemiMajorAxis", semiMajorAxis))
00053     {
00054         if (!orbitData->getNumber("PericenterDistance", pericenterDistance))
00055         {
00056             DPRINTF(0, "SemiMajorAxis/PericenterDistance missing!  Skipping planet . . .\n");
00057             return NULL;
00058         }
00059     }
00060 
00061     double period = 0.0;
00062     if (!orbitData->getNumber("Period", period))
00063     {
00064         DPRINTF(0, "Period missing!  Skipping planet . . .\n");
00065         return NULL;
00066     }
00067 
00068     double eccentricity = 0.0;
00069     orbitData->getNumber("Eccentricity", eccentricity);
00070 
00071     double inclination = 0.0;
00072     orbitData->getNumber("Inclination", inclination);
00073 
00074     double ascendingNode = 0.0;
00075     orbitData->getNumber("AscendingNode", ascendingNode);
00076 
00077     double argOfPericenter = 0.0;
00078     if (!orbitData->getNumber("ArgOfPericenter", argOfPericenter))
00079     {
00080         double longOfPericenter = 0.0;
00081         if (orbitData->getNumber("LongOfPericenter", longOfPericenter))
00082             argOfPericenter = longOfPericenter - ascendingNode;
00083     }
00084 
00085     double epoch = astro::J2000;
00086     ParseDate(orbitData, "Epoch", epoch);
00087 
00088     // Accept either the mean anomaly or mean longitude--use mean anomaly
00089     // if both are specified.
00090     double anomalyAtEpoch = 0.0;
00091     if (!orbitData->getNumber("MeanAnomaly", anomalyAtEpoch))
00092     {
00093         double longAtEpoch = 0.0;
00094         if (orbitData->getNumber("MeanLongitude", longAtEpoch))
00095             anomalyAtEpoch = longAtEpoch - (argOfPericenter + ascendingNode);
00096     }
00097 
00098     if (usePlanetUnits)
00099     {
00100         semiMajorAxis = astro::AUtoKilometers(semiMajorAxis);
00101         pericenterDistance = astro::AUtoKilometers(pericenterDistance);
00102         period = period * 365.25f;
00103     }
00104 
00105     // If we read the semi-major axis, use it to compute the pericenter
00106     // distance.
00107     if (semiMajorAxis != 0.0)
00108         pericenterDistance = semiMajorAxis * (1.0 - eccentricity);
00109 
00110     return new EllipticalOrbit(pericenterDistance,
00111                                eccentricity,
00112                                degToRad(inclination),
00113                                degToRad(ascendingNode),
00114                                degToRad(argOfPericenter),
00115                                degToRad(anomalyAtEpoch),
00116                                period,
00117                                epoch);
00118 }
00119 
00120 
00121 Orbit*
00122 CreateOrbit(PlanetarySystem* system,
00123             Hash* planetData,
00124             const string& path,
00125             bool usePlanetUnits)
00126 {
00127     Orbit* orbit = NULL;
00128 
00129     string customOrbitName;
00130     if (planetData->getString("CustomOrbit", customOrbitName))
00131     {
00132         orbit = GetCustomOrbit(customOrbitName);
00133         if (orbit != NULL)
00134         {
00135             return orbit;
00136         }
00137         DPRINTF(0, "Could not find custom orbit named '%s'\n",
00138                 customOrbitName.c_str());
00139     }
00140 
00141     string sampOrbitFile;
00142     if (planetData->getString("SampledOrbit", sampOrbitFile))
00143     {
00144         DPRINTF(1, "Attempting to load sampled orbit file '%s'\n",
00145                 sampOrbitFile.c_str());
00146         ResourceHandle orbitHandle =
00147             GetTrajectoryManager()->getHandle(TrajectoryInfo(sampOrbitFile, path));
00148         orbit = GetTrajectoryManager()->find(orbitHandle);
00149         if (orbit != NULL)
00150         {
00151             return orbit;
00152         }
00153         DPRINTF(0, "Could not load sampled orbit file '%s'\n",
00154                 sampOrbitFile.c_str());
00155     }
00156 
00157     Value* orbitDataValue = planetData->getValue("EllipticalOrbit");
00158     if (orbitDataValue != NULL)
00159     {
00160         if (orbitDataValue->getType() != Value::HashType)
00161         {
00162             DPRINTF(0, "Object has incorrect elliptical orbit syntax.\n");
00163             return NULL;
00164         }
00165         else
00166         {
00167             return CreateEllipticalOrbit(orbitDataValue->getHash(),
00168                                          usePlanetUnits);
00169         }
00170     }
00171 
00172     Vec3d longlat(0.0, 0.0, 0.0);
00173     if (planetData->getVector("LongLat", longlat) && system != NULL)
00174     {
00175         Body* parent = system->getPrimaryBody();
00176         if (parent != NULL)
00177         {
00178             Vec3f pos = parent->planetocentricToCartesian((float) longlat.x, (float) longlat.y, (float) longlat.z);
00179             Point3d posd(pos.x, pos.y, pos.z);
00180             return new SynchronousOrbit(*parent, posd);
00181         }
00182         else
00183         {
00184             // TODO: Allow fixing objects to the surface of stars.
00185         }
00186         return NULL;
00187     }
00188 
00189     return NULL;
00190 }
00191 
00192 
00193 void
00194 FillinRotationElements(Hash* rotationData, RotationElements& re)
00195 {
00196     float period = 0.0f;
00197     if (rotationData->getNumber("RotationPeriod", period))
00198         re.period = period / 24.0f;
00199 
00200     float offset = 0.0f;
00201     if (rotationData->getNumber("RotationOffset", offset))
00202         re.offset = degToRad(offset);
00203 
00204     rotationData->getNumber("RotationEpoch", re.epoch);
00205 
00206     float obliquity = 0.0f;
00207     if (rotationData->getNumber("Obliquity", obliquity))
00208         re.obliquity = degToRad(obliquity);
00209 
00210     float ascendingNode = 0.0f;
00211     if (rotationData->getNumber("EquatorAscendingNode", ascendingNode))
00212         re.ascendingNode = degToRad(ascendingNode);
00213 
00214     float precessionRate = 0.0f;
00215     if (rotationData->getNumber("PrecessionRate", precessionRate))
00216         re.precessionRate = degToRad(precessionRate);
00217 }
00218 
00219 

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