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 ((
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[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 = *(
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 double *pts = (
double * )geom;
599 point.p.set( pts[0], pts[1] );
601 geom += 2 *
sizeof( double );
611 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
613 int nPoints = *(
unsigned int * )geom;
614 geom +=
sizeof( int );
617 Q_ASSERT( geom + nPoints*
sizeof(
double )*dims <= geomend );
621 double *pts = (
double * )geom;
623 for (
int i = 1; i < nPoints; i++ )
625 double dx = pts[dims*i] - pts[dims*( i-1 )];
626 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
627 tl += sqrt( dx * dx + dy * dy );
633 for (
int i = 1; i < nPoints; i++ )
635 double dx = pts[dims*i] - pts[dims*( i-1 )];
636 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
637 double dl = sqrt( dx * dx + dy * dy );
641 double k = ( tl - l ) / dl;
643 point.p.set( pts[dims*( i-1 )] + k * dx,
644 pts[dims*( i-1 )+1] + k * dy );
645 point.angle = atan2( dy, dx ) * 180.0 * M_1_PI;
652 geom += nPoints *
sizeof( double ) * dims;
662 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
664 int nRings = *(
unsigned int * )geom;
665 geom +=
sizeof( int );
667 for (
int i = 0; i < nRings; ++i )
670 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
672 int nPoints = *(
unsigned int * )geom;
673 geom +=
sizeof( int );
676 Q_ASSERT( geom + nPoints*
sizeof(
double )*dims <= geomend );
681 double sx = 0.0, sy = 0.0;
682 double *pts = (
double* ) geom;
683 for (
int j = 0; j < nPoints - 1; j++ )
688 point.p.set( sx / ( nPoints - 1 ),
689 sy / ( nPoints - 1 ) );
693 geom += nPoints *
sizeof( double ) * dims;
708 bool QgsLabel::readLabelField(
QDomElement &el,
int attr,
const QString& prefix =
"field" )
710 QString name = prefix +
"name";
717 for ( ; idx < mFields.
count(); ++idx )
719 if ( mFields.
at( idx ).
name() == name )
725 if ( idx != mFields.
count() )
727 mLabelFieldIdx[attr] = idx;
734 mLabelFieldIdx[attr] = value.
isEmpty() ? -1 : value.
toInt();
738 mLabelFieldIdx[attr] = -1;
750 int red, green, blue;
756 if ( scratchNode.isNull() )
758 QgsDebugMsg(
"couldn't find QgsLabel ``label'' attribute" );
764 readLabelField( el,
Text );
768 scratchNode = node.
namedItem(
"family" );
770 if ( scratchNode.isNull() )
772 QgsDebugMsg(
"couldn't find QgsLabel ``family'' attribute" );
778 readLabelField( el,
Family );
784 if ( scratchNode.isNull() )
786 QgsDebugMsg(
"couldn't find QgsLabel ``size'' attribute" );
798 readLabelField( el,
SizeType,
"unitfield" );
800 readLabelField( el,
Size );
806 if ( scratchNode.isNull() )
808 QgsDebugMsg(
"couldn't find QgsLabel ``bold'' attribute" );
814 readLabelField( el,
Bold );
818 scratchNode = node.
namedItem(
"italic" );
820 if ( scratchNode.isNull() )
822 QgsDebugMsg(
"couldn't find QgsLabel ``italic'' attribute" );
828 readLabelField( el,
Italic );
832 scratchNode = node.
namedItem(
"underline" );
834 if ( scratchNode.isNull() )
836 QgsDebugMsg(
"couldn't find QgsLabel ``underline'' attribute" );
846 scratchNode = node.
namedItem(
"strikeout" );
848 if ( scratchNode.isNull() )
850 QgsDebugMsg(
"couldn't find QgsLabel ``strikeout'' attribute" );
862 if ( scratchNode.isNull() )
864 QgsDebugMsg(
"couldn't find QgsLabel ``color'' attribute" );
876 readLabelField( el,
Color );
882 if ( scratchNode.isNull() )
884 QgsDebugMsg(
"couldn't find QgsLabel ``x'' attribute" );
895 if ( scratchNode.isNull() )
897 QgsDebugMsg(
"couldn't find QgsLabel ``y'' attribute" );
907 scratchNode = node.
namedItem(
"offset" );
909 if ( scratchNode.isNull() )
911 QgsDebugMsg(
"couldn't find QgsLabel ``offset'' attribute" );
915 double xoffset, yoffset;
923 mLabelAttributes->
setOffset( xoffset, yoffset, type );
924 readLabelField( el,
XOffset,
"xfield" );
925 readLabelField( el,
YOffset,
"yfield" );
931 if ( scratchNode.isNull() )
933 QgsDebugMsg(
"couldn't find QgsLabel ``angle'' attribute" );
939 readLabelField( el,
Angle );
944 scratchNode = node.
namedItem(
"alignment" );
946 if ( scratchNode.isNull() )
948 QgsDebugMsg(
"couldn't find QgsLabel ``alignment'' attribute" );
959 scratchNode = node.
namedItem(
"buffercolor" );
961 if ( scratchNode.isNull() )
963 QgsDebugMsg(
"couldn't find QgsLabel ``buffercolor'' attribute" );
977 scratchNode = node.
namedItem(
"buffersize" );
979 if ( scratchNode.isNull() )
981 QgsDebugMsg(
"couldn't find QgsLabel ``bffersize'' attribute" );
992 scratchNode = node.
namedItem(
"bufferenabled" );
994 if ( scratchNode.isNull() )
996 QgsDebugMsg(
"couldn't find QgsLabel ``bufferenabled'' attribute" );
1006 scratchNode = node.
namedItem(
"multilineenabled" );
1008 if ( scratchNode.isNull() )
1010 QgsDebugMsg(
"couldn't find QgsLabel ``multilineenabled'' attribute" );
1020 scratchNode = node.
namedItem(
"selectedonly" );
1022 if ( scratchNode.isNull() )
1024 QgsDebugMsg(
"couldn't find QgsLabel ``selectedonly'' attribute" );
1043 if ( mLabelAttributes->
textIsSet() && mLabelFieldIdx[
Text] != -1 )
1057 if ( mLabelFieldIdx[
Family] != -1 )
1080 if ( mLabelFieldIdx[
Size] != -1 )
1082 if ( mLabelFieldIdx[
SizeType] != -1 )
1111 if ( mLabelFieldIdx[
Bold] != -1 )
1132 if ( mLabelFieldIdx[
Italic] != -1 )
1197 if ( mLabelFieldIdx[
Color] != -1 )
1256 if ( mLabelFieldIdx[
Angle] != -1 )
1388 mScaleBasedVisibility = theVisibilityFlag;
1393 return mScaleBasedVisibility;
1398 mMinScale = theMinScale;
1408 mMaxScale = theMaxScale;
void setBufferColor(const QColor &color)
const QString & name() const
Gets the name of the field.
double bufferSize() const
void setMultilineEnabled(bool useMultiline)
void setBold(bool enable)
void setLabelField(int attr, int fieldIndex)
Set label field.
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)
void setFamily(const QString &family)
bool alignmentIsSet() const
size_t wkbSize() const
Returns the size of the WKB in asWkb().
QString attribute(const QString &name, const QString &defValue) const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
static QString alignmentName(int alignment)
void scale(qreal sx, qreal sy)
QgsPoint transform(const QgsPoint &p) const
Transform the point from map (world) coordinates to device coordinates.
bool selectedOnly() const
void renderLabel(QgsRenderContext &renderContext, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=0)
render label
void setUnderline(bool enable)
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
bool bufferEnabled() const
void setFields(const QgsFields &fields)
Set available fields.
double scaleFactor() const
WkbType
Used for symbology operations.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
int bufferSizeType() const
const QgsCoordinateTransform * coordinateTransform() const
double toDouble(bool *ok) const
double x() const
Get the x value of the point.
QgsLabelAttributes * labelAttributes()
Pointer to default attributes.
QDomElement toElement() const
void setAutoAngle(bool state)
void setBold(bool enable)
static QString unitsName(int units)
void setPixelSize(int pixelSize)
QColor bufferColor() const
void setFont(const QFont &font)
QString number(int n, int base)
void append(const T &value)
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)
const QColor & color() const
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.
bool scaleBasedVisibility() const
void drawText(const QPointF &position, const QString &text)
double rasterScaleFactor() const
int count() const
Return number of items.
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QString labelField(int attr) const
label field
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 multilineEnabled() const
void setAngle(double angle)
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
A class to represent a point.
void writeXML(QDomNode &label_node, QDomDocument &document) const
Writes the contents of the renderer to a configuration file.
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...
bool bufferSizeIsSet() const
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 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
const QString family() const
void setItalic(bool enable)
void setStrikeOut(bool enable)
void addRequiredFields(QgsAttributeList &fields) const
add vector of required fields to existing list of fields
Contains information about the context of a rendering operation.
void setMaxScale(float theMaxScale)
Accessor and mutator for the maximum scale member.
void setAlignment(int alignment)
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
void setOffset(double x, double y, int type)
QgsLabel(const QgsFields &fields)
bool strikeOutIsSet() const
void setFamily(const QString &family)
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
void setStrikeOut(bool enable)
void translate(const QPointF &offset)
const QgsMapToPixel & mapToPixel() const
double y() const
Get the y value of the point.
bool underlineIsSet() const
void setMinScale(float theMinScale)
Accessor and mutator for the minimum scale member.
Custom exception class for Coordinate Reference System related exceptions.
QDomElement createElement(const QString &tagName)
A class to store attributes needed for label rendering.
void setColor(const QColor &color)
int compare(const QString &other) const
void setBufferEnabled(bool useBufferFlag)
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
bool bufferColorIsSet() const
void setItalic(bool enable)
const QString text() const