17
#include "starbrowser.h"
28
namespace celestia::engine
35
distanceSquared(const Star* star,
37
const Eigen::Vector3f& pos,
38
const UniversalCoord& ucPos)
42
float distance = (pos - star->getPosition()).squaredNorm();
47
distance = static_cast<float>((ucPos - star->getPosition(jd)).toLy().squaredNorm());
52
class DistanceComparison
55
DistanceComparison(double jd, const Eigen::Vector3f& pos, const UniversalCoord& ucPos);
57
StarBrowserRecord createRecord(const Star*) const;
58
void finalizeRecord(StarBrowserRecord&) const;
60
bool operator()(const StarBrowserRecord&, const StarBrowserRecord&) const;
64
Eigen::Vector3f m_pos;
65
UniversalCoord m_ucPos;
68
DistanceComparison::DistanceComparison(double jd, const Eigen::Vector3f& pos, const UniversalCoord& ucPos) :
69
m_jd(jd), m_pos(pos), m_ucPos(ucPos)
74
DistanceComparison::createRecord(const Star* star) const
76
StarBrowserRecord result(star);
77
result.distance = distanceSquared(star, m_jd, m_pos, m_ucPos);
82
DistanceComparison::finalizeRecord(StarBrowserRecord& record) const
84
record.distance = std::sqrt(record.distance);
85
record.appMag = record.star->getApparentMagnitude(record.distance);
89
DistanceComparison::operator()(const StarBrowserRecord& lhs, const StarBrowserRecord& rhs) const
91
return lhs.distance < rhs.distance;
97
AppMagComparison(double jd, const Eigen::Vector3f& pos, const UniversalCoord& ucPos);
99
StarBrowserRecord createRecord(const Star*) const;
100
void finalizeRecord(const StarBrowserRecord&) const { }
102
bool operator()(const StarBrowserRecord&, const StarBrowserRecord&) const;
106
Eigen::Vector3f m_pos;
107
UniversalCoord m_ucPos;
110
AppMagComparison::AppMagComparison(double jd, const Eigen::Vector3f& pos, const UniversalCoord& ucPos) :
111
m_jd(jd), m_pos(pos), m_ucPos(ucPos)
116
AppMagComparison::createRecord(const Star* star) const
118
StarBrowserRecord result(star);
119
result.distance = std::sqrt(distanceSquared(star, m_jd, m_pos, m_ucPos));
120
result.appMag = result.star->getApparentMagnitude(result.distance);
125
AppMagComparison::operator()(const StarBrowserRecord& lhs, const StarBrowserRecord& rhs) const
127
return lhs.appMag < rhs.appMag;
130
class AbsMagComparison
133
AbsMagComparison(double jd, const Eigen::Vector3f& pos, const UniversalCoord& ucPos);
135
StarBrowserRecord createRecord(const Star*) const;
136
void finalizeRecord(StarBrowserRecord&) const;
138
bool operator()(const StarBrowserRecord&, const StarBrowserRecord&) const;
142
Eigen::Vector3f m_pos;
143
UniversalCoord m_ucPos;
146
AbsMagComparison::AbsMagComparison(double jd, const Eigen::Vector3f& pos, const UniversalCoord& ucPos) :
147
m_jd(jd), m_pos(pos), m_ucPos(ucPos)
152
AbsMagComparison::createRecord(const Star* star) const
154
return StarBrowserRecord(star);
158
AbsMagComparison::finalizeRecord(StarBrowserRecord& record) const
160
record.distance = std::sqrt(distanceSquared(record.star, m_jd, m_pos, m_ucPos));
161
record.appMag = record.star->getApparentMagnitude(record.distance);
165
AbsMagComparison::operator()(const StarBrowserRecord& lhs, const StarBrowserRecord& rhs) const
167
return lhs.star->getAbsoluteMagnitude() < rhs.star->getAbsoluteMagnitude();
173
StarFilter(StarBrowser::Filter, const SolarSystemCatalog*);
174
bool operator()(const Star*) const;
176
void setSpectralTypeFilter(const std::function<bool(const char*)>&);
179
StarBrowser::Filter m_filter;
180
const SolarSystemCatalog* m_solarSystems;
181
std::function<bool(const char*)> m_spectralTypeFilter{ nullptr };
184
StarFilter::StarFilter(StarBrowser::Filter filter, const SolarSystemCatalog* solarSystems) :
185
m_filter(filter), m_solarSystems(solarSystems)
190
StarFilter::setSpectralTypeFilter(const std::function<bool(const char*)>& filter)
192
m_spectralTypeFilter = filter;
196
parentHasPlanets(const SolarSystemCatalog* solarSystems, const Star* star)
200
const auto end = solarSystems->end();
203
star = star->getOrbitBarycenter();
204
if (star == nullptr || star->getVisibility())
207
if (solarSystems->find(star->getIndex()) != end)
213
StarFilter::operator()(const Star* star) const
216
bool visibleOnly = util::is_set(m_filter, StarBrowser::Filter::Visible);
217
if (visibleOnly && !star->getVisibility())
220
if (util::is_set(m_filter, StarBrowser::Filter::Multiple))
222
auto barycenter = star->getOrbitBarycenter();
226
if (barycenter == nullptr || barycenter->getOrbitingStars().size() < 2)
230
if (util::is_set(m_filter, StarBrowser::Filter::WithPlanets) &&
231
m_solarSystems->find(star->getIndex()) == m_solarSystems->end() &&
232
!(visibleOnly && parentHasPlanets(m_solarSystems, star)))
237
return (util::is_set(m_filter, StarBrowser::Filter::SpectralType) && m_spectralTypeFilter)
238
? m_spectralTypeFilter(star->getSpectralType())
243
void populateRecords(std::vector<StarBrowserRecord>& records,
245
const StarFilter& filter,
247
const StarDatabase& stardb)
253
records.reserve(size);
255
std::uint32_t totalStars = stardb.size();
259
records.reserve(size);
260
std::uint32_t index = 0;
265
if (index == totalStars)
267
std::sort(records.begin(), records.end(), comparison);
268
for (StarBrowserRecord& record : records)
270
comparison.finalizeRecord(record);
275
if (const Star* star = stardb.getStar(index); filter(star))
277
if (records.size() == size)
280
records.push_back(comparison.createRecord(star));
288
std::make_heap(records.begin(), records.end(), comparison);
290
for (; index < totalStars; ++index)
292
const Star* star = stardb.getStar(index);
296
StarBrowserRecord record = comparison.createRecord(star);
297
if (comparison(record, records.front()))
299
std::pop_heap(records.begin(), records.end(), comparison);
300
records.back() = record;
301
std::push_heap(records.begin(), records.end(), comparison);
305
std::sort_heap(records.begin(), records.end(), comparison);
306
for (StarBrowserRecord& record : records)
308
comparison.finalizeRecord(record);
314
StarBrowser::StarBrowser(const Universe* universe,
316
Comparison comparison,
318
m_universe(universe),
320
m_comparison(comparison),
323
if (m_size < MinListStars)
324
m_size = MinListStars;
325
else if (m_size > MaxListStars)
326
m_size = MaxListStars;
330
StarBrowser::setSize(std::uint32_t size)
333
if (m_size < MinListStars)
335
m_size = MinListStars;
338
if (m_size > MaxListStars)
340
m_size = MaxListStars;
347
StarBrowser::setPosition(const UniversalCoord& ucPos)
350
m_pos = m_ucPos.toLy().cast<float>();
354
StarBrowser::populate(std::vector<StarBrowserRecord>& records) const
356
StarFilter filter(m_filter, m_universe->getSolarSystemCatalog());
357
if (m_spectralTypeFilter)
358
filter.setSpectralTypeFilter(m_spectralTypeFilter);
359
const auto stardb = m_universe->getStarCatalog();
360
if (stardb == nullptr)
363
switch (m_comparison)
365
case Comparison::Nearest:
366
populateRecords(records, DistanceComparison(m_jd, m_pos, m_ucPos), filter, m_size, *stardb);
368
case Comparison::ApparentMagnitude:
369
populateRecords(records, AppMagComparison(m_jd, m_pos, m_ucPos), filter, m_size, *stardb);
371
case Comparison::AbsoluteMagnitude:
372
populateRecords(records, AbsMagComparison(m_jd, m_pos, m_ucPos), filter, m_size, *stardb);