From 3dec432cb69a3e32a3a46b8e7e7471a165569cb7 Mon Sep 17 00:00:00 2001 From: Peter Petrik Date: Tue, 3 Nov 2020 14:05:57 +0100 Subject: [PATCH] [pointclouds] add basic structure for PDAL layer --- CMakeLists.txt | 9 + cmake/FindPDAL.cmake | 62 ++++ images/images.qrc | 4 + .../themes/default/mActionAddEntwineLayer.svg | 221 +++++++++++++ images/themes/default/mActionAddPdalLayer.svg | 294 ++++++++++++++++++ images/themes/default/mIconEntwineLayer.svg | 191 ++++++++++++ images/themes/default/mIconPdalLayer.svg | 262 ++++++++++++++++ .../qgspointclouddataprovider.sip.in | 5 - .../pointcloud/qgspointclouddataprovider.cpp | 10 - .../pointcloud/qgspointclouddataprovider.h | 7 +- src/core/pointcloud/qgspointcloudlayer.cpp | 2 +- src/core/pointcloud/qgspointcloudrenderer.cpp | 5 + src/core/providers/ept/qgseptdataitems.cpp | 1 + .../providers/ept/qgseptdataitemguiprovider.h | 2 +- .../ept/qgseptproviderguimetadata.cpp | 8 +- src/gui/providers/ept/qgseptsourceselect.h | 4 +- src/providers/CMakeLists.txt | 4 + src/providers/pdal/CMakeLists.txt | 73 +++++ .../pdal/qgspdaldataitemguiprovider.cpp | 33 ++ .../pdal/qgspdaldataitemguiprovider.h | 33 ++ src/providers/pdal/qgspdaldataitems.cpp | 79 +++++ src/providers/pdal/qgspdaldataitems.h | 49 +++ src/providers/pdal/qgspdalgresprovidergui.h | 35 +++ src/providers/pdal/qgspdalprovider.cpp | 151 +++++++++ src/providers/pdal/qgspdalprovider.h | 65 ++++ src/providers/pdal/qgspdalprovidergui.cpp | 61 ++++ src/providers/pdal/qgspdalprovidergui.h | 35 +++ src/providers/pdal/qgspdalsourceselect.cpp | 54 ++++ src/providers/pdal/qgspdalsourceselect.h | 46 +++ ...electbase.ui => qgseptsourceselectbase.ui} | 8 +- src/ui/pointcloud/qgspdalsourceselectbase.ui | 108 +++++++ 31 files changed, 1889 insertions(+), 32 deletions(-) create mode 100644 cmake/FindPDAL.cmake create mode 100644 images/themes/default/mActionAddEntwineLayer.svg create mode 100644 images/themes/default/mActionAddPdalLayer.svg create mode 100644 images/themes/default/mIconEntwineLayer.svg create mode 100644 images/themes/default/mIconPdalLayer.svg create mode 100644 src/providers/pdal/CMakeLists.txt create mode 100644 src/providers/pdal/qgspdaldataitemguiprovider.cpp create mode 100644 src/providers/pdal/qgspdaldataitemguiprovider.h create mode 100644 src/providers/pdal/qgspdaldataitems.cpp create mode 100644 src/providers/pdal/qgspdaldataitems.h create mode 100644 src/providers/pdal/qgspdalgresprovidergui.h create mode 100644 src/providers/pdal/qgspdalprovider.cpp create mode 100644 src/providers/pdal/qgspdalprovider.h create mode 100644 src/providers/pdal/qgspdalprovidergui.cpp create mode 100644 src/providers/pdal/qgspdalprovidergui.h create mode 100644 src/providers/pdal/qgspdalsourceselect.cpp create mode 100644 src/providers/pdal/qgspdalsourceselect.h rename src/ui/pointcloud/{qgspointcloudsourceselectbase.ui => qgseptsourceselectbase.ui} (92%) create mode 100644 src/ui/pointcloud/qgspdalsourceselectbase.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index d35835b87ab..50b28979912 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -237,6 +237,11 @@ IF(WITH_CORE) SET(ORACLE_LIBDIR "" CACHE STRING "Path to OCI libraries") ENDIF(WITH_ORACLE) + SET (WITH_PDAL FALSE CACHE BOOL "Determines whether PDAL support should be built") + IF(WITH_PDAL) + SET(HAVE_PDAL TRUE) + ENDIF(WITH_PDAL) + #BUILD WITH QtMobility by default on android only. Other platform can force it IF (ANDROID) SET (DEFAULT_WITH_QTMOBILITY TRUE) @@ -390,6 +395,10 @@ IF(WITH_CORE) MESSAGE(STATUS "Qt WebKit support DISABLED.") ENDIF(WITH_QTWEBKIT) + IF (WITH_PDAL) + FIND_PACKAGE(PDAL) # PDAL provider + ENDIF (WITH_PDAL) + ############################################################# # search for Qt5 SET(QT_MIN_VERSION 5.9.0) diff --git a/cmake/FindPDAL.cmake b/cmake/FindPDAL.cmake new file mode 100644 index 00000000000..b8a0423a55e --- /dev/null +++ b/cmake/FindPDAL.cmake @@ -0,0 +1,62 @@ +# Find PDAL +# ~~~~~~~~~~ +# Copyright (c) 2020, Peter Petrik +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# CMake module to search for PDAL library +# +# If it's found it sets PDAL_FOUND to TRUE +# and following variables are set: +# PDAL_INCLUDE_DIR +# PDAL_LIBRARIES + +# FIND_PATH and FIND_LIBRARY normally search standard locations +# before the specified paths. To search non-standard paths first, +# FIND_* is invoked first with specified paths and NO_DEFAULT_PATH +# and then again with no specified paths to search the default +# locations. When an earlier FIND_* succeeds, subsequent FIND_*s +# searching for the same item do nothing. +FIND_PATH(PDAL_INCLUDE_DIR pdal.hpp + "$ENV{LIB_DIR}/include/" + "$ENV{LIB_DIR}/include/pdal" + c:/msys/local/include + NO_DEFAULT_PATH + ) +FIND_PATH(PDAL_INCLUDE_DIR pdal.hpp) + +FIND_LIBRARY(PDAL_CPP_LIBRARY NAMES pdalccpp libpdalcpp PATHS + "$ENV{LIB_DIR}/lib" + c:/msys/local/lib + NO_DEFAULT_PATH + ) +FIND_LIBRARY(PDAL_CPP_LIBRARY NAMES pdalcpp libpdalcpp) + +FIND_LIBRARY(PDAL_UTIL_LIBRARY NAMES pdal_util libpdal_util PATHS + "$ENV{LIB_DIR}/lib" + c:/msys/local/lib + NO_DEFAULT_PATH + ) +FIND_LIBRARY(PDAL_UTIL_LIBRARY NAMES pdal_util libpdal_util) + + +IF (PDAL_INCLUDE_DIR AND PDAL_CPP_LIBRARY AND PDAL_UTIL_LIBRARY) + SET(PDAL_FOUND TRUE) + SET(PDAL_LIBRARIES ${PDAL_CPP_LIBRARY} ${PDAL_UTIL_LIBRARY}) +ENDIF (PDAL_INCLUDE_DIR AND PDAL_CPP_LIBRARY AND PDAL_UTIL_LIBRARY) + +IF (PDAL_FOUND) + IF (NOT PDAL_FIND_QUIETLY) + MESSAGE(STATUS "Found PDAL: ${PDAL_LIBRARIES}") + ENDIF (NOT PDAL_FIND_QUIETLY) + +ELSE (PDAL_FOUND) + IF (PDAL_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find PDAL") + ELSE (PDAL_FIND_REQUIRED) + IF (NOT PDAL_FIND_QUIETLY) + MESSAGE(STATUS "Could not find PDAL") + ENDIF (NOT PDAL_FIND_QUIETLY) + ENDIF (PDAL_FIND_REQUIRED) + +ENDIF (PDAL_FOUND) diff --git a/images/images.qrc b/images/images.qrc index 7db93727c21..09b573e6999 100644 --- a/images/images.qrc +++ b/images/images.qrc @@ -240,6 +240,8 @@ themes/default/mActionAddXyzLayer.svg themes/default/mActionAddVectorTileLayer.svg themes/default/mActionAddPointCloudLayer.svg + themes/default/mActionAddPdalLayer.svg + themes/default/mActionAddEntwineLayer.svg themes/default/mActionAddGeonodeLayer.svg themes/default/mActionAddDelimitedTextLayer.svg themes/default/mActionAddVirtualLayer.svg @@ -538,6 +540,8 @@ themes/default/mIconVector.svg themes/default/mIconVectorTileLayer.svg themes/default/mIconPointCloudLayer.svg + themes/default/mIconEntwineLayer.svg + themes/default/mIconPdalLayer.svg themes/default/mIconVirtualLayer.svg themes/default/mIconWcs.svg themes/default/mIconWfs.svg diff --git a/images/themes/default/mActionAddEntwineLayer.svg b/images/themes/default/mActionAddEntwineLayer.svg new file mode 100644 index 00000000000..529bdaf416a --- /dev/null +++ b/images/themes/default/mActionAddEntwineLayer.svg @@ -0,0 +1,221 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/themes/default/mActionAddPdalLayer.svg b/images/themes/default/mActionAddPdalLayer.svg new file mode 100644 index 00000000000..3db7501fe80 --- /dev/null +++ b/images/themes/default/mActionAddPdalLayer.svg @@ -0,0 +1,294 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/themes/default/mIconEntwineLayer.svg b/images/themes/default/mIconEntwineLayer.svg new file mode 100644 index 00000000000..3dbf4cbd870 --- /dev/null +++ b/images/themes/default/mIconEntwineLayer.svg @@ -0,0 +1,191 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/themes/default/mIconPdalLayer.svg b/images/themes/default/mIconPdalLayer.svg new file mode 100644 index 00000000000..82f287f4709 --- /dev/null +++ b/images/themes/default/mIconPdalLayer.svg @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/core/auto_generated/pointcloud/qgspointclouddataprovider.sip.in b/python/core/auto_generated/pointcloud/qgspointclouddataprovider.sip.in index d729cea6825..a9468b6392e 100644 --- a/python/core/auto_generated/pointcloud/qgspointclouddataprovider.sip.in +++ b/python/core/auto_generated/pointcloud/qgspointclouddataprovider.sip.in @@ -36,11 +36,6 @@ Ctor %End ~QgsPointCloudDataProvider(); - virtual QgsRectangle extent() const; - - virtual bool isValid() const; - - }; diff --git a/src/core/pointcloud/qgspointclouddataprovider.cpp b/src/core/pointcloud/qgspointclouddataprovider.cpp index 3836383be01..8be83ad5f08 100644 --- a/src/core/pointcloud/qgspointclouddataprovider.cpp +++ b/src/core/pointcloud/qgspointclouddataprovider.cpp @@ -29,13 +29,3 @@ QgsPointCloudDataProvider::QgsPointCloudDataProvider( QgsPointCloudDataProvider::~QgsPointCloudDataProvider() = default; - -QgsRectangle QgsPointCloudDataProvider::extent() const -{ - return index()->extent(); -} - -bool QgsPointCloudDataProvider::isValid() const -{ - return mIsValid; -} diff --git a/src/core/pointcloud/qgspointclouddataprovider.h b/src/core/pointcloud/qgspointclouddataprovider.h index 95aecff92ae..5e8f04eb478 100644 --- a/src/core/pointcloud/qgspointclouddataprovider.h +++ b/src/core/pointcloud/qgspointclouddataprovider.h @@ -44,18 +44,15 @@ class CORE_EXPORT QgsPointCloudDataProvider: public QgsDataProvider QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() ); ~QgsPointCloudDataProvider() override; - QgsRectangle extent() const override; - bool isValid() const override; /** * Returns the point cloud index associated with the provider. * + * Can be nullptr (e.g. the index is being created) + * * \note Not available in Python bindings */ virtual QgsPointCloudIndex *index() const SIP_SKIP {return nullptr;} - - private: - bool mIsValid = false; }; #endif // QGSMESHDATAPROVIDER_H diff --git a/src/core/pointcloud/qgspointcloudlayer.cpp b/src/core/pointcloud/qgspointcloudlayer.cpp index f06b685b577..96f8903cd32 100644 --- a/src/core/pointcloud/qgspointcloudlayer.cpp +++ b/src/core/pointcloud/qgspointcloudlayer.cpp @@ -56,7 +56,7 @@ QgsRectangle QgsPointCloudLayer::extent() const if ( !mDataProvider ) return QgsRectangle(); - return mDataProvider->index()->extent(); + return mDataProvider->extent(); } QgsMapLayerRenderer *QgsPointCloudLayer::createMapRenderer( QgsRenderContext &rendererContext ) diff --git a/src/core/pointcloud/qgspointcloudrenderer.cpp b/src/core/pointcloud/qgspointcloudrenderer.cpp index 1c30771236d..e8d14276647 100644 --- a/src/core/pointcloud/qgspointcloudrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudrenderer.cpp @@ -113,6 +113,8 @@ bool QgsPointCloudLayerRenderer::render() { // TODO cache!? QgsPointCloudIndex *pc = mLayer->dataProvider()->index(); + if ( !pc ) + return false; QgsRenderContext &context = *renderContext(); @@ -162,6 +164,9 @@ QgsPointCloudLayerRenderer::~QgsPointCloudLayerRenderer() = default; void QgsPointCloudLayerRenderer::drawData( QPainter *painter, const QgsPointCloudBlock *data, const QgsPointCloudRendererConfig &config ) { + Q_ASSERT( mLayer->dataProvider() ); + Q_ASSERT( mLayer->dataProvider()->index() ); + if ( !data ) return; diff --git a/src/core/providers/ept/qgseptdataitems.cpp b/src/core/providers/ept/qgseptdataitems.cpp index ebe8d1dadeb..ca750861721 100644 --- a/src/core/providers/ept/qgseptdataitems.cpp +++ b/src/core/providers/ept/qgseptdataitems.cpp @@ -32,6 +32,7 @@ QgsEptLayerItem::QgsEptLayerItem( QgsDataItem *parent, : QgsLayerItem( parent, name, path, uri, QgsLayerItem::PointCloud, QStringLiteral( "ept" ) ) { mToolTip = uri; + mIconName = QStringLiteral( "mIconEntwineLayer.svg" ); setState( Populated ); } diff --git a/src/gui/providers/ept/qgseptdataitemguiprovider.h b/src/gui/providers/ept/qgseptdataitemguiprovider.h index 9f79d5fb499..4f87f4e47cd 100644 --- a/src/gui/providers/ept/qgseptdataitemguiprovider.h +++ b/src/gui/providers/ept/qgseptdataitemguiprovider.h @@ -29,7 +29,7 @@ class QgsEptDataItemGuiProvider : public QObject, public QgsDataItemGuiProvider Q_OBJECT public: - QString name() override { return QStringLiteral( "Point Cloud" ); } + QString name() override { return QStringLiteral( "ept" ); } void populateContextMenu( QgsDataItem *item, QMenu *menu, const QList &selectedItems, QgsDataItemGuiContext context ) override; diff --git a/src/gui/providers/ept/qgseptproviderguimetadata.cpp b/src/gui/providers/ept/qgseptproviderguimetadata.cpp index 589fdbc4d72..0942cce97b1 100644 --- a/src/gui/providers/ept/qgseptproviderguimetadata.cpp +++ b/src/gui/providers/ept/qgseptproviderguimetadata.cpp @@ -27,10 +27,10 @@ class QgsEptSourceSelectProvider : public QgsSourceSelectProvider { public: - QString providerKey() const override { return QStringLiteral( "pointcloud" ); } - QString text() const override { return QObject::tr( "Point Cloud" ); } + QString providerKey() const override { return QStringLiteral( "ept" ); } + QString text() const override { return QObject::tr( "EPT Point Cloud" ); } int ordering() const override { return QgsSourceSelectProvider::OrderLocalProvider + 25; } - QIcon icon() const override { return QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddPointCloudLayer.svg" ) ); } + QIcon icon() const override { return QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddEntwineLayer.svg" ) ); } QgsAbstractDataSourceWidget *createDataSourceWidget( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::Widget, QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::Embedded ) const override { return new QgsEptSourceSelect( parent, fl, widgetMode ); @@ -38,7 +38,7 @@ class QgsEptSourceSelectProvider : public QgsSourceSelectProvider }; QgsEptProviderGuiMetadata::QgsEptProviderGuiMetadata() - : QgsProviderGuiMetadata( QStringLiteral( "etp" ) ) + : QgsProviderGuiMetadata( QStringLiteral( "ept" ) ) { } diff --git a/src/gui/providers/ept/qgseptsourceselect.h b/src/gui/providers/ept/qgseptsourceselect.h index 3af9ebef8be..764ad598e16 100644 --- a/src/gui/providers/ept/qgseptsourceselect.h +++ b/src/gui/providers/ept/qgseptsourceselect.h @@ -21,7 +21,7 @@ #include "qgis_sip.h" #define SIP_NO_FILE -#include "ui_qgspointcloudsourceselectbase.h" +#include "ui_qgseptsourceselectbase.h" #include "qgsabstractdatasourcewidget.h" #include "qgis_gui.h" @@ -30,7 +30,7 @@ * \class QgsEptSourceSelect * \brief Dialog to select EPT point cloud supported sources */ -class QgsEptSourceSelect : public QgsAbstractDataSourceWidget, private Ui::QgsPointCloudSourceSelectBase +class QgsEptSourceSelect : public QgsAbstractDataSourceWidget, private Ui::QgsEptSourceSelectBase { Q_OBJECT diff --git a/src/providers/CMakeLists.txt b/src/providers/CMakeLists.txt index d8aab2d3361..b6d1ac0642f 100644 --- a/src/providers/CMakeLists.txt +++ b/src/providers/CMakeLists.txt @@ -26,6 +26,10 @@ IF (NOT FORCE_STATIC_PROVIDERS) ADD_SUBDIRECTORY(oracle) ENDIF(WITH_ORACLE) + IF (WITH_PDAL) + ADD_SUBDIRECTORY(pdal) + ENDIF(WITH_PDAL) + IF (WITH_GRASS OR WITH_GRASS7) ADD_SUBDIRECTORY(grass) ENDIF (WITH_GRASS OR WITH_GRASS7) diff --git a/src/providers/pdal/CMakeLists.txt b/src/providers/pdal/CMakeLists.txt new file mode 100644 index 00000000000..c930509e223 --- /dev/null +++ b/src/providers/pdal/CMakeLists.txt @@ -0,0 +1,73 @@ +######################################################## +# Files + +SET(PDAL_SRCS + qgspdaldataitems.cpp + qgspdalprovider.cpp +) + +SET(PDAL_HDRS + qgspdaldataitems.h + qgspdalprovider.h +) + +IF (WITH_GUI) + SET(PDAL_SRCS + ${PDAL_SRCS} + qgspdalprovidergui.cpp + qgspdaldataitemguiprovider.cpp + qgspdalsourceselect.cpp + ) + + SET(PDAL_HDRS + ${PDAL_HDRS} + qgspdalprovidergui.h + qgspdaldataitemguiprovider.h + qgspdalsourceselect.h + ) +ENDIF () + +######################################################## +# Build + +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR}/src/core + ${CMAKE_SOURCE_DIR}/src/core/auth + ${CMAKE_SOURCE_DIR}/src/core/expression + ${CMAKE_SOURCE_DIR}/src/core/geometry + ${CMAKE_SOURCE_DIR}/src/core/metadata + ${CMAKE_SOURCE_DIR}/src/core/symbology + ${CMAKE_SOURCE_DIR}/src/core/raster + ${CMAKE_SOURCE_DIR}/src/core/pointcloud + ${CMAKE_SOURCE_DIR}/src/core/providers/ept + ${CMAKE_SOURCE_DIR}/src/gui + ${CMAKE_SOURCE_DIR}/src/gui/auth + ${CMAKE_SOURCE_DIR}/src/gui/codeeditors + ${CMAKE_SOURCE_DIR}/external + ${CMAKE_SOURCE_DIR}/external/nlohmann + + ${CMAKE_BINARY_DIR}/src/core + ${CMAKE_BINARY_DIR}/src/gui + ${CMAKE_BINARY_DIR}/src/ui +) + +INCLUDE_DIRECTORIES(SYSTEM + ${PDAL_INCLUDE_DIR} +) + +# static library +ADD_LIBRARY (pdalprovider MODULE ${PDAL_SRCS} ${PDAL_HDRS}) +TARGET_LINK_LIBRARIES (pdalprovider + ${PDAL_LIBRARIES} +) + +IF (WITH_GUI) + TARGET_LINK_LIBRARIES(pdalprovider + qgis_gui + ) + ADD_DEPENDENCIES(pdalprovider ui) +ENDIF (WITH_GUI) + +INSTALL(TARGETS pdalprovider + RUNTIME DESTINATION ${QGIS_PLUGIN_DIR} + LIBRARY DESTINATION ${QGIS_PLUGIN_DIR}) diff --git a/src/providers/pdal/qgspdaldataitemguiprovider.cpp b/src/providers/pdal/qgspdaldataitemguiprovider.cpp new file mode 100644 index 00000000000..043f1390b47 --- /dev/null +++ b/src/providers/pdal/qgspdaldataitemguiprovider.cpp @@ -0,0 +1,33 @@ +/*************************************************************************** + qgspdaldataitemguiprovider.cpp + -------------------------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgspdaldataitemguiprovider.h" + +#include "qgsmanageconnectionsdialog.h" +#include "qgspdaldataitems.h" +#include "qgspdalprovider.h" +#include "qgspdalsourceselect.h" + +#include +#include +#include + + +void QgsPdalDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu, const QList &, QgsDataItemGuiContext context ) +{ + Q_UNUSED( item ) + Q_UNUSED( menu ) + Q_UNUSED( context ) +} diff --git a/src/providers/pdal/qgspdaldataitemguiprovider.h b/src/providers/pdal/qgspdaldataitemguiprovider.h new file mode 100644 index 00000000000..7871c6fe53f --- /dev/null +++ b/src/providers/pdal/qgspdaldataitemguiprovider.h @@ -0,0 +1,33 @@ +/*************************************************************************** + qgspdaldataitemguiprovider.h + -------------------------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSPDALDATAITEMGUIPROVIDER_H +#define QGSPDALDATAITEMGUIPROVIDER_H + +#include "qgsdataitemguiprovider.h" + + +class QgsPdalDataItemGuiProvider : public QObject, public QgsDataItemGuiProvider +{ + Q_OBJECT + public: + + QString name() override { return QStringLiteral( "pdal" ); } + + void populateContextMenu( QgsDataItem *item, QMenu *menu, + const QList &selectedItems, QgsDataItemGuiContext context ) override; +}; + +#endif // QGSPDALDATAITEMGUIPROVIDER_H diff --git a/src/providers/pdal/qgspdaldataitems.cpp b/src/providers/pdal/qgspdaldataitems.cpp new file mode 100644 index 00000000000..f761e43e78d --- /dev/null +++ b/src/providers/pdal/qgspdaldataitems.cpp @@ -0,0 +1,79 @@ +/*************************************************************************** + qgspdaldataitems.cpp + -------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgspdaldataitems.h" +#include "qgslogger.h" +#include "qgssettings.h" + +#include +#include + +QgsPdalLayerItem::QgsPdalLayerItem( QgsDataItem *parent, + const QString &name, const QString &path, const QString &uri ) + : QgsLayerItem( parent, name, path, uri, QgsLayerItem::PointCloud, QStringLiteral( "pdal" ) ) +{ + mToolTip = uri; + mIconName = QStringLiteral( "mIconPdalLayer.svg" ); + setState( Populated ); +} + +QString QgsPdalLayerItem::layerName() const +{ + QFileInfo info( name() ); + return info.completeBaseName(); +} + +// --------------------------------------------------------------------------- +QgsPdalDataItemProvider::QgsPdalDataItemProvider(): + QgsDataItemProvider() +{ +} + +QString QgsPdalDataItemProvider::name() +{ + return QStringLiteral( "pdal" ); +} + +int QgsPdalDataItemProvider::capabilities() const +{ + return QgsDataProvider::File; +} + +QgsDataItem *QgsPdalDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem ) +{ + if ( path.isEmpty() ) + return nullptr; + + QgsDebugMsgLevel( "thePath = " + path, 2 ); + + // get suffix, removing .gz if present + QFileInfo info( path ); + info.setFile( path ); + + // allow only normal files + if ( !info.isFile() ) + return nullptr; + + // Filter files by extension + // TODO get file filter list from PDAL library + if ( !path.endsWith( QStringLiteral( "laz" ) ) ) + return nullptr; + + QString name = info.baseName() + QStringLiteral( ".laz" ); + + return new QgsPdalLayerItem( parentItem, name, path, path ); +} diff --git a/src/providers/pdal/qgspdaldataitems.h b/src/providers/pdal/qgspdaldataitems.h new file mode 100644 index 00000000000..95fee03e732 --- /dev/null +++ b/src/providers/pdal/qgspdaldataitems.h @@ -0,0 +1,49 @@ +/*************************************************************************** + qgspdaldataitems.h + -------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSPDALDATAITEMS_H +#define QGSPDALDATAITEMS_H + +#include "qgsdataitem.h" +#include "qgsdataitemprovider.h" +#include "qgsprovidermetadata.h" + +class CORE_EXPORT QgsPdalLayerItem : public QgsLayerItem +{ + Q_OBJECT + public: + QgsPdalLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri ); + QString layerName() const override; +}; + +//! Provider for PDAL data items +class QgsPdalDataItemProvider : public QgsDataItemProvider +{ + public: + QgsPdalDataItemProvider(); + + QString name() override; + + int capabilities() const override; + + QgsDataItem *createDataItem( const QString &pathIn, QgsDataItem *parentItem ) override; +}; + +#endif // QGSPDALDATAITEMS_H + + + diff --git a/src/providers/pdal/qgspdalgresprovidergui.h b/src/providers/pdal/qgspdalgresprovidergui.h new file mode 100644 index 00000000000..92a4e72bc76 --- /dev/null +++ b/src/providers/pdal/qgspdalgresprovidergui.h @@ -0,0 +1,35 @@ +/*************************************************************************** + qgspostgresprovidergui.h + ------------------------ + Date : October 2019 + Copyright : (C) 2019 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSPOSTGRESPROVIDERGUI_H +#define QGSPOSTGRESPROVIDERGUI_H + +#include +#include + +#include "qgsproviderguimetadata.h" + +class QgsPostgresProviderGuiMetadata: public QgsProviderGuiMetadata +{ + public: + QgsPostgresProviderGuiMetadata(); + + QList sourceSelectProviders() override; + QList dataItemGuiProviders() override; + QList projectStorageGuiProviders() override; + void registerGui( QMainWindow *mainWindow ) override; +}; + +#endif // QGSPOSTGRESPROVIDERGUI_H diff --git a/src/providers/pdal/qgspdalprovider.cpp b/src/providers/pdal/qgspdalprovider.cpp new file mode 100644 index 00000000000..e744c8caf9d --- /dev/null +++ b/src/providers/pdal/qgspdalprovider.cpp @@ -0,0 +1,151 @@ +/*************************************************************************** + qgspdaldataprovider.cpp + ----------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgis.h" +#include "qgspdalprovider.h" +#include "qgspdaldataitems.h" +#include "qgsruntimeprofiler.h" +#include "qgsapplication.h" + +#include +#include +#include + +#define PROVIDER_KEY QStringLiteral( "pdal" ) +#define PROVIDER_DESCRIPTION QStringLiteral( "PDAL point cloud data provider" ) + +QgsPdalProvider::QgsPdalProvider( + const QString &uri, + const QgsDataProvider::ProviderOptions &options, + QgsDataProvider::ReadFlags flags ) + : QgsPointCloudDataProvider( uri, options, flags ) +{ + std::unique_ptr< QgsScopedRuntimeProfile > profile; + if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) ) + profile = qgis::make_unique< QgsScopedRuntimeProfile >( tr( "Open data source" ), QStringLiteral( "projectload" ) ); + + mIsValid = load( uri ); +} + +QgsPdalProvider::~QgsPdalProvider() = default; + +QgsCoordinateReferenceSystem QgsPdalProvider::crs() const +{ + return mCrs; +} + +QgsRectangle QgsPdalProvider::extent() const +{ + return mExtent; +} + +bool QgsPdalProvider::isValid() const +{ + return mIsValid; +} + +QString QgsPdalProvider::name() const +{ + return QStringLiteral( "pdal" ); +} + +QString QgsPdalProvider::description() const +{ + return QStringLiteral( "Point Clouds PDAL" ); +} + +QgsPointCloudIndex *QgsPdalProvider::index() const +{ + // TODO automatically generate EPT index + return nullptr; +} + +bool QgsPdalProvider::load( const QString &uri ) +{ + pdal::Option las_opt( "filename", uri.toStdString() ); + pdal::Options las_opts; + las_opts.add( las_opt ); + pdal::PointTable table; + pdal::LasReader las_reader; + las_reader.setOptions( las_opts ); + las_reader.prepare( table ); + pdal::PointViewSet point_view_set = las_reader.execute( table ); + pdal::PointViewPtr point_view = *point_view_set.begin(); + pdal::Dimension::IdList dims = point_view->dims(); + pdal::LasHeader las_header = las_reader.header(); + + // extent + /* + double scale_x = las_header.scaleX(); + double scale_y = las_header.scaleY(); + double scale_z = las_header.scaleZ(); + + double offset_x = las_header.offsetX(); + double offset_y = las_header.offsetY(); + double offset_z = las_header.offsetZ(); + */ + + double xmin = las_header.minX(); + double xmax = las_header.maxX(); + double ymin = las_header.minY(); + double ymax = las_header.maxY(); + mExtent = QgsRectangle( xmin, ymin, xmax, ymax ); + + // unsigned int nFeatures = las_header.pointCount(); + + // projection + QString wkt = QString::fromStdString( las_reader.getSpatialReference().getWKT() ); + mCrs = QgsCoordinateReferenceSystem::fromWkt( wkt ); + + return true; +} + +QgsPdalProviderMetadata::QgsPdalProviderMetadata(): + QgsProviderMetadata( PROVIDER_KEY, PROVIDER_DESCRIPTION ) +{ +} + +QgsPdalProvider *QgsPdalProviderMetadata::createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags ) +{ + return new QgsPdalProvider( uri, options, flags ); +} + +QList QgsPdalProviderMetadata::dataItemProviders() const +{ + QList< QgsDataItemProvider * > providers; + providers << new QgsPdalDataItemProvider; + return providers; +} + +QVariantMap QgsPdalProviderMetadata::decodeUri( const QString &uri ) +{ + const QString path = uri; + QVariantMap uriComponents; + uriComponents.insert( QStringLiteral( "path" ), path ); + return uriComponents; +} + +QString QgsPdalProviderMetadata::encodeUri( const QVariantMap &parts ) +{ + const QString path = parts.value( QStringLiteral( "path" ) ).toString(); + return path; +} + +QGISEXTERN QgsProviderMetadata *providerMetadataFactory() +{ + return new QgsPdalProviderMetadata(); +} diff --git a/src/providers/pdal/qgspdalprovider.h b/src/providers/pdal/qgspdalprovider.h new file mode 100644 index 00000000000..054269f8738 --- /dev/null +++ b/src/providers/pdal/qgspdalprovider.h @@ -0,0 +1,65 @@ +/*************************************************************************** + qgspdaldataprovider.h + --------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSPDALPROVIDER_H +#define QGSPDALPROVIDER_H + +#include "qgis_core.h" +#include "qgspointclouddataprovider.h" +#include "qgsprovidermetadata.h" + +#include + +class QgsPdalProvider: public QgsPointCloudDataProvider +{ + Q_OBJECT + public: + QgsPdalProvider( const QString &uri, + const QgsDataProvider::ProviderOptions &providerOptions, + QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() ); + + ~QgsPdalProvider(); + QgsCoordinateReferenceSystem crs() const override; + + QgsRectangle extent() const override; + + bool isValid() const override; + + QString name() const override; + + QString description() const override; + + QgsPointCloudIndex *index() const override; + + private: + bool load( const QString &uri ); + QgsCoordinateReferenceSystem mCrs; + QgsRectangle mExtent; + bool mIsValid = false; +}; + +class QgsPdalProviderMetadata : public QgsProviderMetadata +{ + public: + QgsPdalProviderMetadata(); + QgsPdalProvider *createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() ) override; + QList< QgsDataItemProvider * > dataItemProviders() const override; + QString encodeUri( const QVariantMap &parts ) override; + QVariantMap decodeUri( const QString &uri ) override; +}; + +#endif // QGSPDALPROVIDER_H diff --git a/src/providers/pdal/qgspdalprovidergui.cpp b/src/providers/pdal/qgspdalprovidergui.cpp new file mode 100644 index 00000000000..7b267ca0545 --- /dev/null +++ b/src/providers/pdal/qgspdalprovidergui.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + qgspdalprovidergui.cpp + -------------------------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgsapplication.h" +#include "qgsproviderguimetadata.h" +#include "qgssourceselectprovider.h" + +#include "qgspdalprovider.h" +#include "qgspdalsourceselect.h" + + +//! Provider for pdal source select +class QgsPdalSourceSelectProvider : public QgsSourceSelectProvider +{ + public: + + QString providerKey() const override { return QStringLiteral( "pdal" ); } + QString text() const override { return QObject::tr( "PDAL Point Clouds" ); } + int ordering() const override { return QgsSourceSelectProvider::OrderLocalProvider + 22; } + QIcon icon() const override { return QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddPdalLayer.svg" ) ); } + QgsAbstractDataSourceWidget *createDataSourceWidget( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::Widget, + QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::Embedded ) const override + { + return new QgsPdalSourceSelect( parent, fl, widgetMode ); + } +}; + + +class QgsPdalProviderGuiMetadata: public QgsProviderGuiMetadata +{ + public: + QgsPdalProviderGuiMetadata() + : QgsProviderGuiMetadata( QStringLiteral( "pdal" ) ) + { + } + + QList sourceSelectProviders() override + { + QList providers; + providers << new QgsPdalSourceSelectProvider; + return providers; + } +}; + + +QGISEXTERN QgsProviderGuiMetadata *providerGuiMetadataFactory() +{ + return new QgsPdalProviderGuiMetadata(); +} diff --git a/src/providers/pdal/qgspdalprovidergui.h b/src/providers/pdal/qgspdalprovidergui.h new file mode 100644 index 00000000000..36a12b310b4 --- /dev/null +++ b/src/providers/pdal/qgspdalprovidergui.h @@ -0,0 +1,35 @@ +/*************************************************************************** + qgspdalprovidergui.h + ------------------------ + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSPDALPROVIDERGUI_H +#define QGSPDALPROVIDERGUI_H + +#include +#include + +#include "qgsproviderguimetadata.h" + +class QgsPdalProviderGuiMetadata: public QgsProviderGuiMetadata +{ + public: + QgsPdalProviderGuiMetadata(); + + QList sourceSelectProviders() override; + QList dataItemGuiProviders() override; + QList projectStorageGuiProviders() override; + void registerGui( QMainWindow *mainWindow ) override; +}; + +#endif // QGSPDALPROVIDERGUI_H diff --git a/src/providers/pdal/qgspdalsourceselect.cpp b/src/providers/pdal/qgspdalsourceselect.cpp new file mode 100644 index 00000000000..89ad5d0793e --- /dev/null +++ b/src/providers/pdal/qgspdalsourceselect.cpp @@ -0,0 +1,54 @@ +/*************************************************************************** + qgspdalsourceselect.cpp + ----------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include + +#include "qgspdalsourceselect.h" +#include "qgsproviderregistry.h" +#include "ogr/qgsogrhelperfunctions.h" + +QgsPdalSourceSelect::QgsPdalSourceSelect( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode ): + QgsAbstractDataSourceWidget( parent, fl, widgetMode ) +{ + setupUi( this ); + setupButtons( buttonBox ); + + mFileWidget->setDialogTitle( tr( "Open PDAL Supported Point Cloud Dataset(s)" ) ); + mFileWidget->setFilter( QgsProviderRegistry::instance()->fileMeshFilters() ); + mFileWidget->setStorageMode( QgsFileWidget::GetMultipleFiles ); + connect( mFileWidget, &QgsFileWidget::fileChanged, this, [ = ]( const QString & path ) + { + mPath = path; + emit enableButtons( ! mPath.isEmpty() ); + } ); +} + +void QgsPdalSourceSelect::addButtonClicked() +{ + if ( mPath.isEmpty() ) + { + QMessageBox::information( this, + tr( "Add mesh layer" ), + tr( "No layers selected." ) ); + return; + } + + for ( const QString &path : QgsFileWidget::splitFilePaths( mPath ) ) + { + emit addMeshLayer( path, QFileInfo( path ).baseName(), QStringLiteral( "mdal" ) ); + } +} diff --git a/src/providers/pdal/qgspdalsourceselect.h b/src/providers/pdal/qgspdalsourceselect.h new file mode 100644 index 00000000000..004ad61b903 --- /dev/null +++ b/src/providers/pdal/qgspdalsourceselect.h @@ -0,0 +1,46 @@ +/*************************************************************************** + qgspdalsourceselect.h + ------------------- + Date : November 2020 + Copyright : (C) 2020 by Peter Petrik + Email : zilolv at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef QGSPDALSOURCESELECT_H +#define QGSPDALSOURCESELECT_H + +#include "ui_qgspdalsourceselectbase.h" +#include "qgsabstractdatasourcewidget.h" +#include "qgis_gui.h" + + +/** + * Dialog to select PDAL supported point cloud sources + */ +class QgsPdalSourceSelect : public QgsAbstractDataSourceWidget, private Ui::QgsPdalSourceSelectBase +{ + Q_OBJECT + + public: + //! Constructor + QgsPdalSourceSelect( QWidget *parent = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags, + QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::None ); + + public slots: + //! Determines the tables the user selected and closes the dialog + void addButtonClicked() override; + + private: + QString mPath; + +}; + +#endif // QGSPDALSOURCESELECT_H diff --git a/src/ui/pointcloud/qgspointcloudsourceselectbase.ui b/src/ui/pointcloud/qgseptsourceselectbase.ui similarity index 92% rename from src/ui/pointcloud/qgspointcloudsourceselectbase.ui rename to src/ui/pointcloud/qgseptsourceselectbase.ui index a1a99b64b6f..c2d3c254e47 100644 --- a/src/ui/pointcloud/qgspointcloudsourceselectbase.ui +++ b/src/ui/pointcloud/qgseptsourceselectbase.ui @@ -1,7 +1,7 @@ - QgsPointCloudSourceSelectBase - + QgsEptSourceSelectBase + 0 @@ -41,7 +41,7 @@ - Point cloud dataset + EPT Point cloud dataset @@ -91,7 +91,7 @@ buttonBox rejected() - QgsPointCloudSourceSelectBase + QgsEptSourceSelectBase reject() diff --git a/src/ui/pointcloud/qgspdalsourceselectbase.ui b/src/ui/pointcloud/qgspdalsourceselectbase.ui new file mode 100644 index 00000000000..d5b016ecf28 --- /dev/null +++ b/src/ui/pointcloud/qgspdalsourceselectbase.ui @@ -0,0 +1,108 @@ + + + QgsPdalSourceSelectBase + + + + 0 + 0 + 351 + 119 + + + + Add Point Cloud Layer(s) + + + + .. + + + true + + + true + + + + + + + + + 0 + 0 + + + + Source + + + + + + PDAL Point cloud dataset + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QDialogButtonBox::NoButton + + + + + + + + + QgsFileWidget + QWidget +
qgsfilewidget.h
+
+
+ + buttonBox + + + + + buttonBox + rejected() + QgsPdalSourceSelectBase + reject() + + + 518 + 510 + + + 551 + 370 + + + + +