SkyLabeler
#include <skylabeler.h>
Public Types | |
enum | label_t { STAR_LABEL , ASTEROID_LABEL , COMET_LABEL , PLANET_LABEL , JUPITER_MOON_LABEL , SATURN_MOON_LABEL , DEEP_SKY_LABEL , CONSTEL_NAME_LABEL , SATELLITE_LABEL , RUDE_LABEL , NUM_LABEL_TYPES } |
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 () |
QFontMetricsF & | fontMetrics () |
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 SkyLabeler * | Instance () |
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.
Synopsis:
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
enum SkyLabeler::label_t |
Enumerator | |
---|---|
NUM_LABEL_TYPES | Rude labels block other labels FIXME: find a better solution. |
Definition at line 105 of file skylabeler.h.
Constructor & Destructor Documentation
◆ SkyLabeler()
|
protected |
Definition at line 83 of file skylabeler.cpp.
◆ ~SkyLabeler()
SkyLabeler::~SkyLabeler | ( | ) |
Definition at line 100 of file skylabeler.cpp.
Member Function Documentation
◆ AddLabel()
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
- Parameters
-
p the painter to draw labels with
Definition at line 388 of file skylabeler.cpp.
◆ drawGuideLabel()
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.
- Parameters
-
obj the object to draw the label for _p the position of that object
- Returns
- 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()
draw the object's name label on the map, without checking for overlap with other labels.
- Parameters
-
obj reference to the QPainter on which to draw (either the sky pixmap or printer device) _p The 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 | ( | ) |
diagnostic.
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()
|
inline |
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()
|
inline |
Definition at line 324 of file skylabeler.h.
◆ Instance()
|
static |
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()
|
inline |
Definition at line 325 of file skylabeler.h.
◆ markText()
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()
|
inline |
Definition at line 319 of file skylabeler.h.
◆ stdFont()
|
inline |
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()
|
static |
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:
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.