25 #define GZIP_WINDOWS_BIT 15 + 16 
   26 #define GZIP_CHUNK_SIZE 32 * 1024 
   40   if ( input.isEmpty() )
 
   49   strm.next_in = Z_NULL;
 
   58   const char *input_data = input.constData();
 
   59   int input_data_left = input.length();
 
   68     if ( chunk_size <= 0 )
 
   72     strm.next_in = ( 
unsigned char * )input_data;
 
   73     strm.avail_in = chunk_size;
 
   76     input_data += chunk_size;
 
   77     input_data_left -= chunk_size;
 
   87       strm.next_out = ( 
unsigned char * )out;
 
   91       ret = inflate( &strm, Z_NO_FLUSH );
 
  112         output.append( ( 
char * )out, have );
 
  115     while ( strm.avail_out == 0 );
 
  118   while ( ret != Z_STREAM_END );
 
  124   return ( ret == Z_STREAM_END );
 
  130   for ( 
int i = 0; i < count; ++i )
 
  132     quint16 encoded = *( quint16 * ) dataPtr;
 
  134     qint16 decoded = ( encoded >> 1 ) ^ ( -( encoded & 1 ) );
 
  141 static QString _tileFilename( 
int tx, 
int ty, 
int tz )
 
  143   return QString( 
"/tmp/terrain-%1-%2-%3" ).arg( tz ).arg( tx ).arg( ty );
 
  148   QString filename = _tileFilename( tx, ty, tz );
 
  150   if ( !f.open( QIODevice::ReadOnly ) )
 
  157   if ( data.isEmpty() )
 
  163   const char *dataPtr = data.constData();
 
  178   quint32 vertexCount = *( quint32 * ) dataPtr;
 
  180   t->
uvh.resize( 3 * vertexCount );
 
  181   qint16 *vptr = t->
uvh.data();
 
  184   qint16 u = 0, v = 0, h = 0;
 
  185   for ( uint i = 0; i < vertexCount; ++i )
 
  187     qint16 du = vptr[i], dv = vptr[vertexCount + i], dh = vptr[vertexCount * 2 + i];
 
  192     vptr[vertexCount + i] = v;
 
  193     vptr[vertexCount * 2 + i] = h;
 
  196   Q_ASSERT( vertexCount < 65537 ); 
 
  207   quint32 triangleCount = *( quint32 * ) dataPtr;
 
  209   t->
indices.resize( 3 * triangleCount );
 
  210   quint16 *indicesPtr = t->
indices.data();
 
  211   quint16 *srcIdxPtr = ( quint16 * )dataPtr;
 
  213   for ( uint i = 0; i < triangleCount * 3; ++i )
 
  215     quint16 code = *srcIdxPtr++;
 
  216     *indicesPtr++ = highest - code;
 
  233 #include <QGuiApplication> 
  234 #include <QNetworkRequest> 
  235 #include <QNetworkReply> 
  242   QString tileFilename = _tileFilename( tx, ty, tz );
 
  243   if ( !QFile::exists( tileFilename ) )
 
  245     qDebug() << 
"downloading tile " << tx << 
" " << ty << 
" " << tz;
 
  246     bool downloaded = 
