22 #include <QFontMetrics> 26 #include <QDomElement> 44 #define M_PI 4*atan(1.0) 49 , mMaxScale( 100000000 )
50 , mScaleBasedVisibility( false )
56 mLabelFieldIdx[i] = -1;
63 delete mLabelAttributes;
68 int idx = mLabelFieldIdx[attr];
76 Q_UNUSED( classAttributes );
89 double x1 = point.
x();
91 double x2 = point.
x();
92 double scale = ( x2 - x1 ) * 0.001;
98 text = mLabelAttributes->
text();
120 size = mLabelAttributes->
size();
129 sizeType = mLabelAttributes->
sizeType();
133 if ( value.
compare(
"mapunits" ) == 0 )
144 double sizeMM = size * 0.3527;
152 if ( static_cast< int >( size ) <= 0 )
210 bool useOverridePoint =
false;
215 useOverridePoint =
true;
221 useOverridePoint =
true;
234 for (
int i = 0; i < texts.
size(); i++ )
236 int w = fm.
width( texts[i] );
245 width = fm.
width( text );
255 alignment = mLabelAttributes->
alignment();
264 alignment |= Qt::AlignLeft;
265 else if ( value.
contains(
"right" ) )
266 alignment |= Qt::AlignRight;
268 alignment |= Qt::AlignHCenter;
271 alignment |= Qt::AlignBottom;
273 alignment |= Qt::AlignTop;
275 alignment |= Qt::AlignVCenter;
278 if ( alignment & Qt::AlignLeft )
282 else if ( alignment & Qt::AlignHCenter )
286 else if ( alignment & Qt::AlignRight )
291 if ( alignment & Qt::AlignBottom )
295 else if ( alignment & Qt::AlignVCenter )
299 else if ( alignment & Qt::AlignTop )
305 double xoffset, yoffset;
309 xoffset = mLabelAttributes->
xOffset();
318 yoffset = mLabelAttributes->
yOffset();
333 xoffset = xoffset * 0.3527 * renderContext.
scaleFactor();
334 yoffset = yoffset * 0.3527 * renderContext.
scaleFactor();
342 ang = mLabelAttributes->
angle();
353 if ( useOverridePoint )
355 renderLabel( renderContext, overridePoint, text, font, pen, dx, dy,
356 xoffset, yoffset, ang, width, height, alignment );
360 std::vector<labelpoint> points;
361 labelPoint( points, feature );
362 for ( uint i = 0; i < points.size(); ++i )
364 renderLabel( renderContext, points[i].p, text, font, pen, dx, dy,
365 xoffset, yoffset, mLabelAttributes->
angleIsAuto() ? points[i].angle : ang, width, height, alignment );
374 double xoffset,
double yoffset,
376 int width,
int height,
int alignment )
390 QgsDebugMsg(
"Caught transform error. Skipping rendering this label" );
397 double x = point.
x();
398 double y = point.
y();
400 double rad = ang *
M_PI / 180;
402 x = x + xoffset * cos( rad ) - yoffset * sin( rad );
403 y = y - xoffset * sin( rad ) - yoffset * cos( rad );
427 painter->
setPen( bufferPen );
429 double bufferStepSize;
439 for (
double i = dx - myBufferSize; i <= dx + myBufferSize; i += bufferStepSize )
441 for (
double j = dy - myBufferSize; j <= dy + myBufferSize; j += bufferStepSize )
444 painter->
drawText(
QRectF( i, j - height, width, height ), alignment, text );
453 painter->
drawText( dx, dy - height, width, height, alignment, text );
463 if ( mLabelFieldIdx[i] == -1 )
468 if ( *it == mLabelFieldIdx[i] )
476 fields.
append( mLabelFieldIdx[i] );
496 mLabelFieldIdx[attr] = fieldIndex;
504 int fieldIndex = mLabelFieldIdx[attr];
505 if ( fieldIndex < 0 || fieldIndex >= mFields.
count() )
507 return mFields.
at( fieldIndex ).
name();
512 return mLabelAttributes;
515 void QgsLabel::labelPoint( std::vector<labelpoint>& points,
QgsFeature & feature )
518 const unsigned char *geom = geometry->
asWkb();
519 size_t geomlen = geometry->
wkbSize();
532 labelPoint( point, geom, geomlen );
533 points.push_back( point );
545 Q_ASSERT( 1 +
sizeof( wkbType ) +
sizeof(
int ) <= geomlen );
546 geom += 1 +
sizeof( wkbType );
547 int nFeatures = *(
reinterpret_cast< const unsigned int *
>( geom ) );
548 geom +=
sizeof( int );
550 const unsigned char *feature = geom;
551 for (
int i = 0; i < nFeatures && feature; ++i )
553 feature = labelPoint( point, feature, geom + geomlen - feature );
554 points.push_back( point );
563 const unsigned char* QgsLabel::labelPoint(
labelpoint& point,
const unsigned char *geom,
size_t geomlen )
566 Q_ASSERT(
sizeof(
int ) == 4 );
568 Q_ASSERT(
sizeof(
double ) == 8 );
578 const unsigned char *geomend = geom + geomlen;
579 Q_ASSERT( geom + 1 +
sizeof( wkbType ) <= geomend );
585 memcpy( &wkbType, geom,
sizeof( wkbType ) );
586 geom +=
sizeof( wkbType );
596 Q_ASSERT( geom + 2*
sizeof(
double ) <= geomend );
598 const double *pts =
reinterpret_cast< const double *
>( geom );
599 point.
p.
set( pts[0], pts[1] );
601 geom += 2 *
sizeof( double );
612 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
614 int nPoints = *(
reinterpret_cast< const unsigned int *
>( geom ) );
615 geom +=
sizeof( int );
618 Q_ASSERT( geom + nPoints*
sizeof(
double )*dims <= geomend );
622 const double *pts =
reinterpret_cast< const double *
>( geom );
624 for (
int i = 1; i < nPoints; i++ )
626 double dx = pts[dims*i] - pts[dims*( i-1 )];
627 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
628 tl += sqrt( dx * dx + dy * dy );
634 for (
int i = 1; i < nPoints; i++ )
636 double dx = pts[dims*i] - pts[dims*( i-1 )];
637 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
638 double dl = sqrt( dx * dx + dy * dy );
642 double k = ( tl - l ) / dl;
644 point.
p.
set( pts[dims*( i-1 )] + k * dx,
645 pts[dims*( i-1 )+1] + k * dy );
646 point.
angle = atan2( dy, dx ) * 180.0 * M_1_PI;
653 geom += nPoints *
sizeof( double ) * dims;
664 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
666 int nRings = *(
reinterpret_cast< const unsigned int *
>( geom ) );
667 geom +=
sizeof( int );
669 for (
int i = 0; i < nRings; ++i )
672 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
674 int nPoints = *(
reinterpret_cast< const unsigned int *
>( geom ) );
675 geom +=
sizeof( int );
678 Q_ASSERT( geom + nPoints*
sizeof(
double )*dims <= geomend );
683 double sx = 0.0, sy = 0.0;
684 const double *pts =
reinterpret_cast< const double*
>( geom );
685 for (
int j = 0; j < nPoints - 1; j++ )
690 point.
p.
set( sx / ( nPoints - 1 ),
691 sy / ( nPoints - 1 ) );
695 geom += nPoints *
sizeof( double ) * dims;
710 bool QgsLabel::readLabelField(
QDomElement &el,
int attr,
const QString& prefix =
"field" )
712 QString name = prefix +
"name";
719 for ( ; idx < mFields.
count(); ++idx )
721 if ( mFields.
at( idx ).
name() == name )
727 if ( idx != mFields.
count() )
729 mLabelFieldIdx[attr] = idx;
736 mLabelFieldIdx[attr] = value.
isEmpty() ? -1 : value.
toInt();
740 mLabelFieldIdx[attr] = -1;
752 int red, green, blue;
758 if ( scratchNode.isNull() )
760 QgsDebugMsg(
"couldn't find QgsLabel ``label'' attribute" );
766 readLabelField( el,
Text );
770 scratchNode = node.
namedItem(
"family" );
772 if ( scratchNode.isNull() )
774 QgsDebugMsg(
"couldn't find QgsLabel ``family'' attribute" );
780 readLabelField( el,
Family );
786 if ( scratchNode.isNull() )
788 QgsDebugMsg(
"couldn't find QgsLabel ``size'' attribute" );
800 readLabelField( el,
SizeType,
"unitfield" );
802 readLabelField( el,
Size );
808 if ( scratchNode.isNull() )
810 QgsDebugMsg(
"couldn't find QgsLabel ``bold'' attribute" );
816 readLabelField( el,
Bold );
820 scratchNode = node.
namedItem(
"italic" );
822 if ( scratchNode.isNull() )
824 QgsDebugMsg(
"couldn't find QgsLabel ``italic'' attribute" );
830 readLabelField( el,
Italic );
834 scratchNode = node.
namedItem(
"underline" );
836 if ( scratchNode.isNull() )
838 QgsDebugMsg(
"couldn't find QgsLabel ``underline'' attribute" );
848 scratchNode = node.
namedItem(
"strikeout" );
850 if ( scratchNode.isNull() )
852 QgsDebugMsg(
"couldn't find QgsLabel ``strikeout'' attribute" );
864 if ( scratchNode.isNull() )
866 QgsDebugMsg(
"couldn't find QgsLabel ``color'' attribute" );
878 readLabelField( el,
Color );
884 if ( scratchNode.isNull() )
886 QgsDebugMsg(
"couldn't find QgsLabel ``x'' attribute" );
897 if ( scratchNode.isNull() )
899 QgsDebugMsg(
"couldn't find QgsLabel ``y'' attribute" );
909 scratchNode = node.
namedItem(
"offset" );
911 if ( scratchNode.isNull() )
913 QgsDebugMsg(
"couldn't find QgsLabel ``offset'' attribute" );
917 double xoffset, yoffset;
925 mLabelAttributes->
setOffset( xoffset, yoffset, type );
926 readLabelField( el,
XOffset,
"xfield" );
927 readLabelField( el,
YOffset,
"yfield" );
933 if ( scratchNode.isNull() )
935 QgsDebugMsg(
"couldn't find QgsLabel ``angle'' attribute" );
941 readLabelField( el,
Angle );
946 scratchNode = node.
namedItem(
"alignment" );
948 if ( scratchNode.isNull() )
950 QgsDebugMsg(
"couldn't find QgsLabel ``alignment'' attribute" );
961 scratchNode = node.
namedItem(
"buffercolor" );
963 if ( scratchNode.isNull() )
965 QgsDebugMsg(
"couldn't find QgsLabel ``buffercolor'' attribute" );
979 scratchNode = node.
namedItem(
"buffersize" );
981 if ( scratchNode.isNull() )
983 QgsDebugMsg(
"couldn't find QgsLabel ``bffersize'' attribute" );
994 scratchNode = node.
namedItem(
"bufferenabled" );
996 if ( scratchNode.isNull() )
998 QgsDebugMsg(
"couldn't find QgsLabel ``bufferenabled'' attribute" );
1008 scratchNode = node.
namedItem(
"multilineenabled" );
1010 if ( scratchNode.isNull() )
1012 QgsDebugMsg(
"couldn't find QgsLabel ``multilineenabled'' attribute" );
1022 scratchNode = node.
namedItem(
"selectedonly" );
1024 if ( scratchNode.isNull() )
1026 QgsDebugMsg(
"couldn't find QgsLabel ``selectedonly'' attribute" );
1045 if ( mLabelAttributes->
textIsSet() && mLabelFieldIdx[
Text] != -1 )
1059 if ( mLabelFieldIdx[
Family] != -1 )
1082 if ( mLabelFieldIdx[
Size] != -1 )
1084 if ( mLabelFieldIdx[
SizeType] != -1 )
1113 if ( mLabelFieldIdx[
Bold] != -1 )
1134 if ( mLabelFieldIdx[
Italic] != -1 )
1199 if ( mLabelFieldIdx[
Color] != -1 )
1258 if ( mLabelFieldIdx[
Angle] != -1 )
1390 mScaleBasedVisibility = theVisibilityFlag;
1395 return mScaleBasedVisibility;
1400 mMinScale = theMinScale;
1410 mMaxScale = theMaxScale;
1420 return !mScaleBasedVisibility ||
void setBufferColor(const QColor &color)
void setMultilineEnabled(bool useMultiline)
void setBold(bool enable)
void setLabelField(int attr, int fieldIndex)
Set label field.
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
void setSize(double size, int type)
void setUnderline(bool enable)
void setSelectedOnly(bool selectedonly)
static int unitsCode(const QString &name)
QDomNode appendChild(const QDomNode &newChild)
bool strikeOutIsSet() const
void setFamily(const QString &family)
QString attribute(const QString &name, const QString &defValue) const
int bufferSizeType() const
QString labelField(int attr) const
label field
const QColor & color() const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
static QString alignmentName(int alignment)
void scale(qreal sx, qreal sy)
void setUnderline(bool enable)
QColor bufferColor() const
bool alignmentIsSet() const
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
WkbType
Used for symbology operations.
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
void setFields(const QgsFields &fields)
Set available fields.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
const QString text() const
double toDouble(bool *ok) const
int wkbSize() const
Returns the size of the WKB in asWkb().
int count() const
Return number of items.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
double y() const
Get the y value of the point.
QgsLabelAttributes * labelAttributes()
Pointer to default attributes.
QDomElement toElement() const
void setAutoAngle(bool state)
void setBold(bool enable)
QgsPoint transform(const QgsPoint &p) const
Transform the point from map (world) coordinates to device coordinates.
static QString unitsName(int units)
void setPixelSize(int pixelSize)
void setFont(const QFont &font)
QString number(int n, int base)
const QString family() const
void append(const T &value)
bool isInScaleRange(double scale) const
Return true if the label is visible at the given scale.
bool bufferColorIsSet() const
static int alignmentCode(const QString &name)
bool hasAttribute(const QString &name) const
void setPen(const QColor &color)
void setAttribute(const QString &name, const QString &value)
void setBufferSize(double size, int type)
int toInt(bool *ok, int base) const
void setScaleBasedVisibility(bool theVisibilityFlag)
Accessor and mutator for the scale based visilibility flag.
const QgsCoordinateTransform * coordinateTransform() const
void drawText(const QPointF &position, const QString &text)
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
QgsFields & fields()
Available vector fields.
void setColor(const QColor &color)
void setText(const QString &text)
void readXML(const QDomNode &node)
Reads the renderer configuration from an XML file.
bool scaleBasedVisibility() const
void setAngle(double angle)
void set(double x, double y)
Sets the x and y value of the point.
A class to represent a point.
bool selectedOnly() const
QString fieldValue(int attr, QgsFeature &feature)
Get field value if : 1) field name is not empty 2) field exists 3) value is defined otherwise returns...
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
QDomNode namedItem(const QString &name) const
bool bufferSizeIsSet() const
bool contains(QChar ch, Qt::CaseSensitivity cs) const
void setX(double x)
Sets the x value of the point.
void setY(double y)
Sets the y value of the point.
int width(const QString &text, int len) const
void setItalic(bool enable)
void setStrikeOut(bool enable)
void renderLabel(QgsRenderContext &renderContext, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=nullptr)
render label
Contains information about the context of a rendering operation.
void setMaxScale(float theMaxScale)
Accessor and mutator for the maximum scale member.
bool bufferEnabled() const
void setAlignment(int alignment)
const QgsMapToPixel & mapToPixel() const
void setOffset(double x, double y, int type)
QgsLabel(const QgsFields &fields)
void setFamily(const QString &family)
void setStrikeOut(bool enable)
void translate(const QPointF &offset)
void addRequiredFields(QgsAttributeList &fields) const
add vector of required fields to existing list of fields
void setMinScale(float theMinScale)
Accessor and mutator for the minimum scale member.
Custom exception class for Coordinate Reference System related exceptions.
double rasterScaleFactor() const
QDomElement createElement(const QString &tagName)
A class to store attributes needed for label rendering.
void setColor(const QColor &color)
double scaleFactor() const
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
int compare(const QString &other) const
void setBufferEnabled(bool useBufferFlag)
static double SCALE_PRECISION
Fudge factor used to compare two scales.
bool underlineIsSet() const
void setItalic(bool enable)
double x() const
Get the x value of the point.
void writeXML(QDomNode &label_node, QDomDocument &document) const
Writes the contents of the renderer to a configuration file.
double bufferSize() const
bool multilineEnabled() const