Skip to content

Commit 2c80456

Browse files
committed
gdal vector buffer: automatically set output geometry field type to Polygon or MultiPolygon
Fixes #13512
1 parent 143f3ee commit 2c80456

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

apps/gdalalg_vector_buffer.cpp

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,24 @@ class GDALVectorBufferAlgorithmLayer final
7272
GDALVectorBufferAlgorithmLayer(
7373
OGRLayer &oSrcLayer, const GDALVectorBufferAlgorithm::Options &opts)
7474
: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorBufferAlgorithm>(
75-
oSrcLayer, opts)
75+
oSrcLayer, opts),
76+
m_poFeatureDefn(oSrcLayer.GetLayerDefn()->Clone())
7677
{
78+
m_poFeatureDefn->Reference();
79+
for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i)
80+
{
81+
if (IsSelectedGeomField(i))
82+
{
83+
auto poGeomFieldDefn = m_poFeatureDefn->GetGeomFieldDefn(i);
84+
const auto eType = wkbFlatten(poGeomFieldDefn->GetType());
85+
if (eType == wkbUnknown ||
86+
OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
87+
poGeomFieldDefn->SetType(wkbMultiPolygon);
88+
else
89+
poGeomFieldDefn->SetType(wkbPolygon);
90+
}
91+
}
92+
7793
m_aosBufferOptions.SetNameValue("ENDCAP_STYLE",
7894
opts.m_endCapStyle.c_str());
7995
m_aosBufferOptions.SetNameValue("JOIN_STYLE", opts.m_joinStyle.c_str());
@@ -85,6 +101,16 @@ class GDALVectorBufferAlgorithmLayer final
85101
m_opts.m_side != "both" ? "YES" : "NO");
86102
}
87103

104+
~GDALVectorBufferAlgorithmLayer() override
105+
{
106+
m_poFeatureDefn->Release();
107+
}
108+
109+
const OGRFeatureDefn *GetLayerDefn() const override
110+
{
111+
return m_poFeatureDefn;
112+
}
113+
88114
protected:
89115
using GDALVectorGeomOneToOneAlgorithmLayer::TranslateFeature;
90116

@@ -93,6 +119,9 @@ class GDALVectorBufferAlgorithmLayer final
93119

94120
private:
95121
CPLStringList m_aosBufferOptions{};
122+
OGRFeatureDefn *const m_poFeatureDefn;
123+
124+
CPL_DISALLOW_COPY_ASSIGN(GDALVectorBufferAlgorithmLayer)
96125
};
97126

98127
/************************************************************************/
@@ -102,7 +131,7 @@ class GDALVectorBufferAlgorithmLayer final
102131
std::unique_ptr<OGRFeature> GDALVectorBufferAlgorithmLayer::TranslateFeature(
103132
std::unique_ptr<OGRFeature> poSrcFeature) const
104133
{
105-
const int nGeomFieldCount = poSrcFeature->GetGeomFieldCount();
134+
const int nGeomFieldCount = m_poFeatureDefn->GetGeomFieldCount();
106135
for (int i = 0; i < nGeomFieldCount; ++i)
107136
{
108137
if (IsSelectedGeomField(i))
@@ -114,15 +143,22 @@ std::unique_ptr<OGRFeature> GDALVectorBufferAlgorithmLayer::TranslateFeature(
114143
m_aosBufferOptions.List()));
115144
if (poGeom)
116145
{
117-
poGeom->assignSpatialReference(m_srcLayer.GetLayerDefn()
118-
->GetGeomFieldDefn(i)
119-
->GetSpatialRef());
120-
poSrcFeature->SetGeomField(i, std::move(poGeom));
146+
const auto poGeomFielDefn =
147+
m_poFeatureDefn->GetGeomFieldDefn(i);
148+
poGeom.reset(OGRGeometryFactory::forceTo(
149+
poGeom.release(), poGeomFielDefn->GetType()));
150+
if (poGeom)
151+
{
152+
poGeom->assignSpatialReference(
153+
poGeomFielDefn->GetSpatialRef());
154+
poSrcFeature->SetGeomField(i, std::move(poGeom));
155+
}
121156
}
122157
}
123158
}
124159
}
125160

161+
poSrcFeature->SetFDefnUnsafe(m_poFeatureDefn);
126162
return poSrcFeature;
127163
}
128164

autotest/utilities/test_gdalalg_vector_buffer.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ def get_alg():
5757
"POLYGON ((1 0,0 0,0 1,1 1,1 0))",
5858
),
5959
(
60-
"LINESTRING (0 0,1 0)",
60+
"MULTILINESTRING ((0 0,1 0))",
6161
{"distance": 1, "side": "right"},
62-
"POLYGON ((0 0,1 0,1 -1,0 -1,0 0))",
62+
"MULTIPOLYGON (((0 0,1 0,1 -1,0 -1,0 0)))",
6363
),
6464
],
6565
ids=[
@@ -78,10 +78,11 @@ def test_gdalalg_vector_buffer(input_wkt, options, output_wkt):
7878
src_ds = gdal.GetDriverByName("MEM").Create("", 0, 0, 0, gdal.GDT_Unknown)
7979
srs = osr.SpatialReference()
8080
srs.ImportFromEPSG(32631)
81-
src_lyr = src_ds.CreateLayer("the_layer", srs=srs)
81+
geom = ogr.CreateGeometryFromWkt(input_wkt)
82+
src_lyr = src_ds.CreateLayer("the_layer", srs=srs, geom_type=geom.GetGeometryType())
8283

8384
f = ogr.Feature(src_lyr.GetLayerDefn())
84-
f.SetGeometry(ogr.CreateGeometryFromWkt(input_wkt))
85+
f.SetGeometry(geom)
8586
src_lyr.CreateFeature(f)
8687

8788
f = ogr.Feature(src_lyr.GetLayerDefn())
@@ -99,6 +100,8 @@ def test_gdalalg_vector_buffer(input_wkt, options, output_wkt):
99100
out_ds = alg["output"].GetDataset()
100101
out_lyr = out_ds.GetLayer(0)
101102
out_f = out_lyr.GetNextFeature()
103+
assert out_lyr.GetLayerDefn().IsSame(out_f.GetDefnRef())
104+
assert out_lyr.GetGeomType() == out_f.GetGeometryRef().GetGeometryType()
102105
# print(out_f.GetGeometryRef().ExportToIsoWkt())
103106
ogrtest.check_feature_geometry(out_f, output_wkt)
104107
assert (

0 commit comments

Comments
 (0)