false;
 
  247     QString url = QString( 
"http://assets.agi.com/stk-terrain/tilesets/world/tiles/%1/%2/%3.terrain" ).arg( tz ).arg( tx ).arg( ty );
 
  248     QNetworkRequest request( url );
 
  249     request.setRawHeader( QByteArray( 
"Accept-Encoding" ), QByteArray( 
"gzip" ) );
 
  250     request.setRawHeader( QByteArray( 
"Accept" ), QByteArray( 
"application/vnd.quantized-mesh,application/octet-stream;q=0.9" ) );
 
  251     request.setRawHeader( QByteArray( 
"User-Agent" ), QByteArray( 
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/58.0.3029.110 Chrome/58.0.3029.110 Safari/537.36" ) );
 
  253     connect( reply, &QNetworkReply::finished, [reply, tileFilename, &downloaded]
 
  255       QFile fOut( tileFilename );
 
  256       fOut.open( QIODevice::WriteOnly );
 
  257       fOut.write( reply->readAll() );
 
  259       reply->deleteLater();
 
  263     while ( !downloaded )
 
  265       qApp->processEvents();
 
  277   : QGeometry( parent )
 
  279   int vertexCount = t->
uvh.count() / 3;
 
  280   int indexCount = t->
indices.count();
 
  282   int vertexEntrySize = 
sizeof( float ) * ( 3 + 2 );
 
  291   const qint16 *uvh = t->
uvh.constData();
 
  292   vb.resize( vertexCount * vertexEntrySize );
 
  293   float *vbptr = ( 
float * ) vb.data();
 
  294   for ( 
int i = 0; i < vertexCount; ++i )
 
  296     qint16 u = uvh[i], v = uvh[vertexCount + i], h = uvh[vertexCount * 2 + i];
 
  297     float uNorm = u / 32767.f;  
 
  298     float vNorm = v / 32767.f;  
 
  299     float hNorm = h / 32767.f;  
 
  300     float xWgs = xMinWgs + widthWgs * uNorm;
 
  301     float yWgs = yMinWgs + heightWgs * vNorm;
 
  305     QgsPointXY ptFinal( ptProjected.x() - ptMinProjected.
x(), ptProjected.y() - ptMinProjected.
y() );
 
  308     *vbptr++ = ptFinal.
x();
 
  310     *vbptr++ = -ptFinal.
y();
 
  319   ib.resize( indexCount * 2 );
 
  320   memcpy( ib.data(), t->
indices.constData(), ib.count() );
 
  332 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) 
  333   m_vertexBuffer = 
new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, 
this );
 
  334   m_indexBuffer = 
new Qt3DRender::QBuffer( Qt3DRender::QBuffer::IndexBuffer, 
this );
 
  336   m_vertexBuffer = 
new Qt3DRender::QBuffer( 
this );
 
  337   m_indexBuffer = 
new Qt3DRender::QBuffer( 
this );
 
  340   m_vertexBuffer->setData( vb );
 
  341   m_indexBuffer->setData( ib );
 
  343   m_positionAttribute = 
new Qt3DRender::QAttribute( 
this );
 
  344   m_positionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
 
  345 #if QT_VERSION >= 0x050800 
  346   m_positionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
  347   m_positionAttribute->setVertexSize( 3 );
 
  349   m_positionAttribute->setDataType( Qt3DRender::QAttribute::Float );
 
  350   m_positionAttribute->setDataSize( 3 );
 
  352   m_positionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
  353   m_positionAttribute->setBuffer( m_vertexBuffer );
 
  354   m_positionAttribute->setByteStride( vertexEntrySize );
 
  355   m_positionAttribute->setCount( vertexCount );
 
  357   m_texCoordAttribute = 
new Qt3DRender::QAttribute( 
this );
 
  358   m_texCoordAttribute->setName( Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName() );
 
  359 #if QT_VERSION >= 0x050800 
  360   m_texCoordAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
  361   m_texCoordAttribute->setVertexSize( 2 );
 
  363   m_texCoordAttribute->setDataType( Qt3DRender::QAttribute::Float );
 
  364   m_texCoordAttribute->setDataSize( 2 );
 
  366   m_texCoordAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
  367   m_texCoordAttribute->setBuffer( m_vertexBuffer );
 
  368   m_texCoordAttribute->setByteStride( vertexEntrySize );
 
  369   m_texCoordAttribute->setByteOffset( 3 * 
sizeof( 
float ) );
 
  370   m_texCoordAttribute->setCount( vertexCount );
 
  372   m_indexAttribute = 
new Qt3DRender::QAttribute( 
this );
 
  373   m_indexAttribute->setAttributeType( Qt3DRender::QAttribute::IndexAttribute );
 
  374 #if QT_VERSION >= 0x050800 
  375   m_indexAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedShort );
 
  377   m_indexAttribute->setDataType( Qt3DRender::QAttribute::UnsignedShort );
 
  379   m_indexAttribute->setBuffer( m_indexBuffer );
 
  380   m_indexAttribute->setCount( indexCount );
 
  382   addAttribute( m_positionAttribute );
 
  383   addAttribute( m_texCoordAttribute );
 
  384   addAttribute( m_indexAttribute );
 
Perform transforms between map coordinates and device coordinates.
QgsPointXY transform(const QgsPointXY &p) const
Transform the point p from map (world) coordinates to device coordinates.
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
A class to represent a 2D point.
A rectangle specified with double values.
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
static void downloadTileIfMissing(int tx, int ty, int tz)
Downloads a tile to to a file in the local disk cache.
QuantizedMeshGeometry(QuantizedMeshTile *t, const Map3D &map, const QgsMapToPixel &mapToPixel, const QgsCoordinateTransform &terrainToMap, QNode *parent=nullptr)
Constructs geometry based on the loaded tile data.
static QuantizedMeshTile * readTile(int tx, int ty, int tz, const QgsRectangle &extent)
Reads a tile from a file in the local disk cache.
bool gzipDecompress(QByteArray input, QByteArray &output)
Decompresses the given buffer using the standard GZIP algorithm.
const char * read_zigzag_encoded_int16_array(const char *dataPtr, int count, qint16 *out)
QVector< quint16 > indices
QuantizedMeshHeader header