23 #include "lazperf/readers.hpp" 
   31   if ( mVersion.first == 1 && mVersion.second == 4 )
 
   33   if ( mVersion.first == 1 && mVersion.second == 3 )
 
   35   if ( mVersion.first == 1 && mVersion.second <= 2 )
 
   43   if ( std::string( data, 4 ) != 
"LASF" )
 
   45     mError = QStringLiteral( 
"Supplied header is not from a LAZ file" );
 
   49   std::istringstream file( std::string( data, length ) );
 
   50   lazperf::header14 
header = lazperf::header14::create( file );
 
   58   uint64_t currentOffset = 0;
 
   59   for ( uint64_t i = 0; i < ( uint64_t )mVlrCount && currentOffset < length; ++i )
 
   61     lazperf::vlr_header vlrHeader;
 
   62     vlrHeader.fill( data + currentOffset, 54 );
 
   65     vlr.
userId = QString::fromStdString( vlrHeader.user_id );
 
   67     vlr.
data = QByteArray( data + currentOffset + 54, vlrHeader.data_length );
 
   68     mVlrVector.push_back( vlr );
 
   69     currentOffset += 54 + vlrHeader.data_length;
 
   73   parseExtrabyteAttributes();
 
   77 void QgsLazInfo::parseHeader( lazperf::header14 &header )
 
   83   mCreationYearDay = QPair<uint16_t, uint16_t>( 
header.creation.year, 
header.creation.day );
 
   84   mVersion = QPair<uint8_t, uint8_t>( 
header.version.major, 
header.version.minor );
 
   85   mPointFormat = 
header.pointFormat();
 
   87   mProjectId = QString( QByteArray( 
header.guid, 16 ).toHex() );
 
   88   mSystemId = QString::fromLocal8Bit( 
header.system_identifier, 32 );
 
   89   while ( !mSystemId.isEmpty() && mSystemId.back() == 
'\0' )
 
   91     mSystemId.remove( mSystemId.size() - 1, 1 );
 
   93   mSoftwareId = QString::fromLocal8Bit( 
header.generating_software, 32 ).trimmed();
 
   94   while ( !mSoftwareId.isEmpty() && mSoftwareId.back() == 
'\0' )
 
   96     mSoftwareId.remove( mSoftwareId.size() - 1, 1 );
 
  102   mVlrCount = 
header.vlr_count;
 
  104   parseLazAttributes();
 
  108 void QgsLazInfo::parseCrs()
 
  111   for ( LazVlr &vlr : mVlrVector )
 
  113     if ( vlr.userId.trimmed() == QLatin1String( 
"LASF_Projection" ) && vlr.recordId == 2112 )
 
  123   QVariantMap metadata;
 
  124   metadata[ QStringLiteral( 
"creation_year" ) ] = mHeader.creation.year;
 
  125   metadata[ QStringLiteral( 
"creation_day" ) ] = mHeader.creation.day;
 
  126   metadata[ QStringLiteral( 
"major_version" ) ] = mHeader.version.major;
 
  127   metadata[ QStringLiteral( 
"minor_version" ) ] = mHeader.version.minor;
 
  128   metadata[ QStringLiteral( 
"dataformat_id" ) ] = mHeader.pointFormat();
 
  129   metadata[ QStringLiteral( 
"scale_x" ) ] = mScale.
x();
 
  130   metadata[ QStringLiteral( 
"scale_y" ) ] = mScale.
y();
 
  131   metadata[ QStringLiteral( 
"scale_z" ) ] = mScale.
z();
 
  132   metadata[ QStringLiteral( 
"offset_x" ) ] = mOffset.
x();
 
  133   metadata[ QStringLiteral( 
"offset_y" ) ] = mOffset.
y();
 
  134   metadata[ QStringLiteral( 
"offset_z" ) ] = mOffset.
z();
 
  135   metadata[ QStringLiteral( 
"project_id" ) ] = QString( QByteArray( mHeader.guid, 16 ).toHex() );
 
  136   metadata[ QStringLiteral( 
"system_id" ) ] = QString::fromLocal8Bit( mHeader.system_identifier, 32 );
 
  137   metadata[ QStringLiteral( 
"software_id" ) ] = QString::fromLocal8Bit( mHeader.generating_software, 32 );
 
  143   for ( 
LazVlr vlr : mVlrVector )
 
  145     if ( vlr.userId == userId && vlr.recordId == recordId )
 
  153 void QgsLazInfo::parseLazAttributes()
 
  155   if ( mPointFormat < 0 || mPointFormat > 10 )
 
  157     QgsDebugMsgLevel( QStringLiteral( 
"Invalid point record format %1" ).arg( mPointFormat ), 2 );
 
  173   if ( mPointFormat == 6 || mPointFormat == 7 || mPointFormat == 8 || mPointFormat == 9 || mPointFormat == 10 )
 
  178   if ( mPointFormat != 0 && mPointFormat != 2 )
 
  182   if ( mPointFormat == 2 || mPointFormat == 3 || mPointFormat == 5 || mPointFormat == 7 || mPointFormat == 8 || mPointFormat == 10 )
 
  188   if ( mPointFormat == 8 || mPointFormat == 10 )
 
  195 void QgsLazInfo::parseExtrabyteAttributes()
 
  197   QByteArray ebVlrRaw = 
