Skip to content

Commit

Permalink
Interlis 2: remove write support
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Jan 22, 2025
1 parent 80ca659 commit 4583dc3
Show file tree
Hide file tree
Showing 7 changed files with 4 additions and 501 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda
ESRIJSON -vector- (rov): ESRIJSON (*.json)
TopoJSON -vector- (rov): TopoJSON (*.json, *.topojson)
Interlis 1 -vector- (rov): Interlis 1 (*.itf, *.ili)
Interlis 2 -vector- (rw+v): Interlis 2 (*.xtf, *.xml, *.ili)
Interlis 2 -vector- (rov): Interlis 2 (*.xtf, *.xml, *.ili)
OGR_GMT -vector- (rw+v): GMT ASCII Vectors (.gmt) (*.gmt)
GPKG -raster,vector- (rw+vs): GeoPackage (*.gpkg, *.gpkg.zip)
SQLite -raster,vector- (rw+v): SQLite / Spatialite / RasterLite2 (*.sqlite, *.db)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda
ESRIJSON -vector- (rov): ESRIJSON (*.json)
TopoJSON -vector- (rov): TopoJSON (*.json, *.topojson)
Interlis 1 -vector- (rov): Interlis 1 (*.itf, *.ili)
Interlis 2 -vector- (rw+v): Interlis 2 (*.xtf, *.xml, *.ili)
Interlis 2 -vector- (rov): Interlis 2 (*.xtf, *.xml, *.ili)
OGR_GMT -vector- (rw+v): GMT ASCII Vectors (.gmt) (*.gmt)
GPKG -raster,vector- (rw+vs): GeoPackage (*.gpkg, *.gpkg.zip)
SQLite -vector- (rw+v): SQLite / Spatialite (*.sqlite, *.db)
Expand Down
108 changes: 0 additions & 108 deletions autotest/ogr/ogr_ili.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,95 +786,6 @@ def test_ogr_interlis2_2():
ogrtest.check_feature_geometry(geom, geom_field_values[i])


###############################################################################
# Write Ili2 transfer file.


def test_ogr_interlis2_3(tmp_path):

ds = ogr.Open("data/ili/RoadsExdm2ien.xml,data/ili/RoadsExdm2ien.imd")

lyr = ds.GetLayerByName("RoadsExdm2ien.RoadsExtended.RoadSign")
feat = lyr.GetNextFeature()

driver = ogr.GetDriverByName("Interlis 2")
outfile = tmp_path / "interlis2_3.xtf"
dst_ds = driver.CreateDataSource(f"{outfile},data/ili/RoadsExdm2ien.imd")

dst_lyr = dst_ds.CreateLayer("RoadsExdm2ien.RoadsExtended.RoadSign")

dst_feat = ogr.Feature(feature_def=dst_lyr.GetLayerDefn())
dst_feat.SetFrom(feat)
dst_lyr.CreateFeature(dst_feat)

lyr = ds.GetLayerByName("RoadsExdm2ben.Roads.LandCover")
feat = lyr.GetNextFeature()

dst_lyr = dst_ds.CreateLayer("RoadsExdm2ben.Roads.LandCover")

dst_feat = ogr.Feature(feature_def=dst_lyr.GetLayerDefn())
dst_feat.SetFrom(feat)
dst_lyr.CreateFeature(dst_feat)

dst_ds = None

