From 7db8484759635ccc9b657a5144ebf19bd8c59973 Mon Sep 17 00:00:00 2001
From: Even Rouault <even.rouault@spatialys.com>
Date: Tue, 28 Jan 2025 17:39:20 +0100
Subject: [PATCH] Remove RDB driver

---
 cmake/helpers/CheckDependentLibraries.cmake   |   1 -
 .../development/building_from_source.rst      |  12 -
 doc/source/drivers/raster/index.rst           |   1 -
 doc/source/drivers/raster/rdb.rst             |  66 --
 frmts/CMakeLists.txt                          |   1 -
 frmts/rdb/CMakeLists.txt                      |  10 -
 frmts/rdb/rdbdataset.cpp                      | 788 ------------------
 frmts/rdb/rdbdataset.hpp                      | 135 ---
 8 files changed, 1014 deletions(-)
 delete mode 100644 doc/source/drivers/raster/rdb.rst
 delete mode 100644 frmts/rdb/CMakeLists.txt
 delete mode 100644 frmts/rdb/rdbdataset.cpp
 delete mode 100644 frmts/rdb/rdbdataset.hpp

diff --git a/cmake/helpers/CheckDependentLibraries.cmake b/cmake/helpers/CheckDependentLibraries.cmake
index 09cf2536d907..c7591e955dd0 100644
--- a/cmake/helpers/CheckDependentLibraries.cmake
+++ b/cmake/helpers/CheckDependentLibraries.cmake
@@ -440,7 +440,6 @@ gdal_check_package(JXL_THREADS "JPEG-XL threading" CAN_DISABLE)
 gdal_check_package(Crnlib "enable gdal_DDS driver" CAN_DISABLE)
 gdal_check_package(basisu "Enable BASISU driver" CONFIG CAN_DISABLE)
 gdal_check_package(IDB "enable ogr_IDB driver" CAN_DISABLE)
-gdal_check_package(rdb "enable RIEGL RDB library" CONFIG CAN_DISABLE)
 include(CheckDependentLibrariesTileDB)
 
 gdal_check_package(ExprTk "Enable C++ Mathematical Expression Tooklit Library (ExprTk) for VRT expressions" DISABLED_BY_DEFAULT)
diff --git a/doc/source/development/building_from_source.rst b/doc/source/development/building_from_source.rst
index 9103a013c444..4747cfc483b6 100644
--- a/doc/source/development/building_from_source.rst
+++ b/doc/source/development/building_from_source.rst
@@ -1849,18 +1849,6 @@ It can be detected with pkg-config.
     Control whether to use RasterLite2. Defaults to ON when RasterLite2 is found.
 
 
-rdb
-***
-
-The `RDB <https://repository.riegl.com/software/libraries/rdblib>`
-(closed source/proprietary) library is required for the :ref:`raster.rdb` driver.
-Specify install prefix in the ``CMAKE_PREFIX_PATH`` variable.
-
-.. option:: GDAL_USE_RDB=ON/OFF
-
-    Control whether to use rdb. Defaults to ON when rdb is found.
-
-
 SPATIALITE
 **********
 
diff --git a/doc/source/drivers/raster/index.rst b/doc/source/drivers/raster/index.rst
index f35fede51cda..8198b5df999e 100644
--- a/doc/source/drivers/raster/index.rst
+++ b/doc/source/drivers/raster/index.rst
@@ -146,7 +146,6 @@ Raster drivers
    rasterlite
    rasterlite2
    r
-   rdb
    rcm
    rik
    rmf
diff --git a/doc/source/drivers/raster/rdb.rst b/doc/source/drivers/raster/rdb.rst
deleted file mode 100644
index e7ae0b2030c5..000000000000
--- a/doc/source/drivers/raster/rdb.rst
+++ /dev/null
@@ -1,66 +0,0 @@
-.. _raster.rdb:
-
-================================================================================
-RDB - *RIEGL* Database
-================================================================================
-
-.. shortname:: RDB
-
-.. versionadded:: 3.1
-
-.. build_dependencies:: rdblib >= 2.2.0.
-
-GDAL can read \*.mpx files in the RDB format, the in-house format used by `RIEGL Laser Measurement Systems GmbH <http://www.riegl.com>`__ through the RDB library.
-
-The driver relies on the RDB library, which can be downloaded `here <https://repository.riegl.com/software/libraries/rdblib>`__ . The minimum version required of the rdblib is 2.2.0.
-
-Driver capabilities
--------------------
-
-.. supports_georeferencing::
-
-Provided Bands
--------------------
-
-All attributes stored in the RDB, but the coordinates, are provided in bands. Vector attributes are split up into multiple bands.
-The attributes are currently mapped as follows:
-
-+----------------------------+-------------------------+
-| RDB attribute              | GDAL Band               |
-+============================+=========================+
-| riegl.surface_normal[0],   | Band 1                  |
-|                            |                         |
-| riegl.surface_normal[1],   | Band 2                  |
-|                            |                         |
-| riegl.surface_normal[2]    | Band 3                  |
-+----------------------------+-------------------------+
-| riegl.timestamp_min        | Band 4                  |
-+----------------------------+-------------------------+
-| riegl.timestamp_max        | Band 5                  |
-+----------------------------+-------------------------+
-| riegl.reflectance          | Band 6                  |
-+----------------------------+-------------------------+
-| riegl.amplitude            | Band 7                  |
-+----------------------------+-------------------------+
-| riegl.deviation            | Band 8                  |
-+----------------------------+-------------------------+
-| riegl.height_center        | Band 9                  |
-+----------------------------+-------------------------+
-| riegl.height_mean          | Band 10                 |
-+----------------------------+-------------------------+
-| riegl.height_min           | Band 11                 |
-+----------------------------+-------------------------+
-| riegl.height_max           | Band 12                 |
-+----------------------------+-------------------------+
-| riegl.point_count          | Band 13                 |
-+----------------------------+-------------------------+
-| riegl.point_count_grid_cell| Band 14                 |
-+----------------------------+-------------------------+
-| riegl.pca_thickness        | Band 15                 |
-+----------------------------+-------------------------+
-| riegl.std_dev              | Band 16                 |
-+----------------------------+-------------------------+
-| riegl.voxel_count          | Band 17                 |
-+----------------------------+-------------------------+
-| riegl.id                   | Band 18                 |
-+----------------------------+-------------------------+
diff --git a/frmts/CMakeLists.txt b/frmts/CMakeLists.txt
index 950eba3d1f14..9b8cc662a589 100644
--- a/frmts/CMakeLists.txt
+++ b/frmts/CMakeLists.txt
@@ -184,7 +184,6 @@ include(openjpeg/driver_declaration.cmake)
 include(tiledb/driver_declaration.cmake)
 gdal_dependent_format(exr "EXR support via OpenEXR library" "GDAL_USE_OPENEXR")
 gdal_dependent_format(pcraster "PCRaster CSF 2.0 raster file driver" "GDAL_USE_LIBCSF OR GDAL_USE_LIBCSF_INTERNAL")
