15#include "kstarsdata.h"
17#include "projections/projector.h"
23typedef struct LabelRun
25 LabelRun(
int s,
int e) : start(s), end(e) {}
40 pinstance =
new SkyLabeler();
47 QFont font(m_p.font());
49 QFont font(m_stdFont);
52 if (Options::zoomFactor() < 2.0 * MINZOOM)
54 else if (Options::zoomFactor() < 10.0 * MINZOOM)
68 if (m_drawFont.pointSize() != font.
pointSize())
77 double offset =
dms::PI * Options::zoomFactor() / 10800.0 / 3600.0;
78 return 4.0 + offset * 0.5;
83SkyLabeler::SkyLabeler()
84 : m_fontMetrics(
QFont()), m_picture(-1), labelList(NUM_LABEL_TYPES)
100SkyLabeler::~SkyLabeler()
102 for (
auto &row : screenRows)
104 for (
auto &item : *row)
115 qreal h = m_fontMetrics.height();
116 qreal w = m_fontMetrics.averageCharWidth() * text.
size();
117 qreal s = sin(angle *
dms::PI / 180.0);
118 qreal c = cos(angle *
dms::PI / 180.0);
122 qreal top, bot, left, right;
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;
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;
155 m_p.drawText(
QPointF(-w2, h), text);
162 const qreal padding_factor)
169 QPointF p(_p.
x() + offset, _p.
y() + offset);
171 if (!
markText(p, sLabel, padding_factor))
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());
181 m_p.setFont(zoomFont);
182 m_p.drawText(p, sLabel);
209 QFont font(m_p.font());
211 QFont font(m_drawFont);
229 float height = m_fontMetrics.height();
230 float width = m_fontMetrics.averageCharWidth() * text.
size();
231 float sideMargin = m_fontMetrics.averageCharWidth() * 2 + width / 2.0;
237 winHeight = SkyMapLite::Instance()->height();
238 winWidth = SkyMapLite::Instance()->width();
240 winHeight = m_p.window().height();
241 winWidth = m_p.window().width();
244 *right = winWidth - sideMargin;
247 *bot = winHeight - 2.0 * height;
258 m_p.begin(&m_picture);
261 m_p.drawPoint(skyMap->
width() + 1, skyMap->
height() + 1);
264 m_stdFont =
QFont(m_p.font());
266 m_skyFont = m_p.font();
268 m_minDeltaX = (int) m_fontMetrics.averageCharWidth() * 5;
274 m_yScale = (m_fontMetrics.height() + 1.0);
276 int maxY = int(skyMap->
height() / m_yScale);
280 int m_maxX = skyMap->
width();
281 m_size = (maxY + 1) * m_maxX;
286 screenRows.resize(m_maxY);
287 for (
int y = m_maxY; y <= maxY; y++)
289 screenRows.append(
new LabelRow());
296 int minMaxY = (maxY < m_maxY) ? maxY : m_maxY;
298 for (
int y = 0; y <= minMaxY; y++)
300 LabelRow *row = screenRows[y];
302 for (
auto &item : *row)
314 m_marks = m_hits = m_misses = m_elements = 0;
317 for (
auto &item : labelList)
332 m_skyFont = m_drawFont;
334 m_minDeltaX = (int)m_fontMetrics.width(
"MMMMM");
339 m_yScale = (m_fontMetrics.
height() + 1.0);
341 int maxY = int(skyMap->
height() / m_yScale);
345 int m_maxX = skyMap->
width();
346 m_size = (maxY + 1) * m_maxX;
351 screenRows.resize(m_maxY);
352 for (
int y = m_maxY; y <= maxY; y++)
354 screenRows.append(
new LabelRow());
361 int minMaxY = (maxY < m_maxY) ? maxY : m_maxY;
363 for (
int y = 0; y <= minMaxY; y++)
365 LabelRow *row = screenRows[y];
366 for (
int i = 0; i < row->
size(); i++)
378 m_marks = m_hits = m_misses = m_elements = 0;
381 for (
int i = 0; i < labelList.size(); i++)
383 labelList[i].clear();
410 static const auto ramp_zoom = log10(MAXZOOM) + log10(0.3);
412 if (padding_factor != 1)
415 (1 - ((std::min(log10(Options::zoomFactor()), ramp_zoom)) / ramp_zoom)) *
420 const qreal maxX = p.
x() + m_fontMetrics.averageCharWidth() * text.
size() * padding_factor;
421 const qreal minY = p.
y() - m_fontMetrics.height() * padding_factor;
430 qDebug() << Q_FUNC_INFO <<
QString(
"Someone forgot to reset the SkyLabeler!");
435 int minX = int(left);
436 int maxX = int(right);
444 int maxY = int(bot / m_yScale);
445 int minY = int(top / m_yScale);
465 for (
int y = minY; y <= maxY; y++)
467 LabelRow *row = screenRows[y];
469 for (i = 0; i < row->
size(); i++)
471 if (row->
at(i)->end < minX)
473 if (row->
at(i)->start > maxX)
481 m_marks += (maxX - minX + 1) * (maxY - minY + 1);
486 for (
int y = minY; y <= maxY; y++)
488 LabelRow *row = screenRows[y];
493 row->
append(
new LabelRun(minX, maxX));
501 for (i = 0; i < row->
size(); i++)
503 if (row->
at(i)->end >= minX)
512 if (row->
at(0)->start - maxX < m_minDeltaX)
514 row->
at(0)->start = minX;
518 row->
insert(0,
new LabelRun(minX, maxX));
525 else if (i == row->
size())
527 if (minX - row->
at(i - 1)->end < m_minDeltaX)
529 row->
at(i - 1)->end = maxX;
533 row->
append(
new LabelRun(minX, maxX));
542 bool mergeHead = (minX - row->
at(i - 1)->end < m_minDeltaX);
543 bool mergeTail = (row->
at(i)->start - maxX < m_minDeltaX);
546 if (mergeHead && mergeTail)
548 row->
at(i - 1)->end = row->
at(i)->end;
557 row->
at(i - 1)->end = maxX;
563 row->
at(i)->start = minX;
569 row->
insert(i,
new LabelRun(minX, maxX));
579 bool visible =
false;
580 QPointF p = m_proj->toScreen(obj,
true, &visible);
583 labelList[(int)type].append(SkyLabel(p, obj));
589 labelList[(int)type].append(SkyLabel(pos, obj));
601 if (labelList[SATURN_MOON_LABEL].size() > 0)
608 if (labelList[JUPITER_MOON_LABEL].size() > 0)
625 LabelList list = labelList[RUDE_LABEL];
627 for (
const auto &item : list)
635 LabelList list = labelList[type];
637 for (
const auto &item : list)
651 QRectF rect = m_p.fontMetrics().boundingRect(sLabel);
652 rect.
moveTo(p.
x() + offset, p.
y() + offset);
661 QColor color(KStarsData::Instance()->colorScheme()->colorNamed(
"SkyColor"));
662 color.
setAlpha(m_p.pen().color().alpha());
663 m_p.fillRect(rect2,
QBrush(color));
664 m_p.drawText(rect.
topLeft(), sLabel);
673 return 100.0 * float(m_marks) / float(m_size);
680 return 100.0 * float(m_hits) / (float(m_hits + m_misses));
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);
690 printf(
" screenRows=%d elements=%d virtualSize=%.1f Kbytes\n", screenRows.size(), m_elements,
691 float(m_size) / 1024.0);
QColor colorNamed(const QString &name) const
Retrieve a color by name.
KStarsData is the backbone of KStars.
ColorScheme * colorScheme()
The purpose of this class is to prevent labels from overlapping.
float fillRatio()
diagnostic.
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.
void resetFont()
sets the font in SkyLabeler and in psky back to the zoom dependent value that was set in reset().
void shrinkFont(int delta)
decreases the size of the font in psky and in the SkyLabeler by the delta points.
void setZoomFont()
adjusts the font in psky to be smaller if we are zoomed out.
bool markRegion(qreal left, qreal right, qreal top, qreal bot)
Works just like markText() above but for an arbitrary rectangular region bounded by top,...
void drawQueuedLabels()
draws the labels stored in all the buffers.
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.
void reset(SkyMap *skyMap)
clears the virtual screen (if needed) and resizes the virtual screen (if needed) to match skyMap.
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.
bool drawGuideLabel(QPointF &o, const QString &text, double angle)
Tries to draw the text at the position and angle specified.
void addLabel(SkyObject *obj, label_t type)
queues the label in the "type" buffer for later drawing.
void setPen(const QPen &pen)
sets the pen used for drawing labels on the sky.
static double ZoomOffset()
returns the zoom dependent label offset.
float hitRatio()
diagnostic, the number of times mark() returned true divided by the total number of times mark was ca...
void useStdFont()
sets the font in SkyLabeler and in psky to the font psky had originally when reset() was called.
void printInfo()
diagnostic, prints some brief statistics to the console.
void drawQueuedLabelsType(SkyLabeler::label_t type)
a convenience routine that draws all the labels from a single buffer.
void draw(QPainter &p)
KStars Lite version of the function above.
void drawRudeNameLabel(SkyObject *obj, const QPointF &_p)
draw the object's name label on the map, without checking for overlap with other labels.
bool drawNameLabel(SkyObject *obj, const QPointF &_p, const qreal padding_factor=1)
Tries to draw a label for an object.
This is the main item that displays all SkyItems.
const Projector * projector() const
Get the current projector.
This is the canvas on which the sky is painted.
const Projector * projector() const
Get the current projector.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
QString translatedName() const
virtual QString labelString() const
virtual double labelOffset() 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....
int pointSize() const const
void setPointSize(int pointSize)
void setPointSizeF(qreal pointSize)
qreal height() const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
iterator insert(const_iterator before, parameter_type value)
void removeAt(qsizetype i)
qsizetype size() const const
qreal height() const const
void moveTo(const QPointF &position)
void setHeight(qreal height)
QPointF topLeft() const const
bool isEmpty() const const
qsizetype size() const const