Implemented basic star browser for experimental Qt4 front end.

ver1_5_1
Chris Laurel 2008-01-09 01:30:10 +00:00
parent 6934977bb4
commit 115110a45f
3 changed files with 369 additions and 4 deletions

View File

@ -69,7 +69,7 @@ CelestiaAppWindow::CelestiaAppWindow() :
createMenus();
celestialBrowser = new CelestialBrowser(NULL);
celestialBrowser = new CelestialBrowser(appCore, NULL);
celestialBrowser->setObjectName("celestia-browser");
toolsDock = new QDockWidget(tr("Celestial Browser"), this);

View File

@ -11,14 +11,361 @@
// of the License, or (at your option) any later version.
#include "qtcelestialbrowser.h"
#include <QAbstractItemModel>
#include <QStandardItemModel>
#include <QTreeView>
#include <QPushButton>
#include <QRadioButton>
#include <QVBoxLayout>
#include <vector>
#include <set>
#include <celestia/celestiacore.h>
using namespace std;
CelestialBrowser::CelestialBrowser(QWidget* parent) :
QWidget(parent)
class StarPredicate
{
public:
enum Criterion
{
Distance,
Brightness,
Planets
};
StarPredicate(Criterion _criterion, const UniversalCoord& _observerPos);
bool operator()(const Star* star0, const Star* star1) const;
private:
Criterion criterion;
Point3f pos;
UniversalCoord ucPos;
public:
SolarSystemCatalog* solarSystems;
};
class StarTableModel : public QAbstractTableModel
{
public:
StarTableModel(const Universe* _universe);
virtual ~StarTableModel();
// Methods from QAbstractTableModel
Qt::ItemFlags flags(const QModelIndex& index) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex& index) const;
int columnCount(const QModelIndex& index) const;
enum Predicate
{
DistancePredicate,
BrightnessPredicate,
HasPlanetsPredicate
};
void populate(const UniversalCoord& _observerPos,
StarPredicate::Criterion criterion,
unsigned int nStars);
private:
const Universe* universe;
UniversalCoord observerPos;
vector<const Star*> stars;
};
StarTableModel::StarTableModel(const Universe* _universe) :
universe(_universe),
observerPos(0.0, 0.0, 0.0)
{
}
StarTableModel::~StarTableModel()
{
}
Qt::ItemFlags StarTableModel::flags(const QModelIndex&) const
{
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
QVariant StarTableModel::data(const QModelIndex& index, int role) const
{
int row = index.row();
if (row < 0 || row >= (int) stars.size())
{
// Out of range
return QVariant();
}
const Star* star = stars[row];
if (role != Qt::DisplayRole)
return QVariant();
switch (index.column())
{
case 0:
{
string starNameString = universe->getStarCatalog()->getStarName(*star);
return QVariant(QString(starNameString.c_str()));
}
case 1:
{
UniversalCoord pos = star->getPosition(astro::J2000);
Vec3d v = pos - observerPos;
return QVariant(v.length() * 1.0e-6);
}
case 2:
{
UniversalCoord pos = star->getPosition(astro::J2000);
Vec3d v = pos - observerPos;
double distance = v.length() * 1.0e-6;
return QVariant(star->getApparentMagnitude((float) distance));
}
case 3:
return QVariant(star->getAbsoluteMagnitude());
case 4:
return QString(star->getSpectralType());
default:
return QVariant();
}
}
QVariant StarTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
switch (section)
{
case 0:
return tr("Name");
case 1:
return tr("Distance (ly)");
case 2:
return tr("App. mag");
case 3:
return tr("Abs. mag");
case 4:
return tr("Type");
default:
return QVariant();
}
}
int StarTableModel::rowCount(const QModelIndex&) const
{
return (int) stars.size();
}
int StarTableModel::columnCount(const QModelIndex&) const
{
return 5;
}
static Point3f toMicroLY(const Point3f& p)
{
return Point3f(p.x * 1e6f, p.y * 1e6f, p.z * 1e6f);
}
static Point3f fromMicroLY(const Point3f& p)
{
return Point3f(p.x * 1e-6f, p.y * 1e-6f, p.z * 1e-6f);
}
StarPredicate::StarPredicate(Criterion _criterion,
const UniversalCoord& _observerPos) :
criterion(_criterion),
ucPos(_observerPos),
solarSystems(NULL)
{
pos = fromMicroLY((Point3f) ucPos);
}
bool StarPredicate::operator()(const Star* star0, const Star* star1) const
{
switch (criterion)
{
case Distance:
return ((pos - star0->getPosition()).lengthSquared() <
(pos - star1->getPosition()).lengthSquared());
case Brightness:
{
float d0 = pos.distanceTo(star0->getPosition());
float d1 = pos.distanceTo(star1->getPosition());
// If the stars are closer than one light year, use
// a more precise distance estimate.
if (d0 < 1.0f)
d0 = (toMicroLY(star0->getPosition()) - ucPos).length() * 1e-6f;
if (d1 < 1.0f)
d1 = (toMicroLY(star1->getPosition()) - ucPos).length() * 1e-6f;
return (star0->getApparentMagnitude(d0) <
star1->getApparentMagnitude(d1));
}
case Planets:
if (solarSystems != NULL)
{
SolarSystemCatalog::iterator iter;
iter = solarSystems->find(star0->getCatalogNumber());
bool hasPlanets0 = (iter != solarSystems->end());
iter = solarSystems->find(star1->getCatalogNumber());
bool hasPlanets1 = (iter != solarSystems->end());
if (hasPlanets1 == hasPlanets0)
{
return ((pos - star0->getPosition()).lengthSquared() <
(pos - star1->getPosition()).lengthSquared());
}
else
{
return hasPlanets0;
}
}
else
{
return false;
}
default:
return false;
}
}
void StarTableModel::populate(const UniversalCoord& _observerPos,
StarPredicate::Criterion criterion,
unsigned int nStars)
{
const StarDatabase& stardb = *universe->getStarCatalog();
observerPos = _observerPos;
stars.clear();
typedef multiset<const Star*, StarPredicate> StarSet;
StarPredicate pred(criterion, observerPos);
pred.solarSystems = universe->getSolarSystemCatalog();
StarSet firstStars(pred);
unsigned 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.
unsigned int i = 0;
for (i = 0; i < nStars; i++)
{
Star* star = stardb.getStar(i);
if (star->getVisibility())
firstStars.insert(star);
}
// 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 (star->getVisibility() && pred(star, lastStar))
{
firstStars.insert(star);
firstStars.erase(--firstStars.end());
lastStar = *--firstStars.end();
}
}
// Move the best matching stars into the vector
stars.reserve(nStars);
for (StarSet::const_iterator iter = firstStars.begin();
iter != firstStars.end(); iter++)
{
stars.push_back(*iter);
}
dataChanged(index(0, 0), index(stars.size() - 1, 4));
}
CelestialBrowser::CelestialBrowser(CelestiaCore* _appCore, QWidget* parent) :
QWidget(parent),
appCore(_appCore),
starModel(NULL),
treeView(NULL),
closestButton(NULL),
brightestButton(NULL),
withPlanetsButton(NULL)
{
treeView = new QTreeView();
treeView->setRootIsDecorated(false);
treeView->setAlternatingRowColors(true);
treeView->setItemsExpandable(false);
treeView->setUniformRowHeights(true);
starModel = new StarTableModel(appCore->getSimulation()->getUniverse());
treeView->setModel(starModel);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(treeView);
// Buttons to select filtering method for stars
closestButton = new QRadioButton(tr("Closest Stars"));
connect(closestButton, SIGNAL(clicked()), this, SLOT(slotRefreshTable()));
layout->addWidget(closestButton);
brightestButton = new QRadioButton(tr("Brightest Stars"));
connect(brightestButton, SIGNAL(clicked()), this, SLOT(slotRefreshTable()));
layout->addWidget(brightestButton);
withPlanetsButton = new QRadioButton(tr("Stars With Planets"));
connect(withPlanetsButton, SIGNAL(clicked()), this, SLOT(slotRefreshTable()));
layout->addWidget(withPlanetsButton);
closestButton->setChecked(true);
QPushButton* refreshButton = new QPushButton(tr("Refresh"));
connect(refreshButton, SIGNAL(clicked()), this, SLOT(slotRefreshTable()));
layout->addWidget(refreshButton);
slotRefreshTable();
setLayout(layout);
}
CelestialBrowser::~CelestialBrowser()
{
}
void CelestialBrowser::slotRefreshTable()
{
UniversalCoord observerPos = appCore->getSimulation()->getActiveObserver()->getPosition();
StarPredicate::Criterion criterion = StarPredicate::Distance;
if (brightestButton->isChecked())
criterion = StarPredicate::Brightness;
else if (withPlanetsButton->isChecked())
criterion = StarPredicate::Planets;
((StarTableModel*) starModel)->populate(observerPos, criterion, 1000);
}

View File

@ -15,13 +15,31 @@
#include <QWidget>
class QAbstractItemModel;
class QTreeView;
class CelestiaCore;
class QRadioButton;
class CelestialBrowser : public QWidget
{
Q_OBJECT
public:
CelestialBrowser(QWidget* parent);
CelestialBrowser(CelestiaCore* _appCore, QWidget* parent);
~CelestialBrowser();
public slots:
void slotRefreshTable();
private:
CelestiaCore* appCore;
QAbstractItemModel* starModel;
QTreeView* treeView;
QRadioButton* closestButton;
QRadioButton* brightestButton;
QRadioButton* withPlanetsButton;
};
#endif // _QTCELESTIALBROWSER_H_