celestia/src/celengine/starbrowser.cpp

231 lines
5.9 KiB
C++
Raw Normal View History

2002-01-14 12:17:06 -07:00
// starbrowser.cpp
//
2002-01-14 12:17:06 -07:00
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// Star browser tool for Celestia.
//
// 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 <string>
#include <algorithm>
#include <set>
#include "starbrowser.h"
2009-07-15 21:27:11 -06:00
using namespace Eigen;
2002-11-02 17:20:19 -07:00
using namespace std;
2002-01-14 12:17:06 -07:00
struct CloserStarPredicate
{
2009-07-15 21:27:11 -06:00
Vector3f pos;
2002-01-14 12:17:06 -07:00
bool operator()(const Star* star0, const Star* star1) const
{
2022-02-09 06:20:32 -07:00
return (pos - star0->getPosition()).squaredNorm() < (pos - star1->getPosition()).squaredNorm();
2002-01-14 12:17:06 -07:00
}
};
struct BrighterStarPredicate
{
2009-07-15 21:27:11 -06:00
Vector3f pos;
2002-01-14 12:17:06 -07:00
UniversalCoord ucPos;
bool operator()(const Star* star0, const Star* star1) const
{
2022-02-09 06:20:32 -07:00
float d0 = (pos - star0->getPosition()).norm();
float d1 = (pos - star1->getPosition()).norm();
// If the stars are closer than one light year, use
// a more precise distance estimate.
if (d0 < 1.0f)
d0 = ucPos.offsetFromLy(star0->getPosition()).norm();
if (d1 < 1.0f)
d1 = ucPos.offsetFromLy(star1->getPosition()).norm();
2002-01-14 12:17:06 -07:00
2022-02-09 06:20:32 -07:00
return star0->getApparentMagnitude(d0) < star1->getApparentMagnitude(d1);
2002-01-14 12:17:06 -07:00
}
};
struct BrightestStarPredicate
{
bool operator()(const Star* star0, const Star* star1) const
{
2022-02-09 06:20:32 -07:00
return star0->getAbsoluteMagnitude() < star1->getAbsoluteMagnitude();
2002-01-14 12:17:06 -07:00
}
};
struct SolarSystemPredicate
{
2009-07-15 21:27:11 -06:00
Vector3f pos;
2002-01-14 12:17:06 -07:00
SolarSystemCatalog* solarSystems;
bool operator()(const Star* star0, const Star* star1) const
{
SolarSystemCatalog::iterator iter;
iter = solarSystems->find(star0->getIndex());
2002-01-14 12:17:06 -07:00
bool hasPlanets0 = (iter != solarSystems->end());
iter = solarSystems->find(star1->getIndex());
2002-01-14 12:17:06 -07:00
bool hasPlanets1 = (iter != solarSystems->end());
if (hasPlanets1 == hasPlanets0)
{
2022-02-09 06:20:32 -07:00
return ((pos - star0->getPosition()).squaredNorm() < (pos - star1->getPosition()).squaredNorm());
2002-01-14 12:17:06 -07:00
}
else
{
return hasPlanets0;
}
}
};
// Find the nearest/brightest/X-est N stars in a database. The
// supplied predicate determines which of two stars is a better match.
template<class Pred> static std::vector<const Star*>*
2002-01-14 12:17:06 -07:00
findStars(const StarDatabase& stardb, Pred pred, int nStars)
{
std::vector<const Star*>* finalStars = new std::vector<const Star*>();
2002-01-14 12:17:06 -07:00
if (nStars == 0)
return finalStars;
if(nStars > 500)
nStars = 500;
2002-01-14 12:17:06 -07:00
typedef std::multiset<const Star*, Pred> StarSet;
2002-01-14 12:17:06 -07:00
StarSet firstStars(pred);
int totalStars = stardb.size();
if (totalStars < nStars)
nStars = totalStars;
// We'll need at least nStars in the set, so first fill
// up the list indiscriminately.
int i = 0;
for (i = 0; i < nStars; i++)
firstStars.insert(stardb.getStar(i));
// From here on, only add a star to the set if it's
// a better match than the worst matching star already
// in the set.
const Star* lastStar = *--firstStars.end();
for (; i < totalStars; i++)
{
Star* star = stardb.getStar(i);
if (pred(star, lastStar))
{
firstStars.insert(star);
firstStars.erase(--firstStars.end());
lastStar = *--firstStars.end();
}
}
// Move the best matching stars into the vector
finalStars->reserve(nStars);
for (const auto& star : firstStars)
finalStars->push_back(star);
2002-01-14 12:17:06 -07:00
return finalStars;
}
const Star* StarBrowser::nearestStar()
2002-01-14 12:17:06 -07:00
{
Universe* univ = appSim->getUniverse();
CloserStarPredicate closerPred;
closerPred.pos = pos;
std::vector<const Star*>* stars = findStars(*(univ->getStarCatalog()), closerPred, 1);
const Star *star = (*stars)[0];
2002-01-14 12:17:06 -07:00
delete stars;
return star;
}
std::vector<const Star*>*
2002-01-14 12:17:06 -07:00
StarBrowser::listStars(unsigned int nStars)
{
Universe* univ = appSim->getUniverse();
switch(predicate)
{
case BrighterStars:
{
BrighterStarPredicate brighterPred;
brighterPred.pos = pos;
2002-01-14 12:17:06 -07:00
brighterPred.ucPos = ucPos;
return findStars(*(univ->getStarCatalog()), brighterPred, nStars);
}
break;
2002-01-14 12:17:06 -07:00
case BrightestStars:
{
BrightestStarPredicate brightestPred;
return findStars(*(univ->getStarCatalog()), brightestPred, nStars);
}
break;
2002-01-14 12:17:06 -07:00
case StarsWithPlanets:
{
SolarSystemCatalog* solarSystems = univ->getSolarSystemCatalog();
if (!solarSystems)
return nullptr;
2002-01-14 12:17:06 -07:00
SolarSystemPredicate solarSysPred;
solarSysPred.pos = pos;
2002-01-14 12:17:06 -07:00
solarSysPred.solarSystems = solarSystems;
return findStars(*(univ->getStarCatalog()), solarSysPred,
min((size_t) nStars, solarSystems->size()));
2002-01-14 12:17:06 -07:00
}
break;
2002-01-14 12:17:06 -07:00
case NearestStars:
default:
{
CloserStarPredicate closerPred;
closerPred.pos = pos;
2002-01-14 12:17:06 -07:00
return findStars(*(univ->getStarCatalog()), closerPred, nStars);
}
break;
}
return nullptr; // keep compiler happy
2002-01-14 12:17:06 -07:00
}
bool StarBrowser::setPredicate(int pred)
2002-01-14 12:17:06 -07:00
{
if ((pred < NearestStars) || (pred > StarsWithPlanets))
2002-01-14 12:17:06 -07:00
return false;
predicate = pred;
2002-01-14 12:17:06 -07:00
return true;
}
2002-01-14 12:17:06 -07:00
void StarBrowser::refresh()
{
ucPos = appSim->getObserver().getPosition();
pos = ucPos.toLy().cast<float>();
2002-01-14 12:17:06 -07:00
}
2002-01-14 12:17:06 -07:00
void StarBrowser::setSimulation(Simulation *_appSim)
{
appSim = _appSim;
2002-01-14 12:17:06 -07:00
refresh();
}
2002-01-14 12:17:06 -07:00
StarBrowser::StarBrowser(Simulation* _appSim, int pred) :
appSim(_appSim)
{
ucPos = appSim->getObserver().getPosition();
pos = ucPos.toLy().cast<float>();
2002-01-14 12:17:06 -07:00
predicate = pred;
}
2002-01-14 12:17:06 -07:00
StarBrowser::StarBrowser() :
pos(Vector3f::Zero()),
ucPos(UniversalCoord::Zero()),
appSim(nullptr),
2002-01-14 12:17:06 -07:00
predicate(NearestStars)
{
}