RFC104: add capability of 'filter' and 'reproject' vector pipeline steps to be standalone too

This commit is contained in:
Even Rouault 2024-11-25 14:01:22 +01:00
parent 6544ad4ccd
commit 580958dfda
No known key found for this signature in database
GPG Key ID: 33EBBFC47B3DD87D
12 changed files with 198 additions and 32 deletions

View File

@ -15,6 +15,8 @@
#include "gdalalg_vector_info.h"
#include "gdalalg_vector_convert.h"
#include "gdalalg_vector_pipeline.h"
#include "gdalalg_vector_filter.h"
#include "gdalalg_vector_reproject.h"
/************************************************************************/
/* GDALVectorAlgorithm */
@ -37,6 +39,8 @@ class GDALVectorAlgorithm final : public GDALAlgorithm
RegisterSubAlgorithm<GDALVectorInfoAlgorithm>();
RegisterSubAlgorithm<GDALVectorConvertAlgorithm>();
RegisterSubAlgorithm<GDALVectorPipelineAlgorithm>();
RegisterSubAlgorithm<GDALVectorFilterAlgorithmStandalone>();
RegisterSubAlgorithm<GDALVectorReprojectAlgorithmStandalone>();
}
private:

View File

@ -25,8 +25,9 @@
/* GDALVectorFilterAlgorithm::GDALVectorFilterAlgorithm() */
/************************************************************************/
GDALVectorFilterAlgorithm::GDALVectorFilterAlgorithm()
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL)
GDALVectorFilterAlgorithm::GDALVectorFilterAlgorithm(bool standaloneStep)
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
standaloneStep)
{
auto &arg =
AddArg("bbox", 0, _("Bounding box as xmin,ymin,xmax,ymax"), &m_bbox)
@ -51,10 +52,10 @@ GDALVectorFilterAlgorithm::GDALVectorFilterAlgorithm()
}
/************************************************************************/
/* GDALVectorFilterAlgorithm::RunImpl() */
/* GDALVectorFilterAlgorithm::RunStep() */
/************************************************************************/
bool GDALVectorFilterAlgorithm::RunImpl(GDALProgressFunc, void *)
bool GDALVectorFilterAlgorithm::RunStep(GDALProgressFunc, void *)
{
CPLAssert(m_inputDataset.GetDatasetRef());
CPLAssert(m_outputDataset.GetName().empty());

View File

@ -21,11 +21,12 @@
/* GDALVectorFilterAlgorithm */
/************************************************************************/
class GDALVectorFilterAlgorithm final : public GDALVectorPipelineStepAlgorithm
class GDALVectorFilterAlgorithm /* non final */
: public GDALVectorPipelineStepAlgorithm
{
public:
static constexpr const char *NAME = "filter";
static constexpr const char *DESCRIPTION = "Filter.";
static constexpr const char *DESCRIPTION = "Filter a vector dataset.";
static constexpr const char *HELP_URL = ""; // TODO
static std::vector<std::string> GetAliases()
@ -33,14 +34,28 @@ class GDALVectorFilterAlgorithm final : public GDALVectorPipelineStepAlgorithm
return {};
}
GDALVectorFilterAlgorithm();
explicit GDALVectorFilterAlgorithm(bool standaloneStep = false);
private:
bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override;
bool RunStep(GDALProgressFunc pfnProgress, void *pProgressData) override;
std::vector<double> m_bbox{};
};
/************************************************************************/
/* GDALVectorFilterAlgorithmStandalone */
/************************************************************************/
class GDALVectorFilterAlgorithmStandalone final
: public GDALVectorFilterAlgorithm
{
public:
GDALVectorFilterAlgorithmStandalone()
: GDALVectorFilterAlgorithm(/* standaloneStep = */ true)
{
}
};
//! @endcond
#endif /* GDALALG_VECTOR_FILTER_INCLUDED */

View File

