Remove old EclipseFinder API and cleanup

pull/3/head
Hleb Valoshka 2019-05-05 23:47:18 +03:00
parent 7472122e38
commit dc6e86edbf
2 changed files with 90 additions and 282 deletions

View File

@ -11,12 +11,8 @@
// of the License, or (at your option) any later version.
#include <cstring>
#include <sstream>
#include <algorithm>
#include <set>
#include <cassert>
#include "eclipsefinder.h"
#include "celmath/mathlib.h"
#include "celmath/ray.h"
#include "celmath/distance.h"
@ -24,27 +20,13 @@ using namespace Eigen;
using namespace std;
constexpr const double dT = 1.0 / (24.0 * 60.0);
constexpr const int EclipseObjectMask = Body::Planet |
Body::Moon |
Body::MinorMoon |
Body::DwarfPlanet |
Body::Asteroid;
Eclipse::Eclipse(int Y, int M, int D)
{
date = new astro::Date(Y, M, D);
}
Eclipse::Eclipse(double JD)
{
date = new astro::Date(JD);
}
Eclipse::~Eclipse()
{
delete date;
}
// TODO: share this constant and function with render.cpp
static const float MinRelativeOccluderRadius = 0.005f;
@ -55,8 +37,8 @@ EclipseFinder::EclipseFinder(Body* _body,
{
};
bool EclipseFinder::testEclipse(const Body& receiver, const Body& caster,
double now) const
bool testEclipse(const Body& receiver, const Body& caster, double now)
{
// Ignore situations where the shadow casting body is much smaller than
// the receiver, as these shadows aren't likely to be relevant. Also,
@ -115,9 +97,9 @@ bool EclipseFinder::testEclipse(const Body& receiver, const Body& caster,
return false;
}
double EclipseFinder::findEclipseSpan(const Body& receiver, const Body& caster,
double now, double dt) const
#if 1
double findEclipseSpan(const Body& receiver, const Body& caster,
double now, double dt)
{
double t = now;
while (testEclipse(receiver, caster, t))
@ -125,117 +107,94 @@ double EclipseFinder::findEclipseSpan(const Body& receiver, const Body& caster,
return t;
}
int EclipseFinder::CalculateEclipses() // XXX: this function is very fragile and should be rewritten
#else
// Given a time during an eclipse, find the start of the eclipse to
// a precision of minStep.
double findEclipseStart(const Body& receiver, const Body& occulter,
double now,
double startStep,
double minStep)
{
Simulation* sim = appCore->getSimulation();
double step = startStep / 2;
double t = now - step;
bool eclipsed = true;
Eclipse* eclipse;
double* JDback = nullptr;
int nIDplanetetofindon = 0;
int nSattelites = 0;
const SolarSystem* sys = sim->getNearestSolarSystem();
toProcess = false;
if ((!sys))
// Perform a binary search to find the end of the eclipse
while (step > minStep)
{
eclipse = new Eclipse(0.);
eclipse->planete = "None";
Eclipses_.push_back(*eclipse);
delete eclipse;
return 1;
}
if (sys->getStar()->getCatalogNumber() != 0)
{
eclipse = new Eclipse(0.);
eclipse->planete = "None";
Eclipses_.push_back(*eclipse);
delete eclipse;
return 1;
eclipsed = testEclipse(receiver, occulter, t);
step *= 0.5;
if (eclipsed)
t -= step;
else
t += step;
}
PlanetarySystem* system = sys->getPlanets();
int nbPlanets = system->getSystemSize();
// Always return a time when the receiver is /not/ in eclipse
if (eclipsed)
t -= step;
for (int i = 0; i < nbPlanets; ++i)
return t;
}
// Given a time during an eclipse, find the end of the eclipse to
// a precision of minStep.
double findEclipseEnd(const Body& receiver, const Body& occulter,
double now,
double startStep,
double minStep)
{
// First do a coarse search to find the eclipse end to within the precision
// of startStep.
while (testEclipse(receiver, occulter, now + startStep))
now += startStep;
double step = startStep / 2;
double t = now + step;
bool eclipsed = true;
// Perform a binary search to find the end of the eclipse
while (step > minStep)
{
Body* planete = system->getBody(i);
if (planete != nullptr)
if (strPlaneteToFindOn == planete->getName())
{
nIDplanetetofindon = i;
PlanetarySystem* satellites = planete->getSatellites();
if (satellites)
{
nSattelites = satellites->getSystemSize();
JDback = new double[nSattelites];
memset(JDback, 0, nSattelites*sizeof(double));
}
break;
}
eclipsed = testEclipse(receiver, occulter, t);
step *= 0.5;
if (eclipsed)
t += step;
else
t -= step;
}
Body* planete = system->getBody(nIDplanetetofindon);
while (JDfrom < JDto)
// Always return a time when the receiver is /not/ in eclipse
if (eclipsed)
t += step;
return t;
}
#endif
void addEclipse(const Body& receiver, const Body& occulter,
double now,
double /*startStep*/, double /*minStep*/,
vector<Eclipse>& eclipses,
vector<double>& previousEclipseEndTimes, int i)
{
if (testEclipse(receiver, occulter, now))
{
PlanetarySystem* satellites = planete->getSatellites();
if (satellites)
{
for (int j = 0; j < nSattelites; ++j)
{
Body* caster = nullptr;
Body* receiver = nullptr;
bool test = false;
Eclipse eclipse;
#if 1
eclipse.startTime = findEclipseSpan(receiver, occulter, now, -dT);
eclipse.endTime = findEclipseSpan(receiver, occulter, now, dT);
#else
eclipse.startTime = findEclipseStart(receiver, occulter, now, searchStep, minStep);
eclipse.endTime = findEclipseEnd(receiver, occulter, now, searchStep, minStep);
#endif
eclipse.receiver = const_cast<Body*>(&receiver);
eclipse.occulter = const_cast<Body*>(&occulter);
eclipses.emplace_back(eclipse);
if (satellites->getBody(j)->getClassification() != Body::Spacecraft)
{
if (type == Eclipse::Solar)
{
caster = satellites->getBody(j);
receiver = planete;
}
else
{
caster = planete;
receiver = satellites->getBody(j);
}
test = testEclipse(*receiver, *caster, JDfrom);
}
if (test && JDfrom - JDback[j] > 1)
{
JDback[j] = JDfrom;
eclipse = new Eclipse(JDfrom);
eclipse->startTime = findEclipseSpan(*receiver, *caster,
JDfrom,
-1.0 / (24.0 * 60.0));
eclipse->endTime = findEclipseSpan(*receiver, *caster,
JDfrom,
1.0 / (24.0 * 60.0));
eclipse->body = receiver;
eclipse->planete = planete->getName();
eclipse->sattelite = satellites->getBody(j)->getName();
Eclipses_.push_back(*eclipse);
delete eclipse;
}
}
}
JDfrom += 1.0 / 24.0;
previousEclipseEndTimes[i] = eclipse.endTime;
}
delete[] JDback;
if (Eclipses_.empty())
{
eclipse = new Eclipse(0.);
eclipse->planete = "None";
Eclipses_.push_back(*eclipse);
delete eclipse;
}
return 0;
}
void EclipseFinder::findEclipses(double startDate,
@ -286,124 +245,16 @@ void EclipseFinder::findEclipses(double startDate,
for (unsigned int i = 0; i < testBodies.size(); i++)
{
Body* occulter = nullptr;
Body* receiver = nullptr;
if (eclipseTypeMask == Eclipse::Solar)
{
occulter = testBodies[i];
receiver = body;
}
else
{
occulter = body;
receiver = testBodies[i];
}
// Only test for an eclipse if we're not in the middle of
// of previous one.
if (t > previousEclipseEndTimes[i])
{
if (eclipseTypeMask & Eclipse::Solar)
{
occulter = testBodies[i];
receiver = body;
if (t <= previousEclipseEndTimes[i])
continue;
if (testEclipse(*receiver, *occulter, t))
{
Eclipse eclipse;
eclipse.startTime = findEclipseStart(*receiver, *occulter, t, searchStep, durationPrecision);
eclipse.endTime = findEclipseEnd(*receiver, *occulter, t, searchStep, durationPrecision);
eclipse.receiver = receiver;
eclipse.occulter = occulter;
eclipses.push_back(eclipse);
if (eclipseTypeMask & Eclipse::Solar)
addEclipse(*body, *testBodies[i], t, searchStep, durationPrecision, eclipses, previousEclipseEndTimes, i);
previousEclipseEndTimes[i] = eclipse.endTime;
}
}
if (eclipseTypeMask & Eclipse::Lunar)
{
occulter = body;
receiver = testBodies[i];
if (testEclipse(*receiver, *occulter, t))
{
Eclipse eclipse;
eclipse.startTime = findEclipseStart(*receiver, *occulter, t, searchStep, durationPrecision);
eclipse.endTime = findEclipseEnd(*receiver, *occulter, t, searchStep, durationPrecision);
eclipse.receiver = receiver;
eclipse.occulter = occulter;
eclipses.push_back(eclipse);
previousEclipseEndTimes[i] = eclipse.endTime;
}
}
}
if (eclipseTypeMask & Eclipse::Lunar)
addEclipse(*testBodies[i], *body, t, searchStep, durationPrecision, eclipses, previousEclipseEndTimes, i);
}
}
}
// Given a time during an eclipse, find the start of the eclipse to
// a precision of minStep.
double EclipseFinder::findEclipseStart(const Body& receiver, const Body& occulter,
double now,
double startStep,
double minStep) const
{
double step = startStep / 2;
double t = now - step;
bool eclipsed = true;
// Perform a binary search to find the end of the eclipse
while (step > minStep)
{
eclipsed = testEclipse(receiver, occulter, t);
step *= 0.5;
if (eclipsed)
t -= step;
else
t += step;
}
// Always return a time when the receiver is /not/ in eclipse
if (eclipsed)
t -= step;
return t;
}
// Given a time during an eclipse, find the end of the eclipse to
// a precision of minStep.
double EclipseFinder::findEclipseEnd(const Body& receiver, const Body& occulter,
double now,
double startStep,
double minStep) const
{
// First do a coarse search to find the eclipse end to within the precision
// of startStep.
while (testEclipse(receiver, occulter, now + startStep))
now += startStep;
double step = startStep / 2;
double t = now + step;
bool eclipsed = true;
// Perform a binary search to find the end of the eclipse
while (step > minStep)
{
eclipsed = testEclipse(receiver, occulter, t);
step *= 0.5;
if (eclipsed)
t += step;
else
t -= step;
}
// Always return a time when the receiver is /not/ in eclipse
if (eclipsed)
t += step;
return t;
}

View File

@ -16,30 +16,17 @@
#include <vector>
#include "celestiacore.h"
class Eclipse
struct Eclipse
{
public:
Eclipse() = default;
Eclipse(int Y, int M, int D);
Eclipse(double JD);
~Eclipse();
// values must be 2^n
enum Type {
Solar = 0x01,
Moon = 0x02,
Lunar = 0x02
};
public:
Body* body{ nullptr };
Body* occulter{ nullptr };
Body* receiver{ nullptr };
std::string planete;
std::string sattelite;
astro::Date* date{ nullptr };
double startTime{ 0.0 };
double endTime{ 0.0 };
};
@ -59,43 +46,13 @@ class EclipseFinderWatcher
class EclipseFinder
{
public:
EclipseFinder(Body*, EclipseFinderWatcher* _watcher);
EclipseFinder(CelestiaCore* core,
const std::string& strPlaneteToFindOn_,
Eclipse::Type type_,
double from,
double to )
:appCore(core),
strPlaneteToFindOn(strPlaneteToFindOn_),
type(type_),
JDfrom(from),
JDto(to),
toProcess(true) {};
EclipseFinder(Body*, EclipseFinderWatcher* = nullptr);
void findEclipses(double startDate,
double endDate,
int eclipseTypeMask,
vector<Eclipse>& eclipses);
const std::vector<Eclipse>& getEclipses() { if (toProcess) CalculateEclipses(); return Eclipses_; };
private:
CelestiaCore* appCore;
std::vector<Eclipse> Eclipses_;
std::string strPlaneteToFindOn;
Eclipse::Type type;
double JDfrom, JDto;
bool toProcess;
double findEclipseStart(const Body& recever, const Body& occulter, double now, double startStep, double minStep) const;
double findEclipseEnd(const Body& recever, const Body& occulter, double now, double startStep, double minStep) const;
int CalculateEclipses();
bool testEclipse(const Body& receiver, const Body& caster, double now) const;
double findEclipseSpan(const Body& receiver, const Body& caster, double now, double dt) const;
Body* body;
EclipseFinderWatcher* watcher;
};