Skip to content

Commit fe9d263

Browse files
committed
gdal vector layer-algebra: make it available in pipelines
1 parent 4253428 commit fe9d263

10 files changed

Lines changed: 369 additions & 308 deletions

apps/gdalalg_pipeline.cpp

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,153 @@ bool GDALPipelineStepAlgorithm::Finalize()
541541
return ret;
542542
}
543543

544+
/************************************************************************/
545+
/* CreateDatasetSingleOutputLayerIfNeeded() */
546+
/************************************************************************/
547+
548+
bool GDALPipelineStepAlgorithm::CreateDatasetSingleOutputLayerIfNeeded(
549+
GDALPipelineStepRunContext &ctxt, const std::string &defaultLayerName,
550+
GDALDataset *&poDstDS, bool &bTemporaryFile,
551+
std::unique_ptr<GDALDataset> &poNewRetDS, std::string &outputLayerName,
552+
OGRLayer *&poDstLayer)
553+
{
554+
auto poWriteStep = ctxt.m_poNextUsableStep ? ctxt.m_poNextUsableStep : this;
555+
std::string outputFilename = poWriteStep->GetOutputDataset().GetName();
556+
557+
poDstDS = poWriteStep->GetOutputDataset().GetDatasetRef();
558+
poNewRetDS.reset();
559+
bTemporaryFile = false;
560+
poDstLayer = nullptr;
561+
GDALDriver *poDstDriver = nullptr;
562+
if (!poDstDS)
563+
{
564+
auto poDriverManager = GetGDALDriverManager();
565+
std::string format = poWriteStep->GetOutputFormat();
566+
if (m_standaloneStep || (ctxt.m_poNextUsableStep && format.empty()))
567+
{
568+
if (format.empty())
569+
{
570+
const auto aosFormats =
571+
CPLStringList(GDALGetOutputDriversForDatasetName(
572+
outputFilename.c_str(), GDAL_OF_VECTOR,
573+
/* bSingleMatch = */ true,
574+
/* bWarn = */ true));
575+
if (aosFormats.size() != 1)
576+
{
577+
ReportError(CE_Failure, CPLE_AppDefined,
578+
"Cannot guess driver for %s",
579+
outputFilename.c_str());
580+
return false;
581+
}
582+
format = aosFormats[0];
583+
}
584+
}
585+
else if (!ctxt.m_poNextUsableStep)
586+
{
587+
poDstDriver = poDriverManager->GetDriverByName("GPKG");
588+
if (poDstDriver)
589+
{
590+
bTemporaryFile = true;
591+
outputFilename =
592+
CPLGenerateTempFilenameSafe(
593+
std::string("_").append(defaultLayerName).c_str()) +
594+
".gpkg";
595+
format = "GPKG";
596+
}
597+
else
598+
format = "MEM";
599+
}
600+
601+
if (!poDstDriver)
602+
poDstDriver = poDriverManager->GetDriverByName(format.c_str());
603+
if (!poDstDriver)
604+
{
605+
ReportError(CE_Failure, CPLE_AppDefined, "Cannot find driver %s",
606+
format.c_str());
607+
return false;
608+
}
609+
610+
poNewRetDS.reset(poDstDriver->Create(
611+
outputFilename.c_str(), 0, 0, 0, GDT_Unknown,
612+
CPLStringList(poWriteStep->GetCreationOptions()).List()));
613+
if (!poNewRetDS)
614+
return false;
615+
616+
if (bTemporaryFile)
617+
poNewRetDS->MarkSuppressOnClose();
618+
619+
poDstDS = poNewRetDS.get();
620+
}
621+
else
622+
{
623+
poDstDriver = poDstDS->GetDriver();
624+
}
625+
626+
outputLayerName = poWriteStep->GetOutputLayerName();
627+
if (outputLayerName.empty() && poDstDS->GetLayerCount() > 1)
628+
{
629+
ReportError(CE_Failure, CPLE_AppDefined,
630+
"--output-layer must be specified");
631+
return false;
632+
}
633+
634+
if (poDstDriver && EQUAL(poDstDriver->GetDescription(), "ESRI Shapefile") &&
635+
(EQUAL(CPLGetExtensionSafe(poDstDS->GetDescription()).c_str(), "shp") ||
636+
EQUAL(CPLGetExtensionSafe(poDstDS->GetDescription()).c_str(),
637+
"shz")) &&
638+
poDstDS->GetLayerCount() <= 1)
639+
{
640+
outputLayerName = CPLGetBasenameSafe(poDstDS->GetDescription());
641+
}
642+
if (outputLayerName.empty())
643+
outputLayerName = defaultLayerName;
644+
645+
poDstLayer = poDstDS->GetLayerByName(outputLayerName.c_str());
646+
if (poDstLayer)
647+
{
648+
if (poWriteStep->GetOverwriteLayer())
649+
{
650+
int iLayer = -1;
651+
const int nLayerCount = poDstDS->GetLayerCount();
652+
for (iLayer = 0; iLayer < nLayerCount; iLayer++)
653+
{
654+
if (poDstDS->GetLayer(iLayer) == poDstLayer)
655+
break;
656+
}
657+
658+
if (iLayer < nLayerCount)
659+
{
660+
if (poDstDS->DeleteLayer(iLayer) != OGRERR_NONE)
661+
{
662+
ReportError(CE_Failure, CPLE_AppDefined,
663+
"Cannot delete layer '%s'",
664+
outputLayerName.c_str());
665+
return false;
666+
}
667+
}
668+
poDstLayer = nullptr;
669+
}
670+
else if (!poWriteStep->GetAppendLayer())
671+
{
672+
ReportError(CE_Failure, CPLE_AppDefined,
673+
"Layer '%s' already exists. Specify the "
674+
"--%s option to overwrite it, or --%s "
675+
"to append to it.",
676+
outputLayerName.c_str(), GDAL_ARG_NAME_OVERWRITE_LAYER,
677+
GDAL_ARG_NAME_APPEND);
678+
return false;
679+
}
680+
}
681+
else if (poWriteStep->GetAppendLayer() || poWriteStep->GetOverwriteLayer())
682+
{
683+
ReportError(CE_Failure, CPLE_AppDefined, "Cannot find layer '%s'",
684+
outputLayerName.c_str());
685+
return false;
686+
}
687+
688+
return true;
689+
}
690+
544691
GDALAlgorithmStepRegistry::~GDALAlgorithmStepRegistry() = default;
545692

