Search for usage in LXR

#include <skylabeler.h>

Public Types

enum  label_t {

Public Member Functions

void addLabel (SkyObject *obj, label_t type)
void draw (QPainter &p)
bool drawGuideLabel (QPointF &o, const QString &text, double angle)
bool drawNameLabel (SkyObject *obj, const QPointF &_p, const qreal padding_factor=1)
void drawQueuedLabels ()
void drawQueuedLabelsType (SkyLabeler::label_t type)
void drawRudeNameLabel (SkyObject *obj, const QPointF &_p)
float fillRatio ()
QFontMetricsFfontMetrics ()
void getMargins (const QString &text, float *left, float *right, float *top, float *bot)
float hitRatio ()
int hits ()
bool markRegion (qreal left, qreal right, qreal top, qreal bot)
int marks ()
bool markText (const QPointF &p, const QString &text, qreal padding_factor=1)
void printInfo ()
void reset (SkyMap *skyMap)
void resetFont ()
void setFont (const QFont &font)
void setPen (const QPen &pen)
void setZoomFont ()
void shrinkFont (int delta)
QFont skyFont ()
QFont stdFont ()
void useStdFont ()

Static Public Member Functions

static void AddLabel (SkyObject *obj, label_t type)
static SkyLabelerInstance ()
static double ZoomOffset ()

Protected Member Functions

 SkyLabeler (SkyLabeler &skyLabler)

Detailed Description

The purpose of this class is to prevent labels from overlapping.

We do this by creating a virtual (lower Y-resolution) screen. Each "pixel" of this screen essentially contains a boolean value telling us whether or not there is an existing label covering at least part of that pixel. Before you draw a label, call mark( QPointF, QString ) of that label. We will check to see if it would overlap any existing label. If there is overlap we return false. If there is no overlap then we mark all the pixels that cover the new label and return true.

Since we need to check for overlap for every label every time it is potentially drawn on the screen, efficiency is essential. So instead of having a 2-dimensional array of boolean values we use Run Length Encoding and store the virtual array in a QVector of QLists. Each element of the vector, a LabelRow, corresponds to a horizontal strip of pixels on the actual screen. How many vertical pixels are in each strip is controlled by m_yDensity. The higher the density, the fewer vertical pixels per strip and hence a larger number of strips are needed to cover the screen. As m_yDensity increases so does the density of the strips.

The information in the X-dimension is completed run length encoded. A consecutive run of pixels in one strip that are covered by one or more labels is stored in a LabelRun object that merely stores the start pixel and the end pixel. A LabelRow is a list of LabelRun's stored in ascending order. This saves a lot of space over an explicit array and it also makes checking for overlaps faster and even makes inserting new overlaps faster on average.


1) Create a new SkyLabeler

2) every time you want to draw a new screen, reset the labeler.

3) Either:

A) Call drawLabel() or drawOffsetLabel(), or

B) Call addLabel() or addOffsetLabel()

4) Call draw() if addLabel() or addOffsetLabel() were used.

SkyLabeler works totally on a first come, first served basis which is almost the direct opposite of a z-buffer where the objects drawn last are most visible. This is why the addLabel() and draw() routines were created. They allow us to time-shift the drawing of labels and thus gives us control over their priority. The drawLabel() routines are still available but are not being used. The addLabel() routines adds a label to a specific buffer. Each type of label has its own buffer which lets us control the font and color as well as the priority. The priority is now manually set in the draw() routine by adjusting the order in which the various buffers get drawn.

Finally, even though this code was written to be very efficient, we might want to take some care in how many labels we throw at it. Sending it a large number of overlapping labels can be wasteful. Also, if one type of object floods it with labels early on then there may not be any room left for other types of labels. Therefore for some types of objects (stars) we may want to have a zoom dependent label threshold magnitude just like we have for drawing the stars themselves. This would throw few labels at the labeler when we are zoomed at and they would mostly overlap anyway and it would give us more labels when the user is zoomed in and there is more room for them. The "b" key currently causes the labeler statistics to be printed. This may be useful in figuring out the best settings for the magnitude limits. It may even be possible to have KStars do some of this throttling automatically but I haven't really thought about that problem yet.

