00001
00002 #include "qgsrendererv2.h"
00003 #include "qgssymbolv2.h"
00004 #include "qgssymbollayerv2utils.h"
00005
00006 #include "qgssinglesymbolrendererv2.h"
00007
00008 #include "qgsrendererv2registry.h"
00009
00010 #include "qgsrendercontext.h"
00011 #include "qgsgeometry.h"
00012 #include "qgsfeature.h"
00013 #include "qgslogger.h"
00014 #include "qgsvectorlayer.h"
00015
00016 #include <QDomElement>
00017 #include <QDomDocument>
00018 #include <QPolygonF>
00019
00020
00021
00022 unsigned char* QgsFeatureRendererV2::_getPoint( QPointF& pt, QgsRenderContext& context, unsigned char* wkb )
00023 {
00024 wkb++;
00025 unsigned int wkbType = *(( int* ) wkb );
00026 wkb += sizeof( unsigned int );
00027
00028 double x = *(( double * ) wkb ); wkb += sizeof( double );
00029 double y = *(( double * ) wkb ); wkb += sizeof( double );
00030
00031 if ( wkbType == QGis::WKBPolygon25D )
00032 wkb += sizeof( double );
00033
00034 if ( context.coordinateTransform() )
00035 {
00036 double z = 0;
00037 context.coordinateTransform()->transformInPlace( x, y, z );
00038 }
00039
00040 context.mapToPixel().transformInPlace( x, y );
00041
00042 pt = QPointF( x, y );
00043 return wkb;
00044 }
00045
00046 unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, unsigned char* wkb )
00047 {
00048 wkb++;
00049 unsigned int wkbType = *(( int* ) wkb );
00050 wkb += sizeof( unsigned int );
00051 unsigned int nPoints = *(( int* ) wkb );
00052 wkb += sizeof( unsigned int );
00053
00054 bool hasZValue = ( wkbType == QGis::WKBLineString25D );
00055 double x, y;
00056
00057 pts.resize( nPoints );
00058
00059 const QgsCoordinateTransform* ct = context.coordinateTransform();
00060 const QgsMapToPixel& mtp = context.mapToPixel();
00061 double z = 0;
00062
00063 for ( unsigned int i = 0; i < nPoints; ++i )
00064 {
00065 x = *(( double * ) wkb );
00066 wkb += sizeof( double );
00067 y = *(( double * ) wkb );
00068 wkb += sizeof( double );
00069
00070 if ( hasZValue )
00071 wkb += sizeof( double );
00072
00073
00074 if ( ct )
00075 ct->transformInPlace( x, y, z );
00076 mtp.transformInPlace( x, y );
00077
00078 pts[i] = QPointF( x, y );
00079
00080 }
00081
00082 return wkb;
00083 }
00084
00085 unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, unsigned char* wkb )
00086 {
00087 wkb++;
00088 unsigned int wkbType = *(( int* ) wkb );
00089 wkb += sizeof( unsigned int );
00090 unsigned int numRings = *(( int* ) wkb );
00091 wkb += sizeof( unsigned int );
00092
00093 if ( numRings == 0 )
00094 return wkb;
00095
00096 bool hasZValue = ( wkbType == QGis::WKBPolygon25D );
00097 double x, y;
00098 holes.clear();
00099
00100 const QgsCoordinateTransform* ct = context.coordinateTransform();
00101 const QgsMapToPixel& mtp = context.mapToPixel();
00102 double z = 0;
00103
00104 for ( unsigned int idx = 0; idx < numRings; idx++ )
00105 {
00106 unsigned int nPoints = *(( int* )wkb );
00107 wkb += sizeof( unsigned int );
00108
00109 QPolygonF poly( nPoints );
00110
00111
00112 for ( unsigned int jdx = 0; jdx < nPoints; jdx++ )
00113 {
00114 x = *(( double * ) wkb ); wkb += sizeof( double );
00115 y = *(( double * ) wkb ); wkb += sizeof( double );
00116
00117
00118 if ( ct )
00119 ct->transformInPlace( x, y, z );
00120 mtp.transformInPlace( x, y );
00121
00122 poly[jdx] = QPointF( x, y );
00123
00124 if ( hasZValue )
00125 wkb += sizeof( double );
00126 }
00127
00128 if ( nPoints < 1 )
00129 continue;
00130
00131 if ( idx == 0 )
00132 pts = poly;
00133 else
00134 holes.append( poly );
00135 }
00136
00137 return wkb;
00138 }
00139
00140
00141 QgsFeatureRendererV2::QgsFeatureRendererV2( QString type )
00142 : mType( type ), mUsingSymbolLevels( false ),
00143 mCurrentVertexMarkerType( QgsVectorLayer::Cross ),
00144 mCurrentVertexMarkerSize( 3 )
00145 {
00146 }
00147
00148 QgsFeatureRendererV2* QgsFeatureRendererV2::defaultRenderer( QGis::GeometryType geomType )
00149 {
00150 return new QgsSingleSymbolRendererV2( QgsSymbolV2::defaultSymbol( geomType ) );
00151 }
00152
00153
00154 void QgsFeatureRendererV2::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker )
00155 {
00156 QgsSymbolV2* symbol = symbolForFeature( feature );
00157 if ( symbol == NULL )
00158 return;
00159
00160 QgsSymbolV2::SymbolType symbolType = symbol->type();
00161
00162 QgsGeometry* geom = feature.geometry();
00163 switch ( geom->wkbType() )
00164 {
00165 case QGis::WKBPoint:
00166 case QGis::WKBPoint25D:
00167 {
00168 if ( symbolType != QgsSymbolV2::Marker )
00169 {
00170 QgsDebugMsg( "point can be drawn only with marker symbol!" );
00171 break;
00172 }
00173 QPointF pt;
00174 _getPoint( pt, context, geom->asWkb() );
00175 (( QgsMarkerSymbolV2* )symbol )->renderPoint( pt, context, layer, selected );
00176
00177
00178
00179 }
00180 break;
00181
00182 case QGis::WKBLineString:
00183 case QGis::WKBLineString25D:
00184 {
00185 if ( symbolType != QgsSymbolV2::Line )
00186 {
00187 QgsDebugMsg( "linestring can be drawn only with line symbol!" );
00188 break;
00189 }
00190 QPolygonF pts;
00191 _getLineString( pts, context, geom->asWkb() );
00192 (( QgsLineSymbolV2* )symbol )->renderPolyline( pts, context, layer, selected );
00193
00194 if ( drawVertexMarker )
00195 renderVertexMarkerPolyline( pts, context );
00196 }
00197 break;
00198
00199 case QGis::WKBPolygon:
00200 case QGis::WKBPolygon25D:
00201 {
00202 if ( symbolType != QgsSymbolV2::Fill )
00203 {
00204 QgsDebugMsg( "polygon can be drawn only with fill symbol!" );
00205 break;
00206 }
00207 QPolygonF pts;
00208 QList<QPolygonF> holes;
00209 _getPolygon( pts, holes, context, geom->asWkb() );
00210 (( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), context, layer, selected );
00211
00212 if ( drawVertexMarker )
00213 renderVertexMarkerPolygon( pts, ( holes.count() ? &holes : NULL ), context );
00214 }
00215 break;
00216
00217 case QGis::WKBMultiPoint:
00218 case QGis::WKBMultiPoint25D:
00219 {
00220 if ( symbolType != QgsSymbolV2::Marker )
00221 {
00222 QgsDebugMsg( "multi-point can be drawn only with marker symbol!" );
00223 break;
00224 }
00225
00226 unsigned char* wkb = geom->asWkb();
00227 unsigned int num = *(( int* )( wkb + 5 ) );
00228 unsigned char* ptr = wkb + 9;
00229 QPointF pt;
00230
00231 for ( unsigned int i = 0; i < num; ++i )
00232 {
00233 ptr = _getPoint( pt, context, ptr );
00234 (( QgsMarkerSymbolV2* )symbol )->renderPoint( pt, context, layer, selected );
00235
00236
00237
00238 }
00239 }
00240 break;
00241
00242 case QGis::WKBMultiLineString:
00243 case QGis::WKBMultiLineString25D:
00244 {
00245 if ( symbolType != QgsSymbolV2::Line )
00246 {
00247 QgsDebugMsg( "multi-linestring can be drawn only with line symbol!" );
00248 break;
00249 }
00250
00251 unsigned char* wkb = geom->asWkb();
00252 unsigned int num = *(( int* )( wkb + 5 ) );
00253 unsigned char* ptr = wkb + 9;
00254 QPolygonF pts;
00255
00256 for ( unsigned int i = 0; i < num; ++i )
00257 {
00258 ptr = _getLineString( pts, context, ptr );
00259 (( QgsLineSymbolV2* )symbol )->renderPolyline( pts, context, layer, selected );
00260
00261 if ( drawVertexMarker )
00262 renderVertexMarkerPolyline( pts, context );
00263 }
00264 }
00265 break;
00266
00267 case QGis::WKBMultiPolygon:
00268 case QGis::WKBMultiPolygon25D:
00269 {
00270 if ( symbolType != QgsSymbolV2::Fill )
00271 {
00272 QgsDebugMsg( "multi-polygon can be drawn only with fill symbol!" );
00273 break;
00274 }
00275
00276 unsigned char* wkb = geom->asWkb();
00277 unsigned int num = *(( int* )( wkb + 5 ) );
00278 unsigned char* ptr = wkb + 9;
00279 QPolygonF pts;
00280 QList<QPolygonF> holes;
00281
00282 for ( unsigned int i = 0; i < num; ++i )
00283 {
00284 ptr = _getPolygon( pts, holes, context, ptr );
00285 (( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), context, layer, selected );
00286
00287 if ( drawVertexMarker )
00288 renderVertexMarkerPolygon( pts, ( holes.count() ? &holes : NULL ), context );
00289 }
00290 }
00291 break;
00292
00293 default:
00294 QgsDebugMsg( "unsupported wkb type for rendering" );
00295 }
00296 }
00297
00298 QString QgsFeatureRendererV2::dump()
00299 {
00300 return "UNKNOWN RENDERER\n";
00301 }
00302
00303
00304 QgsFeatureRendererV2* QgsFeatureRendererV2::load( QDomElement& element )
00305 {
00306
00307
00308 if ( element.isNull() )
00309 return NULL;
00310
00311
00312 QString rendererType = element.attribute( "type" );
00313
00314 QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( rendererType );
00315 if ( m == NULL )
00316 return NULL;
00317
00318 QgsFeatureRendererV2* r = m->createRenderer( element );
00319 if ( r )
00320 r->setUsingSymbolLevels( element.attribute( "symbollevels", "0" ).toInt() );
00321
00322 return r;
00323 }
00324
00325 QDomElement QgsFeatureRendererV2::save( QDomDocument& doc )
00326 {
00327
00328 return doc.createElement( RENDERER_TAG_NAME );
00329 }
00330
00331 QgsLegendSymbologyList QgsFeatureRendererV2::legendSymbologyItems( QSize iconSize )
00332 {
00333
00334 return QgsLegendSymbologyList();
00335 }
00336
00337 QgsLegendSymbolList QgsFeatureRendererV2::legendSymbolItems()
00338 {
00339 return QgsLegendSymbolList();
00340 }
00341
00342 void QgsFeatureRendererV2::setVertexMarkerAppearance( int type, int size )
00343 {
00344 mCurrentVertexMarkerType = type;
00345 mCurrentVertexMarkerSize = size;
00346 }
00347
00348 void QgsFeatureRendererV2::renderVertexMarker( QPointF& pt, QgsRenderContext& context )
00349 {
00350 QgsVectorLayer::drawVertexMarker( pt.x(), pt.y(), *context.painter(),
00351 ( QgsVectorLayer::VertexMarkerType ) mCurrentVertexMarkerType,
00352 mCurrentVertexMarkerSize );
00353 }
00354
00355 void QgsFeatureRendererV2::renderVertexMarkerPolyline( QPolygonF& pts, QgsRenderContext& context )
00356 {
00357 foreach( QPointF pt, pts )
00358 renderVertexMarker( pt, context );
00359 }
00360
00361 void QgsFeatureRendererV2::renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context )
00362 {
00363 foreach( QPointF pt, pts )
00364 renderVertexMarker( pt, context );
00365
00366 if ( rings )
00367 {
00368 foreach( QPolygonF ring, *rings )
00369 {
00370 foreach( QPointF pt, ring )
00371 renderVertexMarker( pt, context );
00372 }
00373 }
00374 }