vlrData( 
"LASF_Spec", 4 );
 
  208   QVector<QgsLazInfo::ExtraBytesAttributeDetails> extrabyteAttributes;
 
  209   lazperf::eb_vlr ebVlr;
 
  210   ebVlr.fill( rawData, length );
 
  211   for ( std::vector<lazperf::eb_vlr::ebfield>::reverse_iterator it = ebVlr.items.rbegin(); it != ebVlr.items.rend(); ++it )
 
  213     lazperf::eb_vlr::ebfield &
field = *it;
 
  216     switch ( 
field.data_type )
 
  267     int accOffset = ( extrabyteAttributes.empty() ? 
pointRecordLength : extrabyteAttributes.back().offset ) - ebAtrr.
size;
 
  268     ebAtrr.
offset = accOffset;
 
  269     extrabyteAttributes.push_back( ebAtrr );
 
  271   return extrabyteAttributes;
 
  278   char headerRawData[ 375 ];
 
  280   file.read( headerRawData, 375 );
 
  284   std::unique_ptr<char[]> vlrEntriesRawData( 
new char[ vlrDataSize ] );
 
  286   file.read( vlrEntriesRawData.get(), vlrDataSize );
 
  298     lazInfo.mError = QStringLiteral( 
"The server of submitted URL doesn't support range queries" );
 
  304     QNetworkRequest nr( url );
 
  305     nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork );
 
  306     nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute, 
false );
 
  307     nr.setRawHeader( 
"Range", 
"bytes=0-374" );
 
  312       QgsDebugMsg( QStringLiteral( 
"Request failed: " ) + url.toString() );
 
  313       lazInfo.mError = QStringLiteral( 
"Range query 0-374 to \"%1\" failed: \"%2\"" ).arg( url.toString() ).arg( req.
errorMessage() );
 
  318     QByteArray lazHeaderData = reply.
content();
 
  320     lazInfo.
parseRawHeader( lazHeaderData.data(), lazHeaderData.size() );
 
  325     QNetworkRequest nr( url );
 
  326     nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork );
 
  327     nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute, 
false );
 
  329     QByteArray vlrRequestRange = QStringLiteral( 
"bytes=%1-%2" ).arg( firstVlrOffset ).arg( lazInfo.
firstPointRecordOffset() - 1 ).toLocal8Bit();
 
  330     nr.setRawHeader( 
"Range", vlrRequestRange );
 
  335       QgsDebugMsg( QStringLiteral( 
"Request failed: " ) + url.toString() );
 
  337       lazInfo.mError = QStringLiteral( 
"Range query %1-%2 to \"%3\" failed: \"%4\"" ).arg( firstVlrOffset ).arg( lazInfo.
firstPointRecordOffset() - 1 )
 
  351   QNetworkRequest nr( url );
 
  352   nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork );
 
  353   nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute, 
false );
 
  354   nr.setRawHeader( 
"Range", 
"bytes=0-0" );
 
  358   const QList<QgsNetworkReplyContent::RawHeaderPair> pairs = reply.
rawHeaderPairs();
 
  359   bool acceptsRanges = 
false;
 
  360   for ( 
const auto &pair : pairs )
 
  362     if ( QString::fromLocal8Bit( pair.first ).compare( QStringLiteral( 
"Accept-Ranges" ), Qt::CaseInsensitive ) == 0 &&
 
  363          QString::fromLocal8Bit( pair.second ).compare( QStringLiteral( 
"bytes" ), Qt::CaseInsensitive ) == 0 )
 
  365       acceptsRanges = 
true;