– James B. Bowlin 2007-08-02

Definition at line 98 of file skylabeler.h.

Member Enumeration Documentation

◆ label_t


Rude labels block other labels FIXME: find a better solution.

Definition at line 105 of file skylabeler.h.

Constructor & Destructor Documentation

◆ SkyLabeler()

SkyLabeler::SkyLabeler ( )

Definition at line 83 of file skylabeler.cpp.

◆ ~SkyLabeler()

SkyLabeler::~SkyLabeler ( )

Definition at line 100 of file skylabeler.cpp.

Member Function Documentation

◆ AddLabel()

static void SkyLabeler::AddLabel ( SkyObject * obj,
label_t type )

static version of addLabel() below.

Definition at line 135 of file skylabeler.h.

◆ addLabel()

void SkyLabeler::addLabel ( SkyObject * obj,
SkyLabeler::label_t type )

queues the label in the "type" buffer for later drawing.

Definition at line 577 of file skylabeler.cpp.

◆ draw()

void SkyLabeler::draw ( QPainter & p)

KStars Lite version of the function above.

Draws labels using the given painter

pthe painter to draw labels with

Definition at line 388 of file skylabeler.cpp.

◆ drawGuideLabel()

bool SkyLabeler::drawGuideLabel ( QPointF & o,
const QString & text,
double angle )

Tries to draw the text at the position and angle specified.

If the label would overlap an existing label it is not drawn and we return false, otherwise the label is drawn, its position is marked and we return true.

Definition at line 112 of file skylabeler.cpp.

◆ drawNameLabel()

bool SkyLabeler::drawNameLabel ( SkyObject * obj,
const QPointF & _p,
const qreal padding_factor = 1 )

Tries to draw a label for an object.

objthe object to draw the label for
_pthe position of that object
true if the label was drawn //FIXME: should this just take an object pointer and do its own projection?

padding_factor is the factor by which the real label size is scaled

Definition at line 161 of file skylabeler.cpp.

◆ drawQueuedLabels()

void SkyLabeler::drawQueuedLabels ( )

draws the labels stored in all the buffers.

You can change the priority by editing the .cpp file and changing the order in which buffers are drawn. You can also change the fonts and colors there too.

Definition at line 593 of file skylabeler.cpp.

◆ drawQueuedLabelsType()

void SkyLabeler::drawQueuedLabelsType ( SkyLabeler::label_t type)

a convenience routine that draws all the labels from a single buffer.

Currently this is only called from within draw() above.

Definition at line 633 of file skylabeler.cpp.

◆ drawRudeNameLabel()

void SkyLabeler::drawRudeNameLabel ( SkyObject * obj,
const QPointF & _p )

draw the object's name label on the map, without checking for overlap with other labels.

objreference to the QPainter on which to draw (either the sky pixmap or printer device)
_pThe screen position for the label (in pixels; typically as found by SkyMap::toScreen())

Definition at line 647 of file skylabeler.cpp.

◆ fillRatio()

float SkyLabeler::fillRatio ( )


the percentage of pixels that have been filled. Expect return values between 0.0 and 100.0. A fillRatio above 20 is pretty busy and crowded. I think a fillRatio of about 10 looks good. The fillRatio will be lowered of the screen is zoomed out so are big blank spaces around the celestial sphere.

Definition at line 669 of file skylabeler.cpp.

◆ fontMetrics()

QFontMetricsF & SkyLabeler::fontMetrics ( )

returns the fontMetricsF we have already created.

Definition at line 205 of file skylabeler.h.

◆ getMargins()

void SkyLabeler::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 at line 227 of file skylabeler.cpp.

◆ hitRatio()

float SkyLabeler::hitRatio ( )

