Skip to content

Commit 7faea46

Browse files
NEDJIMAbelgacemwonder-sk
authored andcommittedMar 31, 2022
- Add tests for COPC
- Address some of Martin's reviews
1 parent 458748c commit 7faea46

15 files changed

+710
-113
lines changed
 

‎CMakeLists.txt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -411,21 +411,19 @@ if(WITH_CORE)
411411
message(STATUS "Qt WebKit support DISABLED.")
412412
endif()
413413

414-
if (WITH_EPT) # EPT provider
415-
find_package(ZSTD REQUIRED) # for decompression of point clouds
414+
if (WITH_EPT OR WITH_COPC)
416415
find_package(LazPerf) # for decompression of point clouds
417416
if (NOT LazPerf_FOUND)
418417
message(STATUS "Using embedded laz-perf")
419418
endif()
419+
endif()
420+
421+
if (WITH_EPT) # EPT provider
422+
find_package(ZSTD REQUIRED) # for decompression of point clouds
420423
set(HAVE_EPT TRUE) # used in qgsconfig.h
421424
endif()
422425

423426
if (WITH_COPC) # COPC provider
424-
find_package(ZSTD REQUIRED) # for decompression of point clouds
425-
find_package(LazPerf) # for decompression of point clouds
426-
if (NOT LazPerf_FOUND)
427-
message(STATUS "Using embedded laz-perf")
428-
endif()
429427
set(HAVE_COPC TRUE) # used in qgsconfig.h
430428
endif()
431429

‎src/core/CMakeLists.txt

Lines changed: 35 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,43 +1929,13 @@ if (WITH_EPT)
19291929
${ZSTD_INCLUDE_DIR}
19301930
)
19311931

1932-
if (LazPerf_FOUND)
1933-
# Use system laz-perf
1934-
include_directories(SYSTEM
1935-
${LazPerf_INCLUDE_DIR}
1936-
)
1937-
else()
1938-
# Use embedded laz-perf from external/laz-perf
1939-
include_directories(SYSTEM
1940-
)
1941-
1942-
set(QGIS_CORE_SRCS ${QGIS_CORE_SRCS}
1943-
${CMAKE_SOURCE_DIR}/external/lazperf/charbuf.cpp
1944-
${CMAKE_SOURCE_DIR}/external/lazperf/filestream.cpp
1945-
${CMAKE_SOURCE_DIR}/external/lazperf/header.cpp
1946-
${CMAKE_SOURCE_DIR}/external/lazperf/lazperf.cpp
1947-
${CMAKE_SOURCE_DIR}/external/lazperf/readers.cpp
1948-
${CMAKE_SOURCE_DIR}/external/lazperf/vlr.cpp
1949-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_byte10.cpp
1950-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_byte14.cpp
1951-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_gpstime10.cpp
1952-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_nir14.cpp
1953-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_point10.cpp
1954-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_point14.cpp
1955-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_rgb10.cpp
1956-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_rgb14.cpp
1957-
)
1958-
endif()
1959-
19601932
set(QGIS_CORE_SRCS ${QGIS_CORE_SRCS}
19611933
providers/ept/qgseptprovider.cpp
1962-
pointcloud/qgseptdecoder.cpp
19631934
pointcloud/qgseptpointcloudindex.cpp
19641935
pointcloud/qgsremoteeptpointcloudindex.cpp
19651936
)
19661937
set(QGIS_CORE_HDRS ${QGIS_CORE_HDRS}
19671938
providers/ept/qgseptprovider.h
1968-
pointcloud/qgseptdecoder.h
19691939
pointcloud/qgseptpointcloudindex.h
19701940
pointcloud/qgsremoteeptpointcloudindex.h
19711941
)
@@ -1976,50 +1946,53 @@ endif()
19761946
if (WITH_COPC)
19771947
include_directories(providers/copc)
19781948

