QGIS地图分析
QgsMapCanvas:QGraphicsView
|- 成员变量:
- QGraphicsScene *mScene = nullptr;
随构造函数一起新建,管理items - QgsMapCanvasMap *mMap = nullptr;
拥有一张图片,并控制渲染。 - QgsMapRendererQImageJob *mJob = nullptr;
控制实际的渲染
QImage img = mJob->renderedImage();
mMap->setContent( img, imageRect( img, mSettings ) );
- QgsMapSettings mSettings;
包含与绘制相关的所有设置:范围、图层(QgsMapLayer)等。
渲染
QgsMapCanvas通过Timer对象控制渲染。
connect( &mMapUpdateTimer, &QTimer::timeout, this, &QgsMapCanvas::mapUpdateTimeout );
mMapUpdateTimer.setInterval( 250 );
在构造函数中将timer的超时信号连接到槽QgsMapCanvas::mapUpdateTimeout(),并设置间隔为250ms.
void QgsMapCanvas::mapUpdateTimeout()
{
if ( mJob )
{
const QImage &img = mJob->renderedImage();
mMap->setContent( img, imageRect( img, mSettings ) );
}
}
在槽函数mapUpdateTimeout()中,调用QgsMapRendererQImageJob::renderedImage()输出渲染好的Image对象,并赋值给mMap.
QgsMapRendererQImageJob::renderedImage()是个纯虚函数,分别在子类QgsMapRendererParallelJob和QgsMapRendererSequentialJob中实现。
QImage QgsMapRendererParallelJob::renderedImage()
{
// if status == Idle we are either waiting for the render to start, OR have finished the render completely.
// We can differentiate between those states by checking whether mFinalImage is null -- at the "waiting for
// render to start" state mFinalImage has not yet been created.
const bool jobIsComplete = mStatus == Idle && !mFinalImage.isNull();
if ( !jobIsComplete )
return composeImage( mSettings, mLayerJobs, mLabelJob, mCache );
else
return mFinalImage; // when rendering labels or idle
}
QImage QgsMapRendererSequentialJob::renderedImage()
{
if ( isActive() && mCache )
// this will allow immediate display of cached layers and at the same time updates of the layer being rendered
return composeImage( mSettings, mInternalJob->jobs(), LabelRenderJob() );
else
return mImage;
}
从renderedImage()的实现可知,其通过composeImage()生成QImage对象。composeImage()在QgsMapRendererJob中实现。
QImage QgsMapRendererJob::composeImage( const QgsMapSettings &settings,
const std::vector<LayerRenderJob> &jobs,
const LabelRenderJob &labelJob,
const QgsMapRendererCache *cache
)
{
QImage image( settings.deviceOutputSize(), settings.outputImageFormat() );
image.setDevicePixelRatio( settings.devicePixelRatio() );
image.setDotsPerMeterX( static_cast<int>( settings.outputDpi() * 39.37 ) );
image.setDotsPerMeterY( static_cast<int>( settings.outputDpi() * 39.37 ) );
image.fill( settings.backgroundColor().rgba() );
QPainter painter( &image );
在composeImage()中创建Image对象时,传入了QgsMapSettings::deviceOutputSize()。
QSize QgsMapSettings::deviceOutputSize() const
{
return outputSize() * mDevicePixelRatio;
}
QSize QgsMapSettings::outputSize() const
{
return mSize;
}
void QgsMapSettings::setOutputSize( QSize size )
{
mSize = size;
updateDerived();
}
由QgsMapSettings::deviceOutputSize()的实现可知,其返回的size是成员变量mSize*mDevicePixelRatio。而mSize的赋值由setOutputSize()实现。
继续回到QgsMapCanvas类,查看其调用QgsMapSettings::setOutputSize()的地方:
setOutputSize()调用.png
QSize s = viewport()->size();
mSettings.setOutputSize( s );
传入的size大小其实是QGraphicsView的大小。
再回到QgsMapSettings中对mDevicePixelRatio的使用,对其赋值是通过setDevicePixelRatio()实现:
QgsMapSettings::mDevicePixelRatio
回到QgsMapCanvas中查找对
QgsMapSettings::setDevicePixelRatio()的调用
void QgsMapCanvas::updateDevicePixelFromScreen()
{
mSettings.setDevicePixelRatio( devicePixelRatio() );
......
}
其值是有QPaintDevice::devicePixelRatio()传入。
Layers
~Layers: QgsMapLayer : QObject
MapCanvasMap : QgsMapCanvasItem : QGraphicsItem
重写paint(),利用QPainter::drawImage
ps:
图元unit : QGraphicsItem
图层Layer:QGraphicsItemGroup
地图:Map:QGraphcisScene