diagnostic, the number of times mark() returned true divided by the total number of times mark was called multiplied by 100.

Expect return values between 0.0 an 100. A hit ratio of 100 means no labels would have overlapped. A ratio of zero means no labels got drawn (which should never happen). A hitRatio around 50 might be a good target to shoot for. Expect it to be lower when fully zoomed out and higher when zoomed in.

Definition at line 676 of file skylabeler.cpp.

◆ hits()

int SkyLabeler::hits ( )

Definition at line 324 of file skylabeler.h.

◆ Instance()

SkyLabeler * SkyLabeler::Instance ( )

Definition at line 37 of file skylabeler.cpp.

◆ markRegion()

bool SkyLabeler::markRegion ( qreal left,
qreal right,
qreal top,
qreal bot )

Works just like markText() above but for an arbitrary rectangular region bounded by top, bot, left, and right.

Definition at line 425 of file skylabeler.cpp.

◆ marks()

int SkyLabeler::marks ( )

Definition at line 325 of file skylabeler.h.

◆ markText()

bool SkyLabeler::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.

Returns true if there is room for the label and returns false otherwise. If it returns true, the location of the label is marked on the virtual screen so future labels won't overlap it.

It is usually easier to use drawLabel() or drawLabelOffest() instead which both call mark() internally.

padding_factor is the factor by which the real label size is scaled

Definition at line 408 of file skylabeler.cpp.

◆ printInfo()

void SkyLabeler::printInfo ( )

diagnostic, prints some brief statistics to the console.

Currently this is connected to the "b" key in SkyMapEvents.

Definition at line 683 of file skylabeler.cpp.

◆ reset()

void SkyLabeler::reset ( SkyMap * skyMap)

clears the virtual screen (if needed) and resizes the virtual screen (if needed) to match skyMap.

A font must be specified which is taken to be the average or normal font that will be used. The size of the horizontal strips will be (slightly) optimized for this font. We also adjust the font size in psky to smaller fonts if the screen is zoomed out. You can mimic this setting with the static method SkyLabeler::setZoomFont( psky ).

Definition at line 250 of file skylabeler.cpp.

◆ resetFont()

void SkyLabeler::resetFont ( )

sets the font in SkyLabeler and in psky back to the zoom dependent value that was set in reset().

Also used in ConstellationLines.

Definition at line 222 of file skylabeler.cpp.

◆ setFont()

void SkyLabeler::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.

Also sets this font in the psky since this is almost always what is wanted.

Definition at line 187 of file skylabeler.cpp.

◆ setPen()

void SkyLabeler::setPen ( const QPen & pen)

sets the pen used for drawing labels on the sky.

Definition at line 197 of file skylabeler.cpp.

◆ setZoomFont()

void SkyLabeler::setZoomFont ( )

adjusts the font in psky to be smaller if we are zoomed out.

Definition at line 44 of file skylabeler.cpp.

◆ shrinkFont()

void SkyLabeler::shrinkFont ( int delta)

decreases the size of the font in psky and in the SkyLabeler by the delta points.

Negative deltas will increase the font size.

Definition at line 206 of file skylabeler.cpp.

◆ skyFont()

QFont SkyLabeler::skyFont ( )

Definition at line 319 of file skylabeler.h.

◆ stdFont()

QFont SkyLabeler::stdFont ( )

Definition at line 318 of file skylabeler.h.

◆ useStdFont()

void SkyLabeler::useStdFont ( )

sets the font in SkyLabeler and in psky to the font psky had originally when reset() was called.

Used by ConstellationNames.

Definition at line 217 of file skylabeler.cpp.

◆ ZoomOffset()

double SkyLabeler::ZoomOffset ( )

returns the zoom dependent label offset.

This is used in this class and in SkyObject. It is important that the offsets be the same so highlighted labels are always drawn exactly on top of the normally drawn labels.

Definition at line 75 of file skylabeler.cpp.

The documentation for this class was generated from the following files:
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:48:28 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.