with open(outfile) as f:
xtf = f.read()
expected = """<?xml version="1.0" encoding="utf-8" ?>
<TRANSFER xmlns="http://www.interlis.ch/INTERLIS2.3">
<HEADERSECTION SENDER="OGR/GDAL"""
assert expected in xtf, "Interlis output doesn't match."
expected = """<MODELS>
<MODEL NAME="RoadsExdm2ben" URI="http://www.interlis.ch/models" VERSION="2005-06-16"/>
<MODEL NAME="RoadsExdm2ien" URI="http://www.interlis.ch/models" VERSION="2005-06-16"/>
</MODELS>
</HEADERSECTION>
<DATASECTION>
<RoadsExdm2ien.RoadsExtended BID="RoadsExdm2ien.RoadsExtended">
<RoadsExdm2ien.RoadsExtended.RoadSign TID="501">
<Position>
<COORD><C1>69.389</C1><C2>92.056</C2></COORD>
</Position>
<Type>prohibition.noparking</Type>
</RoadsExdm2ien.RoadsExtended.RoadSign>
<RoadsExdm2ben.Roads.LandCover TID="16">
<Geometry>
<SURFACE>
<BOUNDARY>
<POLYLINE>
<COORD><C1>39.038</C1><C2>60.315</C2></COORD>
<COORD><C1>41.2</C1><C2>59.302</C2></COORD>
<COORD><C1>43.362</C1><C2>60.315</C2></COORD>
<COORD><C1>44.713</C1><C2>66.268</C2></COORD>
<COORD><C1>45.794</C1><C2>67.66200000000001</C2></COORD>
<COORD><C1>48.766</C1><C2>67.408</C2></COORD>
<COORD><C1>53.36</C1><C2>64.11499999999999</C2></COORD>
<COORD><C1>56.197</C1><C2>62.595</C2></COORD>
<COORD><C1>57.818</C1><C2>63.862</C2></COORD>
<COORD><C1>58.899</C1><C2>68.928</C2></COORD>
<COORD><C1>55.927</C1><C2>72.348</C2></COORD>
<COORD><C1>47.955</C1><C2>75.515</C2></COORD>
<COORD><C1>42.281</C1><C2>75.38800000000001</C2></COORD>
<COORD><C1>39.308</C1><C2>73.235</C2></COORD>
<COORD><C1>36.741</C1><C2>69.688</C2></COORD>
<COORD><C1>35.525</C1><C2>66.268</C2></COORD>
<COORD><C1>35.661</C1><C2>63.735</C2></COORD>
<COORD><C1>37.957</C1><C2>61.455</C2></COORD>
<COORD><C1>39.038</C1><C2>60.315</C2></COORD>
</POLYLINE>
</BOUNDARY>
</SURFACE>
</Geometry>
<Type>water</Type>
</RoadsExdm2ben.Roads.LandCover>
</RoadsExdm2ien.RoadsExtended>
</DATASECTION>
</TRANSFER>"""
expected = expected.replace(".11499999999999", ".115")
xtf = xtf.replace(".11499999999999", ".115")
assert expected in xtf, "Interlis output doesn't match."


###############################################################################
# Ili2 Oereb model

Expand Down Expand Up @@ -1035,22 +946,3 @@ def test_ogr_interlis_arc2():
for i in range(feat.GetGeomFieldCount()):
geom = feat.GetGeomFieldRef(i)
ogrtest.check_feature_geometry(geom, geom_field_values[i])


###############################################################################
# Test failure in creation of ILI2 dataset


def test_ogr_interlis2_create_file_error():

with pytest.raises(
Exception, match="model file not specified in destination filename"
):
ogr.GetDriverByName("Interlis 2").CreateDataSource("tmp/out.xtf")

with pytest.raises(
Exception, match="Failed to create XTF file /i_do/not/exist/out.xtf"
):
ogr.GetDriverByName("Interlis 2").CreateDataSource(
"/i_do/not/exist/out.xtf,data/ili/ch.bazl.sicherheitszonenplan.oereb_20131118.imd"
)
16 changes: 0 additions & 16 deletions ogr/ogrsf_frmts/ili/ogr_ili2.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ class OGRILI2Layer final : public OGRLayer

GIntBig GetFeatureCount(int bForce = TRUE) override;

OGRErr ICreateFeature(OGRFeature *poFeature) override;

OGRFeatureDefn *GetLayerDefn() override
{
return poFeatureDefn;
Expand All @@ -62,9 +60,6 @@ class OGRILI2Layer final : public OGRLayer
return oGeomFieldInfos[cFieldName].iliGeomType;
}

OGRErr CreateField(const OGRFieldDefn *poField,
int bApproxOK = TRUE) override;

int TestCapability(const char *) override;

