Kstars

fov.cpp
1/*
2 SPDX-FileCopyrightText: 2003 Jason Harris <kstars@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "fov.h"
8
9#include "geolocation.h"
10#include "kspaths.h"
11#ifndef KSTARS_LITE
12#include "kstars.h"
13#endif
14#include "kstarsdata.h"
15#include "Options.h"
16#include "skymap.h"
17#include "projections/projector.h"
18#include "fovadaptor.h"
19
20#include <QPainter>
21#include <QTextStream>
22#include <QFile>
23#include <QDebug>
24#include <QStandardPaths>
25
26#include <algorithm>
27
28QList<FOV *> FOVManager::m_FOVs;
29int FOV::m_ID = 1;
30
31FOVManager::~FOVManager()
32{
33 qDeleteAll(m_FOVs);
34}
35
36QList<FOV *> FOVManager::defaults()
37{
39 fovs << new FOV(i18nc("use field-of-view for binoculars", "7x35 Binoculars"), 558, 558, 0, 0, 0, FOV::CIRCLE,
40 "#AAAAAA")
41 << new FOV(i18nc("use a Telrad field-of-view indicator", "Telrad"), 30, 30, 0, 0, 0, FOV::BULLSEYE, "#AA0000")
42 << new FOV(i18nc("use 1-degree field-of-view indicator", "One Degree"), 60, 60, 0, 0, 0, FOV::CIRCLE,
43 "#AAAAAA")
44 << new FOV(i18nc("use HST field-of-view indicator", "HST WFPC2"), 2.4, 2.4, 0, 0, 0, FOV::SQUARE, "#AAAAAA")
45 << new FOV(i18nc("use Radiotelescope HPBW", "30m at 1.3cm"), 1.79, 1.79, 0, 0, 0, FOV::SQUARE, "#AAAAAA");
46 return fovs;
47}
48
50{
51 QFile f;
52
53 // TODO: Move FOVs to user database instead of file!!
54 f.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("fov.dat"));
55
56 if (!f.open(QIODevice::WriteOnly))
57 {
58 qDebug() << Q_FUNC_INFO << "Could not open fov.dat.";
59 return false;
60 }
61
63 foreach (FOV *fov, m_FOVs)
64 {
65 ostream << fov->name() << ':' << fov->sizeX() << ':' << fov->sizeY() << ':' << fov->offsetX() << ':'
66 << fov->offsetY() << ':' << fov->PA() << ':' << QString::number(fov->shape())
67 << ':' << fov->color()
68 << ':' << (fov->lockCelestialPole() ? 1 : 0)
69 << '\n';
70 }
71 f.close();
72
73 return true;
74}
75
77{
78 qDeleteAll(m_FOVs);
79 m_FOVs.clear();
80
81 QFile f;
82 f.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("fov.dat"));
83
84 if (!f.exists())
85 {
86 m_FOVs = defaults();
87 save();
88 return m_FOVs;
89 }
90
91 if (f.open(QIODevice::ReadOnly))
92 {
94 while (!istream.atEnd())
95 {
96 QStringList fields = istream.readLine().split(':');
97 bool ok;
98 QString name, color;
99 float sizeX, sizeY, xoffset, yoffset, rot;
100 bool lockedCP = false;
101 FOV::Shape shape;
102 if (fields.count() >= 8)
103 {
104 name = fields[0];
105 sizeX = fields[1].toFloat(&ok);
106 if (!ok)
107 {
108 return m_FOVs;
109 }
110 sizeY = fields[2].toFloat(&ok);
111 if (!ok)
112 {
113 return m_FOVs;
114 }
115 xoffset = fields[3].toFloat(&ok);
116 if (!ok)
117 {
118 return m_FOVs;
119 }
120
121 yoffset = fields[4].toFloat(&ok);
122 if (!ok)
123 {
124 return m_FOVs;
125 }
126
127 rot = fields[5].toFloat(&ok);
128 if (!ok)
129 {
130 return m_FOVs;
131 }
132
133 shape = static_cast<FOV::Shape>(fields[6].toInt(&ok));
134 if (!ok)
135 {
136 return m_FOVs;
137 }
138 color = fields[7];
139
140 if (fields.count() == 9)
141 lockedCP = (fields[8].toInt(&ok) == 1);
142 }
143 else
144 {
145 continue;
146 }
147
148 m_FOVs.append(new FOV(name, sizeX, sizeY, xoffset, yoffset, rot, shape, color, lockedCP));
149 }
150 }
151 return m_FOVs;
152}
153
155{
156 qDeleteAll(m_FOVs);
157 m_FOVs.clear();
158}
159
160FOV::FOV(const QString &n, float a, float b, float xoffset, float yoffset, float rot, Shape sh, const QString &col,
161 bool useLockedCP) : QObject()
162{
163 qRegisterMetaType<FOV::Shape>("FOV::Shape");
165
166 new FovAdaptor(this);
167 QDBusConnection::sessionBus().registerObject(QString("/KStars/FOV/%1").arg(getID()), this);
168
169 m_name = n;
170 m_sizeX = a;
171 m_sizeY = (b < 0.0) ? a : b;
172
173 m_offsetX = xoffset;
174 m_offsetY = yoffset;
175 m_PA = rot;
176 m_shape = sh;
177 m_color = col;
178 m_northPA = 0;
179 m_center.setRA(0);
180 m_center.setDec(0);
181 m_imageDisplay = false;
182 m_lockCelestialPole = useLockedCP;
183}
184
186{
187 qRegisterMetaType<FOV::Shape>("FOV::Shape");
189
190 new FovAdaptor(this);
191 QDBusConnection::sessionBus().registerObject(QString("/KStars/FOV/%1").arg(getID()), this);
192
193 m_name = i18n("No FOV");
194 m_color = "#FFFFFF";
195
196 m_sizeX = m_sizeY = 0;
197 m_shape = SQUARE;
198 m_imageDisplay = false;
199 m_lockCelestialPole = false;
200}
201
202FOV::FOV(const FOV &other) : QObject()
203{
204 m_name = other.m_name;
205 m_color = other.m_color;
206 m_sizeX = other.m_sizeX;
207 m_sizeY = other.m_sizeY;
208 m_shape = other.m_shape;
209 m_offsetX = other.m_offsetX;
210 m_offsetY = other.m_offsetY;
211 m_PA = other.m_PA;
212 m_imageDisplay = other.m_imageDisplay;
213 m_lockCelestialPole = other.m_lockCelestialPole;
214}
215
216void FOV::sync(const FOV &other)
217{
218 m_name = other.m_name;
219 m_color = other.m_color;
220 m_sizeX = other.m_sizeX;
221 m_sizeY = other.m_sizeY;
222 m_shape = other.m_shape;
223 m_offsetX = other.m_offsetX;
224 m_offsetY = other.m_offsetY;
225 m_PA = other.m_PA;
226 m_imageDisplay = other.m_imageDisplay;
227 m_lockCelestialPole = other.m_lockCelestialPole;
228}
229
230void FOV::draw(QPainter &p, float zoomFactor)
231{
232 // Do not draw empty FOVs
233 if (m_sizeX == 0 || m_sizeY == 0)
234 return;
235
236 p.setPen(QColor(color()));
238
239 p.setRenderHint(QPainter::Antialiasing, Options::useAntialias());
240
241 float pixelSizeX = sizeX() * zoomFactor / 57.3 / 60.0;
242 float pixelSizeY = sizeY() * zoomFactor / 57.3 / 60.0;
243
244 float offsetXPixelSize = offsetX() * zoomFactor / 57.3 / 60.0;
245 float offsetYPixelSize = offsetY() * zoomFactor / 57.3 / 60.0;
246
247 p.save();
248
249 if (m_center.ra().Degrees() > 0)
250 {
251 m_center.EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
252 QPointF skypoint_center = KStars::Instance()->map()->projector()->toScreen(&m_center);
253 p.translate(skypoint_center.toPoint());
254 }
255 else
256 p.translate(p.viewport().center());
257
259 p.rotate( (m_PA - m_northPA) * -1);
260
261 QPointF center(0, 0);
262
263 switch (shape())
264 {
265 case SQUARE:
266 {
267 QRect targetRect(center.x() - pixelSizeX / 2, center.y() - pixelSizeY / 2, pixelSizeX, pixelSizeY);
268 if (m_imageDisplay)
269 p.drawImage(targetRect, m_image);
270
272 p.drawRect(center.x(), center.y() - (3 * pixelSizeY / 5), pixelSizeX / 40, pixelSizeX / 10);
273 p.drawLine(center.x() - pixelSizeX / 30, center.y() - (3 * pixelSizeY / 5), center.x() + pixelSizeX / 20,
274 center.y() - (3 * pixelSizeY / 5));
275 p.drawLine(center.x() - pixelSizeX / 30, center.y() - (3 * pixelSizeY / 5), center.x() + pixelSizeX / 70,
276 center.y() - (0.7 * pixelSizeY));
277 p.drawLine(center.x() + pixelSizeX / 20, center.y() - (3 * pixelSizeY / 5), center.x() + pixelSizeX / 70,
278 center.y() - (0.7 * pixelSizeY));
279
280 if (name().count() > 0)
281 {
282 int fontSize = pixelSizeX / 15;
283 fontSize *= 14.0 / name().count();
284
285 // Don't let the font size get larger than the vertical space allotted.
286 const int maxYPixelSize = (14.0 / 15.0) * (pixelSizeY / 8);
287 fontSize = std::min(maxYPixelSize, fontSize);
288
289 if (fontSize <= 4)
290 break;
291
292 QFont font = p.font();
293 font.setPixelSize(fontSize);
294 p.setFont(font);
295
296 QRect nameRect(targetRect.topLeft().x(), targetRect.topLeft().y() - (pixelSizeY / 8), targetRect.width() / 2,
297 pixelSizeX / 10);
299
300 // Maybe make the font size smaller for the field-of-view dimensions.
301 QString fovString = QString("%1'x%2'").arg(QString::number(m_sizeX, 'f', 1), QString::number(m_sizeY, 'f', 1));
302 int fovFontSize = (pixelSizeX / 15) * (14.0 / fovString.count());
304 fontSize = std::min(fovFontSize, fontSize);
305 font.setPixelSize(fontSize);
306 p.setFont(font);
307
308 QRect sizeRect(targetRect.center().x(), targetRect.topLeft().y() - (pixelSizeY / 8), targetRect.width() / 2,
309 pixelSizeX / 10);
310 p.drawText(sizeRect, Qt::AlignCenter, QString("%1'x%2'").arg(QString::number(m_sizeX, 'f', 1), QString::number(m_sizeY, 'f',
311 1)));
312 }
313 }
314 break;
315 case CIRCLE:
316 p.drawEllipse(center, pixelSizeX / 2, pixelSizeY / 2);
317 break;
318 case CROSSHAIRS:
319 //Draw radial lines
320 p.drawLine(center.x() + 0.5 * pixelSizeX, center.y(), center.x() + 1.5 * pixelSizeX, center.y());
321 p.drawLine(center.x() - 0.5 * pixelSizeX, center.y(), center.x() - 1.5 * pixelSizeX, center.y());
322 p.drawLine(center.x(), center.y() + 0.5 * pixelSizeY, center.x(), center.y() + 1.5 * pixelSizeY);
323 p.drawLine(center.x(), center.y() - 0.5 * pixelSizeY, center.x(), center.y() - 1.5 * pixelSizeY);
324 //Draw circles at 0.5 & 1 degrees
325 p.drawEllipse(center, 0.5 * pixelSizeX, 0.5 * pixelSizeY);
327 break;
328 case BULLSEYE:
329 p.drawEllipse(center, 0.5 * pixelSizeX, 0.5 * pixelSizeY);
330 p.drawEllipse(center, 2.0 * pixelSizeX, 2.0 * pixelSizeY);
331 p.drawEllipse(center, 4.0 * pixelSizeX, 4.0 * pixelSizeY);
332 break;
333 case SOLIDCIRCLE:
334 {
335 QColor colorAlpha = color();
336 colorAlpha.setAlpha(127);
338 p.drawEllipse(center, pixelSizeX / 2, pixelSizeY / 2);
340 break;
341 }
342 default:
343 ;
344 }
345
346 p.restore();
347}
348
349void FOV::draw(QPainter &p, float x, float y)
350{
351 float xfactor = x / sizeX() * 57.3 * 60.0;
352 float yfactor = y / sizeY() * 57.3 * 60.0;
353 float zoomFactor = std::min(xfactor, yfactor);
354 switch (shape())
355 {
356 case CROSSHAIRS:
357 zoomFactor /= 3;
358 break;
359 case BULLSEYE:
360 zoomFactor /= 8;
361 break;
362 default:
363 ;
364 }
365 draw(p, zoomFactor);
366}
367
368SkyPoint FOV::center() const
369{
370 return m_center;
371}
372
373void FOV::setCenter(const SkyPoint &center)
374{
375 m_center = center;
376}
377
378float FOV::northPA() const
379{
380 return m_northPA;
381}
382
383void FOV::setNorthPA(float northPA)
384{
385 m_northPA = northPA;
386}
387
388void FOV::setImage(const QImage &image)
389{
390 m_image = image;
391}
392
393void FOV::setImageDisplay(bool value)
394{
395 m_imageDisplay = value;
396}
397
398bool FOV::lockCelestialPole() const
399{
400 return m_lockCelestialPole;
401}
402
403void FOV::setLockCelestialPole(bool lockCelestialPole)
404{
405 m_lockCelestialPole = lockCelestialPole;
406}
407
408QDBusArgument &operator<<(QDBusArgument &argument, const FOV::Shape &source)
409{
410 argument.beginStructure();
412 argument.endStructure();
413 return argument;
414}
415
416const QDBusArgument &operator>>(const QDBusArgument &argument, FOV::Shape &dest)
417{
418 int a;
419 argument.beginStructure();
420 argument >> a;
421 argument.endStructure();
422 dest = static_cast<FOV::Shape>(a);
423 return argument;
424}
static const QList< FOV * > & readFOVs()
Read list of FOVs from "fov.dat".
Definition fov.cpp:76
static bool save()
Write list of FOVs to "fov.dat".
Definition fov.cpp:49
static void releaseCache()
Release the FOV cache.
Definition fov.cpp:154
A simple class encapsulating a Field-of-View symbol.
Definition fov.h:28
FOV()
Default constructor.
Definition fov.cpp:185
void draw(QPainter &p, float zoomFactor)
draw the FOV symbol on a QPainter
Definition fov.cpp:230
static KStars * Instance()
Definition kstars.h:123
The sky coordinates of a point in the sky.
Definition skypoint.h:45
const CachingDms & ra() const
Definition skypoint.h:263
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition skypoint.cpp:77
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
bool registerObject(const QString &path, QObject *object, QDBusConnection::RegisterOptions options)
QDBusConnection sessionBus()
void setPixelSize(int pixelSize)
void drawEllipse(const QRectF &rectangle)
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, Qt::ImageConversionFlags flags)
void drawLine(const QLineF &line)
void drawRect(const QRectF &rectangle)
void drawText(const QPointF &position, const QString &text)
const QFont & font() const const
void restore()
void rotate(qreal angle)
void save()
void setBrush(const QBrush &brush)
void setFont(const QFont &font)
void setPen(const QColor &color)
void setRenderHint(QPainter::RenderHint hint, bool on)
void translate(const QPointF &offset)
QRect viewport() const const
QPoint center() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
int count() const const
QString number(int n, int base)
AlignCenter
QTextStream & center(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sun Feb 25 2024 18:45:33 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.