1979-
include_directories(SYSTEM
1980-
${ZSTD_INCLUDE_DIR}
1949+
set(QGIS_CORE_SRCS ${QGIS_CORE_SRCS}
1950+
providers/copc/qgscopcprovider.cpp
1951+
pointcloud/qgscopcpointcloudindex.cpp
19811952
)
1953+
set(QGIS_CORE_HDRS ${QGIS_CORE_HDRS}
1954+
providers/copc/qgscopcprovider.h
1955+
pointcloud/qgscopcpointcloudindex.h
1956+
)
1957+
1958+
add_definitions( -DWITH_COPC )
1959+
endif()
19821960

1961+
if (WITH_EPT OR WITH_COPC)
19831962
if (LazPerf_FOUND)
1984-
# Use system laz-perf
1985-
include_directories(SYSTEM
1986-
${LazPerf_INCLUDE_DIR}
1987-
)
1963+
# Use system laz-perf
1964+
include_directories(SYSTEM
1965+
${LazPerf_INCLUDE_DIR}
1966+
)
19881967
else()
1989-
# Use embedded laz-perf from external/laz-perf
1990-
include_directories(SYSTEM
1991-
)
1968+
# Use embedded laz-perf from external/laz-perf
1969+
include_directories(SYSTEM
1970+
)
19921971

1993-
set(QGIS_CORE_SRCS ${QGIS_CORE_SRCS}
1994-
${CMAKE_SOURCE_DIR}/external/lazperf/charbuf.cpp
1995-
${CMAKE_SOURCE_DIR}/external/lazperf/filestream.cpp
1996-
${CMAKE_SOURCE_DIR}/external/lazperf/header.cpp
1997-
${CMAKE_SOURCE_DIR}/external/lazperf/lazperf.cpp
1998-
${CMAKE_SOURCE_DIR}/external/lazperf/readers.cpp
1999-
${CMAKE_SOURCE_DIR}/external/lazperf/vlr.cpp
2000-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_byte10.cpp
2001-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_byte14.cpp
2002-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_gpstime10.cpp
2003-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_nir14.cpp
2004-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_point10.cpp
2005-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_point14.cpp
2006-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_rgb10.cpp
2007-
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_rgb14.cpp
2008-
)
1972+
set(QGIS_CORE_SRCS ${QGIS_CORE_SRCS}
1973+
${CMAKE_SOURCE_DIR}/external/lazperf/charbuf.cpp
1974+
${CMAKE_SOURCE_DIR}/external/lazperf/filestream.cpp
1975+
${CMAKE_SOURCE_DIR}/external/lazperf/header.cpp
1976+
${CMAKE_SOURCE_DIR}/external/lazperf/lazperf.cpp
1977+
${CMAKE_SOURCE_DIR}/external/lazperf/readers.cpp
1978+
${CMAKE_SOURCE_DIR}/external/lazperf/vlr.cpp
1979+
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_byte10.cpp
1980+
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_byte14.cpp
1981+
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_gpstime10.cpp
1982+
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_nir14.cpp
1983+
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_point10.cpp
1984+
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_point14.cpp
1985+
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_rgb10.cpp
1986+
${CMAKE_SOURCE_DIR}/external/lazperf/detail/field_rgb14.cpp
1987+
)
20091988
endif()
20101989

20111990
set(QGIS_CORE_SRCS ${QGIS_CORE_SRCS}
2012-
providers/copc/qgscopcprovider.cpp
20131991
pointcloud/qgseptdecoder.cpp
2014-
pointcloud/qgscopcpointcloudindex.cpp
20151992
)
20161993
set(QGIS_CORE_HDRS ${QGIS_CORE_HDRS}
2017-
providers/copc/qgscopcprovider.h
20181994
pointcloud/qgseptdecoder.h
2019-
pointcloud/qgscopcpointcloudindex.h
20201995
)
2021-
2022-
add_definitions( -DWITH_COPC )
20231996
endif()
20241997

20251998
if (APPLE)
@@ -2278,15 +2251,9 @@ if (WITH_EPT)
22782251
target_link_libraries(qgis_core
22792252
${ZSTD_LIBRARY}
22802253
)
2281-
if (LazPerf_FOUND)
2282-
target_link_libraries(qgis_core ${LazPerf_LIBRARY})
2283-
endif()
22842254
endif()
22852255

2286-
if (WITH_COPC)
2287-
target_link_libraries(qgis_core
2288-
${ZSTD_LIBRARY}
2289-
)
2256+
if (WITH_EPT OR WITH_COPC)
22902257
if (LazPerf_FOUND)
22912258
target_link_libraries(qgis_core ${LazPerf_LIBRARY})
22922259
endif()

‎src/core/pointcloud/qgscopcpointcloudindex.cpp

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@
1717

1818
#include "qgscopcpointcloudindex.h"
1919
#include <QFile>
20-
#include <QFileInfo>
21-
#include <QDir>
22-
#include <QJsonArray>
23-
#include <QJsonDocument>
24-
#include <QJsonObject>
25-
#include <QTime>
2620
#include <QtDebug>
2721
#include <QQueue>
2822

@@ -100,22 +94,20 @@ bool QgsCopcPointCloudIndex::loadSchema( const QString &filename )
10094
// Attributes for COPC format
10195
// COPC supports only PDRF 6, 7 and 8
10296

103-
// TODO: How to handle bitfields in LAZ
104-
10597
QgsPointCloudAttributeCollection attributes;
106-
attributes.push_back( QgsPointCloudAttribute( "X", ( QgsPointCloudAttribute::DataType ) 9 ) );
107-
attributes.push_back( QgsPointCloudAttribute( "Y", ( QgsPointCloudAttribute::DataType ) 9 ) );
108-
attributes.push_back( QgsPointCloudAttribute( "Z", ( QgsPointCloudAttribute::DataType ) 9 ) );
109-
attributes.push_back( QgsPointCloudAttribute( "Classification", ( QgsPointCloudAttribute::DataType ) 0 ) );
110-
attributes.push_back( QgsPointCloudAttribute( "Intensity", ( QgsPointCloudAttribute::DataType ) 3 ) );
111-
attributes.push_back( QgsPointCloudAttribute( "ReturnNumber", ( QgsPointCloudAttribute::DataType ) 0 ) );
112-
attributes.push_back( QgsPointCloudAttribute( "NumberOfReturns", ( QgsPointCloudAttribute::DataType ) 0 ) );
113-
attributes.push_back( QgsPointCloudAttribute( "ScanDirectionFlag", ( QgsPointCloudAttribute::DataType ) 0 ) );
114-
attributes.push_back( QgsPointCloudAttribute( "EdgeOfFlightLine", ( QgsPointCloudAttribute::DataType ) 0 ) );
115-
attributes.push_back( QgsPointCloudAttribute( "ScanAngleRank", ( QgsPointCloudAttribute::DataType ) 8 ) );
116-
attributes.push_back( QgsPointCloudAttribute( "UserData", ( QgsPointCloudAttribute::DataType ) 0 ) );
117-
attributes.push_back( QgsPointCloudAttribute( "PointSourceId", ( QgsPointCloudAttribute::DataType ) 3 ) );
118-
attributes.push_back( QgsPointCloudAttribute( "GpsTime", ( QgsPointCloudAttribute::DataType ) 9 ) );
98+
attributes.push_back( QgsPointCloudAttribute( "X", QgsPointCloudAttribute::Int32 ) );
99+
attributes.push_back( QgsPointCloudAttribute( "Y", QgsPointCloudAttribute::Int32 ) );
100+
attributes.push_back( QgsPointCloudAttribute( "Z", QgsPointCloudAttribute::Int32 ) );
101+
attributes.push_back( QgsPointCloudAttribute( "Intensity", QgsPointCloudAttribute::UShort ) );
102+
attributes.push_back( QgsPointCloudAttribute( "ReturnNumber", QgsPointCloudAttribute::Char ) );
103+
attributes.push_back( QgsPointCloudAttribute( "NumberOfReturns", QgsPointCloudAttribute::Char ) );
104+
attributes.push_back( QgsPointCloudAttribute( "ScanDirectionFlag", QgsPointCloudAttribute::Char ) );
105+
attributes.push_back( QgsPointCloudAttribute( "EdgeOfFlightLine", QgsPointCloudAttribute::Char ) );
106+
attributes.push_back( QgsPointCloudAttribute( "Classification", QgsPointCloudAttribute::Char ) );
107+
attributes.push_back( QgsPointCloudAttribute( "ScanAngleRank", QgsPointCloudAttribute::Short ) );
108+
attributes.push_back( QgsPointCloudAttribute( "UserData", QgsPointCloudAttribute::Char ) );
109+
attributes.push_back( QgsPointCloudAttribute( "PointSourceId", QgsPointCloudAttribute::UShort ) );
110+
attributes.push_back( QgsPointCloudAttribute( "GpsTime", QgsPointCloudAttribute::Double ) );
119111

120112
switch ( f.header().point_format_id )
121113
{
@@ -136,7 +128,11 @@ bool QgsCopcPointCloudIndex::loadSchema( const QString &filename )
136128
return false;
137129
}
138130

139-
// TODO: add extrabyte attributes
131+
QVector<QgsEptDecoder::ExtraBytesAttributeDetails> extrabyteAttributes = QgsEptDecoder::readExtraByteAttributes( file );
132+
for ( QgsEptDecoder::ExtraBytesAttributeDetails attr : extrabyteAttributes )
133+
{
134+
attributes.push_back( QgsPointCloudAttribute( attr.attribute, attr.type ) );
135+
}
140136

141137
setAttributes( attributes );
142138

@@ -216,6 +212,21 @@ qint64 QgsCopcPointCloudIndex::pointCount() const
216212

217213
QVariant QgsCopcPointCloudIndex::metadataStatistic( const QString &attribute, QgsStatisticalSummary::Statistic statistic ) const
218214
{
215+
if ( attribute == QStringLiteral( "X" ) && statistic == QgsStatisticalSummary::Min )
216+
return mExtent.xMinimum();
217+
if ( attribute == QStringLiteral( "X" ) && statistic == QgsStatisticalSummary::Max )
218+
return mExtent.xMaximum();
219+
220+
if ( attribute == QStringLiteral( "Y" ) && statistic == QgsStatisticalSummary::Min )
221+
return mExtent.yMinimum();
222+
if ( attribute == QStringLiteral( "Y" ) && statistic == QgsStatisticalSummary::Max )
223+
return mExtent.yMaximum();
224+
225+
if ( attribute == QStringLiteral( "Z" ) && statistic == QgsStatisticalSummary::Min )
226+
return mZMin;
227+
if ( attribute == QStringLiteral( "Z" ) && statistic == QgsStatisticalSummary::Max )
228+
return mZMax;
229+
219230
if ( !mMetadataStats.contains( attribute ) )
220231
return QVariant();
221232

‎src/core/pointcloud/qgspointcloudindex.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ class CORE_EXPORT QgsPointCloudIndex: public QObject
262262
QgsDoubleRange nodeZRange( const IndexedPointCloudNode &node ) const;
263263

264264
//! Returns node's error in map units (used to determine in whether the node has enough detail for the current view)
265-
virtual float nodeError( const IndexedPointCloudNode &n ) const;
265+
float nodeError( const IndexedPointCloudNode &n ) const;
266266

267267
//! Returns scale
268268
QgsVector3D scale() const;

‎src/core/providers/copc/qgscopcprovider.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ QgsCopcProvider *QgsCopcProviderMetadata::createProvider( const QString &uri, co
145145
QList<QgsProviderSublayerDetails> QgsCopcProviderMetadata::querySublayers( const QString &uri, Qgis::SublayerQueryFlags, QgsFeedback * ) const
146146
{
147147
const QVariantMap parts = decodeUri( uri );
148-
if ( parts.value( QStringLiteral( "isCopc" ), false ).toBool() )
148+
if ( parts.value( QStringLiteral( "path" ) ).toString().endsWith( ".copc.laz", Qt::CaseSensitivity::CaseInsensitive ) )
149149
{
150150
QgsProviderSublayerDetails details;
151151
details.setUri( uri );
@@ -164,8 +164,8 @@ int QgsCopcProviderMetadata::priorityForUri( const QString &uri ) const
164164
{
165165
const QVariantMap parts = decodeUri( uri );
166166
const QFileInfo fi( parts.value( QStringLiteral( "path" ) ).toString() );
167-
if ( fi.exists() && parts.value( QStringLiteral( "isCopc" ), false ).toBool() )
168-
return 100;
167+
if ( parts.value( QStringLiteral( "path" ) ).toString().endsWith( ".copc.laz", Qt::CaseSensitivity::CaseInsensitive ) )
168+
return 101;
169169

170170
return 0;
171171
}
@@ -174,7 +174,7 @@ QList<QgsMapLayerType> QgsCopcProviderMetadata::validLayerTypesForUri( const QSt
174174
{
175175
const QVariantMap parts = decodeUri( uri );
176176
const QFileInfo fi( parts.value( QStringLiteral( "path" ) ).toString() );
177-
if ( fi.exists() && parts.value( QStringLiteral( "isCopc" ), false ).toBool() )
177+
if ( parts.value( QStringLiteral( "path" ) ).toString().endsWith( ".copc.laz", Qt::CaseSensitivity::CaseInsensitive ) )
178178
return QList< QgsMapLayerType>() << QgsMapLayerType::PointCloudLayer;
179179

180180
return QList< QgsMapLayerType>();
@@ -189,7 +189,7 @@ bool QgsCopcProviderMetadata::uriIsBlocklisted( const QString &uri ) const
189189
const QFileInfo fi( parts.value( QStringLiteral( "path" ) ).toString() );
190190

191191
// internal details only
192-
if ( fi.exists() && parts.value( QStringLiteral( "isCopc" ), false ).toBool() )
192+
if ( parts.value( QStringLiteral( "path" ) ).toString().endsWith( ".copc.laz", Qt::CaseSensitivity::CaseInsensitive ) )
193193
return true;
194194

195195
return false;
@@ -200,7 +200,6 @@ QVariantMap QgsCopcProviderMetadata::decodeUri( const QString &uri ) const
200200
const QString path = uri;
201201
QVariantMap uriComponents;
202202
uriComponents.insert( QStringLiteral( "path" ), path );
203-
uriComponents.insert( QStringLiteral( "isCopc" ), uri.endsWith( ".copc.laz" ) );
204203
return uriComponents;
205204
}
206205

@@ -215,7 +214,7 @@ QString QgsCopcProviderMetadata::filters( QgsProviderMetadata::FilterType type )
215214
return QString();
216215

217216
case QgsProviderMetadata::FilterType::FilterPointCloud:
218-
return QObject::tr( "COPC Point Clouds" ) + QStringLiteral( "COPC LAZ files (*.copc.laz *.COPC.LAZ)" );
217+
return QObject::tr( "COPC Point Clouds" ) + QStringLiteral( " (*.copc.laz *.COPC.LAZ)" );
219218
}
220219
return QString();
221220
}

‎src/gui/providers/qgspointcloudsourceselect.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,6 @@ void QgsPointCloudSourceSelect::addButtonClicked()
7878
// auto determine preferred provider for each path
7979

8080
const QList< QgsProviderRegistry::ProviderCandidateDetails > preferredProviders = QgsProviderRegistry::instance()->preferredProvidersForUri( mPath );
81-
for ( QgsProviderRegistry::ProviderCandidateDetails p : preferredProviders )
82-
{
83-
qDebug() << p.metadata()->key();
84-
}
8581
// maybe we should raise an assert if preferredProviders size is 0 or >1? Play it safe for now...
8682
if ( preferredProviders.empty() )
8783
continue;

‎tests/src/providers/CMakeLists.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,9 @@ if (WITH_EPT)
5858
add_qgis_test(testqgseptprovider.cpp MODULE provider LINKEDLIBRARIES qgis_core)
5959
endif()
6060

61-
# TODO: test COPC
62-
#if (WITH_COPC)
63-
# add_qgis_test(testqgscopcprovider.cpp MODULE provider LINKEDLIBRARIES qgis_core)
64-
#endif()
61+
if (WITH_COPC)
62+
add_qgis_test(testqgscopcprovider.cpp MODULE provider LINKEDLIBRARIES qgis_core)
63+
endif()
6564

6665
if (WITH_PDAL)
6766
include_directories(

‎tests/src/providers/testqgscopcprovider.cpp

Lines changed: 627 additions & 0 deletions
Large diffs are not rendered by default.
Binary file not shown.
Binary file not shown.
Binary file not shown.

‎tests/testdata/point_clouds/copc/norgb.copc.laz

Whitespace-only changes.
2.11 KB
Binary file not shown.
2.28 KB
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)
Please sign in to comment.