12       m_osmTileEdgeLengthPixel( 256 ),
 
   13       m_emptyPixel( qRgba( 0, 0, 0, 255 )),
 
   16       m_osmMapEdgeLengthPixel(),
 
   17       m_clusterEdgeLengthTiles(),
 
   18       m_mapSourceDefinitions(),
 
   26     m_clusterEdgeLengthTiles = clusterEdgeLengthTiles;
 
   31     m_mapSourceDefinitions = mapSourceDefinitions;
 
   36     m_osmBaseDirectory = osmBaseDirectory;
 
   41     m_osmTileLevel = level;
 
   42     int const osmMapEdgeLengthTiles = pow( 2, m_osmTileLevel );
 
   43     m_osmMapEdgeLengthPixel = osmMapEdgeLengthTiles * m_osmTileEdgeLengthPixel;
 
   44     qDebug() << 
"osmTileLevel:" << m_osmTileLevel
 
   45              << 
"\nosmMapEdgeLengthTiles:" << osmMapEdgeLengthTiles
 
   46              << 
"\nosmMapEdgeLengthPixel:" << m_osmMapEdgeLengthPixel;
 
   49 QDir OsmTileClusterRenderer::checkAndCreateDirectory( 
int const tileX )
 const 
   51     QDir 
const tileDirectory( m_osmBaseDirectory.path() + QString(
"/%1/%2").arg( m_osmTileLevel ).arg( tileX ));
 
   52     if ( !tileDirectory.exists() ) {
 
   53         bool const created = tileDirectory.mkpath( tileDirectory.path() );
 
   56             if ( !tileDirectory.exists() )
 
   57                 qFatal(
"Unable to create directory '%s'.", tileDirectory.path().toStdString().c_str() );
 
   65     QVector<ReadOnlyMapDefinition>::const_iterator pos = m_mapSourceDefinitions.begin();
 
   66     QVector<ReadOnlyMapDefinition>::const_iterator 
const end = m_mapSourceDefinitions.end();
 
   67     for (; pos != end; ++pos )
 
   71             qFatal(
"Invalid map source definition.");
 
   72         m_mapSources.push_back( mapImage );
 
   74     m_mapSourceCount = m_mapSources.count();
 
   79     qDebug() << objectName() << 
"rendering clusterX:" << clusterX << 
", clusterY:" << clusterY;
 
   80     int tilesRenderedCount = 0;
 
   83     int const tileX1 = clusterX * m_clusterEdgeLengthTiles;
 
   84     int const tileX2 = tileX1 + m_clusterEdgeLengthTiles;
 
   85     int const tileY1 = clusterY * m_clusterEdgeLengthTiles;
 
   86     int const tileY2 = tileY1 + m_clusterEdgeLengthTiles;
 
   88     for ( 
int tileX = tileX1; tileX < tileX2; ++tileX ) {
 
   89         QDir 
const tileDirectory = checkAndCreateDirectory( tileX );
 
   90         for ( 
int tileY = tileY1; tileY < tileY2; ++tileY ) {
 
   91             QImage 
const osmTile = renderOsmTile( tileX, tileY );
 
   94             if ( osmTile.isNull() )
 
   97             QString 
const filename = tileDirectory.path() + QString( 
"/%1.png" ).arg( tileY );
 
   98             bool const saved = osmTile.save( filename );
 
  100                 ++tilesRenderedCount;
 
  102                 qFatal(
"Unable to save tile '%s'.", filename.toStdString().c_str() );
 
  105     int const durationMs = t.elapsed();
 
  106     qDebug() << objectName() << 
"clusterX:" <<clusterX << 
", clusterY:" << clusterY
 
  107              << 
"rendered:" << tilesRenderedCount << 
"tiles in" << durationMs << 
"ms =>" 
  108              << 
static_cast<double>( tilesRenderedCount ) * 1000.0 / static_cast<double>( durationMs ) << 
"tiles/s";
 
  112 QImage OsmTileClusterRenderer::renderOsmTile( 
int const tileX, 
int const tileY )
 
  115     int const basePixelX = tileX * m_osmTileEdgeLengthPixel;
 
  116     int const basePixelY = tileY * m_osmTileEdgeLengthPixel;
 
  118     QSize 
const tileSize( m_osmTileEdgeLengthPixel, m_osmTileEdgeLengthPixel );
 
  119     QImage tile( tileSize, QImage::Format_ARGB32 );
 
  120     bool tileEmpty = 
true;
 
  122     for ( 
int y = 0; y < m_osmTileEdgeLengthPixel; ++y ) {
 
  123         int const pixelY = basePixelY + y;
 
  124         double const latRad = osmPixelYtoLatRad( pixelY );
 
  126         for ( 
int x = 0; x < m_osmTileEdgeLengthPixel; ++x ) {
 
  127             int const pixelX = basePixelX + x;
 
  128             double const lonRad = osmPixelXtoLonRad( pixelX );
 
  130             QRgb color = m_emptyPixel;
 
  131             for (
int i = 0; i < m_mapSourceCount; ++i)
 
  133                color = m_mapSources[i]->pixel( lonRad, latRad );
 
  134                if ( color != m_emptyPixel ) {
 
  140             tile.setPixel( x, y, color );
 
  143     return tileEmpty ? QImage() : tile;
 
  146 inline double OsmTileClusterRenderer::osmPixelXtoLonRad( 
int const pixelX )
 const 
  148     double const pixelXd = 
static_cast<double>( pixelX );
 
  149     double const osmMapEdgeLengthPixeld = 
static_cast<double>( m_osmMapEdgeLengthPixel );
 
  150     return pixelXd * 2.0 * 
M_PI / osmMapEdgeLengthPixeld - 
M_PI;
 
  153 inline double OsmTileClusterRenderer::osmPixelYtoLatRad( 
int const pixelY )
 const 
  155     double const pixelYd = 
static_cast<double>( pixelY );
 
  156     double const osmMapEdgeLengthPixeld = 
static_cast<double>( m_osmMapEdgeLengthPixel );
 
  157     return -atan( sinh(( pixelYd - 0.5 * osmMapEdgeLengthPixeld ) * 2.0 * 
M_PI / osmMapEdgeLengthPixeld ));
 
  160 #include "OsmTileClusterRenderer.moc" 
void setOsmTileLevel(int const level)
 
void clusterRendered(OsmTileClusterRenderer *)
 
void setOsmBaseDirectory(QDir const &osmBaseDirectory)
 
OsmTileClusterRenderer(QObject *const parent=NULL)
 
void setMapSources(QVector< ReadOnlyMapDefinition > const &mapSources)
 
void renderOsmTileCluster(int const clusterX, int const clusterY)
 
void setClusterEdgeLengthTiles(int const clusterEdgeLengthTiles)