00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <cmath>
00018 #include <cfloat>
00019
00020 #include "qgscoordinatetransform.h"
00021 #include "qgslogger.h"
00022 #include "qgsmaprenderer.h"
00023 #include "qgsscalecalculator.h"
00024 #include "qgsmaptopixel.h"
00025 #include "qgsmaplayer.h"
00026 #include "qgsmaplayerregistry.h"
00027 #include "qgsdistancearea.h"
00028 #include "qgscentralpointpositionmanager.h"
00029 #include "qgsoverlayobjectpositionmanager.h"
00030 #include "qgspalobjectpositionmanager.h"
00031 #include "qgsvectorlayer.h"
00032 #include "qgsvectoroverlay.h"
00033
00034
00035 #include <QDomDocument>
00036 #include <QDomNode>
00037 #include <QPainter>
00038 #include <QListIterator>
00039 #include <QSettings>
00040 #include <QTime>
00041 #include "qgslogger.h"
00042
00043
00044 QgsMapRenderer::QgsMapRenderer()
00045 {
00046 mScaleCalculator = new QgsScaleCalculator;
00047 mDistArea = new QgsDistanceArea;
00048
00049 mDrawing = false;
00050 mOverview = false;
00051
00052
00053 setMapUnits( QGis::Degrees );
00054
00055 mSize = QSize( 0, 0 );
00056
00057 mProjectionsEnabled = false;
00058 mDestCRS = new QgsCoordinateReferenceSystem( GEOCRS_ID, QgsCoordinateReferenceSystem::InternalCrsId );
00059
00060 mOutputUnits = QgsMapRenderer::Millimeters;
00061
00062 mLabelingEngine = NULL;
00063 }
00064
00065 QgsMapRenderer::~QgsMapRenderer()
00066 {
00067 delete mScaleCalculator;
00068 delete mDistArea;
00069 delete mDestCRS;
00070 delete mLabelingEngine;
00071 }
00072
00073
00074 QgsRectangle QgsMapRenderer::extent() const
00075 {
00076 return mExtent;
00077 }
00078
00079 void QgsMapRenderer::updateScale()
00080 {
00081 mScale = mScaleCalculator->calculate( mExtent, mSize.width() );
00082 }
00083
00084 bool QgsMapRenderer::setExtent( const QgsRectangle& extent )
00085 {
00086
00087 mLastExtent = mExtent;
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 if ( extent.width() > 0 &&
00101 extent.height() > 0 &&
00102 extent.width() < 1 &&
00103 extent.height() < 1 )
00104 {
00105
00106
00107 double xMean = ( fabs( extent.xMinimum() ) + fabs( extent.xMaximum() ) ) * 0.5;
00108 double yMean = ( fabs( extent.yMinimum() ) + fabs( extent.yMaximum() ) ) * 0.5;
00109
00110 double xRange = extent.width() / xMean;
00111 double yRange = extent.height() / yMean;
00112
00113 static const double minProportion = 1e-12;
00114 if ( xRange < minProportion || yRange < minProportion )
00115 return false;
00116 }
00117
00118 mExtent = extent;
00119 if ( !extent.isEmpty() )
00120 adjustExtentToSize();
00121 return true;
00122 }
00123
00124
00125
00126 void QgsMapRenderer::setOutputSize( QSize size, int dpi )
00127 {
00128 mSize = QSizeF( size.width(), size.height() );
00129 mScaleCalculator->setDpi( dpi );
00130 adjustExtentToSize();
00131 }
00132
00133 void QgsMapRenderer::setOutputSize( QSizeF size, double dpi )
00134 {
00135 mSize = size;
00136 mScaleCalculator->setDpi( dpi );
00137 adjustExtentToSize();
00138 }
00139
00140 double QgsMapRenderer::outputDpi()
00141 {
00142 return mScaleCalculator->dpi();
00143 }
00144
00145 QSize QgsMapRenderer::outputSize()
00146 {
00147 return mSize.toSize();
00148 }
00149
00150 QSizeF QgsMapRenderer::outputSizeF()
00151 {
00152 return mSize;
00153 }
00154
00155 void QgsMapRenderer::adjustExtentToSize()
00156 {
00157 double myHeight = mSize.height();
00158 double myWidth = mSize.width();
00159
00160 QgsMapToPixel newCoordXForm;
00161
00162 if ( !myWidth || !myHeight )
00163 {
00164 mScale = 1;
00165 newCoordXForm.setParameters( 0, 0, 0, 0 );
00166 return;
00167 }
00168
00169
00170
00171 double mapUnitsPerPixelY = mExtent.height() / myHeight;
00172 double mapUnitsPerPixelX = mExtent.width() / myWidth;
00173 mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
00174
00175
00176 double dxmin, dxmax, dymin, dymax, whitespace;
00177
00178 if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
00179 {
00180 dymin = mExtent.yMinimum();
00181 dymax = mExtent.yMaximum();
00182 whitespace = (( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
00183 dxmin = mExtent.xMinimum() - whitespace;
00184 dxmax = mExtent.xMaximum() + whitespace;
00185 }
00186 else
00187 {
00188 dxmin = mExtent.xMinimum();
00189 dxmax = mExtent.xMaximum();
00190 whitespace = (( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
00191 dymin = mExtent.yMinimum() - whitespace;
00192 dymax = mExtent.yMaximum() + whitespace;
00193 }
00194
00195 QgsDebugMsg( QString( "Map units per pixel (x,y) : %1, %2\n" ).arg( mapUnitsPerPixelX ).arg( mapUnitsPerPixelY ) );
00196 QgsDebugMsg( QString( "Pixmap dimensions (x,y) : %1, %2\n" ).arg( myWidth ).arg( myHeight ) );
00197 QgsDebugMsg( QString( "Extent dimensions (x,y) : %1, %2\n" ).arg( mExtent.width() ).arg( mExtent.height() ) );
00198 QgsDebugMsg( mExtent.toString() );
00199
00200
00201 mExtent.setXMinimum( dxmin );
00202 mExtent.setXMaximum( dxmax );
00203 mExtent.setYMinimum( dymin );
00204 mExtent.setYMaximum( dymax );
00205
00206
00207 updateScale();
00208
00209 QgsDebugMsg( QString( "Scale (assuming meters as map units) = 1:%1" ).arg( mScale ) );
00210
00211 newCoordXForm.setParameters( mMapUnitsPerPixel, dxmin, dymin, myHeight );
00212 mRenderContext.setMapToPixel( newCoordXForm );
00213 mRenderContext.setExtent( mExtent );
00214 }
00215
00216
00217 void QgsMapRenderer::render( QPainter* painter )
00218 {
00219
00220
00221
00222 bool mySameAsLastFlag = true;
00223
00224 QgsDebugMsg( "========== Rendering ==========" );
00225
00226 if ( mExtent.isEmpty() )
00227 {
00228 QgsDebugMsg( "empty extent... not rendering" );
00229 return;
00230 }
00231
00232 if ( mDrawing )
00233 {
00234 return;
00235 }
00236
00237 QPaintDevice* thePaintDevice = painter->device();
00238 if ( !thePaintDevice )
00239 {
00240 return;
00241 }
00242
00243 mDrawing = true;
00244
00245 QgsCoordinateTransform* ct;
00246
00247 #ifdef QGISDEBUG
00248 QgsDebugMsg( "Starting to render layer stack." );
00249 QTime renderTime;
00250 renderTime.start();
00251 #endif
00252
00253 mRenderContext.setDrawEditingInformation( !mOverview );
00254 mRenderContext.setPainter( painter );
00255 mRenderContext.setCoordinateTransform( 0 );
00256
00257
00258 mRenderContext.setRenderingStopped( false );
00259
00260
00261
00262
00263 double sceneDpi = mScaleCalculator->dpi();
00264 double scaleFactor = 1.0;
00265 if ( mOutputUnits == QgsMapRenderer::Millimeters )
00266 {
00267 scaleFactor = sceneDpi / 25.4;
00268 }
00269 double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi;
00270 if ( mRenderContext.rasterScaleFactor() != rasterScaleFactor )
00271 {
00272 mRenderContext.setRasterScaleFactor( rasterScaleFactor );
00273 mySameAsLastFlag = false;
00274 }
00275 if ( mRenderContext.scaleFactor() != scaleFactor )
00276 {
00277 mRenderContext.setScaleFactor( scaleFactor );
00278 mySameAsLastFlag = false;
00279 }
00280 if ( mRenderContext.rendererScale() != mScale )
00281 {
00282
00283 mRenderContext.setRendererScale( mScale );
00284 mySameAsLastFlag = false;
00285 }
00286 if ( mLastExtent != mExtent )
00287 {
00288 mLastExtent = mExtent;
00289 mySameAsLastFlag = false;
00290 }
00291
00292 mRenderContext.setLabelingEngine( mLabelingEngine );
00293 if ( mLabelingEngine )
00294 mLabelingEngine->init( this );
00295
00296
00297
00298 if ( !mySameAsLastFlag )
00299 {
00300
00301 QSettings mySettings;
00302 if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() )
00303 {
00304 QgsMapLayerRegistry::instance()->clearAllLayerCaches();
00305 }
00306 }
00307
00308 bool placeOverlays = false;
00309 QgsOverlayObjectPositionManager* overlayManager = overlayManagerFromSettings();
00310 QList<QgsVectorOverlay*> allOverlayList;
00311 if ( overlayManager )
00312 {
00313 placeOverlays = true;
00314 }
00315
00316
00317 QListIterator<QString> li( mLayerSet );
00318 li.toBack();
00319
00320 QgsRectangle r1, r2;
00321
00322 while ( li.hasPrevious() )
00323 {
00324 if ( mRenderContext.renderingStopped() )
00325 {
00326 break;
00327 }
00328
00329
00330
00331 QPainter * mypContextPainter = mRenderContext.painter();
00332
00333 QString layerId = li.previous();
00334
00335 QgsDebugMsg( "Rendering at layer item " + layerId );
00336
00337
00338
00339
00340
00341
00342
00343 QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" );
00344
00345
00346 QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId );
00347
00348 if ( !ml )
00349 {
00350 QgsDebugMsg( "Layer not found in registry!" );
00351 continue;
00352 }
00353
00354 QgsDebugMsg( "Rendering layer " + ml->name() );
00355 QgsDebugMsg( " Layer minscale " + QString( "%1" ).arg( ml->minimumScale() ) );
00356 QgsDebugMsg( " Layer maxscale " + QString( "%1" ).arg( ml->maximumScale() ) );
00357 QgsDebugMsg( " Scale dep. visibility enabled? " + QString( "%1" ).arg( ml->hasScaleBasedVisibility() ) );
00358 QgsDebugMsg( " Input extent: " + ml->extent().toString() );
00359
00360 if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() < mScale && mScale < ml->maximumScale() ) || mOverview )
00361 {
00362 connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
00363
00364
00365
00366
00367
00368
00369 bool split = false;
00370
00371 if ( hasCrsTransformEnabled() )
00372 {
00373 r1 = mExtent;
00374 split = splitLayersExtent( ml, r1, r2 );
00375 ct = new QgsCoordinateTransform( ml->srs(), *mDestCRS );
00376 mRenderContext.setExtent( r1 );
00377 }
00378 else
00379 {
00380 ct = NULL;
00381 }
00382
00383 mRenderContext.setCoordinateTransform( ct );
00384
00385
00386
00387 bool scaleRaster = false;
00388 QgsMapToPixel rasterMapToPixel;
00389 QgsMapToPixel bk_mapToPixel;
00390
00391 if ( ml->type() == QgsMapLayer::RasterLayer && fabs( rasterScaleFactor - 1.0 ) > 0.000001 )
00392 {
00393 scaleRaster = true;
00394 }
00395
00396
00397
00398 if ( ml->type() == QgsMapLayer::VectorLayer && overlayManager )
00399 {
00400 QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
00401 if ( vl )
00402 {
00403 QList<QgsVectorOverlay*> thisLayerOverlayList;
00404 vl->vectorOverlays( thisLayerOverlayList );
00405
00406 QList<QgsVectorOverlay*>::iterator overlayIt = thisLayerOverlayList.begin();
00407 for ( ; overlayIt != thisLayerOverlayList.end(); ++overlayIt )
00408 {
00409 if (( *overlayIt )->displayFlag() )
00410 {
00411 ( *overlayIt )->createOverlayObjects( mRenderContext );
00412 allOverlayList.push_back( *overlayIt );
00413 }
00414 }
00415
00416 overlayManager->addLayer( vl, thisLayerOverlayList );
00417 }
00418 }
00419
00420
00421
00422 if ( ml->type() == QgsMapLayer::VectorLayer )
00423 {
00424 QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
00425 if ( vl->isEditable() ||
00426 ( mRenderContext.labelingEngine() && mRenderContext.labelingEngine()->willUseLayer( vl ) ) )
00427 {
00428 ml->setCacheImage( 0 );
00429 }
00430 }
00431
00432 QSettings mySettings;
00433 if ( ! split )
00434 {
00435 if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() )
00436 {
00437 if ( !mySameAsLastFlag || ml->cacheImage() == 0 )
00438 {
00439 QgsDebugMsg( "\n\n\nCaching enabled but layer redraw forced by extent change or empty cache\n\n\n" );
00440 QImage * mypImage = new QImage( mRenderContext.painter()->device()->width(),
00441 mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
00442 mypImage->fill( 0 );
00443 ml->setCacheImage( mypImage );
00444 QPainter * mypPainter = new QPainter( ml->cacheImage() );
00445 if ( mySettings.value( "/qgis/enable_anti_aliasing", false ).toBool() )
00446 {
00447 mypPainter->setRenderHint( QPainter::Antialiasing );
00448 }
00449 mRenderContext.setPainter( mypPainter );
00450 }
00451 else if ( mySameAsLastFlag )
00452 {
00453
00454 QgsDebugMsg( "\n\n\nCaching enabled --- drawing layer from cached image\n\n\n" );
00455 mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) );
00456 disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
00457
00458 continue;
00459 }
00460 }
00461 }
00462
00463 if ( scaleRaster )
00464 {
00465 bk_mapToPixel = mRenderContext.mapToPixel();
00466 rasterMapToPixel = mRenderContext.mapToPixel();
00467 rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor );
00468 rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor );
00469 mRenderContext.setMapToPixel( rasterMapToPixel );
00470 mRenderContext.painter()->save();
00471 mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
00472 }
00473
00474
00475 if ( !ml->draw( mRenderContext ) )
00476 {
00477 emit drawError( ml );
00478 }
00479 else
00480 {
00481 QgsDebugMsg( "Layer rendered without issues" );
00482 }
00483
00484 if ( split )
00485 {
00486 mRenderContext.setExtent( r2 );
00487 if ( !ml->draw( mRenderContext ) )
00488 {
00489 emit drawError( ml );
00490 }
00491 }
00492
00493 if ( scaleRaster )
00494 {
00495 mRenderContext.setMapToPixel( bk_mapToPixel );
00496 mRenderContext.painter()->restore();
00497 }
00498
00499 if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() )
00500 {
00501 if ( !split )
00502 {
00503
00504
00505 delete mRenderContext.painter();
00506 mRenderContext.setPainter( mypContextPainter );
00507
00508 mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) );
00509 }
00510 }
00511 disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
00512 }
00513 else
00514 {
00515 QgsDebugMsg( "Layer not rendered because it is not within the defined "
00516 "visibility scale range" );
00517 }
00518
00519 }
00520
00521 QgsDebugMsg( "Done rendering map layers" );
00522
00523 if ( !mOverview )
00524 {
00525
00526 li.toBack();
00527 while ( li.hasPrevious() )
00528 {
00529 if ( mRenderContext.renderingStopped() )
00530 {
00531 break;
00532 }
00533
00534 QString layerId = li.previous();
00535
00536
00537 QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId );
00538
00539 if ( ml && ( ml->type() != QgsMapLayer::RasterLayer ) )
00540 {
00541
00542
00543 if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() < mScale && mScale < ml->maximumScale() ) )
00544 {
00545 bool split = false;
00546
00547 if ( hasCrsTransformEnabled() )
00548 {
00549 QgsRectangle r1 = mExtent;
00550 split = splitLayersExtent( ml, r1, r2 );
00551 ct = new QgsCoordinateTransform( ml->srs(), *mDestCRS );
00552 mRenderContext.setExtent( r1 );
00553 }
00554 else
00555 {
00556 ct = NULL;
00557 }
00558
00559 mRenderContext.setCoordinateTransform( ct );
00560
00561 ml->drawLabels( mRenderContext );
00562 if ( split )
00563 {
00564 mRenderContext.setExtent( r2 );
00565 ml->drawLabels( mRenderContext );
00566 }
00567 }
00568 }
00569 }
00570 }
00571
00572
00573 if ( overlayManager && allOverlayList.size() > 0 )
00574 {
00575 overlayManager->findObjectPositions( mRenderContext, mScaleCalculator->mapUnits() );
00576
00577 QList<QgsVectorOverlay*>::iterator allOverlayIt = allOverlayList.begin();
00578 for ( ; allOverlayIt != allOverlayList.end(); ++allOverlayIt )
00579 {
00580 ( *allOverlayIt )->drawOverlayObjects( mRenderContext );
00581 }
00582 overlayManager->removeLayers();
00583 }
00584
00585 delete overlayManager;
00586
00587 emit drawingProgress( 1, 1 );
00588
00589 if ( mLabelingEngine )
00590 {
00591
00592 mRenderContext.setExtent( mExtent );
00593 mRenderContext.setCoordinateTransform( NULL );
00594
00595 mLabelingEngine->drawLabeling( mRenderContext );
00596 mLabelingEngine->exit();
00597 }
00598
00599 QgsDebugMsg( "Rendering completed in (seconds): " + QString( "%1" ).arg( renderTime.elapsed() / 1000.0 ) );
00600
00601 mDrawing = false;
00602
00603 }
00604
00605 void QgsMapRenderer::setMapUnits( QGis::UnitType u )
00606 {
00607 mScaleCalculator->setMapUnits( u );
00608
00609
00610 updateScale();
00611
00612 emit mapUnitsChanged();
00613 }
00614
00615 QGis::UnitType QgsMapRenderer::mapUnits() const
00616 {
00617 return mScaleCalculator->mapUnits();
00618 }
00619
00620 void QgsMapRenderer::onDrawingProgress( int current, int total )
00621 {
00622
00623
00624 emit updateMap();
00625 }
00626
00627
00628
00629 void QgsMapRenderer::setProjectionsEnabled( bool enabled )
00630 {
00631 if ( mProjectionsEnabled != enabled )
00632 {
00633 mProjectionsEnabled = enabled;
00634 QgsDebugMsg( "Adjusting DistArea projection on/off" );
00635 mDistArea->setProjectionsEnabled( enabled );
00636 updateFullExtent();
00637 emit hasCrsTransformEnabled( enabled );
00638 }
00639 }
00640
00641 bool QgsMapRenderer::hasCrsTransformEnabled()
00642 {
00643 return mProjectionsEnabled;
00644 }
00645
00646 void QgsMapRenderer::setDestinationSrs( const QgsCoordinateReferenceSystem& srs )
00647 {
00648 QgsDebugMsg( "* Setting destCRS : = " + srs.toProj4() );
00649 QgsDebugMsg( "* DestCRS.srsid() = " + QString::number( srs.srsid() ) );
00650 if ( *mDestCRS != srs )
00651 {
00652 QgsDebugMsg( "Setting DistArea CRS to " + QString::number( srs.srsid() ) );
00653 mDistArea->setSourceCrs( srs.srsid() );
00654 *mDestCRS = srs;
00655 updateFullExtent();
00656 emit destinationSrsChanged();
00657 }
00658 }
00659
00660 const QgsCoordinateReferenceSystem& QgsMapRenderer::destinationSrs()
00661 {
00662 QgsDebugMsgLevel( "* Returning destCRS", 3 );
00663 QgsDebugMsgLevel( "* DestCRS.srsid() = " + QString::number( mDestCRS->srsid() ), 3 );
00664 QgsDebugMsgLevel( "* DestCRS.proj4() = " + mDestCRS->toProj4(), 3 );
00665 return *mDestCRS;
00666 }
00667
00668
00669 bool QgsMapRenderer::splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent, QgsRectangle& r2 )
00670 {
00671 bool split = false;
00672
00673 if ( hasCrsTransformEnabled() )
00674 {
00675 try
00676 {
00677 QgsCoordinateTransform tr( layer->srs(), *mDestCRS );
00678
00679 #ifdef QGISDEBUG
00680
00681 #endif
00682
00683
00684
00685
00686
00687 static const double splitCoord = 180.0;
00688
00689 if ( tr.sourceCrs().geographicFlag() )
00690 {
00691
00692
00693 QgsPoint ll = tr.transform( extent.xMinimum(), extent.yMinimum(),
00694 QgsCoordinateTransform::ReverseTransform );
00695
00696 QgsPoint ur = tr.transform( extent.xMaximum(), extent.yMaximum(),
00697 QgsCoordinateTransform::ReverseTransform );
00698
00699 if ( ll.x() > ur.x() )
00700 {
00701 extent.set( ll, QgsPoint( splitCoord, ur.y() ) );
00702 r2.set( QgsPoint( -splitCoord, ll.y() ), ur );
00703 split = true;
00704 }
00705 else
00706 {
00707 extent = tr.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
00708 }
00709 }
00710 else
00711 {
00712 extent = tr.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
00713 }
00714 }
00715 catch ( QgsCsException &cse )
00716 {
00717 Q_UNUSED( cse );
00718 QgsDebugMsg( "Transform error caught" );
00719 extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
00720 r2 = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
00721 }
00722 }
00723 return split;
00724 }
00725
00726
00727 QgsRectangle QgsMapRenderer::layerExtentToOutputExtent( QgsMapLayer* theLayer, QgsRectangle extent )
00728 {
00729 if ( hasCrsTransformEnabled() )
00730 {
00731 try
00732 {
00733 QgsCoordinateTransform tr( theLayer->srs(), *mDestCRS );
00734 extent = tr.transformBoundingBox( extent );
00735 }
00736 catch ( QgsCsException &cse )
00737 {
00738 Q_UNUSED( cse );
00739 QgsDebugMsg( QString( "Transform error caught: " ).arg( cse.what() ) );
00740 }
00741 }
00742 else
00743 {
00744
00745 }
00746
00747 return extent;
00748 }
00749
00750 QgsPoint QgsMapRenderer::layerToMapCoordinates( QgsMapLayer* theLayer, QgsPoint point )
00751 {
00752 if ( hasCrsTransformEnabled() )
00753 {
00754 try
00755 {
00756 QgsCoordinateTransform tr( theLayer->srs(), *mDestCRS );
00757 point = tr.transform( point, QgsCoordinateTransform::ForwardTransform );
00758 }
00759 catch ( QgsCsException &cse )
00760 {
00761 Q_UNUSED( cse );
00762 QgsDebugMsg( QString( "Transform error caught: %1" ).arg( cse.what() ) );
00763 }
00764 }
00765 else
00766 {
00767
00768 }
00769 return point;
00770 }
00771
00772 QgsPoint QgsMapRenderer::mapToLayerCoordinates( QgsMapLayer* theLayer, QgsPoint point )
00773 {
00774 if ( hasCrsTransformEnabled() )
00775 {
00776 try
00777 {
00778 QgsCoordinateTransform tr( theLayer->srs(), *mDestCRS );
00779 point = tr.transform( point, QgsCoordinateTransform::ReverseTransform );
00780 }
00781 catch ( QgsCsException &cse )
00782 {
00783 QgsDebugMsg( QString( "Transform error caught: %1" ).arg( cse.what() ) );
00784 throw cse;
00785 }
00786 }
00787 else
00788 {
00789
00790 }
00791 return point;
00792 }
00793
00794 QgsRectangle QgsMapRenderer::mapToLayerCoordinates( QgsMapLayer* theLayer, QgsRectangle rect )
00795 {
00796 if ( hasCrsTransformEnabled() )
00797 {
00798 try
00799 {
00800 QgsCoordinateTransform tr( theLayer->srs(), *mDestCRS );
00801 rect = tr.transform( rect, QgsCoordinateTransform::ReverseTransform );
00802 }
00803 catch ( QgsCsException &cse )
00804 {
00805 QgsDebugMsg( QString( "Transform error caught: %1" ).arg( cse.what() ) );
00806 throw cse;
00807 }
00808 }
00809 return rect;
00810 }
00811
00812
00813 void QgsMapRenderer::updateFullExtent()
00814 {
00815 QgsDebugMsg( "called." );
00816 QgsMapLayerRegistry* registry = QgsMapLayerRegistry::instance();
00817
00818
00819
00820 mFullExtent.setMinimal();
00821
00822
00823
00824 QStringList::iterator it = mLayerSet.begin();
00825 while ( it != mLayerSet.end() )
00826 {
00827 QgsMapLayer * lyr = registry->mapLayer( *it );
00828 if ( lyr == NULL )
00829 {
00830 QgsDebugMsg( QString( "WARNING: layer '%1' not found in map layer registry!" ).arg( *it ) );
00831 }
00832 else
00833 {
00834 QgsDebugMsg( "Updating extent using " + lyr->name() );
00835 QgsDebugMsg( "Input extent: " + lyr->extent().toString() );
00836
00837
00838
00839 QgsRectangle extent = layerExtentToOutputExtent( lyr, lyr->extent() );
00840
00841 QgsDebugMsg( "Output extent: " + extent.toString() );
00842 mFullExtent.unionRect( extent );
00843
00844 }
00845 it++;
00846 }
00847
00848 if ( mFullExtent.width() == 0.0 || mFullExtent.height() == 0.0 )
00849 {
00850
00851
00852
00853
00854 if ( mFullExtent.xMinimum() == 0.0 && mFullExtent.xMaximum() == 0.0 &&
00855 mFullExtent.yMinimum() == 0.0 && mFullExtent.yMaximum() == 0.0 )
00856 {
00857 mFullExtent.set( -1.0, -1.0, 1.0, 1.0 );
00858 }
00859 else
00860 {
00861 const double padFactor = 1e-8;
00862 double widthPad = mFullExtent.xMinimum() * padFactor;
00863 double heightPad = mFullExtent.yMinimum() * padFactor;
00864 double xmin = mFullExtent.xMinimum() - widthPad;
00865 double xmax = mFullExtent.xMaximum() + widthPad;
00866 double ymin = mFullExtent.yMinimum() - heightPad;
00867 double ymax = mFullExtent.yMaximum() + heightPad;
00868 mFullExtent.set( xmin, ymin, xmax, ymax );
00869 }
00870 }
00871
00872 QgsDebugMsg( "Full extent: " + mFullExtent.toString() );
00873 }
00874
00875 QgsRectangle QgsMapRenderer::fullExtent()
00876 {
00877 updateFullExtent();
00878 return mFullExtent;
00879 }
00880
00881 void QgsMapRenderer::setLayerSet( const QStringList& layers )
00882 {
00883 mLayerSet = layers;
00884 updateFullExtent();
00885 }
00886
00887 QStringList& QgsMapRenderer::layerSet()
00888 {
00889 return mLayerSet;
00890 }
00891
00892 QgsOverlayObjectPositionManager* QgsMapRenderer::overlayManagerFromSettings()
00893 {
00894 QSettings settings;
00895 QString overlayAlgorithmQString = settings.value( "qgis/overlayPlacementAlgorithm", "Central point" ).toString();
00896
00897 QgsOverlayObjectPositionManager* result = 0;
00898
00899 if ( overlayAlgorithmQString != "Central point" )
00900 {
00901 QgsPALObjectPositionManager* palManager = new QgsPALObjectPositionManager();
00902 if ( overlayAlgorithmQString == "Chain" )
00903 {
00904 palManager->setPlacementAlgorithm( "Chain" );
00905 }
00906 else if ( overlayAlgorithmQString == "Popmusic tabu chain" )
00907 {
00908 palManager->setPlacementAlgorithm( "Popmusic tabu chain" );
00909 }
00910 else if ( overlayAlgorithmQString == "Popmusic tabu" )
00911 {
00912 palManager->setPlacementAlgorithm( "Popmusic tabu" );
00913 }
00914 else if ( overlayAlgorithmQString == "Popmusic chain" )
00915 {
00916 palManager->setPlacementAlgorithm( "Popmusic chain" );
00917 }
00918 result = palManager;
00919 }
00920 else
00921 {
00922 result = new QgsCentralPointPositionManager();
00923 }
00924
00925 return result;
00926 }
00927
00928 bool QgsMapRenderer::readXML( QDomNode & theNode )
00929 {
00930 QDomNode myNode = theNode.namedItem( "units" );
00931 QDomElement element = myNode.toElement();
00932
00933
00934 QGis::UnitType units;
00935 if ( "meters" == element.text() )
00936 {
00937 units = QGis::Meters;
00938 }
00939 else if ( "feet" == element.text() )
00940 {
00941 units = QGis::Feet;
00942 }
00943 else if ( "degrees" == element.text() )
00944 {
00945 units = QGis::Degrees;
00946 }
00947 else if ( "unknown" == element.text() )
00948 {
00949 units = QGis::UnknownUnit;
00950 }
00951 else
00952 {
00953 QgsDebugMsg( "Unknown map unit type " + element.text() );
00954 units = QGis::Degrees;
00955 }
00956 setMapUnits( units );
00957
00958
00959
00960 QgsRectangle aoi;
00961 QDomNode extentNode = theNode.namedItem( "extent" );
00962
00963 QDomNode xminNode = extentNode.namedItem( "xmin" );
00964 QDomNode yminNode = extentNode.namedItem( "ymin" );
00965 QDomNode xmaxNode = extentNode.namedItem( "xmax" );
00966 QDomNode ymaxNode = extentNode.namedItem( "ymax" );
00967
00968 QDomElement exElement = xminNode.toElement();
00969 double xmin = exElement.text().toDouble();
00970 aoi.setXMinimum( xmin );
00971
00972 exElement = yminNode.toElement();
00973 double ymin = exElement.text().toDouble();
00974 aoi.setYMinimum( ymin );
00975
00976 exElement = xmaxNode.toElement();
00977 double xmax = exElement.text().toDouble();
00978 aoi.setXMaximum( xmax );
00979
00980 exElement = ymaxNode.toElement();
00981 double ymax = exElement.text().toDouble();
00982 aoi.setYMaximum( ymax );
00983
00984 setExtent( aoi );
00985
00986
00987 QDomNode projNode = theNode.namedItem( "projections" );
00988 element = projNode.toElement();
00989 setProjectionsEnabled( element.text().toInt() );
00990
00991
00992 QgsCoordinateReferenceSystem srs;
00993 QDomNode srsNode = theNode.namedItem( "destinationsrs" );
00994 srs.readXML( srsNode );
00995 setDestinationSrs( srs );
00996
00997 return true;
00998 }
00999
01000 bool QgsMapRenderer::writeXML( QDomNode & theNode, QDomDocument & theDoc )
01001 {
01002
01003
01004 QDomElement unitsNode = theDoc.createElement( "units" );
01005 theNode.appendChild( unitsNode );
01006
01007 QString unitsString;
01008
01009 switch ( mapUnits() )
01010 {
01011 case QGis::Meters:
01012 unitsString = "meters";
01013 break;
01014 case QGis::Feet:
01015 unitsString = "feet";
01016 break;
01017 case QGis::Degrees:
01018 unitsString = "degrees";
01019 break;
01020 case QGis::UnknownUnit:
01021 default:
01022 unitsString = "unknown";
01023 break;
01024 }
01025 QDomText unitsText = theDoc.createTextNode( unitsString );
01026 unitsNode.appendChild( unitsText );
01027
01028
01029
01030 QDomElement extentNode = theDoc.createElement( "extent" );
01031 theNode.appendChild( extentNode );
01032
01033 QDomElement xMin = theDoc.createElement( "xmin" );
01034 QDomElement yMin = theDoc.createElement( "ymin" );
01035 QDomElement xMax = theDoc.createElement( "xmax" );
01036 QDomElement yMax = theDoc.createElement( "ymax" );
01037
01038 QgsRectangle r = extent();
01039 QDomText xMinText = theDoc.createTextNode( QString::number( r.xMinimum(), 'f' ) );
01040 QDomText yMinText = theDoc.createTextNode( QString::number( r.yMinimum(), 'f' ) );
01041 QDomText xMaxText = theDoc.createTextNode( QString::number( r.xMaximum(), 'f' ) );
01042 QDomText yMaxText = theDoc.createTextNode( QString::number( r.yMaximum(), 'f' ) );
01043
01044 xMin.appendChild( xMinText );
01045 yMin.appendChild( yMinText );
01046 xMax.appendChild( xMaxText );
01047 yMax.appendChild( yMaxText );
01048
01049 extentNode.appendChild( xMin );
01050 extentNode.appendChild( yMin );
01051 extentNode.appendChild( xMax );
01052 extentNode.appendChild( yMax );
01053
01054
01055 QDomElement projNode = theDoc.createElement( "projections" );
01056 theNode.appendChild( projNode );
01057
01058 QDomText projText = theDoc.createTextNode( QString::number( hasCrsTransformEnabled() ) );
01059 projNode.appendChild( projText );
01060
01061
01062 QDomElement srsNode = theDoc.createElement( "destinationsrs" );
01063 theNode.appendChild( srsNode );
01064 destinationSrs().writeXML( srsNode, theDoc );
01065
01066 return true;
01067 }
01068
01069 void QgsMapRenderer::setLabelingEngine( QgsLabelingEngineInterface* iface )
01070 {
01071 if ( mLabelingEngine )
01072 delete mLabelingEngine;
01073
01074 mLabelingEngine = iface;
01075 }