212 lines
5.1 KiB
C++
212 lines
5.1 KiB
C++
// selection.cpp
|
|
//
|
|
// Copyright (C) 2001-2009, the Celestia Development Team
|
|
// Original version by Chris Laurel <claurel@gmail.com>
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
|
|
#include <cassert>
|
|
#include "astro.h"
|
|
#include "selection.h"
|
|
#include "frametree.h"
|
|
#include <celengine/star.h>
|
|
#include <celengine/body.h>
|
|
#include <celengine/location.h>
|
|
#include <celengine/deepskyobj.h>
|
|
#include <fmt/printf.h>
|
|
|
|
using namespace Eigen;
|
|
using namespace std;
|
|
|
|
|
|
// Some velocities are computed by differentiation; units
|
|
// are Julian days.
|
|
static const double VELOCITY_DIFF_DELTA = 1.0 / 1440.0;
|
|
|
|
|
|
double Selection::radius() const
|
|
{
|
|
switch (type)
|
|
{
|
|
case Type_Star:
|
|
return star()->getRadius();
|
|
case Type_Body:
|
|
return body()->getRadius();
|
|
case Type_DeepSky:
|
|
return astro::lightYearsToKilometers(deepsky()->getRadius());
|
|
case Type_Location:
|
|
// The size of a location is its diameter, so divide by 2.
|
|
return location()->getSize() / 2.0f;
|
|
default:
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
|
|
UniversalCoord Selection::getPosition(double t) const
|
|
{
|
|
switch (type)
|
|
{
|
|
case Type_Body:
|
|
return body()->getPosition(t);
|
|
|
|
case Type_Star:
|
|
return star()->getPosition(t);
|
|
|
|
case Type_DeepSky:
|
|
{
|
|
// NOTE: cast to single precision is only present to maintain compatibility with
|
|
// Celestia 1.6.0.
|
|
Vector3f p = deepsky()->getPosition().cast<float>();
|
|
return UniversalCoord::CreateLy(p.cast<double>());
|
|
}
|
|
|
|
case Type_Location:
|
|
{
|
|
Body* body = location()->getParentBody();
|
|
if (body != nullptr)
|
|
{
|
|
return body->getPosition(t).offsetKm(location()->getPlanetocentricPosition(t));
|
|
}
|
|
else
|
|
{
|
|
// Bad location; all locations should have a parent.
|
|
assert(0);
|
|
return UniversalCoord::Zero();
|
|
}
|
|
}
|
|
|
|
default:
|
|
return UniversalCoord::Zero();
|
|
}
|
|
}
|
|
|
|
|
|
Vector3d Selection::getVelocity(double t) const
|
|
{
|
|
switch (type)
|
|
{
|
|
case Type_Body:
|
|
return body()->getVelocity(t);
|
|
|
|
case Type_Star:
|
|
return star()->getVelocity(t);
|
|
|
|
case Type_DeepSky:
|
|
return Vector3d::Zero();
|
|
|
|
case Type_Location:
|
|
{
|
|
// For now, just use differentiation for location velocities.
|
|
return getPosition(t).offsetFromKm(getPosition(t - VELOCITY_DIFF_DELTA)) / VELOCITY_DIFF_DELTA;
|
|
}
|
|
|
|
default:
|
|
return Vector3d::Zero();
|
|
}
|
|
}
|
|
|
|
|
|
string Selection::getName(bool i18n) const
|
|
{
|
|
switch (type)
|
|
{
|
|
case Type_Star:
|
|
return fmt::sprintf("#%u", star()->getIndex());
|
|
|
|
case Type_DeepSky:
|
|
return fmt::sprintf("#%u", deepsky()->getIndex());
|
|
|
|
case Type_Body:
|
|
{
|
|
string name = body()->getName(i18n);
|
|
PlanetarySystem* system = body()->getSystem();
|
|
while (system != nullptr)
|
|
{
|
|
Body* parent = system->getPrimaryBody();
|
|
if (parent != nullptr)
|
|
{
|
|
name = parent->getName(i18n) + '/' + name;
|
|
system = parent->getSystem();
|
|
}
|
|
else
|
|
{
|
|
const Star* parentStar = system->getStar();
|
|
if (parentStar != nullptr)
|
|
name = fmt::sprintf("#%u/%s", parentStar->getIndex(), name);
|
|
system = nullptr;
|
|
}
|
|
}
|
|
return name;
|
|
}
|
|
|
|
case Type_Location:
|
|
if (location()->getParentBody() == nullptr)
|
|
{
|
|
return location()->getName(i18n);
|
|
}
|
|
else
|
|
{
|
|
return Selection(location()->getParentBody()).getName(i18n) + '/' +
|
|
location()->getName(i18n);
|
|
}
|
|
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
|
|
Selection Selection::parent() const
|
|
{
|
|
switch (type)
|
|
{
|
|
case Type_Location:
|
|
return Selection(location()->getParentBody());
|
|
|
|
case Type_Body:
|
|
if (body()->getSystem())
|
|
{
|
|
if (body()->getSystem()->getPrimaryBody() != nullptr)
|
|
return Selection(body()->getSystem()->getPrimaryBody());
|
|
else
|
|
return Selection(body()->getSystem()->getStar());
|
|
}
|
|
else
|
|
{
|
|
return Selection();
|
|
}
|
|
break;
|
|
|
|
case Type_Star:
|
|
return Selection(star()->getOrbitBarycenter());
|
|
|
|
case Type_DeepSky:
|
|
// Currently no hierarchy for stars and deep sky objects.
|
|
return Selection();
|
|
|
|
default:
|
|
return Selection();
|
|
}
|
|
}
|
|
|
|
|
|
/*! Return true if the selection's visibility flag is set. */
|
|
bool Selection::isVisible() const
|
|
{
|
|
switch (type)
|
|
{
|
|
case Type_Body:
|
|
return body()->isVisible();
|
|
case Type_Star:
|
|
return true;
|
|
case Type_DeepSky:
|
|
return deepsky()->isVisible();
|
|
default:
|
|
return false;
|
|
}
|
|
}
|