@ -28,6 +28,24 @@
#define _(x) (x)
#endif
/************************************************************************/
/* GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm() */
/************************************************************************/
GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm(
const std::string &name, const std::string &description,
const std::string &helpURL, bool standaloneStep)
: GDALAlgorithm(name, description, helpURL),
m_standaloneStep(standaloneStep)
{
if (m_standaloneStep)
{
AddInputArgs(false);
AddProgressArg();
AddOutputArgs(false, false);
}
}
/************************************************************************/
/* GDALVectorPipelineStepAlgorithm::AddInputArgs() */
/************************************************************************/
@ -81,12 +99,69 @@ void GDALVectorPipelineStepAlgorithm::AddOutputArgs(
.SetHiddenForCLI(hiddenForCLI);
}
/************************************************************************/
/* GDALVectorPipelineStepAlgorithm::RunImpl() */
/************************************************************************/
bool GDALVectorPipelineStepAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
void *pProgressData)
{
if (m_standaloneStep)
{
GDALVectorReadAlgorithm readAlg;
for (auto &arg : readAlg.GetArgs())
{
auto stepArg = GetArg(arg->GetName());
if (stepArg && stepArg->IsExplicitlySet())
{
arg->SetSkipIfAlreadySet(true);
arg->SetFrom(*stepArg);
}
}
GDALVectorWriteAlgorithm writeAlg;
for (auto &arg : writeAlg.GetArgs())
{
auto stepArg = GetArg(arg->GetName());
if (stepArg && stepArg->IsExplicitlySet())
{
arg->SetSkipIfAlreadySet(true);
arg->SetFrom(*stepArg);
}
}
bool ret = false;
if (readAlg.Run())
{
m_inputDataset.Set(readAlg.m_outputDataset.GetDatasetRef());
m_outputDataset.Set(nullptr);
if (RunStep(nullptr, nullptr))
{
writeAlg.m_inputDataset.Set(m_outputDataset.GetDatasetRef());
if (writeAlg.Run(pfnProgress, pProgressData))
{
m_outputDataset.Set(
writeAlg.m_outputDataset.GetDatasetRef());
ret = true;
}
}
}
return ret;
}
else
{
return RunStep(pfnProgress, pProgressData);
}
}
/************************************************************************/
/* GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm() */
/************************************************************************/
GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm()
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL)
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
/*standaloneStep=*/false)
{
AddInputArgs(/* hiddenForCLI = */ true);
AddProgressArg();
@ -369,10 +444,10 @@ bool GDALVectorPipelineAlgorithm::ParseCommandLineArguments(
}
/************************************************************************/
/* GDALVectorPipelineAlgorithm::RunImpl() */
/* GDALVectorPipelineAlgorithm::RunStep() */
/************************************************************************/
bool GDALVectorPipelineAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
bool GDALVectorPipelineAlgorithm::RunStep(GDALProgressFunc pfnProgress,
void *pProgressData)
{
if (m_steps.empty())

View File

@ -26,16 +26,18 @@ class GDALVectorPipelineStepAlgorithm /* non final */ : public GDALAlgorithm
protected:
GDALVectorPipelineStepAlgorithm(const std::string &name,
const std::string &description,
const std::string &helpURL)
: GDALAlgorithm(name, description, helpURL)
{
}
const std::string &helpURL,
bool standaloneStep);
friend class GDALVectorPipelineAlgorithm;
virtual bool RunStep(GDALProgressFunc pfnProgress, void *pProgressData) = 0;
void AddInputArgs(bool hiddenForCLI);
void AddOutputArgs(bool hiddenForCLI, bool shortNameOutputLayerAllowed);
bool m_standaloneStep = false;
// Input arguments
GDALArgDatasetValue m_inputDataset{};
std::vector<std::string> m_openOptions{};
@ -52,6 +54,9 @@ class GDALVectorPipelineStepAlgorithm /* non final */ : public GDALAlgorithm
bool m_overwriteLayer = false;
bool m_appendLayer = false;
std::string m_outputLayerName{};
private:
bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override;
};
/************************************************************************/
@ -102,7 +107,7 @@ class GDALVectorPipelineAlgorithm final : public GDALVectorPipelineStepAlgorithm
private:
std::string m_pipeline{};
bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override;
bool RunStep(GDALProgressFunc pfnProgress, void *pProgressData) override;
std::unique_ptr<GDALVectorPipelineStepAlgorithm>
GetStepAlg(const std::string &name) const;

View File

@ -26,7 +26,8 @@
/************************************************************************/
GDALVectorReadAlgorithm::GDALVectorReadAlgorithm()
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL)
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
/* standaloneStep =*/false)
{
AddInputArgs(/* hiddenForCLI = */ false);
}
@ -62,10 +63,10 @@ class GDALVectorReadAlgorithmDataset final : public GDALDataset
} // namespace
/************************************************************************/
/* GDALVectorReadAlgorithm::RunImpl() */
/* GDALVectorReadAlgorithm::RunStep() */
/************************************************************************/
bool GDALVectorReadAlgorithm::RunImpl(GDALProgressFunc, void *)
bool GDALVectorReadAlgorithm::RunStep(GDALProgressFunc, void *)
{
CPLAssert(m_inputDataset.GetDatasetRef());
CPLAssert(m_outputDataset.GetName().empty());

View File

@ -36,7 +36,7 @@ class GDALVectorReadAlgorithm final : public GDALVectorPipelineStepAlgorithm
GDALVectorReadAlgorithm();
private:
bool RunImpl(GDALProgressFunc, void *) override;
bool RunStep(GDALProgressFunc, void *) override;
};
//! @endcond

View File

