Kstars

skyqpainter.cpp
1 /*
2  SPDX-FileCopyrightText: 2010 Henry de Valence <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "skyqpainter.h"
8 
9 #include <QPointer>
10 
11 #include "kstarsdata.h"
12 #include "kstars.h"
13 #include "Options.h"
14 #include "skymap.h"
15 #include "projections/projector.h"
16 #include "skycomponents/flagcomponent.h"
17 #include "skycomponents/linelist.h"
18 #include "skycomponents/linelistlabel.h"
19 #include "skycomponents/satellitescomponent.h"
20 #include "skycomponents/skiphashlist.h"
21 #include "skycomponents/skymapcomposite.h"
22 #include "skycomponents/solarsystemcomposite.h"
23 #include "skycomponents/earthshadowcomponent.h"
24 #include "skycomponents/imageoverlaycomponent.h"
25 #include "skyobjects/skyobject.h"
26 #include "skyobjects/constellationsart.h"
27 #include "skyobjects/catalogobject.h"
28 #include "skyobjects/ksasteroid.h"
29 #include "skyobjects/kscomet.h"
30 #include "skyobjects/kssun.h"
31 #include "skyobjects/satellite.h"
32 #include "skyobjects/supernova.h"
33 #include "skyobjects/ksearthshadow.h"
34 #ifdef HAVE_INDI
35 #include "skyobjects/mosaictiles.h"
36 #endif
37 #include "hips/hipsrenderer.h"
38 #include "terrain/terrainrenderer.h"
39 #include <QElapsedTimer>
40 #include "auxiliary/rectangleoverlap.h"
41 
42 namespace
43 {
44 // Convert spectral class to numerical index.
45 // If spectral class is invalid return index for white star (A class)
46 int harvardToIndex(char c)
47 {
48  switch (c)
49  {
50  case 'o':
51  case 'O':
52  return 0;
53  case 'b':
54  case 'B':
55  return 1;
56  case 'a':
57  case 'A':
58  return 2;
59  case 'f':
60  case 'F':
61  return 3;
62  case 'g':
63  case 'G':
64  return 4;
65  case 'k':
66  case 'K':
67  return 5;
68  case 'm':
69  case 'M':
70  return 6;
71  // For unknown spectral class assume A class (white star)
72  default:
73  return 2;
74  }
75 }
76 
77 // Total number of sizes of stars.
78 const int nStarSizes = 15;
79 // Total number of spectral classes
80 // N.B. Must be in sync with harvardToIndex
81 const int nSPclasses = 7;
82 
83 // Cache for star images.
84 //
85 // These pixmaps are never deallocated. Not really good...
86 QPixmap *imageCache[nSPclasses][nStarSizes] = { { nullptr } };
87 
88 std::unique_ptr<QPixmap> visibleSatPixmap, invisibleSatPixmap;
89 } // namespace
90 
91 int SkyQPainter::starColorMode = 0;
92 QColor SkyQPainter::m_starColor = QColor();
93 QMap<char, QColor> SkyQPainter::ColorMap = QMap<char, QColor>();
94 
96 {
97  for (char &color : ColorMap.keys())
98  {
99  QPixmap **pmap = imageCache[harvardToIndex(color)];
100 
101  for (int size = 1; size < nStarSizes; size++)
102  {
103  if (pmap[size])
104  delete pmap[size];
105 
106  pmap[size] = nullptr;
107  }
108  }
109 }
110 
112 {
113  Q_ASSERT(pd);
114  m_pd = pd;
115  m_size = QSize(pd->width(), pd->height());
116  m_hipsRender = new HIPSRenderer();
117 }
118 
120 {
121  Q_ASSERT(pd);
122  m_pd = pd;
123  m_size = size;
124  m_hipsRender = new HIPSRenderer();
125 }
126 
128 {
129  Q_ASSERT(widget);
130  // Set paint device pointer to pd or to the widget if pd = 0
131  m_pd = (pd ? pd : widget);
132  m_size = widget->size();
133  m_hipsRender = new HIPSRenderer();
134 }
135 
136 SkyQPainter::~SkyQPainter()
137 {
138  delete (m_hipsRender);
139 }
140 
142 {
143  QPainter::begin(m_pd);
144  bool aa = !SkyMap::Instance()->isSlewing() && Options::useAntialias();
147  m_proj = SkyMap::Instance()->projector();
148 }
149 
151 {
152  QPainter::end();
153 }
154 
156 {
157  //FIXME use projector
158  fillRect(0, 0, m_size.width(), m_size.height(),
159  KStarsData::Instance()->colorScheme()->colorNamed("SkyColor"));
160 }
161 
162 void SkyQPainter::setPen(const QPen &pen)
163 {
165 }
166 
167 void SkyQPainter::setBrush(const QBrush &brush)
168 {
170 }
171 
173 {
174  const int starColorIntensity = Options::starColorIntensity();
175 
176  ColorMap.clear();
177  switch (Options::starColorMode())
178  {
179  case 1: // Red stars.
180  m_starColor = Qt::red;
181  break;
182  case 2: // Black stars.
183  m_starColor = Qt::black;
184  break;
185  case 3: // White stars
186  m_starColor = Qt::white;
187  break;
188  case 0: // Real color
189  default: // And use real color for everything else
190  m_starColor = QColor();
191  ColorMap.insert('O', QColor::fromRgb(0, 0, 255));
192  ColorMap.insert('B', QColor::fromRgb(0, 200, 255));
193  ColorMap.insert('A', QColor::fromRgb(0, 255, 255));
194  ColorMap.insert('F', QColor::fromRgb(200, 255, 100));
195  ColorMap.insert('G', QColor::fromRgb(255, 255, 0));
196  ColorMap.insert('K', QColor::fromRgb(255, 100, 0));
197  ColorMap.insert('M', QColor::fromRgb(255, 0, 0));
198  break;
199  }
200  if (ColorMap.isEmpty())
201  {
202  ColorMap.insert('O', m_starColor);
203  ColorMap.insert('B', m_starColor);
204  ColorMap.insert('A', m_starColor);
205  ColorMap.insert('F', m_starColor);
206  ColorMap.insert('G', m_starColor);
207  ColorMap.insert('K', m_starColor);
208  ColorMap.insert('M', m_starColor);
209  }
210 
211  for (char &color : ColorMap.keys())
212  {
213  QPixmap BigImage(15, 15);
214  BigImage.fill(Qt::transparent);
215 
216  QPainter p;
217  p.begin(&BigImage);
218 
219  if (Options::starColorMode() == 0)
220  {
221  qreal h, s, v, a;
223  QColor starColor = ColorMap[color];
224  starColor.getHsvF(&h, &s, &v, &a);
225  for (int i = 0; i < 8; i++)
226  {
227  for (int j = 0; j < 8; j++)
228  {
229  qreal x = i - 7;
230  qreal y = j - 7;
231  qreal dist = sqrt(x * x + y * y) / 7.0;
232  starColor.setHsvF(
233  h,
234  qMin(qreal(1),
235  dist < (10 - starColorIntensity) / 10.0 ? 0 : dist),
236  v,
237  qMax(qreal(0),
238  dist < (10 - starColorIntensity) / 20.0 ? 1 : 1 - dist));
239  p.setPen(starColor);
240  p.drawPoint(i, j);
241  p.drawPoint(14 - i, j);
242  p.drawPoint(i, 14 - j);
243  p.drawPoint(14 - i, 14 - j);
244  }
245  }
246  }
247  else
248  {
250  p.setPen(QPen(ColorMap[color], 2.0));
251  p.setBrush(p.pen().color());
252  p.drawEllipse(QRectF(2, 2, 10, 10));
253  }
254  p.end();
255 
256  // Cache array slice
257  QPixmap **pmap = imageCache[harvardToIndex(color)];
258 
259  for (int size = 1; size < nStarSizes; size++)
260  {
261  if (!pmap[size])
262  pmap[size] = new QPixmap();
263  *pmap[size] = BigImage.scaled(size, size, Qt::KeepAspectRatio,
265  }
266  }
267  starColorMode = Options::starColorMode();
268 
269  if (!visibleSatPixmap.get())
270  visibleSatPixmap.reset(new QPixmap(":/icons/kstars_satellites_visible.svg"));
271  if (!invisibleSatPixmap.get())
272  invisibleSatPixmap.reset(new QPixmap(":/icons/kstars_satellites_invisible.svg"));
273 }
274 
276 {
277  bool aVisible, bVisible;
278  QPointF aScreen = m_proj->toScreen(a, true, &aVisible);
279  QPointF bScreen = m_proj->toScreen(b, true, &bVisible);
280 
281  drawLine(aScreen, bScreen);
282 
283  //THREE CASES:
284  // if (aVisible && bVisible)
285  // {
286  // //Both a,b visible, so paint the line normally:
287  // drawLine(aScreen, bScreen);
288  // }
289  // else if (aVisible)
290  // {
291  // //a is visible but b isn't:
292  // drawLine(aScreen, m_proj->clipLine(a, b));
293  // }
294  // else if (bVisible)
295  // {
296  // //b is visible but a isn't:
297  // drawLine(bScreen, m_proj->clipLine(b, a));
298  // } //FIXME: what if both are offscreen but the line isn't?
299 }
300 
301 void SkyQPainter::drawSkyPolyline(LineList *list, SkipHashList *skipList,
302  LineListLabel *label)
303 {
304  SkyList *points = list->points();
305  bool isVisible, isVisibleLast;
306 
307  if (points->size() == 0)
308  return;
309  QPointF oLast = m_proj->toScreen(points->first().get(), true, &isVisibleLast);
310  // & with the result of checkVisibility to clip away things below horizon
311  isVisibleLast &= m_proj->checkVisibility(points->first().get());
312  QPointF oThis, oThis2;
313 
314  for (int j = 1; j < points->size(); j++)
315  {
316  SkyPoint *pThis = points->at(j).get();
317 
318  oThis2 = oThis = m_proj->toScreen(pThis, true, &isVisible);
319  // & with the result of checkVisibility to clip away things below horizon
320  isVisible &= m_proj->checkVisibility(pThis);
321  bool doSkip = false;
322  if (skipList)
323  {
324  doSkip = skipList->skip(j);
325  }
326 
327  bool pointsVisible = false;
328  //Temporary solution to avoid random lines in Gnomonic projection and draw lines up to horizon
329  if (SkyMap::Instance()->projector()->type() == Projector::Gnomonic)
330  {
331  if (isVisible && isVisibleLast)
332  pointsVisible = true;
333  }
334  else
335  {
336  if (isVisible || isVisibleLast)
337  pointsVisible = true;
338  }
339 
340  if (!doSkip)
341  {
342  if (pointsVisible)
343  {
344  drawLine(oLast, oThis);
345  if (label)
346  label->updateLabelCandidates(oThis.x(), oThis.y(), list, j);
347  }
348  }
349 
350  oLast = oThis2;
351  isVisibleLast = isVisible;
352  }
353 }
354 
355 void SkyQPainter::drawSkyPolygon(LineList *list, bool forceClip)
356 {
357  bool isVisible = false, isVisibleLast;
358  SkyList *points = list->points();
359  QPolygonF polygon;
360 
361  if (forceClip == false)
362  {
363  for (const auto &point : *points)
364  {
365  polygon << m_proj->toScreen(point.get(), false, &isVisibleLast);
366  isVisible |= isVisibleLast;
367  }
368 
369  // If 1+ points are visible, draw it
370  if (polygon.size() && isVisible)
371  drawPolygon(polygon);
372 
373  return;
374  }
375 
376  SkyPoint *pLast = points->last().get();
377  QPointF oLast = m_proj->toScreen(pLast, true, &isVisibleLast);
378  // & with the result of checkVisibility to clip away things below horizon
379  isVisibleLast &= m_proj->checkVisibility(pLast);
380 
381  for (const auto &point : *points)
382  {
383  SkyPoint *pThis = point.get();
384  QPointF oThis = m_proj->toScreen(pThis, true, &isVisible);
385  // & with the result of checkVisibility to clip away things below horizon
386  isVisible &= m_proj->checkVisibility(pThis);
387 
388  if (isVisible && isVisibleLast)
389  {
390  polygon << oThis;
391  }
392  else if (isVisibleLast)
393  {
394  QPointF oMid = m_proj->clipLine(pLast, pThis);
395  polygon << oMid;
396  }
397  else if (isVisible)
398  {
399  QPointF oMid = m_proj->clipLine(pThis, pLast);
400  polygon << oMid;
401  polygon << oThis;
402  }
403 
404  pLast = pThis;
405  oLast = oThis;
406  isVisibleLast = isVisible;
407  }
408 
409  if (polygon.size())
410  drawPolygon(polygon);
411 }
412 
414 {
415  if (!m_proj->checkVisibility(planet))
416  return false;
417 
418  bool visible = false;
419  QPointF pos = m_proj->toScreen(planet, true, &visible);
420  if (!visible || !m_proj->onScreen(pos))
421  return false;
422 
423  float fakeStarSize = (10.0 + log10(Options::zoomFactor()) - log10(MINZOOM)) *
424  (10 - planet->mag()) / 10;
425  if (fakeStarSize > 15.0)
426  fakeStarSize = 15.0;
427 
428  double size = planet->angSize() * dms::PI * Options::zoomFactor() / 10800.0;
429  if (size < fakeStarSize && planet->name() != i18n("Sun") &&
430  planet->name() != i18n("Moon"))
431  {
432  // Draw them as bright stars of appropriate color instead of images
433  char spType;
434  //FIXME: do these need i18n?
435  if (planet->name() == i18n("Mars"))
436  {
437  spType = 'K';
438  }
439  else if (planet->name() == i18n("Jupiter") || planet->name() == i18n("Mercury") ||
440  planet->name() == i18n("Saturn"))
441  {
442  spType = 'F';
443  }
444  else
445  {
446  spType = 'B';
447  }
448  drawPointSource(pos, fakeStarSize, spType);
449  }
450  else
451  {
452  float sizemin = 1.0;
453  if (planet->name() == i18n("Sun") || planet->name() == i18n("Moon"))
454  sizemin = 8.0;
455 
456  if (size < sizemin)
457  size = sizemin;
458 
459  if (Options::showPlanetImages() && !planet->image().isNull())
460  {
461  //Because Saturn has rings, we inflate its image size by a factor 2.5
462  if (planet->name() == "Saturn")
463  size = int(2.5 * size);
464  // Scale size exponentially so it is visible at large zooms
465  else if (planet->name() == "Pluto")
466  size = int(size * exp(1.5 * size));
467 
468  save();
469  translate(pos);
470  rotate(m_proj->findPA(planet, pos.x(), pos.y()));
471  drawImage(QRectF(-0.5 * size, -0.5 * size, size, size), planet->image());
472  restore();
473  }
474  else //Otherwise, draw a simple circle.
475  {
476  drawEllipse(pos, size * .5, size * .5);
477  }
478  }
479  return true;
480 }
481 
483 {
484  if (!m_proj->checkVisibility(shadow))
485  return false;
486 
487  bool visible = false;
488  QPointF pos = m_proj->toScreen(shadow, true, &visible);
489 
490  if (!visible)
491  return false;
492 
493  double umbra_size =
494  shadow->getUmbraAngSize() * dms::PI * Options::zoomFactor() / 10800.0;
495  double penumbra_size =
496  shadow->getPenumbraAngSize() * dms::PI * Options::zoomFactor() / 10800.0;
497 
498  save();
499  setBrush(QBrush(QColor(255, 96, 38, 128)));
500  drawEllipse(pos, umbra_size, umbra_size);
501  setBrush(QBrush(QColor(255, 96, 38, 90)));
502  drawEllipse(pos, penumbra_size, penumbra_size);
503  restore();
504 
505  return true;
506 }
507 
509 {
510  if (!m_proj->checkVisibility(com))
511  return false;
512 
513  double size =
514  com->angSize() * dms::PI * Options::zoomFactor() / 10800.0 / 2; // Radius
515  if (size < 1)
516  size = 1;
517 
518  bool visible = false;
519  QPointF pos = m_proj->toScreen(com, true, &visible);
520 
521  // Draw the coma. FIXME: Another Check??
522  if (visible && m_proj->onScreen(pos))
523  {
524  // Draw the comet.
525  drawEllipse(pos, size, size);
526 
527  double comaLength =
528  (com->getComaAngSize().arcmin() * dms::PI * Options::zoomFactor() / 10800.0);
529 
530  // If coma is visible and long enough.
531  if (Options::showCometComas() && comaLength > size)
532  {
533  KSSun *sun =
534  KStarsData::Instance()->skyComposite()->solarSystemComposite()->sun();
535 
536  // Find the angle to the sun.
537  double comaAngle = m_proj->findPA(sun, pos.x(), pos.y());
538 
539  const QVector<QPoint> coma = { QPoint(pos.x() - size, pos.y()),
540  QPoint(pos.x() + size, pos.y()),
541  QPoint(pos.x(), pos.y() + comaLength)
542  };
543 
544  QPolygon comaPoly(coma);
545 
546  comaPoly =
547  QTransform()
548  .translate(pos.x(), pos.y())
549  .rotate(
550  comaAngle) // Already + 180 Deg, because rotated from south, not north.
551  .translate(-pos.x(), -pos.y())
552  .map(comaPoly);
553 
554  save();
555 
556  // Nice fade for the Coma.
557  QLinearGradient linearGrad(pos, comaPoly.point(2));
558  linearGrad.setColorAt(0, QColor("white"));
559  linearGrad.setColorAt(size / comaLength, QColor("white"));
560  linearGrad.setColorAt(0.9, QColor("transparent"));
561  setBrush(linearGrad);
562 
563  // Render Coma.
564  drawConvexPolygon(comaPoly);
565  restore();
566  }
567 
568  return true;
569  }
570  else
571  {
572  return false;
573  }
574 }
575 
577 {
578  if (!m_proj->checkVisibility(ast))
579  {
580  return false;
581  }
582 
583  bool visible = false;
584  QPointF pos = m_proj->toScreen(ast, true, &visible);
585 
586  if (visible && m_proj->onScreen(pos))
587  {
588  KStarsData *data = KStarsData::Instance();
589 
590  setPen(data->colorScheme()->colorNamed("AsteroidColor"));
591  drawLine(QPoint(pos.x() - 1.0, pos.y()), QPoint(pos.x() + 1.0, pos.y()));
592  drawLine(QPoint(pos.x(), pos.y() - 1.0), QPoint(pos.x(), pos.y() + 1.0));
593 
594  return true;
595  }
596 
597  return false;
598 }
599 
600 bool SkyQPainter::drawPointSource(const SkyPoint *loc, float mag, char sp)
601 {
602  //Check if it's even visible before doing anything
603  if (!m_proj->checkVisibility(loc))
604  return false;
605 
606  bool visible = false;
607  QPointF pos = m_proj->toScreen(loc, true, &visible);
608  // FIXME: onScreen here should use canvas size rather than SkyMap size, especially while printing in portrait mode!
609  if (visible && m_proj->onScreen(pos))
610  {
611  drawPointSource(pos, starWidth(mag), sp);
612  return true;
613  }
614  else
615  {
616  return false;
617  }
618 }
619 
620 void SkyQPainter::drawPointSource(const QPointF &pos, float size, char sp)
621 {
622  int isize = qMin(static_cast<int>(size), 14);
623  if (!m_vectorStars || starColorMode == 0)
624  {
625  // Draw stars as bitmaps, either because we were asked to, or because we're painting real colors
626  QPixmap *im = imageCache[harvardToIndex(sp)][isize];
627  float offset = 0.5 * im->width();
628  drawPixmap(QPointF(pos.x() - offset, pos.y() - offset), *im);
629  }
630  else
631  {
632  // Draw stars as vectors, for better printing / SVG export etc.
633  if (starColorMode != 4)
634  {
635  setPen(m_starColor);
636  setBrush(m_starColor);
637  }
638  else
639  {
640  // Note: This is not efficient, but we use vector stars only when plotting SVG, not when drawing the skymap, so speed is not very important.
641  QColor c = ColorMap.value(sp, Qt::white);
642  setPen(c);
643  setBrush(c);
644  }
645 
646  // Be consistent with old raster representation
647  if (size > 14)
648  size = 14;
649  if (size >= 2)
650  drawEllipse(pos.x() - 0.5 * size, pos.y() - 0.5 * size, int(size), int(size));
651  else if (size >= 1)
652  drawPoint(pos.x(), pos.y());
653  }
654 }
655 
657 {
658  double zoom = Options::zoomFactor();
659 
660  bool visible = false;
661  obj->EquatorialToHorizontal(KStarsData::Instance()->lst(),
662  KStarsData::Instance()->geo()->lat());
663  QPointF constellationmidpoint = m_proj->toScreen(obj, true, &visible);
664 
665  if (!visible || !m_proj->onScreen(constellationmidpoint))
666  return false;
667 
668  //qDebug() << Q_FUNC_INFO << "o->pa() " << obj->pa();
669  float positionangle =
670  m_proj->findPA(obj, constellationmidpoint.x(), constellationmidpoint.y());
671  //qDebug() << Q_FUNC_INFO << " final PA " << positionangle;
672 
673  float w = obj->getWidth() * 60 * dms::PI * zoom / 10800;
674  float h = obj->getHeight() * 60 * dms::PI * zoom / 10800;
675 
676  save();
677 
679 
680  translate(constellationmidpoint);
681  rotate(positionangle);
682  setOpacity(0.7);
683  drawImage(QRectF(-0.5 * w, -0.5 * h, w, h), obj->image());
684  setOpacity(1);
685 
687  restore();
688  return true;
689 }
690 
691 #ifdef HAVE_INDI
692 bool SkyQPainter::drawMosaicPanel(MosaicTiles *obj)
693 {
694  bool visible = false;
695  obj->EquatorialToHorizontal(KStarsData::Instance()->lst(),
696  KStarsData::Instance()->geo()->lat());
697  QPointF tileMid = m_proj->toScreen(obj, true, &visible);
698 
699  if (!visible || !m_proj->onScreen(tileMid) || !obj->isValid())
700  return false;
701 
702  //double northRotation = m_proj->findNorthPA(obj, tileMid.x(), tileMid.y())
703 
704  // convert 0 to +180 EAST, and 0 to -180 WEST to 0 to 360 CCW
705  auto PA = (obj->positionAngle() < 0) ? obj->positionAngle() + 360 : obj->positionAngle();
706  auto finalPA = m_proj->findNorthPA(obj, tileMid.x(), tileMid.y()) - PA;
707 
708  save();
709  translate(tileMid.toPoint());
710  rotate(finalPA);
711  obj->draw(this);
712  restore();
713 
714  return true;
715 }
716 #endif
717 
718 bool SkyQPainter::drawHips(bool useCache)
719 {
720  int w = viewport().width();
721  int h = viewport().height();
722 
723  if (useCache && m_HiPSImage)
724  {
725  drawImage(viewport(), *m_HiPSImage.data());
726  return true;
727  }
728  else
729  {
730  m_HiPSImage.reset(new QImage(w, h, QImage::Format_ARGB32_Premultiplied));
731  bool rendered = m_hipsRender->render(w, h, m_HiPSImage.data(), m_proj);
732  if (rendered)
733  drawImage(viewport(), *m_HiPSImage.data());
734  return rendered;
735  }
736 }
737 
738 bool SkyQPainter::drawTerrain(bool useCache)
739 {
740  // TODO
741  Q_UNUSED(useCache);
742  int w = viewport().width();
743  int h = viewport().height();
744  QImage *terrainImage = new QImage(w, h, QImage::Format_ARGB32_Premultiplied);
745  TerrainRenderer *renderer = TerrainRenderer::Instance();
746  bool rendered = renderer->render(w, h, terrainImage, m_proj);
747  if (rendered)
748  drawImage(viewport(), *terrainImage);
749 
750  delete (terrainImage);
751  return rendered;
752 }
753 
754 bool SkyQPainter::drawImageOverlay(const QList<ImageOverlay> *imageOverlays, bool useCache)
755 {
756  Q_UNUSED(useCache);
757  if (!Options::showImageOverlays())
758  return false;
759 
760  constexpr int minDisplayDimension = 5;
761 
762  // Convert the RA/DEC from j2000 to jNow and add in az/alt computations.
763  auto localTime = KStarsData::Instance()->geo()->UTtoLT(KStarsData::Instance()->clock()->utc());
764 
765  const ViewParams view = m_proj->viewParams();
766  const double vw = view.width, vh = view.height;
767  RectangleOverlap overlap(QPointF(vw / 2.0, vh / 2.0), vw, vh);
768 
769  // QElapsedTimer drawTimer;
770  // drawTimer.restart();
771  int numDrawn = 0;
772  for (const ImageOverlay &o : *imageOverlays)
773  {
774  if (o.m_Status != ImageOverlay::AVAILABLE || o.m_Img.get() == nullptr)
775  continue;
776 
777  double orientation = o.m_Orientation, ra = o.m_RA, dec = o.m_DEC, scale = o.m_ArcsecPerPixel;
778  const int origWidth = o.m_Width, origHeight = o.m_Height;
779 
780  // Not sure why I have to do this, suspect it's related to the East-to-the-right thing.
781  // Note that I have mirrored the image above, so east-to-the-right=false is now east-to-the-right=true
782  // BTW, solver gave me -66, but astrometry.net gave me 246.1 East of North
783  orientation += 180;
784 
785  const dms raDms(ra), decDms(dec);
786  SkyPoint coord(raDms, decDms);
787  coord.apparentCoord(static_cast<long double>(J2000), KStars::Instance()->data()->ut().djd());
788  coord.EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
789 
790  // Find if the object is not visible, or if it is very small.
791  const double a = origWidth * scale / 60.0; // This is the width of the image in arcmin--not the major axis
792  const double zoom = Options::zoomFactor();
793  // W & h are the actual pixel width and height (as doubles) though
794  // the projection size might be smaller.
795  const double w = a * dms::PI * zoom / 10800.0;
796  const double h = w * origHeight / origWidth;
797  const double maxDimension = std::max(w, h);
798  if (maxDimension < minDisplayDimension)
799  continue;
800 
801  bool visible;
802  QPointF pos = m_proj->toScreen(&coord, true, &visible);
803  if (!visible || isnan(pos.x()) || isnan(pos.y()))
804  continue;
805 
806  const auto PA = (orientation < 0) ? orientation + 360 : orientation;
807  const auto finalPA = m_proj->findNorthPA(&coord, pos.x(), pos.y()) - PA;
808  if (!overlap.intersects(pos, w, h, finalPA))
809  continue;
810 
811  save();
812  translate(pos);
813  rotate(finalPA);
814  drawImage(QRectF(-0.5 * w, -0.5 * h, w, h), *(o.m_Img.get()));
815  numDrawn++;
816  restore();
817  }
818  // fprintf(stderr, "DrawTimer: %lldms for %d images\n", drawTimer.elapsed(), numDrawn);
819  return true;
820 }
821 
822 void SkyQPainter::drawCatalogObjectImage(const QPointF &pos, const CatalogObject &obj,
823  float positionAngle)
824 {
825  const auto &image = obj.image();
826 
827  if (!image.first)
828  return;
829 
830  double zoom = Options::zoomFactor();
831  double w = obj.a() * dms::PI * zoom / 10800.0;
832  double h = obj.e() * w;
833 
834  save();
835  translate(pos);
836  rotate(positionAngle);
837  drawImage(QRectF(-0.5 * w, -0.5 * h, w, h), image.second);
838  restore();
839 }
840 
842 {
843  if (!m_proj->checkVisibility(&obj))
844  return false;
845 
846  bool visible = false;
847  QPointF pos = m_proj->toScreen(&obj, true, &visible);
848  if (!visible || !m_proj->onScreen(pos))
849  return false;
850 
851  // if size is 0.0 set it to 1.0, this are normally stars (type 0 and 1)
852  // if we use size 0.0 the star wouldn't be drawn
853  float majorAxis = obj.a();
854  if (majorAxis == 0.0)
855  {
856  majorAxis = 1.0;
857  }
858 
859  float size = majorAxis * dms::PI * Options::zoomFactor() / 10800.0;
860 
861  const auto positionAngle =
862  m_proj->findNorthPA(&obj, pos.x(), pos.y()) - obj.pa() + 90;
863 
864  // Draw image
865  if (Options::showInlineImages() && Options::zoomFactor() > 5. * MINZOOM &&
866  !Options::showHIPS())
867  drawCatalogObjectImage(pos, obj, positionAngle);
868 
869  // Draw Symbol
870  drawDeepSkySymbol(pos, obj.type(), size, obj.e(), positionAngle);
871 
872  return true;
873 }
874 
875 void SkyQPainter::drawDeepSkySymbol(const QPointF &pos, int type, float size, float e,
876  float positionAngle)
877 {
878  float x = pos.x();
879  float y = pos.y();
880  float zoom = Options::zoomFactor();
881 
882  int isize = int(size);
883 
884  float dx1 = -0.5 * size;
885  float dx2 = 0.5 * size;
886  float dy1 = -1.0 * e * size / 2.;
887  float dy2 = e * size / 2.;
888  float x1 = x + dx1;
889  float x2 = x + dx2;
890  float y1 = y + dy1;
891  float y2 = y + dy2;
892 
893  float dxa = -size / 4.;
894  float dxb = size / 4.;
895  float dya = -1.0 * e * size / 4.;
896  float dyb = e * size / 4.;
897  float xa = x + dxa;
898  float xb = x + dxb;
899  float ya = y + dya;
900  float yb = y + dyb;
901 
902  QString color;
903 
904  float psize;
905 
906  QBrush tempBrush;
907 
908  std::function<void(float, float, float, float)> lambdaDrawEllipse;
909  std::function<void(float, float, float, float)> lambdaDrawLine;
910  std::function<void(float, float, float, float)> lambdaDrawCross;
911 
912  if (Options::useAntialias())
913  {
914  lambdaDrawEllipse = [this](float x, float y, float width, float height)
915  {
916  drawEllipse(QRectF(x, y, width, height));
917  };
918  lambdaDrawLine = [this](float x1, float y1, float x2, float y2)
919  {
920  drawLine(QLineF(x1, y1, x2, y2));
921  };
922  lambdaDrawCross = [this](float centerX, float centerY, float sizeX, float sizeY)
923  {
924  drawLine(
925  QLineF(centerX - sizeX / 2., centerY, centerX + sizeX / 2., centerY));
926  drawLine(
927  QLineF(centerX, centerY - sizeY / 2., centerX, centerY + sizeY / 2.));
928  };
929  }
930  else
931  {
932  lambdaDrawEllipse = [this](float x, float y, float width, float height)
933  {
934  drawEllipse(QRect(x, y, width, height));
935  };
936  lambdaDrawLine = [this](float x1, float y1, float x2, float y2)
937  {
938  drawLine(QLine(x1, y1, x2, y2));
939  };
940  lambdaDrawCross = [this](float centerX, float centerY, float sizeX, float sizeY)
941  {
942  drawLine(QLine(centerX - sizeX / 2., centerY, centerX + sizeX / 2., centerY));
943  drawLine(QLine(centerX, centerY - sizeY / 2., centerX, centerY + sizeY / 2.));
944  };
945  }
946 
947  switch ((SkyObject::TYPE)type)
948  {
949  case SkyObject::STAR:
950  case SkyObject::CATALOG_STAR: //catalog star
951  //Some NGC/IC objects are stars...changed their type to 1 (was double star)
952  if (size < 2.)
953  size = 2.;
954  lambdaDrawEllipse(x - size / 2., y - size / 2., size, size);
955  break;
956  case SkyObject::PLANET: //Planet
957  break;
958  case SkyObject::OPEN_CLUSTER: //Open cluster; draw circle of points
959  case SkyObject::ASTERISM: // Asterism
960  {
961  tempBrush = brush();
962  color = pen().color().name();
963  setBrush(pen().color());
964  psize = 2.;
965  if (size > 50.)
966  psize *= 2.;
967  if (size > 100.)
968  psize *= 2.;
969  auto putDot = [psize, &lambdaDrawEllipse](float x, float y)
970  {
971  lambdaDrawEllipse(x - psize / 2., y - psize / 2., psize, psize);
972  };
973  putDot(xa, y1);
974  putDot(xb, y1);
975  putDot(xa, y2);
976  putDot(xb, y2);
977  putDot(x1, ya);
978  putDot(x1, yb);
979  putDot(x2, ya);
980  putDot(x2, yb);
981  setBrush(tempBrush);
982  break;
983  }
984  case SkyObject::GLOBULAR_CLUSTER: //Globular Cluster
985  if (size < 2.)
986  size = 2.;
987  save();
988  translate(x, y);
989  color = pen().color().name();
990  rotate(positionAngle); //rotate the coordinate system
991  lambdaDrawEllipse(dx1, dy1, size, e * size);
992  lambdaDrawCross(0, 0, size, e * size);
993  restore(); //reset coordinate system
994  break;
995 
996  case SkyObject::GASEOUS_NEBULA: //Gaseous Nebula
997  case SkyObject::DARK_NEBULA: // Dark Nebula
998  save();
999  translate(x, y);
1000  rotate(positionAngle); //rotate the coordinate system
1001  color = pen().color().name();
1002  lambdaDrawLine(dx1, dy1, dx2, dy1);
1003  lambdaDrawLine(dx2, dy1, dx2, dy2);
1004  lambdaDrawLine(dx2, dy2, dx1, dy2);
1005  lambdaDrawLine(dx1, dy2, dx1, dy1);
1006  restore(); //reset coordinate system
1007  break;
1008  case SkyObject::PLANETARY_NEBULA: //Planetary Nebula
1009  if (size < 2.)
1010  size = 2.;
1011  save();
1012  translate(x, y);
1013  rotate(positionAngle); //rotate the coordinate system
1014  color = pen().color().name();
1015  lambdaDrawEllipse(dx1, dy1, size, e * size);
1016  lambdaDrawLine(0., dy1, 0., dy1 - e * size / 2.);
1017  lambdaDrawLine(0., dy2, 0., dy2 + e * size / 2.);
1018  lambdaDrawLine(dx1, 0., dx1 - size / 2., 0.);
1019  lambdaDrawLine(dx2, 0., dx2 + size / 2., 0.);
1020  restore(); //reset coordinate system
1021  break;
1022  case SkyObject::SUPERNOVA_REMNANT: //Supernova remnant // FIXME: Why is SNR drawn different from a gaseous nebula?
1023  save();
1024  translate(x, y);
1025  rotate(positionAngle); //rotate the coordinate system
1026  color = pen().color().name();
1027  lambdaDrawLine(0., dy1, dx2, 0.);
1028  lambdaDrawLine(dx2, 0., 0., dy2);
1029  lambdaDrawLine(0., dy2, dx1, 0.);
1030  lambdaDrawLine(dx1, 0., 0., dy1);
1031  restore(); //reset coordinate system
1032  break;
1033  case SkyObject::GALAXY: //Galaxy
1034  case SkyObject::QUASAR: // Quasar
1035  color = pen().color().name();
1036  if (size < 1. && zoom > 20 * MINZOOM)
1037  size = 3.; //force ellipse above zoomFactor 20
1038  if (size < 1. && zoom > 5 * MINZOOM)
1039  size = 1.; //force points above zoomFactor 5
1040  if (size > 2.)
1041  {
1042  save();
1043  translate(x, y);
1044  rotate(positionAngle); //rotate the coordinate system
1045  lambdaDrawEllipse(dx1, dy1, size, e * size);
1046  restore(); //reset coordinate system
1047  }
1048  else if (size > 0.)
1049  {
1050  drawPoint(QPointF(x, y));
1051  }
1052  break;
1053  case SkyObject::GALAXY_CLUSTER: // Galaxy cluster - draw a dashed circle
1054  {
1055  tempBrush = brush();
1056  setBrush(QBrush());
1057  color = pen().color().name();
1058  save();
1059  translate(x, y);
1060  rotate(positionAngle); //rotate the coordinate system
1061  QPen newPen = pen();
1062  newPen.setStyle(Qt::DashLine);
1063  setPen(newPen);
1064  lambdaDrawEllipse(dx1, dy1, size, e * size);
1065  restore();
1066  setBrush(tempBrush);
1067  break;
1068  }
1069  default
1070 : // Unknown object or something we don't know how to draw. Just draw an ellipse with a ?-mark
1071  color = pen().color().name();
1072  if (size < 1. && zoom > 20 * MINZOOM)
1073  size = 3.; //force ellipse above zoomFactor 20
1074  if (size < 1. && zoom > 5 * MINZOOM)
1075  size = 1.; //force points above zoomFactor 5
1076  if (size > 2.)
1077  {
1078  save();
1079  QFont f = font();
1080  const QString qMark = " ? ";
1081 
1082 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
1083  double scaleFactor = 0.8 * size / fontMetrics().horizontalAdvance(qMark);
1084 #else
1085  double scaleFactor = 0.8 * size / fontMetrics().width(qMark);
1086 #endif
1087 
1088  f.setPointSizeF(f.pointSizeF() * scaleFactor);
1089  setFont(f);
1090  translate(x, y);
1091  rotate(positionAngle); //rotate the coordinate system
1092  lambdaDrawEllipse(dx1, dy1, size, e * size);
1093  if (Options::useAntialias())
1094  drawText(QRectF(dx1, dy1, size, e * size), Qt::AlignCenter, qMark);
1095  else
1096  {
1097  int idx1 = int(dx1);
1098  int idy1 = int(dy1);
1099  drawText(QRect(idx1, idy1, isize, int(e * size)), Qt::AlignCenter,
1100  qMark);
1101  }
1102  restore(); //reset coordinate system (and font?)
1103  }
1104  else if (size > 0.)
1105  {
1106  if (Options::useAntialias())
1107  drawPoint(QPointF(x, y));
1108  else
1109  drawPoint(QPoint(x, y));
1110  }
1111  }
1112 }
1113 
1115 {
1116  foreach (SkyObject *obj, obs)
1117  {
1118  bool visible = false;
1119  QPointF o = m_proj->toScreen(obj, true, &visible);
1120  if (!visible || !m_proj->onScreen(o))
1121  continue;
1122 
1123  float size = 20.;
1124  float x1 = o.x() - 0.5 * size;
1125  float y1 = o.y() - 0.5 * size;
1126  drawArc(QRectF(x1, y1, size, size), -60 * 16, 120 * 16);
1127  drawArc(QRectF(x1, y1, size, size), 120 * 16, 120 * 16);
1128  }
1129 }
1130 
1132 {
1133  KStarsData *data = KStarsData::Instance();
1134  std::shared_ptr<SkyPoint> point;
1135  QImage image;
1136  bool visible = false;
1137  QPointF pos;
1138 
1139  for (int i = 0; i < data->skyComposite()->flags()->size(); i++)
1140  {
1141  point = data->skyComposite()->flags()->pointList().at(i);
1142  image = data->skyComposite()->flags()->image(i);
1143 
1144  // Set Horizontal coordinates
1145  point->EquatorialToHorizontal(data->lst(), data->geo()->lat());
1146 
1147  // Get flag position on screen
1148  pos = m_proj->toScreen(point.get(), true, &visible);
1149 
1150  // Return if flag is not visible
1151  if (!visible || !m_proj->onScreen(pos))
1152  continue;
1153 
1154  // Draw flag image
1155  drawImage(pos.x() - 0.5 * image.width(), pos.y() - 0.5 * image.height(), image);
1156 
1157  // Draw flag label
1158  setPen(data->skyComposite()->flags()->labelColor(i));
1159  setFont(QFont("Helvetica", 10, QFont::Bold));
1160  drawText(pos.x() + 10, pos.y() - 10, data->skyComposite()->flags()->label(i));
1161  }
1162 }
1163 
1164 void SkyQPainter::drawHorizon(bool filled, SkyPoint *labelPoint, bool *drawLabel)
1165 {
1166  QVector<Eigen::Vector2f> ground = m_proj->groundPoly(labelPoint, drawLabel);
1167  if (ground.size())
1168  {
1169  QPolygonF groundPoly(ground.size());
1170  for (int i = 0; i < ground.size(); ++i)
1171  groundPoly[i] = KSUtils::vecToPoint(ground[i]);
1172  if (filled)
1173  drawPolygon(groundPoly);
1174  else
1175  {
1176  groundPoly.append(groundPoly.first());
1177  drawPolyline(groundPoly);
1178  }
1179  }
1180 }
1181 
1183 {
1184  if (!m_proj->checkVisibility(sat))
1185  return false;
1186 
1187  QPointF pos;
1188  bool visible = false;
1189 
1190  //sat->HorizontalToEquatorial( data->lst(), data->geo()->lat() );
1191 
1192  pos = m_proj->toScreen(sat, true, &visible);
1193 
1194  if (!visible || !m_proj->onScreen(pos))
1195  return false;
1196 
1197  if (Options::drawSatellitesLikeStars())
1198  {
1199  drawPointSource(pos, 3.5, 'B');
1200  }
1201  else
1202  {
1203  if (sat->isVisible())
1204  drawPixmap(QPoint(pos.x() - 15, pos.y() - 11), *visibleSatPixmap);
1205  else
1206  drawPixmap(QPoint(pos.x() - 15, pos.y() - 11), *invisibleSatPixmap);
1207 
1208  //drawPixmap(pos, *genericSatPixmap);
1209  /*drawLine( QPoint( pos.x() - 0.5, pos.y() - 0.5 ), QPoint( pos.x() + 0.5, pos.y() - 0.5 ) );
1210  drawLine( QPoint( pos.x() + 0.5, pos.y() - 0.5 ), QPoint( pos.x() + 0.5, pos.y() + 0.5 ) );
1211  drawLine( QPoint( pos.x() + 0.5, pos.y() + 0.5 ), QPoint( pos.x() - 0.5, pos.y() + 0.5 ) );
1212  drawLine( QPoint( pos.x() - 0.5, pos.y() + 0.5 ), QPoint( pos.x() - 0.5, pos.y() - 0.5 ) );*/
1213  }
1214 
1215  return true;
1216 
1217  //if ( Options::showSatellitesLabels() )
1218  //data->skyComposite()->satellites()->drawLabel( sat, pos );
1219 }
1220 
1222 {
1223  KStarsData *data = KStarsData::Instance();
1224  if (!m_proj->checkVisibility(sup))
1225  {
1226  return false;
1227  }
1228 
1229  bool visible = false;
1230  QPointF pos = m_proj->toScreen(sup, true, &visible);
1231  //qDebug()<<"sup->ra() = "<<(sup->ra()).toHMSString()<<"sup->dec() = "<<sup->dec().toDMSString();
1232  //qDebug()<<"pos = "<<pos<<"m_proj->onScreen(pos) = "<<m_proj->onScreen(pos);
1233  if (!visible || !m_proj->onScreen(pos))
1234  return false;
1235 
1236  setPen(data->colorScheme()->colorNamed("SupernovaColor"));
1237  //qDebug()<<"Here";
1238  drawLine(QPoint(pos.x() - 2.0, pos.y()), QPoint(pos.x() + 2.0, pos.y()));
1239  drawLine(QPoint(pos.x(), pos.y() - 2.0), QPoint(pos.x(), pos.y() + 2.0));
1240  return true;
1241 }
static void releaseImageCache()
Release the image cache.
Definition: skyqpainter.cpp:95
void setColorAt(qreal position, const QColor &color)
QPoint map(const QPoint &point) const const
AlignCenter
void begin() override
Begin painting.
bool isVisible()
Definition: satellite.cpp:1294
int width() const const
static constexpr double PI
PI is a const static member; it's public so that it can be used anywhere, as long as dms....
Definition: dms.h:385
void setPen(const QColor &color)
void getHsvF(qreal *h, qreal *s, qreal *v, qreal *a) const const
void drawConvexPolygon(const QPointF *points, int pointCount)
Format_ARGB32_Premultiplied
int height() const const
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
T & last()
float e() const
void rotate(qreal angle)
void drawEllipse(const QRectF &rectangle)
QTransform & rotate(qreal angle, Qt::Axis axis)
QImage image(int index)
Get image.
int width(const QString &text, int len) const const
void drawFlags() override
Draw flags.
double findPA(const SkyObject *o, float x, float y) const
Determine the on-screen position angle of a SkyObject.
Definition: projector.cpp:267
void clear()
const T value(const Key &key, const T &defaultValue) const const
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
static void initStarImages()
Recalculates the star pixmaps.
void drawSkyPolyline(LineList *list, SkipHashList *skipList=nullptr, LineListLabel *label=nullptr) override
Draw a polyline in the sky.
void drawSkyBackground() override
Draw the sky background.
bool drawPointSource(const SkyPoint *loc, float mag, char sp='A') override
Draw a point source (e.g., a star).
void setPen(const QPen &pen) override
Set the pen of the painter.
int horizontalAdvance(const QString &text, int len) const const
QString name() const const
A subclass of KSPlanetBase that implements asteroids.
Definition: ksasteroid.h:41
CachingDms * lst()
Definition: kstarsdata.h:224
A subclass of KSPlanetBase that implements comets.
Definition: kscomet.h:43
virtual QString name(void) const
Definition: skyobject.h:145
float starWidth(float mag) const
Get the width of a star of magnitude mag.
Definition: skypainter.cpp:30
void fill(const QColor &color)
int width() const const
bool drawSupernova(Supernova *sup) override
Draw a Supernova.
float mag() const
Definition: skyobject.h:206
bool intersects(const QPointF &center, int width, int height, double rotationDegrees=0.0) const
Check if the input rectangle overlaps the reference rectangle.
QPointF clipLine(SkyPoint *p1, SkyPoint *p2) const
ASSUMES *p1 did not clip but *p2 did.
Definition: projector.cpp:108
int width() const const
const QPen & pen() const const
bool drawPlanet(KSPlanetBase *planet) override
Draw a planet.
QColor labelColor(int index)
Get label color.
void drawSkyPolygon(LineList *list, bool forceClip=true) override
Draw a polygon in the sky.
T & first()
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 fillRect(const QRectF &rectangle, const QBrush &brush)
int arcmin() const
Definition: dms.cpp:180
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, Qt::ImageConversionFlags flags)
int height() const const
bool drawComet(KSComet *com) override
Draw a comet in the sky.
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
static KStars * Instance()
Definition: kstars.h:123
int type(void) const
Definition: skyobject.h:188
A class that manages the calculation of the earths shadow (in moon distance) as a 'virtual' skyobject...
Definition: ksearthshadow.h:27
bool begin(QPaintDevice *device)
float a() const
bool onScreen(const QPointF &p) const
Check whether the projected point is on-screen.
Definition: projector.cpp:98
QMap::iterator insert(const Key &key, const T &value)
bool drawEarthShadow(KSEarthShadow *shadow) override
Draw the earths shadow on the moon (red-ish)
T * data() const const
Provides necessary information about the Sun.
Definition: kssun.h:23
bool end()
KeepAspectRatio
QString i18n(const char *text, const TYPE &arg...)
bool drawTerrain(bool useCache=false) override
drawTerrain Draw the Terrain
const QImage & image() const
Definition: ksplanetbase.h:127
const CachingDms * lat() const
Definition: geolocation.h:70
int height() const const
void scale(qreal sx, qreal sy)
double getUmbraAngSize() const
Definition: ksearthshadow.h:92
QTransform & translate(qreal dx, qreal dy)
void drawObservingList(const QList< SkyObject * > &obs) override
Draw the symbols for the observing list.
const T & at(int i) const const
ColorScheme * colorScheme()
Definition: kstarsdata.h:172
GeoLocation * geo()
Definition: kstarsdata.h:230
bool isNull() const const
const T & at(int i) const const
bool drawImageOverlay(const QList< ImageOverlay > *imageOverlays, bool useCache=false) override
drawImageOverlay Draws a user-supplied image onto the skymap
QFontMetrics fontMetrics() const const
double pa() const override
This is just a container that holds information needed to do projections.
Definition: projector.h:36
void drawPolyline(const QPointF *points, int pointCount)
double findNorthPA(const SkyPoint *o, float x, float y) const
Determine the on-screen position angle of a SkyPont with recept with NCP.
Definition: projector.cpp:237
Draws things on the sky, without regard to backend.
Definition: skypainter.h:39
const QBrush & brush() const const
QColor fromRgb(QRgb rgb)
void setBrush(const QBrush &brush)
void point(int index, int *x, int *y) const const
const QImage & image()
double getPenumbraAngSize() const
SkyQPainter(QPaintDevice *pd, const QSize &canvasSize)
Creates a SkyQPainter with the given QPaintDevice and uses the dimensions of the paint device as canv...
SkyMapComposite * skyComposite()
Definition: kstarsdata.h:166
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
void setOpacity(qreal opacity)
double angSize() const
Definition: ksplanetbase.h:184
void drawSkyLine(SkyPoint *a, SkyPoint *b) override
Draw a line between points in the sky.
QPixmap scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
virtual QVector< Eigen::Vector2f > groundPoly(SkyPoint *labelpoint=nullptr, bool *drawLabel=nullptr) const
Get the ground polygon.
Definition: projector.cpp:305
int height() const const
void drawPoint(const QPointF &position)
bool drawConstellationArtImage(ConstellationsArt *obj) override
Draw a ConstellationsArt object.
qreal x() const const
qreal y() const const
QList< Key > keys() const const
void apparentCoord(long double jd0, long double jdf)
Computes the apparent coordinates for this SkyPoint for any epoch, accounting for the effects of prec...
Definition: skypoint.cpp:700
QString label(int index)
Get label.
Checks if two potentially rotated rectangles intersect.
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
bool drawAsteroid(KSAsteroid *ast) override
Draw an asteroid in the sky.
void end() override
End and finalize painting.
void drawLine(const QLineF &line)
QRect viewport() const const
const QFont & font() const const
QPoint toPoint() const const
QColor color() const const
void translate(const QPointF &offset)
bool drawSatellite(Satellite *sat) override
Draw a satellite.
void restore()
int size() const const
void save()
const Projector * projector() const
Get the current projector.
Definition: skymap.h:300
void setHsvF(qreal h, qreal s, qreal v, qreal a)
void setStyle(Qt::PenStyle style)
void setRenderHint(QPainter::RenderHint hint, bool on)
bool drawCatalogObject(const CatalogObject &obj) override
Draw a deep sky object (loaded from the new implementation)
DashLine
void setFont(const QFont &font)
void reset(T *other)
SmoothTransformation
dms getComaAngSize()
Definition: kscomet.h:109
Information about a ConstellationsArt object. This class represents a constellation image.
QColor colorNamed(const QString &name) const
Retrieve a color by name.
Definition: colorscheme.cpp:87
A simple container object to hold the minimum information for a Deep Sky Object to be drawn on the sk...
Definition: catalogobject.h:40
Information about an object in the sky.
Definition: skyobject.h:41
std::pair< bool, const QImage & > image() const
Get the image for this object.
bool drawHips(bool useCache=false) override
drawMosaicPanel Draws mosaic panel in planning or operation mode.
void drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
void setBrush(const QBrush &brush) override
Set the brush of the painter.
bool checkVisibility(const SkyPoint *p) const
Determine if the skypoint p is likely to be visible in the display window.
Definition: projector.cpp:183
int width() const const
Provides necessary information about objects in the solar system.
Definition: ksplanetbase.h:49
bool isEmpty() const const
int width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Dec 5 2023 03:58:32 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.