GDALDataset *GetDataset() override;
Expand All @@ -82,7 +77,6 @@ class OGRILI2DataSource final : public GDALDataset
char *pszName;
ImdReader *poImdReader;
IILI2Reader *poReader;
VSILFILE *fpOutput;

int nLayers;
OGRILI2Layer **papoLayers;
Expand All @@ -94,7 +88,6 @@ class OGRILI2DataSource final : public GDALDataset
virtual ~OGRILI2DataSource();

int Open(const char *, char **papszOpenOptions, int bTestOpen);
int Create(const char *pszFile, char **papszOptions);

int GetLayerCount() override
{
Expand All @@ -103,15 +96,6 @@ class OGRILI2DataSource final : public GDALDataset

OGRLayer *GetLayer(int) override;

OGRLayer *ICreateLayer(const char *pszName,
const OGRGeomFieldDefn *poGeomFieldDefn,
CSLConstList papszOptions) override;

VSILFILE *GetOutputFP()
{
return fpOutput;
}

int TestCapability(const char *) override;
};

Expand Down
136 changes: 2 additions & 134 deletions ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ using namespace std;

OGRILI2DataSource::OGRILI2DataSource()
: pszName(nullptr), poImdReader(new ImdReader(2)), poReader(nullptr),
fpOutput(nullptr), nLayers(0), papoLayers(nullptr)
nLayers(0), papoLayers(nullptr)
{
}

Expand All @@ -43,14 +43,6 @@ OGRILI2DataSource::~OGRILI2DataSource()
}
CPLFree(papoLayers);

if (fpOutput != nullptr)
{
VSIFPrintfL(fpOutput, "</%s>\n", poImdReader->mainBasketName.c_str());
VSIFPrintfL(fpOutput, "</DATASECTION>\n");
VSIFPrintfL(fpOutput, "</TRANSFER>\n");
VSIFCloseL(fpOutput);
}

DestroyILI2Reader(poReader);
delete poImdReader;
CPLFree(pszName);
Expand Down Expand Up @@ -161,138 +153,14 @@ int OGRILI2DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn,
return TRUE;
}

/************************************************************************/
/* Create() */
/************************************************************************/

int OGRILI2DataSource::Create(const char *pszFilename,
CPL_UNUSED char **papszOptions)

{
char **filenames = CSLTokenizeString2(pszFilename, ",", 0);
pszName = CPLStrdup(filenames[0]);
const char *pszModelFilename =
(CSLCount(filenames) > 1) ? filenames[1] : nullptr;

if (pszModelFilename == nullptr)
{
CPLError(
CE_Failure, CPLE_AppDefined,
"ILI2 Create(): model file not specified in destination filename.");
CSLDestroy(filenames);
return FALSE;
}

/* -------------------------------------------------------------------- */
/* Create the output file. */
/* -------------------------------------------------------------------- */

if (strcmp(pszName, "/vsistdout/") == 0 ||
STARTS_WITH(pszName, "/vsigzip/"))
{
fpOutput = VSIFOpenL(pszName, "wb");
}
else if (STARTS_WITH(pszName, "/vsizip/"))
{
if (EQUAL(CPLGetExtensionSafe(pszName).c_str(), "zip"))
{
char *pszNewName = CPLStrdup(
CPLFormFilenameSafe(pszName, "out.xtf", nullptr).c_str());
CPLFree(pszName);
pszName = pszNewName;
}

fpOutput = VSIFOpenL(pszName, "wb");
}
else
fpOutput = VSIFOpenL(pszName, "wb+");
if (fpOutput == nullptr)
{
CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create XTF file %s.",
pszName);
CSLDestroy(filenames);
return FALSE;
}

/* -------------------------------------------------------------------- */
/* Parse model */
/* -------------------------------------------------------------------- */
poImdReader->ReadModel(pszModelFilename);

