00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <string>
00014 #include <sstream>
00015 #include <algorithm>
00016 #include <set>
00017 #include <cassert>
00018 #include "eclipsefinder.h"
00019 #include "celmath/mathlib.h"
00020 #include "celmath/ray.h"
00021 #include "celmath/distance.h"
00022
00023 using namespace std;
00024
00025 Eclipse::Eclipse(int Y, int M, int D) :
00026 body(NULL)
00027 {
00028 date = new astro::Date(Y, M, D);
00029 }
00030
00031 Eclipse::Eclipse(double JD) :
00032 body(NULL)
00033 {
00034 date = new astro::Date(JD);
00035 }
00036
00037
00038 bool EclipseFinder::testEclipse(const Body& receiver, const Body& caster,
00039 double now) const
00040 {
00041
00042
00043
00044
00045 if (caster.getRadius() * 100 >= receiver.getRadius() &&
00046 caster.getModel() == InvalidResource)
00047 {
00048
00049
00050
00051
00052
00053
00054
00055
00056 Point3d posReceiver = receiver.getHeliocentricPosition(now);
00057 Point3d posCaster = caster.getHeliocentricPosition(now);
00058
00059 const Star* sun = receiver.getSystem()->getStar();
00060 assert(sun != NULL);
00061 double distToSun = posReceiver.distanceFromOrigin();
00062 float appSunRadius = (float) (sun->getRadius() / distToSun);
00063
00064 Vec3d dir = posCaster - posReceiver;
00065 double distToCaster = dir.length() - receiver.getRadius();
00066 float appOccluderRadius = (float) (caster.getRadius() / distToCaster);
00067
00068
00069
00070
00071
00072 float shadowRadius = (1 + appSunRadius / appOccluderRadius) *
00073 caster.getRadius();
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 float R = receiver.getRadius() + shadowRadius;
00085 double dist = distance(posReceiver,
00086 Ray3d(posCaster, posCaster - Point3d(0, 0, 0)));
00087 if (dist < R)
00088 {
00089 return true;
00090 }
00091 }
00092
00093 return false;
00094 }
00095
00096
00097 double EclipseFinder::findEclipseSpan(const Body& receiver, const Body& caster,
00098 double now, double dt) const
00099 {
00100 double t = now;
00101 while (testEclipse(receiver, caster, t))
00102 t += dt;
00103
00104 return t;
00105 }
00106
00107
00108 int EclipseFinder::CalculateEclipses()
00109 {
00110 Simulation* sim = appCore->getSimulation();
00111
00112 Eclipse* eclipse;
00113 double* JDback = NULL;
00114
00115 int nIDplanetetofindon = 0;
00116 int nSattelites = 0;
00117
00118 const SolarSystem* sys = sim->getNearestSolarSystem();
00119
00120 toProcess = false;
00121
00122 if ((!sys))
00123 {
00124 eclipse = new Eclipse(0.);
00125 eclipse->planete = "None";
00126 Eclipses_.insert(Eclipses_.end(), *eclipse);
00127 delete eclipse;
00128 return 1;
00129 }
00130 else if (sys->getStar()->getCatalogNumber() != 0)
00131 {
00132 eclipse = new Eclipse(0.);
00133 eclipse->planete = "None";
00134 Eclipses_.insert(Eclipses_.end(), *eclipse);
00135 delete eclipse;
00136 return 1;
00137 }
00138
00139 PlanetarySystem* system = sys->getPlanets();
00140 int nbPlanets = system->getSystemSize();
00141
00142 for (int i = 0; i < nbPlanets; ++i)
00143 {
00144 Body* planete = system->getBody(i);
00145 if (planete != NULL)
00146 if (strPlaneteToFindOn == planete->getName())
00147 {
00148 nIDplanetetofindon = i;
00149 PlanetarySystem* satellites = planete->getSatellites();
00150 if (satellites)
00151 {
00152 nSattelites = satellites->getSystemSize();
00153 JDback = new double[nSattelites];
00154 memset(JDback, 0, nSattelites*sizeof(double));
00155 }
00156 break;
00157 }
00158 }
00159
00160 Body* planete = system->getBody(nIDplanetetofindon);
00161 while (JDfrom < JDto)
00162 {
00163 PlanetarySystem* satellites = planete->getSatellites();
00164 if (satellites)
00165 {
00166 for (int j = 0; j < nSattelites; ++j)
00167 {
00168 Body* caster = NULL;
00169 Body* receiver = NULL;
00170 bool test = false;
00171
00172 if (satellites->getBody(j)->getClassification() != Body::Spacecraft)
00173 {
00174 if (type == Eclipse::Solar)
00175 {
00176 caster = satellites->getBody(j);
00177 receiver = planete;
00178 }
00179 else
00180 {
00181 caster = planete;
00182 receiver = satellites->getBody(j);
00183 }
00184
00185 test = testEclipse(*receiver, *caster, JDfrom);
00186 }
00187
00188 if (test && JDfrom - JDback[j] > 1)
00189 {
00190 JDback[j] = JDfrom;
00191 eclipse = new Eclipse(JDfrom);
00192 eclipse->startTime = findEclipseSpan(*receiver, *caster,
00193 JDfrom,
00194 -1.0 / (24.0 * 60.0));
00195 eclipse->endTime = findEclipseSpan(*receiver, *caster,
00196 JDfrom,
00197 1.0 / (24.0 * 60.0));
00198 eclipse->body = receiver;
00199 eclipse->planete = planete->getName();
00200 eclipse->sattelite = satellites->getBody(j)->getName();
00201 Eclipses_.insert(Eclipses_.end(), *eclipse);
00202 delete eclipse;
00203 }
00204 }
00205 }
00206 JDfrom += 1.0 / 24.0;
00207 }
00208 if (JDback)
00209 delete JDback;
00210 if (Eclipses_.empty())
00211 {
00212 eclipse = new Eclipse(0.);
00213 eclipse->planete = "None";
00214 Eclipses_.insert(Eclipses_.end(), *eclipse);
00215 delete eclipse;
00216 }
00217 return 0;
00218 }
00219