Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f016500f12 | |||
| 6069ebbbac |
+55
-2
@@ -16,10 +16,29 @@ bool Database::init(const QLatin1String &connectionName)
|
|||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
|
|
||||||
database = QSqlDatabase::addDatabase("QSQLITE", connectionName);
|
database = QSqlDatabase::addDatabase("QSQLITE", connectionName);
|
||||||
|
ngc = QSqlDatabase::addDatabase("QSQLITE", connectionName + "ngc");
|
||||||
|
|
||||||
if(!dir.mkpath("."))
|
if(!dir.mkpath("."))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if(ngc.isValid())
|
||||||
|
{
|
||||||
|
QString ngcDb = dir.absoluteFilePath("ngc.db");
|
||||||
|
if(!QFile::exists(ngcDb))
|
||||||
|
QFile::copy(":/ngc.db", ngcDb);
|
||||||
|
|
||||||
|
ngc.setDatabaseName(ngcDb);
|
||||||
|
if(ngc.open())
|
||||||
|
{
|
||||||
|
m_getNgc = QSqlQuery(ngc);
|
||||||
|
m_getNgc.prepare("SELECT *,IIF(V_Mag IS NULL, B_Mag, V_Mag) AS mag FROM ngc WHERE RA_deg BETWEEN ? AND ? AND DEC_deg BETWEEN ? AND ?");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "Could not open NGC database";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(database.isValid())
|
if(database.isValid())
|
||||||
{
|
{
|
||||||
database.setDatabaseName(dir.absoluteFilePath("database2.db"));
|
database.setDatabaseName(dir.absoluteFilePath("database2.db"));
|
||||||
@@ -182,7 +201,6 @@ void Database::indexDir(const QDir &dir, QProgressDialog *progress)
|
|||||||
QStringList scannedDirs;
|
QStringList scannedDirs;
|
||||||
int count = countFiles(dir, scannedDirs);
|
int count = countFiles(dir, scannedDirs);
|
||||||
progress->setMaximum(count);
|
progress->setMaximum(count);
|
||||||
QSqlDatabase database = QSqlDatabase::database();
|
|
||||||
database.transaction();
|
database.transaction();
|
||||||
|
|
||||||
scannedDirs.clear();
|
scannedDirs.clear();
|
||||||
@@ -200,7 +218,6 @@ void Database::indexDir(const QDir &dir, QProgressDialog *progress)
|
|||||||
void Database::reindex(QProgressDialog *progress)
|
void Database::reindex(QProgressDialog *progress)
|
||||||
{
|
{
|
||||||
QVariantList deleteids;
|
QVariantList deleteids;
|
||||||
QSqlDatabase database = QSqlDatabase::database();
|
|
||||||
database.transaction();
|
database.transaction();
|
||||||
QSqlQuery size("SELECT COUNT(*) FROM fits_files", database);
|
QSqlQuery size("SELECT COUNT(*) FROM fits_files", database);
|
||||||
size.next();
|
size.next();
|
||||||
@@ -239,6 +256,42 @@ QStringList Database::getFitsKeywords()
|
|||||||
return keywords;
|
return keywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<SkyObject> Database::getObjects(double minRa, double maxRa, double minDec, double maxDec)
|
||||||
|
{
|
||||||
|
QVector<SkyObject> objects;
|
||||||
|
if(!ngc.isOpen())return objects;
|
||||||
|
|
||||||
|
m_getNgc.bindValue(0, minRa);
|
||||||
|
m_getNgc.bindValue(1, maxRa);
|
||||||
|
m_getNgc.bindValue(2, minDec);
|
||||||
|
m_getNgc.bindValue(3, maxDec);
|
||||||
|
|
||||||
|
if(m_getNgc.exec())
|
||||||
|
{
|
||||||
|
while(m_getNgc.next())
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QString m = m_getNgc.value("M").toString();
|
||||||
|
QString ic = m_getNgc.value("IC").toString();
|
||||||
|
if(!m.isEmpty())name = "M" + m + " ";
|
||||||
|
if(!ic.isEmpty())name += "IC" + ic + " ";
|
||||||
|
name += m_getNgc.value("Name").toString();
|
||||||
|
|
||||||
|
objects.append({
|
||||||
|
name,
|
||||||
|
m_getNgc.value("Common names").toString(),
|
||||||
|
{m_getNgc.value("RA_deg").toDouble(), m_getNgc.value("DEC_deg").toDouble()},
|
||||||
|
m_getNgc.value("MajAx").toDouble(),
|
||||||
|
m_getNgc.value("MinAx").toDouble(),
|
||||||
|
m_getNgc.value("PosAng").toDouble(),
|
||||||
|
m_getNgc.value("mag").toDouble(),
|
||||||
|
{0, 0},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
bool Database::indexDir2(const QDir &dir, QProgressDialog *progress, QStringList &scannedDirs)
|
bool Database::indexDir2(const QDir &dir, QProgressDialog *progress, QStringList &scannedDirs)
|
||||||
{
|
{
|
||||||
if(scannedDirs.contains(dir.canonicalPath()))return true;
|
if(scannedDirs.contains(dir.canonicalPath()))return true;
|
||||||
|
|||||||
@@ -6,11 +6,13 @@
|
|||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
|
#include "imageinfodata.h"
|
||||||
|
|
||||||
class Database : public QObject
|
class Database : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QSqlDatabase database;
|
QSqlDatabase database;
|
||||||
|
QSqlDatabase ngc;
|
||||||
QSqlQuery m_markQuery;
|
QSqlQuery m_markQuery;
|
||||||
QSqlQuery m_unmarkQuery;
|
QSqlQuery m_unmarkQuery;
|
||||||
QSqlQuery m_isMarkedQuery;
|
QSqlQuery m_isMarkedQuery;
|
||||||
@@ -22,6 +24,8 @@ class Database : public QObject
|
|||||||
QSqlQuery m_headerKeywords;
|
QSqlQuery m_headerKeywords;
|
||||||
QSqlQuery m_deleteFile;
|
QSqlQuery m_deleteFile;
|
||||||
|
|
||||||
|
QSqlQuery m_getNgc;
|
||||||
|
|
||||||
int m_progress;
|
int m_progress;
|
||||||
public:
|
public:
|
||||||
explicit Database(QObject *parent = 0);
|
explicit Database(QObject *parent = 0);
|
||||||
@@ -37,6 +41,7 @@ public:
|
|||||||
void indexDir(const QDir &dir, QProgressDialog *progress);
|
void indexDir(const QDir &dir, QProgressDialog *progress);
|
||||||
void reindex(QProgressDialog *progress);
|
void reindex(QProgressDialog *progress);
|
||||||
QStringList getFitsKeywords();
|
QStringList getFitsKeywords();
|
||||||
|
QVector<SkyObject> getObjects(double minRa, double maxRa, double minDec, double maxDec);
|
||||||
protected:
|
protected:
|
||||||
bool indexDir2(const QDir &dir, QProgressDialog *progress, QStringList &scannedDirs);
|
bool indexDir2(const QDir &dir, QProgressDialog *progress, QStringList &scannedDirs);
|
||||||
bool indexFile(const QFileInfo &file);
|
bool indexFile(const QFileInfo &file);
|
||||||
|
|||||||
+157
-2
@@ -4,6 +4,7 @@
|
|||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <wcslib/wcshdr.h>
|
#include <wcslib/wcshdr.h>
|
||||||
#include <wcslib/wcsfix.h>
|
#include <wcslib/wcsfix.h>
|
||||||
|
#include "database.h"
|
||||||
#include "libxisf.h"
|
#include "libxisf.h"
|
||||||
|
|
||||||
static const QVector<QByteArray> noEditableKey = {"SIMPLE", "BITPIX", "NAXIS", "NAXIS1", "NAXIS2", "NAXIS3", "EXTEND", "BZERO", "BSCALE"};
|
static const QVector<QByteArray> noEditableKey = {"SIMPLE", "BITPIX", "NAXIS", "NAXIS1", "NAXIS2", "NAXIS3", "EXTEND", "BZERO", "BSCALE"};
|
||||||
@@ -153,9 +154,9 @@ bool WCSDataT::worldToPixel(const SkyPoint &point, QPointF &pixel) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCSDataT::calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec, double &crVal1, double &crVal2) const
|
bool WCSDataT::calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec, double &crVal1, double &crVal2) const
|
||||||
{
|
{
|
||||||
if(wcs == nullptr)return;
|
if(wcs == nullptr)return false;
|
||||||
|
|
||||||
minRa = 1000;
|
minRa = 1000;
|
||||||
maxRa = -1000;
|
maxRa = -1000;
|
||||||
@@ -208,6 +209,7 @@ void WCSDataT::calculateBounds(double &minRa, double &maxRa, double &minDec, dou
|
|||||||
if(s.contains(scp))
|
if(s.contains(scp))
|
||||||
minDec = -90;
|
minDec = -90;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double hav(double x)
|
double hav(double x)
|
||||||
@@ -327,6 +329,14 @@ QString SkyPoint::toDMS(double deg)
|
|||||||
return QString("%1˚ %2' %3\"").arg((int)d * sign, 2, 10, QChar('0')).arg((int)m, 2, 10, QChar('0')).arg((int)s, 2, 10, QChar('0'));
|
return QString("%1˚ %2' %3\"").arg((int)d * sign, 2, 10, QChar('0')).arg((int)m, 2, 10, QChar('0')).arg((int)s, 2, 10, QChar('0'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkyPoint SkyPoint::operator+(const SkyPoint &p)
|
||||||
|
{
|
||||||
|
SkyPoint ret;
|
||||||
|
ret.ra = ra + p.ra;
|
||||||
|
ret.dec = dec + p.dec;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
SkyPointScale ImageInfoData::getCenterRaDec() const
|
SkyPointScale ImageInfoData::getCenterRaDec() const
|
||||||
{
|
{
|
||||||
SkyPointScale ret;
|
SkyPointScale ret;
|
||||||
@@ -415,3 +425,148 @@ SkyPointScale ImageInfoData::getCenterRaDec() const
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkyPoint greatCircle(SkyPoint &p, double dist, double azm)
|
||||||
|
{
|
||||||
|
dist = dist * M_PI / 180;
|
||||||
|
azm = azm * M_PI / 180;
|
||||||
|
double dec0 = p.DEC() * M_PI / 180;
|
||||||
|
double ra0 = p.RA() * M_PI / 180;
|
||||||
|
double dec1 = std::asin(std::sin(dec0) * std::cos(dist) + std::cos(dec0) * std::sin(dist) * std::cos(azm));
|
||||||
|
double ra1 = ra0 + std::atan2(std::sin(azm) * std::sin(dist) * std::cos(dec0), std::cos(dist) - std::sin(dec0) * std::sin(dec1));
|
||||||
|
return SkyPoint(ra1 * 180 / M_PI, dec1 * 180 / M_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkyGrid WCSDataT::prepareGrid(uint32_t w, uint32_t h, Database *database)
|
||||||
|
{
|
||||||
|
SkyGrid skyGrid;
|
||||||
|
if(!wcs)return skyGrid;
|
||||||
|
|
||||||
|
double minRa, maxRa, minDec, maxDec, crVal1, crVal2;
|
||||||
|
calculateBounds(minRa, maxRa, minDec, maxDec, crVal1, crVal2);
|
||||||
|
|
||||||
|
QPointF a,b;
|
||||||
|
worldToPixel(SkyPoint(crVal1, crVal2), a);
|
||||||
|
worldToPixel(SkyPoint(crVal1 + 0.01, crVal2), b);
|
||||||
|
skyGrid.rot_ang = std::atan2(b.y() - a.y(), b.x() - a.x()) / M_PI * -180.0;
|
||||||
|
|
||||||
|
if(database)
|
||||||
|
{
|
||||||
|
skyGrid.objects = database->getObjects(minRa, maxRa, minDec, maxDec);
|
||||||
|
for(auto &object : skyGrid.objects)
|
||||||
|
{
|
||||||
|
QPointF p;
|
||||||
|
if(worldToPixel(object.skyPoint, p))
|
||||||
|
object.pixel = p;
|
||||||
|
|
||||||
|
QPointF majax;
|
||||||
|
worldToPixel(greatCircle(object.skyPoint, (object.min_ax + object.maj_ax) / 120.0, object.pos_ang), majax);
|
||||||
|
majax -= p;
|
||||||
|
object.maj_ax = std::sqrt(QPointF::dotProduct(majax, majax));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double raStep = 15;
|
||||||
|
double decStep = 15;
|
||||||
|
double raRange = maxRa - minRa;
|
||||||
|
double decRange = maxDec - minDec;
|
||||||
|
const QVector<double> raSteps = {15, 5, 2.5, 1.25, 0.25, 20/240.0, 10/240.0, 5/240.0, 1/240.0};
|
||||||
|
const QVector<double> decSteps = {20, 10, 5, 2, 1, 20/60.0, 10/60.0, 5/60.0, 2/60.0, 1/60.0, 20/3600.0, 10/3600.0, 5/3600.0, 2/3600.0, 1/3600.0};
|
||||||
|
|
||||||
|
for(double ra : raSteps)
|
||||||
|
{
|
||||||
|
if(ra * 5 <= raRange)
|
||||||
|
{
|
||||||
|
raStep = ra;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(double dec : decSteps)
|
||||||
|
{
|
||||||
|
if(dec * 5 <= decRange)
|
||||||
|
{
|
||||||
|
decStep = dec;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minRa -= std::fmod(minRa, raStep);
|
||||||
|
minDec -= std::fmod(minDec, decStep);
|
||||||
|
if(minRa < 0)minRa -= raStep;
|
||||||
|
if(minDec < 0)minDec -= decStep;
|
||||||
|
|
||||||
|
QRectF clip(0, 0, w, h);
|
||||||
|
const double step = 0.2;
|
||||||
|
|
||||||
|
maxRa += raStep;
|
||||||
|
maxDec += decStep;
|
||||||
|
for(double ra = minRa; ra <= maxRa; ra += raStep)
|
||||||
|
{
|
||||||
|
QPointF p;
|
||||||
|
worldToPixel(SkyPoint(ra, minDec), p);
|
||||||
|
skyGrid.grid.moveTo(p);
|
||||||
|
for(double dec = minDec + decStep * step; dec <= maxDec; dec += decStep * step)
|
||||||
|
{
|
||||||
|
worldToPixel(SkyPoint(ra, dec), p);
|
||||||
|
skyGrid.grid.lineTo(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(double dec = minDec; dec <= maxDec; dec += decStep)
|
||||||
|
{
|
||||||
|
QPointF p;
|
||||||
|
worldToPixel(SkyPoint(minRa, dec), p);
|
||||||
|
skyGrid.grid.moveTo(p);
|
||||||
|
for(double ra = minRa + raStep * step; ra <= maxRa; ra += raStep * step)
|
||||||
|
{
|
||||||
|
worldToPixel(SkyPoint(ra, dec), p);
|
||||||
|
skyGrid.grid.lineTo(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkyPoint sp1, sp2,orig;
|
||||||
|
pixelToWorld(QPointF(-1, -1), orig);
|
||||||
|
sp1 = orig;
|
||||||
|
for(uint32_t x = 0; x < w; x++)
|
||||||
|
{
|
||||||
|
QPointF p(x, 0);
|
||||||
|
if(!pixelToWorld(p, sp2))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(static_cast<int>(sp1.RA() / raStep) != static_cast<int>(sp2.RA() / raStep))
|
||||||
|
skyGrid.text.append({p, std::abs(sp1.RA()) > std::abs(sp2.RA()) ? sp1.RAString() : sp2.RAString()});
|
||||||
|
|
||||||
|
if(static_cast<int>(sp1.DEC() / decStep) != static_cast<int>(sp2.DEC() / decStep))
|
||||||
|
skyGrid.text.append({p, std::abs(sp1.DEC()) > std::abs(sp2.DEC()) ? sp1.DECString() : sp2.DECString()});
|
||||||
|
|
||||||
|
sp1 = sp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp1 = orig;
|
||||||
|
for(uint32_t y = 0; y < h; y++)
|
||||||
|
{
|
||||||
|
QPointF p(0, y);
|
||||||
|
if(!pixelToWorld(p, sp2))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(static_cast<int>(sp1.RA() / raStep) != static_cast<int>(sp2.RA() / raStep))
|
||||||
|
skyGrid.text.append({p, std::abs(sp1.RA()) > std::abs(sp2.RA()) ? sp1.RAString() : sp2.RAString()});
|
||||||
|
|
||||||
|
if(static_cast<int>(sp1.DEC() / decStep) != static_cast<int>(sp2.DEC() / decStep))
|
||||||
|
skyGrid.text.append({p, std::abs(sp1.DEC()) > std::abs(sp2.DEC()) ? sp1.DECString() : sp2.DECString()});
|
||||||
|
|
||||||
|
sp1 = sp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
skyGrid.empty = false;
|
||||||
|
return skyGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyGrid::clear()
|
||||||
|
{
|
||||||
|
empty = true;
|
||||||
|
grid.clear();
|
||||||
|
text.clear();
|
||||||
|
objects.clear();
|
||||||
|
}
|
||||||
|
|||||||
+28
-1
@@ -5,12 +5,15 @@
|
|||||||
#include <QPointF>
|
#include <QPointF>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QPainterPath>
|
||||||
#include <wcslib/wcs.h>
|
#include <wcslib/wcs.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace LibXISF { struct FITSKeyword; struct Property; }
|
namespace LibXISF { struct FITSKeyword; struct Property; }
|
||||||
|
|
||||||
|
class Database;
|
||||||
|
|
||||||
struct FITSRecord
|
struct FITSRecord
|
||||||
{
|
{
|
||||||
QByteArray key;
|
QByteArray key;
|
||||||
@@ -42,6 +45,7 @@ public:
|
|||||||
static double fromDMS(const QString &dms);
|
static double fromDMS(const QString &dms);
|
||||||
static QString toHMS(double decHour);
|
static QString toHMS(double decHour);
|
||||||
static QString toDMS(double deg);
|
static QString toDMS(double deg);
|
||||||
|
SkyPoint operator+(const SkyPoint &p);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SkyPointScale
|
struct SkyPointScale
|
||||||
@@ -53,6 +57,28 @@ struct SkyPointScale
|
|||||||
double scaleHigh = 10000.0;
|
double scaleHigh = 10000.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SkyObject
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QString name2;
|
||||||
|
SkyPoint skyPoint;
|
||||||
|
double maj_ax;
|
||||||
|
double min_ax;
|
||||||
|
double pos_ang;
|
||||||
|
double vmag;
|
||||||
|
QPointF pixel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SkyGrid
|
||||||
|
{
|
||||||
|
bool empty = true;
|
||||||
|
QPainterPath grid;
|
||||||
|
QVector<QPair<QPointF, QString>> text;
|
||||||
|
QVector<SkyObject> objects;
|
||||||
|
double rot_ang = 0;
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
class WCSDataT
|
class WCSDataT
|
||||||
{
|
{
|
||||||
int nwcs = 0;
|
int nwcs = 0;
|
||||||
@@ -67,9 +93,10 @@ public:
|
|||||||
~WCSDataT();
|
~WCSDataT();
|
||||||
bool pixelToWorld(const QPointF &pixel, SkyPoint &point) const;
|
bool pixelToWorld(const QPointF &pixel, SkyPoint &point) const;
|
||||||
bool worldToPixel(const SkyPoint &point, QPointF &pixel) const;
|
bool worldToPixel(const SkyPoint &point, QPointF &pixel) const;
|
||||||
void calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec, double &crVal1, double &crVal2) const;
|
bool calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec, double &crVal1, double &crVal2) const;
|
||||||
bool valid() const { return wcs; };
|
bool valid() const { return wcs; };
|
||||||
SkyPointScale getRaDecScale() const;
|
SkyPointScale getRaDecScale() const;
|
||||||
|
SkyGrid prepareGrid(uint32_t w, uint32_t h, Database *database);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImageInfoData
|
struct ImageInfoData
|
||||||
|
|||||||
+27
-115
@@ -26,8 +26,6 @@ struct RawImageType
|
|||||||
QOpenGLTexture::PixelType dataType;
|
QOpenGLTexture::PixelType dataType;
|
||||||
};
|
};
|
||||||
|
|
||||||
void prepareGrid(WCSDataT *wcs, uint32_t w, uint32_t h, QPainterPath &grid, QPainterPath &text);
|
|
||||||
|
|
||||||
RawImageType getRawImageType(const RawImage *img)
|
RawImageType getRawImageType(const RawImage *img)
|
||||||
{
|
{
|
||||||
RawImageType type;
|
RawImageType type;
|
||||||
@@ -183,9 +181,9 @@ void ImageWidgetGL::setWCS(std::shared_ptr<WCSDataT> wcs)
|
|||||||
{
|
{
|
||||||
m_wcs = wcs;
|
m_wcs = wcs;
|
||||||
m_grid.clear();
|
m_grid.clear();
|
||||||
m_text.clear();
|
|
||||||
if(m_drawGrid)
|
if(m_drawGrid && m_wcs)
|
||||||
prepareGrid(m_wcs.get(), m_imgWidth, m_imgHeight, m_grid, m_text);
|
m_grid = m_wcs->prepareGrid(m_imgWidth, m_imgHeight, m_database);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageWidgetGL::zoom(int zoom, const QPointF &mousePos)
|
void ImageWidgetGL::zoom(int zoom, const QPointF &mousePos)
|
||||||
@@ -502,111 +500,10 @@ void swPaint(std::shared_ptr<RawImage> &rawImage, float dx, float dy, float scal
|
|||||||
painter.drawImage(0, 0, img);
|
painter.drawImage(0, 0, img);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareGrid(WCSDataT *wcs, uint32_t w, uint32_t h, QPainterPath &grid, QPainterPath &text)
|
|
||||||
{
|
|
||||||
if(!wcs)return;
|
|
||||||
|
|
||||||
double minRa, maxRa, minDec, maxDec, crVal1, crVal2;
|
|
||||||
wcs->calculateBounds(minRa, maxRa, minDec, maxDec, crVal1, crVal2);
|
|
||||||
|
|
||||||
double raStep = 15;
|
|
||||||
double decStep = 15;
|
|
||||||
double raRange = maxRa - minRa;
|
|
||||||
double decRange = maxDec - minDec;
|
|
||||||
const QVector<double> raSteps = {15, 5, 2.5, 1.25, 0.25, 20/240.0, 10/240.0, 5/240.0, 1/240.0};
|
|
||||||
const QVector<double> decSteps = {20, 10, 5, 2, 1, 20/60.0, 10/60.0, 5/60.0, 2/60.0, 1/60.0, 20/3600.0, 10/3600.0, 5/3600.0, 2/3600.0, 1/3600.0};
|
|
||||||
|
|
||||||
for(double ra : raSteps)
|
|
||||||
{
|
|
||||||
if(ra * 5 <= raRange)
|
|
||||||
{
|
|
||||||
raStep = ra;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(double dec : decSteps)
|
|
||||||
{
|
|
||||||
if(dec * 5 <= decRange)
|
|
||||||
{
|
|
||||||
decStep = dec;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
minRa -= std::fmod(minRa, raStep);
|
|
||||||
minDec -= std::fmod(minDec, decStep);
|
|
||||||
if(minRa < 0)minRa -= raStep;
|
|
||||||
if(minDec < 0)minDec -= decStep;
|
|
||||||
|
|
||||||
QRectF clip(0, 0, w, h);
|
|
||||||
|
|
||||||
maxRa += raStep;
|
|
||||||
maxDec += decStep;
|
|
||||||
for(double ra = minRa; ra <= maxRa; ra += raStep)
|
|
||||||
{
|
|
||||||
QPointF p;
|
|
||||||
wcs->worldToPixel(SkyPoint(ra, minDec), p);
|
|
||||||
grid.moveTo(p);
|
|
||||||
for(double dec = minDec + decStep * 0.02; dec <= maxDec; dec += decStep * 0.02)
|
|
||||||
{
|
|
||||||
wcs->worldToPixel(SkyPoint(ra, dec), p);
|
|
||||||
grid.lineTo(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(double dec = minDec; dec <= maxDec; dec += decStep)
|
|
||||||
{
|
|
||||||
QPointF p;
|
|
||||||
wcs->worldToPixel(SkyPoint(minRa, dec), p);
|
|
||||||
grid.moveTo(p);
|
|
||||||
for(double ra = minRa + raStep * 0.02; ra <= maxRa; ra += raStep * 0.02)
|
|
||||||
{
|
|
||||||
wcs->worldToPixel(SkyPoint(ra, dec), p);
|
|
||||||
grid.lineTo(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SkyPoint sp1, sp2,orig;
|
|
||||||
wcs->pixelToWorld(QPointF(-1, -1), orig);
|
|
||||||
sp1 = orig;
|
|
||||||
QFont font("Sans", 12);
|
|
||||||
for(uint32_t x = 0; x < w; x++)
|
|
||||||
{
|
|
||||||
QPointF p(x, 0);
|
|
||||||
if(!wcs->pixelToWorld(p, sp2))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(static_cast<int>(sp1.RA() / raStep) != static_cast<int>(sp2.RA() / raStep))
|
|
||||||
text.addText(p + QPointF(0, 14), font, std::abs(sp1.RA()) > std::abs(sp2.RA()) ? sp1.RAString() : sp2.RAString());
|
|
||||||
|
|
||||||
if(static_cast<int>(sp1.DEC() / decStep) != static_cast<int>(sp2.DEC() / decStep))
|
|
||||||
text.addText(p + QPointF(0, 14), font, std::abs(sp1.DEC()) > std::abs(sp2.DEC()) ? sp1.DECString() : sp2.DECString());
|
|
||||||
|
|
||||||
sp1 = sp2;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp1 = orig;
|
|
||||||
for(uint32_t y = 0; y < h; y++)
|
|
||||||
{
|
|
||||||
QPointF p(0, y);
|
|
||||||
if(!wcs->pixelToWorld(p, sp2))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(static_cast<int>(sp1.RA() / raStep) != static_cast<int>(sp2.RA() / raStep))
|
|
||||||
text.addText(p + QPointF(2, 0), font, std::abs(sp1.RA()) > std::abs(sp2.RA()) ? sp1.RAString() : sp2.RAString());
|
|
||||||
|
|
||||||
if(static_cast<int>(sp1.DEC() / decStep) != static_cast<int>(sp2.DEC() / decStep))
|
|
||||||
text.addText(p + QPointF(2, 0), font, std::abs(sp1.DEC()) > std::abs(sp2.DEC()) ? sp1.DECString() : sp2.DECString());
|
|
||||||
|
|
||||||
sp1 = sp2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageWidgetGL::drawGrid(bool enable)
|
void ImageWidgetGL::drawGrid(bool enable)
|
||||||
{
|
{
|
||||||
if(m_grid.elementCount() == 0)
|
if(m_grid.empty && m_wcs)
|
||||||
prepareGrid(m_wcs.get(), m_imgWidth, m_imgHeight, m_grid, m_text);
|
m_grid = m_wcs->prepareGrid(m_imgWidth, m_imgHeight, m_database);
|
||||||
|
|
||||||
if(enable != m_drawGrid)
|
if(enable != m_drawGrid)
|
||||||
{
|
{
|
||||||
@@ -733,7 +630,7 @@ void ImageWidgetGL::paintGL()
|
|||||||
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
m_vao->release();
|
m_vao->release();
|
||||||
|
|
||||||
if(m_drawGrid)
|
if(m_drawGrid && !m_grid.empty)
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
@@ -745,15 +642,30 @@ void ImageWidgetGL::paintGL()
|
|||||||
tran.scale(m_scale, m_scale);
|
tran.scale(m_scale, m_scale);
|
||||||
painter.setTransform(tran);
|
painter.setTransform(tran);
|
||||||
painter.setClipRect(0, 0, m_imgWidth, m_imgHeight);
|
painter.setClipRect(0, 0, m_imgWidth, m_imgHeight);
|
||||||
painter.drawPath(m_grid);
|
painter.drawPath(m_grid.grid);
|
||||||
painter.setPen(Qt::NoPen);
|
painter.setPen(Qt::yellow);
|
||||||
painter.setBrush(Qt::yellow);
|
QFont font({"Arial", "serif-sans"});
|
||||||
painter.drawPath(m_text);
|
font.setPointSizeF(12 / m_scale);
|
||||||
}
|
painter.setFont(font);
|
||||||
|
for(auto &text : m_grid.text)
|
||||||
|
painter.drawText(QRectF(text.first, QSizeF(4000, 4000)), text.second);
|
||||||
|
|
||||||
|
painter.setPen(QPen(Qt::green, 1.0 / m_scale));
|
||||||
|
QFontMetricsF fontMetric = QFontMetricsF(font);
|
||||||
|
for(auto &object : m_grid.objects)
|
||||||
|
{
|
||||||
|
QRectF rect = fontMetric.boundingRect(object.name);
|
||||||
|
rect.moveCenter(object.pixel);
|
||||||
|
painter.setTransform(tran);
|
||||||
|
painter.drawText(rect, Qt::TextDontClip, object.name);
|
||||||
|
|
||||||
|
painter.translate(object.pixel);
|
||||||
|
painter.rotate(object.pos_ang);
|
||||||
|
painter.drawEllipse(QPointF(0, 0), object.maj_ax, object.maj_ax);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageWidgetGL::resizeGL(int w, int h)
|
void ImageWidgetGL::resizeGL(int w, int h)
|
||||||
|
|||||||
+1
-2
@@ -72,8 +72,7 @@ class ImageWidgetGL : public QOpenGLWidget, public ImageWidget
|
|||||||
GLuint m_debayerTex = 0;
|
GLuint m_debayerTex = 0;
|
||||||
std::shared_ptr<RawImage> m_rawImage;
|
std::shared_ptr<RawImage> m_rawImage;
|
||||||
std::shared_ptr<WCSDataT> m_wcs;
|
std::shared_ptr<WCSDataT> m_wcs;
|
||||||
QPainterPath m_grid;
|
SkyGrid m_grid;
|
||||||
QPainterPath m_text;
|
|
||||||
int m_width, m_height;
|
int m_width, m_height;
|
||||||
int m_imgWidth = -1, m_imgHeight = -1;
|
int m_imgWidth = -1, m_imgHeight = -1;
|
||||||
int m_currentImg = 0;
|
int m_currentImg = 0;
|
||||||
|
|||||||
Binary file not shown.
@@ -19,6 +19,7 @@
|
|||||||
<file>../translations/tenmon_pt_BR.qm</file>
|
<file>../translations/tenmon_pt_BR.qm</file>
|
||||||
<file alias="help">../about/help_en</file>
|
<file alias="help">../about/help_en</file>
|
||||||
<file>colormap.png</file>
|
<file>colormap.png</file>
|
||||||
|
<file>ngc.db</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/" lang="en">
|
<qresource prefix="/" lang="en">
|
||||||
<file alias="help">../about/help_en</file>
|
<file alias="help">../about/help_en</file>
|
||||||
|
|||||||
@@ -92,6 +92,28 @@ bool ScriptEngine::isMarked(const File *file)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJSValue ScriptEngine::getObjects(double ra, double dec, double distance)
|
||||||
|
{
|
||||||
|
QVector<SkyObject> objects;
|
||||||
|
QMetaObject::invokeMethod(_database, [this, ra, dec, distance](){
|
||||||
|
return _database->getObjects(ra - distance, ra + distance, dec - distance, dec + distance); }, Qt::BlockingQueuedConnection, &objects);
|
||||||
|
|
||||||
|
QJSValue ret = newArray(objects.size());
|
||||||
|
qint32 i = 0;
|
||||||
|
for(auto &object : objects)
|
||||||
|
{
|
||||||
|
QJSValue jsObj = newObject();
|
||||||
|
jsObj.setProperty("name", object.name);
|
||||||
|
jsObj.setProperty("name2", object.name2);
|
||||||
|
jsObj.setProperty("ra", object.skyPoint.RA());
|
||||||
|
jsObj.setProperty("dec", object.skyPoint.DEC());
|
||||||
|
jsObj.setProperty("vmag", object.vmag);
|
||||||
|
ret.setProperty(i++, jsObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptEngine::setMaxThread(int maxthread)
|
void ScriptEngine::setMaxThread(int maxthread)
|
||||||
{
|
{
|
||||||
int newval = std::max(std::min(QThread::idealThreadCount(), maxthread), 1);
|
int newval = std::max(std::min(QThread::idealThreadCount(), maxthread), 1);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
Q_INVOKABLE void mark(File *file);
|
Q_INVOKABLE void mark(File *file);
|
||||||
Q_INVOKABLE void unmark(File *file);
|
Q_INVOKABLE void unmark(File *file);
|
||||||
Q_INVOKABLE bool isMarked(const File *file);
|
Q_INVOKABLE bool isMarked(const File *file);
|
||||||
|
Q_INVOKABLE QJSValue getObjects(double ra, double dec, double distance);
|
||||||
Q_INVOKABLE void setMaxThread(int maxthread);
|
Q_INVOKABLE void setMaxThread(int maxthread);
|
||||||
Q_INVOKABLE void sync();
|
Q_INVOKABLE void sync();
|
||||||
Q_INVOKABLE QJSValue getString(const QString &label = QString(), const QString &text = QString()) const;
|
Q_INVOKABLE QJSValue getString(const QString &label = QString(), const QString &text = QString()) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user