546693
/************************************************************************/

apps/gdalalg_raster_polygonize.cpp

Lines changed: 11 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -97,125 +97,15 @@ bool GDALRasterPolygonizeAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
9797

9898
auto poWriteStep = ctxt.m_poNextUsableStep ? ctxt.m_poNextUsableStep : this;
9999

100-
GDALDataset *poDstDS = poWriteStep->GetOutputDataset().GetDatasetRef();
101-
std::unique_ptr<GDALDataset> poRetDS;
102-
std::string outputFilename = poWriteStep->GetOutputDataset().GetName();
103-
GDALDriver *poDstDriver = nullptr;
100+
GDALDataset *poDstDS = nullptr;
104101
bool bTemporaryFile = false;
105-
if (!poDstDS)
102+
std::unique_ptr<GDALDataset> poNewRetDS;
103+
std::string outputLayerName;
104+
OGRLayer *poDstLayer = nullptr;
105+
if (!CreateDatasetSingleOutputLayerIfNeeded(ctxt, "polygonize", poDstDS,
106+
bTemporaryFile, poNewRetDS,
107+
outputLayerName, poDstLayer))
106108
{
107-
auto poDriverManager = GetGDALDriverManager();
108-
std::string format = poWriteStep->GetOutputFormat();
109-
if (m_standaloneStep || (ctxt.m_poNextUsableStep && format.empty()))
110-
{
111-
if (format.empty())
112-
{
113-
const auto aosFormats =
114-
CPLStringList(GDALGetOutputDriversForDatasetName(
115-
outputFilename.c_str(), GDAL_OF_VECTOR,
116-
/* bSingleMatch = */ true,
117-
/* bWarn = */ true));
118-
if (aosFormats.size() != 1)
119-
{
120-
ReportError(CE_Failure, CPLE_AppDefined,
121-
"Cannot guess driver for %s",
122-
outputFilename.c_str());
123-
return false;
124-
}
125-
format = aosFormats[0];
126-
}
127-
}
128-
else if (!ctxt.m_poNextUsableStep)
129-
{
130-
poDstDriver = poDriverManager->GetDriverByName("GPKG");
131-
if (poDstDriver)
132-
{
133-
bTemporaryFile = true;
134-
outputFilename =
135-
CPLGenerateTempFilenameSafe("_polygonize") + ".gpkg";
136-
format = "GPKG";
137-
}
138-
else
139-
format = "MEM";
140-
}
141-
142-
if (!poDstDriver)
143-
poDstDriver = poDriverManager->GetDriverByName(format.c_str());
144-
if (!poDstDriver)
145-
{
146-
ReportError(CE_Failure, CPLE_AppDefined, "Cannot find driver %s",
147-
format.c_str());
148-
return false;
149-
}
150-
151-
poRetDS.reset(poDstDriver->Create(
152-
outputFilename.c_str(), 0, 0, 0, GDT_Unknown,
153-
CPLStringList(poWriteStep->GetCreationOptions()).List()));
154-
if (!poRetDS)
155-
return false;
156-
157-
if (bTemporaryFile)
158-
poRetDS->MarkSuppressOnClose();
159-
160-
poDstDS = poRetDS.get();
161-
}
162-
else
163-
{
164-
poDstDriver = poDstDS->GetDriver();
165-
}
166-
167-
std::string outputLayerName = poWriteStep->GetOutputLayerName();
168-
if (poDstDriver && EQUAL(poDstDriver->GetDescription(), "ESRI Shapefile") &&
169-
(EQUAL(CPLGetExtensionSafe(poDstDS->GetDescription()).c_str(), "shp") ||
170-
EQUAL(CPLGetExtensionSafe(poDstDS->GetDescription()).c_str(),
171-
"shz")) &&
172-
poDstDS->GetLayerCount() <= 1)
173-
{
174-
outputLayerName = CPLGetBasenameSafe(poDstDS->GetDescription());
175-
}
176-
if (outputLayerName.empty())
177-
outputLayerName = "polygonize";
178-
179-
auto poDstLayer = poDstDS->GetLayerByName(outputLayerName.c_str());
180-
if (poDstLayer)
181-
{
182-
if (poWriteStep->GetOverwriteLayer())
183-
{
184-
int iLayer = -1;
185-
const int nLayerCount = poDstDS->GetLayerCount();
186-
for (iLayer = 0; iLayer < nLayerCount; iLayer++)
187-
{
188-
if (poDstDS->GetLayer(iLayer) == poDstLayer)
189-
break;
190-
}
191-
192-
if (iLayer < nLayerCount)
193-
{
194-
if (poDstDS->DeleteLayer(iLayer) != OGRERR_NONE)
195-
{
196-
ReportError(CE_Failure, CPLE_AppDefined,
197-
"Cannot delete layer '%s'",
198-
outputLayerName.c_str());
199-
return false;
200-
}
201-
}
202-
poDstLayer = nullptr;
203-
}
204-
else if (!poWriteStep->GetAppendLayer())
205-
{
206-
ReportError(CE_Failure, CPLE_AppDefined,
207-
"Layer '%s' already exists. Specify the "
208-
"--%s option to overwrite it, or --%s "
209-
"to append to it.",
210-
outputLayerName.c_str(), GDAL_ARG_NAME_OVERWRITE_LAYER,
211-
GDAL_ARG_NAME_APPEND);
212-
return false;
213-
}
214-
}
215-
else if (poWriteStep->GetAppendLayer() || poWriteStep->GetOverwriteLayer())
216-
{
217-
ReportError(CE_Failure, CPLE_AppDefined, "Cannot find layer '%s'",
218-
outputLayerName.c_str());
219109
return false;
220110
}
221111

