Skip to content

Commit e5bed15

Browse files
committed
gdal vector: make 'read', 'clip' and 'reproject' compatible of OSM-type of datasources that require ODsCRandomLayerRead
On-the-fly reading of OSM requires to be able to iterate over features at the dataset level, and not just at the layer level. Let's implement that.
1 parent 51ee293 commit e5bed15

17 files changed

+702
-125
lines changed

apps/gdalalg_vector_clip.cpp

+59-88
Original file line numberDiff line numberDiff line change
@@ -65,129 +65,99 @@ GDALVectorClipAlgorithm::GDALVectorClipAlgorithm(bool standaloneStep)
6565

6666
namespace
6767
{
68-
class GDALVectorClipAlgorithmLayer final
69-
: public OGRLayer,
70-
public OGRGetNextFeatureThroughRaw<GDALVectorClipAlgorithmLayer>
68+
class GDALVectorClipAlgorithmLayer final : public GDALVectorPipelineOutputLayer
7169
{
72-
73-
DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorClipAlgorithmLayer)
74-
7570
public:
76-
GDALVectorClipAlgorithmLayer(OGRLayer *poSrcLayer,
71+
GDALVectorClipAlgorithmLayer(OGRLayer &oSrcLayer,
7772
std::unique_ptr<OGRGeometry> poClipGeom)
78-
: m_poSrcLayer(poSrcLayer), m_poClipGeom(std::move(poClipGeom)),
79-
m_eSrcLayerGeomType(m_poSrcLayer->GetGeomType()),
73+
: GDALVectorPipelineOutputLayer(oSrcLayer),
74+
m_poClipGeom(std::move(poClipGeom)),
75+
m_eSrcLayerGeomType(oSrcLayer.GetGeomType()),
8076
m_eFlattenSrcLayerGeomType(wkbFlatten(m_eSrcLayerGeomType)),
8177
m_bSrcLayerGeomTypeIsCollection(OGR_GT_IsSubClassOf(
8278
m_eFlattenSrcLayerGeomType, wkbGeometryCollection))
8379
{
84-
SetDescription(poSrcLayer->GetDescription());
85-
poSrcLayer->SetSpatialFilter(m_poClipGeom.get());
80+
SetDescription(oSrcLayer.GetDescription());
81+
oSrcLayer.SetSpatialFilter(m_poClipGeom.get());
8682
}
8783

8884
OGRFeatureDefn *GetLayerDefn() override
8985
{
90-
return m_poSrcLayer->GetLayerDefn();
91-
}
92-
93-
void ResetReading() override
94-
{
95-
m_poSrcLayer->ResetReading();
96-
m_poSrcFeature.reset();
97-
m_poCurGeomColl.reset();
98-
m_idxInCurGeomColl = 0;
86+
return m_srcLayer.GetLayerDefn();
9987
}
10088

101-
OGRFeature *GetNextRawFeature()
89+
void TranslateFeature(
90+
std::unique_ptr<OGRFeature> poSrcFeature,
91+
std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override
10292
{
103-
if (m_poSrcFeature && m_poCurGeomColl)
93+
auto poGeom = poSrcFeature->GetGeometryRef();
94+
if (!poGeom)
95+
return;
96+
97+
auto poIntersection = std::unique_ptr<OGRGeometry>(
98+
poGeom->Intersection(m_poClipGeom.get()));
99+
if (!poIntersection)
100+
return;
101+
102+
const auto eFeatGeomType =
103+
wkbFlatten(poIntersection->getGeometryType());
104+
if (m_eFlattenSrcLayerGeomType != wkbUnknown &&
105+
m_eFlattenSrcLayerGeomType != eFeatGeomType)
104106
{
105-
while (m_idxInCurGeomColl < m_poCurGeomColl->getNumGeometries())
107+
// If the intersection is a collection of geometry and the
108+
// layer geometry type is of non-collection type, create
109+
// one feature per element of the collection.
110+
if (!m_bSrcLayerGeomTypeIsCollection &&
111+
OGR_GT_IsSubClassOf(eFeatGeomType, wkbGeometryCollection))
106112
{
107-
const auto poGeom =
108-
m_poCurGeomColl->getGeometryRef(m_idxInCurGeomColl);
109-
++m_idxInCurGeomColl;
110-
if (m_eFlattenSrcLayerGeomType == wkbUnknown ||
111-
m_eFlattenSrcLayerGeomType ==
112-
wkbFlatten(poGeom->getGeometryType()))
113+
auto poGeomColl = std::unique_ptr<OGRGeometryCollection>(
114+
poIntersection.release()->toGeometryCollection());
115+
for (const auto *poSubGeom : poGeomColl.get())
113116
{
114117
auto poDstFeature =
115-
std::unique_ptr<OGRFeature>(m_poSrcFeature->Clone());
116-
poDstFeature->SetGeometry(poGeom);
117-
return poDstFeature.release();
118+
std::unique_ptr<OGRFeature>(poSrcFeature->Clone());
119+
poDstFeature->SetGeometry(poSubGeom);
120+
apoOutFeatures.push_back(std::move(poDstFeature));
118121
}
119122
}
120-
m_poSrcFeature.reset();
121-
m_poCurGeomColl.reset();
122-
m_idxInCurGeomColl = 0;
123-
}
124-
125-
while (auto poFeature =
126-
std::unique_ptr<OGRFeature>(m_poSrcLayer->GetNextFeature()))
127-
{
128-
auto poGeom = poFeature->GetGeometryRef();
129-
if (!poGeom)
130-
continue;
131-
132-
auto poIntersection = std::unique_ptr<OGRGeometry>(
133-
poGeom->Intersection(m_poClipGeom.get()));
134-
if (!poIntersection)
135-
continue;
136-
137-
const auto eFeatGeomType =
138-
wkbFlatten(poIntersection->getGeometryType());
139-
if (m_eFlattenSrcLayerGeomType != wkbUnknown &&
140-
m_eFlattenSrcLayerGeomType != eFeatGeomType)
123+
else if (OGR_GT_GetCollection(eFeatGeomType) ==
124+
m_eFlattenSrcLayerGeomType)
141125
{
142-
// If the intersection is a collection of geometry and the
143-
// layer geometry type is of non-collection type, create
144-
// one feature per element of the collection.
145-
if (!m_bSrcLayerGeomTypeIsCollection &&
146-
OGR_GT_IsSubClassOf(eFeatGeomType, wkbGeometryCollection))
147-
{
148-
m_poSrcFeature = std::move(poFeature);
149-
m_poCurGeomColl.reset(
150-
poIntersection.release()->toGeometryCollection());
151-
m_idxInCurGeomColl = 0;
152-
return GetNextFeature();
153-
}
154-
else if (OGR_GT_GetCollection(eFeatGeomType) ==
155-
m_eFlattenSrcLayerGeomType)
156-
{
157-
poIntersection.reset(OGRGeometryFactory::forceTo(
158-
poIntersection.release(), m_eSrcLayerGeomType));
159-
poFeature->SetGeometryDirectly(poIntersection.release());
160-
return poFeature.release();
161-
}
162-
// else discard geometries of incompatible type with the
163-
// layer geometry type
126+
poIntersection.reset(OGRGeometryFactory::forceTo(
127+
poIntersection.release(), m_eSrcLayerGeomType));
128+
poSrcFeature->SetGeometryDirectly(poIntersection.release());
129+
apoOutFeatures.push_back(std::move(poSrcFeature));
164130
}
165-
else
131+
else if (m_eFlattenSrcLayerGeomType == wkbGeometryCollection)
166132
{
167-
poFeature->SetGeometryDirectly(poIntersection.release());
168-
return poFeature.release();
133+
auto poGeomColl = std::make_unique<OGRGeometryCollection>();
134+
poGeomColl->addGeometry(std::move(poIntersection));
135+
poSrcFeature->SetGeometryDirectly(poGeomColl.release());
136+
apoOutFeatures.push_back(std::move(poSrcFeature));
169137
}
138+
// else discard geometries of incompatible type with the
139+
// layer geometry type
140+
}
141+
else
142+
{
143+
poSrcFeature->SetGeometryDirectly(poIntersection.release());
144+
apoOutFeatures.push_back(std::move(poSrcFeature));
170145
}
171-
return nullptr;
172146
}
173147

174148
int TestCapability(const char *pszCap) override
175149
{
176150
if (EQUAL(pszCap, OLCStringsAsUTF8) ||
177151
EQUAL(pszCap, OLCCurveGeometries) || EQUAL(pszCap, OLCZGeometries))
178-
return m_poSrcLayer->TestCapability(pszCap);
152+
return m_srcLayer.TestCapability(pszCap);
179153
return false;
180154
}
181155

182156
private:
183-
OGRLayer *m_poSrcLayer = nullptr;
184157
std::unique_ptr<OGRGeometry> m_poClipGeom{};
185158
const OGRwkbGeometryType m_eSrcLayerGeomType;
186159
const OGRwkbGeometryType m_eFlattenSrcLayerGeomType;
187160
const bool m_bSrcLayerGeomTypeIsCollection;
188-
std::unique_ptr<OGRFeature> m_poSrcFeature{};
189-
std::unique_ptr<OGRGeometryCollection> m_poCurGeomColl{};
190-
int m_idxInCurGeomColl = 0;
191161

192162
CPL_DISALLOW_COPY_ASSIGN(GDALVectorClipAlgorithmLayer)
193163
};
@@ -428,8 +398,7 @@ bool GDALVectorClipAlgorithm::RunStep(GDALProgressFunc, void *)
428398
return false;
429399
}
430400

431-
auto outDS = std::make_unique<GDALVectorPipelineOutputDataset>();
432-
outDS->SetDescription(poSrcDS->GetDescription());
401+
auto outDS = std::make_unique<GDALVectorPipelineOutputDataset>(*poSrcDS);
433402

434403
bool ret = true;
435404
for (int i = 0; ret && i < nLayerCount; ++i)
@@ -448,8 +417,10 @@ bool GDALVectorClipAlgorithm::RunStep(GDALProgressFunc, void *)
448417
}
449418
if (ret)
450419
{
451-
outDS->AddLayer(std::make_unique<GDALVectorClipAlgorithmLayer>(
452-
poSrcLayer, std::move(poClipGeomForLayer)));
420+
outDS->AddLayer(
421+
*poSrcLayer,
422+
std::make_unique<GDALVectorClipAlgorithmLayer>(
423+
*poSrcLayer, std::move(poClipGeomForLayer)));
453424
}
454425
}
455426
}

