Kstars

skylabeler.cpp
1 /*
2  SPDX-FileCopyrightText: 2007 James B. Bowlin <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "skylabeler.h"
8 
9 #include <cstdio>
10 
11 #include <QPainter>
12 #include <QPixmap>
13 
14 #include "Options.h"
15 #include "kstarsdata.h" // MINZOOM
16 #include "skymap.h"
17 #include "projections/projector.h"
18 
19 //---------------------------------------------------------------------------//
20 // A Little data container class
21 //---------------------------------------------------------------------------//
22 
23 typedef struct LabelRun
24 {
25  LabelRun(int s, int e) : start(s), end(e) {}
26  int start;
27  int end;
28 
29 } LabelRun;
30 
31 //----- Now for the main event ----------------------------------------------//
32 
33 //----- Static Methods ------------------------------------------------------//
34 
35 SkyLabeler *SkyLabeler::pinstance = nullptr;
36 
37 SkyLabeler *SkyLabeler::Instance()
38 {
39  if (!pinstance)
40  pinstance = new SkyLabeler();
41  return pinstance;
42 }
43 
45 {
46 #ifndef KSTARS_LITE
47  QFont font(m_p.font());
48 #else
49  QFont font(m_stdFont);
50 #endif
51  int deltaSize = 0;
52  if (Options::zoomFactor() < 2.0 * MINZOOM)
53  deltaSize = 2;
54  else if (Options::zoomFactor() < 10.0 * MINZOOM)
55  deltaSize = 1;
56 
57 #ifndef KSTARS_LITE
58  if (deltaSize)
59  {
60  font.setPointSize(font.pointSize() - deltaSize);
61  m_p.setFont(font);
62  }
63 #else
64  if (deltaSize)
65  {
66  font.setPointSize(font.pointSize() - deltaSize);
67  }
68  if (m_drawFont.pointSize() != font.pointSize())
69  {
70  m_drawFont = font;
71  }
72 #endif
73 }
74 
76 {
77  double offset = dms::PI * Options::zoomFactor() / 10800.0 / 3600.0;
78  return 4.0 + offset * 0.5;
79 }
80 
81 //----- Constructor ---------------------------------------------------------//
82 
83 SkyLabeler::SkyLabeler()
84  : m_fontMetrics(QFont()), m_picture(-1), labelList(NUM_LABEL_TYPES)
85 {
86 #ifdef KSTARS_LITE
87  //Painter is needed to get default font and we use it only once to have only one warning
88  m_stdFont = QFont();
89 
90 //For some reason there is no point size in default font on Android
91 #ifdef ANDROID
92  m_stdFont.setPointSize(16);
93 #else
94  m_stdFont.setPointSize(m_stdFont.pointSize()+2);
95 #endif
96 
97 #endif
98 }
99 
100 SkyLabeler::~SkyLabeler()
101 {
102  for (auto &row : screenRows)
103  {
104  for (auto &item : *row)
105  {
106  delete item;
107  }
108  delete row;
109  }
110 }
111 
112 bool SkyLabeler::drawGuideLabel(QPointF &o, const QString &text, double angle)
113 {
114  // Create bounding rectangle by rotating the (height x width) rectangle
115  qreal h = m_fontMetrics.height();
116  qreal w = m_fontMetrics.width(text);
117  qreal s = sin(angle * dms::PI / 180.0);
118  qreal c = cos(angle * dms::PI / 180.0);
119 
120  qreal w2 = w / 2.0;
121 
122  qreal top, bot, left, right;
123 
124  // These numbers really do depend on the sign of the angle like this
125  if (angle >= 0.0)
126  {
127  top = o.y() - s * w2;
128  bot = o.y() + c * h + s * w2;
129  left = o.x() - c * w2 - s * h;
130  right = o.x() + c * w2;
131  }
132  else
133  {
134  top = o.y() + s * w2;
135  bot = o.y() + c * h - s * w2;
136  left = o.x() - c * w2;
137  right = o.x() + c * w2 - s * h;
138  }
139 
140  // return false if label would overlap existing label
141  if (!markRegion(left, right, top, bot))
142  return false;
143 
144  // for debugging the bounding rectangle:
145  //psky.drawLine( QPointF( left, top ), QPointF( right, top ) );
146  //psky.drawLine( QPointF( right, top ), QPointF( right, bot ) );
147  //psky.drawLine( QPointF( right, bot ), QPointF( left, bot ) );
148  //psky.drawLine( QPointF( left, bot ), QPointF( left, top ) );
149 
150  // otherwise draw the label and return true
151  m_p.save();
152  m_p.translate(o);
153 
154  m_p.rotate(angle); //rotate the coordinate system
155  m_p.drawText(QPointF(-w2, h), text);
156  m_p.restore(); //reset coordinate system
157 
158  return true;
159 }
160 
162  const qreal padding_factor)
163 {
164  QString sLabel = obj->labelString();
165  if (sLabel.isEmpty())
166  return false;
167 
168  double offset = obj->labelOffset();
169  QPointF p(_p.x() + offset, _p.y() + offset);
170 
171  if (!markText(p, sLabel, padding_factor))
172  {
173  return false;
174  }
175  else
176  {
177  double factor = log(Options::zoomFactor() / 750.0);
178  double newPointSize = qBound(12.0, factor * m_stdFont.pointSizeF(), 18.0) * (1.0 + 0.7 * Options::labelFontScaling()/100.0);
179  QFont zoomFont(m_p.font());
180  zoomFont.setPointSizeF(newPointSize);
181  m_p.setFont(zoomFont);
182  m_p.drawText(p, sLabel);
183  return true;
184  }
185 }
186 
187 void SkyLabeler::setFont(const QFont &font)
188 {
189 #ifndef KSTARS_LITE
190  m_p.setFont(font);
191 #else
192  m_drawFont = font;
193 #endif
194  m_fontMetrics = QFontMetrics(font);
195 }
196 
197 void SkyLabeler::setPen(const QPen &pen)
198 {
199 #ifdef KSTARS_LITE
200  Q_UNUSED(pen);
201 #else
202  m_p.setPen(pen);
203 #endif
204 }
205 
206 void SkyLabeler::shrinkFont(int delta)
207 {
208 #ifndef KSTARS_LITE
209  QFont font(m_p.font());
210 #else
211  QFont font(m_drawFont);
212 #endif
213  font.setPointSize(font.pointSize() - delta);
214  setFont(font);
215 }
216 
218 {
219  setFont(m_stdFont);
220 }
221 
223 {
224  setFont(m_skyFont);
225 }
226 
227 void SkyLabeler::getMargins(const QString &text, float *left, float *right, float *top, float *bot)
228 {
229  float height = m_fontMetrics.height();
230  float width = m_fontMetrics.width(text);
231  float sideMargin = m_fontMetrics.width("MM") + width / 2.0;
232 
233  // Create the margins within which it is okay to draw the label
234  double winHeight;
235  double winWidth;
236 #ifdef KSTARS_LITE
237  winHeight = SkyMapLite::Instance()->height();
238  winWidth = SkyMapLite::Instance()->width();
239 #else
240  winHeight = m_p.window().height();
241  winWidth = m_p.window().width();
242 #endif
243 
244  *right = winWidth - sideMargin;
245  *left = sideMargin;
246  *top = height;
247  *bot = winHeight - 2.0 * height;
248 }
249 
251 {
252  // ----- Set up Projector ---
253  m_proj = skyMap->projector();
254  // ----- Set up Painter -----
255  if (m_p.isActive())
256  m_p.end();
257  m_picture = QPicture();
258  m_p.begin(&m_picture);
259  //This works around BUG 10496 in Qt
260  m_p.drawPoint(0, 0);
261  m_p.drawPoint(skyMap->width() + 1, skyMap->height() + 1);
262  // ----- Set up Zoom Dependent Font -----
263 
264  m_stdFont = QFont(m_p.font());
265  setZoomFont();
266  m_skyFont = m_p.font();
267  m_fontMetrics = QFontMetrics(m_skyFont);
268  m_minDeltaX = (int)m_fontMetrics.width("MMMMM");
269 
270  // ----- Set up Zoom Dependent Offset -----
271  m_offset = SkyLabeler::ZoomOffset();
272 
273  // ----- Prepare Virtual Screen -----
274  m_yScale = (m_fontMetrics.height() + 1.0);
275 
276  int maxY = int(skyMap->height() / m_yScale);
277  if (maxY < 1)
278  maxY = 1; // prevents a crash below?
279 
280  int m_maxX = skyMap->width();
281  m_size = (maxY + 1) * m_maxX;
282 
283  // Resize if needed:
284  if (maxY > m_maxY)
285  {
286  screenRows.resize(m_maxY);
287  for (int y = m_maxY; y <= maxY; y++)
288  {
289  screenRows.append(new LabelRow());
290  }
291  //printf("resize: %d -> %d, size:%d\n", m_maxY, maxY, screenRows.size());
292  }
293 
294  // Clear all pre-existing rows as needed
295 
296  int minMaxY = (maxY < m_maxY) ? maxY : m_maxY;
297 
298  for (int y = 0; y <= minMaxY; y++)
299  {
300  LabelRow *row = screenRows[y];
301 
302  for (auto &item : *row)
303  {
304  delete item;
305  }
306  row->clear();
307  }
308 
309  // never decrease m_maxY:
310  if (m_maxY < maxY)
311  m_maxY = maxY;
312 
313  // reset the counters
314  m_marks = m_hits = m_misses = m_elements = 0;
315 
316  //----- Clear out labelList -----
317  for (auto &item : labelList)
318  {
319  item.clear();
320  }
321 }
322 
323 #ifdef KSTARS_LITE
324 void SkyLabeler::reset()
325 {
326  SkyMapLite *skyMap = SkyMapLite::Instance();
327  // ----- Set up Projector ---
328  m_proj = skyMap->projector();
329 
330  //m_stdFont was moved to constructor
331  setZoomFont();
332  m_skyFont = m_drawFont;
333  m_fontMetrics = QFontMetrics(m_skyFont);
334  m_minDeltaX = (int)m_fontMetrics.width("MMMMM");
335  // ----- Set up Zoom Dependent Offset -----
336  m_offset = ZoomOffset();
337 
338  // ----- Prepare Virtual Screen -----
339  m_yScale = (m_fontMetrics.height() + 1.0);
340 
341  int maxY = int(skyMap->height() / m_yScale);
342  if (maxY < 1)
343  maxY = 1; // prevents a crash below?
344 
345  int m_maxX = skyMap->width();
346  m_size = (maxY + 1) * m_maxX;
347 
348  // Resize if needed:
349  if (maxY > m_maxY)
350  {
351  screenRows.resize(m_maxY);
352  for (int y = m_maxY; y <= maxY; y++)
353  {
354  screenRows.append(new LabelRow());
355  }
356  //printf("resize: %d -> %d, size:%d\n", m_maxY, maxY, screenRows.size());
357  }
358 
359  // Clear all pre-existing rows as needed
360 
361  int minMaxY = (maxY < m_maxY) ? maxY : m_maxY;
362 
363  for (int y = 0; y <= minMaxY; y++)
364  {
365  LabelRow *row = screenRows[y];
366  for (int i = 0; i < row->size(); i++)
367  {
368  delete row->at(i);
369  }
370  row->clear();
371  }
372 
373  // never decrease m_maxY:
374  if (m_maxY < maxY)
375  m_maxY = maxY;
376 
377  // reset the counters
378  m_marks = m_hits = m_misses = m_elements = 0;
379 
380  //----- Clear out labelList -----
381  for (int i = 0; i < labelList.size(); i++)
382  {
383  labelList[i].clear();
384  }
385 }
386 #endif
387 
389 {
390  //FIXME: need a better soln. Apparently starting a painter
391  //clears the picture.
392  // But it's not like that's something that should be in the docs, right?
393  // No, that's definitely better to leave to people to figure out on their own.
394  if (m_p.isActive())
395  {
396  m_p.end();
397  }
398  m_picture.play(&p); //can't replay while it's being painted on
399  //this is also undocumented btw.
400  //m_p.begin(&m_picture);
401 }
402 
403 // We use Run Length Encoding to hold the information instead of an array of
404 // chars. This is both faster and smaller but the code is more complicated.
405 //
406 // This code is easy to break and hard to fix.
407 
408 bool SkyLabeler::markText(const QPointF &p, const QString &text, qreal padding_factor)
409 {
410  static const auto ramp_zoom = log10(MAXZOOM) + log10(0.3);
411 
412  if (padding_factor != 1)
413  {
414  padding_factor =
415  (1 - ((std::min(log10(Options::zoomFactor()), ramp_zoom)) / ramp_zoom)) *
416  padding_factor +
417  1;
418  }
419 
420  const qreal maxX = p.x() + m_fontMetrics.width(text) * padding_factor;
421  const qreal minY = p.y() - m_fontMetrics.height() * padding_factor;
422  return markRegion(p.x(), maxX, p.y(), minY);
423 }
424 
425 bool SkyLabeler::markRegion(qreal left, qreal right, qreal top, qreal bot)
426 {
427  if (m_maxY < 1)
428  {
429  if (!m_errors++)
430  qDebug() << Q_FUNC_INFO << QString("Someone forgot to reset the SkyLabeler!");
431  return true;
432  }
433 
434  // setup x coordinates of rectangular region
435  int minX = int(left);
436  int maxX = int(right);
437  if (maxX < minX)
438  {
439  maxX = minX;
440  minX = int(right);
441  }
442 
443  // setup y coordinates
444  int maxY = int(bot / m_yScale);
445  int minY = int(top / m_yScale);
446 
447  if (maxY < 0)
448  maxY = 0;
449  if (maxY > m_maxY)
450  maxY = m_maxY;
451  if (minY < 0)
452  minY = 0;
453  if (minY > m_maxY)
454  minY = m_maxY;
455 
456  if (maxY < minY)
457  {
458  int temp = maxY;
459  maxY = minY;
460  minY = temp;
461  }
462 
463  // check to see if we overlap any existing label
464  // We must check all rows before we start marking
465  for (int y = minY; y <= maxY; y++)
466  {
467  LabelRow *row = screenRows[y];
468  int i;
469  for (i = 0; i < row->size(); i++)
470  {
471  if (row->at(i)->end < minX)
472  continue; // skip past these
473  if (row->at(i)->start > maxX)
474  break;
475  m_misses++;
476  return false;
477  }
478  }
479 
480  m_hits++;
481  m_marks += (maxX - minX + 1) * (maxY - minY + 1);
482 
483  // Okay, there was no overlap so let's insert the current rectangle into
484  // screenRows.
485 
486  for (int y = minY; y <= maxY; y++)
487  {
488  LabelRow *row = screenRows[y];
489 
490  // Simplest case: an empty row
491  if (row->size() < 1)
492  {
493  row->append(new LabelRun(minX, maxX));
494  m_elements++;
495  continue;
496  }
497 
498  // Find out our place in the universe (or row).
499  // H'mm. Maybe we could cache these numbers above.
500  int i;
501  for (i = 0; i < row->size(); i++)
502  {
503  if (row->at(i)->end >= minX)
504  break;
505  }
506 
507  // i now points to first label PAST ours
508 
509  // if we are first, append or merge at start of list
510  if (i == 0)
511  {
512  if (row->at(0)->start - maxX < m_minDeltaX)
513  {
514  row->at(0)->start = minX;
515  }
516  else
517  {
518  row->insert(0, new LabelRun(minX, maxX));
519  m_elements++;
520  }
521  continue;
522  }
523 
524  // if we are past the last label, merge or append at end
525  else if (i == row->size())
526  {
527  if (minX - row->at(i - 1)->end < m_minDeltaX)
528  {
529  row->at(i - 1)->end = maxX;
530  }
531  else
532  {
533  row->append(new LabelRun(minX, maxX));
534  m_elements++;
535  }
536  continue;
537  }
538 
539  // if we got here, we must insert or merge the new label
540  // between [i-1] and [i]
541 
542  bool mergeHead = (minX - row->at(i - 1)->end < m_minDeltaX);
543  bool mergeTail = (row->at(i)->start - maxX < m_minDeltaX);
544 
545  // double merge => combine all 3 into one
546  if (mergeHead && mergeTail)
547  {
548  row->at(i - 1)->end = row->at(i)->end;
549  delete row->at(i);
550  row->removeAt(i);
551  m_elements--;
552  }
553 
554  // Merge label with [i-1]
555  else if (mergeHead)
556  {
557  row->at(i - 1)->end = maxX;
558  }
559 
560  // Merge label with [i]
561  else if (mergeTail)
562  {
563  row->at(i)->start = minX;
564  }
565 
566  // insert between the two
567  else
568  {
569  row->insert(i, new LabelRun(minX, maxX));
570  m_elements++;
571  }
572  }
573 
574  return true;
575 }
576 
578 {
579  bool visible = false;
580  QPointF p = m_proj->toScreen(obj, true, &visible);
581  if (!visible || !m_proj->onScreen(p) || obj->translatedName().isEmpty())
582  return;
583  labelList[(int)type].append(SkyLabel(p, obj));
584 }
585 
586 #ifdef KSTARS_LITE
587 void SkyLabeler::addLabel(SkyObject *obj, QPointF pos, label_t type)
588 {
589  labelList[(int)type].append(SkyLabel(pos, obj));
590 }
591 #endif
592 
594 {
595  KStarsData *data = KStarsData::Instance();
596 
597  resetFont();
598  m_p.setPen(QColor(data->colorScheme()->colorNamed("PNameColor")));
599  drawQueuedLabelsType(PLANET_LABEL);
600 
601  if (labelList[SATURN_MOON_LABEL].size() > 0)
602  {
603  shrinkFont(2);
604  drawQueuedLabelsType(SATURN_MOON_LABEL);
605  resetFont();
606  }
607 
608  if (labelList[JUPITER_MOON_LABEL].size() > 0)
609  {
610  shrinkFont(2);
611  drawQueuedLabelsType(JUPITER_MOON_LABEL);
612  resetFont();
613  }
614 
615  // No colors for these fellas? Just following planets along?
616  drawQueuedLabelsType(ASTEROID_LABEL);
617  drawQueuedLabelsType(COMET_LABEL);
618 
619  m_p.setPen(QColor(data->colorScheme()->colorNamed("SatLabelColor")));
620  drawQueuedLabelsType(SATELLITE_LABEL);
621 
622  // Whelp we're here and we don't have a Rude Label color?
623  // Will just set it to Planet color since this is how it used to be!!
624  m_p.setPen(QColor(data->colorScheme()->colorNamed("PNameColor")));
625  LabelList list = labelList[RUDE_LABEL];
626 
627  for (const auto &item : list)
628  {
629  drawRudeNameLabel(item.obj, item.o);
630  }
631 }
632 
634 {
635  LabelList list = labelList[type];
636 
637  for (const auto &item : list)
638  {
639  drawNameLabel(item.obj, item.o);
640  }
641 }
642 
643 //Rude name labels don't check for collisions with other labels,
644 //these get drawn no matter what. Transient labels are rude labels.
645 //To mitigate confusion from possibly "underlapping" labels, paint a
646 //semi-transparent background.
648 {
649  QString sLabel = obj->labelString();
650  double offset = obj->labelOffset();
651  QRectF rect = m_p.fontMetrics().boundingRect(sLabel);
652  rect.moveTo(p.x() + offset, p.y() + offset);
653 
654  //Interestingly, the fontMetric boundingRect isn't where you might think...
655  //We need to tweak rect to get the BG rectangle rect2
656  QRectF rect2 = rect;
657  rect2.moveTop(rect.top() - 0.6 * rect.height());
658  rect2.setHeight(0.8 * rect.height());
659 
660  //FIXME: Implement label background options
661  QColor color(KStarsData::Instance()->colorScheme()->colorNamed("SkyColor"));
662  color.setAlpha(m_p.pen().color().alpha()); //same transparency for the text and the background
663  m_p.fillRect(rect2, QBrush(color));
664  m_p.drawText(rect.topLeft(), sLabel);
665 }
666 
667 //----- Diagnostic and information routines -----
668 
670 {
671  if (m_size == 0)
672  return 0.0;
673  return 100.0 * float(m_marks) / float(m_size);
674 }
675 
677 {
678  if (m_hits == 0)
679  return 0.0;
680  return 100.0 * float(m_hits) / (float(m_hits + m_misses));
681 }
682 
684 {
685  printf("SkyLabeler:\n");
686  printf(" fillRatio=%.1f%%\n", fillRatio());
687  printf(" hits=%d misses=%d ratio=%.1f%%\n", m_hits, m_misses, hitRatio());
688  printf(" yScale=%.1f maxY=%d\n", m_yScale, m_maxY);
689 
690  printf(" screenRows=%d elements=%d virtualSize=%.1f Kbytes\n", screenRows.size(), m_elements,
691  float(m_size) / 1024.0);
692 
693 // static const char *labelName[NUM_LABEL_TYPES];
694 //
695 // labelName[STAR_LABEL] = "Star";
696 // labelName[ASTEROID_LABEL] = "Asteroid";
697 // labelName[COMET_LABEL] = "Comet";
698 // labelName[PLANET_LABEL] = "Planet";
699 // labelName[JUPITER_MOON_LABEL] = "Jupiter Moon";
700 // labelName[SATURN_MOON_LABEL] = "Saturn Moon";
701 // labelName[DEEP_SKY_LABEL] = "Deep Sky Object";
702 // labelName[CONSTEL_NAME_LABEL] = "Constellation Name";
703 //
704 // for (int i = 0; i < NUM_LABEL_TYPES; i++)
705 // {
706 // printf(" %20ss: %d\n", labelName[i], labelList[i].size());
707 // }
708 //
709 // // Check for errors in the data structure
710 // for (int y = 0; y <= m_maxY; y++)
711 // {
712 // LabelRow *row = screenRows[y];
713 // int size = row->size();
714 // if (size < 2)
715 // continue;
716 //
717 // bool error = false;
718 // for (int i = 1; i < size; i++)
719 // {
720 // if (row->at(i - 1)->end > row->at(i)->start)
721 // error = true;
722 // }
723 // if (!error)
724 // continue;
725 //
726 // printf("ERROR: %3d: ", y);
727 // for (int i = 0; i < row->size(); i++)
728 // {
729 // printf("(%d, %d) ", row->at(i)->start, row->at(i)->end);
730 // }
731 // printf("\n");
732 // }
733 }
void append(const T &value)
void drawRudeNameLabel(SkyObject *obj, const QPointF &_p)
draw the object's name label on the map, without checking for overlap with other labels.
Definition: skylabeler.cpp:647
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 rotate(qreal angle)
void moveTo(qreal x, qreal y)
void setPointSize(int pointSize)
int pointSize() const const
void resetFont()
sets the font in SkyLabeler and in psky back to the zoom dependent value that was set in reset().
Definition: skylabeler.cpp:222
int width() const const
QString translatedName() const
Definition: skyobject.h:148
QRect boundingRect(QChar ch) const const
qreal width(const QString &text) const const
void setZoomFont()
adjusts the font in psky to be smaller if we are zoomed out.
Definition: skylabeler.cpp:44
void setPen(const QPen &pen)
sets the pen used for drawing labels on the sky.
Definition: skylabeler.cpp:197
const QPen & pen() const const
void shrinkFont(int delta)
decreases the size of the font in psky and in the SkyLabeler by the delta points.
Definition: skylabeler.cpp:206
void drawText(const QPointF &position, const QString &text)
void fillRect(const QRectF &rectangle, const QBrush &brush)
void removeAt(int i)
bool begin(QPaintDevice *device)
bool onScreen(const QPointF &p) const
Check whether the projected point is on-screen.
Definition: projector.cpp:98
int size() const const
bool end()
void addLabel(SkyObject *obj, label_t type)
queues the label in the "type" buffer for later drawing.
Definition: skylabeler.cpp:577
const Projector * projector() const
Get the current projector.
Definition: skymaplite.h:323
void draw(QPainter &p)
KStars Lite version of the function above.
Definition: skylabeler.cpp:388
QPointF topLeft() const const
bool drawGuideLabel(QPointF &o, const QString &text, double angle)
Tries to draw the text at the position and angle specified.
Definition: skylabeler.cpp:112
ColorScheme * colorScheme()
Definition: kstarsdata.h:171
bool isEmpty() const const
bool play(QPainter *painter)
bool isActive() const const
virtual double labelOffset() const
Definition: skyobject.cpp:454
const T & at(int i) const const
void setAlpha(int alpha)
int alpha() const const
QFontMetrics fontMetrics() const const
void getMargins(const QString &text, float *left, float *right, float *top, float *bot)
sets four margins for help in keeping labels entirely on the screen.
Definition: skylabeler.cpp:227
bool markText(const QPointF &p, const QString &text, qreal padding_factor=1)
tells the labeler the location and text of a label you want to draw.
Definition: skylabeler.cpp:408
void setFont(const QFont &font)
tells the labeler the font you will be using so it can figure out the height and width of the labels.
Definition: skylabeler.cpp:187
void insert(int i, const T &value)
virtual QString labelString() const
Definition: skyobject.cpp:449
qreal top() const const
bool markRegion(qreal left, qreal right, qreal top, qreal bot)
Works just like markText() above but for an arbitrary rectangular region bounded by top,...
Definition: skylabeler.cpp:425
Item for displaying sky objects; also handles user interaction events.
Definition: skymaplite.h:58
void printInfo()
diagnostic, prints some brief statistics to the console.
Definition: skylabeler.cpp:683
int height() const const
QRect window() const const
void drawPoint(const QPointF &position)
float fillRatio()
diagnostic.
Definition: skylabeler.cpp:669
qreal x() const const
qreal y() const const
static double ZoomOffset()
returns the zoom dependent label offset.
Definition: skylabeler.cpp:75
bool drawNameLabel(SkyObject *obj, const QPointF &_p, const qreal padding_factor=1)
Tries to draw a label for an object.
Definition: skylabeler.cpp:161
Canvas widget for displaying the sky bitmap; also handles user interaction events.
Definition: skymap.h:53
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
const QFont & font() const const
QColor color() const const
void translate(const QPointF &offset)
void clear()
void restore()
float hitRatio()
diagnostic, the number of times mark() returned true divided by the total number of times mark was ca...
Definition: skylabeler.cpp:676
void save()
void moveTop(qreal y)
void useStdFont()
sets the font in SkyLabeler and in psky to the font psky had originally when reset() was called.
Definition: skylabeler.cpp:217
qreal height() const const
void setPointSizeF(qreal pointSize)
const Projector * projector() const
Get the current projector.
Definition: skymap.h:300
qreal pointSizeF() const const
void drawQueuedLabelsType(SkyLabeler::label_t type)
a convenience routine that draws all the labels from a single buffer.
Definition: skylabeler.cpp:633
void setFont(const QFont &font)
void setHeight(qreal height)
QColor colorNamed(const QString &name) const
Retrieve a color by name.
Definition: colorscheme.cpp:87
Information about an object in the sky.
Definition: skyobject.h:41
const QList< QKeySequence > & end()
void drawQueuedLabels()
draws the labels stored in all the buffers.
Definition: skylabeler.cpp:593
void reset(SkyMap *skyMap)
clears the virtual screen (if needed) and resizes the virtual screen (if needed) to match skyMap.
Definition: skylabeler.cpp:250
qreal height() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Jun 4 2023 03:57:17 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.