@@ -288,19 +178,19 @@ bool GDALRasterPolygonizeAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
288178
ctxt.m_pProgressData) == CE_None;
289179
}
290180

291-
if (ret && poRetDS)
181+
if (ret && poNewRetDS)
292182
{
293183
if (bTemporaryFile)
294184
{
295-
ret = poRetDS->FlushCache() == CE_None;
185+
ret = poNewRetDS->FlushCache() == CE_None;
296186
#if !defined(__APPLE__)
297187
// For some unknown reason, unlinking the file on MacOSX
298188
// leads to later "disk I/O error". See https://github.com/OSGeo/gdal/issues/13794
299-
VSIUnlink(outputFilename.c_str());
189+
VSIUnlink(poNewRetDS->GetDescription());
300190
#endif
301191
}
302192

303-
m_outputDataset.Set(std::move(poRetDS));
193+
m_outputDataset.Set(std::move(poNewRetDS));
304194
}
305195

306196
return ret;

apps/gdalalg_vector.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ GDALVectorAlgorithm::GDALVectorAlgorithm()
9292
RegisterSubAlgorithm<GDALVectorPipelineAlgorithm>();
9393
RegisterSubAlgorithm<GDALVectorFilterAlgorithmStandalone>();
9494
RegisterSubAlgorithm<GDALVectorIndexAlgorithm>();
95-
RegisterSubAlgorithm<GDALVectorLayerAlgebraAlgorithm>();
95+
RegisterSubAlgorithm<GDALVectorLayerAlgebraAlgorithmStandalone>();
9696
RegisterSubAlgorithm<GDALVectorMakePointAlgorithmStandalone>();
9797
RegisterSubAlgorithm<GDALVectorMakeValidAlgorithmStandalone>();
9898
RegisterSubAlgorithm<GDALVectorPartitionAlgorithmStandalone>();

0 commit comments

Comments
 (0)