apps/gdalalg_vector_pipeline.cpp

+171
Original file line numberDiff line numberDiff line change
@@ -516,4 +516,175 @@ std::string GDALVectorPipelineAlgorithm::GetUsageForCLI(
516516
return ret;
517517
}
518518

519+
/************************************************************************/
520+
/* GDALVectorPipelineOutputLayer */
521+
/************************************************************************/
522+
523+
/************************************************************************/
524+
/* GDALVectorPipelineOutputLayer() */
525+
/************************************************************************/
526+
527+
GDALVectorPipelineOutputLayer::GDALVectorPipelineOutputLayer(OGRLayer &srcLayer)
528+
: m_srcLayer(srcLayer)
529+
{
530+
}
531+
532+
/************************************************************************/
533+
/* GDALVectorPipelineOutputLayer::ResetReading() */
534+
/************************************************************************/
535+
536+
void GDALVectorPipelineOutputLayer::ResetReading()
537+
{
538+
m_srcLayer.ResetReading();
539+
m_pendingFeatures.clear();
540+
m_idxInPendingFeatures = 0;
541+
}
542+
543+
/************************************************************************/
544+
/* GDALVectorPipelineOutputLayer::GetNextRawFeature() */
545+
/************************************************************************/
546+
547+
OGRFeature *GDALVectorPipelineOutputLayer::GetNextRawFeature()
548+
{
549+
if (m_idxInPendingFeatures < m_pendingFeatures.size())
550+
{
551+
OGRFeature *poFeature =
552+
m_pendingFeatures[m_idxInPendingFeatures].release();
553+
++m_idxInPendingFeatures;
554+
return poFeature;
555+
}
556+
m_pendingFeatures.clear();
557+
m_idxInPendingFeatures = 0;
558+
while (true)
559+
{
560+
auto poSrcFeature =
561+
std::unique_ptr<OGRFeature>(m_srcLayer.GetNextFeature());
562+
if (!poSrcFeature)
563+
return nullptr;
564+
TranslateFeature(std::move(poSrcFeature), m_pendingFeatures);
565+
if (!m_pendingFeatures.empty())
566+
break;
567+
}
568+
OGRFeature *poFeature = m_pendingFeatures[0].release();
569+
m_idxInPendingFeatures = 1;
570+
return poFeature;
571+
}
572+
573+
/************************************************************************/
574+
/* GDALVectorPipelineOutputDataset */
575+
/************************************************************************/
576+
577+
/************************************************************************/
578+
/* GDALVectorPipelineOutputDataset() */
579+
/************************************************************************/
580+
581+
GDALVectorPipelineOutputDataset::GDALVectorPipelineOutputDataset(
582+
GDALDataset &srcDS)
583+
: m_srcDS(srcDS)
584+
{
585+
SetDescription(m_srcDS.GetDescription());
586+
}
587+
588+
/************************************************************************/
589+
/* GDALVectorPipelineOutputDataset::AddLayer() */
590+
/************************************************************************/
591+
592+
void GDALVectorPipelineOutputDataset::AddLayer(
593+
OGRLayer &oSrcLayer,
594+
std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer)
595+
{
596+
m_layersToDestroy.push_back(std::move(poNewLayer));
597+
OGRLayerWithTranslateFeature *poNewLayerRaw =
598+
m_layersToDestroy.back().get();
599+
m_layers.push_back(poNewLayerRaw);
600+
m_mapSrcLayerToNewLayer[&oSrcLayer] = poNewLayerRaw;
601+
}
602+
603+
/************************************************************************/
604+
/* GDALVectorPipelineOutputDataset::GetLayerCount() */
605+
/************************************************************************/
606+
607+
int GDALVectorPipelineOutputDataset::GetLayerCount()
608+
{
609+
return static_cast<int>(m_layers.size());
610+
}
611+
612+
/************************************************************************/
613+
/* GDALVectorPipelineOutputDataset::GetLayer() */
614+
/************************************************************************/
615+
616+
OGRLayer *GDALVectorPipelineOutputDataset::GetLayer(int idx)
617+
{
618+
return idx >= 0 && idx < GetLayerCount() ? m_layers[idx] : nullptr;
619+
}
620+
621+
/************************************************************************/
622+
/* GDALVectorPipelineOutputDataset::TestCapability() */
623+
/************************************************************************/
624+
625+
int GDALVectorPipelineOutputDataset::TestCapability(const char *pszCap)
626+
{
627+
if (EQUAL(pszCap, ODsCRandomLayerRead))
628+
{
629+
return m_srcDS.TestCapability(pszCap);
630+
}
631+
return false;
632+
}
633+
634+
/************************************************************************/
635+
/* GDALVectorPipelineOutputDataset::ResetReading() */
636+
/************************************************************************/
637+
638+
void GDALVectorPipelineOutputDataset::ResetReading()
639+
{
640+
m_srcDS.ResetReading();
641+
m_pendingFeatures.clear();
642+
m_idxInPendingFeatures = 0;
643+
}
644+
645+
/************************************************************************/
646+
/* GDALVectorPipelineOutputDataset::GetNextFeature() */
647+
/************************************************************************/
648+
649+
OGRFeature *GDALVectorPipelineOutputDataset::GetNextFeature(
650+
OGRLayer **ppoBelongingLayer, double *pdfProgressPct,
651+
GDALProgressFunc pfnProgress, void *pProgressData)
652+
{
653+
if (m_idxInPendingFeatures < m_pendingFeatures.size())
654+
{
655+
OGRFeature *poFeature =
656+
m_pendingFeatures[m_idxInPendingFeatures].release();
657+
if (ppoBelongingLayer)
658+
*ppoBelongingLayer = m_belongingLayer;
659+
++m_idxInPendingFeatures;
660+
return poFeature;
661+
}
662+
663+
m_pendingFeatures.clear();
664+
m_idxInPendingFeatures = 0;
665+
666+
while (true)
667+
{
668+
OGRLayer *poSrcBelongingLayer = nullptr;
669+
auto poSrcFeature = std::unique_ptr<OGRFeature>(m_srcDS.GetNextFeature(
670+
&poSrcBelongingLayer, pdfProgressPct, pfnProgress, pProgressData));
671+
if (!poSrcFeature)
672+
return nullptr;
673+
auto iterToDstLayer = m_mapSrcLayerToNewLayer.find(poSrcBelongingLayer);
674+
if (iterToDstLayer != m_mapSrcLayerToNewLayer.end())
675+
{
676+
m_belongingLayer = iterToDstLayer->second;
677+
m_belongingLayer->TranslateFeature(std::move(poSrcFeature),
678+
m_pendingFeatures);
679+
if (!m_pendingFeatures.empty())
680+
break;
681+
}
682+
}
683+
OGRFeature *poFeature = m_pendingFeatures[0].release();
684+
if (ppoBelongingLayer)
685+
*ppoBelongingLayer = m_belongingLayer;
686+
m_idxInPendingFeatures = 1;
687+
return poFeature;
688+
}
689+
519690
//! @endcond

0 commit comments

Comments
 (0)