2
#include "qgsrendererv2.h"
3
#include "qgssymbolv2.h"
4
#include "qgssymbollayerv2utils.h"
6
#include "qgssinglesymbolrendererv2.h" // for default renderer
8
#include "qgsrendererv2registry.h"
10
#include "qgsrendercontext.h"
11
#include "qgsgeometry.h"
12
#include "qgsfeature.h"
13
#include "qgslogger.h"
14
#include "qgsvectorlayer.h"
16
#include <QDomElement>
17
#include <QDomDocument>
22
static unsigned char* _getPoint( QPointF& pt, QgsRenderContext& context, unsigned char* wkb )
24
wkb++; // jump over endian info
25
unsigned int wkbType = *(( int* ) wkb );
26
wkb += sizeof( unsigned int );
28
double x = *(( double * ) wkb ); wkb += sizeof( double );
29
double y = *(( double * ) wkb ); wkb += sizeof( double );
31
if ( wkbType == QGis::WKBPolygon25D )
32
wkb += sizeof( double );
34
if ( context.coordinateTransform() )
36
double z = 0; // dummy variable for coordiante transform
37
context.coordinateTransform()->transformInPlace( x, y, z );
40
context.mapToPixel().transformInPlace( x, y );
46
static unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, unsigned char* wkb )
48
wkb++; // jump over endian info
49
unsigned int wkbType = *(( int* ) wkb );
50
wkb += sizeof( unsigned int );
51
unsigned int nPoints = *(( int* ) wkb );
52
wkb += sizeof( unsigned int );
54
bool hasZValue = ( wkbType == QGis::WKBLineString25D );
57
pts.resize( nPoints );
59
const QgsCoordinateTransform* ct = context.coordinateTransform();
60
const QgsMapToPixel& mtp = context.mapToPixel();
61
double z = 0; // dummy variable for coordiante transform
63
for ( unsigned int i = 0; i < nPoints; ++i )
65
x = *(( double * ) wkb );
66
wkb += sizeof( double );
67
y = *(( double * ) wkb );
68
wkb += sizeof( double );
70
if ( hasZValue ) // ignore Z value
71
wkb += sizeof( double );
73
// TODO: maybe to the transform at once (faster?)
75
ct->transformInPlace( x, y, z );
76
mtp.transformInPlace( x, y );
78
pts[i] = QPointF( x, y );
85
static unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, unsigned char* wkb )
87
wkb++; // jump over endian info
88
unsigned int wkbType = *(( int* ) wkb );
89
wkb += sizeof( unsigned int ); // jump over wkb type
90
unsigned int numRings = *(( int* ) wkb );
91
wkb += sizeof( unsigned int );
93
if ( numRings == 0 ) // sanity check for zero rings in polygon
96
bool hasZValue = ( wkbType == QGis::WKBPolygon25D );
100
const QgsCoordinateTransform* ct = context.coordinateTransform();
101
const QgsMapToPixel& mtp = context.mapToPixel();
102
double z = 0; // dummy variable for coordiante transform
104
for ( unsigned int idx = 0; idx < numRings; idx++ )
106
unsigned int nPoints = *(( int* )wkb );
107
wkb += sizeof( unsigned int );
109
QPolygonF poly( nPoints );
111
// Extract the points from the WKB and store in a pair of vectors.
112
for ( unsigned int jdx = 0; jdx < nPoints; jdx++ )
114
x = *(( double * ) wkb ); wkb += sizeof( double );
115
y = *(( double * ) wkb ); wkb += sizeof( double );
117
// TODO: maybe to the transform at once (faster?)
119
ct->transformInPlace( x, y, z );
120
mtp.transformInPlace( x, y );
122
poly[jdx] = QPointF( x, y );
125
wkb += sizeof( double );
134
holes.append( poly );
141
QgsFeatureRendererV2::QgsFeatureRendererV2( QString type )
142
: mType( type ), mUsingSymbolLevels( false ),
143
mCurrentVertexMarkerType( QgsVectorLayer::Cross ),
144
mCurrentVertexMarkerSize( 3 )
148
QgsFeatureRendererV2* QgsFeatureRendererV2::defaultRenderer( QGis::GeometryType geomType )
150
return new QgsSingleSymbolRendererV2( QgsSymbolV2::defaultSymbol( geomType ) );
154
void QgsFeatureRendererV2::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool drawVertexMarker )
156
QgsSymbolV2* symbol = symbolForFeature( feature );
157
if ( symbol == NULL )
160
QgsSymbolV2::SymbolType symbolType = symbol->type();
162
QgsGeometry* geom = feature.geometry();
163
switch ( geom->wkbType() )
166
case QGis::WKBPoint25D:
168
if ( symbolType != QgsSymbolV2::Marker )
170
QgsDebugMsg( "point can be drawn only with marker symbol!" );
174
_getPoint( pt, context, geom->asWkb() );
175
(( QgsMarkerSymbolV2* )symbol )->renderPoint( pt, context, layer );
177
//if ( drawVertexMarker )
178
// renderVertexMarker( pt, context );
182
case QGis::WKBLineString:
183
case QGis::WKBLineString25D:
185
if ( symbolType != QgsSymbolV2::Line )
187
QgsDebugMsg( "linestring can be drawn only with line symbol!" );
191
_getLineString( pts, context, geom->asWkb() );
192
(( QgsLineSymbolV2* )symbol )->renderPolyline( pts, context, layer );
194
if ( drawVertexMarker )
195
renderVertexMarkerPolyline( pts, context );
199
case QGis::WKBPolygon:
200
case QGis::WKBPolygon25D:
202
if ( symbolType != QgsSymbolV2::Fill )
204
QgsDebugMsg( "polygon can be drawn only with fill symbol!" );
208
QList<QPolygonF> holes;
209
_getPolygon( pts, holes, context, geom->asWkb() );
210
(( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), context, layer );
212
if ( drawVertexMarker )
213
renderVertexMarkerPolygon( pts, ( holes.count() ? &holes : NULL ), context );
217
case QGis::WKBMultiPoint:
218
case QGis::WKBMultiPoint25D:
220
if ( symbolType != QgsSymbolV2::Marker )
222
QgsDebugMsg( "multi-point can be drawn only with marker symbol!" );
226
unsigned char* wkb = geom->asWkb();
227
unsigned int num = *(( int* )( wkb + 5 ) );
228
unsigned char* ptr = wkb + 9;
231
for ( unsigned int i = 0; i < num; ++i )
233
ptr = _getPoint( pt, context, ptr );
234
(( QgsMarkerSymbolV2* )symbol )->renderPoint( pt, context, layer );
236
//if ( drawVertexMarker )
237
// renderVertexMarker( pt, context );
242
case QGis::WKBMultiLineString:
243
case QGis::WKBMultiLineString25D:
245
if ( symbolType != QgsSymbolV2::Line )
247
QgsDebugMsg( "multi-linestring can be drawn only with line symbol!" );
251
unsigned char* wkb = geom->asWkb();
252
unsigned int num = *(( int* )( wkb + 5 ) );
253
unsigned char* ptr = wkb + 9;
256
for ( unsigned int i = 0; i < num; ++i )
258
ptr = _getLineString( pts, context, ptr );
259
(( QgsLineSymbolV2* )symbol )->renderPolyline( pts, context, layer );
261
if ( drawVertexMarker )
262
renderVertexMarkerPolyline( pts, context );
267
case QGis::WKBMultiPolygon:
268
case QGis::WKBMultiPolygon25D:
270
if ( symbolType != QgsSymbolV2::Fill )
272
QgsDebugMsg( "multi-polygon can be drawn only with fill symbol!" );
276
unsigned char* wkb = geom->asWkb();
277
unsigned int num = *(( int* )( wkb + 5 ) );
278
unsigned char* ptr = wkb + 9;
280
QList<QPolygonF> holes;
282
for ( unsigned int i = 0; i < num; ++i )
284
ptr = _getPolygon( pts, holes, context, ptr );
285
(( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), context, layer );
287
if ( drawVertexMarker )
288
renderVertexMarkerPolygon( pts, ( holes.count() ? &holes : NULL ), context );
294
QgsDebugMsg( "unsupported wkb type for rendering" );
298
QString QgsFeatureRendererV2::dump()
300
return "UNKNOWN RENDERER\n";
304
QgsFeatureRendererV2* QgsFeatureRendererV2::load( QDomElement& element )
306
// <renderer-v2 type=""> ... </renderer-v2>
308
if ( element.isNull() )
312
QString rendererType = element.attribute( "type" );
314
QgsRendererV2CreateFunc pfCreate = QgsRendererV2Registry::instance()->rendererMetadata( rendererType ).createFunction();
316
// unknown renderer type?
317
if ( pfCreate == NULL )
320
QgsFeatureRendererV2* r = pfCreate( element );
322
r->setUsingSymbolLevels( element.attribute( "symbollevels", "0" ).toInt() );
327
QDomElement QgsFeatureRendererV2::save( QDomDocument& doc )
329
// create empty renderer element
330
return doc.createElement( RENDERER_TAG_NAME );
333
QgsLegendSymbologyList QgsFeatureRendererV2::legendSymbologyItems( QSize iconSize )
335
// empty list by default
336
return QgsLegendSymbologyList();
339
void QgsFeatureRendererV2::setVertexMarkerAppearance( int type, int size )
341
mCurrentVertexMarkerType = type;
342
mCurrentVertexMarkerSize = size;
345
void QgsFeatureRendererV2::renderVertexMarker( QPointF& pt, QgsRenderContext& context )
347
QgsVectorLayer::drawVertexMarker( pt.x(), pt.y(), *context.painter(),
348
( QgsVectorLayer::VertexMarkerType ) mCurrentVertexMarkerType,
349
mCurrentVertexMarkerSize );
352
void QgsFeatureRendererV2::renderVertexMarkerPolyline( QPolygonF& pts, QgsRenderContext& context )
354
foreach( QPointF pt, pts )
355
renderVertexMarker( pt, context );
358
void QgsFeatureRendererV2::renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context )
360
foreach( QPointF pt, pts )
361
renderVertexMarker( pt, context );
365
foreach( QPolygonF ring, *rings )
367
foreach( QPointF pt, ring )
368
renderVertexMarker( pt, context );