/* -------------------------------------------------------------------- */
/* Write headers */
/* -------------------------------------------------------------------- */
VSIFPrintfL(fpOutput, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
VSIFPrintfL(fpOutput,
"<TRANSFER xmlns=\"http://www.interlis.ch/INTERLIS2.3\">\n");
VSIFPrintfL(fpOutput,
"<HEADERSECTION SENDER=\"OGR/GDAL %s\" VERSION=\"2.3\">\n",
GDALVersionInfo("RELEASE_NAME"));
VSIFPrintfL(fpOutput, "<MODELS>\n");
for (IliModelInfos::const_iterator it = poImdReader->modelInfos.begin();
it != poImdReader->modelInfos.end(); ++it)
{
VSIFPrintfL(fpOutput,
"<MODEL NAME=\"%s\" URI=\"%s\" VERSION=\"%s\"/>\n",
it->name.c_str(), it->uri.c_str(), it->version.c_str());
}
VSIFPrintfL(fpOutput, "</MODELS>\n");
VSIFPrintfL(fpOutput, "</HEADERSECTION>\n");
VSIFPrintfL(fpOutput, "<DATASECTION>\n");
const char *basketName = poImdReader->mainBasketName.c_str();
VSIFPrintfL(fpOutput, "<%s BID=\"%s\">\n", basketName, basketName);

CSLDestroy(filenames);
return TRUE;
}

/************************************************************************/
/* ICreateLayer() */
/************************************************************************/

OGRLayer *
OGRILI2DataSource::ICreateLayer(const char *pszLayerName,
const OGRGeomFieldDefn *poGeomFieldDefn,
CSLConstList /*papszOptions*/)
{
if (fpOutput == nullptr)
return nullptr;

const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;

FeatureDefnInfo featureDefnInfo =
poImdReader->GetFeatureDefnInfo(pszLayerName);
OGRFeatureDefn *poFeatureDefn = featureDefnInfo.GetTableDefnRef();
if (poFeatureDefn == nullptr)
{
CPLError(CE_Warning, CPLE_AppDefined,
"Layer '%s' not found in model definition. "
"Creating adhoc layer",
pszLayerName);
poFeatureDefn = new OGRFeatureDefn(pszLayerName);
poFeatureDefn->SetGeomType(eType);
}
OGRILI2Layer *poLayer =
new OGRILI2Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);

nLayers++;
papoLayers = static_cast<OGRILI2Layer **>(
CPLRealloc(papoLayers, sizeof(OGRILI2Layer *) * nLayers));
papoLayers[nLayers - 1] = poLayer;

return poLayer;
}

/************************************************************************/
/* TestCapability() */
/************************************************************************/

int OGRILI2DataSource::TestCapability(const char *pszCap)

{
if (EQUAL(pszCap, ODsCCreateLayer))
return TRUE;
else if (EQUAL(pszCap, ODsCCurveGeometries))
if (EQUAL(pszCap, ODsCCurveGeometries))
return TRUE;
else if (EQUAL(pszCap, ODsCZGeometries))
return TRUE;
Expand Down
22 changes: 0 additions & 22 deletions ogr/ogrsf_frmts/ili/ogrili2driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,6 @@ static GDALDataset *OGRILI2DriverOpen(GDALOpenInfo *poOpenInfo)
return poDS;
}

/************************************************************************/
/* Create() */
/************************************************************************/

static GDALDataset *OGRILI2DriverCreate(const char *pszName, int /* nBands */,
int /* nXSize */, int /* nYSize */,
GDALDataType /* eDT */,
char **papszOptions)
{
OGRILI2DataSource *poDS = new OGRILI2DataSource();

if (!poDS->Create(pszName, papszOptions))
{
delete poDS;
return nullptr;
}

return poDS;
}

/************************************************************************/
/* RegisterOGRILI2() */
/************************************************************************/
Expand All @@ -86,7 +66,6 @@ void RegisterOGRILI2()

poDriver->SetDescription("Interlis 2");
poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
poDriver->SetMetadataItem(GDAL_DCAP_CURVE_GEOMETRIES, "YES");
poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Interlis 2");
Expand All @@ -102,7 +81,6 @@ void RegisterOGRILI2()
poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");

poDriver->pfnOpen = OGRILI2DriverOpen;
poDriver->pfnCreate = OGRILI2DriverCreate;

GetGDALDriverManager()->RegisterDriver(poDriver);
}
Loading

0 comments on commit 4583dc3

Please sign in to comment.