Kstars

fov.cpp
1 /*
2  SPDX-FileCopyrightText: 2003 Jason Harris <[email protected]>
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 
28 QList<FOV *> FOVManager::m_FOVs;
29 int FOV::m_ID = 1;
30 
31 FOVManager::~FOVManager()
32 {
33  qDeleteAll(m_FOVs);
34 }
35 
36 QList<FOV *> FOVManager::defaults()
37 {
38  QList<FOV *> fovs;
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 
62  QTextStream ostream(&f);
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  {
93  QTextStream istream(&f);
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 
160 FOV::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");
164  qDBusRegisterMetaType<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");
188  qDBusRegisterMetaType<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 
202 FOV::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 
216 void 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 
230 void 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 
258  p.translate(offsetXPixelSize, offsetYPixelSize);
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 
271  p.drawRect(targetRect);
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);
298  p.drawText(nameRect, Qt::AlignCenter, name());
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());
303  fovFontSize = std::min(maxYPixelSize, fovFontSize);
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);
326  p.drawEllipse(center, pixelSizeX, 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);
337  p.setBrush(QBrush(colorAlpha));
338  p.drawEllipse(center, pixelSizeX / 2, pixelSizeY / 2);
340  break;
341  }
342  default:
343  ;
344  }
345 
346  p.restore();
347 }
348 
349 void 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 
368 SkyPoint FOV::center() const
369 {
370  return m_center;
371 }
372 
373 void FOV::setCenter(const SkyPoint &center)
374 {
375  m_center = center;
376 }
377 
378 float FOV::northPA() const
379 {
380  return m_northPA;
381 }
382 
383 void FOV::setNorthPA(float northPA)
384 {
385  m_northPA = northPA;
386 }
387 
388 void FOV::setImage(const QImage &image)
389 {
390  m_image = image;
391 }
392 
393 void FOV::setImageDisplay(bool value)
394 {
395  m_imageDisplay = value;
396 }
397 
398 bool FOV::lockCelestialPole() const
399 {
400  return m_lockCelestialPole;
401 }
402 
403 void FOV::setLockCelestialPole(bool lockCelestialPole)
404 {
405  m_lockCelestialPole = lockCelestialPole;
406 }
407 
408 QDBusArgument &operator<<(QDBusArgument &argument, const FOV::Shape &source)
409 {
410  argument.beginStructure();
411  argument << static_cast<int>(source);
412  argument.endStructure();
413  return argument;
414 }
415 
416 const 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 }
void append(const T &value)
Definition: fov.h:27
AlignCenter
void setPen(const QColor &color)
QPoint topLeft() const const
QString number(int n, int base)
void rotate(qreal angle)
void drawEllipse(const QRectF &rectangle)
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
void drawRect(const QRectF &rectangle)
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
int width() const const
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
SkyMap * map() const
Definition: kstars.h:141
bool registerObject(const QString &path, QObject *object, QDBusConnection::RegisterOptions options)
int x() const const
int y() const const
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
void drawText(const QPointF &position, const QString &text)
void draw(QPainter &p, float zoomFactor)
draw the FOV symbol on a QPainter
Definition: fov.cpp:230
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, Qt::ImageConversionFlags flags)
static KStars * Instance()
Definition: kstars.h:123
static bool save()
Write list of FOVs to "fov.dat".
Definition: fov.cpp:49
QString i18n(const char *text, const TYPE &arg...)
QDBusConnection sessionBus()
FOV()
Default constructor.
Definition: fov.cpp:185
void setPixelSize(int pixelSize)
bool atEnd() const const
QString readLine(qint64 maxlen)
static void releaseCache()
Release the FOV cache.
Definition: fov.cpp:154
void setAlpha(int alpha)
QPoint center() const const
void setBrush(const QBrush &brush)
const CachingDms & ra() const
Definition: skypoint.h:263
int count() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QDebug operator<<(QDebug d, const QCPVector2D &vec)
Definition: qcustomplot.h:446
const double & Degrees() const
Definition: dms.h:141
void beginStructure()
QPointF toScreen(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const
This is exactly the same as toScreenVec but it returns a QPointF.
Definition: projector.cpp:93
void drawLine(const QLineF &line)
QRect viewport() const const
const QFont & font() const const
QPoint toPoint() const const
void translate(const QPointF &offset)
static const QList< FOV * > & readFOVs()
Read list of FOVs from "fov.dat".
Definition: fov.cpp:76
void clear()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void restore()
void endStructure()
QTextStream & center(QTextStream &stream)
void save()
const Projector * projector() const
Get the current projector.
Definition: skymap.h:300
void setRenderHint(QPainter::RenderHint hint, bool on)
void setFont(const QFont &font)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Sep 27 2023 04:02:10 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.