@ -27,8 +27,9 @@
/* GDALVectorReprojectAlgorithm::GDALVectorReprojectAlgorithm() */
/************************************************************************/
GDALVectorReprojectAlgorithm::GDALVectorReprojectAlgorithm()
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL)
GDALVectorReprojectAlgorithm::GDALVectorReprojectAlgorithm(bool standaloneStep)
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
standaloneStep)
{
AddArg("src-crs", 's', _("Source CRS"), &m_srsCrs).AddHiddenAlias("s_srs");
AddArg("dst-crs", 'd', _("Destination CRS"), &m_dstCrs)
@ -68,10 +69,10 @@ class GDALVectorReprojectAlgorithmDataset final : public GDALDataset
} // namespace
/************************************************************************/
/* GDALVectorReprojectAlgorithm::RunImpl() */
/* GDALVectorReprojectAlgorithm::RunStep() */
/************************************************************************/
bool GDALVectorReprojectAlgorithm::RunImpl(GDALProgressFunc, void *)
bool GDALVectorReprojectAlgorithm::RunStep(GDALProgressFunc, void *)
{
CPLAssert(m_inputDataset.GetDatasetRef());
CPLAssert(m_outputDataset.GetName().empty());

View File

@ -21,12 +21,12 @@
/* GDALVectorReprojectAlgorithm */
/************************************************************************/
class GDALVectorReprojectAlgorithm final
class GDALVectorReprojectAlgorithm /* non final */
: public GDALVectorPipelineStepAlgorithm
{
public:
static constexpr const char *NAME = "reproject";
static constexpr const char *DESCRIPTION = "Reproject.";
static constexpr const char *DESCRIPTION = "Reproject a vector dataset.";
static constexpr const char *HELP_URL = ""; // TODO
static std::vector<std::string> GetAliases()
@ -34,15 +34,29 @@ class GDALVectorReprojectAlgorithm final
return {};
}
GDALVectorReprojectAlgorithm();
explicit GDALVectorReprojectAlgorithm(bool standaloneStep = false);
private:
bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override;
bool RunStep(GDALProgressFunc pfnProgress, void *pProgressData) override;
std::string m_srsCrs{};
std::string m_dstCrs{};
};
/************************************************************************/
/* GDALVectorReprojectAlgorithmStandalone */
/************************************************************************/
class GDALVectorReprojectAlgorithmStandalone final
: public GDALVectorReprojectAlgorithm
{
public:
GDALVectorReprojectAlgorithmStandalone()
: GDALVectorReprojectAlgorithm(/* standaloneStep = */ true)
{
}
};
//! @endcond
#endif /* GDALALG_VECTOR_REPROJECT_INCLUDED */

View File

@ -27,17 +27,18 @@
/************************************************************************/
GDALVectorWriteAlgorithm::GDALVectorWriteAlgorithm()
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL)
: GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
/* standaloneStep =*/false)
{
AddOutputArgs(/* hiddenForCLI = */ false,
/* shortNameOutputLayerAllowed=*/true);
}
/************************************************************************/
/* GDALVectorWriteAlgorithm::RunImpl() */
/* GDALVectorWriteAlgorithm::RunStep() */
/************************************************************************/
bool GDALVectorWriteAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
bool GDALVectorWriteAlgorithm::RunStep(GDALProgressFunc pfnProgress,
void *pProgressData)
{
CPLAssert(m_inputDataset.GetDatasetRef());

View File

@ -36,7 +36,7 @@ class GDALVectorWriteAlgorithm final : public GDALVectorPipelineStepAlgorithm
GDALVectorWriteAlgorithm();
private:
bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override;
bool RunStep(GDALProgressFunc pfnProgress, void *pProgressData) override;
};
//! @endcond

View File

@ -0,0 +1,49 @@
#!/usr/bin/env pytest
# -*- coding: utf-8 -*-
###############################################################################
# Project: GDAL/OGR Test Suite
# Purpose: 'gdal vector filter' testing
# Author: Even Rouault <even dot rouault @ spatialys.com>
#
###############################################################################
# Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
#
# SPDX-License-Identifier: MIT
###############################################################################
from osgeo import gdal
def get_filter_alg():
reg = gdal.GetGlobalAlgorithmRegistry()
vector = reg.InstantiateAlg("vector")
return vector.InstantiateSubAlgorithm("filter")
def test_gdalalg_vector_filter_no_filter(tmp_vsimem):
out_filename = str(tmp_vsimem / "out.shp")
filter_alg = get_filter_alg()
assert filter_alg.ParseCommandLineArguments(["../ogr/data/poly.shp", out_filename])
assert filter_alg.Run()
ds = filter_alg.GetArg("output").Get().GetDataset()
assert ds.GetLayer(0).GetFeatureCount() == 10
assert filter_alg.Finalize()
ds = None
with gdal.OpenEx(out_filename) as ds:
assert ds.GetLayer(0).GetFeatureCount() == 10
def test_gdalalg_vector_filter_base(tmp_vsimem):
out_filename = str(tmp_vsimem / "out.shp")
filter_alg = get_filter_alg()
assert filter_alg.ParseRunAndFinalize(
["--bbox=479867,4762909,479868,4762910", "../ogr/data/poly.shp", out_filename]
)
with gdal.OpenEx(out_filename) as ds:
assert ds.GetLayer(0).GetFeatureCount() == 1