22 #include <QFontMetrics>
26 #include <QDomElement>
44 #define M_PI 4*atan(1.0)
49 mMaxScale( 100000000 ),
50 mScaleBasedVisibility( false )
69 return idx < 0 ? QString() : feature.
attribute( idx ).toString();
76 Q_UNUSED( classAttributes );
89 double x1 = point.
x();
91 double x2 = point.
x();
92 double scale = ( x2 - x1 ) * 0.001;
96 if ( value.isEmpty() )
107 if ( value.isEmpty() )
113 font.setFamily( value );
118 if ( value.isEmpty() )
124 size = value.toDouble();
128 if ( value.isEmpty() )
132 value = value.toLower();
133 if ( value.compare(
"mapunits" ) == 0 )
144 double sizeMM = size * 0.3527;
152 if ((
int )size <= 0 )
156 font.setPixelSize( size );
159 if ( value.isEmpty() )
165 pen.setColor( QColor( value ) );
169 if ( value.isEmpty() )
175 font.setBold((
bool ) value.toInt() );
179 if ( value.isEmpty() )
185 font.setItalic((
bool ) value.toInt() );
189 if ( value.isEmpty() )
195 font.setUnderline((
bool ) value.toInt() );
199 if ( value.isEmpty() )
205 font.setStrikeOut((
bool ) value.toInt() );
210 bool useOverridePoint =
false;
212 if ( !value.isEmpty() )
214 overridePoint.
setX( value.toDouble() );
215 useOverridePoint =
true;
218 if ( !value.isEmpty() )
220 overridePoint.
setY( value.toDouble() );
221 useOverridePoint =
true;
226 QFontMetrics fm( font );
231 QStringList texts = text.split(
"\n" );
234 for (
int i = 0; i < texts.size(); i++ )
236 int w = fm.width( texts[i] );
241 height = fm.height() * texts.size();
245 width = fm.width( text );
246 height = fm.height();
253 if ( value.isEmpty() )
259 value = value.toLower();
263 if ( value.contains(
"left" ) )
264 alignment |= Qt::AlignLeft;
265 else if ( value.contains(
"right" ) )
266 alignment |= Qt::AlignRight;
268 alignment |= Qt::AlignHCenter;
270 if ( value.contains(
"bottom" ) )
271 alignment |= Qt::AlignBottom;
272 else if ( value.contains(
"top" ) )
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;
307 if ( value.isEmpty() )
313 xoffset = value.toDouble();
316 if ( value.isEmpty() )
322 yoffset = value.toDouble();
333 xoffset = xoffset * 0.3527 * renderContext.
scaleFactor();
334 yoffset = yoffset * 0.3527 * renderContext.
scaleFactor();
340 if ( value.isEmpty() )
346 ang = value.toDouble();
353 if ( useOverridePoint )
355 renderLabel( renderContext, overridePoint, text, font, pen, dx, dy,
356 xoffset, yoffset, ang, width, height, alignment );
360 std::vector<labelpoint> points;
362 for ( uint i = 0; i < points.size(); ++i )
364 renderLabel( renderContext, points[i].p, text, font, pen, dx, dy,
372 QString text, QFont font, QPen pen,
374 double xoffset,
double yoffset,
376 int width,
int height,
int alignment )
378 QPainter *painter = renderContext.
painter();
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 );
406 painter->setFont( font );
407 painter->translate( x, y );
410 painter->rotate( -ang );
425 bufferPen.setColor( Qt::white );
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 );
446 painter->drawText( QPointF( i, j ), text );
451 painter->setPen( pen );
453 painter->drawText( dx, dy - height, width, height, alignment, text );
455 painter->drawText( dx, dy, text );
466 for ( QgsAttributeList::iterator it = fields.begin(); it != fields.end(); ++it )
507 return mFields[fieldIndex].name();
518 const unsigned char *geom = geometry->
asWkb();
519 size_t geomlen = geometry->
wkbSize();
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 );
559 QgsDebugMsg(
"Unknown geometry type of " + QString::number( wkbType ) );
566 Q_ASSERT(
sizeof(
int ) == 4 );
568 Q_ASSERT(
sizeof(
double ) == 8 );
578 const unsigned char *geomend = geom + geomlen;
582 Q_ASSERT( geom + 1 +
sizeof( wkbType ) <= geomend );
585 memcpy( &wkbType, geom,
sizeof( wkbType ) );
586 geom +=
sizeof( wkbType );
595 Q_ASSERT( geom + 2*
sizeof(
double ) <= geomend );
596 double *pts = (
double * )geom;
597 point.
p.
set( pts[0], pts[1] );
599 geom += 2 *
sizeof( double );
607 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
608 int nPoints = *(
unsigned int * )geom;
609 geom +=
sizeof( int );
611 Q_ASSERT( geom + nPoints*
sizeof(
double )*dims <= geomend );
614 double *pts = (
double * )geom;
616 for (
int i = 1; i < nPoints; i++ )
618 double dx = pts[dims*i] - pts[dims*( i-1 )];
619 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
620 tl += sqrt( dx * dx + dy * dy );
626 for (
int i = 1; i < nPoints; i++ )
628 double dx = pts[dims*i] - pts[dims*( i-1 )];
629 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
630 double dl = sqrt( dx * dx + dy * dy );
634 double k = ( tl - l ) / dl;
636 point.
p.
set( pts[dims*( i-1 )] + k * dx,
637 pts[dims*( i-1 )+1] + k * dy );
638 point.
angle = atan2( dy, dx ) * 180.0 * M_1_PI;
645 geom += nPoints *
sizeof( double ) * dims;
653 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
654 int nRings = *(
unsigned int * )geom;
655 geom +=
sizeof( int );
657 for (
int i = 0; i < nRings; ++i )
659 Q_ASSERT( geom +
sizeof(
int ) <= geomend );
660 int nPoints = *(
unsigned int * )geom;
661 geom +=
sizeof( int );
663 Q_ASSERT( geom + nPoints*
sizeof(
double )*dims <= geomend );
667 double sx = 0.0, sy = 0.0;
668 double *pts = (
double* ) geom;
669 for (
int j = 0; j < nPoints - 1; j++ )
674 point.
p.
set( sx / ( nPoints - 1 ),
675 sy / ( nPoints - 1 ) );
679 geom += nPoints *
sizeof( double ) * dims;
696 QString name = prefix +
"name";
698 if ( el.hasAttribute( name ) )
700 name = el.attribute( name );
705 if (
mFields[idx].name() == name )
717 else if ( el.hasAttribute( prefix ) )
719 QString value = el.attribute( prefix );
731 QgsDebugMsg(
" called for layer label properties, got node " + node.nodeName() );
733 QDomNode scratchNode;
736 int red, green, blue;
740 scratchNode = node.namedItem(
"label" );
742 if ( scratchNode.isNull() )
744 QgsDebugMsg(
"couldn't find QgsLabel ``label'' attribute" );
748 el = scratchNode.toElement();
754 scratchNode = node.namedItem(
"family" );
756 if ( scratchNode.isNull() )
758 QgsDebugMsg(
"couldn't find QgsLabel ``family'' attribute" );
762 el = scratchNode.toElement();
768 scratchNode = node.namedItem(
"size" );
770 if ( scratchNode.isNull() )
772 QgsDebugMsg(
"couldn't find QgsLabel ``size'' attribute" );
776 el = scratchNode.toElement();
777 if ( !el.hasAttribute(
"unitfield" ) && !el.hasAttribute(
"unitfieldname" ) )
790 scratchNode = node.namedItem(
"bold" );
792 if ( scratchNode.isNull() )
794 QgsDebugMsg(
"couldn't find QgsLabel ``bold'' attribute" );
798 el = scratchNode.toElement();
804 scratchNode = node.namedItem(
"italic" );
806 if ( scratchNode.isNull() )
808 QgsDebugMsg(
"couldn't find QgsLabel ``italic'' attribute" );
812 el = scratchNode.toElement();
818 scratchNode = node.namedItem(
"underline" );
820 if ( scratchNode.isNull() )
822 QgsDebugMsg(
"couldn't find QgsLabel ``underline'' attribute" );
826 el = scratchNode.toElement();
832 scratchNode = node.namedItem(
"strikeout" );
834 if ( scratchNode.isNull() )
836 QgsDebugMsg(
"couldn't find QgsLabel ``strikeout'' attribute" );
840 el = scratchNode.toElement();
846 scratchNode = node.namedItem(
"color" );
848 if ( scratchNode.isNull() )
850 QgsDebugMsg(
"couldn't find QgsLabel ``color'' attribute" );
854 el = scratchNode.toElement();
856 red = el.attribute(
"red",
"0" ).toInt();
857 green = el.attribute(
"green",
"0" ).toInt();
858 blue = el.attribute(
"blue",
"0" ).toInt();
866 scratchNode = node.namedItem(
"x" );
868 if ( scratchNode.isNull() )
870 QgsDebugMsg(
"couldn't find QgsLabel ``x'' attribute" );
874 el = scratchNode.toElement();
879 scratchNode = node.namedItem(
"y" );
881 if ( scratchNode.isNull() )
883 QgsDebugMsg(
"couldn't find QgsLabel ``y'' attribute" );
887 el = scratchNode.toElement();
893 scratchNode = node.namedItem(
"offset" );
895 if ( scratchNode.isNull() )
897 QgsDebugMsg(
"couldn't find QgsLabel ``offset'' attribute" );
901 double xoffset, yoffset;
903 el = scratchNode.toElement();
906 xoffset = el.attribute(
"x",
"0.0" ).toDouble();
907 yoffset = el.attribute(
"y",
"0.0" ).toDouble();
915 scratchNode = node.namedItem(
"angle" );
917 if ( scratchNode.isNull() )
919 QgsDebugMsg(
"couldn't find QgsLabel ``angle'' attribute" );
923 el = scratchNode.toElement();
930 scratchNode = node.namedItem(
"alignment" );
932 if ( scratchNode.isNull() )
934 QgsDebugMsg(
"couldn't find QgsLabel ``alignment'' attribute" );
938 el = scratchNode.toElement();
945 scratchNode = node.namedItem(
"buffercolor" );
947 if ( scratchNode.isNull() )
949 QgsDebugMsg(
"couldn't find QgsLabel ``buffercolor'' attribute" );
953 el = scratchNode.toElement();
955 red = el.attribute(
"red",
"0" ).toInt();
956 green = el.attribute(
"green",
"0" ).toInt();
957 blue = el.attribute(
"blue",
"0" ).toInt();
963 scratchNode = node.namedItem(
"buffersize" );
965 if ( scratchNode.isNull() )
967 QgsDebugMsg(
"couldn't find QgsLabel ``bffersize'' attribute" );
971 el = scratchNode.toElement();
978 scratchNode = node.namedItem(
"bufferenabled" );
980 if ( scratchNode.isNull() )
982 QgsDebugMsg(
"couldn't find QgsLabel ``bufferenabled'' attribute" );
986 el = scratchNode.toElement();
992 scratchNode = node.namedItem(
"multilineenabled" );
994 if ( scratchNode.isNull() )
996 QgsDebugMsg(
"couldn't find QgsLabel ``multilineenabled'' attribute" );
1000 el = scratchNode.toElement();
1006 scratchNode = node.namedItem(
"selectedonly" );
1008 if ( scratchNode.isNull() )
1010 QgsDebugMsg(
"couldn't find QgsLabel ``selectedonly'' attribute" );
1014 el = scratchNode.toElement();
1024 QDomElement labelattributes = document.createElement(
"labelattributes" );
1027 QDomElement label = document.createElement(
"label" );
1035 label.setAttribute(
"fieldname",
"" );
1037 labelattributes.appendChild( label );
1040 QDomElement family = document.createElement(
"family" );
1051 family.setAttribute(
"fieldname",
"" );
1056 family.setAttribute(
"name",
"Arial" );
1057 family.setAttribute(
"fieldname",
"" );
1059 labelattributes.appendChild( family );
1062 QDomElement
size = document.createElement(
"size" );
1081 size.setAttribute(
"fieldname",
"" );
1086 size.setAttribute(
"value",
"12" );
1087 size.setAttribute(
"units",
"Points" );
1088 size.setAttribute(
"fieldname",
"" );
1090 labelattributes.appendChild( size );
1093 QDomElement bold = document.createElement(
"bold" );
1103 bold.setAttribute(
"fieldname",
"" );
1108 bold.setAttribute(
"on", 0 );
1109 bold.setAttribute(
"fieldname", 0 );
1111 labelattributes.appendChild( bold );
1114 QDomElement italic = document.createElement(
"italic" );
1124 italic.setAttribute(
"fieldname",
"" );
1129 italic.setAttribute(
"on",
"0" );
1130 italic.setAttribute(
"fieldname",
"" );
1132 labelattributes.appendChild( italic );
1135 QDomElement underline = document.createElement(
"underline" );
1145 underline.setAttribute(
"fieldname",
"" );
1150 underline.setAttribute(
"on", 0 );
1151 underline.setAttribute(
"fieldname",
"" );
1153 labelattributes.appendChild( underline );
1156 QDomElement strikeOut = document.createElement(
"strikeout" );
1166 strikeOut.setAttribute(
"fieldname",
"" );
1171 strikeOut.setAttribute(
"on", 0 );
1172 strikeOut.setAttribute(
"fieldname",
"" );
1174 labelattributes.appendChild( strikeOut );
1177 QDomElement color = document.createElement(
"color" );
1189 color.setAttribute(
"fieldname",
"" );
1194 color.setAttribute(
"red", 0 );
1195 color.setAttribute(
"green", 0 );
1196 color.setAttribute(
"blue", 0 );
1197 color.setAttribute(
"fieldname",
"" );
1199 labelattributes.appendChild( color );
1202 QDomElement x = document.createElement(
"x" );
1209 x.setAttribute(
"fieldname",
"" );
1211 labelattributes.appendChild( x );
1214 QDomElement y = document.createElement(
"y" );
1221 y.setAttribute(
"fieldname",
"" );
1223 labelattributes.appendChild( y );
1228 QDomElement offset = document.createElement(
"offset" );
1234 labelattributes.appendChild( offset );
1238 QDomElement
angle = document.createElement(
"angle" );
1248 angle.setAttribute(
"fieldname",
"" );
1253 angle.setAttribute(
"value",
"" );
1254 angle.setAttribute(
"fieldname",
"" );
1257 labelattributes.appendChild( angle );
1262 QDomElement alignment = document.createElement(
"alignment" );
1265 labelattributes.appendChild( alignment );
1269 QDomElement buffercolor = document.createElement(
"buffercolor" );
1281 buffercolor.setAttribute(
"fieldname",
"" );
1286 buffercolor.setAttribute(
"red",
"" );
1287 buffercolor.setAttribute(
"green",
"" );
1288 buffercolor.setAttribute(
"blue",
"" );
1289 buffercolor.setAttribute(
"fieldname",
"" );
1291 labelattributes.appendChild( buffercolor );
1294 QDomElement buffersize = document.createElement(
"buffersize" );
1305 buffersize.setAttribute(
"fieldname",
"" );
1310 buffersize.setAttribute(
"value",
"" );
1311 buffersize.setAttribute(
"units",
"" );
1312 buffersize.setAttribute(
"fieldname",
"" );
1314 labelattributes.appendChild( buffersize );
1317 QDomElement bufferenabled = document.createElement(
"bufferenabled" );
1327 bufferenabled.setAttribute(
"fieldname",
"" );
1332 bufferenabled.setAttribute(
"on",
"" );
1333 bufferenabled.setAttribute(
"fieldname",
"" );
1335 labelattributes.appendChild( bufferenabled );
1338 QDomElement multilineenabled = document.createElement(
"multilineenabled" );
1348 multilineenabled.setAttribute(
"fieldname",
"" );
1353 multilineenabled.setAttribute(
"on",
"" );
1354 multilineenabled.setAttribute(
"fieldname",
"" );
1356 labelattributes.appendChild( multilineenabled );
1358 QDomElement selectedonly = document.createElement(
"selectedonly" );
1365 selectedonly.setAttribute(
"on",
"" );
1367 labelattributes.appendChild( selectedonly );
1369 layer_node.appendChild( labelattributes );
void setBufferColor(const QColor &color)
double bufferSize() const
void setMultilineEnabled(bool useMultiline)
bool readLabelField(QDomElement &el, int attr, QString prefix)
QgsLabelAttributes * mLabelAttributes
Default layer attributes.
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)
void setFamily(const QString &family)
bool alignmentIsSet() const
size_t wkbSize() const
Returns the size of the WKB in asWkb().
static QString alignmentName(int alignment)
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
QgsPoint transform(const QgsPoint &p) const
bool selectedOnly() const
void renderLabel(QgsRenderContext &renderContext, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=0)
render label
Container of fields for a vector layer.
bool bufferEnabled() const
WkbType
Used for symbology operations.
void setFields(const QgsFields &fields)
Set available fields.
double scaleFactor() const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
int bufferSizeType() const
const QgsCoordinateTransform * coordinateTransform() const
QgsLabelAttributes * labelAttributes()
Pointer to default attributes.
bool mScaleBasedVisibility
A flag that tells us whether to use the above vars to restrict the label's visibility.
void setAutoAngle(bool state)
static QString unitsName(int units)
QgsFields mFields
Available layer fields.
QColor bufferColor() const
static int alignmentCode(const QString &name)
float mMaxScale
Maximum scale at which this label should be displayed.
const QColor & color() const
void setBufferSize(double size, int type)
void setScaleBasedVisibility(bool theVisibilityFlag)
Accessor and mutator for the scale based visilibility flag.
QList< int > QgsAttributeList
bool scaleBasedVisibility() const
double rasterScaleFactor() const
int count() const
Return number of items.
QGis::WkbType wkbType() const
Returns type of wkb (point / linestring / polygon etc.)
QString labelField(int attr) const
label field
QgsFields & fields()
Available vector fields.
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)
void set(double x, double y)
A class to represent a point geometry.
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)
const QString family() const
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)
void labelPoint(std::vector< labelpoint > &, QgsFeature &feature)
Get label point for simple feature in map units.
QgsLabel(const QgsFields &fields)
std::vector< int > mLabelFieldIdx
Label field indexes.
bool strikeOutIsSet() const
const QgsMapToPixel & mapToPixel() const
bool underlineIsSet() const
void setMinScale(float theMinScale)
Accessor and mutator for the minimum scale member.
Custom exception class for Coordinate Reference System related exceptions.
A class to store attributes needed for label rendering.
void setColor(const QColor &color)
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)
float mMinScale
Minimum scale at which this label should be displayed.
const QString text() const