-gdal_dependent_format(rdb "RIEGL RDB Map Pixel (.mpx) driver" "rdb_FOUND")
 gdal_dependent_format(jpegxl "JPEG-XL" "GDAL_USE_JXL")
 gdal_dependent_format(basisu_ktx2 "Basis Universal and KTX2 texture formats" "GDAL_USE_BASISU")
 
diff --git a/frmts/rdb/CMakeLists.txt b/frmts/rdb/CMakeLists.txt
deleted file mode 100644
index b212a5499596..000000000000
--- a/frmts/rdb/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-add_gdal_driver(TARGET gdal_RDB SOURCES rdbdataset.cpp PLUGIN_CAPABLE_IF "NOT GDAL_USE_JSONC_INTERNAL")
-gdal_standard_includes(gdal_RDB)
-target_include_directories(gdal_RDB PRIVATE ${GDAL_VECTOR_FORMAT_SOURCE_DIR}/geojson)
-gdal_target_link_libraries(TARGET gdal_RDB PRIVATE LIBRARIES rdbcpp)
-
-if (GDAL_USE_JSONC_INTERNAL)
-  gdal_add_vendored_lib(gdal_RDB libjson)
-else ()
-  gdal_target_link_libraries(gdal_RDB PRIVATE ${JSONC_TARGET})
-endif ()
diff --git a/frmts/rdb/rdbdataset.cpp b/frmts/rdb/rdbdataset.cpp
deleted file mode 100644
index d4c087404538..000000000000
--- a/frmts/rdb/rdbdataset.cpp
+++ /dev/null
@@ -1,788 +0,0 @@
-/******************************************************************************
- *
- * Project:  RIEGL RDB 2 driver
- * Purpose:  Add support for reading *.mpx RDB 2 files.
- * Author:   RIEGL Laser Measurement Systems GmbH (support@riegl.com)
- *
- ******************************************************************************
- * Copyright (c) 2019, RIEGL Laser Measurement Systems GmbH (support@riegl.com)
- *
- * SPDX-License-Identifier: MIT
- ****************************************************************************/
-
-#include "ogrgeojsonreader.h"
-
-#include "rdbdataset.hpp"
-
-#include <algorithm>
-#include <limits>
-#include <cmath>
-#include <sstream>
-
-namespace rdb
-{
-void RDBOverview::addRDBNode(RDBNode &oRDBNode, double dfXMin, double dfYMin,
-                             double dfXMax, double dfYMax)
-{
-    adfMinimum[0] = std::min(adfMinimum[0], dfXMin);
-    adfMaximum[0] = std::max(adfMaximum[0], dfXMax);
-
-    adfMinimum[1] = std::min(adfMinimum[1], dfYMin);
-    adfMaximum[1] = std::max(adfMaximum[1], dfYMax);
-
-    aoRDBNodes.push_back(oRDBNode);
-}
-
-void RDBOverview::setTileSize(double dfTileSizeIn)
-{
-    dfTileSize = dfTileSizeIn;
-    dfPixelSize = dfTileSize / 256.0;
-}
-
-template <typename T> struct CPLMallocGuard
-{
-    T *const pData = nullptr;
-
-    explicit CPLMallocGuard(std::size_t count)
-        : pData(static_cast<T *>(CPLMalloc(sizeof(T) * count)))
-    {
-    }
-
-    ~CPLMallocGuard()
-    {
-        CPLFree(pData);
-    }
-};
-
-template <typename T> class RDBRasterBandInternal;
-
-template <typename T> class RDBRasterBandInternal final : public RDBRasterBand
-{
-    std::vector<std::unique_ptr<RDBRasterBandInternal<T>>> aoOverviewBands;
-    std::vector<VRTSourcedRasterBand *> aoVRTRasterBand;
-
-  public:
-    RDBRasterBandInternal(
-        RDBDataset *poDSIn, const std::string &osAttributeNameIn,
-        const riegl::rdb::pointcloud::PointAttribute &oPointAttributeIn,
-        int nBandIn, GDALDataType eDataTypeIn, int nLevelIn)
-        : RDBRasterBand(poDSIn, osAttributeNameIn, oPointAttributeIn, nBandIn,
-                        eDataTypeIn, nLevelIn)
-    {
-        poDS = poDSIn;
-        nBand = nBandIn;
-
-        eDataType = eDataTypeIn;
-        eAccess = poDSIn->eAccess;
-
-        auto &oRDBOverview = poDSIn->aoRDBOverviews[nLevelIn];
-
-        nRasterXSize = static_cast<int>(
-            (oRDBOverview.adfMaximum[0] - oRDBOverview.adfMinimum[0]) * 256);
-        nRasterYSize = static_cast<int>(
-            (oRDBOverview.adfMaximum[1] - oRDBOverview.adfMinimum[1]) * 256);
-
-        nBlockXSize = 256;
-        nBlockYSize = 256;
-    }
-
-    ~RDBRasterBandInternal()
-    {
-    }
-
-    RDBRasterBandInternal(
-        RDBDataset *poDSIn, const std::string &osAttributeNameIn,
-        const riegl::rdb::pointcloud::PointAttribute &oPointAttributeIn,
-        int nBandIn, GDALDataType eDataTypeIn, int nLevelIn,
-        int nNumberOfLayers)
-        : RDBRasterBandInternal(poDSIn, osAttributeNameIn, oPointAttributeIn,
-                                nBandIn, eDataTypeIn, nLevelIn)
-    {
-        aoOverviewBands.resize(nNumberOfLayers);
-        poDSIn->apoVRTDataset.resize(nNumberOfLayers);
-
-        for (int i = nNumberOfLayers - 2; i >= 0; i--)
-        {
-            aoOverviewBands[i].reset(new RDBRasterBandInternal<T>(
-                poDSIn, osAttributeNameIn, oPointAttributeIn, nBandIn,
-                eDataTypeIn, i));
-            RDBOverview &oRDBOverview = poDSIn->aoRDBOverviews[i];
-
-            int nDatasetXSize = static_cast<int>(std::round(
-                (poDSIn->dfXMax - poDSIn->dfXMin) / oRDBOverview.dfPixelSize));
-
-            int nDatasetYSize = static_cast<int>(std::round(
-                (poDSIn->dfYMax - poDSIn->dfYMin) / oRDBOverview.dfPixelSize));
-
-            if (!poDSIn->apoVRTDataset[i])
-            {
-                poDSIn->apoVRTDataset[i].reset(
-                    new VRTDataset(nDatasetXSize, nDatasetYSize));
-            }
-
-            VRTAddBand(poDSIn->apoVRTDataset[i].get(), eDataType, nullptr);
-
-            VRTSourcedRasterBand *hVRTBand(dynamic_cast<VRTSourcedRasterBand *>(
-                poDSIn->apoVRTDataset[i]->GetRasterBand(nBandIn)));
-
-            int bSuccess = FALSE;
-            double dfNoDataValue =
-                RDBRasterBandInternal::GetNoDataValue(&bSuccess);
-            if (bSuccess == FALSE)
-            {
-                dfNoDataValue = VRT_NODATA_UNSET;
-            }
-
-            hVRTBand->AddSimpleSource(
-                aoOverviewBands[i].get(),
-                (poDSIn->dfXMin -
-                 oRDBOverview.adfMinimum[0] * oRDBOverview.dfTileSize) /
-                    (oRDBOverview.dfPixelSize),
-                (poDSIn->dfYMin -
-                 oRDBOverview.adfMinimum[1] * oRDBOverview.dfTileSize) /
-                    (oRDBOverview.dfPixelSize),
-                nDatasetXSize, nDatasetYSize, 0, 0, nDatasetXSize,
-                nDatasetYSize, "average", dfNoDataValue);
-
-            aoVRTRasterBand.push_back(hVRTBand);
-        }
-        poDS = poDSIn;
-        nBand = nBandIn;
-
-        eDataType = eDataTypeIn;
-        eAccess = poDSIn->eAccess;
-        nRasterXSize = poDSIn->nRasterXSize;
-        nRasterYSize = poDSIn->nRasterYSize;
-        nBlockXSize = 256;
-        nBlockYSize = 256;
-    }
-
-    double GetNoDataValue(int *pbSuccess) override
-    {
-        double dfInvalidValue = RDBRasterBand::GetNoDataValue(pbSuccess);
-
-        if (pbSuccess != nullptr && *pbSuccess == TRUE)
-        {
-            return dfInvalidValue;
-        }
-        else
-        {
-            if (oPointAttribute.maximumValue < std::numeric_limits<T>::max())
-            {
-                if (pbSuccess != nullptr)
-                {
-                    *pbSuccess = TRUE;
-                }
-                return std::numeric_limits<T>::max();
-            }
-            else if (oPointAttribute.minimumValue >
-                     std::numeric_limits<T>::lowest())
-            {
-                if (pbSuccess != nullptr)
-                {
-                    *pbSuccess = TRUE;
-                }
-                return std::numeric_limits<T>::lowest();
-            }
-            // Another no data value could be any value that is actually not in
-            // the data but in the range of specified rdb attribute. However,
-            // this could maybe be a problem when combining multiple files.
-
-            // Using always the maximum or minimum value in such cases might be
-            // at least consistent across multiple files.
-            if (pbSuccess != nullptr)
-            {
-                *pbSuccess = FALSE;
-            }
-            return 0.0;
-        }
-    }
-
-    virtual CPLErr IReadBlock(int nBlockXOff, int nBlockYOff,
-                              void *pImageIn) override
-    {
-        T *pImage = reinterpret_cast<T *>(pImageIn);
-
-        constexpr std::size_t nTileSize = 256 * 256;
-        if (std::isnan(oPointAttribute.invalidValue))
-        {
-            memset(pImageIn, 0, sizeof(T) * nTileSize);
-        }
-        else
-        {
-            for (std::size_t i = 0; i < nTileSize; i++)
-            {
-                pImage[i] = static_cast<T>(oPointAttribute.invalidValue);
-            }
-        }
-
-        try
-        {
-            RDBDataset *poRDBDs = dynamic_cast<RDBDataset *>(poDS);
-            if (poRDBDs != nullptr)
-            {
-                auto &oRDBOverview = poRDBDs->aoRDBOverviews[nLevel];
-                auto &aoRDBNodes = oRDBOverview.aoRDBNodes;
-
-                auto pIt = std::find_if(
-                    aoRDBNodes.begin(), aoRDBNodes.end(),
-                    [&](const RDBNode &poRDBNode)
-                    {
-                        return poRDBNode.nXBlockCoordinates == nBlockXOff &&
-                               poRDBNode.nYBlockCoordinates == nBlockYOff;
-                    });
-
-                if (pIt != aoRDBNodes.end())
-                {
-                    using type = RDBCoordinatesPlusData<T>;
-                    CPLMallocGuard<type> oData(pIt->nPointCount);
-
-                    uint32_t nPointsReturned = 0;
-                    {
-                        // is locking needed?
-                        // std::lock_guard<std::mutex>
-                        // oGuard(poRDBDs->oLock);
-                        auto oSelectQuery =
-                            poRDBDs->oPointcloud.select(pIt->iID);
-                        oSelectQuery.bindBuffer(
-                            poRDBDs->oPointcloud.pointAttribute()
-                                .primaryAttributeName(),
-                            oData.pData[0].adfCoordinates[0],
-                            static_cast<int32_t>(sizeof(type)));
-
-                        oSelectQuery.bindBuffer(
-                            osAttributeName, oData.pData[0].data,
-                            static_cast<int32_t>(sizeof(type)));
-
-                        nPointsReturned = oSelectQuery.next(pIt->nPointCount);
-                    }
-
-                    if (nPointsReturned > 0)
-                    {
-                        double dfHalvePixel = oRDBOverview.dfPixelSize * 0.5;
-
-                        double dfTileMinX =
-                            (std::floor((poRDBDs->dfXMin + dfHalvePixel) /
-                                        oRDBOverview.dfTileSize) +
-                             nBlockXOff) *
-                            oRDBOverview.dfTileSize;
-                        double dfTileMinY =
-                            (std::floor((poRDBDs->dfYMin + dfHalvePixel) /
-                                        oRDBOverview.dfTileSize) +
-                             nBlockYOff) *
-                            oRDBOverview.dfTileSize;
-
-                        for (uint32_t i = 0; i < nPointsReturned; i++)
-                        {
-                            int dfPixelX = static_cast<int>(
-                                std::floor((oData.pData[i].adfCoordinates[0] +
-                                            dfHalvePixel - dfTileMinX) /
-                                           oRDBOverview.dfPixelSize));
-
-                            int dfPixelY = static_cast<int>(
-                                std::floor((oData.pData[i].adfCoordinates[1] +
-                                            dfHalvePixel - dfTileMinY) /
-                                           oRDBOverview.dfPixelSize));
-
-                            pImage[dfPixelY * 256 + dfPixelX] =
-                                oData.pData[i].data;
-                        }
-                    }
-                }
-            }
-        }
-        catch (const riegl::rdb::Error &oException)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "RDB error: %s, %s",
-                     oException.what(), oException.details());
-            return CE_Failure;
-        }
-        catch (const std::exception &oException)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Error: %s",
-                     oException.what());
-            return CE_Failure;
-        }
-        catch (...)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Unknown error in IReadBlock.");
-            return CE_Failure;
-        }
-        return CE_None;
-    }
-
-    virtual int GetOverviewCount() override
-    {
-        RDBDataset *poRDBDs = dynamic_cast<RDBDataset *>(poDS);
-        if (poRDBDs == nullptr)
-        {
-            return 0;
-        }
-        return static_cast<int>(aoVRTRasterBand.size());
-    }
-
-    virtual GDALRasterBand *GetOverview(int i) override
-    {
-        return aoVRTRasterBand[i];
-    }
-};
-
-RDBDataset::~RDBDataset()
-{
-}
-
-void RDBDataset::SetBandInternal(
-    RDBDataset *poDs, const std::string &osAttributeName,
-    const riegl::rdb::pointcloud::PointAttribute &oPointAttribute,
-    riegl::rdb::pointcloud::DataType eRDBDataType, int nLevel,
-    int nNumberOfLayers, int &nBandIndex)
-{
-    RDBRasterBand *poBand = nullptr;
-    // map riegl rdb datatype to gdal data type
-    switch (eRDBDataType)
-    {
-        case riegl::rdb::pointcloud::DataType::UINT8:
-        // Should I do ignore the other type?
-        case riegl::rdb::pointcloud::DataType::INT8:
-            poBand = new RDBRasterBandInternal<std::uint8_t>(
-                poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Byte,
-                nLevel, nNumberOfLayers);
-            break;
-        case riegl::rdb::pointcloud::DataType::UINT16:
-            poBand = new RDBRasterBandInternal<std::uint16_t>(
-                poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_UInt16,
-                nLevel, nNumberOfLayers);
-            break;
-        case riegl::rdb::pointcloud::DataType::INT16:
-            poBand = new RDBRasterBandInternal<std::int16_t>(
-                poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Int16,
-                nLevel, nNumberOfLayers);
-            break;
-        case riegl::rdb::pointcloud::DataType::UINT32:
-            poBand = new RDBRasterBandInternal<std::uint32_t>(
-                poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_UInt32,
-                nLevel, nNumberOfLayers);
-            break;
-        case riegl::rdb::pointcloud::DataType::INT32:
-            poBand = new RDBRasterBandInternal<std::int32_t>(
-                poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Int32,
-                nLevel, nNumberOfLayers);
-            break;
-        case riegl::rdb::pointcloud::DataType::FLOAT32:
-            poBand = new RDBRasterBandInternal<float>(
-                poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Float32,
-                nLevel, nNumberOfLayers);
-            break;
-        case riegl::rdb::pointcloud::DataType::FLOAT64:
-            poBand = new RDBRasterBandInternal<double>(
-                poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Float64,
-                nLevel, nNumberOfLayers);
-            break;
-        default:
-            // for all reamining use double. e.g. u/int64_t
-            // an alternate option would be to check the data in the rdb and use
-            // the minimum required data type. could be a problem when working
-            // with multiple files.
-            poBand = new RDBRasterBandInternal<double>(
-                poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Float64,
-                nLevel, nNumberOfLayers);
-            break;
-    }
-
-    poDs->SetBand(nBandIndex, poBand);
-    nBandIndex++;
-}
-
-void RDBDataset::addRDBNode(const riegl::rdb::pointcloud::GraphNode &oNode,
-                            double dfTileSize, std::size_t nLevel)
-{
-    double adfNodeMinimum[2];
-    double adfNodeMaximum[2];
-
-    oStatQuery.minimum(oNode.id,
-                       oPointcloud.pointAttribute().primaryAttributeName(),
-                       adfNodeMinimum[0]);
-    oStatQuery.maximum(oNode.id,
-                       oPointcloud.pointAttribute().primaryAttributeName(),
-                       adfNodeMaximum[0]);
-
-    int dfXNodeMin = static_cast<int>(
-        std::floor((adfNodeMinimum[0] + dfSizeOfPixel * 0.5) / dfTileSize));
-    int dfYNodeMin = static_cast<int>(
-        std::floor((adfNodeMinimum[1] + dfSizeOfPixel * 0.5) / dfTileSize));
-
-    int dfXNodeMax = static_cast<int>(
-        std::ceil((adfNodeMaximum[0] + dfSizeOfPixel * 0.5) / dfTileSize));
-    int dfYNodeMax = static_cast<int>(
-        std::ceil((adfNodeMaximum[1] + dfSizeOfPixel * 0.5) / dfTileSize));
-
-    RDBNode oRDBNode;
-
-    oRDBNode.iID = oNode.id;
-    oRDBNode.nPointCount = oNode.pointCountNode;
-    oRDBNode.nXBlockCoordinates =
-        dfXNodeMin - static_cast<int>(std::floor(
-                         (dfXMin + dfSizeOfPixel * 0.5) / dfTileSize));
-    oRDBNode.nYBlockCoordinates =
-        dfYNodeMin - static_cast<int>(std::floor(
-                         (dfYMin + dfSizeOfPixel * 0.5) / dfTileSize));
-
-    if (aoRDBOverviews.size() <= nLevel)
-    {
-        aoRDBOverviews.resize(nLevel + 1);
-    }
-    aoRDBOverviews[nLevel].setTileSize(dfTileSize);
-
-    aoRDBOverviews[nLevel].addRDBNode(oRDBNode, dfXNodeMin, dfYNodeMin,
-                                      dfXNodeMax, dfYNodeMax);
-}
-
-double
-RDBDataset::traverseRDBNodes(const riegl::rdb::pointcloud::GraphNode &oNode,
-                             std::size_t nLevel)
-{
-    if (oNode.children.size() == 0)
-    {
-        addRDBNode(oNode, dfSizeOfTile, nLevel);
-        return dfSizeOfTile;
-    }
-    else
-    {
-        double dfSizeOfChildTile = 0.0;
-        for (auto &&oChild : oNode.children)
-        {
-            dfSizeOfChildTile = traverseRDBNodes(oChild, nLevel + 1);
-        }
-        if (dfSizeOfChildTile >= dfSizeOfTile && oNode.pointCountNode > 0)
-        {
-            double dfTileSizeCurrentLevel = dfSizeOfChildTile * 2.0;
-
-            addRDBNode(oNode, dfTileSizeCurrentLevel, nLevel);
-
-            return dfTileSizeCurrentLevel;
-        }
-        return 0.0;
-    }
-}
-
-RDBDataset::RDBDataset(GDALOpenInfo *poOpenInfo) : oPointcloud(oContext)
-{
-    int nBandIndex = 1;
-
-    riegl::rdb::pointcloud::OpenSettings oSettings(oContext);
-    oPointcloud.open(poOpenInfo->pszFilename, oSettings);
-
-    oStatQuery = oPointcloud.stat();
-
-    std::string oPrimaryAttribute =
-        oPointcloud.pointAttribute().primaryAttributeName();
-
-    oStatQuery.minimum(1, oPrimaryAttribute, adfMinimumDs[0]);
-    oStatQuery.maximum(1, oPrimaryAttribute, adfMaximumDs[0]);
-
-    dfResolution =
-        oPointcloud.pointAttribute().get(oPrimaryAttribute).resolution;
-
-    nChunkSize = oPointcloud.management().getChunkSizeLOD();
-
-    std::string oPixelInfo = oPointcloud.metaData().get("riegl.pixel_info");
-
-    json_object *poObj = nullptr;
-    if (!OGRJSonParse(oPixelInfo.c_str(), &poObj, true))
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "riegl.pixel_info is invalid JSon: %s", oPixelInfo.c_str());
-    }
-    JsonObjectUniquePtr oObj(poObj);
-
-    json_object *poPixelSize = CPL_json_object_object_get(poObj, "size");
-
-    if (poPixelSize != nullptr)
-    {
-        json_object *poSize0 = json_object_array_get_idx(poPixelSize, 0);
-        if (poSize0 != nullptr)
-        {
-            dfSizeOfPixel = json_object_get_double(poSize0);
-        }
-    }
-
-    ReadGeoreferencing();
-
-    dfSizeOfTile = dfSizeOfPixel * 256;  // 2^8
-
-    double dfHalvePixel = dfSizeOfPixel * 0.5;
-    dfXMin = std::floor((adfMinimumDs[0] + dfHalvePixel) / dfSizeOfTile) *
-             dfSizeOfTile;
-    dfYMin = std::floor((adfMinimumDs[1] + dfHalvePixel) / dfSizeOfTile) *
-             dfSizeOfTile;
-
-    dfXMax = std::ceil((adfMaximumDs[0] + dfHalvePixel) / dfSizeOfTile) *
-             dfSizeOfTile;
-    dfYMax = std::ceil((adfMaximumDs[1] + dfHalvePixel) / dfSizeOfTile) *
-             dfSizeOfTile;
-
-    nRasterXSize = static_cast<int>((dfXMax - dfXMin) / dfSizeOfPixel);
-    nRasterYSize = static_cast<int>((dfYMax - dfYMin) / dfSizeOfPixel);
-
-    traverseRDBNodes(oStatQuery.index());
-
-    aoRDBOverviews.erase(
-        std::remove_if(aoRDBOverviews.begin(), aoRDBOverviews.end(),
-                       [](const RDBOverview &oRDBOverView)
-                       { return oRDBOverView.aoRDBNodes.empty(); }),
-        aoRDBOverviews.end());
-
-    double dfLevelFactor = std::pow(2, aoRDBOverviews.size());
-    nRasterXSize = static_cast<int>(std::ceil(nRasterXSize / dfLevelFactor) *
-                                    dfLevelFactor);
-    nRasterYSize = static_cast<int>(std::ceil(nRasterYSize / dfLevelFactor) *
-                                    dfLevelFactor);
-
-    dfXMax = dfXMin + nRasterXSize * dfSizeOfPixel;
-    dfYMax = dfYMin + nRasterYSize * dfSizeOfPixel;
-
-    riegl::rdb::pointcloud::PointAttributes &oPointAttribute =
-        oPointcloud.pointAttribute();
-
-    int nNumberOfLevels = static_cast<int>(aoRDBOverviews.size());
-    std::vector<std::string> aoExistingPointAttributes = oPointAttribute.list();
-
-    for (auto &&osAttributeName : aoExistingPointAttributes)
-    {
-        riegl::rdb::pointcloud::PointAttribute oAttribute =
-            oPointAttribute.get(osAttributeName);
-
-        if (osAttributeName == oPointAttribute.primaryAttributeName())
-        {
-            continue;
-        }
-        if (oAttribute.length == 1)
-        {
-            SetBandInternal(this, osAttributeName, oAttribute,
-                            oAttribute.dataType(), nNumberOfLevels - 1,
-                            nNumberOfLevels, nBandIndex);
-        }
-        else
-        {
-            for (uint32_t i = 0; i < oAttribute.length; i++)
-            {
-                std::ostringstream oOss;
-                oOss << osAttributeName << '[' << i << ']';
-                SetBandInternal(this, oOss.str(), oAttribute,
-                                oAttribute.dataType(), nNumberOfLevels - 1,
-                                nNumberOfLevels, nBandIndex);
-            }
-        }
-    }
-}
-
-GDALDataset *RDBDataset::Open(GDALOpenInfo *poOpenInfo)
-{
-    if (!Identify(poOpenInfo))
-    {
-        return nullptr;
-    }
-
-    if (poOpenInfo->eAccess == GA_Update)
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "The RDB driver does not support update access to existing "
-                 "datasets.");
-        return nullptr;
-    }
-
-    if (poOpenInfo->fpL == nullptr)
-    {
-        return nullptr;
-    }
-    try
-    {
-        std::unique_ptr<RDBDataset> poDS(new RDBDataset(poOpenInfo));
-        // std::swap(poDS->fp, poOpenInfo->fpL);
-        // Initialize any PAM information.
-        poDS->SetDescription(poOpenInfo->pszFilename);
-        poDS->TryLoadXML();
-
-        return poDS.release();
-    }
-    catch (const riegl::rdb::Error &oException)
-    {
-        CPLError(CE_Failure, CPLE_OpenFailed, "RDB error: %s, %s",
-                 oException.what(), oException.details());
-        return nullptr;
-    }
-
-    catch (const std::exception &oException)
-    {
-        CPLError(CE_Failure, CPLE_OpenFailed, "Error: %s", oException.what());
-        return nullptr;
-    }
-    catch (...)
-    {
-        CPLError(CE_Failure, CPLE_OpenFailed, "Unknown error in Open.");
-        return nullptr;
-    }
-
-    return nullptr;
-}
-
-int RDBDataset::Identify(GDALOpenInfo *poOpenInfo)
-{
-    const char *psHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
-    if (poOpenInfo->nHeaderBytes < 32)
-    {
-        return FALSE;
-    }
-
-    constexpr int kSizeOfRDBHeaderIdentifier = 32;
-    constexpr char szRDBHeaderIdentifier[kSizeOfRDBHeaderIdentifier] =
-        "RIEGL LMS RDB 2 POINTCLOUD FILE";
-
-    if (strncmp(psHeader, szRDBHeaderIdentifier, kSizeOfRDBHeaderIdentifier))
-    {
-        // A more comprehensive test could be done by the library.
-        // Should file -> library incompatibilities handled in Identify or
-        // in the Open function?
-        return FALSE;
-    }
-    return TRUE;
-}
-
-CPLErr RDBDataset::GetGeoTransform(double *padfTransform)
-{
-    padfTransform[0] = dfXMin;
-    padfTransform[1] = dfSizeOfPixel;
-    padfTransform[2] = 0;
-
-    padfTransform[3] = dfYMin;
-    padfTransform[4] = 0;
-    padfTransform[5] = dfSizeOfPixel;
-
-    return CE_None;
-}
-
-const OGRSpatialReference *RDBDataset::GetSpatialRef() const
-{
-    return &oSpatialReference;
-}
-
-void RDBDataset::ReadGeoreferencing()
-{
-    if (osWktString.empty())
-    {
-        try
-        {
-            std::string oPixelInfo =
-                oPointcloud.metaData().get("riegl.geo_tag");
-
-            json_object *poObj = nullptr;
-            if (!OGRJSonParse(oPixelInfo.c_str(), &poObj, true))
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "riegl.geo_tag is invalid JSon: %s",
-                         oPixelInfo.c_str());
-            }
-            JsonObjectUniquePtr oObj(poObj);
-
-            json_object *poCrs = CPL_json_object_object_get(poObj, "crs");
-
-            if (poCrs != nullptr)
-            {
-                json_object *poWkt = CPL_json_object_object_get(poCrs, "wkt");
-
-                if (poWkt != nullptr)
-                {
-                    osWktString = json_object_get_string(poWkt);
-                    oSpatialReference.importFromWkt(osWktString.c_str());
-                    oSpatialReference.SetAxisMappingStrategy(
-                        OAMS_TRADITIONAL_GIS_ORDER);
-                }
-            }
-        }
-        catch (const riegl::rdb::Error &oException)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "RDB error: %s, %s",
-                     oException.what(), oException.details());
-        }
-        catch (const std::exception &oException)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Error: %s",
-                     oException.what());
-        }
-        catch (...)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Unknown error in IReadBlock.");
-        }
-    }
-}
-
-RDBRasterBand::RDBRasterBand(
-    RDBDataset *poDSIn, const std::string &osAttributeNameIn,
-    const riegl::rdb::pointcloud::PointAttribute &oPointAttributeIn,
-    int nBandIn, GDALDataType eDataTypeIn, int nLevelIn)
-    : osAttributeName(osAttributeNameIn), oPointAttribute(oPointAttributeIn),
-      nLevel(nLevelIn)
-{
-
-    osDescription.Printf("%s (%s)", oPointAttribute.title.c_str(),
-                         osAttributeName.c_str());
-
-    poDS = poDSIn;
-    nBand = nBandIn;
-
-    eDataType = eDataTypeIn;
-    eAccess = poDSIn->eAccess;
-    nRasterXSize = poDSIn->nRasterXSize;
-    nRasterYSize = poDSIn->nRasterYSize;
-    nBlockXSize = 256;
-    nBlockYSize = 256;
-}
-
-double RDBRasterBand::GetNoDataValue(int *pbSuccess)
-{
-    if (!std::isnan(oPointAttribute.invalidValue))
-    {
-        if (pbSuccess != nullptr)
-        {
-            *pbSuccess = TRUE;
-        }
-        return oPointAttribute.invalidValue;
-    }
-    else
-    {
-        if (pbSuccess != nullptr)
-        {
-            *pbSuccess = FALSE;
-        }
-        return 0.0;
-    }
-}
-
-const char *RDBRasterBand::GetDescription() const
-{
-    return osDescription.c_str();
-}
-
-}  // namespace rdb
-
-void GDALRegister_RDB()
-{
-    if (!GDAL_CHECK_VERSION("RDB"))
-        return;
-    if (GDALGetDriverByName("RDB") != NULL)
-        return;
-    GDALDriver *poDriver = new GDALDriver();
-    poDriver->SetDescription("RDB");
-    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
-    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "RIEGL RDB Map Pixel (.mpx)");
-    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/rdb.html");
-    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "mpx");
-    poDriver->pfnOpen = rdb::RDBDataset::Open;
-    poDriver->pfnIdentify = rdb::RDBDataset::Identify;
-    GetGDALDriverManager()->RegisterDriver(poDriver);
-}
-
-// includes the cpp wrapper of the rdb library
-#include <riegl/rdb.cpp>
diff --git a/frmts/rdb/rdbdataset.hpp b/frmts/rdb/rdbdataset.hpp
deleted file mode 100644
index 89a83b78d2c4..000000000000
--- a/frmts/rdb/rdbdataset.hpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/******************************************************************************
- * Project:  RIEGL RDB 2 driver
- * Purpose:  Add support for reading *.mpx RDB 2 files.
- * Author:   RIEGL Laser Measurement Systems GmbH (support@riegl.com)
- *
- ******************************************************************************
- * Copyright (c) 2019, RIEGL Laser Measurement Systems GmbH (support@riegl.com)
- *
- * SPDX-License-Identifier: MIT
- ****************************************************************************/
-
-#ifndef RDB_DATASET_INCLUDED
-#define RDB_DATASET_INCLUDED
-
-#include "../frmts/vrt/vrtdataset.h"
-#include "gdal_pam.h"
-
-#include <riegl/rdb.hpp>
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <mutex>
-#include <string>
-
-namespace rdb
-{
-class RDBRasterBand;
-
-struct RDBNode
-{
-    int nXBlockCoordinates = 0;
-    int nYBlockCoordinates = 0;
-    riegl::rdb::pointcloud::GraphNode::ID iID = 0;
-    uint64_t nPointCount = 0;
-};
-
-struct RDBOverview
-{
-    double dfTileSize = 0;
-    double dfPixelSize = 0;
-    double adfMinimum[2] = {std::numeric_limits<double>::max(),
-                            std::numeric_limits<double>::max()};
-    double adfMaximum[2] = {std::numeric_limits<double>::lowest(),
-                            std::numeric_limits<double>::lowest()};
-    std::vector<RDBNode> aoRDBNodes;
-    void addRDBNode(RDBNode &oRDBNode, double dfXMin, double dfYMin,
-                    double dfXMax, double dfYMax);
-    void setTileSize(double dfTileSizeIn);
-};
-
-template <typename T> struct RDBCoordinatesPlusData
-{
-    double adfCoordinates[2];
-    T data;
-};
-
-class RDBDataset final : public GDALPamDataset
-{
-    friend class RDBRasterBand;
-    template <typename T> friend class RDBRasterBandInternal;
-
-    // is locking needed?
-    // std::mutex oLock;
-    FILE *fp = nullptr;
-    riegl::rdb::Context oContext;
-    riegl::rdb::Pointcloud oPointcloud;
-    riegl::rdb::pointcloud::QueryStat oStatQuery;
-
-    OGRSpatialReference oSpatialReference;
-
-    double dfResolution = 0;
-    int nChunkSize = 0;
-    double dfSizeOfTile;
-    double dfSizeOfPixel;
-    CPLString osWktString;
-
-    std::vector<RDBOverview> aoRDBOverviews;
-    std::vector<std::unique_ptr<VRTDataset>> apoVRTDataset;
-
-    double dfXMin;
-    double dfYMin;
-
-    double dfXMax;
-    double dfYMax;
-
-    double adfMinimumDs[2] = {};
-    double adfMaximumDs[2] = {};
-
-  public:
-    explicit RDBDataset(GDALOpenInfo *poOpenInfo);
-    ~RDBDataset();
-
-    static GDALDataset *Open(GDALOpenInfo *poOpenInfo);
-    static int Identify(GDALOpenInfo *poOpenInfo);
-
-    CPLErr GetGeoTransform(double *padfTransform) override;
-    const OGRSpatialReference *GetSpatialRef() const override;
-
-  protected:
-    static void SetBandInternal(
-        RDBDataset *poDs, const std::string &osAttributeName,
-        const riegl::rdb::pointcloud::PointAttribute &oPointAttribute,
-        riegl::rdb::pointcloud::DataType eRDBDataType, int nLevel,
-        int nNumberOfLevels, int &nBandIndex);
-    void addRDBNode(const riegl::rdb::pointcloud::GraphNode &oNode,
-                    double dfTileSize, std::size_t nLeve);
-    double traverseRDBNodes(const riegl::rdb::pointcloud::GraphNode &oNode,
-                            std::size_t nLevel = 0);
-
-    void ReadGeoreferencing();
-};
-
-class RDBRasterBand CPL_NON_FINAL : public GDALPamRasterBand
-{
-  protected:
-    CPLString osAttributeName;
-    CPLString osDescription;
-    riegl::rdb::pointcloud::PointAttribute oPointAttribute;
-    int nLevel;
-
-  public:
-    RDBRasterBand(
-        RDBDataset *poDSIn, const std::string &osAttributeName,
-        const riegl::rdb::pointcloud::PointAttribute &oPointAttributeIn,
-        int nBandIn, GDALDataType eDataTypeIn, int nLevelIn);
-
-    virtual double GetNoDataValue(int *pbSuccess = nullptr) override;
-    virtual const char *GetDescription() const override;
-};
-}  // namespace rdb
-
-void GDALRegister_RDB();
-
-#endif  // RDB_DATASET_INCLUDED