diff --git a/.github/workflows/alpine/Dockerfile.ci b/.github/workflows/alpine/Dockerfile.ci index 291a18345ba0..090bc0b66e2e 100644 --- a/.github/workflows/alpine/Dockerfile.ci +++ b/.github/workflows/alpine/Dockerfile.ci @@ -44,7 +44,6 @@ RUN apk add \ muparser-dev \ netcdf-dev \ odbc-cpp-wrapper-dev \ - ogdi-dev \ openexr-dev \ openjpeg-dev \ openssl-dev \ diff --git a/.github/workflows/alpine_32bit/Dockerfile.ci b/.github/workflows/alpine_32bit/Dockerfile.ci index 935527a4a707..96b5c858ff75 100644 --- a/.github/workflows/alpine_32bit/Dockerfile.ci +++ b/.github/workflows/alpine_32bit/Dockerfile.ci @@ -45,7 +45,6 @@ RUN apk add \ mariadb-connector-c-dev \ netcdf-dev \ odbc-cpp-wrapper-dev \ - ogdi-dev \ openexr-dev \ openjpeg-dev \ openssl-dev \ diff --git a/.github/workflows/alpine_32bit/test.sh b/.github/workflows/alpine_32bit/test.sh index 65f5b11fb26d..c0f21c260137 100755 --- a/.github/workflows/alpine_32bit/test.sh +++ b/.github/workflows/alpine_32bit/test.sh @@ -11,9 +11,6 @@ make quicktest PYTEST_SKIP= PYTEST_XFAIL="gcore/tiff_ovr.py gdrivers/gribmultidim.py gdrivers/mbtiles.py gdrivers/vrtwarp.py gdrivers/wcs.py utilities/test_gdalwarp.py pyscripts/test_gdal_pansharpen.py" -# Fails with ERROR 1: OGDI DataSource Open Failed: Could not find the dynamic library "vrf" -PYTEST_SKIP="ogr/ogr_ogdi.py $PYTEST_SKIP" - # Stalls on it. Probably not enough memory PYTEST_SKIP="gdrivers/jp2openjpeg.py $PYTEST_SKIP" diff --git a/.github/workflows/asan/test.sh b/.github/workflows/asan/test.sh index acf8a6576fd7..051aa88a92d4 100755 --- a/.github/workflows/asan/test.sh +++ b/.github/workflows/asan/test.sh @@ -49,7 +49,6 @@ find -L \ ! -name netcdf_cfchecks.py \ ! -name ogr_fgdb.py `# Don't run these` \ ! -name ogr_pgeo.py `# Don't run these` \ - ! -name ogr_ogdi.py `# Error on ogdi_5 test` \ ! -name ogr_gpsbabel.py `# new-delete-type-mismatch error in gpsbabel binary that we can't suppress` \ ! -name "__init__.py" \ ! -path 'ogr/data/*' \ diff --git a/.github/workflows/cmake_builds.yml b/.github/workflows/cmake_builds.yml index 36b90f13a3d2..5f5fdacf6fe9 100644 --- a/.github/workflows/cmake_builds.yml +++ b/.github/workflows/cmake_builds.yml @@ -55,7 +55,7 @@ jobs: libfreexl-dev unixodbc-dev libwebp-dev libepsilon-dev liblcms2-2 libcrypto++-dev libkml-dev \ libmysqlclient-dev libarmadillo-dev wget libfyba-dev libjsoncpp-dev libexpat1-dev \ libclc-dev ocl-icd-opencl-dev libsqlite3-dev sqlite3-pcre libpcre3-dev libspatialite-dev libsfcgal-dev fossil libcairo2-dev libjson-c-dev libdeflate-dev liblz4-dev libblosc-dev libarchive-dev \ - libqhull-dev libcfitsio-dev libogdi-dev libopenjp2-7-dev libheif-dev \ + libqhull-dev libcfitsio-dev libopenjp2-7-dev libheif-dev \ python3-dev libpython3-dev libpython3.8-dev python3.8-dev python3-numpy python3-lxml pyflakes python3-setuptools python3-pip python3-venv \ python3-pytest swig doxygen texlive-latex-base make cppcheck ccache g++ \ libpq-dev libpqtypes-dev postgresql-12 postgresql-12-postgis-3 postgresql-client-12 postgresql-12-postgis-3-scripts @@ -94,9 +94,6 @@ jobs: sudo apt-get update sudo apt-get install -y -V libarrow-dev libparquet-dev libarrow-dataset-dev # - # Workaround bug in ogdi packaging - sudo ln -s /usr/lib/ogdi/libvrf.so /usr/lib - # PYTHON_CMD=python3 && $PYTHON_CMD -m pip install -U pip wheel setuptools numpy importlib_metadata PYTHON_CMD=python3 && $PYTHON_CMD -m pip install -r $GITHUB_WORKSPACE/autotest/requirements.txt diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index bb776b79012e..c9dc8899895a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -74,7 +74,6 @@ jobs: liblzma-dev \ libmysqlclient-dev \ libnetcdf-dev \ - libogdi-dev \ libopenexr-dev \ libopenjp2-7-dev \ libpcre3-dev \ diff --git a/.github/workflows/s390x/Dockerfile.ci b/.github/workflows/s390x/Dockerfile.ci index 090b1f9ae9a2..9f3857f3f99a 100644 --- a/.github/workflows/s390x/Dockerfile.ci +++ b/.github/workflows/s390x/Dockerfile.ci @@ -53,7 +53,6 @@ RUN apt-get update && \ liblzma-dev${APT_ARCH_SUFFIX} \ libmysqlclient-dev${APT_ARCH_SUFFIX} \ libnetcdf-dev${APT_ARCH_SUFFIX} \ - libogdi-dev${APT_ARCH_SUFFIX} \ libopenexr-dev${APT_ARCH_SUFFIX} \ libopenjp2-7-dev${APT_ARCH_SUFFIX} \ libpcre3-dev${APT_ARCH_SUFFIX} \ diff --git a/.github/workflows/ubuntu_20.04/Dockerfile.ci b/.github/workflows/ubuntu_20.04/Dockerfile.ci index 1cced8bce495..57de7a406734 100644 --- a/.github/workflows/ubuntu_20.04/Dockerfile.ci +++ b/.github/workflows/ubuntu_20.04/Dockerfile.ci @@ -52,7 +52,6 @@ RUN apt-get update -y \ libmuparser-dev \ libmysqlclient-dev \ libnetcdf-dev \ - libogdi-dev \ libopenexr-dev \ libopenjp2-7-dev \ libpcre2-dev \ @@ -124,9 +123,6 @@ RUN mkdir tiledb \ && cd ../.. \ && rm -rf tiledeb -# Workaround bug in ogdi packaging -RUN ln -s /usr/lib/ogdi/libvrf.so /usr/lib - # Build libjxl # libjxl being still unstable, if the main branch fails to compile/test # you can replace JXL_TREEISH=main by JXL_TREEISH=sha1_of_known_working_commit @@ -276,7 +272,7 @@ RUN if test "${OPENDRIVE_VERSION}" != ""; then ( \ ); fi # Install exprtk -RUN wget -q -P /usr/local/include https://raw.githubusercontent.com/ArashPartow/exprtk/refs/heads/master/exprtk.hpp +RUN wget -q -P /usr/local/include https://raw.githubusercontent.com/ArashPartow/exprtk/refs/heads/master/exprtk.hpp RUN ldconfig diff --git a/.github/workflows/ubuntu_22.04/Dockerfile.ci b/.github/workflows/ubuntu_22.04/Dockerfile.ci index ec8f111a6362..19e046eeaf21 100644 --- a/.github/workflows/ubuntu_22.04/Dockerfile.ci +++ b/.github/workflows/ubuntu_22.04/Dockerfile.ci @@ -39,7 +39,6 @@ RUN apt-get update && \ liblzma-dev \ libmysqlclient-dev \ libnetcdf-dev \ - libogdi-dev \ libopenexr-dev \ libopenjp2-7-dev \ libpcre3-dev \ diff --git a/.github/workflows/ubuntu_24.04/Dockerfile.ci b/.github/workflows/ubuntu_24.04/Dockerfile.ci index 87a682a43eee..e548b76658d5 100644 --- a/.github/workflows/ubuntu_24.04/Dockerfile.ci +++ b/.github/workflows/ubuntu_24.04/Dockerfile.ci @@ -40,7 +40,6 @@ RUN apt-get update && \ libmuparser-dev \ libmysqlclient-dev \ libnetcdf-dev \ - libogdi-dev \ libopenexr-dev \ libopenjp2-7-dev \ libpcre3-dev \ @@ -158,10 +157,6 @@ RUN curl -L -O https://download.oracle.com/otn_software/linux/instantclient/1990 && apt-get install -y libaio1t64 \ && ln -s /usr/lib/x86_64-linux-gnu/libaio.so.1t64 /usr/lib/x86_64-linux-gnu/libaio.so.1 -# Workaround libogdi packaging issue -# Cf https://lists.debian.org/debian-gis/2024/04/msg00006.html -RUN ln -s /usr/lib/x86_64-linux-gnu/ogdi/4.1/libvrf.so /usr/lib/x86_64-linux-gnu - COPY requirements.txt /tmp/ RUN PYTHON_CMD=python3 && $PYTHON_CMD -m pip install -U --break-system-packages -r /tmp/requirements.txt diff --git a/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt b/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt index 54759dcf3534..ac5e33d7eb05 100644 --- a/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt +++ b/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt @@ -14,13 +14,11 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda CEOS -raster- (rov): CEOS Image JAXAPALSAR -raster- (rov): JAXA PALSAR Product Reader (Level 1.1/1.5) GFF -raster- (rov): Ground-based SAR Applications Testbed File Format (.gff) (*.gff) - ELAS -raster- (rw+v): ELAS ESRIC -raster- (rov): Esri Compact Cache (*.json, *.tpkx) AIG -raster- (rov): Arc/Info Binary Grid AAIGrid -raster- (rwv): Arc/Info ASCII Grid (*.asc) GRASSASCIIGrid -raster- (rov): GRASS ASCII Grid ISG -raster- (rov): International Service for the Geoid (*.isg) - SDTS -raster- (rov): SDTS Raster (*.ddf) DTED -raster- (rwv): DTED Elevation Raster (*.dt0, *.dt1, *.dt2) PNG -raster- (rwv): Portable Network Graphics (*.png) JPEG -raster- (rwv): JPEG JFIF (*.jpg, *.jpeg) @@ -31,7 +29,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda ESAT -raster- (rov): Envisat Image Format (*.n1) FITS -raster,vector- (rw+): Flexible Image Transport System (*.fits) BSB -raster- (rov): Maptech BSB Nautical Charts (*.kap) - XPM -raster- (rwv): X11 PixMap Format (*.xpm) BMP -raster- (rw+v): MS Windows Device Independent Bitmap (*.bmp) DIMAP -raster- (rovs): SPOT DIMAP AirSAR -raster- (rov): AirSAR Polarimetric Image @@ -40,7 +37,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda PCIDSK -raster,vector- (rw+v): PCIDSK Database File (*.pix) PCRaster -raster- (rw+): PCRaster Raster File (*.map) ILWIS -raster- (rw+v): ILWIS Raster Map (*.mpr, *.mpl) - SGI -raster- (rw+v): SGI Image File Format 1.0 (*.rgb) SRTMHGT -raster- (rwv): SRTMHGT File Format (*.hgt) Leveller -raster- (rw+v): Leveller heightfield (*.ter) Terragen -raster- (rw+v): Terragen heightfield (*.ter) @@ -48,7 +44,7 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda HDF4 -raster,multidimensional raster- (ros): Hierarchical Data Format Release 4 (*.hdf) HDF4Image -raster- (rw+): HDF4 Dataset ISIS3 -raster- (rw+v): USGS Astrogeology ISIS cube (Version 3) (*.lbl, *.cub) - ISIS2 -raster- (rw+v): USGS Astrogeology ISIS cube (Version 2) + ISIS2 -raster- (rov): USGS Astrogeology ISIS cube (Version 2) PDS -raster- (rov): NASA Planetary Data System PDS4 -raster,vector- (rw+vs): NASA Planetary Data System 4 (*.xml) VICAR -raster,vector- (rw+v): MIPL VICAR file @@ -56,25 +52,20 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda ERS -raster- (rw+v): ERMapper .ers Labelled (*.ers) JP2OpenJPEG -raster,vector- (rwv): JPEG-2000 driver based on JP2OpenJPEG library (*.jp2, *.j2k) L1B -raster- (rovs): NOAA Polar Orbiter Level 1b Data Set - FIT -raster- (rwv): FIT Image GRIB -raster,multidimensional raster- (rwv): GRIdded Binary (.grb, .grb2) (*.grb, *.grb2, *.grib2) RMF -raster- (rw+v): Raster Matrix Format (*.rsw) WCS -raster- (rovs): OGC Web Coverage Service WMS -raster- (rwvs): OGC Web Map Service MSGN -raster- (rov): EUMETSAT Archive native (.nat) (*.nat) RST -raster- (rw+v): Idrisi Raster A.1 (*.rst) - GSAG -raster- (rwv): Golden Software ASCII Grid (.grd) (*.grd) - GSBG -raster- (rw+v): Golden Software Binary Grid (.grd) (*.grd) GS7BG -raster- (rw+v): Golden Software 7 Binary Grid (.grd) (*.grd) COSAR -raster- (rov): COSAR Annotated Binary Matrix (TerraSAR-X) TSX -raster- (rov): TerraSAR-X Product COASP -raster- (ro): DRDC COASP SAR Processor Raster (*.hdr) - R -raster- (rwv): R Object Data Store (*.rda) MAP -raster- (rov): OziExplorer .MAP KMLSUPEROVERLAY -raster- (rwv): Kml Super Overlay (*.kml, *.kmz) WEBP -raster- (rwv): WEBP (*.webp) PDF -raster,vector- (rw+vs): Geospatial PDF (*.pdf) - Rasterlite -raster- (rwvs): Rasterlite (*.sqlite) MBTiles -raster,vector- (rw+v): MBTiles (*.mbtiles) PLMOSAIC -raster- (ro): Planet Labs Mosaics API CALS -raster- (rwv): CALS (Type 1) (*.cal, *.ct1) @@ -84,32 +75,29 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda PNM -raster- (rw+v): Portable Pixmap Format (netpbm) (*.pgm, *.ppm, *.pnm) DOQ1 -raster- (rov): USGS DOQ (Old Style) DOQ2 -raster- (rov): USGS DOQ (New Style) - PAux -raster- (rw+v): PCI .aux Labelled - MFF -raster- (rw+v): Vexcel MFF Raster (*.hdr) - MFF2 -raster- (rw+): Vexcel MFF2 (HKV) Raster + PAux -raster- (rov): PCI .aux Labelled + MFF -raster- (rov): Vexcel MFF Raster (*.hdr) + MFF2 -raster- (ro): Vexcel MFF2 (HKV) Raster GSC -raster- (rov): GSC Geogrid FAST -raster- (rov): EOSAT FAST Format - BT -raster- (rw+v): VTP .bt (Binary Terrain) 1.3 Format (*.bt) - LAN -raster- (rw+v): Erdas .LAN/.GIS + LAN -raster- (rov): Erdas .LAN/.GIS CPG -raster- (rov): Convair PolGASP NDF -raster- (rov): NLAPS Data Format EIR -raster- (rov): Erdas Imagine Raw - DIPEx -raster- (rov): DIPEx LCP -raster- (rwv): FARSITE v.4 Landscape File (.lcp) (*.lcp) GTX -raster- (rw+v): NOAA Vertical Datum .GTX (*.gtx) LOSLAS -raster- (rov): NADCON .los/.las Datum Grid Shift - NTv2 -raster- (rw+vs): NTv2 Datum Grid Shift (*.gsb, *.gvb) - CTable2 -raster- (rw+v): CTable2 Datum Grid Shift + NTv2 -raster- (rovs): NTv2 Datum Grid Shift (*.gsb, *.gvb) ACE2 -raster- (rov): ACE2 (*.ACE2) SNODAS -raster- (rov): Snow Data Assimilation System (*.hdr) KRO -raster- (rw+v): KOLOR Raw (*.kro) ROI_PAC -raster- (rw+v): ROI_PAC raster RRASTER -raster- (rw+v): R Raster (*.grd) - BYN -raster- (rw+v): Natural Resources Canada's Geoid (*.byn, *.err) + BYN -raster- (rov): Natural Resources Canada's Geoid (*.byn, *.err) NOAA_B -raster- (rov): NOAA GEOCON/NADCON5 .b format (*.b) NSIDCbin -raster- (rov): NSIDC Sea Ice Concentrations binary (.bin) (*.bin) RIK -raster- (rov): Swedish Grid RIK (.rik) (*.rik) - USGSDEM -raster- (rwv): USGS Optional ASCII DEM (and CDED) (*.dem) + USGSDEM -raster- (rov): USGS Optional ASCII DEM (and CDED) (*.dem) GXF -raster- (rov): GeoSoft Grid Exchange Format (*.gxf) BAG -raster,multidimensional raster,vector- (rw+v): Bathymetry Attributed Grid (*.bag) S102 -raster,multidimensional raster- (rovs): S-102 Bathymetric Surface Product (*.h5) @@ -119,9 +107,8 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda HDF5Image -raster- (rov): HDF5 Dataset NWT_GRD -raster- (rw+v): Northwood Numeric Grid Format .grd/.tab (*.grd) NWT_GRC -raster- (rov): Northwood Classified Grid Format .grc/.tab (*.grc) - ADRG -raster- (rw+vs): ARC Digitized Raster Graphics (*.gen) + ADRG -raster- (rovs): ARC Digitized Raster Graphics (*.gen) SRP -raster- (rovs): Standard Raster Product (ASRP/USRP) (*.img) - BLX -raster- (rwv): Magellan topo (.blx) (*.blx) GeoRaster -raster- (rw+s): Oracle Spatial GeoRaster PostGISRaster -raster- (rws): PostGIS Raster driver SAGA -raster- (rw+v): SAGA GIS Binary Grid (.sdat, .sg-grd-z) (*.sdat, *.sg-grd-z) diff --git a/.github/workflows/ubuntu_24.04/expected_ogrinfo_formats.txt b/.github/workflows/ubuntu_24.04/expected_ogrinfo_formats.txt index 7c177754dd40..053c150f30ab 100644 --- a/.github/workflows/ubuntu_24.04/expected_ogrinfo_formats.txt +++ b/.github/workflows/ubuntu_24.04/expected_ogrinfo_formats.txt @@ -12,9 +12,7 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda OGCAPI -raster,vector- (rov): OGCAPI ESRI Shapefile -vector- (rw+v): ESRI Shapefile (*.shp, *.dbf, *.shz, *.shp.zip) MapInfo File -vector- (rw+v): MapInfo File (*.tab, *.mif, *.mid) - UK .NTF -vector- (rov): UK .NTF LVBAG -vector- (rov): Kadaster LV BAG Extract 2.0 (*.xml) - OGR_SDTS -vector- (rov): SDTS S57 -vector- (rw+v): IHO S-57 (ENC) (*.000) DGN -vector- (rw+v): Microstation DGN (*.dgn) OGR_VRT -vector- (rov): VRT - Virtual Datasource (*.vrt) @@ -38,7 +36,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda WAsP -vector- (rw+v): WAsP .map format (*.map) PGeo -vector- (ro): ESRI Personal GeoDatabase (*.mdb) MSSQLSpatial -vector- (rw+): Microsoft SQL Server Spatial Database (BCP) - OGR_OGDI -vector- (ro): OGDI Vectors (VPF, VMAP, DCW) PostgreSQL -vector- (rw+): PostgreSQL/PostGIS MySQL -vector- (rw+): MySQL OCI -vector- (rw+): Oracle Spatial @@ -83,7 +80,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda MiraMonVector -vector- (rw+v): MiraMon Vectors (.pol, .arc, .pnt) (*.pol, *.arc, *.pnt) XODR -vector- (ro): OpenDRIVE - Open Dynamic Road Information for Vehicle Environment (*.xodr) ADBC -vector- (ro): Arrow Database Connectivity - TIGER -vector- (rov): U.S. Census TIGER/Line AVCBin -vector- (rov): Arc/Info Binary Coverage AVCE00 -vector- (rov): Arc/Info E00 (ASCII) Coverage (*.e00) AIVector -vector- (ro): Artificial Intelligence powered vector driver diff --git a/.github/workflows/windows_conda_expected_gdalinfo_formats.txt b/.github/workflows/windows_conda_expected_gdalinfo_formats.txt index 2077516a871d..e2e4c551d3e3 100644 --- a/.github/workflows/windows_conda_expected_gdalinfo_formats.txt +++ b/.github/workflows/windows_conda_expected_gdalinfo_formats.txt @@ -14,13 +14,11 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda CEOS -raster- (rov): CEOS Image JAXAPALSAR -raster- (rov): JAXA PALSAR Product Reader (Level 1.1/1.5) GFF -raster- (rov): Ground-based SAR Applications Testbed File Format (.gff) (*.gff) - ELAS -raster- (rw+v): ELAS ESRIC -raster- (rov): Esri Compact Cache (*.json, *.tpkx) AIG -raster- (rov): Arc/Info Binary Grid AAIGrid -raster- (rwv): Arc/Info ASCII Grid (*.asc) GRASSASCIIGrid -raster- (rov): GRASS ASCII Grid ISG -raster- (rov): International Service for the Geoid (*.isg) - SDTS -raster- (rov): SDTS Raster (*.ddf) DTED -raster- (rwv): DTED Elevation Raster (*.dt0, *.dt1, *.dt2) PNG -raster- (rwv): Portable Network Graphics (*.png) JPEG -raster- (rwv): JPEG JFIF (*.jpg, *.jpeg) @@ -31,7 +29,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda ESAT -raster- (rov): Envisat Image Format (*.n1) FITS -raster,vector- (rw+): Flexible Image Transport System (*.fits) BSB -raster- (rov): Maptech BSB Nautical Charts (*.kap) - XPM -raster- (rwv): X11 PixMap Format (*.xpm) BMP -raster- (rw+v): MS Windows Device Independent Bitmap (*.bmp) DIMAP -raster- (rovs): SPOT DIMAP AirSAR -raster- (rov): AirSAR Polarimetric Image @@ -40,7 +37,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda PCIDSK -raster,vector- (rw+v): PCIDSK Database File (*.pix) PCRaster -raster- (rw+): PCRaster Raster File (*.map) ILWIS -raster- (rw+v): ILWIS Raster Map (*.mpr, *.mpl) - SGI -raster- (rw+v): SGI Image File Format 1.0 (*.rgb) SRTMHGT -raster- (rwv): SRTMHGT File Format (*.hgt) Leveller -raster- (rw+v): Leveller heightfield (*.ter) Terragen -raster- (rw+v): Terragen heightfield (*.ter) @@ -48,7 +44,7 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda HDF4 -raster,multidimensional raster- (ros): Hierarchical Data Format Release 4 (*.hdf) HDF4Image -raster- (rw+): HDF4 Dataset ISIS3 -raster- (rw+v): USGS Astrogeology ISIS cube (Version 3) (*.lbl, *.cub) - ISIS2 -raster- (rw+v): USGS Astrogeology ISIS cube (Version 2) + ISIS2 -raster- (rov): USGS Astrogeology ISIS cube (Version 2) PDS -raster- (rov): NASA Planetary Data System PDS4 -raster,vector- (rw+vs): NASA Planetary Data System 4 (*.xml) VICAR -raster,vector- (rw+v): MIPL VICAR file @@ -56,7 +52,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda ERS -raster- (rw+v): ERMapper .ers Labelled (*.ers) JP2OpenJPEG -raster,vector- (rwv): JPEG-2000 driver based on JP2OpenJPEG library (*.jp2, *.j2k) L1B -raster- (rovs): NOAA Polar Orbiter Level 1b Data Set - FIT -raster- (rwv): FIT Image GRIB -raster,multidimensional raster- (rwv): GRIdded Binary (.grb, .grb2) (*.grb, *.grb2, *.grib2) RMF -raster- (rw+v): Raster Matrix Format (*.rsw) WCS -raster- (rovs): OGC Web Coverage Service @@ -64,18 +59,14 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda MSGN -raster- (rov): EUMETSAT Archive native (.nat) (*.nat) MSG -raster- (ro): MSG HRIT Data RST -raster- (rw+v): Idrisi Raster A.1 (*.rst) - GSAG -raster- (rwv): Golden Software ASCII Grid (.grd) (*.grd) - GSBG -raster- (rw+v): Golden Software Binary Grid (.grd) (*.grd) GS7BG -raster- (rw+v): Golden Software 7 Binary Grid (.grd) (*.grd) COSAR -raster- (rov): COSAR Annotated Binary Matrix (TerraSAR-X) TSX -raster- (rov): TerraSAR-X Product COASP -raster- (ro): DRDC COASP SAR Processor Raster (*.hdr) - R -raster- (rwv): R Object Data Store (*.rda) MAP -raster- (rov): OziExplorer .MAP KMLSUPEROVERLAY -raster- (rwv): Kml Super Overlay (*.kml, *.kmz) WEBP -raster- (rwv): WEBP (*.webp) PDF -raster,vector- (rw+vs): Geospatial PDF (*.pdf) - Rasterlite -raster- (rwvs): Rasterlite (*.sqlite) MBTiles -raster,vector- (rw+v): MBTiles (*.mbtiles) PLMOSAIC -raster- (ro): Planet Labs Mosaics API CALS -raster- (rwv): CALS (Type 1) (*.cal, *.ct1) @@ -86,31 +77,28 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda PNM -raster- (rw+v): Portable Pixmap Format (netpbm) (*.pgm, *.ppm, *.pnm) DOQ1 -raster- (rov): USGS DOQ (Old Style) DOQ2 -raster- (rov): USGS DOQ (New Style) - PAux -raster- (rw+v): PCI .aux Labelled - MFF -raster- (rw+v): Vexcel MFF Raster (*.hdr) - MFF2 -raster- (rw+): Vexcel MFF2 (HKV) Raster + PAux -raster- (rov): PCI .aux Labelled + MFF -raster- (rov): Vexcel MFF Raster (*.hdr) + MFF2 -raster- (ro): Vexcel MFF2 (HKV) Raster GSC -raster- (rov): GSC Geogrid FAST -raster- (rov): EOSAT FAST Format - BT -raster- (rw+v): VTP .bt (Binary Terrain) 1.3 Format (*.bt) - LAN -raster- (rw+v): Erdas .LAN/.GIS + LAN -raster- (rov): Erdas .LAN/.GIS CPG -raster- (rov): Convair PolGASP NDF -raster- (rov): NLAPS Data Format EIR -raster- (rov): Erdas Imagine Raw - DIPEx -raster- (rov): DIPEx LCP -raster- (rwv): FARSITE v.4 Landscape File (.lcp) (*.lcp) GTX -raster- (rw+v): NOAA Vertical Datum .GTX (*.gtx) LOSLAS -raster- (rov): NADCON .los/.las Datum Grid Shift - NTv2 -raster- (rw+vs): NTv2 Datum Grid Shift (*.gsb, *.gvb) - CTable2 -raster- (rw+v): CTable2 Datum Grid Shift + NTv2 -raster- (rovs): NTv2 Datum Grid Shift (*.gsb, *.gvb) ACE2 -raster- (rov): ACE2 (*.ACE2) SNODAS -raster- (rov): Snow Data Assimilation System (*.hdr) KRO -raster- (rw+v): KOLOR Raw (*.kro) ROI_PAC -raster- (rw+v): ROI_PAC raster RRASTER -raster- (rw+v): R Raster (*.grd) - BYN -raster- (rw+v): Natural Resources Canada's Geoid (*.byn, *.err) + BYN -raster- (rov): Natural Resources Canada's Geoid (*.byn, *.err) NOAA_B -raster- (rov): NOAA GEOCON/NADCON5 .b format (*.b) RIK -raster- (rov): Swedish Grid RIK (.rik) (*.rik) - USGSDEM -raster- (rwv): USGS Optional ASCII DEM (and CDED) (*.dem) + USGSDEM -raster- (rov): USGS Optional ASCII DEM (and CDED) (*.dem) GXF -raster- (rov): GeoSoft Grid Exchange Format (*.gxf) KEA -raster- (rw+v): KEA Image Format (.kea) (*.kea) BAG -raster,multidimensional raster,vector- (rw+v): Bathymetry Attributed Grid (*.bag) @@ -121,9 +109,8 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda HDF5Image -raster- (rov): HDF5 Dataset NWT_GRD -raster- (rw+v): Northwood Numeric Grid Format .grd/.tab (*.grd) NWT_GRC -raster- (rov): Northwood Classified Grid Format .grc/.tab (*.grc) - ADRG -raster- (rw+vs): ARC Digitized Raster Graphics (*.gen) + ADRG -raster- (rovs): ARC Digitized Raster Graphics (*.gen) SRP -raster- (rovs): Standard Raster Product (ASRP/USRP) (*.img) - BLX -raster- (rwv): Magellan topo (.blx) (*.blx) PostGISRaster -raster- (rws): PostGIS Raster driver SAGA -raster- (rw+v): SAGA GIS Binary Grid (.sdat, .sg-grd-z) (*.sdat, *.sg-grd-z) XYZ -raster- (rwv): ASCII Gridded XYZ (*.xyz) diff --git a/.github/workflows/windows_conda_expected_ogrinfo_formats.txt b/.github/workflows/windows_conda_expected_ogrinfo_formats.txt index 8835cecc2370..744a9af312b4 100644 --- a/.github/workflows/windows_conda_expected_ogrinfo_formats.txt +++ b/.github/workflows/windows_conda_expected_ogrinfo_formats.txt @@ -13,9 +13,7 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda OGCAPI -raster,vector- (rov): OGCAPI ESRI Shapefile -vector- (rw+v): ESRI Shapefile (*.shp, *.dbf, *.shz, *.shp.zip) MapInfo File -vector- (rw+v): MapInfo File (*.tab, *.mif, *.mid) - UK .NTF -vector- (rov): UK .NTF LVBAG -vector- (rov): Kadaster LV BAG Extract 2.0 (*.xml) - OGR_SDTS -vector- (rov): SDTS S57 -vector- (rw+v): IHO S-57 (ENC) (*.000) DGN -vector- (rw+v): Microstation DGN (*.dgn) OGR_VRT -vector- (rov): VRT - Virtual Datasource (*.vrt) @@ -78,7 +76,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda JSONFG -vector- (rw+v): OGC Features and Geometries JSON (*.json) MiraMonVector -vector- (rw+v): MiraMon Vectors (.pol, .arc, .pnt) (*.pol, *.arc, *.pnt) ADBC -vector- (ro): Arrow Database Connectivity - TIGER -vector- (rov): U.S. Census TIGER/Line AVCBin -vector- (rov): Arc/Info Binary Coverage AVCE00 -vector- (rov): Arc/Info E00 (ASCII) Coverage (*.e00) AIVector -vector- (ro): Artificial Intelligence powered vector driver diff --git a/autotest/gdrivers/adrg.py b/autotest/gdrivers/adrg.py index b373759cbce4..a6cec6e33432 100755 --- a/autotest/gdrivers/adrg.py +++ b/autotest/gdrivers/adrg.py @@ -12,9 +12,6 @@ # SPDX-License-Identifier: MIT ############################################################################### -import os -import shutil - import gdaltest import pytest @@ -58,91 +55,6 @@ def test_adrg_read_subdataset_img(): tst.testOpen() -############################################################################### -# Test copying. - - -def test_adrg_copy(): - - drv = gdal.GetDriverByName("ADRG") - srcds = gdal.Open("data/adrg/SMALL_ADRG/ABCDEF01.GEN") - - dstds = drv.CreateCopy("tmp/ABCDEF01.GEN", srcds) - - chksum = dstds.GetRasterBand(1).Checksum() - - assert chksum == 62833, "Wrong checksum" - - dstds = None - - drv.Delete("tmp/ABCDEF01.GEN") - - -############################################################################### -# Test creating a fake 2 subdataset image and reading it. - - -def test_adrg_2subdatasets(): - - drv = gdal.GetDriverByName("ADRG") - srcds = gdal.Open("data/adrg/SMALL_ADRG/ABCDEF01.GEN") - - with gdal.config_option("ADRG_SIMULATE_MULTI_IMG", "ON"): - dstds = drv.CreateCopy("tmp/XXXXXX01.GEN", srcds) - del dstds - - shutil.copy("tmp/XXXXXX01.IMG", "tmp/XXXXXX02.IMG") - - ds = gdal.Open("tmp/TRANSH01.THF") - assert ds.RasterCount == 0, "did not expected non 0 RasterCount" - ds = None - - ds = gdal.Open("ADRG:tmp/XXXXXX01.GEN,tmp/XXXXXX02.IMG") - chksum = ds.GetRasterBand(1).Checksum() - - assert chksum == 62833, "Wrong checksum" - - md = ds.GetMetadata("") - assert md["ADRG_NAM"] == "XXXXXX02", "metadata wrong." - - ds = None - - os.remove("tmp/XXXXXX01.GEN") - os.remove("tmp/XXXXXX01.GEN.aux.xml") - os.remove("tmp/XXXXXX01.IMG") - os.remove("tmp/XXXXXX02.IMG") - os.remove("tmp/TRANSH01.THF") - - -############################################################################### -# Test creating an in memory copy. - - -def test_adrg_copy_vsimem(): - - drv = gdal.GetDriverByName("ADRG") - srcds = gdal.Open("data/adrg/SMALL_ADRG/ABCDEF01.GEN") - - dstds = drv.CreateCopy("/vsimem/ABCDEF01.GEN", srcds) - - chksum = dstds.GetRasterBand(1).Checksum() - - assert chksum == 62833, "Wrong checksum" - - dstds = None - - # Reopen file - ds = gdal.Open("/vsimem/ABCDEF01.GEN") - - chksum = ds.GetRasterBand(1).Checksum() - assert chksum == 62833, "Wrong checksum" - - ds = None - - drv.Delete("/vsimem/ABCDEF01.GEN") - gdal.Unlink("/vsimem/TRANSH01.THF") - - ############################################################################### # Test reading a fake North Polar dataset (#6560) @@ -196,3 +108,23 @@ def test_adrg_zna_18(): ############################################################################### +# Test reading dataset with 2 subdataset image + + +def test_adrg_read_2subdatasets(): + + ds = gdal.Open("data/adrg/subdataset/TRANSH01.THF") + assert ds.RasterCount == 0, "did not expected non 0 RasterCount" + ds = None + + ds = gdal.Open( + "ADRG:data/adrg/subdataset/XXXXXX01.GEN,data/adrg/subdataset/XXXXXX02.IMG" + ) + chksum = ds.GetRasterBand(1).Checksum() + + assert chksum == 62833, "Wrong checksum" + + md = ds.GetMetadata("") + assert md["ADRG_NAM"] == "XXXXXX02", "metadata wrong." + + ds = None diff --git a/autotest/gdrivers/blx.py b/autotest/gdrivers/blx.py deleted file mode 100755 index 2edc448e43ef..000000000000 --- a/autotest/gdrivers/blx.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test BLX support. -# Author: Even Rouault < even dot rouault @ spatialys.com > -# -############################################################################### -# Copyright (c) 2008, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import gdaltest -import pytest - -from osgeo import gdal - -pytestmark = pytest.mark.require_driver("BLX") - -############################################################################### -# Test reading a little-endian BLX - - -def test_blx_1(): - - prj = "WGS84" - gt = [20.0004166, 0.0008333, 0.0, 50.0004166, 0.0, -0.0008333] - tst = gdaltest.GDALTest("BLX", "blx/s4103.blx", 1, 47024) - tst.testOpen(check_prj=prj, check_gt=gt) - - -############################################################################### -# Test reading a big-endian BLX - - -def test_blx_2(): - - prj = "WGS84" - gt = [20.0004166, 0.0008333, 0.0, 50.0004166, 0.0, -0.0008333] - tst = gdaltest.GDALTest("BLX", "blx/s4103.xlb", 1, 47024) - tst.testOpen(check_prj=prj, check_gt=gt) - - -############################################################################### -# Test writing a little-endian BLX - - -def test_blx_3(): - - tst = gdaltest.GDALTest("BLX", "blx/s4103.xlb", 1, 47024) - tst.testCreateCopy(check_gt=1, check_srs=1) - - -############################################################################### -# Test writing a big-endian BLX - - -def test_blx_4(): - - tst = gdaltest.GDALTest("BLX", "blx/s4103.blx", 1, 47024, options=["BIGENDIAN=YES"]) - tst.testCreateCopy(check_gt=1, check_srs=1) - - -############################################################################### -# Test overviews - - -def test_blx_5(): - - ds = gdal.Open("data/blx/s4103.blx") - - band = ds.GetRasterBand(1) - assert band.GetOverviewCount() == 4, "did not get expected overview count" - - cs = band.GetOverview(0).Checksum() - assert cs == 42981, "wrong overview checksum (%d)" % cs - - cs = band.GetOverview(1).Checksum() - assert cs == 61363, "wrong overview checksum (%d)" % cs - - cs = band.GetOverview(2).Checksum() - assert cs == 48060, "wrong overview checksum (%d)" % cs - - cs = band.GetOverview(3).Checksum() - assert cs == 12058, "wrong overview checksum (%d)" % cs diff --git a/autotest/gdrivers/bt.py b/autotest/gdrivers/bt.py deleted file mode 100755 index 2aba56e14f9a..000000000000 --- a/autotest/gdrivers/bt.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read/write functionality for BT driver. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2008-2011, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import gdaltest -import pytest - -from osgeo import gdal, osr - -pytestmark = pytest.mark.require_driver("BT") - - -@pytest.fixture(scope="module", autouse=True) -def setup_and_cleanup(): - - yield - - for f in ("/vsimem/int16.tif.prj", "tmp/int32.tif.prj", "tmp/float32.tif.prj"): - try: - gdal.Unlink(f) - except RuntimeError: - pass - - -############################################################################### -# Test CreateCopy() - - -@pytest.mark.parametrize( - "fname,to_vsimem", - [("int16.tif", True), ("int32.tif", False), ("float32.tif", False)], -) -def test_bt_create_copy(fname, to_vsimem): - - tst = gdaltest.GDALTest("BT", fname, 1, 4672) - srs = osr.SpatialReference() - srs.SetWellKnownGeogCS("NAD27") - tst.testCreateCopy( - vsimem=to_vsimem, - check_srs=srs.ExportToWkt(), - check_gt=(-67.00041667, 0.00083333, 0.0, 50.000416667, 0.0, -0.00083333), - ) - - -############################################################################### -# Test Create() of float32.tif - - -def test_bt_create(): - - tst = gdaltest.GDALTest("BT", "float32.tif", 1, 4672) - tst.testCreate(out_bands=1) - - -############################################################################### -# Test testSetProjection() of float32.tif - - -def test_bt_set_projection(): - - tst = gdaltest.GDALTest("BT", "float32.tif", 1, 4672) - tst.testSetProjection() - - -############################################################################### -# Test testSetGeoTransform() of float32.tif - - -def test_bt_set_geotransform(): - - tst = gdaltest.GDALTest("BT", "float32.tif", 1, 4672) - tst.testSetGeoTransform() diff --git a/autotest/gdrivers/byn.py b/autotest/gdrivers/byn.py index 3027fb12a724..68417f7bd9f2 100755 --- a/autotest/gdrivers/byn.py +++ b/autotest/gdrivers/byn.py @@ -34,16 +34,6 @@ def test_byn_1(): # -def test_byn_2(): - - tst = gdaltest.GDALTest("BYN", "byn/cgg2013ai08_reduced.byn", 1, 64764) - tst.testCreateCopy(new_filename="tmp/byn_test_2.byn") - - -############################################################################### -# - - def test_byn_invalid_header_bytes(): tst = gdaltest.GDALTest("BYN", "byn/test_invalid_header_bytes.byn", 1, 64764) diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107CATD.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107CATD.DDF deleted file mode 100644 index 852afcf4bba3..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107CATD.DDF +++ /dev/null @@ -1 +0,0 @@ -001672L 1 0600049 22040000210000012921CATD68500000;&1107CATD.DDF0100;&DDF RECORD IDENTIFER1600;&Catalog/DirectoryMODN!RCID!NAME!TYPE!FILE!EXTR!MVER(A,I,5A)00091 D 1 00039 21040001080CATD4480000001CATD1IDENIdentification1107IDEN.DDFN100103 D 1 00039 21040001080CATD5680000002CATD2IREFInternal Spatial Reference1107IREF.DDFN100103 D 1 00039 21040001080CATD5680000003CATD3XREFExternal Spatial Reference1107XREF.DDFN100099 D 1 00039 21040001080CATD5280000004CATD4DDSHData Dictionary/Schema1107DDSH.DDFN100099 D 1 00039 21040001080CATD5280000005CATD5DDOMData Dictionary/Domain1107DDOM.DDFN100097 D 1 00039 21040001080CATD5080000006CATD6DQHLData Quality/Lineage1107DQHL.DDFN100109 D 1 00039 21040001080CATD6280000007CATD7DQPAData Quality/Positional Accuracy1107DQPA.DDFN100108 D 1 00039 21040001080CATD6180000008CATD8DQAAData Quality/Attribute Accuracy1107DQAA.DDFN100109 D 1 00039 21040001080CATD6280000009CATD9DQLCData Quality/Logical Consistency1107DQLC.DDFN100103 D 1 00039 21040001080CATD5680000010CATD10DQCGData Quality/Completeness1107DQCG.DDFN100095 D 1 00039 21040001080CATD4880000011CATD11RSDFRaster Definition1107RSDF.DDFN100094 D 1 00039 21040001080CATD4780000012CATD12LDEFLayer Definition1107LDEF.DDFN100095 D 1 00039 21040001080CATD4880000013CATD13CATDCatalog/Directory1107CATD.DDFN100100 D 1 00039 21040001080CATD5380000014CATD14CATSCatalog/Spatial Domain1107CATS.DDFN100097 D 1 00039 21040001080CATD5080000015CATD15STATTransfer Statistics1107STAT.DDFN100104 D 1 00039 21040001080CATD5780000016CATD16DDDFData Dictionary/Definition1107DDDF.DDFN100092 D 1 00039 21040001080CATD4580000017CATD17SPDMSpatial Domain1107SPDM.DDFN100082 D 1 00039 21040001080CATD3580000018CATD18CEL0Cell1107CEL0.DDFN1 \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107CATS.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107CATS.DDF deleted file mode 100644 index 2eead64d098c..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107CATS.DDF +++ /dev/null @@ -1 +0,0 @@ -001762L 1 0600049 22040000210000012921CATS77500000;&1107CATS.DDF0100;&DDF RECORD IDENTIFER1600;&Catalog/Spatial DomainMODN!RCID!NAME!TYPE!MAP!THEM!AGOB!AGTP(A,I,6A)00133 D 1 00039 21040001080CATS8680000001CATS1IDENIdentificationALANSON, MI ELEVATIONDEM1G200145 D 1 00039 21040001080CATS9880000002CATS2IREFInternal Spatial ReferenceALANSON, MI ELEVATIONDEM1G200145 D 1 00039 21040001080CATS9880000003CATS3XREFExternal Spatial ReferenceALANSON, MI ELEVATIONDEM1G200133 D 1 00039 21040001080CATS8680000004CATS4SPDMSpatial DomainALANSON, MI ELEVATIONDEM1G200139 D 1 00039 21040001080CATS9280000005CATS5DQHLData Quality/LineageALANSON, MI ELEVATIONDEM1G200153 D 1 00041 310400010080CATS10480000006CATS6DQPAData Quality/Positional AccuracyALANSON, MI ELEVATIONDEM1G200152 D 1 00041 310400010080CATS10380000007CATS7DQAAData Quality/Attribute AccuracyALANSON, MI ELEVATIONDEM1G200153 D 1 00041 310400010080CATS10480000008CATS8DQLCData Quality/Logical ConsistancyALANSON, MI ELEVATIONDEM1G200144 D 1 00039 21040001080CATS9780000009CATS9DQCGData Quality/CompletenessALANSON, MI ELEVATIONDEM1G200146 D 1 00039 21040001080CATS9980000010CATS10DDDFData Dictionary/DefinitionALANSON, MI ELEVATIONDEM1G200142 D 1 00039 21040001080CATS9580000011CATS11DDOMData Dictionary/DomainALANSON, MI ELEVATIONDEM1G200142 D 1 00039 21040001080CATS9580000012CATS12DDSHData Dictionary/SchemaALANSON, MI ELEVATIONDEM1G200137 D 1 00039 21040001080CATS9080000013CATS13RSDFRaster DefinitionALANSON, MI ELEVATIONDEM1G200136 D 1 00039 21040001080CATS8980000014CATS14LDEFLayer DefinitionALANSON, MI ELEVATIONDEM1G200124 D 1 00039 21040001080CATS7780000015CATS15CEL0CellALANSON, MI ELEVATIONDEM1G200142 D 1 00039 21040001080CATS9580000016CATS16CATSCatalog/Spatial DomainALANSON, MI ELEVATIONDEM1G200139 D 1 00039 21040001080CATS9280000017CATS17STATTransfer StatisticsALANSON, MI ELEVATIONDEM1G200137 D 1 00039 21040001080CATS9080000018CATS18CATDCatalog/DirectoryALANSON, MI ELEVATIONDEM1G2 \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107CEL0.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107CEL0.DDF deleted file mode 100644 index cf38cbb1e08b..000000000000 Binary files a/autotest/gdrivers/data/STDS_1107834_truncated/1107CEL0.DDF and /dev/null differ diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107DDDF.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107DDDF.DDF deleted file mode 100644 index e479d2bffa4b..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107DDDF.DDF +++ /dev/null @@ -1 +0,0 @@ -001762L 1 0600049 22040000210000012921DDDF77500000;&1107DDDF.DDF0100;&DDF RECORD IDENTIFER1600;&Data Dictionary/DefinitionMODN!RCID!EORA!EALB!DFIN!AUTH!ADSC(A,I,5A)00169 D 1 00041 310400010080DDDF12080000001DDDF1ATTELEVATIONThe vertical distance from a given datumUSGS/NMDU.S. Geological Survey/National Mapping Division \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107DDOM.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107DDOM.DDF deleted file mode 100644 index 825275c8ca95..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107DDOM.DDF +++ /dev/null @@ -1 +0,0 @@ -001912L 1 0600049 22040000210000012921DDOM92500000;&1107DDOM.DDF0100;&DDF RECORD IDENTIFER1600;&Data Dictionary/DomainMODN!RCID!ATLB!AUTH!ATYP!ADVF!ADMU!RAVA!DVAL!DVDF(A,I,6A,I,A)00114 D 1 00039 21040001080DDOM6780000001DDOM1ELEVATIONUSGS/NMDINTEGERIVALUE-32767Void area in DEM00141 D 1 00039 21040001080DDOM9480000002DDOM2ELEVATIONUSGS/NMDINTEGERIVALUE-32766Fill Value used to make the DEM a rectangle00127 D 1 00039 21040001080DDOM8080000003DDOM3ELEVATIONUSGS/NMDINTEGERIMETERSMIN182Minimum elevation of the DEM00127 D 1 00039 21040001080DDOM8080000004DDOM4ELEVATIONUSGS/NMDINTEGERIMETERSMAX345Maximum elevation of the DEM \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107DDSH.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107DDSH.DDF deleted file mode 100644 index 6ce062b997d8..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107DDSH.DDF +++ /dev/null @@ -1 +0,0 @@ -001832L 1 0600049 22040000210000012921DDSH84500000;&1107DDSH.DDF0100;&DDF RECORD IDENTIFER1600;&Data Dictionary/SchemaMODN!RCID!NAME!TYPE!ATLB!AUTH!FMT!UNIT!PREC(A,I,6A,R)00106 D 1 00039 21040001080DDSH5980000001DDSH1CEL0CELLELEVATIONUSGS/NMDBI16METERS1.00000000 \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQAA.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107DQAA.DDF deleted file mode 100644 index 03b809607e9c..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQAA.DDF +++ /dev/null @@ -1,2 +0,0 @@ -001472L 1 0600049 22040000210000012921DQAA48500000;&1107DQAA.DDF0100;&DDF RECORD IDENTIFER1600;&Attribute AccuracyMODN!RCID!COMT(A,I,A)00175 D 1 00041 310400010080DQAA12680000001DQAA1No Attribute Accuracy to report. See Positional Accuracy module, -because the cell values are elevation measurements. \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQCG.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107DQCG.DDF deleted file mode 100644 index db00e4582d61..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQCG.DDF +++ /dev/null @@ -1,34 +0,0 @@ -001412L 1 0600049 22040000210000012921DQCG42500000;&1107DQCG.DDF0100;&DDF RECORD IDENTIFER1600;&CompletenessMODN!RCID!COMT(A,I,A)00081 D 1 00039 21040001080DQCG3480000001DQCG1VOID AREAS: No void areas.00793 D 1 00041 310400010080DQCG74480000002DQCG2The 7.5-minute series DEMS are based on a UTM grid. Hence, the scans -do not always have the same number of elevation posts due to the -variable angle between true north and grid north of the UTM coordinate -system. Any elevation post that falls outside of the 7.5-minute -quadrangle edge is dropped, i.e. there is no overedge. The 7.5-minute -DEM will be encoded as a non-ragged grid by filling with a background -post value to the edges of the minimum bounding rectangle. The fill -value is distinguishable from all other elevation post values, and it -will be same value for all USGS DEM series encoded in SDTS. The Void -post value(-32767) will not be reused as the fill value, so the -original extent of the DEM data can easily be detected.00471 D 1 00041 310400010080DQCG42280000003DQCG3Void areas occur in the DEM as a result of interruptions -to the contours of the source graphic or DLG (eg. photoimages -overprinted onto a topographic map). Each DEM elevation post located -within a void area is assigned a false negative value of -32,767. The -percentage of void elevation values in the DEM, if present, was -calculated from the total number of grid posts in the DEM assigned the -false negative value.01225 D 1 00043 4104000100080DQCG117480000004DQCG4HYDROGRAPHY INCLUDED: For DEM Level 1 and 2, water bodies -contained in DEM data are edited when they conform to the following -criteria: 1) Type is a pond, lake, reservoir, or double-line drainage; -and, 2) Size of a pond, lake or reservoir exceeds approximately 1/2 -inch at map scale (1000 feet at 1:24,000 scale, 4167 feet at 1:100,000 -scale) along the major axis; or, 3) Size of a double-line drain -exceeds 1/4 inch (500 feet at 1:24,000 scale, 2087 feet at 1:100,000 -scale) in width. For level 3 DEM's, the grid is constrained by all -major hydrographic features contained within a DLG hydrography -category, including drainage, lakes, swamps, and -shorelines. Elevations of hydrographic features are determined through -interpolation of contours using a registered DLG hypsography file. DEM -surfaces constrained to drains are treated as a special case of -hypsographic faulting where the DEM surface is simply creased along -the track line of the drain. Additionally, all grid cells are tilted -consistent with the direction of stream flow, along the track line of -the drain. There must not be any unsupported breaks or discontinuities -in the rate of slope of the drain. \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQHL.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107DQHL.DDF deleted file mode 100644 index 48e36ed738dc..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQHL.DDF +++ /dev/null @@ -1,46 +0,0 @@ -001362L 1 0600049 22040000210000012921DQHL37500000;&1107DQHL.DDF0100;&DDF RECORD IDENTIFER1600;&LineageMODN!RCID!COMT(A,I,A)01754 D 1 00043 4104000100080DQHL170380000001DQHL1CONVERSION TO SDTS: This DEM was converted to SDTS Raster Profile as -part ofa mass conversion of US Geological Survey Digital Elevation -model archive to SDTS. The data organization was changed from a -southwest origin with south to north scans to a northwest origin with -west to east scans. The x,y grid positions were not altered -- i.e., -the data was not resampled. The UTM gridded DEMs are ragged in their -native form. A fill value was used too make the DEM grid rectangular -in this transfer. - - -GENERAL NOTES: A number of factors affect gridding processes and the -accuracy of the final DEM product: 1) A dependency exists between the -scale of the source materials and the level of detail or grid -refinement that is possible from a given source. 2) During the -process of changing scale, from large to small, some source data may -be generalized or dropped out and, therefore, some features would not -be available for formation of, or incorporation into, a grid at that -scale. 3) The process of forming a grid with regular spacing requires -the transfer of precise point or vector data to generalized grid -square corners using a process similar to taking a simple weighted -average. This process may alter the apparent position upon display of -point or vector source data, reducing the ability to recover positions -of specific features whose dimensions are less than the internal grid -cell spacing. For all DEM's, the grid spacing and spatial resolution -results in data intervals that span terrain discontinuities, such as -benches, tops, and drainage. Some features can be appropriately -captured at a given grid spacing while other, smaller features are -subdued or filtered out altogether.00087 D 1 00039 21040001080DQHL4080000002DQHL2DEM CELL NAME: ALANSON, MI-2400000117 D 1 00039 21040001080DQHL7080000003DQHL3PROCESS CODE 5: DLG/hypsography LINETRACE, LT4X complex linear00070 D 1 00039 21040001080DQHL2380000004DQHL4DEM PRODUCER: 00066 D 1 00039 21040001080DQHL1980000005DQHL5DEM LEVEL-200436 D 1 00041 310400010080DQHL38780000006DQHL6DEM LEVEL 2 means: DEM created from digital line graph (DLG) contours or equivalent, or from any USGS map series up to 1:100,00 scale using stable base contour separate or equivalent. DEM data derived from hyposgraphic and hydrographic data digitizing, either photogrammetrically or from existing maps, are entered into the Level 2 category after review on a DEM editing system.00105 D 1 00039 21040001080DQHL5880000007DQHL7SOURCE DATE OF PUBLISHED MAP OR PHOTOGRAPHY: 198300094 D 1 00039 21040001080DQHL4780000008DQHL8DATA INSPECTION OR REVISION DATE: 199800145 D 1 00039 21040001080DQHL9880000009DQHL9INSPECTION FLAG: Iindicates all process of part three quality control have been performed.00152 D 1 00041 310400010080DQHL10380000010DQHL10DATA VALIDATION FLAG: Level 2 and 3 DEMs reviewed and edited. RSME computed from test points.00085 D 1 00039 21040001080DQHL3880000011DQHL11DATA EDITION: 1: USGS default00111 D 1 00039 21040001080DQHL6480000012DQHL12GRID RESOLUTION: 30.000000 METERS X, 30.000000 METERS Y01326 D 1 00043 4104000100080DQHL127580000013DQHL13VISUAL VERIFICATION: Because of practical limitations -inherent in all collection systems, there will always be some artifacts -such as benches, striations, patches, or some other anomaly that -imparts some signature of the collection system in the data set. Some -of these artifacts, although falling within normal DEM vertical error -tolerances, can coalesce with valid surface features. All DEM's are -viewed and edited so corrective actions can be taken to minimize these -artifacts. For example, 1) Isolated tops are depicted with their -approximate size and shape; 2) Flat trending surfaces are depicted as -generally flat trending without confusing patterns or striations; and, -3) Water bodies are flat, lower than the surrounding terrain, and have -shorelines clearly delineated. Additional testing is performed using -a DEM Editing System (DES) to aid in the identification of blunders -such as irregularly gridded data, mistagging of tops and depressions, -and spikes. These blunders are generally identified by displaying the -DEM with the aid of DES options, which include color banding of -elevation gradients, stereoscopic viewing using anaglyphic filters, -and shaded-relief enhancement. An elevation matrix is analyzed in -suspect areas and corrected as required. \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQLC.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107DQLC.DDF deleted file mode 100644 index 0eb2e690c3f2..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQLC.DDF +++ /dev/null @@ -1,18 +0,0 @@ -001482L 1 0600049 22040000210000012921DQLC49500000;&1107DQLC.DDF0100;&DDF RECORD IDENTIFER1600;&Logical ConsistencyMODN!RCID!COMT(A,I,A)00650 D 1 00041 310400010080DQLC60180000001DQLC1EDGE MATCH STATUS: West(1), North(1), East(4), South(4). - -Edge matching is a process of matching elevation values along common -quadrangle edges. The objective of edge matching is to improve the -alignment of ridges and drains and overall topographic shaping and -representation. Code of 0 = not edge matched; 1 = edge match checked -and joined; 2 = not edge matched because adjoining DEM is on a -different horizontal or vertical datum; 3 = not edge matched because -the adjoining DEM is not part of the current project; 4 = not edge -matched because the adjoining DEM has a different vertical unit.00618 D 1 00041 310400010080DQLC56980000002DQLC2NULL SCHEME: The method for indicating no value for a cell in the -Cell module records contained in this transfer is described here. In -the Data Dictionary Domain module there are specific values that are -reserved to mean VOID and FILL for ELEVATION. VOID means there is no -elevation measurement available for a cell that falls within the -*geographic boundaries* of the DEM. (In the geographic coordinate -system the bounds of the DEM data are rectangular.) A fill also means -there is no data, but is used to make the DEM rectangular in the UTM -coordinate system. \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQPA.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107DQPA.DDF deleted file mode 100644 index 0eafa94d2a8a..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107DQPA.DDF +++ /dev/null @@ -1,32 +0,0 @@ -001482L 1 0600049 22040000210000012921DQPA49500000;&1107DQPA.DDF0100;&DDF RECORD IDENTIFER1600;&Positional AccuracyMODN!RCID!COMT(A,I,A)00295 D 1 00041 310400010080DQPA24680000001DQPA1DEM LEVEL 2 means: Data sets have been processed or smoothed for consistency and edited to remove identifiable systematic errors. An RMSE of half of the contour interval is the maximum permitted, with no errors greater than one contour.00197 D 1 00041 310400010080DQPA14880000002DQPA2ACCURACY: RMSE of the DEM data relative to the file's datum -(x,y,z) is (0, 0, 1); accuracy has been calculated based on a sample -size of 30.00076 D 1 00039 21040001080DQPA2980000003DQPA3CONTOUR INTERVAL: 5.00087 D 1 00039 21040001080DQPA4080000004DQPA4CONTOUR INTERVAL UNITS: METERS.00087 D 1 00039 21040001080DQPA4080000005DQPA5SUSPECT AREAS: No suspect areas.00297 D 1 00041 310400010080DQPA24880000006DQPA6VERTICAL DATUM SHIFT: -0.050000. Adding this value to -the elevation values will convert it to North American Vertical Datum -1988. Value is computed by averaging the shift values for the four -quadrangle corners obtained from program VERTCON.01219 D 1 00043 4104000100080DQPA116880000007DQPA7SUSPECT AREAS: Suspect areas in the DEM result from corresponding -areas on the graphic source that are shown as disturbed surfaces. -They are symbolized by contours that have been overprinted with -photorevised or other surface patterns. Examples of disturbed surfaces -are: lava flows, land slides, open pit mining, construction cut and -fill, and land fill operations. An estimated elevation is supplied for -suspect areas based on the presumed elevation at the time the DEM grid -is generated; however, the true elevation is subject to change without -notice. When an elevation cannot be estimated for a suspect area, the -area is downgraded to a void area and assigned a false negative value --32,767. Grid posts falling in suspect areas are added to the DEM grid -as though they were valid elevations; they are distinguishable from -normal DEM grid posts only by an independent inspection of the graphic -source. For this reason, no percentage value for the total number of -cells in the DEM that are assigned an estimated value. Suspect areas -relate only to graphic sources. Furthermore, no commensurate code -exists for suspects areas in the DLG hypsography category.00296 D 1 00041 310400010080DQPA24780000008DQPA8WATER BODIES: Water body areas are naturally occurring -areas of constant elevation. Oceans or estuaries at mean sea level -are assigned an elevation value of zero. All other water bodies are -assigned their known or an estimated elevation.00586 D 1 00041 310400010080DQPA53780000009DQPA9HORIZONTAL ACCURACY: The horizontal positions of grid posts -in USGS DEM's are located at precise mathematically defined positions -in UTM meters or arc seconds. These grid posts are fixed in position -and can be considered constants for the purpose of determining -accuracy. The only measurable or perceivable errors in the DEM exist -as vertical errors that may be partially attributable to horizontal -error inherent in the source data or to errors in converting -horizontal and vertical components of the source to gridded format. \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107IDEN.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107IDEN.DDF deleted file mode 100644 index c7287149dbf2..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107IDEN.DDF +++ /dev/null @@ -1 +0,0 @@ -002752L 1 0600061 2304000021000000129021IDEN96050CONF681460000;&1107IDEN.DDF0100;&DDF RECORD IDENTIFER1600;&IdentificationMODN!RCID!STID!STVS!DOCU!PRID!PDOC!PRVS!TITL!DAID!DAST!MPDT!DCDT(A,I,11A)1600;&ConformanceFFYN!VGYN!GTYN!RCYN!EXSP!FTLV!CDLV!NGDM(4A,3I,A)00342 D 1 00055 33040001008000IDEN263008CONF0162710000001IDEN1SPATIAL DATA TRANSFER STANDARD1998 JUNE 9ANSI NCITS 320-1998SRPE: SDTS RASTER PROFILE and EXTENSIONSFederal Geographic Data Committee FGDC-STD-002.51998ALANSON, MI-24000LAT:: 45 22 30.0000 N LONG:: -84 45 0.0000 W SCALE:: 24000DEM19982001808NNNY140N \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107IREF.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107IREF.DDF deleted file mode 100644 index d65316534168..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107IREF.DDF +++ /dev/null @@ -1 +0,0 @@ -002072L 1 0600052 3204000002100000102921IREF105500000;&1107IREF.DDF0100;&DDF RECORD IDENTIFER1600;&Internal Spacial ReferenceMODN!RCID!SATP!XLBL!YLBL!HFMT!SFAX!SFAY!XORG!YORG!XHRS!YHRS(A,I,4A,6R)00151 D 1 00041 310400010080IREF10280000001IREF12-TUPLEEastingNorthingR1.000000001.000000000.000000000.0000000030.0000000030.00000000 \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107LDEF.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107LDEF.DDF deleted file mode 100644 index 89e79aed56a2..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107LDEF.DDF +++ /dev/null @@ -1 +0,0 @@ -001962L 1 0600049 22040000210000012921LDEF97500000;&1107LDEF.DDF0100;&DDF RECORD IDENTIFER1600;&Layer DefinitionMODN!RCID!CMNM!LLBL!CODE!NROW!NCOL!SORI!SOCI!RWOO!CLOO!INTR(A,I,3A,6I,A)00090 D 1 00039 21040001080LDEF4380000001LDEF1CEL0ELEVATIONV0253391100CE \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107RSDF.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107RSDF.DDF deleted file mode 100644 index 90c480529f1f..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107RSDF.DDF +++ /dev/null @@ -1 +0,0 @@ -003512L 1 0600085 330400000210000001029021RSDF112050ISID042162SADR031204LYID0312350000;&1107RSDF.DDF0100;&DDF RECORD IDENTIFER1600;&Raster DefinitionMODN!RCID!OBRP!CSCD!DEFI!RWXT!CLXT!SCOR!TIDX!ALTN!FSCN!ASPR!NLAY(A,I,3A,2I,2A,I,A,R,I)1600;&Internal Spatial IDMODN!RCID(A,I)1600;&Spatial AddressX!Y(2R)1600;&Layer IDMODN!RCID(A,I)00177 D 1 00070 2304000108000RSDF52008ISID07060SADR33067LYID071000000001RSDF1G2GIDEF472339TLNOTESS1R1.000000001IREF1666030.000000005040720.00000000LDEF1 \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107SPDM.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107SPDM.DDF deleted file mode 100644 index fb4b65ca1d5d..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107SPDM.DDF +++ /dev/null @@ -1 +0,0 @@ -001992L 1 0600061 2304000021000000129021SPDM50050DMSA381000000;&1107SPDM.DDF0100;&DDF RECORD IDENTIFER1600;&Spatial DomainMODN!RCID!DTYP!DSTP(A,I,2A)1600;&Domain Spatial AddressX!Y(2R)00213 D 1 00052 3204000100800SPDM02108DMSA132290000001SPDM1RINGEXTERNAL666390.919530005026588.57789500666023.795294005040475.32910700675789.821559005040741.40018700676178.562581005026854.66559100 \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107STAT.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107STAT.DDF deleted file mode 100644 index c02d2a36c20a..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107STAT.DDF +++ /dev/null @@ -1 +0,0 @@ -001672L 1 0600049 22040000210000012921STAT68500000;&1107STAT.DDF0100;&DDF RECORD IDENTIFER1600;&Transfer StatisticsMODN!RCID!MNTF!MNRF!NREC!NSAD(A,I,2A,2I)00078 D 1 00039 21040001080STAT3180000001STAT1IdentificationIDEN1000090 D 1 00039 21040001080STAT4380000002STAT2Internal Spatial ReferenceIREF1000090 D 1 00039 21040001080STAT4380000003STAT3External Spatial ReferenceXREF1000086 D 1 00039 21040001080STAT3980000004STAT4Data Dictionary/SchemaDDSH1000086 D 1 00039 21040001080STAT3980000005STAT5Data Dictionary/DomainDDOM4000085 D 1 00039 21040001080STAT3880000006STAT6Data Quality/LineageDQHL13000096 D 1 00039 21040001080STAT4980000007STAT7Data Quality/Positional AccuracyDQPA9000095 D 1 00039 21040001080STAT4880000008STAT8Data Quality/Attribute AccuracyDQAA1000096 D 1 00039 21040001080STAT4980000009STAT9Data Quality/Logical ConsistencyDQLC2000090 D 1 00039 21040001080STAT4380000010STAT10Data Quality/CompletenessDQCG4000082 D 1 00039 21040001080STAT3580000011STAT11Raster DefinitionRSDF1000081 D 1 00039 21040001080STAT3480000012STAT12Layer DefinitionLDEF1000083 D 1 00039 21040001080STAT3680000013STAT13Catalog/DirectoryCATD18000088 D 1 00039 21040001080STAT4180000014STAT14Catalog/Spatial DomainCATS18000091 D 1 00039 21040001080STAT4480000015STAT15Data Dictionary/DefinitionDDDF1000079 D 1 00039 21040001080STAT3280000016STAT16Spatial DomainSPDM1000071 D 1 00039 21040001080STAT2480000017STAT17CellCEL0472000085 D 1 00039 21040001080STAT3880000018STAT18Transfer StatisticsSTAT180 \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/1107XREF.DDF b/autotest/gdrivers/data/STDS_1107834_truncated/1107XREF.DDF deleted file mode 100644 index a2171dfa9367..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/1107XREF.DDF +++ /dev/null @@ -1 +0,0 @@ -002332L 1 0600061 2304000021000000129021XREF72050VATT501220000;&1107XREF.DDF0100;&DDF RECORD IDENTIFER1600;&External Spatial ReferenceMODN!RCID!COMT!RSNM!HDAT!ZONE(A,I,4A)1600;&Vertical AttributesVDAT!VEM!ATLB!AUTH(4A)00282 D 1 00055 33040001008000XREF190008VATT0291980000001XREF1National Geodetic Vertical Datum 1929 Vertical Datum Shift = -0.05; always add to convert from National Geodetic Vertical Datum 1929 to North American Vertical Datum 1988.UTMNAS16NGVDCELLELEVATIONUSGS/NMD \ No newline at end of file diff --git a/autotest/gdrivers/data/STDS_1107834_truncated/README b/autotest/gdrivers/data/STDS_1107834_truncated/README deleted file mode 100644 index ba67fdc7573b..000000000000 --- a/autotest/gdrivers/data/STDS_1107834_truncated/README +++ /dev/null @@ -1,74 +0,0 @@ -This dataset has been truncated to 25 scanlines for GDAL testing purpose. -Original README: - -**************************************************************************** -NOTICE: THESE FILES ARE FOR SOFTWARE TESTING ONLY NOT FOR DISTRIBUTION -**************************************************************************** - -1:24,000-Scale Raster Profile Digital Elevation Model Readme File -Version: 08/2001 (README) - -This directory contains a Spatial Data Transfer Standard (SDTS)-compliant -raster profile transfer, produced by the National Mapping Program of the -U.S. Geological Survey (USGS). - -This transfer corrects potential horizontal errors in SDTS DEMs created -before January 1, 2001. This transfer also corrects a variant in the -profile identifier field. - -If you have questions or comments, please send e-mail to sdts@usgs.gov -or contact the USGS at: - U.S. Geological Survey - SDTS Task Force - 1400 Independence Road - Rolla, MO 65401 - -PURPOSE OF TRANSFER: - The mission of the USGS National Mapping Program is to meet the - Nation's need for basic geospatial data, ensuring access to and - advancing the application of these data and other related earth - science information for users worldwide. These data are provided - in SDTS format as the result of a Federal mandate. - - The digital elevation model (DEM) is the USGS National Mapping - Program's response to the Nation's need for accurate and - consistent geospatial digital elevation data in raster format. - -STANDARD AUTHORITY: - American National Standards Institute (ANSI): - Parts 1-3: ANSI NCITS 320-1998 The Spatial Data Transfer Standard - Federal Geographic Data Committee: - FGDC-STD-002.5-1999, February 1999 - Part 5: SDTS Raster Profile (RPE) with Basic Image Interchange - Format (BIIF). - -ISO 8211 CONFORMANCE: - All files with extension *.DDF are in the ISO 8211 file transfer - format. All SDTS spatial addresses are expressed in two 32-bit - binary subfields defined by the ISO 8211. Files are Level 2 of - ISO 8211. - -CATALOG DIRECTORY MODULE xxxxCATD.DDF: - Each transfer includes this catalog directory module that - contains a listing of every SDTS ISO 8211 file included in the - transfer (xxxx indicates a four-character transfer base that - is common to all files in a transfer). - -IDENTIFICATION MODULE xxxxIDEN.DDF: - This module contains information that describes the overall - characteristics of the data in a transfer. - -REFERENCES: - "The Spatial Data Transfer Standard Mapping of the USGS Digital - Elevation Model" describes SDTS transfers of DEM data, including - detailed information on each module. The file can be downloaded - from the SDTS FTP site: - ftp://sdts.er.usgs.gov/pub/sdts/datasets/raster/dem/ - -Additional information can be found on the SDTS Web site: - http://mcmcweb.er.usgs.gov/sdts - - - - - diff --git a/autotest/gdrivers/data/adrg/subdataset/TRANSH01.THF b/autotest/gdrivers/data/adrg/subdataset/TRANSH01.THF new file mode 100644 index 000000000000..4712972d3115 --- /dev/null +++ b/autotest/gdrivers/data/adrg/subdataset/TRANSH01.THF @@ -0,0 +1 @@ +009902L 0600135 340300003000000010420030VDR1180072FDR1020190QSR0740292QUV0670366CPS0990433CPT0570532SPR1700589BDF0500759VFF0460809 TRANSMITTAL_HEADER_FILE1000;&RECORD_ID_FIELDRTY!RID(A(3),A(2))1600;&TRANSMITTAL_HEADER_FIELDMSD!VOO!ADR!NOV!SQN!NOF!URF!END!DAT(A(1),A(200),A(1),I(1),I(1),I(3),A(16),I(3),A(12))1600;&DATA_SET_DESCRIPTION_FIELDNAM!STR!PRT!SWO!SWA!NEO!NEA(A(8),I(1),A(4),A(11),A(10),A(11),A(10))1000;&SECURITY_AND_RELEASE_FIELDQSS!QOD!DAT!QLE(A(1),A(1),A(12),A(200))1000;&VOLUME_UP_TO_DATENESS_FIELDSRC!DAT!SPA(A(100),A(12),A(20))1600;&TEST_PATCH_IDENTIFIER_FIELDPNM!DWV!REF!PUR!PIR!PIG!PIB(A(7),I(6),R(5),R(5),I(3),I(3),I(3))1600;&TEST_PATCH_INFORMATION_FIELDSTR!SCR(I(1),A(100))1600;&DATA_SET_PARAMETERS_FIELDNUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF(I(6),I(6),I(6),I(6),I(3),I(3),I(6),I(6),I(1),I(1),I(1),I(1),I(1),A(12),A(1))2600;&BAND_ID_FIELD*BID!WS1!WS2(A(5),I(5),I(5))1000;&TRANSMITTAL_FILENAMES_FIELDVFF(A(51))00356 D 00055 34030010060000VDR2390006FDR0560245VTH01 11001 001017,19940101XXXXXX013ADRG-0000000.50+465959.48+0010000.52+480000.5000409 D 00055 34030010060000QSR2150006QUV1330221LCF01UN MILITARY SPECIFICATION ARC DIGITIZED RASTER GRAPHICS (ADRG) 022,19900222MIL-A-89007 00323 D 00075 34030010060000CPS0330006CPT1020039SPR0610141BDF0460202TPA01Black 0000000003 00000000051100051100000000400400012800012801008TESTPA01.CPHNRed 0000000000Green0000000000Blue 000000000000417 D 00151 9903001000000006000000000VFF000000052000000006VFF000000052000000058VFF000000052000000110VFF000000052000000162VFF000000052000000214TFN01TRANSH01.THF TESTPA01.CPH XXXXXX01.GEN XXXXXX01.IMG XXXXXX02.IMG  \ No newline at end of file diff --git a/autotest/gdrivers/data/adrg/subdataset/XXXXXX01.GEN b/autotest/gdrivers/data/adrg/subdataset/XXXXXX01.GEN new file mode 100644 index 000000000000..ff9f53d030aa --- /dev/null +++ b/autotest/gdrivers/data/adrg/subdataset/XXXXXX01.GEN @@ -0,0 +1 @@ +008182L 0600115 340300003100000010420031DRF0570073DSI0440130OVI0820174GEN2290256SPR1290485BDF0500614TIM0390664 GENERAL_INFORMATION_FILE1000;&RECORD_ID_FIELDRTY!RID(A(3),A(2))1100;&DATA_SET_DESCRIPTION_FIELDNSH!NSV!NOZ!NOS(4I(2))1000;&DATA_SET-ID_FIELDPRT!NAM(A(4),A(8))1600;&OVERVIEW_INFORMATION_FIELDSTR!ARV!BRV!LSO!PSO(I(1),I(8),I(8),A(11),A(10))1600;&GENERAL_INFORMATION_FIELDSTR!LOD!LAD!UNIloa!SWO!SWA!NWO!NWA!NEO!NEA!SEO!SEA!SCA!ZNA!PSP!IMR!ARV!BRV!LSO!PSO!TXT(I(1),2R(6),I(3),A(11),A(10),A(11),A(10),A(11),A(10),A(11),A(10),I(9),I(2),R(5),A(1),2I(8),A(11),A(10),A(64))1600;&DATA_SET_PARAMETERS_FIELDNUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF(4I(6),2I(3),2I(6),5I(1),A(12),A(1))2600;&BAND_ID_FIELD*BID!WS1!WS2(A(5),I(5),I(5))2100;&TILE_INDEX_MAP_FIELD*TSI(I(5))00060 D 00045 34030010060000DRF0090006DSS010101010100322 D 00151 9903001000000006000000000DSI000000013000000006OVI000000039000000019SPR000000061000000058BDF000000046000000119TIM000000006000000165OVV01ADRGXXXXXX0130004606700046067-0000000.50+480000.5000000000012700012700000000100100012800012801008XXXXXX01.IMGYRed 0000000000Green0000000000Blue 00000000000000100502 D 00151 9903001000000006000000000DSI000000013000000006GEN000000219000000019SPR000000061000000238BDF000000046000000299TIM000000006000000345GIN01ADRGXXXXXX0130099.90099.9016-0000000.50+465959.48-0000000.50+480000.50+0010000.52+480000.50+0010000.52+465959.4800869134101100.0N0004606700046067-0000000.50+480000.50 00000000012700012700000000100100012800012801008XXXXXX01.IMGYRed 0000000000Green0000000000Blue 00000000000000100502 D 00151 9903001000000006000000000DSI000000013000000006GEN000000219000000019SPR000000061000000238BDF000000046000000299TIM000000006000000345GIN01ADRGXXXXXX0230099.90099.9016-0000000.50+465959.48-0000000.50+480000.50+0010000.52+480000.50+0010000.52+465959.4800869134101100.0N0004606700046067-0000000.50+480000.50 00000000012700012700000000100100012800012801008XXXXXX02.IMGYRed 0000000000Green0000000000Blue 000000000000001 \ No newline at end of file diff --git a/autotest/gdrivers/data/adrg/subdataset/XXXXXX01.IMG b/autotest/gdrivers/data/adrg/subdataset/XXXXXX01.IMG new file mode 100644 index 000000000000..0955a8b16c1a --- /dev/null +++ b/autotest/gdrivers/data/adrg/subdataset/XXXXXX01.IMG @@ -0,0 +1,19 @@ +001852L 0600065 340300002000000010420020PAD0280062SCN0300090 GEO_DATA_FILE1000;&RECORD_ID_FIELDRTY!RID(A(3),A(2))1000;&PADDING_FIELDPAD(A)2000;&PIXEL_FIELD*PIX(A(1))51015 D 00088 9903001000000006000000000PAD000001769000000006SCN000049152000001775IMG01 ����������������������������������������������������������������������������������������������������������������������������~}|���������������������������������������������������������������������������������������������������������������������������~}|{��������������������������������������������������������������������������������������������������������������������������~}||z�������������������������������������������������������������������������������������������������������������������������~}||{y�������������������������������������������������������������������������������������������������������������������������~}}{zyy�����������������������������������������������������������������������������������������������������������������������~~||{zyx����������������������������������������������������������������������������������������������������������������������}||{zyxw���������������������������������������������������������������������������������������������������������������������~~}|{zyxwv��������������������������������������������������������������������������������������������������������������������~}}|{zyxwvu��������������������������������������������������������������������������������������������������������������������~~}{{zyxwwuu�������������������������������������������������������������������������������������������������������������������~~||{zyxwwvut������������������������������������������������������������������������������������������������������������������~}}|{{yxxwvuts�����������������������������������������������������������������������������������������������������������������~}|{zyxxwuttsr���������������������������������������������������������������������������������������������������������������~}||{yywvuutsrq���������������������������������������������������������������������������������������������������������������~}|{zzyxwvutsrqq��������������������������������������������������������������������������������������������������������������~}||{zxxwvutssqqo�������������������������������������������������������������������������������������������������������������~}|{{yyxwvuttrqppo������������������������������������������������������������������������������������������������������������~}}{zyyxwvutsrrpoon������������������������������������������������������������������������������������������������������������}}|{zyxwwuttrrpponm����������������������������������������������������������������������������������������������������������~}||{zyxwwuttrqqponml���������������������������������������������������������������������������������������������������������}|{{yyxwvvttrrqppomll���������������������������������������������������������������������������������������������������������}}|{zyxxvvutsrqponmmkk��������������������������������������������������������������������������������������������������������~~}|{zyxxwvttsrqpoomlkjj������������������������������������������������������������������������������������������������������~}|{{yxwwvutsrqqpnnmkkji�����������������������������������������������������������������������������������������������������~}||zzyxvuutsrqqoonmlkjih����������������������������������������������������������������������������������������������������}}|{{yxxwvutsrqponnllkjihg����������������������������������������������������������������������������������������������������~}}{zyxwwuuttrqqponmlkjiigg���������������������������������������������������������������������������������������������������~}|{zzywwvuusrrqoonmlkjiigge��������������������������������������������������������������������������������������������������~~}{zzxxwvutssqqpnmmllkihgffe�������������������������������������������������������������������������������������������������}||{zxxwvuttsrqoonmlkjjhhgfed������������������������������������������������������������������������������������������������~}}|{zyxwvuutrrqponmlkkjihgfeec�����������������������������������������������������������������������������������������������~}||zzyxwvutssrqponmlkjjihgfeddb����������������������������������������������������������������������������������������������}|{{zyxwwvttsrqponmlljiihggeeccb����������������������������������������������������������������������������������������������~~}{{zyxwvvtsrrqpponlljjihgfedcca`���������������������������������������������������������������������������������������������~~}|{zzywvvutsrqpoonllkiihgfedccb``�������������������������������������������������������������������������������������������~}|{zyxxwuussrqpoonlljjihgfeeccba`_�������������������������ؾ��������������������������������������躔������������ď�������������ɗzxw��utss����ml�����Ɗfddcb��_^���������������������������Ʒ��������ˮ������������������������������������������񙅄������������xww��tsr����nl��������ddbba��^]�������������������������������������쭬���������������������������뒑�����髏����퉃���������xvv��sr����nll��Ҁjs��dcbaa��]]����������������������������ڴ��������������������������������������������퐊������������}}{zzxxwvu��r����nmlk��shgfeccbba`��]\����������������������������ﳲ�������ڪ�������������������������������������������������}|{zzyxwvut������nmlkj���rfddcbaa`_��\[�������������������������������������������������������������������ڐ��������������������|{{yyxwvvtt�����nmlkjj�����˝ea`__^��[Z����������������������������������ᬫ��ɨ�������������������������皎������������������~|{yyxwwuuts����mmkjiih�������o`_^]��ZY���������������������������������������짦���������������������������������������������zyxxwvuutsq�����kjjhhgfef}����^^]]��ZX���������������������������������������������������������������������������������}���zyxwvvttsqq��o����iihgfeddbav��^]\[��YW����������������������������ׯ����������ڤ�������������������������茌����닅�������}|���xxwvttsrqp��mm����hgffedcb`k��^][[ZYWW���������������������������������������������������������������������������祈�����}|~���xy���qqo��lkk����feޤ{fe���]\ZYYXWV�������������׻�����������������穩������ơ���������������������������������������}{{{����������poo��lkji����d���������\ZYY��VU������������Ż�����������ѳ�����ƪ�������졠�������������������������ڇ�����������}|{{yx{������ŏonm��kjiig����������ʁ\[ZYX��VT�������������������������������������������������������������������������������~}|{zzywvvuttrqppnnmlkjihggeddcbba`^]\\[ZYXXVUTS�����������������������������������������������������������������������������~}|{zzywwvutsrrqonmmlkjiigffdccba`__]]\[ZYXXVUUTS�����������������������������������������������������������������������������~}||{yyxvuutsrrqoommlkjiihffedcba``_^\\[ZYXWWUTTSR����������������������������������������������������������������������������~~|{{zyxwvutsrqpponmlkjiiggfedccb``_^]\[ZYXWWVTTSRQ���������������������������������������������������������������������������~}}{zzywwvutsrrqponmlkjjhhgfedcbb``_^]\[ZZXXVVUTSRQP��������������������������������������������������������������������������~}|{zyyxwwuussrqpnnmlkkjihgeedcbb``^^]\[ZYXXVVUTSRRPO��������������������������������������������������������������������������~}||{zxxwvutsrrqponmllkiiggfeecbb`__^]\[ZYYWVVUTSSRPOO������������������������������������������������������������������������~~}|{zyxwwuusrrqponmlljjiggfedccaa_^^]\[ZZYXWUUTTRQQPOM�����������������������������������������������������������������������}}|zzyyxvuussqqppnnmlkjihgfeecbba`_^]\[ZZYXWVUUSRQPPONM����������������������������������������������������������������������}}|{zyxwvuutsrqponmmkkjihgffedcb```^]\\[YXXWVUTSRQPPONML����������������������������������������������������������������������~~||{zyywwuttsrqpoonmkjiihgfeeccba``_]\\[ZXXWVUTSSRQPONMML���������������������������������������������������������������������~}|{zyxxvvutsrqqpnmmlkjihgfeddcba`_^]][[YYXWVUUSRQQPONMLLK�������������������������������������������������������������������~~}|{zyxwvuutsrrqponmkkjihhffedcba`_^]\\ZZYXWVVTTRRQPONNLKJI������������������������������������������������������������������~}||zyxxwvutsrqppnnmkkkiihgeeccbb``^^\\[YYXXVVTSRRQPONMMKJJI�����������������������������������������������������������������~}|{{yxxwvutssqqonnmlljiiggeddcbba`^]]\[ZYXWVUTSSRQPPNNMKJJIH�����������������������������������������������������������������~}||zzxxwvutssqpponmlljihggfedcbb`_^^]\[[ZXXWUTSSRQPOOMLKJJIHG�����������������������������������������������������������������~||{zyxwvuttsqqponmlkjihhffedccb`__]]\[ZYYXVUUTSRQPOONMLKIIHGF����������������������������������������������������������������~~}{zzyxwvuusrrpponmlkjjihffeddbba`_^]\[ZYXXWUUTSRQPONNLLKJIHGGF��������������������������������������������������������������~~||{yyxwvuutsrqponnmkjjiggfeecbba`^^]\\ZZYWWVUTSSQQOONMLKJIHGFFE�������������������������������������������������������������~}}{{yyxxvvutsrqpoomllkjhhgfeedcba__^]\[ZYYXVUUTSRQQOONMLKJIHGFFED�������������������������������������������������������������~}}{{zyywvuutsrqppnmmlkiihgffecbba`_^]\\ZYYWWVUTSSQPPOMMLKKIIHFFECC�����������������������������������������������������������~}}{{zyxwvvussrqponmllkjihgfeddcb``_^]\[ZZYXWVUTSSQPPONMLKJJIHGFEDCB����������������������������������������������������������~~||{zzyxvvttsrqppomlljjihgfeedcba`_^^\\ZZYXWVUTSSRQPONNLKJJHHGFEDCBA���������������������������������������������������������~}|{zyxxvvussrqpoonmkkjihhgeddcba`_^]][[ZXXWVUTTRQQPONMMKKJIGGFEECBA@��������������������������������������������������������~}|{zzxwvvttsrqponmlljjjigffedcba`_^]]\[ZYXWVUUTRRQPONNLKJJHHGFEDCBAA@��������������������������������������������������������~}|{{yywwuttsrqqponmlkjiihffddcba`_^^]\[ZXXWWUTTSQQPONMLKJJIHGGEDCBA@@?�������������������������������������������������������~}}|zzyxwvuttrqqpnnmlkjjhggfedcbb`__^]\ZZYXWWVUTSRQPONMLKKJIHGGEECCBA@?>������������������������������������������������������~}|{{zyxwvuttsqpoommlkjiiggfedcca`__]]\[ZYXWWUTTSRQPONNLKJIIHHFEDDCBA@?>>�����������������������������������������������������~~||{yyxwvuussqqponmmkjjhggfedcbb`__^]\[ZYYWWVUTSRRPOOMLKKJIHGFFDCBBA@?>><����������������������������������������������������~~|{zzxxwvutssqqponmlkkihhgfeddcaa`^]]\[[ZXWVVUTSRQPOONMLKJIHHFEDDCBA@?>=<<���������������������������������������������������~~||{zyxwwuutrrqponnlkjjhhgfedcba``^^]\[[ZYWWVUTSRQQOONMLKJIIGFEECBBA@??=<<:���������������������������������������������������~}}{{zyxxvuussqqponmlkjjhhgfedccba`_^]\\ZZXXWUUTTRQPPONLLKJIHHGFEDCBA@@>>=<;:�������������������������������������������������}||{zzxwwutssrqponmlljiihgfedccb``_^]][ZYYXVVUUSRRQPONMLKJIIHGFEDCBA@?>=<<;:9������������������������������������������������~}}|{zyywvvutsrqponnmljjhhhffedbba`__]\[[YYXWVUTSSQPPONMLKKJIGGFEDCBA@??>=<;:98������������������������������������������������~||{zyxwwuutsrqppnmlkkiihgffdccba`_^^\[ZYYXWVUTTSQQONNMLKJJHHGFEDCBBA@>=<<;:997�����������������������������������������������~}}|{zyxwvvutsrqpponmkkjihhgfedcba`_^]][ZYYXWVUTSRQPOONMLKKIIHGFEDCBA@@?>=<<:9977����������������������������������������������~}||zyxxwvutsrqqonnmlkjihgfeddcbaa_^]]\[ZYXXVUTSSQPPOOMLKJJHHGFEECBAA??>=<;::9866���������������������������������������������~}|{zyxxvvutsrqpponmlkjiihgeeccbb`_^]\\[ZYXWVVTTRRQPOOMMLJIIHGFEDCCBA??>==<;:88765��������������������������������������������~}|{zzxwwvutsrqqponmlkkiiggeedcba`__^][[ZYXWVVUSSRQPONMMLJJIHGFFDCCBA??>=<;:9877654�������������������������������������������~}}|zzxwvvuttrrppnnmmkjihhgfddcbaa`^^\[[ZYXXVVTTSRQPONMMLKJIHGFEDDCB@@?>==<::9876543������������������������������������������~}|{{yyxwvutssqpoonmlkkjiggfedcbb``_^][[ZZYWWUTTSRQPONMMKKJIIGGFDDCB@??>>=<::88765433�����������������������������������������~}}{{zyxwvutssqqponmlljihhgfedccb`_^^]\[ZYYWVVUTSRQQONMMLKJIHGFEDDCB@@??=<;::977654432����������������������������������������~}|{{yyxwwvttrrqpoomlljjhhffeecba``_^]\[[YYXWVTTSRRPOOMLLKJIHGGEDDCBA@??>=;;99876644321���������������������������������������}||{zyxwvutssqqpoonlljjihgfedcbb``_^]\[ZZYXWVUTSSQQOONLLKJIHHFEDDCBB@@?>=<:998776443210��������������������������������������~}}{{zyxwvvusrrqpoomlkkjhhgfeeccba`_^]\\ZZXXWVUTTRRQPONMLKJIHHFFEDCBA@??><<::98866543210/��������������������������������������~}}|{zyxwvutssrqpoonmlkjihgfeddcaa`_^]][ZYYXWVUTSRRQPONMLLJIHHFFEDCBA@@?>=<;:98765543210//������������������������������������~}|{zyywwvttsrqppnnmlkjihgfeddcaa`__]\[ZZYWWWUTSRQPPONMLKJIIHGFEDCBAA?>><<;:98865543210//.������������������������������������~}|{zzxxwvttsrrqpnmmlkjiigffecbba`_^]]\[ZYXWVVTTRRQPONMMKJIHGGFEDCBBA?>>=<<:99876533210/.--�����������������������������������~~}|{zyywvvutsrqppomllkjjhgfeedcba`_^^\\[ZYXWWUUSSRQPONMMKJJHHGFEDCCBA??>=<;;99876543210/.--,���������������������������������}}||zyywwvutsrqpponmlkjihgffeccba`__]\\[ZYXWVVUTSRPPPOMMKKJIHGFEDCBBA@?>=<;;:8765544220/..-,+���������������������������������~}||{yywwvutsrrqponmlkjihgfeeccba``^]\\ZZYXWVVTTRQQPONNMLKJIHGFEEDBAA@?>=<;;98875554311/..-,,*��������������������������������~}||{yxxwvutsrrqponmlkjihhgfedcba`_^^]\[ZYYXWUUTSRQPONMLLKJIHGGEEDCBA@?>=<<::98765533110/.-,+**�������������������������������~}|{{yyxvvutsrqppnmmlkjjhgfeedcbb`_^^]\[ZZXXWUTSSRQQPNNMKKJIHHGEEDCBA@?>=<<:998665433110/.-,,*)(������������������������������~}}{{zxxwvuutrrpponmmkkiihgeedccba`_]]\[ZYXWWVTTSRQPOONLKKJIHGFFECCBA@?>><<;:98765543210/.-,,+)((�����������������������������}||{zyxwvutssrqponmmkkjihgfeeccaa_^^]\\ZZYXWVUTSRQPOOMLLKJIHHFEDCCBA@?>><<;:98765542110/.-,,+*)('�����������������������������~}|{yyxwvuutsrqponnlkjiihgffddbba`_^]\[ZYXWWVUTSRRPOONLLKJIIHFEEDCBAA?>==<;999776543210//--,+*(('&���������������������������~}|{zyxxvuttrrqpoomllkjhhgfedccaa__^]\[[ZYWWVUTSRQQOOMMLKJIHHFFECCBAA??><<;:987654432100.--,+*(('&%���������������������������~||{zyxwvuutsrqpoonmlkjhhgfedcbba`_^]\[ZZXXWVUTTSQQPNNMLKJIHGGFEDCBAA?>=<<;:98765542220//.,,**)('&&%�������������������������~~}|{zyyxwvttsrqppnmmlkiiigfeedcba`__^\[[ZYXWVUTSRRPONNMLKJIHHGFDDCBA@?>>=<;:998665432110/-,,+*)((&&%$�������������������������~~}{{zyxwwuttrrqpponmlkjihgfeedcba`__]\[[ZYXWVUTSSRPOONMLLJJHHGFEDCBBA??><;<:98776543210//--,**)(''&$$#�����������������������~}|{zyxwwvttsrqpoommlkjihhfeddcba``_]\\[ZXXWVVTTRQQPONMLKKJIHGFEDCBAA??>=<<:99876443221/.-,,**)('&%$$#"�����������������������~}|{zyywvvutsrrqoommlkjihhffedcba`_^]\\ZZXXWVVUTSRQPONMLKKJIHGFEDCCBA@>>=<<:99876543311/..-,+*))''%$$#"!����������������������~}}{zyxxwvutsrrqpnnmlkjiiggfddbba`_^]]\[ZYXWVVTTSRQPPNMMLKJIHGFEDCBA@@?>=<;;:88765433200/.-,+**((&%%$#"!!��������������������~~}{zzxwwvuussqpponmlkjjhgffddcba`_^]][[ZYXXVUTTSRQPONNMKJJIHGFFDDBAA@?>=<<;:98765533210..-,+**(('&%###"!��������������������~}}{{zyxwvvutrqqoonmlkjihhgeedcba`_^^]\[ZYXWWVUSSRQPPONMLKJIHGGEECCAA@?>><;::9776544221//.-,+*))(&&$$#"!!�������������������~}}|{zyxwvuttsqpponmmkkiigffedcbba__^]\\ZYXWWUUSSSQPOONMLKJIHGFEDDCBAA@>><<;:88765533200/.--++*((&&%$$#! �������������������~}{{zywwvvussrqponnmkkjihgfeedcaa__^]\[ZYYWVVTTTRQPOOMMLKJIHHFEDDCBAA??=<<;:98765532210/.-,+**((&&%%#""! �����������������~~}{{zyxxwvusrrqponnmlkiihffeddcb``^^]\[ZZXXWVUTSSQPOONMLKKIHGFEEDCBA@??==<;:99866543210/.-,,+))('&%$##!!�����������������~}}|{zyxwwvttrrqponmlljjihgfedcbaa`_^]\[[YXXWVUTTRRQONNMLKJIHGFFDDCBBA?>><<;:99765543200/.--,**)('&%$##"! ���������������~}||{zyxwwvutrrqponmlkjjihgffddbaa`_^]\[[ZYXWVUTTRRQOOMMLLKIIHFFEDDBA@@?==<;:997654422100/-,++*)(('%$##"! ��������������~}|{zyxxvvutsrqpoonllkjihggfecbba`_^]][ZZYXWVVUSSRQPONMLLKIIGGFEDDCBA??>=<;::87665432100.--++*)('&%$$"" ��������������~~}|{{yxxwuutsrqqoonmljjihggfddcba`_^^\[ZYYXWVVUTSQQPONMLKKIHHGFEEDCAA@>>=<;::8776432210/.--,+))('&%%$#"! �������������}}||zzxwvuutsrqpoonlkkjihgffecbba`__]][[ZYXWWVTTRRQPOOMLLJJIGGFFDCBBA@?>=<;::88765432100..-++*)('&%$$#"! ������������~}|{zzxwwvutssqqpnnmlkjihggfeccba`_^^]\[ZYXWVUUTRRPOONMLKJJIHGFFDCBBA@?>=<;:988765433110/.-,+*)('&%%$#"" �����������~}|{zyyxwuutsrrpponmlkjjhhffedcba``_^\[[ZYXWVVTTRQQPONNLLJJIHGFEEDBBA@?>=<;;:88655432210/.-,+*)('&&%$#"! ����������~}|{zyxwuvttrqqpnmmlkjjhggfedcba`_^^]\[ZYYXVUUTRRQPPNMLKJIIHHFFEDBAA@?>><<::8876543321//.-,+*))''%%$#"!! ���������~}||{zywwvvtsrqqoonmlkjiihgfedcba``_]]\[ZYXWWVTTSQQPPNMMKKIIHGFEECCAA@?>=<;:988765433200/--,+*)(''&%$#"! ��������~~||zzyxwvutssqqponnllkjhhgfedcbaa__^]\[[YXXWUTTSRQPOONMLKJIHGFEECCBA@?>><<:998765432210/.--+*)(('&%$##! �������~}}|zyyxxvuutsrqponmlkjjigffeddcb`_^]]\[[YYWVVTTSRRPONNMKJJIHHFEECCBA@?>><<;:98765533210/.-,,+*(('&%$##!! ����������������������������������������������������������������������������������������������������������������������������~}|���������������������������������������������������������������������������������������������������������������������������~}}{��������������������������������������������������������������������������������������������������������������������������~}|{z�������������������������������������������������������������������������������������������������������������������������}|{{z������������������������������������������������������������������������������������������������������������������������~}|{zzy�����������������������������������������������������������������������������������������������������������������������~}}|{zyx����������������������������������������������������������������������������������������������������������������������~}}|{zyxw���������������������������������������������������������������������������������������������������������������������~}}|{zyywv���������������������������������������������������������������������������������������������������������������������}}|{zyxwvv��������������������������������������������������������������������������������������������������������������������~}{{zyxwvuu������������������������������������������������������������������������������������������������������������������~}|{zyxxwvtt�����������������������������������������������������������������������������������������������������������������~}|{zyxwwvuss�����������������������������������������������������������������������������������������������������������������~}|{zyywvvutsr���������������������������������������������������������������������������������������������������������������~}||zyyxwvutsrr��������������������������������������������������������������������������������������������������������������~~}|{{yxxwvutssrq��������������������������������������������������������������������������������������������������������������~}|{zzxxwvuussqqp�������������������������������������������������������������������������������������������������������������}|{zzxxwvutssqqoo������������������������������������������������������������������������������������������������������������~~||{zyxwvuutrrqpnn�����������������������������������������������������������������������������������������������������������~}|{{zyxwvuttrrqponm�����������������������������������������������������������������������������������������������������������~}}|{zyxwvvttsqpponml���������������������������������������������������������������������������������������������������������~~}|{zyxwvutssrqponmmk���������������������������������������������������������������������������������������������������������~~}|{zyyxwvtsrrqppnmmlk�������������������������������������������������������������������������������������������������������~}|{zyywwuutsrqponmmlkj������������������������������������������������������������������������������������������������������~}|{{yxxvuutsrqppnmllkji������������������������������������������������������������������������������������������������������~}|{zzyxvuutsrqqpnmlkkjjh�����������������������������������������������������������������������������������������������������~}|{{zyxvvutsrrqpnnmlkjihg����������������������������������������������������������������������������������������������������~~|{zzyxwvutssrqponmlkjihgf���������������������������������������������������������������������������������������������������~}|{zzxxvvutsrqpoonmlkjihggf��������������������������������������������������������������������������������������������������~}|{{yxxwvuttrqqoonmlkjiiggfe�������������������������������������������������������������������������������������������������}||{zyxwvuutsrqoonmmkjihggeed�������������������������������������������������������������������������������������������������}}|zzyxwvvtsrqqponmlljiiggfedc�����������������������������������������������������������������������������������������������~~}{{zyxwvvussrqpoommkjiiggfeecc�����������������������������������������������������������������������������������������������}|{{zyxwwvutsqqpoomlkkiiggffdcba���������������������������������������������������������������������������������������������~}|{zyxwvutssrqpoonlljjihgfeeccba��������������������������������������������������������������������������������������������~~}|{zyxxvuttsrqqonnlljjihgffedbba`��������������������������������������������������������������������������������������������~}|{zyxwvvussrqppnnllkjihgfedccba`_������s2 %T�����4j��������� ��������������������� a��������FC�������P$ 3`zyxutsrb :mmP 'Oeedca__���ΰ�����������rq��������������������]�����wp����tyxwtsr` ?mlJedcba^]������Ľ�s+��������t������))�����������������������:�����d��b��KmzwfIxwuss^ Enml We_Ddcbb`^]���t ������������������![�����'#����������������������������P������K��Ns}||zyxwvvur] Jnmlkaggfeccbb`_]\���1�������������������{'����LjkK���������������������������"\������V ��!P}|{{zxxwvut[Nnmllj 5^fedcbaa`^\[������������������ ���� �� ����������������������91���� +~������w +�� s|{{zyxwvuutRnmlkkj@"?aa`_^^[Z���������������������m@��Ki������������������ ��������������{|zzyxwvutss +\mlljjihMW__^]ZY��� ������������������ ���&����%������������������d����� +}������v +~ q{zyxwvuussrM YljihhgfedS; "_^]\ ZX���.�����������������y'�����������������������cq����!Y������U~} NyyxwvvttsqqnHVihhgfeedcbS^]][XX���l*����������������Y��GE��������������������T����L�����{H~}JoxwwuutsrqpmmDRggffddbb`Y]\[ZYXXW��ǻ,����r��������q��� +������ ���������������������R����`}|_y}|xGitpbFqpomkj@Pfe:S^_M][ZZYXWV���šp�������h0������.c��������������h{���oj}|{zlponlkji<Ke@\[ZYVU����÷d' K������3h����"q������m ���������������.+����{@>u}|{zyxuJ +/Woomkjihg8HP+ +H[[ZYXUU�������������������������������������������������������������������������������~}|{zyywwvutsrqppnmmlkjjhgffddcba`__]\[[ZYXWVUUS������������������������������������������������������������������������������~}||zyywwvuttrqqonnmlkjihhgfeccbba_^^][[ZYXWVUTSS�����������������������������������������������������������������������������~}|{{zxxwvutsrrqonnmlljjigffedcba`__^\\[ZYXXVVUTSQ����������������������������������������������������������������������������~}|{zzyxwvutsrrqponmlkjiigffedcbb`__]]\[ZYXWVVUSSRR���������������������������������������������������������������������������~}}{zzyxwvvttsrqponmlkkiihgeeddcaa`_]]\[ZYYXVVUTSRQP���������������������������������������������������������������������������}|{{zxxwvutsrqpponmlkjiihgeedcbaa`_^]\[[YXWWUUTSRQPO�������������������������������������������������������������������������~}|{zyxwvutsrrqponmlkkiiggfedccba__]]\[ZZYWWVUTSRRPOO������������������������������������������������������������������������~}}|{zyxxvuttsrqponmmlkiihgfeecbba`_^^\[ZYXXWVUTSRQQPOM�����������������������������������������������������������������������~||{zyxwvvutsrqponmllkjhhgfedccb``_^]\[ZZYWWVUTSRQQOONM�����������������������������������������������������������������������~~||{zzxwvvttrrqppnnmlkiihggeddbba`_^]\[[YXXWVVUSRRPPONML���������������������������������������������������������������������~}|{zyywwuussrqponnllkjihgffeccba`_^]\[[ZYXWVVUTSRPPONMLK���������������������������������������������������������������������~~}|{zyxxvvutsrrponmmlkjihgffedcba`_^^\\[ZYXWVVUSSRPPONMLLJ�������������������������������������������������������������������~}|{zyxxwuutssqpoonmlkjihgfedccba`_^^\\[ZYXWVUUTSRPOONMLKKJ������������������������������������������������������������������~~}||zyxwwvutsrqppomllkjiigffecbbb`__]][[ZYXWVVTTSRQPONMLLJJH�����������������������������������������������������������������~}||zyxwwvutssqpponmlkjihggfedcca``^]\\[ZYXWWUTTSQQQONNLKKIIH�����������������������������������������������������������������~}}{{yyxwvutsrrqonnmlljjiggfedcbb``_^]\[ZYXXWVUSSRQPONNMLKJIHG����������������������������������������������������������������~}}{{zxxwvvttsqqpnnmlkkjihgeedcbba__^]\[ZYYWVVUTSRQPPNMLLKJIHGG���������������������������������������������������������������~}}{zzyxwvuttrqqpoomlkkiihffedccb``_^]\\[ZYWVVUTSRQPPONMLKJIHHFE��������������������������������������������������������������}}|{zyxwvuutsrpoonmlkkiiggfedcbba__^]\\ZYXXWVUTSRQPONNMLKJIHGFFE�������������������������������������������������������������~}}|{zyxwvuutsrpponmllkjihgfeecbb`__^]][ZZXXWVUTSRRQPNMMLKJJIHFFED������������������������������������������������������������~~}{{zyxwwuutsrqpoonlkkjhhgfeedbba`_^]\[ZZXWWVUTSRQQOONMLKJIHGFFEDC�����������������������������������������������������������~~}|{zyxwwuttsrqqoonlljjihgfeedcba`_^^\[[ZYXWVVUSSRQONNMLKJJIHFEEDDB����������������������������������������������������������}}|{zyxwwvussrqpoommkkjihggfeccba`_^]\\ZZYXWVUTSRRQPONMLKJIIHGFEDCBA����������������������������������������������������������}}|{{yxxwuttsrqpoommkkjihgffedca``_^]\\[YYXWVUTSSRPPONNLLJIIHGFEDDCB@���������������������������������������������������������~}|{zzxxvuttsrqqoommljjihhgfecbba`_^]\\[YXXWVUUTRRQPOOMLKKJHHFFFDCBB@@��������������������������������������������������������~~}|{zyywwvttsrrponmmlkjjhhgeedbba`_^]\\ZZYXWVUTTSRQPONMMKKJIHGFFDCBBA@?�������������������������������������������������������~}|{zzyxvuuusrqqoonllkjihggfedcba``^]]\[ZYYWVVTSSRQPOONMKKJIHGGEDCCBA@?>�����������������������������������������������������~}|{zyxxwvuussqqponmlkjiihgfedcba``^]]\[ZYYXWUUTSRQPPONMLKJIHGFEEDBBA??>=�����������������������������������������������������~}}{zzyxwvuutrrqpnmmlkjjihfeedcbb``^^]\[ZZXWWUUTSRQPOONMLJJIHGFEDDCBA@?>==����������������������������������������������������~}|{{zywwvutsrrqpnnmllkiihgeedccba__]]\[[YXWVUTTSRQPONNMLKJJHGGEECCBA@?>==<���������������������������������������������������~}}{{zyxwvuusrrpponmlkjjhhgfedcbba`_^]\[ZYYXWVUTSRQPPOMMLKJIHGFFEDCBA@?>==;;��������������������������������������������������~||{zyxwwvutsrpponmmljjhggfeddcb`__^]\[ZZYWVUUTSRQQPONMLKJJIGGFECBBA@@>=<;::�������������������������������������������������~~||{zyxwvuussrqponmlkjjihgfedccb``_^]\[ZZXXWVUTTSRQONNMLKJIHGFEEDCBBA@>=<;;:9�������������������������������������������������~}|{zyywvuttsrqponmmlkjhhgffddcba__^^\[ZYXXWVUTSRRPPONMLKJJHHGFEDCBB@??>=<;:98�����������������������������������������������~}|{zyxxwuttsrqponnmlkjihhffedbb``__]\[[ZYWWVUUTSRPPONMLKJIIHGFEDCCA@??==<;:988�����������������������������������������������~}|{{yywvuussrqponnllkjihggfedcba`_^]\\ZZYXWVUTTRRQPONMLLJJHHGFEECBB@@>>=<;:9876���������������������������������������������~~}|{zyyxvvutsrqpoonmljjihggeddcaa``^]\\[ZXXWVUUSSRQPONMLKKJIHGFEDCBBA@>==<<::9776���������������������������������������������~}|{zyxxwuutsrrqoonmlkjihhgfeccba`_^^][[ZYXWWUUSSRQPONMLLKJIHGFEEDBAA@?>=<;;:87665�������������������������������������������~}}|{zyxwvutsrrqoonmlkjihggeedcba`__]][[ZYXXWVUTRRQPPNMMLKJIHGFEDCCAA@?>=<<;:987554�������������������������������������������~}|{zyxxwvutsrqpponlllkjigfeedcba`__^][[ZYXXWVUSSRQPPOMLLJJIHGFEECCA@@?>=<;:99876553������������������������������������������~}}|{zyxwvuussqqponmlkkjhhgfedcba`_^^]\[ZYXWVUUTSRQPPNNMKJJHHGFEEDCBA@?>=<;;:98765442�����������������������������������������~}||{yyxwvvtsrrpponmlljiiggfedcba``_]]\[ZYXXWVUTSRRPPNNMKKJIHGFFECCBA@??><<;:987654432�����������������������������������������}}|{zyxwwuusrrqponnlkkjihgfeddbaa__^]\[ZZYWWVUTSRQPPONMLKJIHHFEDDCBB@@>><;;:9877554320����������������������������������������~~||{zyxwwvutsrqpoommkkiihgfedcba``^^]\[ZZXWVVUTSRQQPONMLKJJHGGEEDCBA@@>>=<;:98766433210��������������������������������������}}|{zyxwvvutsrqponnllkiihgfedcbba`_^]\[ZYYWWVUTSRQQPNMLLLKJIHGEEDCBAA?>==<;:98876443210/��������������������������������������~}|{zyxwvuutsrqpoomllkjhhhffedcaa`_^]\\ZZXXWVUUSRQQOOMMLLJJIHGEEDCBA@??>=<;:98765543210/.�������������������������������������~~}|{zyxxvuutsrqqponmlkjihgfeedcba`_^]][[ZYWWVUTSSQQPONMLKKIIGGFEDCCB@??>=<;:98766542210/.-�����������������������������������~||{zyxwwutssrqponmmlkjihggfdcbba`_^]\[[YYXWWUTSRRQPNNMLLJIHHGFEDDCBA?>==<;;:97764432100.--�����������������������������������~}|{zyyxvvutsrqpponmlkjihgffddcaa`_^]][ZZYXWVVTSSRQPONMLKKIIHGFEDCBBA@>==<;::88665432110..-,����������������������������������~}|{{zxwwvutsrqqpnmmlkjiigffedbbaa_^]]\[ZYXWVUUTSRQPOOMMKJJIHGFFECBA@@?>==;;998765432100/--,+���������������������������������~~}||zzxxwvutsrrpponmlkjjhhfeeccca`__]]\[ZYYWVVUTRRQPONMLKJJHHGFEDDCBA@?>=<;::98665433100/.-,+*��������������������������������~}||{yyxwvutssrqpnnmlljiihffedcbaa_^^]\[ZYYXVVUSSRQPONMMLKJIHGFEDCBAA@?>==<:998765432100/.--+*)�������������������������������}}{{zyxwvuttrqqpommlkjjhggfedcba`__]]\[[YYWVUUSSRQPONNLLJJIHGFFDCCBA@?>==<::98765532210/.-,+**(������������������������������~~|{zzyxwvvutrrqponnlkjjihffedcbaa__^]\\ZYXWVVTSSRQPONNLKKJIHGFEEDBBA@??>=<;998765432100/.-,+**)(������������������������������~~||{zyxwvvtsrrqponnlkjihhgfedcbba__^]\\ZYYXWUUTSRQPPOMLLKJIIGFFEDCBAA?>=<;;:98865432210/.-,,*))('����������������������������~}||{zyxwwutssrqponmmlkjihgfeddcba`^^]\[ZYYXVVUTSRRPONMMLKJIHGGFEDCBA@?>>=<;:99766432200/.--++))('&���������������������������}|{{zyxwvvutrrpponnlkjjihgfedccba__^]][ZYXWWVUTSRQPOONMLKKIHGFEEDCBA@??><<;:99776443210//.-++))('&%��������������������������~}}|zzyxwvuutsrqponmmkjjihhfeecbaa`__]\\ZYXXWVUTSSQPONNMLKJJIGFFEDDBAA@?>=;;:99776433210/.-,++*))'&&%�������������������������~~}|{zyyxvuussrqponmllkjihggedccba`_^]\\[ZYWWVVUSRRPPONMLKJIHGGFEDCBA@?>=<<;;:87765432100..,++*))'&%$$������������������������~~}|{zzywvuutsrqqonnllkjihhgfddcba``^^\\ZYYXWVVTTSRPPONMLKJJIHFFEDCBBA@?><<;:987765432100..-,**)(('&$##������������������������~~}|{zyxwwvttsrqponmmlkjihgfeeccba`_^]\[[YYXWWUUTSQQPONMLKJJHHGFEDCCA@??>=<;;998754432100..-,+*)('&%$#""�����������������������~}|{zyywwvuttrqppnnmlkjihgffedcba`_^]]\[YYXWVUUTSRQPONMMKJJIHGFEDCBB@@?>=<;:997765442110/.-,+*))''&%$#"!���������������������~}||zyywvuuttrqqponmlkjihhgeeccba`_^]\[[ZYXWVVUTRRPPPNNLKKJIHGFEEDBBA@?>=<<::87765442100.--,+**)''%%$#"!!���������������������~}|{zzyxwvuttrqpponllkjiigffedcbaa__^]\[ZYXWVUUTSRQPPNNLLJJIHGFFEDCBA@?>==<::97765442110/.--++))('&%$#"! ��������������������~}|{{zyxwvutssrqoonmlkkiihffddcbaa`_^][[ZYXWWUUTSRQQONNMLKJIHGGEDCCBA??>><;;:8876653210//.-,+*))''&%%##! �������������������}}{zyyxwvvtssrqponmllkihggfedcbb``_^]\[ZYYWWVUTSRQPPNMMKKJIHGFFECCBA@??>=<;:8776554221//.--+**)('%%$$#!! ������������������~}||{zyxwvuttsrqpoomlkkiihgeedcba``_^]\[ZYXXWUUTSRRPPNNMLKJIHGFEDDCBA@?>==<;:9876643321//.--,+*(('&%$#"!!������������������}}|{yyxwvuusrqqpoomlkkjhhgfedcbaa__]]\[[YYXWVUTSSQQONNLLKJJHGGEEDCBAA??=<<;:98865443210/.-,++*)('&%%#""! ����������������~~||{zyxwvuussrqponmlkjjihgfeddcaa`_^]\\ZZXWWVUTSRQQONNMLKJIHHGEDDBBA@?>==<;:98766443100/..,+**)('&%$#"" ���������������~~}|zzzyxwuutsrqponmlkkjihggeddbba__^^\[[ZYXWVUUSSQQOONMLKJIIGGFEDCCA@??>=<;:98776543210//-,,+*)(''&%$#!! ��������������~}|{zzxwvvttsrqppnnmlkjihgfeedbaa`__]][[ZYWWVUTTRQQOONMLLKIHGGFEDCBAA??==<;:99775542210/.-,,+*)((&&$$#"! �������������}}|{zyyxwvutrrqqonnmkkjihgfeecca``_^]\[ZZYXWVUTSSRQPNNMLLKIIHGFEDCBA@@>>=<;:98775533210//--++*)('&%%$#"! �������������~}|{zzxwvvutsrqqoonmkjjihggeddcba`_^]\[[ZYXWVVTSRRQPONMLKKJIHGFFDCBAA@>>=<;:997665432100.--,+*)(('%$##"! ������������~~}|{zyxxwuutsrqqonmllkjihgfeedcba``_^\\ZZYXWWVTTRRPPONMLLKJIHGFEDCCAA??>=<<:98775543321//.,,+*)((&&%$#"! �����������~}|{zyyxwvutssqqponmlkjjigffedcba``_^\\[ZYXWVUUTRQQPONNLLKJIHGFEDCBBA@?>=<;::8776544210//.-,++*)'&%%$#"!!����������~}|{{zxxvvutsrqpponmmkjihhgfedcbb`__]]\ZZYXXWUTSSRQPOOMMLKJIHGFEDCBAA@?>==;:99876543220//.,,++)(''&%$#"! ���������~~}|{yyxwvvutsrpponmlkjiihgeedcba``_^]\[ZZXXVVUSSRQPPONLKJJIHGGFDCCBA@?>><;::98765532100/.-,+*)(('&%$#"!!��������}}|zzywwvutsrrpoonmlljiiggfedcbba`^^]\[ZZXWWVUTSRRPOONMLKJIHGGEDDCBA@?>=<;:99776553211//.-,+**)('&%$$"! �������~}}{{yyxwwuttrrqponmllkjhhgfeeccba__^]\[[ZYXVVUTSRRPPONMLKJIHGGFEDCAA@?>><;::98775443200/..,,*)(('&%$##!! ���������������������������������������������������������������������������������������������������������������������������~}}��������������������������������������������������������������������������������������������������������������������������~}}{��������������������������������������������������������������������������������������������������������������������������~}|{z�������������������������������������������������������������������������������������������������������������������������~}||{z������������������������������������������������������������������������������������������������������������������������~~||{zy�����������������������������������������������������������������������������������������������������������������������}}{{zxx����������������������������������������������������������������������������������������������������������������������~|{zzyxw���������������������������������������������������������������������������������������������������������������������}|{{zxywv��������������������������������������������������������������������������������������������������������������������~}{zzyxwvv�������������������������������������������������������������������������������������������������������������������~~}|{zyxwvvt�������������������������������������������������������������������������������������������������������������������~~||{zyxxwuus�����������������������������������������������������������������������������������������������������������������~}|{{yywvvuts�����������������������������������������������������������������������������������������������������������������~}|{zyyxwvttsr����������������������������������������������������������������������������������������������������������������~}|{zzywvvutsrq���������������������������������������������������������������������������������������������������������������~~}|{zyyxwvutsrrq�������������������������������������������������������������������������������������������������������������~}|{zyxxwvuttrqpo�������������������������������������������������������������������������������������������������������������~~||{zywwvutsrrppo������������������������������������������������������������������������������������������������������������~~}|zzyxwvuussqqpon�����������������������������������������������������������������������������������������������������������~~|{{zyxwwvttrrpoonn����������������������������������������������������������������������������������������������������������~~||{zyxwwuttsrqponmm���������������������������������������������������������������������������������������������������������~}||{zyxwvuussqqponmll��������������������������������������������������������������������������������������������������������}||{zyxwwuttrrqponmlkj�������������������������������������������������������������������������������������������������������~}}|{zyxwwuussrqponnmlkj�������������������������������������������������������������������������������������������������������}}|{zyxxwuutsrqpoonlkjji������������������������������������������������������������������������������������������������������~~||{zyywwvutsrqpoomlkjjih�����������������������������������������������������������������������������������������������������~~}||zzxwvvutsrqpponmlkjihh����������������������������������������������������������������������������������������������������~~}|{{yyxvuutsrqpoommlkjiigg���������������������������������������������������������������������������������������������������~}|{{yyxwvvtsrqqpnmllkkiihgf��������������������������������������������������������������������������������������������������~}}{zyxxwvutssqqponmlkjihggfd�������������������������������������������������������������������������������������������������~}|{zzyxwvutsrrqponmlkkiihfeed������������������������������������������������������������������������������������������������~~}{{zyxwvuusrqqponmllkiihgfedc�����������������������������������������������������������������������������������������������~}}{{yyxwvuussrqponnlljjihgfedcc����������������������������������������������������������������������������������������������~}}|{zyxwwvttsqqponmmlkjihgfedccb����������������������������������������������������������������������������������������������~~}|{zyxwvvttsrqponmmlkiihggedccba���������������������������������������������������������������������������������������������~||{zyywvvutsrqpoonmkkjihggeeccba`��������������������������������������������������������������������������������������������~~}|{zzyxwuutsrrpoommkkiihggfeccaa`_������t2 %T�����4j��������� ��������������������� a��������FC������Q$ 3`yxwussra :mmP 'Ofdcbb`^���Ͱ�����������rq��������������������^�����wp����tyxvtsr` ?nlJedcba^^������Ľ�s+��������u������)*�����������������������:�����d��c��KmzwfIxvvsr^ Enml Wf^Ddcba`]\���s ������������������![�����'#����������������������������P������J��Ms~}{{zyxwvur] Inmlkbhgfedcba``\\���1�������������������{'����LjkK���������������������������"\������W ��!P~|{{yywwvut\Nnmlkj 5_fedcba`_^\[������������������ ���� �� ����������������������91���� +~������w +�� +r|{{zyxwvuttRnmmlki@"?`aa__][Z���������������������m@��Kj������������������ ��������������z{zzxxwvvttr +\mlkjiihMX`^^]ZY��� ������������������ ���&����%������������������e����� +|������v +�~ qzzyxwvutssqM YkkiihgfedS; "^^]\ ZY���.�����������������y'�����������������������bp����!Y������U ~} NzyxwvvussrqnHViihgfeedbbT^]\[XX���l*����������������Y��GE��������������������S����M�����|H}|JoxxwuttsrqpmmDRhgfeeccbaY^]\[YXXW��Ƽ,����r��������q��� +������ ���������������������Q����`}}_y}|xGhsqbFqqolkk@Ofe:S__M\\ZZYXWV���šo�������h0������.c��������������h{���oi||{zlpoolkji<Ke?[ZZYWU����ķd' +J������3h����"q������m ���������������.,����{@>v}||zyxuJ +/Woonkjiig8IP+ +H\[ZYXUU�������������������������������������������������������������������������������}}|{{yywvvutsrrqoonmlkjihgffedcba`_^^]\[ZYXWVVTT�����������������������������������������������������������������������������~}|{{yyxwvutsrqpoonllkkihhgfedcba`__^\\[ZYYWVVUTR�����������������������������������������������������������������������������~}|{{yywvvutsrqpponmlkjihgffddcba`__^\[[ZYXWVUUTSR����������������������������������������������������������������������������~}||zyyxwvuusrrpoonmmkjjhggfedcbaa__^]\[ZZXWVVUTSRQ���������������������������������������������������������������������������~}||zyyxwvuttrrqoonmlkkihggfeddba`__^]\[ZYXWVUUTRRQP��������������������������������������������������������������������������~~}{{zyxwvuutrqqponmlljiihgfedcbb`_^]]\[ZYXWVVUTSRQQP�������������������������������������������������������������������������~~}|{zyxwvutssqqponmlkjjiggfedccba__^]\[ZYYXWVUTSSQQPN������������������������������������������������������������������������~}|{zyxwvuussrqponnmlkiihggfddbaa`_^]\[ZYYXVVUTSRRQPON�����������������������������������������������������������������������~}}|zzyxxvvutsrqpoomlkkjiggfeedbaa__^]\[ZZXXVVUUTRRQPONM�����������������������������������������������������������������������~~||{zyxwwuutrrqppnmlkjiihgfedcbba`_^]\[[ZYXVVVTSSQPPONML���������������������������������������������������������������������~}}|{zyxxvvttsrqponnmlkiihggfedbb``_^]][[ZYXWVVUSSQPPONMLK��������������������������������������������������������������������~~}||zyyxvvutsrqppnnllkjihgfeddcba`__]\\[YYXXVUTSRQQPONMLKK�������������������������������������������������������������������}}||zyyxwvutsrqppnnmlkjihgffedcba``_^\\[ZYXWVVUTSRPPONNLLKJ�������������������������������������������������������������������~~}|{{zxxwvutsrrpoonmkkjihhffddcba`_^]][[ZYXWVUUTSQQPONMMKJJI������������������������������������������������������������������~}|{{zyxwuutssqqoonmlkjiigfedccbaa`^]]\[ZZYWWUTTSRQPPNMLLJJHH�����������������������������������������������������������������~}|{{yyxwvutssqppnnmmkjjiggfedcca``^]\\[ZYYWWUTTSRQQONNMKKJIHG����������������������������������������������������������������~}|{{yyxwvutssqqoonmlkjjhggfedcbaa_^^]\[ZYXWWUUTSRQPOONMKKJIIGG���������������������������������������������������������������~}|{{zyxwvvtssrqponnlkjihhgfedcbaa`^^]\[ZYYWVVTTSRQQOOMMLKJIIGGF��������������������������������������������������������������~}||zyxxwvuusrqqponmlkkihhgfedccba_^^]\\[YXWVVUTSRQQOOMLLKJJIGFFE�������������������������������������������������������������}||{zxxwvuussrqponnlkkjihgfeddbba`_^]\[ZYXXWVUTSRQPPONMLKJJIGGFED������������������������������������������������������������}}|{zyxwwuttsrqponnllkihhgfedcca``_^]\[ZYYXVVUTSRQPPONMLKJJIHGEDDC������������������������������������������������������������~~}|{{yxwwuutrrqponmmlkjihgfeddcba`__]\[ZZXXWVUUSRRPPONMLLJIHGFEEDCB�����������������������������������������������������������~}|{zyxxvvussrqpoonmlkjihgffeccba`_^]\[ZZYXWVUTSSRQOONMLKJIIHFFEDCBB���������������������������������������������������������~}|{{yyxwvutsrqppnnlkkjihhffddcba`_^^\[[ZYXWWVTTSQQONNMLLKIIGGFEDCCA@��������������������������������������������������������~}||zyywwvutsrrqoommlkjihgffedcba`_^^]\[ZYXWVUTSSRQOONMLKJJIHGFEDDCA@@��������������������������������������������������������~}||zzywvvutsrrqponmkkjjiggeddbbaa`^^]\[YYXWWUUTRRQPONMMKJJIGGFEDDBA@@?�������������������������������������������������������~}|{zzxxwvutsrqpoonmlljjihffddcba``_^][[ZYXXVUTTSRQPONMLKKIIHGFEEDCBA@?>������������������������������������������������������~}||zzxxwvuttrqqonnmlkjjhhgfddcbaa__^]\[ZYXWVVUTSRQPONNLKKIIHGFEEDCBA@?>=�����������������������������������������������������~}||{yxxwvutsrrqponmlkkiihffedcbb`__]]\[[YXXVVUSSRRPOONMKKJIHGFEEDBBA@?>><����������������������������������������������������~~|{zzyxwvuutrqqponmlljjhggfeecbba`^]]\\[ZYWVVUTSRQPOONMLKJIHGFEEDCBA@?>>=;���������������������������������������������������~}}|{yxxwvuusrrqponmlkkjhgffedccaa`_^]\[ZYYWWUUTSRQPPNMLLKJJHGFEEDCAA@@>=<<:��������������������������������������������������~~}|{zyxwvuutrqqponmlkjjihgfeecbba__^]\\ZZXXWUUTSRQPONNMLKJIHGGEEDCBA@@>>=<;:�������������������������������������������������~}{zzyxwvuutsqqponnmkkiihgfedcbba`_^]\[[YXXVVUTSRRPPONMLKKIHGFEDDCCA@??>=<;:9�������������������������������������������������~}}{{zyyxvvussrqppnmlkjjihgfeeccba`_^]\[[ZYXVVUTSRRPPOMMLKKJIHFFEDCBA@??==<;:98�����������������������������������������������}||{{zxwwvutsrqppnnmlkjihgfeedba```^]\\[ZYXWVUTTRQQOONMLLJJIHGFEDCBB@@>=<<;:988�����������������������������������������������}}|{zyxxvvussrqppnmmlkjihgfeddcba`_^^][ZZYXWVUTTSRQPONMLKJIHHGFEDDBAA??==<;:9976���������������������������������������������~}|{zzxxwuttsrrpoonmlkjihhffdccba`_^]\[ZZYXWWUUSSRQPONMLLKIHHGFEDCCB@@?==<;:99876���������������������������������������������~}||{yywvvutsrqponnmlkjihhffdccba`_^^\\[ZXXXVUUTRRQPONNLKJJHHGFEDCBAA@?>=<;;:87765�������������������������������������������~}|{zzxxwvutsrrqonnmlkjjhhfeedccaa_^^][[ZYXXWVUTSQPPONMMLJJIGGFEDCBAA@?>=<;::986654�������������������������������������������~}||{zyxwvuttrrqpnnmlljjhhgeedcbaa`_]][[ZYXWWUUSSRQPONMMKJJIHGFEDCBAA@?>==<::8876554������������������������������������������~~|{zyyxwvutssqqonnmlljjigfeedccaa`^^\\[ZYXWWVUTSRQPOOMLKJJIHGFEEDCBA@?>==;:988765432�����������������������������������������~~}{{zyxwvutsrqpponmmljiiggfedccaa`^^]\[ZYYWWUUSSRQPOONLLKJIHGFEECCBA@?>=<;;:987764322����������������������������������������}}{{zyxwvvusrrqoonmlljiihgfeddba``_^]\[ZZYXWVUTSRRQONNLLKJIHHGEEDCBA@?>>=<;99876553210���������������������������������������~~|{{zyxwvvutsrppoonmkkjihggeecca``^^]\[[YXXVUUTSRQPPONLLKJIHGFEECCBA@??>=<;:98765533210���������������������������������������}}|{zyxwvvutsqqponmllkjihgfeddbb``_^]\[ZYYXWVUTSRQPPNNMLKKJHGFEEDCBB@?>=<<;:98776533210/��������������������������������������~}|{zzxwwuttrrqqonmmlkjihgfeeccba__^]\\ZZYXWVUUSRQPPNNMLKJIHHGFEDCBAA?>>=<;:98776543211//������������������������������������~}||{zyywwvutsrqponnmlkjihgffedcba`__]\[[ZYXWVUTTSRQPNNMMKKIHGGEEDCBAA?>>=<;:987655432100.-�����������������������������������~}|{zzxxwvutsrqppnnmkkjihgfedccba`__]\[[ZYXWVUTSSQQPONNMKJIIGFFEDCBB@@?>=<;:987765432200.-,����������������������������������~}|{{yxwwvutsrqqonnmlkjihggeddbbaa_^^\\[ZYXWWVTTSQQPONMLKJJHHFFEDCCBA@>>=<;:98866543211/.--,���������������������������������~}}{zyxwwvttsrrqoonllkjihgffeccba``_^][[YYYXVVUTSRQOONMLKJJIHGFEDCBB@@?>=<;;988765443100/--,+��������������������������������~}|{zyxwwvuttrrqoonmlkjiihgfedcbba_^]]\[ZYXWWVUSSRQPONNLKKJHHGFEDDCBA??>=<;:998665432100/.-,+*��������������������������������~}|{{yywwvutsrqpponmlkjihhfeedcbba`_^][[ZYXWVUTSSRQPONMMKJIIHGFEDDBBA@?>=<<;:88765533200/--,+**�������������������������������~}|{zyyxwvutsrqpoonmmkjiihgfedcbb`__^]\[ZYXXVVTTSRQPONNMKKJIHGFEDCCBA@?>=<<:988765432210..-,,+*(������������������������������~}}|{yyxwvutsrrqponmlkkihhfeedccaa__^]\[ZYXXVVUSSRQPONMLLKJIHGGFEDBBA@?>>=;;:98765533100/..,,**)(�����������������������������~~||{zyxwwvttsrqpoommkjiihffeddbaa`_]]\[ZYXXWUUTSRQQOONMLJJIHHFFEDCBA@@?=<;;:98765543200/.--++*)('����������������������������~~}|{zyxwvvtsrqpponmlkkiihgffdcbba`_^]\[[YXWVUUTSSQQPOMMLKJIHHFFEDCBB@@>==<::98765543210/.--,*))(''���������������������������~~||{zyxwvuutsrpponmlljjihgfeedcaa__^]\[[YXXWVTTSSQQPONMLKJIHHFFEDCBA@@>=<<;:99765542200/..,++*)('&%���������������������������~~}|{zyywwuttrrqponmmkjjihggeddcba`_^]][[YYXWVUTSSRPOOMMLKKJIGFFEDCBAA?>==<;:99766543210/.-,,+*)('&%$��������������������������~}|{zyyxwvutsrqponnmkjjihgfeddcba``^^][[ZYXWVUTSRQQPOMMLKJIIGFFEDCBA@??=<<;:98765543210/.--++*)(''%%$������������������������}||{zyxwwvutsrqppnmllkjihhffdccba`_^^\\ZZYXWWUTSSQQPONNMKJJIHFFEDCBAA@?>=<;:988764432110.-,,+*)(''&%$#������������������������~~}|{{zyxwvutsrqppomlljjihgfeedcbaa__]\\[ZYXWVUTSRQQPONMLKJJIHGFEEDBBA@?>=<<:997765433110..-++*)(''&$##"�����������������������~}||zyxxwvutssqqoommkkjihhffedcbaa_^]\\ZYYXWWUTTSRQPONMMKKJHGGFEDCBB@@?>=<;::9876543210/.--,+*))'&&%$#"!����������������������~}}|zzyxvvutsrqpoonmllkjigfeedbbaa_^^]\[ZYXWWVTTSRQPONMMKKJIHGGEDCCAA??>==;:998765432100/.-,+*))''%%##"! ���������������������~}|{{yxxwvutssrpponmlkjihggfedcbaa`^^\\[ZYXXVUTTSRQPONNMLKJIHGFEDCBBA@?>=<;;98876543221//.-,+**((&&%$#"" ��������������������~}|{{zyxwvutssrppommlkjihhfeedcbba__^\\[ZYYWVVUSSRQQONNMKKIIHGFFDCCAA@?>><;;998765432100..-,+*))(&&%$#"!! �������������������~}|{{yyxwvutssrpponmlkjiiggfedcbba__^]\[ZZXWVUUTSRQPONNLLKJJHGFEDCCBA@@>=<;;:98765432200/.--+*)(('&%$#"! ������������������~}|{{zxxwvutsrrpponmlkjiihffedccaa__^]\[ZYYWWVUTSRQPONMMLKJIHGGEEDCBAA??>=;;:98765433110/.-,,+*)('&%$#"! ������������������~~||{yyxwvutssrqponmmkjiihgfeddca`__^]\[ZZXWWVTTSRQQPNNMLKJJHHGFECCBA@??>=<;:98775543210/.-,++)(('&&%$#"! ����������������}}|{zyxwwuttrrqponnlkjjihgfeddbb``_^]\[ZZYXVVUTSRQQONNMLKJIIGGFEDCBAA@>=<<;998776443200//--,+*)(''%$#"! ����������������~}|{zyxwvvutsqqpoommlkihhggfeccba`_^]\\ZZYXWVUUSRRQPONMLKKIHHFFEDCBB@??==<;:99866533210/..-,+*)('&&$$#!!��������������~}}|{zzyxvuttsrqponmmlkiihggeedcba`_^^\[ZZYXWVUTSSQPPONMLKJJIGFFEDCBB@?>>=<;:99775543211/..-++))('&%$##"! �������������~~}|{{yxwvuttsrqponmmljjihgfeddcba`_^^][[ZYXWWUTSSQQPONMLKJJHGGFEDCCAA@?==<;:988765432100.--,+*))(&%%$#"! ������������~~}|{zyxxwuttsrqponnmlkjiihffddcba`_^]]\ZZYXWWUTTRRQPONMMLKJIHFFEDCBAA@?><<;:99866543311//-,,+*))''%$$#"!!�����������}}|{{yyxwvutsrqponmllkjihggeddcba`_^^]\[ZYXXWUUTRQPPONMMKKJIHGFEEDBAA@?>=<;;:9876544211//.-,+*)('&&%#""! ����������~}|{zzxxwvuttsqqponmlkjihgffecbba`_^^]\[ZYXWVVTSSRQPONMMKKJIHGFEDDBA@@?>==;;98776443210/..,,+**)''&$##"! ����������~}|{zyxwwvutsrqpoonmlkjihhffddcba``^^]\[ZYXXWVTTSQQPPNMMKJJIHGFEDDBAA@?>=<<:99876544311//.,,+*)(('%$$#"! ���������~}|{{yyxwvutssqqpnnmlkjihhgeedcbba`_^]\[ZYXXVVTSSQQPOONMKKJIHGFEDDBAA@?>>=<;:98765433200/.-,+**)''&%$#""! ��������~}|{{zxxwvutsrrqponmmkjjiggfedcba``_^]\[ZYYWVUUTSRQPPOMLLKJIIGFEEDBBA@?>=<;;998776542210/..,,+))''%%%#"! �������~~|{{zyxwvuussrpponmlljiihgfeddbba`_^]\[ZYYXVVUTSRQPPOMMLKJJHGGEEDCBA@?>=<<;:98866533200/.--++))('&%$##!  \ No newline at end of file diff --git a/autotest/gdrivers/data/adrg/subdataset/XXXXXX02.IMG b/autotest/gdrivers/data/adrg/subdataset/XXXXXX02.IMG new file mode 100644 index 000000000000..0955a8b16c1a --- /dev/null +++ b/autotest/gdrivers/data/adrg/subdataset/XXXXXX02.IMG @@ -0,0 +1,19 @@ +001852L 0600065 340300002000000010420020PAD0280062SCN0300090 GEO_DATA_FILE1000;&RECORD_ID_FIELDRTY!RID(A(3),A(2))1000;&PADDING_FIELDPAD(A)2000;&PIXEL_FIELD*PIX(A(1))51015 D 00088 9903001000000006000000000PAD000001769000000006SCN000049152000001775IMG01 ����������������������������������������������������������������������������������������������������������������������������~}|���������������������������������������������������������������������������������������������������������������������������~}|{��������������������������������������������������������������������������������������������������������������������������~}||z�������������������������������������������������������������������������������������������������������������������������~}||{y�������������������������������������������������������������������������������������������������������������������������~}}{zyy�����������������������������������������������������������������������������������������������������������������������~~||{zyx����������������������������������������������������������������������������������������������������������������������}||{zyxw���������������������������������������������������������������������������������������������������������������������~~}|{zyxwv��������������������������������������������������������������������������������������������������������������������~}}|{zyxwvu��������������������������������������������������������������������������������������������������������������������~~}{{zyxwwuu�������������������������������������������������������������������������������������������������������������������~~||{zyxwwvut������������������������������������������������������������������������������������������������������������������~}}|{{yxxwvuts�����������������������������������������������������������������������������������������������������������������~}|{zyxxwuttsr���������������������������������������������������������������������������������������������������������������~}||{yywvuutsrq���������������������������������������������������������������������������������������������������������������~}|{zzyxwvutsrqq��������������������������������������������������������������������������������������������������������������~}||{zxxwvutssqqo�������������������������������������������������������������������������������������������������������������~}|{{yyxwvuttrqppo������������������������������������������������������������������������������������������������������������~}}{zyyxwvutsrrpoon������������������������������������������������������������������������������������������������������������}}|{zyxwwuttrrpponm����������������������������������������������������������������������������������������������������������~}||{zyxwwuttrqqponml���������������������������������������������������������������������������������������������������������}|{{yyxwvvttrrqppomll���������������������������������������������������������������������������������������������������������}}|{zyxxvvutsrqponmmkk��������������������������������������������������������������������������������������������������������~~}|{zyxxwvttsrqpoomlkjj������������������������������������������������������������������������������������������������������~}|{{yxwwvutsrqqpnnmkkji�����������������������������������������������������������������������������������������������������~}||zzyxvuutsrqqoonmlkjih����������������������������������������������������������������������������������������������������}}|{{yxxwvutsrqponnllkjihg����������������������������������������������������������������������������������������������������~}}{zyxwwuuttrqqponmlkjiigg���������������������������������������������������������������������������������������������������~}|{zzywwvuusrrqoonmlkjiigge��������������������������������������������������������������������������������������������������~~}{zzxxwvutssqqpnmmllkihgffe�������������������������������������������������������������������������������������������������}||{zxxwvuttsrqoonmlkjjhhgfed������������������������������������������������������������������������������������������������~}}|{zyxwvuutrrqponmlkkjihgfeec�����������������������������������������������������������������������������������������������~}||zzyxwvutssrqponmlkjjihgfeddb����������������������������������������������������������������������������������������������}|{{zyxwwvttsrqponmlljiihggeeccb����������������������������������������������������������������������������������������������~~}{{zyxwvvtsrrqpponlljjihgfedcca`���������������������������������������������������������������������������������������������~~}|{zzywvvutsrqpoonllkiihgfedccb``�������������������������������������������������������������������������������������������~}|{zyxxwuussrqpoonlljjihgfeeccba`_�������������������������ؾ��������������������������������������躔������������ď�������������ɗzxw��utss����ml�����Ɗfddcb��_^���������������������������Ʒ��������ˮ������������������������������������������񙅄������������xww��tsr����nl��������ddbba��^]�������������������������������������쭬���������������������������뒑�����髏����퉃���������xvv��sr����nll��Ҁjs��dcbaa��]]����������������������������ڴ��������������������������������������������퐊������������}}{zzxxwvu��r����nmlk��shgfeccbba`��]\����������������������������ﳲ�������ڪ�������������������������������������������������}|{zzyxwvut������nmlkj���rfddcbaa`_��\[�������������������������������������������������������������������ڐ��������������������|{{yyxwvvtt�����nmlkjj�����˝ea`__^��[Z����������������������������������ᬫ��ɨ�������������������������皎������������������~|{yyxwwuuts����mmkjiih�������o`_^]��ZY���������������������������������������짦���������������������������������������������zyxxwvuutsq�����kjjhhgfef}����^^]]��ZX���������������������������������������������������������������������������������}���zyxwvvttsqq��o����iihgfeddbav��^]\[��YW����������������������������ׯ����������ڤ�������������������������茌����닅�������}|���xxwvttsrqp��mm����hgffedcb`k��^][[ZYWW���������������������������������������������������������������������������祈�����}|~���xy���qqo��lkk����feޤ{fe���]\ZYYXWV�������������׻�����������������穩������ơ���������������������������������������}{{{����������poo��lkji����d���������\ZYY��VU������������Ż�����������ѳ�����ƪ�������졠�������������������������ڇ�����������}|{{yx{������ŏonm��kjiig����������ʁ\[ZYX��VT�������������������������������������������������������������������������������~}|{zzywvvuttrqppnnmlkjihggeddcbba`^]\\[ZYXXVUTS�����������������������������������������������������������������������������~}|{zzywwvutsrrqonmmlkjiigffdccba`__]]\[ZYXXVUUTS�����������������������������������������������������������������������������~}||{yyxvuutsrrqoommlkjiihffedcba``_^\\[ZYXWWUTTSR����������������������������������������������������������������������������~~|{{zyxwvutsrqpponmlkjiiggfedccb``_^]\[ZYXWWVTTSRQ���������������������������������������������������������������������������~}}{zzywwvutsrrqponmlkjjhhgfedcbb``_^]\[ZZXXVVUTSRQP��������������������������������������������������������������������������~}|{zyyxwwuussrqpnnmlkkjihgeedcbb``^^]\[ZYXXVVUTSRRPO��������������������������������������������������������������������������~}||{zxxwvutsrrqponmllkiiggfeecbb`__^]\[ZYYWVVUTSSRPOO������������������������������������������������������������������������~~}|{zyxwwuusrrqponmlljjiggfedccaa_^^]\[ZZYXWUUTTRQQPOM�����������������������������������������������������������������������}}|zzyyxvuussqqppnnmlkjihgfeecbba`_^]\[ZZYXWVUUSRQPPONM����������������������������������������������������������������������}}|{zyxwvuutsrqponmmkkjihgffedcb```^]\\[YXXWVUTSRQPPONML����������������������������������������������������������������������~~||{zyywwuttsrqpoonmkjiihgfeeccba``_]\\[ZXXWVUTSSRQPONMML���������������������������������������������������������������������~}|{zyxxvvutsrqqpnmmlkjihgfeddcba`_^]][[YYXWVUUSRQQPONMLLK�������������������������������������������������������������������~~}|{zyxwvuutsrrqponmkkjihhffedcba`_^]\\ZZYXWVVTTRRQPONNLKJI������������������������������������������������������������������~}||zyxxwvutsrqppnnmkkkiihgeeccbb``^^\\[YYXXVVTSRRQPONMMKJJI�����������������������������������������������������������������~}|{{yxxwvutssqqonnmlljiiggeddcbba`^]]\[ZYXWVUTSSRQPPNNMKJJIH�����������������������������������������������������������������~}||zzxxwvutssqpponmlljihggfedcbb`_^^]\[[ZXXWUTSSRQPOOMLKJJIHG�����������������������������������������������������������������~||{zyxwvuttsqqponmlkjihhffedccb`__]]\[ZYYXVUUTSRQPOONMLKIIHGF����������������������������������������������������������������~~}{zzyxwvuusrrpponmlkjjihffeddbba`_^]\[ZYXXWUUTSRQPONNLLKJIHGGF��������������������������������������������������������������~~||{yyxwvuutsrqponnmkjjiggfeecbba`^^]\\ZZYWWVUTSSQQOONMLKJIHGFFE�������������������������������������������������������������~}}{{yyxxvvutsrqpoomllkjhhgfeedcba__^]\[ZYYXVUUTSRQQOONMLKJIHGFFED�������������������������������������������������������������~}}{{zyywvuutsrqppnmmlkiihgffecbba`_^]\\ZYYWWVUTSSQPPOMMLKKIIHFFECC�����������������������������������������������������������~}}{{zyxwvvussrqponmllkjihgfeddcb``_^]\[ZZYXWVUTSSQPPONMLKJJIHGFEDCB����������������������������������������������������������~~||{zzyxvvttsrqppomlljjihgfeedcba`_^^\\ZZYXWVUTSSRQPONNLKJJHHGFEDCBA���������������������������������������������������������~}|{zyxxvvussrqpoonmkkjihhgeddcba`_^]][[ZXXWVUTTRQQPONMMKKJIGGFEECBA@��������������������������������������������������������~}|{zzxwvvttsrqponmlljjjigffedcba`_^]]\[ZYXWVUUTRRQPONNLKJJHHGFEDCBAA@��������������������������������������������������������~}|{{yywwuttsrqqponmlkjiihffddcba`_^^]\[ZXXWWUTTSQQPONMLKJJIHGGEDCBA@@?�������������������������������������������������������~}}|zzyxwvuttrqqpnnmlkjjhggfedcbb`__^]\ZZYXWWVUTSRQPONMLKKJIHGGEECCBA@?>������������������������������������������������������~}|{{zyxwvuttsqpoommlkjiiggfedcca`__]]\[ZYXWWUTTSRQPONNLKJIIHHFEDDCBA@?>>�����������������������������������������������������~~||{yyxwvuussqqponmmkjjhggfedcbb`__^]\[ZYYWWVUTSRRPOOMLKKJIHGFFDCBBA@?>><����������������������������������������������������~~|{zzxxwvutssqqponmlkkihhgfeddcaa`^]]\[[ZXWVVUTSRQPOONMLKJIHHFEDDCBA@?>=<<���������������������������������������������������~~||{zyxwwuutrrqponnlkjjhhgfedcba``^^]\[[ZYWWVUTSRQQOONMLKJIIGFEECBBA@??=<<:���������������������������������������������������~}}{{zyxxvuussqqponmlkjjhhgfedccba`_^]\\ZZXXWUUTTRQPPONLLKJIHHGFEDCBA@@>>=<;:�������������������������������������������������}||{zzxwwutssrqponmlljiihgfedccb``_^]][ZYYXVVUUSRRQPONMLKJIIHGFEDCBA@?>=<<;:9������������������������������������������������~}}|{zyywvvutsrqponnmljjhhhffedbba`__]\[[YYXWVUTSSQPPONMLKKJIGGFEDCBA@??>=<;:98������������������������������������������������~||{zyxwwuutsrqppnmlkkiihgffdccba`_^^\[ZYYXWVUTTSQQONNMLKJJHHGFEDCBBA@>=<<;:997�����������������������������������������������~}}|{zyxwvvutsrqpponmkkjihhgfedcba`_^]][ZYYXWVUTSRQPOONMLKKIIHGFEDCBA@@?>=<<:9977����������������������������������������������~}||zyxxwvutsrqqonnmlkjihgfeddcbaa_^]]\[ZYXXVUTSSQPPOOMLKJJHHGFEECBAA??>=<;::9866���������������������������������������������~}|{zyxxvvutsrqpponmlkjiihgeeccbb`_^]\\[ZYXWVVTTRRQPOOMMLJIIHGFEDCCBA??>==<;:88765��������������������������������������������~}|{zzxwwvutsrqqponmlkkiiggeedcba`__^][[ZYXWVVUSSRQPONMMLJJIHGFFDCCBA??>=<;:9877654�������������������������������������������~}}|zzxwvvuttrrppnnmmkjihhgfddcbaa`^^\[[ZYXXVVTTSRQPONMMLKJIHGFEDDCB@@?>==<::9876543������������������������������������������~}|{{yyxwvutssqpoonmlkkjiggfedcbb``_^][[ZZYWWUTTSRQPONMMKKJIIGGFDDCB@??>>=<::88765433�����������������������������������������~}}{{zyxwvutssqqponmlljihhgfedccb`_^^]\[ZYYWVVUTSRQQONMMLKJIHGFEDDCB@@??=<;::977654432����������������������������������������~}|{{yyxwwvttrrqpoomlljjhhffeecba``_^]\[[YYXWVTTSRRPOOMLLKJIHGGEDDCBA@??>=;;99876644321���������������������������������������}||{zyxwvutssqqpoonlljjihgfedcbb``_^]\[ZZYXWVUTSSQQOONLLKJIHHFEDDCBB@@?>=<:998776443210��������������������������������������~}}{{zyxwvvusrrqpoomlkkjhhgfeeccba`_^]\\ZZXXWVUTTRRQPONMLKJIHHFFEDCBA@??><<::98866543210/��������������������������������������~}}|{zyxwvutssrqpoonmlkjihgfeddcaa`_^]][ZYYXWVUTSRRQPONMLLJIHHFFEDCBA@@?>=<;:98765543210//������������������������������������~}|{zyywwvttsrqppnnmlkjihgfeddcaa`__]\[ZZYWWWUTSRQPPONMLKJIIHGFEDCBAA?>><<;:98865543210//.������������������������������������~}|{zzxxwvttsrrqpnmmlkjiigffecbba`_^]]\[ZYXWVVTTRRQPONMMKJIHGGFEDCBBA?>>=<<:99876533210/.--�����������������������������������~~}|{zyywvvutsrqppomllkjjhgfeedcba`_^^\\[ZYXWWUUSSRQPONMMKJJHHGFEDCCBA??>=<;;99876543210/.--,���������������������������������}}||zyywwvutsrqpponmlkjihgffeccba`__]\\[ZYXWVVUTSRPPPOMMKKJIHGFEDCBBA@?>=<;;:8765544220/..-,+���������������������������������~}||{yywwvutsrrqponmlkjihgfeeccba``^]\\ZZYXWVVTTRQQPONNMLKJIHGFEEDBAA@?>=<;;98875554311/..-,,*��������������������������������~}||{yxxwvutsrrqponmlkjihhgfedcba`_^^]\[ZYYXWUUTSRQPONMLLKJIHGGEEDCBA@?>=<<::98765533110/.-,+**�������������������������������~}|{{yyxvvutsrqppnmmlkjjhgfeedcbb`_^^]\[ZZXXWUTSSRQQPNNMKKJIHHGEEDCBA@?>=<<:998665433110/.-,,*)(������������������������������~}}{{zxxwvuutrrpponmmkkiihgeedccba`_]]\[ZYXWWVTTSRQPOONLKKJIHGFFECCBA@?>><<;:98765543210/.-,,+)((�����������������������������}||{zyxwvutssrqponmmkkjihgfeeccaa_^^]\\ZZYXWVUTSRQPOOMLLKJIHHFEDCCBA@?>><<;:98765542110/.-,,+*)('�����������������������������~}|{yyxwvuutsrqponnlkjiihgffddbba`_^]\[ZYXWWVUTSRRPOONLLKJIIHFEEDCBAA?>==<;999776543210//--,+*(('&���������������������������~}|{zyxxvuttrrqpoomllkjhhgfedccaa__^]\[[ZYWWVUTSRQQOOMMLKJIHHFFECCBAA??><<;:987654432100.--,+*(('&%���������������������������~||{zyxwvuutsrqpoonmlkjhhgfedcbba`_^]\[ZZXXWVUTTSQQPNNMLKJIHGGFEDCBAA?>=<<;:98765542220//.,,**)('&&%�������������������������~~}|{zyyxwvttsrqppnmmlkiiigfeedcba`__^\[[ZYXWVUTSRRPONNMLKJIHHGFDDCBA@?>>=<;:998665432110/-,,+*)((&&%$�������������������������~~}{{zyxwwuttrrqpponmlkjihgfeedcba`__]\[[ZYXWVUTSSRPOONMLLJJHHGFEDCBBA??><;<:98776543210//--,**)(''&$$#�����������������������~}|{zyxwwvttsrqpoommlkjihhfeddcba``_]\\[ZXXWVVTTRQQPONMLKKJIHGFEDCBAA??>=<<:99876443221/.-,,**)('&%$$#"�����������������������~}|{zyywvvutsrrqoommlkjihhffedcba`_^]\\ZZXXWVVUTSRQPONMLKKJIHGFEDCCBA@>>=<<:99876543311/..-,+*))''%$$#"!����������������������~}}{zyxxwvutsrrqpnnmlkjiiggfddbba`_^]]\[ZYXWVVTTSRQPPNMMLKJIHGFEDCBA@@?>=<;;:88765433200/.-,+**((&%%$#"!!��������������������~~}{zzxwwvuussqpponmlkjjhgffddcba`_^]][[ZYXXVUTTSRQPONNMKJJIHGFFDDBAA@?>=<<;:98765533210..-,+**(('&%###"!��������������������~}}{{zyxwvvutrqqoonmlkjihhgeedcba`_^^]\[ZYXWWVUSSRQPPONMLKJIHGGEECCAA@?>><;::9776544221//.-,+*))(&&$$#"!!�������������������~}}|{zyxwvuttsqpponmmkkiigffedcbba__^]\\ZYXWWUUSSSQPOONMLKJIHGFEDDCBAA@>><<;:88765533200/.--++*((&&%$$#! �������������������~}{{zywwvvussrqponnmkkjihgfeedcaa__^]\[ZYYWVVTTTRQPOOMMLKJIHHFEDDCBAA??=<<;:98765532210/.-,+**((&&%%#""! �����������������~~}{{zyxxwvusrrqponnmlkiihffeddcb``^^]\[ZZXXWVUTSSQPOONMLKKIHGFEEDCBA@??==<;:99866543210/.-,,+))('&%$##!!�����������������~}}|{zyxwwvttrrqponmlljjihgfedcbaa`_^]\[[YXXWVUTTRRQONNMLKJIHGFFDDCBBA?>><<;:99765543200/.--,**)('&%$##"! ���������������~}||{zyxwwvutrrqponmlkjjihgffddbaa`_^]\[[ZYXWVUTTRRQOOMMLLKIIHFFEDDBA@@?==<;:997654422100/-,++*)(('%$##"! ��������������~}|{zyxxvvutsrqpoonllkjihggfecbba`_^]][ZZYXWVVUSSRQPONMLLKIIGGFEDDCBA??>=<;::87665432100.--++*)('&%$$"" ��������������~~}|{{yxxwuutsrqqoonmljjihggfddcba`_^^\[ZYYXWVVUTSQQPONMLKKIHHGFEEDCAA@>>=<;::8776432210/.--,+))('&%%$#"! �������������}}||zzxwvuutsrqpoonlkkjihgffecbba`__]][[ZYXWWVTTRRQPOOMLLJJIGGFFDCBBA@?>=<;::88765432100..-++*)('&%$$#"! ������������~}|{zzxwwvutssqqpnnmlkjihggfeccba`_^^]\[ZYXWVUUTRRPOONMLKJJIHGFFDCBBA@?>=<;:988765433110/.-,+*)('&%%$#"" �����������~}|{zyyxwuutsrrpponmlkjjhhffedcba``_^\[[ZYXWVVTTRQQPONNLLJJIHGFEEDBBA@?>=<;;:88655432210/.-,+*)('&&%$#"! ����������~}|{zyxwuvttrqqpnmmlkjjhggfedcba`_^^]\[ZYYXVUUTRRQPPNMLKJIIHHFFEDBAA@?>><<::8876543321//.-,+*))''%%$#"!! ���������~}||{zywwvvtsrqqoonmlkjiihgfedcba``_]]\[ZYXWWVTTSQQPPNMMKKIIHGFEECCAA@?>=<;:988765433200/--,+*)(''&%$#"! ��������~~||zzyxwvutssqqponnllkjhhgfedcbaa__^]\[[YXXWUTTSRQPOONMLKJIHGFEECCBA@?>><<:998765432210/.--+*)(('&%$##! �������~}}|zyyxxvuutsrqponmlkjjigffeddcb`_^]]\[[YYWVVTTSRRPONNMKJJIHHFEECCBA@?>><<;:98765533210/.-,,+*(('&%$##!! ����������������������������������������������������������������������������������������������������������������������������~}|���������������������������������������������������������������������������������������������������������������������������~}}{��������������������������������������������������������������������������������������������������������������������������~}|{z�������������������������������������������������������������������������������������������������������������������������}|{{z������������������������������������������������������������������������������������������������������������������������~}|{zzy�����������������������������������������������������������������������������������������������������������������������~}}|{zyx����������������������������������������������������������������������������������������������������������������������~}}|{zyxw���������������������������������������������������������������������������������������������������������������������~}}|{zyywv���������������������������������������������������������������������������������������������������������������������}}|{zyxwvv��������������������������������������������������������������������������������������������������������������������~}{{zyxwvuu������������������������������������������������������������������������������������������������������������������~}|{zyxxwvtt�����������������������������������������������������������������������������������������������������������������~}|{zyxwwvuss�����������������������������������������������������������������������������������������������������������������~}|{zyywvvutsr���������������������������������������������������������������������������������������������������������������~}||zyyxwvutsrr��������������������������������������������������������������������������������������������������������������~~}|{{yxxwvutssrq��������������������������������������������������������������������������������������������������������������~}|{zzxxwvuussqqp�������������������������������������������������������������������������������������������������������������}|{zzxxwvutssqqoo������������������������������������������������������������������������������������������������������������~~||{zyxwvuutrrqpnn�����������������������������������������������������������������������������������������������������������~}|{{zyxwvuttrrqponm�����������������������������������������������������������������������������������������������������������~}}|{zyxwvvttsqpponml���������������������������������������������������������������������������������������������������������~~}|{zyxwvutssrqponmmk���������������������������������������������������������������������������������������������������������~~}|{zyyxwvtsrrqppnmmlk�������������������������������������������������������������������������������������������������������~}|{zyywwuutsrqponmmlkj������������������������������������������������������������������������������������������������������~}|{{yxxvuutsrqppnmllkji������������������������������������������������������������������������������������������������������~}|{zzyxvuutsrqqpnmlkkjjh�����������������������������������������������������������������������������������������������������~}|{{zyxvvutsrrqpnnmlkjihg����������������������������������������������������������������������������������������������������~~|{zzyxwvutssrqponmlkjihgf���������������������������������������������������������������������������������������������������~}|{zzxxvvutsrqpoonmlkjihggf��������������������������������������������������������������������������������������������������~}|{{yxxwvuttrqqoonmlkjiiggfe�������������������������������������������������������������������������������������������������}||{zyxwvuutsrqoonmmkjihggeed�������������������������������������������������������������������������������������������������}}|zzyxwvvtsrqqponmlljiiggfedc�����������������������������������������������������������������������������������������������~~}{{zyxwvvussrqpoommkjiiggfeecc�����������������������������������������������������������������������������������������������}|{{zyxwwvutsqqpoomlkkiiggffdcba���������������������������������������������������������������������������������������������~}|{zyxwvutssrqpoonlljjihgfeeccba��������������������������������������������������������������������������������������������~~}|{zyxxvuttsrqqonnlljjihgffedbba`��������������������������������������������������������������������������������������������~}|{zyxwvvussrqppnnllkjihgfedccba`_������s2 %T�����4j��������� ��������������������� a��������FC�������P$ 3`zyxutsrb :mmP 'Oeedca__���ΰ�����������rq��������������������]�����wp����tyxwtsr` ?mlJedcba^]������Ľ�s+��������t������))�����������������������:�����d��b��KmzwfIxwuss^ Enml We_Ddcbb`^]���t ������������������![�����'#����������������������������P������K��Ns}||zyxwvvur] Jnmlkaggfeccbb`_]\���1�������������������{'����LjkK���������������������������"\������V ��!P}|{{zxxwvut[Nnmllj 5^fedcbaa`^\[������������������ ���� �� ����������������������91���� +~������w +�� s|{{zyxwvuutRnmlkkj@"?aa`_^^[Z���������������������m@��Ki������������������ ��������������{|zzyxwvutss +\mlljjihMW__^]ZY��� ������������������ ���&����%������������������d����� +}������v +~ q{zyxwvuussrM YljihhgfedS; "_^]\ ZX���.�����������������y'�����������������������cq����!Y������U~} NyyxwvvttsqqnHVihhgfeedcbS^]][XX���l*����������������Y��GE��������������������T����L�����{H~}JoxwwuutsrqpmmDRggffddbb`Y]\[ZYXXW��ǻ,����r��������q��� +������ ���������������������R����`}|_y}|xGitpbFqpomkj@Pfe:S^_M][ZZYXWV���šp�������h0������.c��������������h{���oj}|{zlponlkji<Ke@\[ZYVU����÷d' K������3h����"q������m ���������������.+����{@>u}|{zyxuJ +/Woomkjihg8HP+ +H[[ZYXUU�������������������������������������������������������������������������������~}|{zyywwvutsrqppnmmlkjjhgffddcba`__]\[[ZYXWVUUS������������������������������������������������������������������������������~}||zyywwvuttrqqonnmlkjihhgfeccbba_^^][[ZYXWVUTSS�����������������������������������������������������������������������������~}|{{zxxwvutsrrqonnmlljjigffedcba`__^\\[ZYXXVVUTSQ����������������������������������������������������������������������������~}|{zzyxwvutsrrqponmlkjiigffedcbb`__]]\[ZYXWVVUSSRR���������������������������������������������������������������������������~}}{zzyxwvvttsrqponmlkkiihgeeddcaa`_]]\[ZYYXVVUTSRQP���������������������������������������������������������������������������}|{{zxxwvutsrqpponmlkjiihgeedcbaa`_^]\[[YXWWUUTSRQPO�������������������������������������������������������������������������~}|{zyxwvutsrrqponmlkkiiggfedccba__]]\[ZZYWWVUTSRRPOO������������������������������������������������������������������������~}}|{zyxxvuttsrqponmmlkiihgfeecbba`_^^\[ZYXXWVUTSRQQPOM�����������������������������������������������������������������������~||{zyxwvvutsrqponmllkjhhgfedccb``_^]\[ZZYWWVUTSRQQOONM�����������������������������������������������������������������������~~||{zzxwvvttrrqppnnmlkiihggeddbba`_^]\[[YXXWVVUSRRPPONML���������������������������������������������������������������������~}|{zyywwuussrqponnllkjihgffeccba`_^]\[[ZYXWVVUTSRPPONMLK���������������������������������������������������������������������~~}|{zyxxvvutsrrponmmlkjihgffedcba`_^^\\[ZYXWVVUSSRPPONMLLJ�������������������������������������������������������������������~}|{zyxxwuutssqpoonmlkjihgfedccba`_^^\\[ZYXWVUUTSRPOONMLKKJ������������������������������������������������������������������~~}||zyxwwvutsrqppomllkjiigffecbbb`__]][[ZYXWVVTTSRQPONMLLJJH�����������������������������������������������������������������~}||zyxwwvutssqpponmlkjihggfedcca``^]\\[ZYXWWUTTSQQQONNLKKIIH�����������������������������������������������������������������~}}{{yyxwvutsrrqonnmlljjiggfedcbb``_^]\[ZYXXWVUSSRQPONNMLKJIHG����������������������������������������������������������������~}}{{zxxwvvttsqqpnnmlkkjihgeedcbba__^]\[ZYYWVVUTSRQPPNMLLKJIHGG���������������������������������������������������������������~}}{zzyxwvuttrqqpoomlkkiihffedccb``_^]\\[ZYWVVUTSRQPPONMLKJIHHFE��������������������������������������������������������������}}|{zyxwvuutsrpoonmlkkiiggfedcbba__^]\\ZYXXWVUTSRQPONNMLKJIHGFFE�������������������������������������������������������������~}}|{zyxwvuutsrpponmllkjihgfeecbb`__^]][ZZXXWVUTSRRQPNMMLKJJIHFFED������������������������������������������������������������~~}{{zyxwwuutsrqpoonlkkjhhgfeedbba`_^]\[ZZXWWVUTSRQQOONMLKJIHGFFEDC�����������������������������������������������������������~~}|{zyxwwuttsrqqoonlljjihgfeedcba`_^^\[[ZYXWVVUSSRQONNMLKJJIHFEEDDB����������������������������������������������������������}}|{zyxwwvussrqpoommkkjihggfeccba`_^]\\ZZYXWVUTSRRQPONMLKJIIHGFEDCBA����������������������������������������������������������}}|{{yxxwuttsrqpoommkkjihgffedca``_^]\\[YYXWVUTSSRPPONNLLJIIHGFEDDCB@���������������������������������������������������������~}|{zzxxvuttsrqqoommljjihhgfecbba`_^]\\[YXXWVUUTRRQPOOMLKKJHHFFFDCBB@@��������������������������������������������������������~~}|{zyywwvttsrrponmmlkjjhhgeedbba`_^]\\ZZYXWVUTTSRQPONMMKKJIHGFFDCBBA@?�������������������������������������������������������~}|{zzyxvuuusrqqoonllkjihggfedcba``^]]\[ZYYWVVTSSRQPOONMKKJIHGGEDCCBA@?>�����������������������������������������������������~}|{zyxxwvuussqqponmlkjiihgfedcba``^]]\[ZYYXWUUTSRQPPONMLKJIHGFEEDBBA??>=�����������������������������������������������������~}}{zzyxwvuutrrqpnmmlkjjihfeedcbb``^^]\[ZZXWWUUTSRQPOONMLJJIHGFEDDCBA@?>==����������������������������������������������������~}|{{zywwvutsrrqpnnmllkiihgeedccba__]]\[[YXWVUTTSRQPONNMLKJJHGGEECCBA@?>==<���������������������������������������������������~}}{{zyxwvuusrrpponmlkjjhhgfedcbba`_^]\[ZYYXWVUTSRQPPOMMLKJIHGFFEDCBA@?>==;;��������������������������������������������������~||{zyxwwvutsrpponmmljjhggfeddcb`__^]\[ZZYWVUUTSRQQPONMLKJJIGGFECBBA@@>=<;::�������������������������������������������������~~||{zyxwvuussrqponmlkjjihgfedccb``_^]\[ZZXXWVUTTSRQONNMLKJIHGFEEDCBBA@>=<;;:9�������������������������������������������������~}|{zyywvuttsrqponmmlkjhhgffddcba__^^\[ZYXXWVUTSRRPPONMLKJJHHGFEDCBB@??>=<;:98�����������������������������������������������~}|{zyxxwuttsrqponnmlkjihhffedbb``__]\[[ZYWWVUUTSRPPONMLKJIIHGFEDCCA@??==<;:988�����������������������������������������������~}|{{yywvuussrqponnllkjihggfedcba`_^]\\ZZYXWVUTTRRQPONMLLJJHHGFEECBB@@>>=<;:9876���������������������������������������������~~}|{zyyxvvutsrqpoonmljjihggeddcaa``^]\\[ZXXWVUUSSRQPONMLKKJIHGFEDCBBA@>==<<::9776���������������������������������������������~}|{zyxxwuutsrrqoonmlkjihhgfeccba`_^^][[ZYXWWUUSSRQPONMLLKJIHGFEEDBAA@?>=<;;:87665�������������������������������������������~}}|{zyxwvutsrrqoonmlkjihggeedcba`__]][[ZYXXWVUTRRQPPNMMLKJIHGFEDCCAA@?>=<<;:987554�������������������������������������������~}|{zyxxwvutsrqpponlllkjigfeedcba`__^][[ZYXXWVUSSRQPPOMLLJJIHGFEECCA@@?>=<;:99876553������������������������������������������~}}|{zyxwvuussqqponmlkkjhhgfedcba`_^^]\[ZYXWVUUTSRQPPNNMKJJHHGFEEDCBA@?>=<;;:98765442�����������������������������������������~}||{yyxwvvtsrrpponmlljiiggfedcba``_]]\[ZYXXWVUTSRRPPNNMKKJIHGFFECCBA@??><<;:987654432�����������������������������������������}}|{zyxwwuusrrqponnlkkjihgfeddbaa__^]\[ZZYWWVUTSRQPPONMLKJIHHFEDDCBB@@>><;;:9877554320����������������������������������������~~||{zyxwwvutsrqpoommkkiihgfedcba``^^]\[ZZXWVVUTSRQQPONMLKJJHGGEEDCBA@@>>=<;:98766433210��������������������������������������}}|{zyxwvvutsrqponnllkiihgfedcbba`_^]\[ZYYWWVUTSRQQPNMLLLKJIHGEEDCBAA?>==<;:98876443210/��������������������������������������~}|{zyxwvuutsrqpoomllkjhhhffedcaa`_^]\\ZZXXWVUUSRQQOOMMLLJJIHGEEDCBA@??>=<;:98765543210/.�������������������������������������~~}|{zyxxvuutsrqqponmlkjihgfeedcba`_^]][[ZYWWVUTSSQQPONMLKKIIGGFEDCCB@??>=<;:98766542210/.-�����������������������������������~||{zyxwwutssrqponmmlkjihggfdcbba`_^]\[[YYXWWUTSRRQPNNMLLJIHHGFEDDCBA?>==<;;:97764432100.--�����������������������������������~}|{zyyxvvutsrqpponmlkjihgffddcaa`_^]][ZZYXWVVTSSRQPONMLKKIIHGFEDCBBA@>==<;::88665432110..-,����������������������������������~}|{{zxwwvutsrqqpnmmlkjiigffedbbaa_^]]\[ZYXWVUUTSRQPOOMMKJJIHGFFECBA@@?>==;;998765432100/--,+���������������������������������~~}||zzxxwvutsrrpponmlkjjhhfeeccca`__]]\[ZYYWVVUTRRQPONMLKJJHHGFEDDCBA@?>=<;::98665433100/.-,+*��������������������������������~}||{yyxwvutssrqpnnmlljiihffedcbaa_^^]\[ZYYXVVUSSRQPONMMLKJIHGFEDCBAA@?>==<:998765432100/.--+*)�������������������������������}}{{zyxwvuttrqqpommlkjjhggfedcba`__]]\[[YYWVUUSSRQPONNLLJJIHGFFDCCBA@?>==<::98765532210/.-,+**(������������������������������~~|{zzyxwvvutrrqponnlkjjihffedcbaa__^]\\ZYXWVVTSSRQPONNLKKJIHGFEEDBBA@??>=<;998765432100/.-,+**)(������������������������������~~||{zyxwvvtsrrqponnlkjihhgfedcbba__^]\\ZYYXWUUTSRQPPOMLLKJIIGFFEDCBAA?>=<;;:98865432210/.-,,*))('����������������������������~}||{zyxwwutssrqponmmlkjihgfeddcba`^^]\[ZYYXVVUTSRRPONMMLKJIHGGFEDCBA@?>>=<;:99766432200/.--++))('&���������������������������}|{{zyxwvvutrrpponnlkjjihgfedccba__^]][ZYXWWVUTSRQPOONMLKKIHGFEEDCBA@??><<;:99776443210//.-++))('&%��������������������������~}}|zzyxwvuutsrqponmmkjjihhfeecbaa`__]\\ZYXXWVUTSSQPONNMLKJJIGFFEDDBAA@?>=;;:99776433210/.-,++*))'&&%�������������������������~~}|{zyyxvuussrqponmllkjihggedccba`_^]\\[ZYWWVVUSRRPPONMLKJIHGGFEDCBA@?>=<<;;:87765432100..,++*))'&%$$������������������������~~}|{zzywvuutsrqqonnllkjihhgfddcba``^^\\ZYYXWVVTTSRPPONMLKJJIHFFEDCBBA@?><<;:987765432100..-,**)(('&$##������������������������~~}|{zyxwwvttsrqponmmlkjihgfeeccba`_^]\[[YYXWWUUTSQQPONMLKJJHHGFEDCCA@??>=<;;998754432100..-,+*)('&%$#""�����������������������~}|{zyywwvuttrqppnnmlkjihgffedcba`_^]]\[YYXWVUUTSRQPONMMKJJIHGFEDCBB@@?>=<;:997765442110/.-,+*))''&%$#"!���������������������~}||zyywvuuttrqqponmlkjihhgeeccba`_^]\[[ZYXWVVUTRRPPPNNLKKJIHGFEEDBBA@?>=<<::87765442100.--,+**)''%%$#"!!���������������������~}|{zzyxwvuttrqpponllkjiigffedcbaa__^]\[ZYXWVUUTSRQPPNNLLJJIHGFFEDCBA@?>==<::97765442110/.--++))('&%$#"! ��������������������~}|{{zyxwvutssrqoonmlkkiihffddcbaa`_^][[ZYXWWUUTSRQQONNMLKJIHGGEDCCBA??>><;;:8876653210//.-,+*))''&%%##! �������������������}}{zyyxwvvtssrqponmllkihggfedcbb``_^]\[ZYYWWVUTSRQPPNMMKKJIHGFFECCBA@??>=<;:8776554221//.--+**)('%%$$#!! ������������������~}||{zyxwvuttsrqpoomlkkiihgeedcba``_^]\[ZYXXWUUTSRRPPNNMLKJIHGFEDDCBA@?>==<;:9876643321//.--,+*(('&%$#"!!������������������}}|{yyxwvuusrqqpoomlkkjhhgfedcbaa__]]\[[YYXWVUTSSQQONNLLKJJHGGEEDCBAA??=<<;:98865443210/.-,++*)('&%%#""! ����������������~~||{zyxwvuussrqponmlkjjihgfeddcaa`_^]\\ZZXWWVUTSRQQONNMLKJIHHGEDDBBA@?>==<;:98766443100/..,+**)('&%$#"" ���������������~~}|zzzyxwuutsrqponmlkkjihggeddbba__^^\[[ZYXWVUUSSQQOONMLKJIIGGFEDCCA@??>=<;:98776543210//-,,+*)(''&%$#!! ��������������~}|{zzxwvvttsrqppnnmlkjihgfeedbaa`__]][[ZYWWVUTTRQQOONMLLKIHGGFEDCBAA??==<;:99775542210/.-,,+*)((&&$$#"! �������������}}|{zyyxwvutrrqqonnmkkjihgfeecca``_^]\[ZZYXWVUTSSRQPNNMLLKIIHGFEDCBA@@>>=<;:98775533210//--++*)('&%%$#"! �������������~}|{zzxwvvutsrqqoonmkjjihggeddcba`_^]\[[ZYXWVVTSRRQPONMLKKJIHGFFDCBAA@>>=<;:997665432100.--,+*)(('%$##"! ������������~~}|{zyxxwuutsrqqonmllkjihgfeedcba``_^\\ZZYXWWVTTRRPPONMLLKJIHGFEDCCAA??>=<<:98775543321//.,,+*)((&&%$#"! �����������~}|{zyyxwvutssqqponmlkjjigffedcba``_^\\[ZYXWVUUTRQQPONNLLKJIHGFEDCBBA@?>=<;::8776544210//.-,++*)'&%%$#"!!����������~}|{{zxxvvutsrqpponmmkjihhgfedcbb`__]]\ZZYXXWUTSSRQPOOMMLKJIHGFEDCBAA@?>==;:99876543220//.,,++)(''&%$#"! ���������~~}|{yyxwvvutsrpponmlkjiihgeedcba``_^]\[ZZXXVVUSSRQPPONLKJJIHGGFDCCBA@?>><;::98765532100/.-,+*)(('&%$#"!!��������}}|zzywwvutsrrpoonmlljiiggfedcbba`^^]\[ZZXWWVUTSRRPOONMLKJIHGGEDDCBA@?>=<;:99776553211//.-,+**)('&%$$"! �������~}}{{yyxwwuttrrqponmllkjhhgfeeccba__^]\[[ZYXVVUTSRRPPONMLKJIHGGFEDCAA@?>><;::98775443200/..,,*)(('&%$##!! ���������������������������������������������������������������������������������������������������������������������������~}}��������������������������������������������������������������������������������������������������������������������������~}}{��������������������������������������������������������������������������������������������������������������������������~}|{z�������������������������������������������������������������������������������������������������������������������������~}||{z������������������������������������������������������������������������������������������������������������������������~~||{zy�����������������������������������������������������������������������������������������������������������������������}}{{zxx����������������������������������������������������������������������������������������������������������������������~|{zzyxw���������������������������������������������������������������������������������������������������������������������}|{{zxywv��������������������������������������������������������������������������������������������������������������������~}{zzyxwvv�������������������������������������������������������������������������������������������������������������������~~}|{zyxwvvt�������������������������������������������������������������������������������������������������������������������~~||{zyxxwuus�����������������������������������������������������������������������������������������������������������������~}|{{yywvvuts�����������������������������������������������������������������������������������������������������������������~}|{zyyxwvttsr����������������������������������������������������������������������������������������������������������������~}|{zzywvvutsrq���������������������������������������������������������������������������������������������������������������~~}|{zyyxwvutsrrq�������������������������������������������������������������������������������������������������������������~}|{zyxxwvuttrqpo�������������������������������������������������������������������������������������������������������������~~||{zywwvutsrrppo������������������������������������������������������������������������������������������������������������~~}|zzyxwvuussqqpon�����������������������������������������������������������������������������������������������������������~~|{{zyxwwvttrrpoonn����������������������������������������������������������������������������������������������������������~~||{zyxwwuttsrqponmm���������������������������������������������������������������������������������������������������������~}||{zyxwvuussqqponmll��������������������������������������������������������������������������������������������������������}||{zyxwwuttrrqponmlkj�������������������������������������������������������������������������������������������������������~}}|{zyxwwuussrqponnmlkj�������������������������������������������������������������������������������������������������������}}|{zyxxwuutsrqpoonlkjji������������������������������������������������������������������������������������������������������~~||{zyywwvutsrqpoomlkjjih�����������������������������������������������������������������������������������������������������~~}||zzxwvvutsrqpponmlkjihh����������������������������������������������������������������������������������������������������~~}|{{yyxvuutsrqpoommlkjiigg���������������������������������������������������������������������������������������������������~}|{{yyxwvvtsrqqpnmllkkiihgf��������������������������������������������������������������������������������������������������~}}{zyxxwvutssqqponmlkjihggfd�������������������������������������������������������������������������������������������������~}|{zzyxwvutsrrqponmlkkiihfeed������������������������������������������������������������������������������������������������~~}{{zyxwvuusrqqponmllkiihgfedc�����������������������������������������������������������������������������������������������~}}{{yyxwvuussrqponnlljjihgfedcc����������������������������������������������������������������������������������������������~}}|{zyxwwvttsqqponmmlkjihgfedccb����������������������������������������������������������������������������������������������~~}|{zyxwvvttsrqponmmlkiihggedccba���������������������������������������������������������������������������������������������~||{zyywvvutsrqpoonmkkjihggeeccba`��������������������������������������������������������������������������������������������~~}|{zzyxwuutsrrpoommkkiihggfeccaa`_������t2 %T�����4j��������� ��������������������� a��������FC������Q$ 3`yxwussra :mmP 'Ofdcbb`^���Ͱ�����������rq��������������������^�����wp����tyxvtsr` ?nlJedcba^^������Ľ�s+��������u������)*�����������������������:�����d��c��KmzwfIxvvsr^ Enml Wf^Ddcba`]\���s ������������������![�����'#����������������������������P������J��Ms~}{{zyxwvur] Inmlkbhgfedcba``\\���1�������������������{'����LjkK���������������������������"\������W ��!P~|{{yywwvut\Nnmlkj 5_fedcba`_^\[������������������ ���� �� ����������������������91���� +~������w +�� +r|{{zyxwvuttRnmmlki@"?`aa__][Z���������������������m@��Kj������������������ ��������������z{zzxxwvvttr +\mlkjiihMX`^^]ZY��� ������������������ ���&����%������������������e����� +|������v +�~ qzzyxwvutssqM YkkiihgfedS; "^^]\ ZY���.�����������������y'�����������������������bp����!Y������U ~} NzyxwvvussrqnHViihgfeedbbT^]\[XX���l*����������������Y��GE��������������������S����M�����|H}|JoxxwuttsrqpmmDRhgfeeccbaY^]\[YXXW��Ƽ,����r��������q��� +������ ���������������������Q����`}}_y}|xGhsqbFqqolkk@Ofe:S__M\\ZZYXWV���šo�������h0������.c��������������h{���oi||{zlpoolkji<Ke?[ZZYWU����ķd' +J������3h����"q������m ���������������.,����{@>v}||zyxuJ +/Woonkjiig8IP+ +H\[ZYXUU�������������������������������������������������������������������������������}}|{{yywvvutsrrqoonmlkjihgffedcba`_^^]\[ZYXWVVTT�����������������������������������������������������������������������������~}|{{yyxwvutsrqpoonllkkihhgfedcba`__^\\[ZYYWVVUTR�����������������������������������������������������������������������������~}|{{yywvvutsrqpponmlkjihgffddcba`__^\[[ZYXWVUUTSR����������������������������������������������������������������������������~}||zyyxwvuusrrpoonmmkjjhggfedcbaa__^]\[ZZXWVVUTSRQ���������������������������������������������������������������������������~}||zyyxwvuttrrqoonmlkkihggfeddba`__^]\[ZYXWVUUTRRQP��������������������������������������������������������������������������~~}{{zyxwvuutrqqponmlljiihgfedcbb`_^]]\[ZYXWVVUTSRQQP�������������������������������������������������������������������������~~}|{zyxwvutssqqponmlkjjiggfedccba__^]\[ZYYXWVUTSSQQPN������������������������������������������������������������������������~}|{zyxwvuussrqponnmlkiihggfddbaa`_^]\[ZYYXVVUTSRRQPON�����������������������������������������������������������������������~}}|zzyxxvvutsrqpoomlkkjiggfeedbaa__^]\[ZZXXVVUUTRRQPONM�����������������������������������������������������������������������~~||{zyxwwuutrrqppnmlkjiihgfedcbba`_^]\[[ZYXVVVTSSQPPONML���������������������������������������������������������������������~}}|{zyxxvvttsrqponnmlkiihggfedbb``_^]][[ZYXWVVUSSQPPONMLK��������������������������������������������������������������������~~}||zyyxvvutsrqppnnllkjihgfeddcba`__]\\[YYXXVUTSRQQPONMLKK�������������������������������������������������������������������}}||zyyxwvutsrqppnnmlkjihgffedcba``_^\\[ZYXWVVUTSRPPONNLLKJ�������������������������������������������������������������������~~}|{{zxxwvutsrrpoonmkkjihhffddcba`_^]][[ZYXWVUUTSQQPONMMKJJI������������������������������������������������������������������~}|{{zyxwuutssqqoonmlkjiigfedccbaa`^]]\[ZZYWWUTTSRQPPNMLLJJHH�����������������������������������������������������������������~}|{{yyxwvutssqppnnmmkjjiggfedcca``^]\\[ZYYWWUTTSRQQONNMKKJIHG����������������������������������������������������������������~}|{{yyxwvutssqqoonmlkjjhggfedcbaa_^^]\[ZYXWWUUTSRQPOONMKKJIIGG���������������������������������������������������������������~}|{{zyxwvvtssrqponnlkjihhgfedcbaa`^^]\[ZYYWVVTTSRQQOOMMLKJIIGGF��������������������������������������������������������������~}||zyxxwvuusrqqponmlkkihhgfedccba_^^]\\[YXWVVUTSRQQOOMLLKJJIGFFE�������������������������������������������������������������}||{zxxwvuussrqponnlkkjihgfeddbba`_^]\[ZYXXWVUTSRQPPONMLKJJIGGFED������������������������������������������������������������}}|{zyxwwuttsrqponnllkihhgfedcca``_^]\[ZYYXVVUTSRQPPONMLKJJIHGEDDC������������������������������������������������������������~~}|{{yxwwuutrrqponmmlkjihgfeddcba`__]\[ZZXXWVUUSRRPPONMLLJIHGFEEDCB�����������������������������������������������������������~}|{zyxxvvussrqpoonmlkjihgffeccba`_^]\[ZZYXWVUTSSRQOONMLKJIIHFFEDCBB���������������������������������������������������������~}|{{yyxwvutsrqppnnlkkjihhffddcba`_^^\[[ZYXWWVTTSQQONNMLLKIIGGFEDCCA@��������������������������������������������������������~}||zyywwvutsrrqoommlkjihgffedcba`_^^]\[ZYXWVUTSSRQOONMLKJJIHGFEDDCA@@��������������������������������������������������������~}||zzywvvutsrrqponmkkjjiggeddbbaa`^^]\[YYXWWUUTRRQPONMMKJJIGGFEDDBA@@?�������������������������������������������������������~}|{zzxxwvutsrqpoonmlljjihffddcba``_^][[ZYXXVUTTSRQPONMLKKIIHGFEEDCBA@?>������������������������������������������������������~}||zzxxwvuttrqqonnmlkjjhhgfddcbaa__^]\[ZYXWVVUTSRQPONNLKKIIHGFEEDCBA@?>=�����������������������������������������������������~}||{yxxwvutsrrqponmlkkiihffedcbb`__]]\[[YXXVVUSSRRPOONMKKJIHGFEEDBBA@?>><����������������������������������������������������~~|{zzyxwvuutrqqponmlljjhggfeecbba`^]]\\[ZYWVVUTSRQPOONMLKJIHGFEEDCBA@?>>=;���������������������������������������������������~}}|{yxxwvuusrrqponmlkkjhgffedccaa`_^]\[ZYYWWUUTSRQPPNMLLKJJHGFEEDCAA@@>=<<:��������������������������������������������������~~}|{zyxwvuutrqqponmlkjjihgfeecbba__^]\\ZZXXWUUTSRQPONNMLKJIHGGEEDCBA@@>>=<;:�������������������������������������������������~}{zzyxwvuutsqqponnmkkiihgfedcbba`_^]\[[YXXVVUTSRRPPONMLKKIHGFEDDCCA@??>=<;:9�������������������������������������������������~}}{{zyyxvvussrqppnmlkjjihgfeeccba`_^]\[[ZYXVVUTSRRPPOMMLKKJIHFFEDCBA@??==<;:98�����������������������������������������������}||{{zxwwvutsrqppnnmlkjihgfeedba```^]\\[ZYXWVUTTRQQOONMLLJJIHGFEDCBB@@>=<<;:988�����������������������������������������������}}|{zyxxvvussrqppnmmlkjihgfeddcba`_^^][ZZYXWVUTTSRQPONMLKJIHHGFEDDBAA??==<;:9976���������������������������������������������~}|{zzxxwuttsrrpoonmlkjihhffdccba`_^]\[ZZYXWWUUSSRQPONMLLKIHHGFEDCCB@@?==<;:99876���������������������������������������������~}||{yywvvutsrqponnmlkjihhffdccba`_^^\\[ZXXXVUUTRRQPONNLKJJHHGFEDCBAA@?>=<;;:87765�������������������������������������������~}|{zzxxwvutsrrqonnmlkjjhhfeedccaa_^^][[ZYXXWVUTSQPPONMMLJJIGGFEDCBAA@?>=<;::986654�������������������������������������������~}||{zyxwvuttrrqpnnmlljjhhgeedcbaa`_]][[ZYXWWUUSSRQPONMMKJJIHGFEDCBAA@?>==<::8876554������������������������������������������~~|{zyyxwvutssqqonnmlljjigfeedccaa`^^\\[ZYXWWVUTSRQPOOMLKJJIHGFEEDCBA@?>==;:988765432�����������������������������������������~~}{{zyxwvutsrqpponmmljiiggfedccaa`^^]\[ZYYWWUUSSRQPOONLLKJIHGFEECCBA@?>=<;;:987764322����������������������������������������}}{{zyxwvvusrrqoonmlljiihgfeddba``_^]\[ZZYXWVUTSRRQONNLLKJIHHGEEDCBA@?>>=<;99876553210���������������������������������������~~|{{zyxwvvutsrppoonmkkjihggeecca``^^]\[[YXXVUUTSRQPPONLLKJIHGFEECCBA@??>=<;:98765533210���������������������������������������}}|{zyxwvvutsqqponmllkjihgfeddbb``_^]\[ZYYXWVUTSRQPPNNMLKKJHGFEEDCBB@?>=<<;:98776533210/��������������������������������������~}|{zzxwwuttrrqqonmmlkjihgfeeccba__^]\\ZZYXWVUUSRQPPNNMLKJIHHGFEDCBAA?>>=<;:98776543211//������������������������������������~}||{zyywwvutsrqponnmlkjihgffedcba`__]\[[ZYXWVUTTSRQPNNMMKKIHGGEEDCBAA?>>=<;:987655432100.-�����������������������������������~}|{zzxxwvutsrqppnnmkkjihgfedccba`__]\[[ZYXWVUTSSQQPONNMKJIIGFFEDCBB@@?>=<;:987765432200.-,����������������������������������~}|{{yxwwvutsrqqonnmlkjihggeddbbaa_^^\\[ZYXWWVTTSQQPONMLKJJHHFFEDCCBA@>>=<;:98866543211/.--,���������������������������������~}}{zyxwwvttsrrqoonllkjihgffeccba``_^][[YYYXVVUTSRQOONMLKJJIHGFEDCBB@@?>=<;;988765443100/--,+��������������������������������~}|{zyxwwvuttrrqoonmlkjiihgfedcbba_^]]\[ZYXWWVUSSRQPONNLKKJHHGFEDDCBA??>=<;:998665432100/.-,+*��������������������������������~}|{{yywwvutsrqpponmlkjihhfeedcbba`_^][[ZYXWVUTSSRQPONMMKJIIHGFEDDBBA@?>=<<;:88765533200/--,+**�������������������������������~}|{zyyxwvutsrqpoonmmkjiihgfedcbb`__^]\[ZYXXVVTTSRQPONNMKKJIHGFEDCCBA@?>=<<:988765432210..-,,+*(������������������������������~}}|{yyxwvutsrrqponmlkkihhfeedccaa__^]\[ZYXXVVUSSRQPONMLLKJIHGGFEDBBA@?>>=;;:98765533100/..,,**)(�����������������������������~~||{zyxwwvttsrqpoommkjiihffeddbaa`_]]\[ZYXXWUUTSRQQOONMLJJIHHFFEDCBA@@?=<;;:98765543200/.--++*)('����������������������������~~}|{zyxwvvtsrqpponmlkkiihgffdcbba`_^]\[[YXWVUUTSSQQPOMMLKJIHHFFEDCBB@@>==<::98765543210/.--,*))(''���������������������������~~||{zyxwvuutsrpponmlljjihgfeedcaa__^]\[[YXXWVTTSSQQPONMLKJIHHFFEDCBA@@>=<<;:99765542200/..,++*)('&%���������������������������~~}|{zyywwuttrrqponmmkjjihggeddcba`_^]][[YYXWVUTSSRPOOMMLKKJIGFFEDCBAA?>==<;:99766543210/.-,,+*)('&%$��������������������������~}|{zyyxwvutsrqponnmkjjihgfeddcba``^^][[ZYXWVUTSRQQPOMMLKJIIGFFEDCBA@??=<<;:98765543210/.--++*)(''%%$������������������������}||{zyxwwvutsrqppnmllkjihhffdccba`_^^\\ZZYXWWUTSSQQPONNMKJJIHFFEDCBAA@?>=<;:988764432110.-,,+*)(''&%$#������������������������~~}|{{zyxwvutsrqppomlljjihgfeedcbaa__]\\[ZYXWVUTSRQQPONMLKJJIHGFEEDBBA@?>=<<:997765433110..-++*)(''&$##"�����������������������~}||zyxxwvutssqqoommkkjihhffedcbaa_^]\\ZYYXWWUTTSRQPONMMKKJHGGFEDCBB@@?>=<;::9876543210/.--,+*))'&&%$#"!����������������������~}}|zzyxvvutsrqpoonmllkjigfeedbbaa_^^]\[ZYXWWVTTSRQPONMMKKJIHGGEDCCAA??>==;:998765432100/.-,+*))''%%##"! ���������������������~}|{{yxxwvutssrpponmlkjihggfedcbaa`^^\\[ZYXXVUTTSRQPONNMLKJIHGFEDCBBA@?>=<;;98876543221//.-,+**((&&%$#"" ��������������������~}|{{zyxwvutssrppommlkjihhfeedcbba__^\\[ZYYWVVUSSRQQONNMKKIIHGFFDCCAA@?>><;;998765432100..-,+*))(&&%$#"!! �������������������~}|{{yyxwvutssrpponmlkjiiggfedcbba__^]\[ZZXWVUUTSRQPONNLLKJJHGFEDCCBA@@>=<;;:98765432200/.--+*)(('&%$#"! ������������������~}|{{zxxwvutsrrpponmlkjiihffedccaa__^]\[ZYYWWVUTSRQPONMMLKJIHGGEEDCBAA??>=;;:98765433110/.-,,+*)('&%$#"! ������������������~~||{yyxwvutssrqponmmkjiihgfeddca`__^]\[ZZXWWVTTSRQQPNNMLKJJHHGFECCBA@??>=<;:98775543210/.-,++)(('&&%$#"! ����������������}}|{zyxwwuttrrqponnlkjjihgfeddbb``_^]\[ZZYXVVUTSRQQONNMLKJIIGGFEDCBAA@>=<<;998776443200//--,+*)(''%$#"! ����������������~}|{zyxwvvutsqqpoommlkihhggfeccba`_^]\\ZZYXWVUUSRRQPONMLKKIHHFFEDCBB@??==<;:99866533210/..-,+*)('&&$$#!!��������������~}}|{zzyxvuttsrqponmmlkiihggeedcba`_^^\[ZZYXWVUTSSQPPONMLKJJIGFFEDCBB@?>>=<;:99775543211/..-++))('&%$##"! �������������~~}|{{yxwvuttsrqponmmljjihgfeddcba`_^^][[ZYXWWUTSSQQPONMLKJJHGGFEDCCAA@?==<;:988765432100.--,+*))(&%%$#"! ������������~~}|{zyxxwuttsrqponnmlkjiihffddcba`_^]]\ZZYXWWUTTRRQPONMMLKJIHFFEDCBAA@?><<;:99866543311//-,,+*))''%$$#"!!�����������}}|{{yyxwvutsrqponmllkjihggeddcba`_^^]\[ZYXXWUUTRQPPONMMKKJIHGFEEDBAA@?>=<;;:9876544211//.-,+*)('&&%#""! ����������~}|{zzxxwvuttsqqponmlkjihgffecbba`_^^]\[ZYXWVVTSSRQPONMMKKJIHGFEDDBA@@?>==;;98776443210/..,,+**)''&$##"! ����������~}|{zyxwwvutsrqpoonmlkjihhffddcba``^^]\[ZYXXWVTTSQQPPNMMKJJIHGFEDDBAA@?>=<<:99876544311//.,,+*)(('%$$#"! ���������~}|{{yyxwvutssqqpnnmlkjihhgeedcbba`_^]\[ZYXXVVTSSQQPOONMKKJIHGFEDDBAA@?>>=<;:98765433200/.-,+**)''&%$#""! ��������~}|{{zxxwvutsrrqponmmkjjiggfedcba``_^]\[ZYYWVUUTSRQPPOMLLKJIIGFEEDBBA@?>=<;;998776542210/..,,+))''%%%#"! �������~~|{{zyxwvuussrpponmlljiihgfeddbba`_^]\[ZYYXVVUTSRQPPOMMLKJJHGGEEDCBA@?>=<<;:98866533200/.--++))('&%$##!  \ No newline at end of file diff --git a/autotest/gdrivers/data/blx/s4103.blx b/autotest/gdrivers/data/blx/s4103.blx deleted file mode 100644 index c8a3fe4bca1f..000000000000 Binary files a/autotest/gdrivers/data/blx/s4103.blx and /dev/null differ diff --git a/autotest/gdrivers/data/blx/s4103.xlb b/autotest/gdrivers/data/blx/s4103.xlb deleted file mode 100644 index 86a9f49fa127..000000000000 Binary files a/autotest/gdrivers/data/blx/s4103.xlb and /dev/null differ diff --git a/autotest/gdrivers/data/elas/byte_elas.bin b/autotest/gdrivers/data/elas/byte_elas.bin deleted file mode 100644 index 873a904bfcfb..000000000000 Binary files a/autotest/gdrivers/data/elas/byte_elas.bin and /dev/null differ diff --git a/autotest/gdrivers/data/gsg/gsg_ascii.grd b/autotest/gdrivers/data/gsg/gsg_ascii.grd deleted file mode 100644 index 73e272d3a7a3..000000000000 --- a/autotest/gdrivers/data/gsg/gsg_ascii.grd +++ /dev/null @@ -1,65 +0,0 @@ -DSAA -20 20 -440750 441890 -3750150 3751290 -74 255 -181 181 156 148 156 156 156 181 132 148 -115 132 107 107 107 107 107 115 99 107 - -173 247 255 206 132 107 140 123 148 132 -165 165 148 140 132 123 107 123 107 123 - -156 181 140 173 123 132 99 115 123 74 -115 99 123 140 156 132 165 140 140 99 - -189 173 140 140 165 115 132 90 99 115 -90 99 99 107 99 132 99 107 132 132 - -165 148 156 123 107 107 107 115 140 99 -115 99 99 107 115 132 115 90 123 115 - -140 107 140 90 107 115 107 90 99 123 -115 115 115 123 123 148 115 148 99 132 - -148 132 132 107 123 99 99 115 99 132 -99 140 115 148 123 99 132 123 148 140 - -173 148 99 123 123 107 123 99 107 189 -173 107 115 115 107 99 140 107 173 140 - -123 123 123 107 140 123 123 115 115 90 -107 173 107 107 107 107 99 132 123 115 - -132 132 132 123 99 132 123 107 148 99 -115 123 140 173 123 107 123 123 123 107 - -140 140 99 140 99 115 123 107 132 107 -115 107 115 123 132 123 107 123 132 132 - -123 115 132 115 123 132 115 132 132 123 -123 132 99 115 99 123 132 115 115 107 - -148 123 148 115 148 123 140 123 107 115 -132 115 107 115 99 123 99 181 99 107 - -197 173 148 140 140 132 99 132 123 115 -140 132 132 99 132 123 132 173 123 115 - -189 173 173 148 148 115 148 123 107 132 -115 132 156 99 123 115 132 132 206 107 - -132 156 132 140 132 132 115 115 115 123 -148 123 165 123 132 107 107 132 156 123 - -148 132 123 123 115 132 132 123 115 123 -115 123 107 115 148 107 115 140 115 132 - -115 132 140 132 123 115 140 107 140 115 -132 123 107 132 132 115 115 107 115 107 - -115 132 107 123 148 115 165 115 140 107 -123 123 99 132 123 132 132 132 99 156 - -107 123 132 115 132 132 140 132 132 132 -107 132 107 132 132 107 123 115 156 148 - diff --git a/autotest/gdrivers/data/gsg/gsg_binary.grd b/autotest/gdrivers/data/gsg/gsg_binary.grd deleted file mode 100644 index 2deff0e48842..000000000000 Binary files a/autotest/gdrivers/data/gsg/gsg_binary.grd and /dev/null differ diff --git a/autotest/gdrivers/data/r/r_test.asc b/autotest/gdrivers/data/r/r_test.asc deleted file mode 100644 index b151184ec205..000000000000 --- a/autotest/gdrivers/data/r/r_test.asc +++ /dev/null @@ -1,64 +0,0 @@ -RDA2 -A -2 -133377 -131840 -1026 -1 -4105 -2 -gg -526 -40 -107 -123 -132 -115 -115 -132 -107 -123 -115 -132 -140 -132 -148 -132 -123 -123 -132 -156 -132 -140 -107 -123 -132 -115 -115 -132 -107 -123 -115 -132 -140 -132 -148 -132 -123 -123 -132 -156 -132 -140 -1026 -1 -4105 -3 -dim -13 -3 -4 -5 -2 -254 -254 diff --git a/autotest/gdrivers/data/r/r_test.rdb b/autotest/gdrivers/data/r/r_test.rdb deleted file mode 100644 index 177a2e9d8fca..000000000000 Binary files a/autotest/gdrivers/data/r/r_test.rdb and /dev/null differ diff --git a/autotest/gdrivers/data/rasterlite/byte.rasterlite b/autotest/gdrivers/data/rasterlite/byte.rasterlite deleted file mode 100644 index 127347c31bcd..000000000000 Binary files a/autotest/gdrivers/data/rasterlite/byte.rasterlite and /dev/null differ diff --git a/autotest/gdrivers/data/rasterlite/byte.rasterlite.sql b/autotest/gdrivers/data/rasterlite/byte.rasterlite.sql deleted file mode 100644 index 8e9a39ed6a0b..000000000000 --- a/autotest/gdrivers/data/rasterlite/byte.rasterlite.sql +++ /dev/null @@ -1,11 +0,0 @@ --- SQL RASTERLITE -CREATE TABLE spatial_ref_sys (srid INTEGER PRIMARY KEY,auth_name,auth_srid,ref_sys_name,proj4text,srtext); -INSERT INTO spatial_ref_sys VALUES(26711,'epsg',26711,'NAD27 / UTM zone 11N','+proj=utm +zone=11 +datum=NAD27 +units=m +no_defs','PROJCS["NAD27 / UTM zone 11N",GEOGCS[NAD27,DATUM[North_American_Datum_1927,SPHEROID["Clarke 1866",6378206.4,294.9786982138982]],UNIT[degree,0.0174532925199433]],PROJECTION[Transverse_Mercator],PARAMETER[central_meridian,-117],PARAMETER[scale_factor,0.9996],PARAMETER[false_easting,500000],AUTHORITY[EPSG,26711]]'); -CREATE TABLE geometry_columns (f_table_name,f_geometry_column,geometry_type,coord_dimension,srid,spatial_index_enabled); -INSERT INTO geometry_columns VALUES('byte_metadata','geometry',3,2,26711,1); -CREATE TABLE byte_rasters (id INTEGER PRIMARY KEY,raster); -INSERT INTO byte_rasters VALUES(1,X'49492A00080000000B000001030001000000140000000101030001000000140000000201030001000000080000000301030001000000010000000601030001000000010000001101040001000000920000001501030001000000010000001601030001000000140000001701040001000000900100001C0103000100000001000000530103000100000001000000000000006B7B847384848C8484846B846B84846B7B739C9473846B7B9473A5738C6B7B7B63847B848484639C73848C847B738C6B8C73847B6B848473736B736B94847B7B7384847B737B737B6B73946B738C7384849C848C84847373737B947BA57B846B6B849C7BBDADAD949473947B6B8473849C637B738484CE6BC5AD948C8C8463847B738C848463847B84AD7B73947B9473947B8C7B6B7384736B73637B63B5636B7B7384737B847384847B7B846373637B8473736B8C8C638C63737B6B846B736B737B847B6B7B84848484847B63847B6B9463737B8CAD7B6B7B7B7B6B7B7B7B6B8C7B7B73735A6BAD6B6B6B6B63847B73AD94637B7B6B7B636BBDAD6B73736B638C6BAD8C9484846B7B6363736384638C73947B63847B948C8C6B8C5A6B736B5A637B7373737B7B9473946384A5949C7B6B6B6B738C637363636B7384735A7B73BDAD8C8CA573845A63735A63636B6384636B84849CB58CAD7B8463737B4A73637B8C9C84A58C8C63ADF7FFCE846B8C7B9484A5A5948C847B6B7B6B7BB5B59C949C9C9CB5849473846B6B6B6B6B73636B'); -CREATE TABLE byte_metadata (id INTEGER PRIMARY KEY,tile_id,width,height,pixel_x_size,pixel_y_size,geometry POLYGON); -INSERT INTO byte_metadata VALUES(1,0,20,20,60.0,60.0,X'0001576800000000000040E61A4100000000749C4C410000000000F91A4100000000CC9E4C417C0300000001000000050000000000000040E61A4100000000749C4C410000000040E61A4100000000CC9E4C410000000000F91A4100000000CC9E4C410000000000F91A4100000000749C4C410000000040E61A4100000000749C4C41FE'); -CREATE VIRTUAL TABLE idx_byte_metadata_geometry USING rtree(pkid, xmin, xmax, ymin, ymax); -INSERT INTO idx_byte_metadata_geometry SELECT rowid, ST_MinX(geometry), ST_MaxX(geometry), ST_MinY(geometry), ST_MaxY(geometry) FROM byte_metadata; diff --git a/autotest/gdrivers/data/rasterlite/rasterlite.sqlite b/autotest/gdrivers/data/rasterlite/rasterlite.sqlite deleted file mode 100644 index bc9bacbec793..000000000000 Binary files a/autotest/gdrivers/data/rasterlite/rasterlite.sqlite and /dev/null differ diff --git a/autotest/gdrivers/data/rasterlite/rasterlite_pct.sqlite b/autotest/gdrivers/data/rasterlite/rasterlite_pct.sqlite deleted file mode 100644 index b24fb9eab839..000000000000 Binary files a/autotest/gdrivers/data/rasterlite/rasterlite_pct.sqlite and /dev/null differ diff --git a/autotest/gdrivers/data/rasterlite/rasterlite_pyramids.sqlite b/autotest/gdrivers/data/rasterlite/rasterlite_pyramids.sqlite deleted file mode 100644 index 8d0ac323b97b..000000000000 Binary files a/autotest/gdrivers/data/rasterlite/rasterlite_pyramids.sqlite and /dev/null differ diff --git a/autotest/gdrivers/data/sgi/byte.sgi b/autotest/gdrivers/data/sgi/byte.sgi deleted file mode 100644 index 241038682446..000000000000 Binary files a/autotest/gdrivers/data/sgi/byte.sgi and /dev/null differ diff --git a/autotest/gdrivers/dipex.py b/autotest/gdrivers/dipex.py deleted file mode 100755 index b1f36662580a..000000000000 --- a/autotest/gdrivers/dipex.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test DIPEx driver -# Author: Even Rouault, -# -############################################################################### -# Copyright (c) 2009, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import gdaltest -import pytest - -pytestmark = pytest.mark.require_driver("DIPEx") - -############################################################################### -# Test a fake DIPex dataset - - -def test_dipex_1(): - - tst = gdaltest.GDALTest("DIPEx", "dipex/fakedipex.dat", 1, 1) - tst.testOpen() diff --git a/autotest/gdrivers/elas.py b/autotest/gdrivers/elas.py deleted file mode 100755 index baff705655a6..000000000000 --- a/autotest/gdrivers/elas.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test ELAS driver -# Author: Even Rouault, -# -############################################################################### -# Copyright (c) 2009, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - - -import gdaltest - -############################################################################### -# Test a dataset generated by Create() - - -def test_elas_1(): - - tst = gdaltest.GDALTest("ELAS", "elas/byte_elas.bin", 1, 4672) - tst.testOpen() - - -############################################################################### -# Test Create() - - -def test_elas_2(): - - tst = gdaltest.GDALTest("ELAS", "elas/byte_elas.bin", 1, 4672) - tst.testCreate() diff --git a/autotest/gdrivers/fit.py b/autotest/gdrivers/fit.py deleted file mode 100755 index 654f8cf19732..000000000000 --- a/autotest/gdrivers/fit.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read functionality for FIT driver. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2008, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import pytest - -from osgeo import gdal - -pytestmark = pytest.mark.require_driver("FIT") - - -@pytest.mark.parametrize( - "filename", ["byte", "int16", "uint16", "int32", "uint32", "float32", "float64"] -) -def test_fit(filename): - fitDriver = gdal.GetDriverByName("FIT") - - ds = gdal.Open("../gcore/data/" + filename + ".tif") - fitDriver.CreateCopy("tmp/" + filename + ".fit", ds, options=["PAGESIZE=2,2"]) - - ds2 = gdal.Open("tmp/" + filename + ".fit") - assert ds2.GetRasterBand(1).Checksum() == ds.GetRasterBand(1).Checksum() - - assert ds2.GetRasterBand(1).DataType == ds.GetRasterBand(1).DataType - ds2 = None diff --git a/autotest/gdrivers/gsg.py b/autotest/gdrivers/gsg.py index 8773e5e1b671..6fb025393bae 100755 --- a/autotest/gdrivers/gsg.py +++ b/autotest/gdrivers/gsg.py @@ -18,49 +18,12 @@ # Perform simple read tests. -def test_gsg_1(): - - tst = gdaltest.GDALTest("gsbg", "gsg/gsg_binary.grd", 1, 4672) - tst.testOpen(check_gt=(440720, 60, 0, 3751320, 0, -60)) - - -def test_gsg_2(): - - tst = gdaltest.GDALTest("gsag", "gsg/gsg_ascii.grd", 1, 4672) - tst.testOpen(check_gt=(440720, 60, 0, 3751320, 0, -60)) - - def test_gsg_3(): tst = gdaltest.GDALTest("gs7bg", "gsg/gsg_7binary.grd", 1, 4672) tst.testOpen(check_gt=(440720, 60, 0, 3751320, 0, -60)) -############################################################################### -# Create simple copy and check. - - -def test_gsg_4(): - - tst = gdaltest.GDALTest("gsbg", "gsg/gsg_binary.grd", 1, 4672) - - tst.testCreateCopy(check_gt=1) - - -def test_gsg_5(): - - tst = gdaltest.GDALTest("gsag", "gsg/gsg_ascii.grd", 1, 4672) - - tst.testCreateCopy(check_gt=1) - - -def test_gsg_6(): - - tst = gdaltest.GDALTest("gsbg", "gsg/gsg_binary.grd", 1, 4672) - - tst.testCreate(out_bands=1) - - def test_gsg_7(): tst = gdaltest.GDALTest("gs7bg", "gsg/gsg_7binary.grd", 1, 4672) diff --git a/autotest/gdrivers/isis2.py b/autotest/gdrivers/isis2.py index 94657211d39b..56845f8fd4a5 100755 --- a/autotest/gdrivers/isis2.py +++ b/autotest/gdrivers/isis2.py @@ -47,31 +47,3 @@ def test_isis2_1(): -1200.0000476837158, ) tst.testOpen(check_prj=expected_prj, check_gt=expected_gt) - - -############################################################################### -# Test simple creation on disk. - - -def test_isis2_2(): - - tst = gdaltest.GDALTest("ISIS2", "byte.tif", 1, 4672) - - tst.testCreate() - - -############################################################################### -# Test a different data type with some options. - - -def test_isis2_3(): - - tst = gdaltest.GDALTest( - "ISIS2", - "float32.tif", - 1, - 4672, - options=["LABELING_METHOD=DETACHED", "IMAGE_EXTENSION=qub"], - ) - - tst.testCreateCopy(vsimem=1) diff --git a/autotest/gdrivers/mff2.py b/autotest/gdrivers/mff2.py index f6c096387438..7c57ad4b5ec7 100755 --- a/autotest/gdrivers/mff2.py +++ b/autotest/gdrivers/mff2.py @@ -24,14 +24,3 @@ def test_mff2_1(): tst = gdaltest.GDALTest("MFF2", "mff2/bytemff2", 1, 4672) tst.testOpen() - - -############################################################################### -# Test writing a MFF2 file - - -def test_mff2_write(): - - with gdaltest.config_option("GDAL_PAM_ENABLED", "NO"): - tst = gdaltest.GDALTest("MFF2", "mff2/bytemff2", 1, 4672) - tst.testCreateCopy(check_srs=True) diff --git a/autotest/gdrivers/ntv2.py b/autotest/gdrivers/ntv2.py index 8f930746c3a9..08d109c2d46a 100755 --- a/autotest/gdrivers/ntv2.py +++ b/autotest/gdrivers/ntv2.py @@ -16,8 +16,6 @@ import gdaltest import pytest -from osgeo import gdal - pytestmark = pytest.mark.require_driver("NTV2") ############################################################################### @@ -42,95 +40,6 @@ def test_ntv2_2(): tst.testOpen(check_gt=gt, check_prj="WGS84") -############################################################################### -# Test creating a little-endian NTv2 grid - - -def test_ntv2_3(): - - tst = gdaltest.GDALTest( - "NTV2", "ntv2/test_ntv2_le.gsb", 2, 10, options=["ENDIANNESS=LE"] - ) - tst.testCreateCopy(vsimem=1) - - -############################################################################### -# Test creating a big-endian NTv2 grid - - -def test_ntv2_4(): - - tst = gdaltest.GDALTest( - "NTV2", "ntv2/test_ntv2_le.gsb", 2, 10, options=["ENDIANNESS=BE"] - ) - tst.testCreateCopy(vsimem=1) - - -############################################################################### -# Test appending to a little-endian NTv2 grid - - -def test_ntv2_5(): - - src_ds = gdal.Open("data/ntv2/test_ntv2_le.gsb") - gdal.GetDriverByName("NTv2").Create( - "/vsimem/ntv2_5.gsb", 1, 1, 4, gdal.GDT_Float32, options=["ENDIANNESS=LE"] - ) - ds = gdal.GetDriverByName("NTv2").CreateCopy( - "/vsimem/ntv2_5.gsb", src_ds, options=["APPEND_SUBDATASET=YES"] - ) - assert ds.FlushCache() == gdal.CE_None - assert ds.GetRasterBand(2).Checksum() == 10 - ds = None - ds = gdal.Open("NTv2:1:/vsimem/ntv2_5.gsb") - assert ds.GetRasterBand(2).Checksum() == 10 - ds = None - gdal.GetDriverByName("NTv2").Delete("/vsimem/ntv2_5.gsb") - - -############################################################################### -# Test appending to a big-endian NTv2 grid - - -def test_ntv2_6(): - - src_ds = gdal.Open("data/ntv2/test_ntv2_le.gsb") - gdal.GetDriverByName("NTv2").Create( - "/vsimem/ntv2_6.gsb", 1, 1, 4, gdal.GDT_Float32, options=["ENDIANNESS=BE"] - ) - ds = gdal.GetDriverByName("NTv2").CreateCopy( - "/vsimem/ntv2_6.gsb", src_ds, options=["APPEND_SUBDATASET=YES"] - ) - assert ds.GetRasterBand(2).Checksum() == 10 - ds = None - ds = gdal.Open("NTv2:1:/vsimem/ntv2_6.gsb") - assert ds.GetRasterBand(2).Checksum() == 10 - ds = None - gdal.GetDriverByName("NTv2").Delete("/vsimem/ntv2_6.gsb") - - -############################################################################### -# Test creating a file with invalid filename - - -def test_ntv2_7(): - - with pytest.raises(Exception): - gdal.GetDriverByName("NTv2").Create( - "/does/not/exist.gsb", 1, 1, 4, gdal.GDT_Float32 - ) - - with pytest.raises(Exception): - gdal.GetDriverByName("NTv2").Create( - "/does/not/exist.gsb", - 1, - 1, - 4, - gdal.GDT_Float32, - options=["APPEND_SUBDATASET=YES"], - ) - - ############################################################################### @@ -150,35 +59,3 @@ def test_ntv2_online_1(): ) gt = (165.95, 0.1, 0.0, -33.95, 0.0, -0.1) tst.testOpen(check_gt=gt, check_prj="WGS84") - - -############################################################################### - - -def test_ntv2_online_2(): - - try: - os.stat("tmp/cache/nzgd2kgrid0005.gsb") - except OSError: - pytest.skip() - - tst = gdaltest.GDALTest( - "NTV2", "tmp/cache/nzgd2kgrid0005.gsb", 1, 54971, filename_absolute=1 - ) - tst.testCreateCopy(vsimem=1) - - -############################################################################### - - -def test_ntv2_online_3(): - - try: - os.stat("tmp/cache/nzgd2kgrid0005.gsb") - except OSError: - pytest.skip() - - tst = gdaltest.GDALTest( - "NTV2", "tmp/cache/nzgd2kgrid0005.gsb", 1, 54971, filename_absolute=1 - ) - tst.testCreate(vsimem=1, out_bands=4) diff --git a/autotest/gdrivers/paux.py b/autotest/gdrivers/paux.py index eb27fa7edc22..c3095354e569 100755 --- a/autotest/gdrivers/paux.py +++ b/autotest/gdrivers/paux.py @@ -14,8 +14,6 @@ import gdaltest import pytest -from osgeo import gdal - pytestmark = pytest.mark.require_driver("PAUX") ############################################################################### @@ -26,35 +24,3 @@ def test_paux_1(): tst = gdaltest.GDALTest("PAux", "paux/small16.raw", 2, 12816) tst.testOpen() - - -############################################################################### -# Test copying. - - -def test_paux_2(): - - tst = gdaltest.GDALTest("PAux", "byte.tif", 1, 4672) - - tst.testCreateCopy(check_gt=1) - - -############################################################################### -# Test /vsimem based. - - -def test_paux_3(): - - tst = gdaltest.GDALTest("PAux", "byte.tif", 1, 4672) - - tst.testCreateCopy(vsimem=1) - - -############################################################################### -# Cleanup. - - -def test_paux_cleanup(): - gdaltest.clean_tmp() - if gdal.VSIStatL("/vsimem/byte.tif.tst.aux.xml") is not None: - gdal.Unlink("/vsimem/byte.tif.tst.aux.xml") diff --git a/autotest/gdrivers/r.py b/autotest/gdrivers/r.py deleted file mode 100755 index ec02766b8abe..000000000000 --- a/autotest/gdrivers/r.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test R driver support. -# Author: Frank Warmerdam -# -############################################################################### -# Copyright (c) 2009, Frank Warmerdam -# -# SPDX-License-Identifier: MIT -############################################################################### - - -import gdaltest - -############################################################################### -# Perform simple read test on an ascii file. - - -def test_r_1(): - - tst = gdaltest.GDALTest("R", "r/r_test.asc", 2, 202) - - tst.testOpen() - - -############################################################################### -# Perform a simple read test on a binary (uncompressed) file. - - -def test_r_2(): - - tst = gdaltest.GDALTest("R", "r/r_test.rdb", 1, 202) - tst.testOpen() - - -############################################################################### -# Verify a simple createcopy operation with 16bit data. - - -def test_r_3(): - - tst = gdaltest.GDALTest("R", "byte.tif", 1, 4672, options=["ASCII=YES"]) - tst.testCreateCopy() - - -############################################################################### -# Test creating a compressed binary stream and reading it back. - - -def test_r_4(): - - tst = gdaltest.GDALTest("R", "byte.tif", 1, 4672) - return tst.testCreateCopy(new_filename="tmp/r_4.rda") - - -############################################################################### diff --git a/autotest/gdrivers/rasterlite.py b/autotest/gdrivers/rasterlite.py deleted file mode 100755 index 2f9f8d1ce5aa..000000000000 --- a/autotest/gdrivers/rasterlite.py +++ /dev/null @@ -1,355 +0,0 @@ -#!/usr/bin/env pytest -# -*- coding: utf-8 -*- -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read functionality for Rasterlite driver. -# Author: Even Rouault, -# -############################################################################### -# Copyright (c) 2009-2013, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import gdaltest -import pytest - -from osgeo import gdal, ogr - -pytestmark = pytest.mark.require_driver("RASTERLITE") - - -@pytest.fixture(scope="module", autouse=True) -def setup(): - - # This is to speed-up the runtime of tests on EXT4 filesystems - # Do not use this for production environment if you care about data safety - # w.r.t system/OS crashes, unless you know what you are doing. - with gdal.config_option("OGR_SQLITE_SYNCHRONOUS", "OFF"): - yield - - -def has_spatialite(): - drv = ogr.GetDriverByName("SQLite") - return drv is not None and "SPATIALITE" in drv.GetMetadataItem( - "DMD_CREATIONOPTIONLIST" - ) - - -def sqlite_supports_rtree(tmp_path): - # Test if SQLite3 supports rtrees - ds2 = ogr.GetDriverByName("SQLite").CreateDataSource( - str(tmp_path / "testrtree.sqlite") - ) - gdal.ErrorReset() - ds2.ExecuteSQL("CREATE VIRTUAL TABLE testrtree USING rtree(id,minX,maxX,minY,maxY)") - - return "rtree" not in gdal.GetLastErrorMsg() - - -def sqlite_supports_rasterlite(): - - gdal.ErrorReset() - gdal.Open("data/rasterlite/rasterlite.sqlite") - - return "unsupported file format" not in gdal.GetLastErrorMsg() - - -############################################################################### -# Test opening a rasterlite DB without overviews - - -def test_rasterlite_2(tmp_path): - - if not sqlite_supports_rtree(tmp_path): - pytest.skip( - "Please upgrade your sqlite3 library to be able to read Rasterlite DBs (needs rtree support)!" - ) - - if not sqlite_supports_rasterlite(): - pytest.skip( - "Please upgrade your sqlite3 library to be able to read Rasterlite DBs!" - ) - - ds = gdal.Open("data/rasterlite/rasterlite.sqlite") - - if ds is None: - pytest.fail() - - assert ds.RasterCount == 3, "expected 3 bands" - - assert ds.GetRasterBand(1).GetOverviewCount() == 0, "did not expect overview" - - cs = ds.GetRasterBand(1).Checksum() - expected_cs = 11746 - assert ( - cs == expected_cs or cs == 11751 - ), "for band 1, cs = %d, different from expected_cs = %d" % (cs, expected_cs) - - cs = ds.GetRasterBand(2).Checksum() - expected_cs = 19843 - assert ( - cs == expected_cs or cs == 20088 or cs == 20083 - ), "for band 2, cs = %d, different from expected_cs = %d" % (cs, expected_cs) - - cs = ds.GetRasterBand(3).Checksum() - expected_cs = 48911 - assert ( - cs == expected_cs or cs == 47978 - ), "for band 3, cs = %d, different from expected_cs = %d" % (cs, expected_cs) - - assert ds.GetProjectionRef().find("WGS_1984") != -1, ( - "projection_ref = %s" % ds.GetProjectionRef() - ) - - gt = ds.GetGeoTransform() - expected_gt = ( - -180.0, - 360.0 / ds.RasterXSize, - 0.0, - 90.0, - 0.0, - -180.0 / ds.RasterYSize, - ) - - gdaltest.check_geotransform(gt, expected_gt, 1e-15) - - ds = None - - -############################################################################### -# Test opening a rasterlite DB with overviews - - -def test_rasterlite_3(): - - ds = gdal.Open("RASTERLITE:data/rasterlite/rasterlite_pyramids.sqlite,table=test") - - assert ds.RasterCount == 3, "expected 3 bands" - - assert ds.GetRasterBand(1).GetOverviewCount() == 1, "expected 1 overview" - - cs = ds.GetRasterBand(1).GetOverview(0).Checksum() - expected_cs = 59551 - assert ( - cs == expected_cs or cs == 59833 - ), "for overview of band 1, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - cs = ds.GetRasterBand(2).GetOverview(0).Checksum() - expected_cs = 59603 - assert ( - cs == expected_cs or cs == 59588 - ), "for overview of band 2, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - cs = ds.GetRasterBand(3).GetOverview(0).Checksum() - expected_cs = 42173 - assert ( - cs == expected_cs or cs == 42361 - ), "for overview of band 3, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - ds = None - - -############################################################################### -# Test opening a rasterlite DB with color table and user-defined spatial extent - - -def test_rasterlite_4(): - - ds = gdal.Open( - "RASTERLITE:data/rasterlite/rasterlite_pct.sqlite,minx=0,miny=0,maxx=180,maxy=90" - ) - - assert ds.RasterCount == 1, "expected 1 band" - - assert ds.RasterXSize == 169 and ds.RasterYSize == 85 - - ct = ds.GetRasterBand(1).GetRasterColorTable() - assert ct is not None, "did not get color table" - - cs = ds.GetRasterBand(1).Checksum() - expected_cs = 36473 - assert cs == expected_cs, "for band 1, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - ds = None - - -############################################################################### -# Test opening a rasterlite DB with color table and do color table expansion - - -def test_rasterlite_5(): - - ds = gdal.Open("RASTERLITE:data/rasterlite/rasterlite_pct.sqlite,bands=3") - - assert ds.RasterCount == 3, "expected 3 bands" - - ct = ds.GetRasterBand(1).GetRasterColorTable() - assert ct is None, "did not expect color table" - - cs = ds.GetRasterBand(1).Checksum() - expected_cs = 506 - assert cs == expected_cs, "for band 1, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - cs = ds.GetRasterBand(2).Checksum() - expected_cs = 3842 - assert cs == expected_cs, "for band 2, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - cs = ds.GetRasterBand(3).Checksum() - expected_cs = 59282 - assert cs == expected_cs, "for band 3, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - ds = None - - -############################################################################### -# Test CreateCopy() - - -@pytest.fixture() -def byte_sqlite(tmp_path): - byte_sqlite_path = str(tmp_path / "byte.sqlite") - byte_sqlite_dsn = f"RASTERLITE:{byte_sqlite_path},table=byte" - - with gdal.Open("data/byte.tif") as src_ds: - ds = gdal.GetDriverByName("RASTERLITE").CreateCopy(byte_sqlite_dsn, src_ds) - assert ds is not None - del ds - - return byte_sqlite_dsn - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_6(byte_sqlite): - - # Test result of CreateCopy() - ds = gdal.Open(byte_sqlite) - assert ds is not None - - with gdal.Open("data/byte.tif") as src_ds: - assert ( - ds.GetRasterBand(1).Checksum() == src_ds.GetRasterBand(1).Checksum() - ), "Wrong checksum" - - expected_gt = src_ds.GetGeoTransform() - gt = ds.GetGeoTransform() - - gdaltest.check_geotransform(gt, expected_gt, 1e-5) - - assert "NAD27 / UTM zone 11N" in ds.GetProjectionRef(), "Wrong SRS" - - ds = None - - -############################################################################### -# Test BuildOverviews() - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_7(byte_sqlite): - - ds = gdal.Open(byte_sqlite, gdal.GA_Update) - - # Resampling method is not taken into account - ds.BuildOverviews("NEAREST", overviewlist=[2, 4]) - - assert ( - ds.GetRasterBand(1).GetOverview(0).Checksum() == 1192 - ), "Wrong checksum for overview 0" - - assert ( - ds.GetRasterBand(1).GetOverview(1).Checksum() == 233 - ), "Wrong checksum for overview 1" - - # Reopen and test - ds = None - ds = gdal.Open(byte_sqlite) - - assert ( - ds.GetRasterBand(1).GetOverview(0).Checksum() == 1192 - ), "Wrong checksum for overview 0" - - assert ( - ds.GetRasterBand(1).GetOverview(1).Checksum() == 233 - ), "Wrong checksum for overview 1" - - ############################################################################### - # Test CleanOverviews() - - ds = gdal.Open(byte_sqlite, gdal.GA_Update) - - ds.BuildOverviews(overviewlist=[]) - - assert ds.GetRasterBand(1).GetOverviewCount() == 0 - - -############################################################################### -# Test BuildOverviews() with AVERAGE resampling - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_11(byte_sqlite): - - ds = gdal.Open(byte_sqlite, gdal.GA_Update) - - # Resampling method is not taken into account - ds.BuildOverviews("AVERAGE", overviewlist=[2, 4]) - - # Reopen and test - ds = None - ds = gdal.Open(byte_sqlite) - - assert ( - ds.GetRasterBand(1).GetOverview(0).Checksum() == 1152 - ), "Wrong checksum for overview 0" - - assert ( - ds.GetRasterBand(1).GetOverview(1).Checksum() == 215 - ), "Wrong checksum for overview 1" - - -############################################################################### -# Test opening a .rasterlite file - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_12(): - - ds = gdal.Open("data/rasterlite/byte.rasterlite") - assert ds.GetRasterBand(1).Checksum() == 4672, "validation failed" - - -############################################################################### -# Test opening a .rasterlite.sql file - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_13(): - - if gdaltest.rasterlite_drv.GetMetadataItem("ENABLE_SQL_SQLITE_FORMAT") != "YES": - pytest.skip() - - ds = gdal.Open("data/rasterlite/byte.rasterlite.sql") - assert ds.GetRasterBand(1).Checksum() == 4672, "validation failed" diff --git a/autotest/gdrivers/sdts.py b/autotest/gdrivers/sdts.py deleted file mode 100755 index 958c7bd212ea..000000000000 --- a/autotest/gdrivers/sdts.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read/write functionality for SDTS driver. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2008, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import gdaltest - -from osgeo import gdal, osr - -############################################################################### -# Test a truncated version of an SDTS DEM downloaded at -# http://thor-f5.er.usgs.gov/sdts/datasets/raster/dem/dem_oct_2001/1107834.dem.sdts.tar.gz - - -def test_sdts_1(): - - tst = gdaltest.GDALTest("SDTS", "STDS_1107834_truncated/1107CATD.DDF", 1, 61672) - srs = osr.SpatialReference() - srs.SetWellKnownGeogCS("NAD27") - srs.SetUTM(16) - tst.testOpen( - check_prj=srs.ExportToWkt(), - check_gt=(666015, 30, 0, 5040735, 0, -30), - check_filelist=False, - ) - - ds = gdal.Open("data/STDS_1107834_truncated/1107CATD.DDF") - md = ds.GetMetadata() - - assert md["TITLE"] == "ALANSON, MI-24000" diff --git a/autotest/gdrivers/sgi.py b/autotest/gdrivers/sgi.py deleted file mode 100755 index 5b4343e23f3c..000000000000 --- a/autotest/gdrivers/sgi.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: PNM (Portable Anyware Map) Testing. -# Author: Frank Warmerdam -# -############################################################################### -# Copyright (c) 2007, Frank Warmerdam -# -# SPDX-License-Identifier: MIT -############################################################################### - - -import gdaltest - -############################################################################### -# Read existing simple 1 band SGI file. - - -def test_sgi_1(): - - tst = gdaltest.GDALTest("SGI", "sgi/byte.sgi", 1, 4672) - - tst.testOpen() - - -############################################################################### -# Write Test grayscale - - -def test_sgi_2(): - - tst = gdaltest.GDALTest("SGI", "byte.tif", 1, 4672) - - tst.testCreate() - - -############################################################################### -# Write Test rgb - - -def test_sgi_3(): - - tst = gdaltest.GDALTest("SGI", "rgbsmall.tif", 2, 21053) - - tst.testCreate() diff --git a/autotest/gdrivers/usgsdem.py b/autotest/gdrivers/usgsdem.py index 87494d5dc63d..1379e8ff8ae7 100755 --- a/autotest/gdrivers/usgsdem.py +++ b/autotest/gdrivers/usgsdem.py @@ -16,7 +16,7 @@ import gdaltest import pytest -from osgeo import gdal, osr +from osgeo import osr pytestmark = pytest.mark.require_driver("USGSDEM") @@ -75,148 +75,6 @@ def test_usgsdem_3(): ) -############################################################################### -# Test CreateCopy() - - -def test_usgsdem_4(): - - tst = gdaltest.GDALTest( - "USGSDEM", - "usgsdem/39079G6_truncated.dem", - 1, - 61424, - options=["RESAMPLE=Nearest"], - ) - tst.testCreateCopy(check_gt=1, check_srs=1, vsimem=1) - - -############################################################################### -# Test CreateCopy() without any creation options - - -@pytest.mark.require_driver("DTED") -def test_usgsdem_5(): - - ds = gdal.Open("data/n43.dt0") - ds2 = gdal.GetDriverByName("USGSDEM").CreateCopy( - "tmp/n43.dem", ds, options=["RESAMPLE=Nearest"] - ) - - if ds.GetRasterBand(1).Checksum() != ds2.GetRasterBand(1).Checksum(): - print(ds2.GetRasterBand(1).Checksum()) - print(ds.GetRasterBand(1).Checksum()) - ds2 = None - print(open("tmp/n43.dem", "rb").read()) - pytest.fail("Bad checksum.") - - gt1 = ds.GetGeoTransform() - gt2 = ds2.GetGeoTransform() - for i in range(6): - if gt1[i] != pytest.approx(gt2[i], abs=1e-5): - print("") - print("old = ", gt1) - print("new = ", gt2) - pytest.fail("Geotransform differs.") - - srs = osr.SpatialReference() - srs.SetWellKnownGeogCS("WGS84") - assert ds2.GetProjectionRef() == srs.ExportToWkt(), "Bad SRS." - - ds2 = None - - -############################################################################### -# Test CreateCopy() without a few creation options. Then create a new copy with TEMPLATE -# creation option and check that both files are binary identical. - - -@pytest.mark.require_driver("DTED") -def test_usgsdem_6(): - - ds = gdal.Open("data/n43.dt0") - ds2 = gdal.GetDriverByName("USGSDEM").CreateCopy( - "tmp/file_1.dem", - ds, - options=[ - "PRODUCER=GDAL", - "OriginCode=GDAL", - "ProcessCode=A", - "RESAMPLE=Nearest", - ], - ) - - ds3 = gdal.GetDriverByName("USGSDEM").CreateCopy( - "tmp/file_2.dem", ds2, options=["TEMPLATE=tmp/file_1.dem", "RESAMPLE=Nearest"] - ) - - del ds2 - del ds3 - - f1 = open("tmp/file_1.dem", "rb") - f2 = open("tmp/file_2.dem", "rb") - - # Skip the 40 first bytes because the dataset name will differ - f1.seek(40, 0) - f2.seek(40, 0) - - data1 = f1.read() - data2 = f2.read() - - assert data1 == data2 - - f1.close() - f2.close() - - -############################################################################### -# Test CreateCopy() with CDED50K profile - - -@pytest.mark.require_driver("DTED") -def test_usgsdem_7(): - - ds = gdal.Open("data/n43.dt0") - - # To avoid warning about 'Unable to find NTS mapsheet lookup file: NTS-50kindex.csv' - with gdal.quiet_errors(): - ds2 = gdal.GetDriverByName("USGSDEM").CreateCopy( - "tmp/000a00DEMz", - ds, - options=[ - "PRODUCT=CDED50K", - "TOPLEFT=80w,44n", - "RESAMPLE=Nearest", - "ZRESOLUTION=1.1", - "INTERNALNAME=GDAL", - ], - ) - - assert ds2.RasterXSize == 1201 and ds2.RasterYSize == 1201, "Bad image dimensions." - - expected_gt = ( - -80.000104166666674, - 0.000208333333333, - 0, - 44.000104166666667, - 0, - -0.000208333333333, - ) - got_gt = ds2.GetGeoTransform() - for i in range(6): - if expected_gt[i] != pytest.approx(got_gt[i], abs=1e-5): - print("") - print("expected = ", expected_gt) - print("got = ", got_gt) - pytest.fail("Geotransform differs.") - - srs = osr.SpatialReference() - srs.SetWellKnownGeogCS("NAD83") - assert ds2.GetProjectionRef() == srs.ExportToWkt(), "Bad SRS." - - ds2 = None - - ############################################################################### # Test truncated version of http://download.osgeo.org/gdal/data/usgsdem/various.zip/39109h1.dem # Undocumented format diff --git a/autotest/gdrivers/xpm.py b/autotest/gdrivers/xpm.py deleted file mode 100755 index ae67f81158ba..000000000000 --- a/autotest/gdrivers/xpm.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read/write functionality for XPM driver. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2008, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - - -import gdaltest -import pytest - -from osgeo import gdal - -xpm_list = [("http://download.osgeo.org/gdal/data/xpm", "utm.xpm", 44206, -1)] - -pytestmark = pytest.mark.require_driver("XPM") - - -@pytest.mark.parametrize( - "downloadURL,fileName,checksum,download_size", - xpm_list, - ids=[item[1] for item in xpm_list], -) -def test_xpm(downloadURL, fileName, checksum, download_size): - gdaltest.download_or_skip(downloadURL + "/" + fileName, fileName, download_size) - - ds = gdal.Open("tmp/cache/" + fileName) - - assert ( - ds.GetRasterBand(1).Checksum() == checksum - ), "Bad checksum. Expected %d, got %d" % (checksum, ds.GetRasterBand(1).Checksum()) - - -def test_xpm_1(): - tst = gdaltest.GDALTest("XPM", "byte.tif", 1, 4583) - tst.testCreateCopy(vsimem=1, check_minmax=False) diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/README b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/README deleted file mode 100644 index bd33586d5819..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/README +++ /dev/null @@ -1,17 +0,0 @@ -Dataset originally downloaded at wget http://thor-f5.er.usgs.gov/sdts/datasets/tvp/dlg3/24K/martin_point/D3607551_rd0s_1_sdts.tar.gz - -This is an extract to make it small. - -The following files have been removed as unncesseray for the OGR SDTS driver : - 3961 TR01CATS.DDF - 4709 TR01DDSH.DDF - 1177 TR01DQAA.DDF - 983 TR01DQCG.DDF - 3637 TR01DQHL.DDF - 2369 TR01DQLC.DDF - 2202 TR01DQPA.DDF - 1629 TR01STAT.DDF - -And the following files have been truncated to be smaller : (original size below) - 41420 TR01LE01.DDF - 11684 TR01NO01.DDF diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01AHDR.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01AHDR.DDF deleted file mode 100644 index 48fdf0f33785..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01AHDR.DDF +++ /dev/null @@ -1 +0,0 @@ -007112L 0600061 3204000001500000102815ATPR04043ATTP567830000;&TR01AHDR0100;&DDF RECORD IDENTIFIER1600;&ATTRIBUTE PRIMARYMODN!RCID(A,I)1600;&PRIMARY ATTRIBUTESBANNER !SOURCE_DATE !DATE_QUALIFIER !QUAD_NUMBER !L_PRIM_INTERVAL !L_PB_INTERVAL !S_PRIM_INTERVAL !S_PB_INTERVAL !CODED_FLAG !EDGEWS !EDGEWR !EDGENS !EDGENR !EDGEES !EDGEER !EDGESS !EDGESR !VERTICAL_DATUM !SW_LATITUDE !SW_LONGITUDE !NW_LATITUDE !NW_LONGITUDE !NE_LATITUDE !NE_LONGITUDE !SE_LATITUDE !SE_LONGITUDE (A(72),A(4),A(1),A(3),4R(5),9A(1),A(20),8R(12))00297 R 00052 3204000100700ATPR01207ATTP22619 1AHDR 1USGS-NMD DLG DATA - CHARACTER FORMAT - 09-29-87 VERSION 1982 60 4 40 NGVD 36.125000 -75.750000 36.250000 -75.750000 36.250000 -75.625000 36.125000 -75.625000 \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01ARDF.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01ARDF.DDF deleted file mode 100644 index 61bf74d5798e..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01ARDF.DDF +++ /dev/null @@ -1 +0,0 @@ -005132L 0600061 3204000001500000102815ATPR04643ATTP363890000;&TR01ARDF0100;&DDF RECORD IDENTIFIER1600;&ATTRIBUTE PRIMARYMODN!RCID(A(4),I(6))1600;&PRIMARY ATTRIBUTESENTITY_LABEL !ARBITRARY_EXT !RELATION_TO_GROUND!VERTICAL_RELATION !OPERATIONAL_STATUS!ACCESS_RESTRICTION!OLD_RAILROAD_GRADE!WITH_RAILROAD !COVERED !HISTORICAL !LIMITED_ACCESS !PHOTOREVISED !LANES !ROAD_WIDTH !BEST_ESTIMATE !FUNCTIONAL_CLASS (A(7),11A(1),I(2),I(3),A(1),A(2))00094 R 00049 220400010700ATPR1107ATTP2718 1ARDF 11700005 -9-99  2ARDF 21700005 -9-99  3ARDF 31700005 -9-99  4ARDF 41700209 -9-99  5ARDF 51700209 -9-99  6ARDF 61700209 -9-99  7ARDF 71700209 -9-99  8ARDF 81700209 -9-99  9ARDF 91700209 -9-99  10ARDF 101700209 -9-99  11ARDF 111700209 -9-99  12ARDF 121700209 -9-99  13ARDF 131700209 -9-99  14ARDF 141700209 -9-99  15ARDF 151700209 -9-99  16ARDF 161700209 -9-99  17ARDF 171700005 -9-99  18ARDF 181700209 -9-99  19ARDF 191700005 -9-99  20ARDF 201700210 -9-99  21ARDF 211700005 -9-99  22ARDF 221700405 -9-99  23ARDF 231700405 -9-99  24ARDF 241700210 -9-99  25ARDF 251700210 -9-99  26ARDF 261700205 -9-99  27ARDF 271700205 -9-99  28ARDF 281700205 -9-99  29ARDF 291700205 -9-99  30ARDF 301700205 -9-99  31ARDF 311700205 -9-99  32ARDF 321700205 -9-99  33ARDF 331700205 -9-99  34ARDF 341700205 -9-99  35ARDF 351700205 -9-99  36ARDF 361700205 -9-99  37ARDF 371700205 -9-99  38ARDF 381700205 -9-99  39ARDF 391700205 -9-99  40ARDF 401700205 -9-99  41ARDF 411700205 -9-99  42ARDF 421700205 -9-99  43ARDF 431700205 -9-99  44ARDF 441700205 -9-99  45ARDF 451700205 -9-99  46ARDF 461700205 -9-99  47ARDF 471700209 -9-99  48ARDF 481700209 -9-99  49ARDF 491700209 -9-99  50ARDF 501700209 -9-99  51ARDF 511700209 -9-99  52ARDF 521700209 -9-99  53ARDF 531700209 -9-99  54ARDF 541700209 -9-99  55ARDF 551700209 -9-99  56ARDF 561700209 -9-99  57ARDF 571700209 -9-99  58ARDF 581700209 -9-99  59ARDF 591700209 -9-99  60ARDF 601700209 -9-99  61ARDF 611700209 -9-99  62ARDF 621700209 -9-99  63ARDF 631700209 -9-99  64ARDF 641700209 -9-99  65ARDF 651700209 -9-99  66ARDF 661700209 -9-99  67ARDF 671700209 -9-99  68ARDF 681700209 -9-99  69ARDF 691700209 -9-99  70ARDF 701700209 -9-99  71ARDF 711700209 -9-99  72ARDF 721700209 -9-99  73ARDF 731700209 -9-99  74ARDF 741700209 -9-99  75ARDF 751700209 -9-99  76ARDF 761700209 -9-99  77ARDF 771700209 -9-99  78ARDF 781700209 -9-99  79ARDF 791700209 -9-99  80ARDF 801700209 -9-99  81ARDF 811700209 -9-99  82ARDF 821700209 -9-99  83ARDF 831700209 -9-99  84ARDF 841700209 -9-99  85ARDF 851700209 -9-99  86ARDF 861700209 -9-99  87ARDF 871700209 -9-99  88ARDF 881700209 -9-99  89ARDF 891700209 -9-99  90ARDF 901700209 -9-99  91ARDF 911700209 -9-99  92ARDF 921700209 -9-99  93ARDF 931700209 -9-99  94ARDF 941700209 -9-99  95ARDF 951700209 -9-99  96ARDF 961700209 -9-99  97ARDF 971700209 -9-99  98ARDF 981700209 -9-99  99ARDF 991700209 -9-99  100ARDF 1001700209 -9-99  101ARDF 1011700209 -9-99  102ARDF 1021700209 -9-99  103ARDF 1031700209 -9-99  104ARDF 1041700209 -9-99  105ARDF 1051700209 -9-99  106ARDF 1061700209 -9-99  107ARDF 1071700209 -9-99  108ARDF 1081700209 -9-99  109ARDF 1091700209 -9-99  110ARDF 1101700209 -9-99  111ARDF 1111700209 -9-99  112ARDF 1121700209 -9-99  113ARDF 1131700209 -9-99  114ARDF 1141700209 -9-99  115ARDF 1151700209 -9-99  116ARDF 1161700209 -9-99  117ARDF 1171700209 -9-99  118ARDF 1181700209 -9-99  119ARDF 1191700209 -9-99  120ARDF 1201700209 -9-99  121ARDF 1211700209 -9-99  122ARDF 1221700209 -9-99  123ARDF 1231700209 -9-99  124ARDF 1241700209 -9-99  125ARDF 1251700209 -9-99  126ARDF 1261700209 -9-99  127ARDF 1271700209 -9-99  128ARDF 1281700209 -9-99  129ARDF 1291700209 -9-99  130ARDF 1301700209 -9-99  131ARDF 1311700209 -9-99  132ARDF 1321700209 -9-99  133ARDF 1331700209 -9-99  134ARDF 1341700209 -9-99  135ARDF 1351700209 -9-99  136ARDF 1361700209 -9-99  137ARDF 1371700209 -9-99  138ARDF 1381700209 -9-99  139ARDF 1391700209 -9-99  140ARDF 1401700209 -9-99  141ARDF 1411700209 -9-99  142ARDF 1421700209 -9-99  143ARDF 1431700209 -9-99  144ARDF 1441700209 -9-99  145ARDF 1451700209 -9-99  146ARDF 1461700209 -9-99  147ARDF 1471700209 -9-99  148ARDF 1481700209 -9-99  149ARDF 1491700209 -9-99  150ARDF 1501700209 -9-99  151ARDF 1511700209 -9-99  152ARDF 1521700209 -9-99  153ARDF 1531700209 -9-99  154ARDF 1541700209 -9-99  155ARDF 1551700209 -9-99  156ARDF 1561700209 -9-99  157ARDF 1571700218 -9-99  158ARDF 1581700218 -9-99  159ARDF 1591700218 -9-99  160ARDF 1601700218 -9-99  161ARDF 1611700218 -9-99  162ARDF 1621700218 -9-99  163ARDF 1631700218 -9-99  164ARDF 1641700218 -9-99  \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01ARDM.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01ARDM.DDF deleted file mode 100644 index 47e21d1dbb16..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01ARDM.DDF +++ /dev/null @@ -1 +0,0 @@ -002212L 0600057 22040000150000012815ATPR4643ATTP75890000;&TR01ARDM0100;&DDF RECORD IDENTIFIER1600;&ATTRIBUTE PRIMARYMODN!RCID(A(4),I(6))1600;&PRIMARY ATTRIBUTESROUTE_NUMBER !ROUTE_TYPE (A(7),A(9))00084 R 00049 220400010700ATPR1107ATTP1718 1ARDM 1SR 1200  2ARDM 2SR 1200  3ARDM 3SR 1200  4ARDM 4SR 1200  5ARDM 5SR 1200  6ARDM 6SR 1200  7ARDM 7SR 1200  8ARDM 8SR 1200  9ARDM 9SR 1200  10ARDM 10SR 1200  11ARDM 11SR 1200  12ARDM 12SR 1200  13ARDM 13SR 1200  14ARDM 14SR 1200  15ARDM 15SR 1200  16ARDM 16SR 1200  17ARDM 17SR 1200  18ARDM 18SR 1200  19ARDM 19SR 1200  20ARDM 20SR 1200  21ARDM 21SR 1200  \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01CATD.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01CATD.DDF deleted file mode 100644 index 7adb3e4d2784..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01CATD.DDF +++ /dev/null @@ -1 +0,0 @@ -001602L 0600049 22040000150000012815CATD68430000;&TR01CATD0100;&DDF RECORD IDENTIFIER1600;&CATALOG/DIRECTORYMODN!RCID!NAME!TYPE!FILE!EXTR!MVER(A,I,5A)00111 R 00039 21040001070CATD657 1CATD 1IDENIdentification TR01IDEN.DDFN  2CATD 2CATDCatalog/Directory TR01CATD.DDFN  3CATD 3CATXCatalog/Cross-Reference TR01CATX.DDFN  4CATD 4CATSCatalog/Spatial Domain TR01CATS.DDFN  5CATD 5IREFInternal Spatial ReferenceTR01IREF.DDFN  6CATD 6XREFExternal Spatial ReferenceTR01XREF.DDFN  7CATD 7MDEFData Dictionary/DefinitionDLG3MDEF.DDFY 3.00 8CATD 8MDOMData Dictionary/Domain DLG3MDOM.DDFY 3.00 9CATD 9DDSHData Dictionary/Schema TR01DDSH.DDFN  10CATD 10STATTransfer Statistics TR01STAT.DDFN  11CATD 11DQHLLineage TR01DQHL.DDFN  12CATD 12DQPAPositional Accuracy TR01DQPA.DDFN  13CATD 13DQAAAttribute Accuracy TR01DQAA.DDFN  14CATD 14DQLCLogical Consistency TR01DQLC.DDFN  15CATD 15DQCGCompleteness TR01DQCG.DDFN  16CATD 16ARDFAttribute Primary TR01ARDF.DDFN  17CATD 17ARDMAttribute Primary TR01ARDM.DDFN  18CATD 18AHDRAttribute Primary TR01AHDR.DDFN  19CATD 19FF01Composite TR01FF01.DDFN  20CATD 20NP01Point-Node TR01NP01.DDFN  21CATD 21NA01Point-Node TR01NA01.DDFN  22CATD 22NO01Point-Node TR01NO01.DDFN  23CATD 23LE01Line TR01LE01.DDFN  24CATD 24PC01Polygon TR01PC01.DDFN  \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01CATX.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01CATX.DDF deleted file mode 100644 index 24757fd5df78..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01CATX.DDF +++ /dev/null @@ -1 +0,0 @@ -001662L 0600049 22040000150000012815CATX74430000;&TR01CATX0100;&DDF RECORD IDENTIFIER1600;&CATALOG/CROSS-REFERENCEMODN!RCID!NAM1!TYP1!NAM2!TYP2!COMT(A,I,5A)00264 D 00041 310400010070CATX2167 1CATX 1DQHLLineageNP*Point-NodeThe modules starting with "NP" are part of the Data Quality/Lineage report. The NP modules contain control points used for transformations in the DLG data collection process.00279 D 00041 310400010070CATX2317 2CATX 2DQLCLogical ConsistencyA*Attribute PrimaryThe attribute modules (all modules with the name starting with "A") use the null scheme for fixed length subfields mentioned in the Data Quality/Logical Consistency report. \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01FF01.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01FF01.DDF deleted file mode 100644 index dbd1e3e4a805..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01FF01.DDF +++ /dev/null @@ -1 +0,0 @@ -002432L 0600070 2304000015000000128015COMP48043ATID42091FRID401330000;&TR01FF010100;&DDF RECORD IDENTIFIER1600;&COMPOSITEMODN!RCID!OBRP(A(4),I(6),A(2))2600;&ATTRIBUTE ID*MODN!RCID(A(4),I(6))2600;&FOREIGN ID*MODN!RCID(A(4),I(6))00139 D 00057 220400010700COMP1307ATID1120FRID5131 1FF01 1FFAHDR 1NP01 -4NA01 -35NO01 -146LE01 -179PC01 -35 \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01IDEN.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01IDEN.DDF deleted file mode 100644 index 0267136d6171..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01IDEN.DDF +++ /dev/null @@ -1 +0,0 @@ -002692L 0600065 330400000150000001028015IDEN105043CONF0561480000;&TR01IDEN0100;&DDF RECORD IDENTIFIER1600;&IDENTIFICATIONMODN!RCID!STID!STVS!DOCU!PRID!PRVS!PDOC!TITL!DAST!MPDT!DCDT!SCAL!COMT(A,I,10A,I,A)1600;&CONFORMANCEFFYN!VGYN!GTYN!RCYN!EXSP!FTLV(4A,2I)00449 R 00055 33040001007000IDEN375007CONF012382 1IDEN 1SPATIAL DATA TRANSFER STANDARD1994 JUNE 10FIPS PUB 173-1SDTS TOPOLOGICAL VECTOR PROFILEVERSION 1.0 JUNE 10, 1994FIPS 173-1 PART 4MARTIN POINT, NC / TRANSPORTATIONDLG-3198219960815 24000This transfer requires an external data dictionary from the U.S. Geological Survey, National Mapping Division, with a 4-character code of DLG3, version number 3.00YYYN14 \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01IREF.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01IREF.DDF deleted file mode 100644 index 8e639577cf2f..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01IREF.DDF +++ /dev/null @@ -1 +0,0 @@ -002002L 0600052 3204000001500000102815IREF105430000;&TR01IREF0100;&DDF RECORD IDENTIFIER1600;&INTERNAL SPATIAL REFERENCEMODN!RCID!SATP!XLBL!YLBL!HFMT!SFAX!SFAY!XORG!YORG!XHRS!YHRS(A,I,4A,6R)00124 D 00039 21040001070IREF787 1IREF 12-TUPLEEASTINGNORTHINGBI320.010.010.00.00.6100000.610000 \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01LE01.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01LE01.DDF deleted file mode 100644 index 641b27a00b2f..000000000000 Binary files a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01LE01.DDF and /dev/null differ diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NA01.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NA01.DDF deleted file mode 100644 index e97cbfe8feab..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NA01.DDF +++ /dev/null @@ -1 +0,0 @@ -002332L 0600070 2304000015000000128015PNTS49043SADR35092ARID361270000;&TR01NA010100;&DDF RECORD IDENTIFIER1600;&POINT-NODEMODN!RCID!OBRP(A(4),I(6),A(2))1600;&SPATIAL ADDRESSX!Y(2B(32))1600;&AREA IDMODN!RCID(A(4),I(6))00097 R 00057 220400010700PNTS1307SADR0920ARID1129 1NA01 2NA��+��rPC01 2 2NA01 3NA�.�OPC01 3 3NA01 4NA����EPC01 4 4NA01 5NA���ԉ�PC01 5 5NA01 6NA�T�tePC01 6 6NA01 7NA���d�PC01 7 7NA01 8NA�}jԍPC01 8 8NA01 9NA�0ԕ.PC01 9 9NA01 10NA�����JPC01 10 10NA01 11NA�� �G�PC01 11 11NA01 12NA�-�!PC01 12 12NA01 13NA�3~��YPC01 13 13NA01 14NA�aU՝�PC01 14 14NA01 15NA�� �"�PC01 15 15NA01 16NA���ԦsPC01 16 16NA01 17NA��6ֹ�PC01 17 17NA01 18NA�[֥�PC01 18 18NA01 19NA�>�ձ�PC01 19 19NA01 20NA�4K�V^PC01 20 20NA01 21NA�a�A�PC01 21 21NA01 22NA�����PC01 22 22NA01 23NA����PC01 23 23NA01 24NA�,֔=PC01 24 24NA01 25NA�i���PC01 25 25NA01 26NA�\Ԉ�PC01 26 26NA01 27NA����@PC01 27 27NA01 28NA�����`PC01 28 28NA01 29NA�7YԨ PC01 29 29NA01 30NA�$����PC01 30 30NA01 31NA���מKPC01 31 31NA01 32NA�d����PC01 32 32NA01 33NA�g/ۻ6PC01 33 33NA01 34NA�f��� PC01 34 34NA01 35NA��pԩ�PC01 35 \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NO01.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NO01.DDF deleted file mode 100644 index 7e1636e5b8b3..000000000000 Binary files a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NO01.DDF and /dev/null differ diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NP01.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NP01.DDF deleted file mode 100644 index 96d7dffe21e3..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01NP01.DDF +++ /dev/null @@ -1 +0,0 @@ -001842L 0600057 22040000150000012815PNTS4943SADR35920000;&TR01NP010100;&DDF RECORD IDENTIFIER1600;&POINT-NODEMODN!RCID!OBRP(A(4),I(6),A(2))1600;&SPATIAL ADDRESSX!Y(2B(32))00078 R 00049 220400010700PNTS1307SADR0920 1NP01 1NP����E 2NP01 2NP���l� 3NP01 3NP�A��M� 4NP01 4NP���%� \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01PC01.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01PC01.DDF deleted file mode 100644 index 946651e741df..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01PC01.DDF +++ /dev/null @@ -1 +0,0 @@ -001882L 0600057 22040000150000012815POLY4643ATID42890000;&TR01PC010100;&DDF RECORD IDENTIFIER1600;&POLYGONMODN!RCID!OBRP(A(4),I(6),A(2))2600;&ATTRIBUTE ID*MODN!RCID(A(4),I(6))00059 D 00039 21040001070POLY137 1PC01 1PW00059 D 00039 21040001070POLY137 2PC01 2PC00059 D 00039 21040001070POLY137 3PC01 3PC00059 D 00039 21040001070POLY137 4PC01 4PC00059 D 00039 21040001070POLY137 5PC01 5PC00059 D 00039 21040001070POLY137 6PC01 6PC00059 D 00039 21040001070POLY137 7PC01 7PC00059 D 00039 21040001070POLY137 8PC01 8PC00059 D 00039 21040001070POLY137 9PC01 9PC00059 D 00039 21040001070POLY137 10PC01 10PC00059 D 00039 21040001070POLY137 11PC01 11PC00059 D 00039 21040001070POLY137 12PC01 12PC00059 D 00039 21040001070POLY137 13PC01 13PC00059 D 00039 21040001070POLY137 14PC01 14PC00059 D 00039 21040001070POLY137 15PC01 15PC00059 D 00039 21040001070POLY137 16PC01 16PC00059 D 00039 21040001070POLY137 17PC01 17PC00059 D 00039 21040001070POLY137 18PC01 18PC00059 D 00039 21040001070POLY137 19PC01 19PC00059 D 00039 21040001070POLY137 20PC01 20PC00059 D 00039 21040001070POLY137 21PC01 21PC00059 D 00039 21040001070POLY137 22PC01 22PC00059 D 00039 21040001070POLY137 23PC01 23PC00059 D 00039 21040001070POLY137 24PC01 24PC00059 D 00039 21040001070POLY137 25PC01 25PC00059 D 00039 21040001070POLY137 26PC01 26PC00059 D 00039 21040001070POLY137 27PC01 27PC00059 D 00039 21040001070POLY137 28PC01 28PC00059 D 00039 21040001070POLY137 29PC01 29PC00059 D 00039 21040001070POLY137 30PC01 30PC00059 D 00039 21040001070POLY137 31PC01 31PC00059 D 00039 21040001070POLY137 32PC01 32PC00059 D 00039 21040001070POLY137 33PC01 33PC00059 D 00039 21040001070POLY137 34PC01 34PC00059 D 00039 21040001070POLY137 35PC01 35PC \ No newline at end of file diff --git a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01XREF.DDF b/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01XREF.DDF deleted file mode 100644 index 3222aaf5fc95..000000000000 --- a/autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated/TR01XREF.DDF +++ /dev/null @@ -1 +0,0 @@ -001592L 0600049 22040000150000012815XREF67430000;&TR01XREF0100;&DDF RECORD IDENTIFIER1600;&EXTERNAL SPATIAL REFERENCEMODN!RCID!RSNM!HDAT!ZONE(A,I,3A)00069 D 00039 21040001070XREF237 1XREF 1UTMNAS18 \ No newline at end of file diff --git a/autotest/ogr/data/vm2alv2_texash/README b/autotest/ogr/data/vm2alv2_texash/README deleted file mode 100644 index d7760da4cb6b..000000000000 --- a/autotest/ogr/data/vm2alv2_texash/README +++ /dev/null @@ -1,2 +0,0 @@ -This is an extract of a few coverages from the vpf/vm2alv2 dataset of -http://freefr.dl.sourceforge.net/project/ogdi/OGDI_Test_Suite/3.1/ogdits-3.1.0.zip diff --git a/autotest/ogr/data/vm2alv2_texash/dht b/autotest/ogr/data/vm2alv2_texash/dht deleted file mode 100644 index f46eaafa9668..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/dht and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/lat b/autotest/ogr/data/vm2alv2_texash/lat deleted file mode 100644 index 44fcd6b6d294..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/lat and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/bndtxt.tft b/autotest/ogr/data/vm2alv2_texash/texash/bnd/bndtxt.tft deleted file mode 100644 index 351ddca23478..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/bndtxt.tft and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/char.vdt b/autotest/ogr/data/vm2alv2_texash/texash/bnd/char.vdt deleted file mode 100644 index 1ccbc909e4c0..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/char.vdt and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/edg.fit b/autotest/ogr/data/vm2alv2_texash/texash/bnd/edg.fit deleted file mode 100644 index 78f6511049c4..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/edg.fit and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/edg3_id.lti b/autotest/ogr/data/vm2alv2_texash/texash/bnd/edg3_id.lti deleted file mode 100644 index caed0f272df8..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/edg3_id.lti and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/end.fit b/autotest/ogr/data/vm2alv2_texash/texash/bnd/end.fit deleted file mode 100644 index b0245dcf73ab..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/end.fit and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/end1_id.pti b/autotest/ogr/data/vm2alv2_texash/texash/bnd/end1_id.pti deleted file mode 100644 index cb99ee61eef0..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/end1_id.pti and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/cnd b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/cnd deleted file mode 100644 index e27e79af56e9..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/cnd and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/ebr b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/ebr deleted file mode 100644 index 5a30267df603..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/ebr and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/edg b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/edg deleted file mode 100644 index cb3c81f8e584..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/edg and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/edx b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/edx deleted file mode 100644 index 61582542f7a3..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/edx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/end b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/end deleted file mode 100644 index 08f0af57a378..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/end and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/esi b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/esi deleted file mode 100644 index 8366c4c088c8..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/esi and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fac b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fac deleted file mode 100644 index 819ccf349263..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fac and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fbr b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fbr deleted file mode 100644 index 4bb7c3ea8bc0..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fbr and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fsi b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fsi deleted file mode 100644 index 13d53adf56cc..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/fsi and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/nsi b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/nsi deleted file mode 100644 index 32ac11e9ecbf..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/nsi and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/rng b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/rng deleted file mode 100644 index 23d3854befa3..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/rng and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/txt b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/txt deleted file mode 100644 index fc916a48ed74..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/txt and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/txx b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/txx deleted file mode 100644 index 4ef95f6ba0c1..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f/j/hb/1500/txx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code.tti b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code.tti deleted file mode 100644 index 1e35d15e7f82..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code.tti and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code1.ati b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code1.ati deleted file mode 100644 index dcf57fb2ceda..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code1.ati and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code3.lti b/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code3.lti deleted file mode 100644 index b3c38c074380..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/f_code3.lti and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fac.fit b/autotest/ogr/data/vm2alv2_texash/texash/bnd/fac.fit deleted file mode 100644 index df7ebc557194..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fac.fit and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fac1_id.ati b/autotest/ogr/data/vm2alv2_texash/texash/bnd/fac1_id.ati deleted file mode 100644 index 85a71995b696..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fac1_id.ati and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fca b/autotest/ogr/data/vm2alv2_texash/texash/bnd/fca deleted file mode 100644 index 4c901f5533ab..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fca and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fcs b/autotest/ogr/data/vm2alv2_texash/texash/bnd/fcs deleted file mode 100644 index b738b547e6fd..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fcs and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fcx b/autotest/ogr/data/vm2alv2_texash/texash/bnd/fcx deleted file mode 100644 index deb912714e48..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/fcx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/int.vdt b/autotest/ogr/data/vm2alv2_texash/texash/bnd/int.vdt deleted file mode 100644 index 2e708a7b2075..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/int.vdt and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/markersp.pft b/autotest/ogr/data/vm2alv2_texash/texash/bnd/markersp.pft deleted file mode 100644 index 425ca7ff7794..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/markersp.pft and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/markersp.pfx b/autotest/ogr/data/vm2alv2_texash/texash/bnd/markersp.pfx deleted file mode 100644 index 91676e22d3d6..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/markersp.pfx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbnda.aft b/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbnda.aft deleted file mode 100644 index f69ecc4f40c0..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbnda.aft and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbnda.afx b/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbnda.afx deleted file mode 100644 index ae73a853dc2f..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbnda.afx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbndl.lft b/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbndl.lft deleted file mode 100644 index 51f6b452bda7..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbndl.lft and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbndl.lfx b/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbndl.lfx deleted file mode 100644 index 23fe4bd3c284..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/polbndl.lfx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/symbol.rat b/autotest/ogr/data/vm2alv2_texash/texash/bnd/symbol.rat deleted file mode 100644 index c3a77d670503..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/symbol.rat and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile1_id.ati b/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile1_id.ati deleted file mode 100644 index 14386ffa2881..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile1_id.ati and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile3_id.lti b/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile3_id.lti deleted file mode 100644 index f4e4c83c57d8..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile3_id.lti and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile_id.tti b/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile_id.tti deleted file mode 100644 index 3d499e74a885..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/tile_id.tti and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/txt.fit b/autotest/ogr/data/vm2alv2_texash/texash/bnd/txt.fit deleted file mode 100644 index c4abcb51f9f2..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/txt.fit and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/bnd/txt_id.tti b/autotest/ogr/data/vm2alv2_texash/texash/bnd/txt_id.tti deleted file mode 100644 index a0d42c7fbf4d..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/bnd/txt_id.tti and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/cat b/autotest/ogr/data/vm2alv2_texash/texash/cat deleted file mode 100644 index 3665c6aabe6d..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/cat and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/dqt b/autotest/ogr/data/vm2alv2_texash/texash/dqt deleted file mode 100644 index 60cb4d40516a..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/dqt and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/dqx b/autotest/ogr/data/vm2alv2_texash/texash/dqx deleted file mode 100644 index f65e60b03a54..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/dqx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/grt b/autotest/ogr/data/vm2alv2_texash/texash/grt deleted file mode 100644 index a2b97f885042..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/grt and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/lht b/autotest/ogr/data/vm2alv2_texash/texash/lht deleted file mode 100644 index 4990566347e3..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/lht and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/cnd b/autotest/ogr/data/vm2alv2_texash/texash/tileref/cnd deleted file mode 100644 index 0e5577430a55..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/cnd and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/ebr b/autotest/ogr/data/vm2alv2_texash/texash/tileref/ebr deleted file mode 100644 index 3ad7b169b6e0..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/ebr and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/edg b/autotest/ogr/data/vm2alv2_texash/texash/tileref/edg deleted file mode 100644 index 8a9557daec55..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/edg and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/edx b/autotest/ogr/data/vm2alv2_texash/texash/tileref/edx deleted file mode 100644 index 3729198801aa..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/edx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/esi b/autotest/ogr/data/vm2alv2_texash/texash/tileref/esi deleted file mode 100644 index b9c75404e924..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/esi and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fac b/autotest/ogr/data/vm2alv2_texash/texash/tileref/fac deleted file mode 100644 index e1c76310af1a..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fac and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fbr b/autotest/ogr/data/vm2alv2_texash/texash/tileref/fbr deleted file mode 100644 index a7dcbdeb96ee..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fbr and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fca b/autotest/ogr/data/vm2alv2_texash/texash/tileref/fca deleted file mode 100644 index f18b4b62d7ea..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fca and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fcs b/autotest/ogr/data/vm2alv2_texash/texash/tileref/fcs deleted file mode 100644 index ac5eeb046111..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fcs and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fcx b/autotest/ogr/data/vm2alv2_texash/texash/tileref/fcx deleted file mode 100644 index 884bc64cd611..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fcx and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fsi b/autotest/ogr/data/vm2alv2_texash/texash/tileref/fsi deleted file mode 100644 index 512179438965..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/fsi and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/nsi b/autotest/ogr/data/vm2alv2_texash/texash/tileref/nsi deleted file mode 100644 index 429dd476d308..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/nsi and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/rng b/autotest/ogr/data/vm2alv2_texash/texash/tileref/rng deleted file mode 100644 index d70a7b49b266..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/rng and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/tileref.aft b/autotest/ogr/data/vm2alv2_texash/texash/tileref/tileref.aft deleted file mode 100644 index b07d7f9a3ba5..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/tileref.aft and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/tilereft.tft b/autotest/ogr/data/vm2alv2_texash/texash/tileref/tilereft.tft deleted file mode 100644 index c55098ee64f2..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/tilereft.tft and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/tsi b/autotest/ogr/data/vm2alv2_texash/texash/tileref/tsi deleted file mode 100644 index 68e64f961854..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/tsi and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/txt b/autotest/ogr/data/vm2alv2_texash/texash/tileref/txt deleted file mode 100644 index ad98d8a0c1a3..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/txt and /dev/null differ diff --git a/autotest/ogr/data/vm2alv2_texash/texash/tileref/txx b/autotest/ogr/data/vm2alv2_texash/texash/tileref/txx deleted file mode 100644 index b1c316fb4adb..000000000000 Binary files a/autotest/ogr/data/vm2alv2_texash/texash/tileref/txx and /dev/null differ diff --git a/autotest/ogr/ogr_ntf.py b/autotest/ogr/ogr_ntf.py deleted file mode 100755 index 0ed29c805724..000000000000 --- a/autotest/ogr/ogr_ntf.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read functionality for OGR NTF driver. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2009-2010, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -# The following tests will download sample data from -# http://www.ordnancesurvey.co.uk/oswebsite/products/meridian2/sampledata/meridian2ntf.exe -# and http://www.ordnancesurvey.co.uk/oswebsite/products/strategi/sampledata/stratntf.exe -# -# That data is subject to the terms of the 'Discover' Data License, that can be found here : -# http://www.ordnancesurvey.co.uk/oswebsite/products/sampledata/discoverdatalicense.html -# -# Verbatim copy of it : - -############################################################################### -# 'Discover' Data License -# -# Thank you for your interest in this Sample Data. The terms and conditions below set out a legal agreement -# between you and Ordnance Survey for your use of the Sample Data. Please read these terms carefully. If you do -# not agree to these terms and conditions, you should not use, download or access the Sample Data. -# -# 1 The Sample Data belongs to the Crown (or its suppliers). -# -# 2 Ordnance Survey grants you a limited, personal, non-exclusive, non-transferable, free-of-charge and fully terminable -# licence to use the Sample Data for the purpose of internal testing and evaluation only. By way of example, this means -# that you are not permitted to (i) sub-license, transfer, share or otherwise #distribute the Sample Data to any other -# person; (ii) incorporate the Sample Data into your products or services (unless solely for the purposes of internal -# testing and evaluation); or (iii) commercially exploit the Sample Data. -# -# 3 The Sample Data is provided "as is" and without any warranty as to quality, fitness for purpose, accuracy, availability -# or otherwise. You acknowledge that it is your responsibility to ensure that the Sample Data is suitable for your intended -# purposes. -# -# 4 To the fullest extent permitted by law, Ordnance Survey excludes all liability for any loss or damage of whatever nature -# arising from any use of the Sample Data. -# -# 5 You agree that Ordnance Survey (and its suppliers) shall retain all rights, title and interest in the Sample Data, including -# but not limited to any and all copyrights, patents, trade marks, trade secrets and all other intellectual property rights. -# -# 6 You agree not to tamper with or remove any copyright, trade mark, trade mark symbol or other proprietary notice of -# Ordnance Survey (or its suppliers) contained in the Sample Data. -# -# 7 Ordnance Survey may terminate this agreement immediately if you breach any of the terms and conditions. -# Ordnance Survey also reserves the right to terminate the agreement at any time on giving you thirty (30) days written -# notice (which may be given by email or by posting a notification on Ordnance Survey's website). -# -# 8 These terms and conditions are governed by English law, and you agree to the exclusive jurisdiction of the English courts. -# (C) Crown copyright and/or database right 2009 Ordnance Survey -# -# v1.0 May 2009 -############################################################################### - - -import os - -import gdaltest -import pytest - -from osgeo import ogr - -pytestmark = pytest.mark.require_driver("UK .NTF") - -############################################################################### - - -def test_ogr_ntf_1(): - - gdaltest.download_or_skip( - "http://www.ordnancesurvey.co.uk/oswebsite/products/strategi/sampledata/stratntf.exe", - "stratntf.exe", - ) - - try: - os.stat("tmp/cache/SS.ntf") - except OSError: - try: - gdaltest.unzip("tmp/cache", "tmp/cache/stratntf.exe") - try: - os.stat("tmp/cache/SS.ntf") - except OSError: - pytest.skip() - except OSError: - pytest.skip() - - ds = ogr.Open("tmp/cache/SS.ntf") - assert ds.GetLayerCount() == 5 - - layers = [ - ("STRATEGI_POINT", ogr.wkbPoint, 9193), - ("STRATEGI_LINE", ogr.wkbLineString, 8369), - ("STRATEGI_TEXT", ogr.wkbPoint, 1335), - ("STRATEGI_NODE", ogr.wkbNone, 10991), - ("FEATURE_CLASSES", ogr.wkbNone, 224), - ] - - for l in layers: - lyr = ds.GetLayerByName(l[0]) - assert lyr.GetLayerDefn().GetGeomType() == l[1] - assert lyr.GetFeatureCount() == l[2] - if l[1] != ogr.wkbNone: - assert lyr.GetSpatialRef().ExportToWkt().find("OSGB 1936") != -1 - - lyr = ds.GetLayerByName("STRATEGI_POINT") - feat = lyr.GetNextFeature() - assert feat.GetGeometryRef().ExportToWkt() == "POINT (222904 127850)" - - -############################################################################### -def test_ogr_ntf_2(): - - gdaltest.download_or_skip( - "http://www.ordnancesurvey.co.uk/oswebsite/products/meridian2/sampledata/meridian2ntf.exe", - "meridian2ntf.exe", - ) - - try: - os.stat("tmp/cache/Port_Talbot_NTF/SS78.ntf") - except OSError: - try: - gdaltest.unzip("tmp/cache", "tmp/cache/meridian2ntf.exe") - try: - os.stat("tmp/cache/Port_Talbot_NTF/SS78.ntf") - except OSError: - pytest.skip() - except OSError: - pytest.skip() - - ds = ogr.Open("tmp/cache/Port_Talbot_NTF/SS78.ntf") - assert ds.GetLayerCount() == 5 - - layers = [ - ("MERIDIAN2_POINT", ogr.wkbPoint, 408), - ("MERIDIAN2_LINE", ogr.wkbLineString, 513), - ("MERIDIAN2_TEXT", ogr.wkbPoint, 7), - ("MERIDIAN2_NODE", ogr.wkbNone, 397), - ("FEATURE_CLASSES", ogr.wkbNone, 50), - ] - - for l in layers: - lyr = ds.GetLayerByName(l[0]) - assert lyr.GetLayerDefn().GetGeomType() == l[1] - assert lyr.GetFeatureCount() == l[2] - if l[1] != ogr.wkbNone: - assert lyr.GetSpatialRef().ExportToWkt().find("OSGB 1936") != -1 - - lyr = ds.GetLayerByName("MERIDIAN2_POINT") - feat = lyr.GetNextFeature() - assert feat.GetGeometryRef().ExportToWkt() == "POINT (275324 189274)" - - lyr = ds.GetLayerByName("MERIDIAN2_LINE") - feat = lyr.GetNextFeature() - assert ( - feat.GetGeometryRef().ExportToWkt() - == "LINESTRING (275324 189274,275233 189114,275153 189048)" - ) diff --git a/autotest/ogr/ogr_ogdi.py b/autotest/ogr/ogr_ogdi.py deleted file mode 100755 index 9e8883b7d866..000000000000 --- a/autotest/ogr/ogr_ogdi.py +++ /dev/null @@ -1,204 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read functionality for OGR OGDI driver. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2010-2011, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import os - -import gdaltest -import ogrtest -import pytest - -from osgeo import ogr - -pytestmark = pytest.mark.require_driver("OGDI") - -############################################################################### - - -@pytest.fixture(scope="module", autouse=True) -def setup_and_cleanup(): - - # Skip tests when -fsanitize is used because of memleaks in libogdi - if gdaltest.is_travis_branch("sanitize"): - ogrtest.ogdi_drv = None - pytest.skip("Skipping because of memory leaks in OGDI") - - ogrtest.ogdi_drv = ogr.GetDriverByName("OGDI") - - -@pytest.fixture() -def ogdi_ds(): - - gdaltest.download_or_skip( - "http://freefr.dl.sourceforge.net/project/ogdi/OGDI_Test_Suite/3.1/ogdits-3.1.0.zip", - "ogdits-3.1.0.zip", - ) - - if not os.path.exists("tmp/cache/ogdits-3.1"): - gdaltest.unzip("tmp/cache", "tmp/cache/ogdits-3.1.0.zip") - - if not os.path.exists("tmp/cache/ogdits-3.1"): - pytest.skip("Could not extract test data") - - url_name = ( - "gltp:/vrf/" + os.getcwd() + "/tmp/cache/ogdits-3.1/data/vpf/vm2alv2/texash" - ) - - ds = ogr.Open(url_name) - assert ds is not None, "cannot open " + url_name - - return ds - - -def test_ogr_ogdi_1(ogdi_ds): - - assert ogdi_ds.GetLayerCount() == 57, "did not get expected layer count" - - layers = [ - ("libref@libref(*)_line", ogr.wkbLineString, 15), - ("libreft@libref(*)_text", ogr.wkbPoint, 4), - ("markersp@bnd(*)_point", ogr.wkbPoint, 40), - ("polbnda@bnd(*)_area", ogr.wkbPolygon, 6), - ] - - for l in layers: - lyr = ogdi_ds.GetLayerByName(l[0]) - assert lyr.GetLayerDefn().GetGeomType() == l[1] - assert lyr.GetFeatureCount() == l[2] - # if l[1] != ogr.wkbNone: - # if lyr.GetSpatialRef().ExportToWkt().find('WGS 84') == -1: - # return 'fail' - - lyr = ogdi_ds.GetLayerByName("libref@libref(*)_line") - feat = lyr.GetNextFeature() - - wkt = "LINESTRING (-97.570159912109375 31.242000579833984,-97.569938659667969 31.242116928100586,-97.562828063964844 31.245765686035156,-97.558868408203125 31.247797012329102,-97.555778503417969 31.249361038208008,-97.55413818359375 31.250171661376953)" - ref_geom = ogr.CreateGeometryFromWkt(wkt) - - ogrtest.check_feature_geometry(feat, ref_geom) - - -############################################################################### -# Run test_ogrsf - - -def test_ogr_ogdi_2(ogdi_ds): - - import test_cli_utilities - - if test_cli_utilities.get_test_ogrsf_path() is None: - pytest.skip() - - ret = gdaltest.runexternal( - test_cli_utilities.get_test_ogrsf_path() - + ' --config OGR_OGDI_LAUNDER_LAYER_NAMES YES -ro "' - + ogdi_ds.GetDescription() - + '" markersp_bnd contourl_elev polbnda_bnd extractp_ind' - ) - - assert ret.find("INFO") != -1 and ret.find("ERROR") == -1 - - -############################################################################### -# Test GetFeature() - - -def test_ogr_ogdi_3(ogdi_ds): - - lyr0 = ogdi_ds.GetLayer(0) - lyr0.ResetReading() - feat00_ref = lyr0.GetNextFeature() - feat01_ref = lyr0.GetNextFeature() - feat02_ref = lyr0.GetNextFeature() - - lyr1 = ogdi_ds.GetLayer(1) - lyr1.ResetReading() - feat10_ref = lyr1.GetNextFeature() - feat11_ref = lyr1.GetNextFeature() - - feat02 = lyr0.GetFeature(2) - feat00 = lyr0.GetFeature(0) - feat01 = lyr0.GetFeature(1) - feat10 = lyr1.GetFeature(0) - feat11 = lyr1.GetFeature(1) - - assert feat00.Equal(feat00_ref), "features not equal" - - assert feat01.Equal(feat01_ref), "features not equal" - - assert feat02.Equal(feat02_ref), "features not equal" - - assert feat10.Equal(feat10_ref), "features not equal" - - assert feat11.Equal(feat11_ref), "features not equal" - - -############################################################################### -# Extract of full dataset - - -def test_ogr_ogdi_4(): - - url_name = "gltp:/vrf/" + os.getcwd() + "/data/vm2alv2_texash/texash" - ds = ogr.Open(url_name) - assert ds is not None, "cannot open dataset" - - assert ds.GetLayerCount() == 6, "did not get expected layer count" - - layers = [("polbnda@bnd(*)_area", ogr.wkbPolygon, 6)] - - for l in layers: - lyr = ds.GetLayerByName(l[0]) - assert lyr.GetLayerDefn().GetGeomType() == l[1] - assert lyr.GetFeatureCount() == l[2] - - lyr = ds.GetLayerByName("polbnda@bnd(*)_area") - feat = lyr.GetNextFeature() - - if feat["id"] != 1 or feat["f_code"] != "FA001" or feat["acc"] != 1: - feat.DumpReadable() - pytest.fail("bad attributes") - - wkt = "POLYGON ((-97.6672973632812 31.250171661377,-97.5832977294922 31.250171661377,-97.5780029296875 31.250171661377,-97.5780029296875 31.250171661377,-97.5780944824219 31.2494583129883,-97.5779724121094 31.2492084503174,-97.577751159668 31.24880027771,-97.5776443481445 31.2484683990479,-97.5775451660156 31.2482070922852,-97.5774078369141 31.2479457855225,-97.5772705078125 31.2477989196777,-97.5771331787109 31.2477321624756,-97.5768661499023 31.2476787567139,-97.5766830444336 31.2476959228516,-97.5763168334961 31.2477016448975,-97.576042175293 31.247673034668,-97.5757141113281 31.2475509643555,-97.5754852294922 31.2473278045654,-97.5752792358398 31.2470207214356,-97.5751190185547 31.2467250823975,-97.5750122070312 31.2465076446533,-97.5748443603516 31.2462825775147,-97.5746002197266 31.2460918426514,-97.5742874145508 31.2459144592285,-97.5739288330078 31.2458171844482,-97.5736083984375 31.2457542419434,-97.5731201171875 31.2456817626953,-97.5728302001953 31.245641708374,-97.5724792480469 31.2455806732178,-97.5721817016602 31.2454471588135,-97.5719223022461 31.2453022003174,-97.5717086791992 31.2450218200684,-97.5715408325195 31.2446899414062,-97.5713882446289 31.2445201873779,-97.5711669921875 31.2442722320557,-97.5710678100586 31.2440910339355,-97.5711975097656 31.2438926696777,-97.5713577270508 31.2437191009521,-97.5718154907227 31.2434253692627,-97.5724258422852 31.2431831359863,-97.5726470947266 31.2430419921875,-97.5728530883789 31.2427291870117,-97.5728759765625 31.2424869537354,-97.57275390625 31.2423858642578,-97.5727996826172 31.2423534393311,-97.5712738037109 31.2422771453857,-97.5710067749023 31.2422466278076,-97.5707092285156 31.2421951293945,-97.5702285766602 31.2420444488525,-97.5701599121094 31.242000579834,-97.5701599121094 31.242000579834,-97.5794296264648 31.2372093200684,-97.5909194946289 31.2314224243164,-97.6050415039062 31.2241363525391,-97.6213302612305 31.2157878875732,-97.6490707397461 31.201566696167,-97.6662445068359 31.1928386688232,-97.6803207397461 31.1855792999268,-97.6936721801758 31.1787204742432,-97.7042617797852 31.1732997894287,-97.7107391357422 31.1699485778809,-97.7178192138672 31.1663246154785,-97.7325134277344 31.1587982177734,-97.7502975463867 31.1499614715576,-97.7502975463867 31.1499614715576,-97.7502975463867 31.1671733856201,-97.7502975463867 31.1671733856201,-97.7502975463867 31.250171661377,-97.6672973632812 31.250171661377))" - ref_geom = ogr.CreateGeometryFromWkt(wkt) - - ogrtest.check_feature_geometry(feat, ref_geom) - - ds = None - - # Test opening one single layer - ds = ogr.Open(url_name + ":polbnda@bnd(*):area") - assert ds is not None, "cannot open dataset" - assert ds.GetLayerCount() == 1, "did not get expected layer count" - - -############################################################################### -# Run test_ogrsf - - -def test_ogr_ogdi_5(): - - import test_cli_utilities - - if test_cli_utilities.get_test_ogrsf_path() is None: - pytest.skip() - - url_name = "gltp:/vrf/" + os.getcwd() + "/data/vm2alv2_texash/texash" - - ret = gdaltest.runexternal( - test_cli_utilities.get_test_ogrsf_path() - + ' --config OGR_OGDI_LAUNDER_LAYER_NAMES YES -ro "' - + url_name - + '"' - ) - - assert ret.find("INFO") != -1 and ret.find("ERROR") == -1 diff --git a/autotest/ogr/ogr_sdts.py b/autotest/ogr/ogr_sdts.py deleted file mode 100755 index 3fd0bd4bd838..000000000000 --- a/autotest/ogr/ogr_sdts.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test OGR SDTS driver functionality. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2008-2009, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - - -import gdaltest -import pytest - -from osgeo import gdal, ogr - -pytestmark = pytest.mark.require_driver("OGR_SDTS") - -############################################################################### -@pytest.fixture(autouse=True, scope="module") -def module_disable_exceptions(): - with gdaltest.disable_exceptions(): - yield - - -############################################################################### -# Test reading - - -def test_ogr_sdts_1(): - - ds = ogr.Open("data/sdts/D3607551_rd0s_1_sdts_truncated/TR01CATD.DDF") - - assert ds is not None - - layers = [ - ("ARDF", 164, ogr.wkbNone, [("ENTITY_LABEL", "1700005")]), - ("ARDM", 21, ogr.wkbNone, [("ROUTE_NUMBER", "SR 1200")]), - ( - "AHDR", - 1, - ogr.wkbNone, - [ - ( - "BANNER", - "USGS-NMD DLG DATA - CHARACTER FORMAT - 09-29-87 VERSION ", - ) - ], - ), - ("NP01", 4, ogr.wkbPoint, [("RCID", "1")]), - ("NA01", 34, ogr.wkbPoint, [("RCID", "2")]), - ("NO01", 88, ogr.wkbPoint, [("RCID", "1")]), - ("LE01", 27, ogr.wkbLineString, [("RCID", "1")]), - ("PC01", 35, ogr.wkbPolygon, [("RCID", "1")]), - ] - - for layer in layers: - lyr = ds.GetLayerByName(layer[0]) - assert lyr is not None, "could not get layer %s" % (layer[0]) - with gdal.quiet_errors(): - assert ( - lyr.GetFeatureCount() == layer[1] - ), "wrong number of features for layer %s : %d. %d were expected " % ( - layer[0], - lyr.GetFeatureCount(), - layer[1], - ) - assert lyr.GetLayerDefn().GetGeomType() == layer[2] - feat_read = lyr.GetNextFeature() - for item in layer[3]: - if feat_read.GetFieldAsString(item[0]) != item[1]: - print(layer[0]) - print('"%s"' % (item[1])) - pytest.fail('"%s"' % (feat_read.GetField(item[0]))) - - # Check that we get non-empty polygons - lyr = ds.GetLayerByName("PC01") - with gdal.quiet_errors(): - f = lyr.GetNextFeature() - g = f.GetGeometryRef() - assert g - assert g.GetGeometryType() == ogr.wkbPolygon25D - assert not g.IsEmpty() - - ds = None - - -############################################################################### -# diff --git a/autotest/ogr/ogr_tiger.py b/autotest/ogr/ogr_tiger.py deleted file mode 100755 index e24371d11087..000000000000 --- a/autotest/ogr/ogr_tiger.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read functionality for OGR TIGER driver. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2011-2012, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import os -import pathlib - -import gdaltest -import ogrtest -import pytest - -from osgeo import gdal, ogr - -pytestmark = pytest.mark.require_driver("Tiger") - -############################################################################### - - -@pytest.fixture(scope="module") -def TGR01001_dir(): - - gdaltest.download_or_skip( - "http://www2.census.gov/geo/tiger/tiger2006se/AL/TGR01001.ZIP", "TGR01001.ZIP" - ) - - dirname = pathlib.Path("tmp") / "cache" / "TGR01001" - - try: - os.stat("tmp/cache/TGR01001/TGR01001.MET") - except OSError: - try: - try: - os.stat("tmp/cache/TGR01001") - except OSError: - os.mkdir("tmp/cache/TGR01001") - gdaltest.unzip("tmp/cache/TGR01001", "tmp/cache/TGR01001.ZIP") - try: - os.stat("tmp/cache/TGR01001/TGR01001.MET") - except OSError: - pytest.skip() - except Exception: - pytest.skip() - - return dirname - - -def test_ogr_tiger_1(TGR01001_dir): - - tiger_ds = ogr.Open(TGR01001_dir) - assert tiger_ds is not None - - tiger_ds = None - # also test opening with a filename (#4443) - tiger_ds = ogr.Open(TGR01001_dir / "TGR01001.RT1") - assert tiger_ds is not None - - # Check a few features. - cc_layer = tiger_ds.GetLayerByName("CompleteChain") - assert cc_layer.GetFeatureCount() == 19289, "wrong cc feature count" - - feat = cc_layer.GetNextFeature() - feat = cc_layer.GetNextFeature() - feat = cc_layer.GetNextFeature() - - assert ( - feat.TLID == 2833200 and feat.FRIADDL is None and feat.BLOCKL == 5000 - ), "wrong attribute on cc feature." - - ogrtest.check_feature_geometry( - feat, - "LINESTRING (-86.4402 32.504137,-86.440313 32.504009,-86.440434 32.503884,-86.440491 32.503805,-86.44053 32.503757,-86.440578 32.503641,-86.440593 32.503515,-86.440588 32.503252,-86.440596 32.50298)", - max_error=0.000001, - ) - - feat = tiger_ds.GetLayerByName("TLIDRange").GetNextFeature() - assert ( - feat.MODULE == "TGR01001" and feat.TLMINID == 2822718 - ), "got wrong TLIDRange attributes" - - -############################################################################### -# Run test_ogrsf - - -def test_ogr_tiger_2(TGR01001_dir): - - import test_cli_utilities - - if test_cli_utilities.get_test_ogrsf_path() is None: - pytest.skip() - - ret = gdaltest.runexternal( - test_cli_utilities.get_test_ogrsf_path() + f" -ro {TGR01001_dir}" - ) - - assert ret.find("INFO") != -1 and ret.find("ERROR") == -1 - - -############################################################################### -# Load into a /vsimem instance to test virtualization. - - -def test_ogr_tiger_4(tmp_vsimem, TGR01001_dir): - - # load all the files into memory. - for filename in gdal.ReadDir(TGR01001_dir): - - if filename.startswith("."): - continue - - data = open(TGR01001_dir / filename, "r").read() - - f = gdal.VSIFOpenL(tmp_vsimem / filename, "wb") - gdal.VSIFWriteL(data, 1, len(data), f) - gdal.VSIFCloseL(f) - - # Try reading. - ogrtest.tiger_ds = ogr.Open(tmp_vsimem / "TGR01001.RT1") - assert ogrtest.tiger_ds is not None, "fail to open." - - ogrtest.tiger_ds = None - # also test opening with a filename (#4443) - ogrtest.tiger_ds = ogr.Open(tmp_vsimem / "TGR01001.RT1") - assert ogrtest.tiger_ds is not None - - # Check a few features. - cc_layer = ogrtest.tiger_ds.GetLayerByName("CompleteChain") - assert cc_layer.GetFeatureCount() == 19289, "wrong cc feature count" - - feat = cc_layer.GetNextFeature() - feat = cc_layer.GetNextFeature() - feat = cc_layer.GetNextFeature() - - assert ( - feat.TLID == 2833200 and feat.FRIADDL is None and feat.BLOCKL == 5000 - ), "wrong attribute on cc feature." - - ogrtest.check_feature_geometry( - feat, - "LINESTRING (-86.4402 32.504137,-86.440313 32.504009,-86.440434 32.503884,-86.440491 32.503805,-86.44053 32.503757,-86.440578 32.503641,-86.440593 32.503515,-86.440588 32.503252,-86.440596 32.50298)", - max_error=0.000001, - ) - - feat = ogrtest.tiger_ds.GetLayerByName("TLIDRange").GetNextFeature() - assert ( - feat.MODULE == "TGR01001" and feat.TLMINID == 2822718 - ), "got wrong TLIDRange attributes" diff --git a/cmake/helpers/CheckDependentLibraries.cmake b/cmake/helpers/CheckDependentLibraries.cmake index 09cf2536d907..3eaf1a074ea1 100644 --- a/cmake/helpers/CheckDependentLibraries.cmake +++ b/cmake/helpers/CheckDependentLibraries.cmake @@ -409,7 +409,6 @@ gdal_check_package(NetCDF "Enable netCDF driver" CAN_DISABLE NAMES netCDF TARGETS netCDF::netcdf NETCDF::netCDF VERSION "4.7") -gdal_check_package(OGDI "Enable ogr_OGDI driver" CAN_DISABLE) gdal_check_package(OpenCL "Enable OpenCL (may be used for warping)" CAN_DISABLE) set(PostgreSQL_ADDITIONAL_VERSIONS "14" CACHE STRING "Additional PostgreSQL versions to check") @@ -440,7 +439,6 @@ gdal_check_package(JXL_THREADS "JPEG-XL threading" CAN_DISABLE) gdal_check_package(Crnlib "enable gdal_DDS driver" CAN_DISABLE) gdal_check_package(basisu "Enable BASISU driver" CONFIG CAN_DISABLE) gdal_check_package(IDB "enable ogr_IDB driver" CAN_DISABLE) -gdal_check_package(rdb "enable RIEGL RDB library" CONFIG CAN_DISABLE) include(CheckDependentLibrariesTileDB) gdal_check_package(ExprTk "Enable C++ Mathematical Expression Tooklit Library (ExprTk) for VRT expressions" DISABLED_BY_DEFAULT) diff --git a/cmake/modules/packages/FindOGDI.cmake b/cmake/modules/packages/FindOGDI.cmake deleted file mode 100644 index 2077341f353f..000000000000 --- a/cmake/modules/packages/FindOGDI.cmake +++ /dev/null @@ -1,63 +0,0 @@ -# FindOGDI -# ~~~~~~~~~ -# -# Copyright (c) 2017, Hiroshi Miura -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. -# -# If it's found it sets OGDI_FOUND to TRUE -# and following variables are set: -# OGDI_INCLUDE_DIRS -# OGDI_LIBRARIES -# OGDI_VERSION -# - -find_package(PkgConfig QUIET) -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_OGDI QUIET ogdi) - set(OGDI_VERSION_STRING ${PC_OGDI_VERSION}) - set(OGDI_INCLUDE_DIRS ${PC_OGDI_INCLUDE_DIRS}) -endif() - -find_path(OGDI_INCLUDE_DIR ecs.h - HINTS ${PC_OGDI_INCLUDE_DIRS} - PATH_SUFFIXES ogdi) -mark_as_advanced(OGDI_INCLUDE_DIR) - -find_library(OGDI_LIBRARY NAMES ogdi libogdi NAMES_PER_DIR) -mark_as_advanced(OGDI_LIBRARY) - -if(OGDI_INCLUDE_DIR AND OGDI_LIBRARY) - find_program(OGDI_CONFIG_EXE ogdi-config) - mark_as_advanced(OGDI_CONFIG_EXE) - execute_process(COMMAND ${OGDI_CONFIG_EXE} --version - OUTPUT_VARIABLE OGDI_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process(COMMAND ${OGDI_CONFIG_EXE} --cflags - OUTPUT_VARIABLE _cflags OUTPUT_STRIP_TRAILING_WHITESPACE - ) - # Collect paths of include directories from CFLAGS - separate_arguments(_cflags NATIVE_COMMAND "${_cflags}") - foreach(arg IN LISTS _cflags) - if("${arg}" MATCHES "^-I(.*)$") - list(APPEND OGDI_INCLUDE_DIRS "${CMAKE_MATCH_1}") - endif() - endforeach() - unset(_cflags) -endif() - -find_package_handle_standard_args(OGDI REQUIRED_VARS OGDI_LIBRARY OGDI_INCLUDE_DIRS - VERSION_VAR OGDI_VERSION) - -if(OGDI_FOUND) - set(OGDI_LIBRARIES ${OGDI_LIBRARY}) - set(OGDI_INCLUDE_DIRS ${OGDI_INCLUDE_DIRS}) - if(NOT TARGET OGDI::OGDI) - add_library(OGDI::OGDI UNKNOWN IMPORTED) - set_target_properties(OGDI::OGDI PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${OGDI_INCLUDE_DIRS}" - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${OGDI_LIBRARY}") - endif() -endif() diff --git a/doc/source/development/building_from_source.rst b/doc/source/development/building_from_source.rst index 9103a013c444..c510f32569e3 100644 --- a/doc/source/development/building_from_source.rst +++ b/doc/source/development/building_from_source.rst @@ -1490,25 +1490,6 @@ the :ref:`vector.hana` driver. Control whether to use ODBC-CPP. Defaults to ON when ODBC-CPP is found. -OGDI -**** - -The `OGDI `_ library is required for the :ref:`vector.ogdi` -driver. It can be detected with pkg-config. - -.. option:: OGDI_INCLUDE_DIR - - Path to an include directory with the ``ecs.h`` header file. - -.. option:: OGDI_LIBRARY - - Path to a shared or static library file. - -.. option:: GDAL_USE_OGDI=ON/OFF - - Control whether to use OGDI. Defaults to ON when OGDI is found. - - OpenCAD ******* @@ -1849,18 +1830,6 @@ It can be detected with pkg-config. Control whether to use RasterLite2. Defaults to ON when RasterLite2 is found. -rdb -*** - -The `RDB ` -(closed source/proprietary) library is required for the :ref:`raster.rdb` driver. -Specify install prefix in the ``CMAKE_PREFIX_PATH`` variable. - -.. option:: GDAL_USE_RDB=ON/OFF - - Control whether to use rdb. Defaults to ON when rdb is found. - - SPATIALITE ********** diff --git a/doc/source/drivers/raster/adrg.rst b/doc/source/drivers/raster/adrg.rst index 8dfcc170a0af..90f5e5f06455 100644 --- a/doc/source/drivers/raster/adrg.rst +++ b/doc/source/drivers/raster/adrg.rst @@ -8,10 +8,7 @@ ADRG -- ADRG/ARC Digitized Raster Graphics (.gen/.thf) .. built_in_by_default:: -Supported by GDAL for read access. Creation is possible, but it must be -considered as experimental and a means of testing read access (although -files created by the driver can be read successfully on another GIS -software) +Supported by GDAL for read access. An ADRG dataset is made of several files. The file recognised by GDAL is the General Information File (.GEN). GDAL will also need the image file @@ -32,10 +29,6 @@ See also : the `ADRG specification Driver capabilities ------------------- -.. supports_createcopy:: - -.. supports_create:: - .. supports_georeferencing:: .. supports_virtualio:: diff --git a/doc/source/drivers/raster/blx.rst b/doc/source/drivers/raster/blx.rst deleted file mode 100644 index d9bc0b7066bf..000000000000 --- a/doc/source/drivers/raster/blx.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. _raster.blx: - -================================================================================ -BLX -- Magellan BLX Topo File Format -================================================================================ - -.. shortname:: BLX - -.. built_in_by_default:: - -BLX is the format for storing topographic data in Magellan GPS units. -This driver supports both reading and writing. In addition the 4 -overview levels inherent in the BLX format can be used with the driver. - -The BLX format is tile based, for the moment the tile size is fixed to -128x128 size. Furthermore the dimensions must be a multiple of the tile -size. - -The data type is fixed to Int16 and the value for undefined values is -fixed to -32768. In the BLX format undefined values are only really -supported on tile level. For undefined pixels in non-empty tiles see the -FILLUNDEF/FILLUNDEFVAL options. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_georeferencing:: - -.. supports_virtualio:: - -Georeferencing --------------- - -The BLX projection is fixed to WGS84 and georeferencing from BLX is -supported in the form of one tiepoint and pixelsize. - -Creation Options ----------------- - -|about-creation-options| -The following creation options are supported: - -- .. co:: ZSCALE - :default: 1 - - Set the desired quantization increment for write - access. A higher value will result in better compression and lower - vertical resolution. - -- .. co:: BIGENDIAN - :choices: YES, NO - - If BIGENDIAN is defined, the output file will be - in XLB format (big endian blx). - -- .. co:: FILLUNDEF - :choices: YES, NO - - If FILLUNDEF is yes the value of :co:`FILLUNDEFVAL` will - be used instead of -32768 for non-empty tiles. This is needed since - the BLX format only support undefined values for full tiles, not - individual pixels. - -- .. co:: FILLUNDEFVAL - :choices: - - See :co:`FILLUNDEF`. diff --git a/doc/source/drivers/raster/bt.rst b/doc/source/drivers/raster/bt.rst deleted file mode 100644 index 9a7ede7256e3..000000000000 --- a/doc/source/drivers/raster/bt.rst +++ /dev/null @@ -1,42 +0,0 @@ -.. _raster.bt: - -================================================================================ -BT -- VTP .bt Binary Terrain Format -================================================================================ - -.. shortname:: BT - -.. built_in_by_default:: - -The .bt format is used for elevation data in the VTP software. The -driver includes support for reading and writing .bt 1.3 format including -support for Int16, Int32 and Float32 pixel data types. - -The driver does **not** support reading or writing gzipped (.bt.gz) .bt -files even though this is supported by the VTP software. Please unpack -the files before using with GDAL using the "gzip -d file.bt.gz". - -Projections in external .prj files are read and written, and support for -most internally defined coordinate systems is also available. - -Read/write imagery access with the GDAL .bt driver is terribly slow due -to a very inefficient access strategy to this column oriented data. This -could be corrected, but it would be a fair effort. - -NOTE: Implemented as :source_file:`frmts/raw/btdataset.cpp`. - -See Also: The `BT file -format `__ is -defined on the `VTP `__ web site. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_create:: - -.. supports_georeferencing:: - -.. supports_virtualio:: - diff --git a/doc/source/drivers/raster/byn.rst b/doc/source/drivers/raster/byn.rst index efe70ae25e8c..82ae0f99b20b 100644 --- a/doc/source/drivers/raster/byn.rst +++ b/doc/source/drivers/raster/byn.rst @@ -43,10 +43,6 @@ will have variable Data equal to 1 or 3. Driver capabilities ------------------- -.. supports_createcopy:: - -.. supports_create:: - .. supports_georeferencing:: .. supports_virtualio:: @@ -54,7 +50,7 @@ Driver capabilities Factor ------ -When translating from or into BYN file to or from another formats the +When translating from BYN file to or from another formats the scale will affect the result profoundly. Translating to a format that supports Scale (GTIFF for example) will diff --git a/doc/source/drivers/raster/ctable2.rst b/doc/source/drivers/raster/ctable2.rst deleted file mode 100644 index 70304144698b..000000000000 --- a/doc/source/drivers/raster/ctable2.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. _raster.ctable2: - -================================================================================ -CTable2 -- CTable2 Datum Grid Shift -================================================================================ - -.. shortname:: CTable2 - -.. built_in_by_default:: - -NOTE: Implemented as :source_file:`frmts/raw/ctable2dataset.cpp`. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_create:: - -.. supports_georeferencing:: - -.. supports_virtualio:: - diff --git a/doc/source/drivers/raster/dipex.rst b/doc/source/drivers/raster/dipex.rst deleted file mode 100644 index d6cda7aef5b1..000000000000 --- a/doc/source/drivers/raster/dipex.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _raster.dipex: - -================================================================================ -DIPEx -- ELAS DIPEx -================================================================================ - -.. shortname:: DIPEx - -.. built_in_by_default:: - -NOTE: Implemented as :source_file:`frmts/raw/dipxdataset.cpp`. - -Driver capabilities -------------------- - -.. supports_georeferencing:: - -.. supports_virtualio:: diff --git a/doc/source/drivers/raster/elas.rst b/doc/source/drivers/raster/elas.rst deleted file mode 100644 index e3ff222edd89..000000000000 --- a/doc/source/drivers/raster/elas.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _raster.elas: - -================================================================================ -ELAS - Earth Resources Laboratory Applications Software -================================================================================ - -.. shortname:: ELAS - -.. built_in_by_default:: - -ELAS is an old remote sensing system still used for a variety of -research projects within NASA. The ELAS format support can be found in -:source_file:`frmts/elas`. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_create:: - -.. supports_georeferencing:: - -.. supports_virtualio:: - -See Also --------- - -- `Short announcement of ELAS driver in - GDAL `__ -- `NASA Software Used In Imaging - Service `__ - includes ELAS overview diff --git a/doc/source/drivers/raster/fit.rst b/doc/source/drivers/raster/fit.rst deleted file mode 100644 index cbdcd4468969..000000000000 --- a/doc/source/drivers/raster/fit.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. _raster.fit: - -================================================================================ -FIT -- FIT -================================================================================ - -.. shortname:: FIT - -.. built_in_by_default:: - -NOTE: Implemented as :source_file:`frmts/fit/fitdataset.cpp`. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_georeferencing:: - -.. supports_virtualio:: diff --git a/doc/source/drivers/raster/gs7bg.rst b/doc/source/drivers/raster/gs7bg.rst index 28e9609b2a96..2eca64c8d594 100644 --- a/doc/source/drivers/raster/gs7bg.rst +++ b/doc/source/drivers/raster/gs7bg.rst @@ -10,8 +10,6 @@ GS7BG -- Golden Software Surfer 7 Binary Grid File Format This is the binary (non-human-readable) version of one of the raster formats used by Golden Software products (such as the Surfer series). -This format differs from the :ref:`raster.gsbg` format (also known as -Surfer 6 binary grid format), it is more complicated and flexible. NOTE: Implemented as :source_file:`frmts/gsg/gs7bgdataset.cpp`. diff --git a/doc/source/drivers/raster/gsag.rst b/doc/source/drivers/raster/gsag.rst deleted file mode 100644 index 138edc5343fb..000000000000 --- a/doc/source/drivers/raster/gsag.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. _raster.gsag: - -================================================================================ -GSAG -- Golden Software ASCII Grid File Format -================================================================================ - -.. shortname:: GSAG - -.. built_in_by_default:: - -This is the ASCII-based (human-readable) version of one of the raster -formats used by Golden Software products (such as the Surfer series). -This format is supported for both reading and writing (copy mode only). -Currently the associated formats for color, metadata, -and shapes are not supported. - -NOTE: Implemented as :source_file:`frmts/gsg/gsagdataset.cpp`. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_georeferencing:: - -.. supports_virtualio:: - diff --git a/doc/source/drivers/raster/gsbg.rst b/doc/source/drivers/raster/gsbg.rst deleted file mode 100644 index fe083b65be40..000000000000 --- a/doc/source/drivers/raster/gsbg.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _raster.gsbg: - -================================================================================ -GSBG -- Golden Software Binary Grid File Format -================================================================================ - -.. shortname:: GSBG - -.. built_in_by_default:: - -This is the binary (non-human-readable) version of one of the raster -formats used by Golden Software products (such as the Surfer series). -Like the ASCII version, this format is supported for both reading and -writing (including create, delete, and copy). Currently the associated -formats for color, metadata, and shapes are not supported. - -Surfer 8 uses a fixed nodata value at 1.701410009187828e+38. When writing a -GSBG dataset, GDAL remaps the user-specified input nodata value to 1.701410009187828e+38. - -NOTE: Implemented as :source_file:`frmts/gsg/gsbgdataset.cpp`. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_create:: - -.. supports_georeferencing:: - -.. supports_virtualio:: diff --git a/doc/source/drivers/raster/index.rst b/doc/source/drivers/raster/index.rst index f35fede51cda..fade9dc11eb6 100644 --- a/doc/source/drivers/raster/index.rst +++ b/doc/source/drivers/raster/index.rst @@ -29,10 +29,8 @@ Raster drivers avif bag basisu - blx bmp bsb - bt byn cad cals @@ -41,13 +39,11 @@ Raster drivers cog cosar cpg - ctable2 ctg daas dds derived dimap - dipex doq1 doq2 dted @@ -56,14 +52,12 @@ Raster drivers eedai ehdr eir - elas envi esat esric ers exr fast - fit fits genbin georaster @@ -74,8 +68,6 @@ Raster drivers grassasciigrid grib gs7bg - gsag - gsbg gsc gta gti @@ -143,10 +135,7 @@ Raster drivers pnm postgisraster prf - rasterlite rasterlite2 - r - rdb rcm rik rmf @@ -160,9 +149,7 @@ Raster drivers safe sar_ceos sdat - sdts sentinel2 - sgi sigdem snap_tiff snodas @@ -182,7 +169,6 @@ Raster drivers webp wms wmts - xpm xyz zarr zmap diff --git a/doc/source/drivers/raster/isis2.rst b/doc/source/drivers/raster/isis2.rst index b57655ffaa47..9d3beed50a2a 100644 --- a/doc/source/drivers/raster/isis2.rst +++ b/doc/source/drivers/raster/isis2.rst @@ -9,7 +9,7 @@ ISIS2 -- USGS Astrogeology ISIS Cube (Version 2) .. built_in_by_default:: ISIS2 is a format used by the USGS Planetary Cartography group to store -and distribute planetary imagery data. GDAL provides read and write +and distribute planetary imagery data. GDAL provides read access to ISIS2 formatted imagery data. ISIS2 files often have the extension .cub, sometimes with an associated @@ -28,41 +28,10 @@ ISIS2 is part of a family of related formats including PDS and ISIS3. Driver capabilities ------------------- -.. supports_createcopy:: - -.. supports_create:: - .. supports_georeferencing:: .. supports_virtualio:: -Creation Issues ---------------- - -Currently the ISIS2 writer writes a very minimal header with only the -image structure information. No coordinate system, georeferencing or -other metadata is captured. - -Creation Options -~~~~~~~~~~~~~~~~ - -|about-creation-options| -The following creation options are supported: - -- .. co:: LABELING_METHOD - :choices: ATTACHED, DETACHED - :default: ATTACHED - - Determines whether the header - labeling should be in the same file as the imagery (ATTACHED) - or in a separate file (DETACHED). - -- .. co:: IMAGE_EXTENSION - :default: cub - - Set the extension used for detached image files. Only used if - :co:`LABELING_METHOD=DETACHED`. - See Also -------- diff --git a/doc/source/drivers/raster/lan.rst b/doc/source/drivers/raster/lan.rst index 736846e2516b..3e1d8ba580cb 100644 --- a/doc/source/drivers/raster/lan.rst +++ b/doc/source/drivers/raster/lan.rst @@ -8,9 +8,9 @@ LAN -- Erdas 7.x .LAN and .GIS .. built_in_by_default:: -GDAL supports reading and writing Erdas 7.x .LAN and .GIS raster files. +GDAL supports reading Erdas 7.x .LAN and .GIS raster files. Currently 4bit, 8bit and 16bit pixel data types are supported for -reading and 8bit and 16bit for writing. +reading. GDAL does read the map extents (geotransform) from LAN/GIS files, and attempts to read the coordinate system information. However, this format @@ -31,5 +31,3 @@ Driver capabilities .. supports_georeferencing:: .. supports_virtualio:: - -.. supports_create:: diff --git a/doc/source/drivers/raster/mff.rst b/doc/source/drivers/raster/mff.rst index 93e03461975f..51485b264348 100644 --- a/doc/source/drivers/raster/mff.rst +++ b/doc/source/drivers/raster/mff.rst @@ -8,7 +8,7 @@ MFF -- Vexcel MFF Raster .. built_in_by_default:: -GDAL includes read, update, and creation support for Vexcel's MFF raster +GDAL includes read support for Vexcel's MFF raster format. MFF dataset consist of a header file (typically with the extension .hdr) and a set of data files with extensions like .x00, .b00 and so on. To open a dataset select the .hdr file. @@ -23,9 +23,6 @@ and 64 bit data precisions in integer, real and complex data types. In addition tile organized files (as produced by the Vexcel SAR Processor - APP) are supported for reading. -On creation (with a format code of MFF) a simple, ungeoreferenced raster -file is created. - MFF files are not normally portable between systems with different byte orders. However GDAL honours the new BYTE_ORDER keyword which can take a value of LSB (Integer - little endian), and MSB (Motorola - big @@ -36,10 +33,6 @@ NOTE: Implemented as :source_file:`frmts/raw/mffdataset.cpp`. Driver capabilities ------------------- -.. supports_createcopy:: - -.. supports_create:: - .. supports_georeferencing:: .. supports_virtualio:: diff --git a/doc/source/drivers/raster/mff2.rst b/doc/source/drivers/raster/mff2.rst index b091efbfbc38..1de60c9fc141 100644 --- a/doc/source/drivers/raster/mff2.rst +++ b/doc/source/drivers/raster/mff2.rst @@ -8,8 +8,8 @@ MFF2 -- Vexcel MFF2 Image .. built_in_by_default:: -GDAL supports MFF2 Image raster file format for read, update, and -creation. The MFF2 (Multi-File Format 2) format was designed to fit into +GDAL supports MFF2 Image raster file format for read. +The MFF2 (Multi-File Format 2) format was designed to fit into Vexcel Hierarchical Key-Value (HKV) databases, which can store binary data as well as ASCII parameters. This format is primarily used internally to the Vexcel InSAR processing system. @@ -23,25 +23,14 @@ affine transform computed from the lat/long control points. In any event, if GCPs are available in a georef file, they are returned with the dataset. -Newly created files (with a type of ``MFF2``) are always just raw -rasters with no georeferencing information. For read, and creation all -data types (real, integer and complex in bit depths of 8, 16, 32) should +For read, all data types (real, integer and complex in bit depths of 8, 16, 32) should be supported. -IMPORTANT: When creating a new MFF2, be sure to set the projection -before setting the geotransform (this is necessary because the -geotransform is stored internally as 5 latitude-longitude ground control -points, and the projection is needed to do the conversion). - NOTE: Implemented as :source_file:`frmts/raw/hkvdataset.cpp`. Driver capabilities ------------------- -.. supports_createcopy:: - -.. supports_create:: - .. supports_georeferencing:: .. supports_virtualio:: diff --git a/doc/source/drivers/raster/ntv2.rst b/doc/source/drivers/raster/ntv2.rst index e570f38423ab..2b4e1325a521 100644 --- a/doc/source/drivers/raster/ntv2.rst +++ b/doc/source/drivers/raster/ntv2.rst @@ -13,10 +13,6 @@ NOTE: Implemented as :source_file:`frmts/raw/ntv2dataset.cpp`. Driver capabilities ------------------- -.. supports_createcopy:: - -.. supports_create:: - .. supports_georeferencing:: .. supports_virtualio:: diff --git a/doc/source/drivers/raster/paux.rst b/doc/source/drivers/raster/paux.rst index 55c1b7c2567b..b3fc73bb428d 100644 --- a/doc/source/drivers/raster/paux.rst +++ b/doc/source/drivers/raster/paux.rst @@ -17,28 +17,10 @@ The format type for creating new files is ``PAux``. All PCI data types (8U, 16U, 16S, and 32R) are supported. Currently georeferencing, projections, and other metadata is ignored. -Creation Options: - -- .. co:: INTERLEAVE - :choices: PIXEL, LINE, BAND - :default: BAND - - Establish output interleaving. - Starting with GDAL 3.5, when copying from a source dataset with multiple bands - which advertises a INTERLEAVE metadata item, if the INTERLEAVE creation option - is not specified, the source dataset INTERLEAVE will be automatically taken - into account. - -NOTE: Implemented as :source_file:`frmts/raw/pauxdataset.cpp`. - See Also: `PCI's .aux Format Description `__ Driver capabilities ------------------- -.. supports_createcopy:: - -.. supports_create:: - .. supports_virtualio:: diff --git a/doc/source/drivers/raster/r.rst b/doc/source/drivers/raster/r.rst deleted file mode 100644 index 69a33245d250..000000000000 --- a/doc/source/drivers/raster/r.rst +++ /dev/null @@ -1,50 +0,0 @@ -.. _raster.r: - -================================================================================ -R -- R Object Data Store -================================================================================ - -.. shortname:: R - -.. built_in_by_default:: - -The R Object File Format is supported for write access, and limited read -access by GDAL. This format is the native format R uses for objects -saved with the *save* command and loaded with the *load* command. GDAL -supports writing a dataset as an array object in this format, and -supports reading files with simple rasters in essentially the same -organization. It will not read most R object files. - -Currently there is no support for reading or writing georeferencing -information. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_virtualio:: - -Creation Options ----------------- - -|about-creation-options| -The following creation options are available: - -- .. co:: ASCII - :choices: YES, NO - :default: NO - - Produce an ASCII formatted file, instead of binary, - if set to YES. - -- .. co:: COMPRESS - :choices: YES, NO - :default: YES - - Produces a compressed file if YES, otherwise an - uncompressed file. - -See Also: - -- `R Project `__ diff --git a/doc/source/drivers/raster/rasterlite.rst b/doc/source/drivers/raster/rasterlite.rst deleted file mode 100644 index 6e6b35d89c60..000000000000 --- a/doc/source/drivers/raster/rasterlite.rst +++ /dev/null @@ -1,300 +0,0 @@ -.. _raster.rasterlite: - -================================================================================ -Rasterlite - Rasters in SQLite DB -================================================================================ - -.. shortname:: Rasterlite - -.. build_dependencies:: libsqlite3 - -The Rasterlite driver allows reading and -creating Rasterlite databases. - -| Those databases can be produced by the utilities of the - `rasterlite `__ distribution, such - as rasterlite_load, rasterlite_pyramids, .... -| The driver supports reading grayscale, paletted and RGB images stored - as GIF, PNG, TIFF or JPEG tiles. The driver also supports reading - overviews/pyramids, spatial reference system and spatial extent. - -GDAL/OGR must be compiled with OGR SQLite driver support. For read -support, linking against spatialite library is not required, but recent -enough sqlite3 library is needed to read rasterlite databases. -rasterlite library is not required either. - -For write support a new table, linking against spatialite library \*is\* -required. - -Although the Rasterlite documentation only mentions GIF, PNG, TIFF, JPEG -as compression formats for tiles, the -driver supports reading and writing internal tiles in any format handled -by GDAL. Furthermore, the Rasterlite driver also allow reading and -writing as many bands and as many band types as supported by the driver -for the internal tiles. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_georeferencing:: - -.. supports_virtualio:: - -Connection string syntax in read mode -------------------------------------- - -Syntax: 'rasterlitedb_name' or -'RASTERLITE:rasterlitedb_name[,table=raster_table_prefix][,minx=minx_val,miny=miny_val,maxx=maxx_val,maxy=maxy_val][,level=level_number] - -where : - -- *rasterlitedb_name* is the filename of the RasterLite DB. -- *raster_table_prefix* is the prefix of the raster table to open. For - each raster, there are 2 corresponding SQLite tables, suffixed with - \_rasters and \_metadata -- *minx_val,miny_val,maxx_val,maxy_val* set a user-defined extent - (expressed in coordinate system units) for the raster that can be - different from the default extent. -- *level_number* is the level of the pyramid/overview to open, 0 being - the base pyramid. - -Creation issues ---------------- - -The driver can create a new database if necessary, create a new raster -table if necessary and copy a source dataset into the specified raster -table. - -If data already exists in the raster table, the new data will be added. -You can use the WIPE=YES creation options to erase existing data. - -The driver does not support updating a block in an existing raster -table. It can only append new data. - -Syntax for the name of the output dataset: -'RASTERLITE:rasterlitedb_name,table=raster_table_prefix' or -'rasterlitedb_name' - -It is possible to specify only the DB name as in the later form, but -only if the database does not already exists. In that case, the raster -table name will be base on the DB name itself. - -Creation options -~~~~~~~~~~~~~~~~ - -|about-creation-options| -The following creation options are supported: - -- .. co:: WIPE - - Set to YES to erase all preexisting data - in the specified table - -- .. co:: TILED - - Set to NO if the source dataset must be - written as a single tile in the raster table - -- .. co:: BLOCKXSIZE - :choices: - :default: 256 - - Sets tile width. - -- .. co:: BLOCKYSIZE - :choices: - :default: 256 - - Sets tile height. - -- .. co:: DRIVER - :default: GTiff - - name of the GDAL - driver to use for storing tiles. - -- .. co:: COMPRESS - :choices: LZW, JPEG, DEFLATE, ... - - (GTiff driver) name of the - compression method - -- .. co:: PHOTOMETRIC - :choices: RGB, YCbCr, ... - - (GTiff driver) photometric interpretation - -- .. co:: QUALITY - :choices: [1-100] - :default: 75 - - (JPEG-compressed GTiff, JPEG and WEBP drivers) - JPEG/WEBP quality. - -Configuration options -~~~~~~~~~~~~~~~~~~~~~ - -|about-config-options| -The following configuration option is supported: - -- .. config:: RASTERLITE_OVR_OPTIONS - - Comma-separated list of creation options to be applied to overviews. - See `Overviews`_. - -Overviews ---------- - -The driver supports building (if the dataset is opened in update mode) -and reading internal overviews. - -If no internal overview is detected, the driver will try using external -overviews (.ovr files). - -Options can be used for internal overviews -building. They can be specified with the :config:`RASTERLITE_OVR_OPTIONS` -configuration option, as a comma separated list of the above creation -options. See below examples. - -All resampling methods supported by GDAL -overviews are available. - -Performance hints ------------------ - -Some of the performance hints of the OGR SQLite driver apply. In -particular setting the OGR_SQLITE_SYNCHRONOUS configuration option to -OFF when creating a dataset or adding overviews might increase -performance on some filesystems. - -After having added all the raster tables and building all the needed -overview levels, it is advised to run : - -:: - - ogrinfo rasterlitedb.sqlite -sql "VACUUM" - -in order to optimize the database, and increase read performances -afterwards. This is particularly true with big rasterlite datasets. Note -that the operation might take a long time. - -Examples --------- - -- Accessing a rasterlite DB with a single raster table : - - :: - - $ gdalinfo rasterlitedb.sqlite -noct - - Output: - - :: - - Driver: Rasterlite/Rasterlite - Files: rasterlitedb.sqlite - Size is 7200, 7200 - Coordinate System is: - GEOGCS["WGS 84", - DATUM["WGS_1984", - SPHEROID["WGS 84",6378137,298.257223563, - AUTHORITY["EPSG","7030"]], - AUTHORITY["EPSG","6326"]], - PRIMEM["Greenwich",0, - AUTHORITY["EPSG","8901"]], - UNIT["degree",0.01745329251994328, - AUTHORITY["EPSG","9122"]], - AUTHORITY["EPSG","4326"]] - Origin = (-5.000000000000000,55.000000000000000) - Pixel Size = (0.002083333333333,-0.002083333333333) - Metadata: - TILE_FORMAT=GIF - Image Structure Metadata: - INTERLEAVE=PIXEL - Corner Coordinates: - Upper Left ( -5.0000000, 55.0000000) ( 5d 0'0.00"W, 55d 0'0.00"N) - Lower Left ( -5.0000000, 40.0000000) ( 5d 0'0.00"W, 40d 0'0.00"N) - Upper Right ( 10.0000000, 55.0000000) ( 10d 0'0.00"E, 55d 0'0.00"N) - Lower Right ( 10.0000000, 40.0000000) ( 10d 0'0.00"E, 40d 0'0.00"N) - Center ( 2.5000000, 47.5000000) ( 2d30'0.00"E, 47d30'0.00"N) - Band 1 Block=480x480 Type=Byte, ColorInterp=Palette - Color Table (RGB with 256 entries) - -- Listing a multi-raster table DB : - - :: - - $ gdalinfo multirasterdb.sqlite - - Output: - - :: - - Driver: Rasterlite/Rasterlite - Files: - Size is 512, 512 - Coordinate System is `' - Subdatasets: - SUBDATASET_1_NAME=RASTERLITE:multirasterdb.sqlite,table=raster1 - SUBDATASET_1_DESC=RASTERLITE:multirasterdb.sqlite,table=raster1 - SUBDATASET_2_NAME=RASTERLITE:multirasterdb.sqlite,table=raster2 - SUBDATASET_2_DESC=RASTERLITE:multirasterdb.sqlite,table=raster2 - Corner Coordinates: - Upper Left ( 0.0, 0.0) - Lower Left ( 0.0, 512.0) - Upper Right ( 512.0, 0.0) - Lower Right ( 512.0, 512.0) - Center ( 256.0, 256.0) - -- Accessing a raster table within a multi-raster table DB: - - :: - - $ gdalinfo RASTERLITE:multirasterdb.sqlite,table=raster1 - -- Creating a new rasterlite DB with data encoded in JPEG tiles : - - :: - - $ gdal_translate -of Rasterlite source.tif RASTERLITE:my_db.sqlite,table=source -co DRIVER=JPEG - -- Creating internal overviews : - - :: - - $ gdaladdo RASTERLITE:my_db.sqlite,table=source 2 4 8 16 - -- Cleaning internal overviews : - - :: - - $ gdaladdo -clean RASTERLITE:my_db.sqlite,table=source - -- Creating external overviews in a .ovr file: - - :: - - $ gdaladdo -ro RASTERLITE:my_db.sqlite,table=source 2 4 8 16 - -- Creating internal overviews with options (GDAL 1.10 or later): - - :: - - $ gdaladdo RASTERLITE:my_db.sqlite,table=source 2 4 8 16 --config RASTERLITE_OVR_OPTIONS DRIVER=GTiff,COMPRESS=JPEG,PHOTOMETRIC=YCbCr - -: - -See Also --------- - -- `Spatialite and Rasterlite home - page `__ -- `Rasterlite - manual `__ -- `Rasterlite - howto `__ -- `Sample - databases `__ -- :ref:`OGR SQLite driver ` diff --git a/doc/source/drivers/raster/rdb.rst b/doc/source/drivers/raster/rdb.rst deleted file mode 100644 index e7ae0b2030c5..000000000000 --- a/doc/source/drivers/raster/rdb.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. _raster.rdb: - -================================================================================ -RDB - *RIEGL* Database -================================================================================ - -.. shortname:: RDB - -.. versionadded:: 3.1 - -.. build_dependencies:: rdblib >= 2.2.0. - -GDAL can read \*.mpx files in the RDB format, the in-house format used by `RIEGL Laser Measurement Systems GmbH `__ through the RDB library. - -The driver relies on the RDB library, which can be downloaded `here `__ . The minimum version required of the rdblib is 2.2.0. - -Driver capabilities -------------------- - -.. supports_georeferencing:: - -Provided Bands -------------------- - -All attributes stored in the RDB, but the coordinates, are provided in bands. Vector attributes are split up into multiple bands. -The attributes are currently mapped as follows: - -+----------------------------+-------------------------+ -| RDB attribute | GDAL Band | -+============================+=========================+ -| riegl.surface_normal[0], | Band 1 | -| | | -| riegl.surface_normal[1], | Band 2 | -| | | -| riegl.surface_normal[2] | Band 3 | -+----------------------------+-------------------------+ -| riegl.timestamp_min | Band 4 | -+----------------------------+-------------------------+ -| riegl.timestamp_max | Band 5 | -+----------------------------+-------------------------+ -| riegl.reflectance | Band 6 | -+----------------------------+-------------------------+ -| riegl.amplitude | Band 7 | -+----------------------------+-------------------------+ -| riegl.deviation | Band 8 | -+----------------------------+-------------------------+ -| riegl.height_center | Band 9 | -+----------------------------+-------------------------+ -| riegl.height_mean | Band 10 | -+----------------------------+-------------------------+ -| riegl.height_min | Band 11 | -+----------------------------+-------------------------+ -| riegl.height_max | Band 12 | -+----------------------------+-------------------------+ -| riegl.point_count | Band 13 | -+----------------------------+-------------------------+ -| riegl.point_count_grid_cell| Band 14 | -+----------------------------+-------------------------+ -| riegl.pca_thickness | Band 15 | -+----------------------------+-------------------------+ -| riegl.std_dev | Band 16 | -+----------------------------+-------------------------+ -| riegl.voxel_count | Band 17 | -+----------------------------+-------------------------+ -| riegl.id | Band 18 | -+----------------------------+-------------------------+ diff --git a/doc/source/drivers/raster/sdts.rst b/doc/source/drivers/raster/sdts.rst deleted file mode 100644 index fc76c8c32e80..000000000000 --- a/doc/source/drivers/raster/sdts.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _raster.sdts: - -================================================================================ -SDTS -- USGS SDTS DEM -================================================================================ - -.. shortname:: SDTS - -.. built_in_by_default:: - -GDAL includes support for reading USGS SDTS formatted DEMs. USGS DEMs -are always returned with a data type of signed sixteen bit integer, or -32bit float. Projection and georeferencing information is also returned. - -SDTS datasets consist of a number of files. Each DEM should have one -file with a name like XXXCATD.DDF. This should be selected to open the -dataset. - -The elevation units of DEMs may be feet or meters. The GetType() method -on a band will attempt to return if the units are Feet ("ft") or Meters -("m"). - -NOTE: Implemented as :source_file:`frmts/sdts/sdtsdataset.cpp`. - -Driver capabilities -------------------- - -.. supports_georeferencing:: - -.. supports_virtualio:: diff --git a/doc/source/drivers/raster/sgi.rst b/doc/source/drivers/raster/sgi.rst deleted file mode 100644 index 530fda6b47fe..000000000000 --- a/doc/source/drivers/raster/sgi.rst +++ /dev/null @@ -1,37 +0,0 @@ -.. _raster.sgi: - -================================================================================ -SGI -- SGI Image Format -================================================================================ - -.. shortname:: SGI - -.. built_in_by_default:: - -The SGI driver currently supports the reading and writing of SGI Image -files. - -The driver currently supports 1, 2, 3, and 4 band images. The driver -currently supports "8 bit per channel value" images. The driver supports -both uncompressed and run-length encoded (RLE) images for reading, but -created files are always RLE compressed.. - -The GDAL SGI Driver was based on Paul Bourke's SGI image read code. - -See Also: - -- `Paul Bourke's SGI Image Read - Code `__ -- `SGI Image File Format - Document `__ - -NOTE: Implemented as :source_file:`frmts/sgi/sgidataset.cpp`. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_create:: - -.. supports_virtualio:: diff --git a/doc/source/drivers/raster/usgsdem.rst b/doc/source/drivers/raster/usgsdem.rst index cb3275e91703..a68abe01923c 100644 --- a/doc/source/drivers/raster/usgsdem.rst +++ b/doc/source/drivers/raster/usgsdem.rst @@ -33,127 +33,10 @@ VTP. Driver capabilities ------------------- -.. supports_createcopy:: - .. supports_georeferencing:: .. supports_virtualio:: -Creation Issues ---------------- - -GDAL supports export of geographic (and UTM) USGS DEM and CDED data -files, including the ability to generate CDED 2.0 50K products to -Canadian federal government specifications. - -Input data must already be sampled in a geographic or UTM coordinate -system. By default the entire area of the input file will be output, but -for CDED50K products the output file will be sampled at the production -specified resolution and on product tile boundaries. - -If the input file has appropriate coordinate system information set, -export to specific product formats can take input in different -coordinate systems (i.e. from Albers projection to NAD83 geographic for -CDED50K production). - -|about-creation-options| -The following creation options are supported: - -- .. co:: PRODUCT - :choices: DEFAULT, CDED50K - - When CDED50K is specified, the output - file will be forced to adhere to CDED 50K product specifications. The - output will always be 1201x1201 and generally a 15 minute by 15 - minute tile (though wider in longitude in far north areas). - -- .. co:: TOPLEFT - :choices: - - For CDED50K products, this is used to specify - the top left corner of the tile to be generated. It should be on a 15 - minute boundary and can be given in decimal degrees or degrees and - minutes (eg. TOPLEFT=117d15w,52d30n). - -- .. co:: RESAMPLE - :choices: Nearest, Bilinear, Cubic, CubicSpline - :default: Bilinear - - Set the resampling - kernel used for resampling the data to the target grid. Only has an - effect when particular products like CDED50K are being produced. - -- .. co:: DEMLevelCode - :choices: 1, 2, 3 - :default: 1 - - DEM Level (1, 2 or 3 if set). - -- .. co:: DataSpecVersion - :choices: - - Data and Specification version/revision - (eg. 1020) - -- .. co:: PRODUCER - :choices: - - Up to 60 characters to be put into the producer - field of the generated file. - -- .. co:: OriginCode - :choices: - - Up to 4 characters to be put into the origin - code field of the generated file (YT for Yukon). - -- .. co:: ProcessCode - :choices: - - One character to be put into the process code - field of the generated file (8=ANUDEM, 9=FME, A=TopoGrid). - -- .. co:: TEMPLATE - :choices: - - For any output file, a template file can be - specified. A number of fields (including the Data Producer) will be - copied from the template file if provided, and are otherwise left - blank. - -- .. co:: ZRESOLUTION - :default: 1.0 - - DEM's store elevation information as positive - integers, and these integers are scaled using the "z resolution." By - default, this resolution is written as 1.0. However, you may specify - a different resolution here, if you would like your integers to be - scaled into floating point numbers. - -- .. co:: NTS - :choices: - - NTS Mapsheet name, used to derive TOPLEFT. Only has an - effect when particular products like CDED50K are being produced. - -- .. co:: INTERNALNAME - :choices: - - Dataset name written into file header. Only - has an effect when particular products like CDED50K are being - produced. - -Example: The following would generate a single CDED50K tile, extracting -from the larger DEM coverage yk_3arcsec for a tile with the top left -corner -117w,60n. The file yk_template.dem is used to set some product -fields including the Producer of Data, Process Code and Origin Code -fields. - -:: - - gdal_translate -of USGSDEM -co PRODUCT=CDED50K -co TEMPLATE=yk_template.dem \ - -co TOPLEFT=-117w,60n yk_3arcsec 031a01_e.dem - -------------- NOTE: Implemented as :source_file:`frmts/usgsdem/usgsdemdataset.cpp`. diff --git a/doc/source/drivers/raster/webp.rst b/doc/source/drivers/raster/webp.rst index d93a9dac9a45..8a5f4fb6bb02 100644 --- a/doc/source/drivers/raster/webp.rst +++ b/doc/source/drivers/raster/webp.rst @@ -22,9 +22,6 @@ with big images (which are limited to 16383x16383 pixels). The WEBP driver supports 3 bands (RGB) images. It also supports 4 bands (RGBA) -The WEBP driver can be used as the internal format used by the -:ref:`raster.rasterlite` driver. - XMP metadata can be extracted from the file, and will be stored as XML raw content in the xml:XMP metadata domain. diff --git a/doc/source/drivers/raster/xpm.rst b/doc/source/drivers/raster/xpm.rst deleted file mode 100644 index d3722bb95ed2..000000000000 --- a/doc/source/drivers/raster/xpm.rst +++ /dev/null @@ -1,29 +0,0 @@ -.. _raster.xpm: - -================================================================================ -XPM -- X11 Pixmap -================================================================================ - -.. shortname:: XPM - -.. built_in_by_default:: - -GDAL includes support for reading and writing XPM (X11 Pixmap Format) -image files. These are colormapped one band images primarily used for -simple graphics purposes in X11 applications. It has been incorporated -in GDAL primarily to ease translation of GDAL images into a form usable -with the GTK toolkit. - -The XPM support does not support georeferencing (not available from XPM -files) nor does it support XPM files with more than one character per -pixel. New XPM files must be colormapped or greyscale, and colortables -will be reduced to about 70 colors automatically. - -NOTE: Implemented as :source_file:`frmts/xpm/xpmdataset.cpp`. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_virtualio:: diff --git a/doc/source/drivers/vector/index.rst b/doc/source/drivers/vector/index.rst index 411189072692..da2fda75878a 100644 --- a/doc/source/drivers/vector/index.rst +++ b/doc/source/drivers/vector/index.rst @@ -74,12 +74,10 @@ Vector drivers nas netcdf ngw - ntf oapif oci odbc ods - ogdi openfilegdb osm parquet @@ -91,14 +89,12 @@ Vector drivers plscenes pmtiles s57 - sdts selafin shapefile sosi sqlite svg sxf - tiger tiledb topojson vdv diff --git a/doc/source/drivers/vector/ntf.rst b/doc/source/drivers/vector/ntf.rst deleted file mode 100644 index 8c813fdb9bbe..000000000000 --- a/doc/source/drivers/vector/ntf.rst +++ /dev/null @@ -1,217 +0,0 @@ -.. _vector.ntf: - -UK .NTF -======= - -.. shortname:: UK .NTF - -.. built_in_by_default:: - -The National Transfer Format, mostly used by the UK Ordnance Survey, is -supported for read access. - -This driver treats a directory as a dataset and attempts to merge all -the .NTF files in the directory, producing a layer for each type of -feature (but generally not for each source file). Thus a directory -containing several Landline files will have three layers -(LANDLINE_POINT, LANDLINE_LINE and LANDLINE_NAME) regardless of the -number of landline files. - -NTF features are always returned with the British National Grid -coordinate system. This may be inappropriate for NTF files written by -organizations other than the UK Ordnance Survey. - -Driver capabilities -------------------- - -.. supports_georeferencing:: - -.. supports_virtualio:: - -See Also --------- - -- `General UK NTF - Information `__ - -Implementation Notes --------------------- - -Products (and Layers) Supported -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Landline (and Landline Plus): - LANDLINE_POINT - LANDLINE_LINE - LANDLINE_NAME - - Panorama Contours: - PANORAMA_POINT - PANORAMA_CONTOUR - - HEIGHT attribute holds elevation. - - Strategi: - STRATEGI_POINT - STRATEGI_LINE - STRATEGI_TEXT - STRATEGI_NODE - - Meridian: - MERIDIAN_POINT - MERIDIAN_LINE - MERIDIAN_TEXT - MERIDIAN_NODE - - Boundaryline: - BOUNDARYLINE_LINK - BOUNDARYLINE_POLY - BOUNDARYLINE_COLLECTIONS - - The _POLY layer has links to links allowing true polygons to - be formed (otherwise the _POLY's only have a seed point for geometry. - The collections are collections of polygons (also without geometry - as read). This is the only product from which polygons can be - constructed. - - BaseData.GB: - BASEDATA_POINT - BASEDATA_LINE - BASEDATA_TEXT - BASEDATA_NODE - - OSCAR Asset/Traffic: - OSCAR_POINT - OSCAR_LINE - OSCAR_NODE - - OSCAR Network: - OSCAR_NETWORK_POINT - OSCAR_NETWORK_LINE - OSCAR_NETWORK_NODE - - Address Point: - ADDRESS_POINT - - Code Point: - CODE_POINT - - Code Point Plus: - CODE_POINT_PLUS - -The dataset as a whole will also have a FEATURE_CLASSES layer containing -a pure table relating FEAT_CODE numbers with feature class names -(FC_NAME). This applies to all products in the dataset. A few layer -types (such as the Code Point, and Address Point products) don't include -feature classes. Some products use features classes that are not defined -in the file, and so they will not appear in the FEATURE_CLASSES layer. - -Product Schemas -~~~~~~~~~~~~~~~ - -The approach taken in this reader is to treat one file, or a directory -of files as a single dataset. All files in the dataset are scanned on -open. For each particular product (listed above) a set of layers are -created; however, these layers may be extracted from several files of -the same product. - -The layers are based on a low level feature type in the NTF file, but -will generally contain features of many different feature codes -(FEAT_CODE attribute). Different features within a given layer may have -a variety of attributes in the file; however, the schema is established -based on the union of all attributes possible within features of a -particular type (i.e. POINT) of that product family (i.e. OSCAR -Network). - -If an NTF product is read that doesn't match one of the known schema's -it will go through a different generic handler which has only layers of -type GENERIC_POINT and GENERIC_LINE. The features only have a FEAT_CODE -attribute. - -Details of what layers of what products have what attributes can be -found in the NTFFileReader::EstablishLayers() method at the end of -ntf_estlayers.cpp. This file also contains all the product specific -translation code. - -Special Attributes -~~~~~~~~~~~~~~~~~~ - -:: - - FEAT_CODE: General feature code integer, can be used to lookup a name in the - FEATURE_CLASSES layer/table. - - TEXT_ID/POINT_ID/LINE_ID/NAME_ID/COLL_ID/POLY_ID/GEOM_ID: - Unique identifier for a feature of the appropriate type. - - TILE_REF: All layers (except FEATURE_CLASSES) contain a TILE_REF attribute - which indicates which tile (file) the features came from. Generally - speaking the id numbers are only unique within the tile and so - the TILE_REF can be used restrict id links within features from - the same file. - - FONT/TEXT_HT/DIG_POSTN/ORIENT: - Detailed information on the font, text height, digitizing position, - and orientation of text or name objects. Review the OS product - manuals to understand the units, and meaning of these codes. - - GEOM_ID_OF_POINT: - For _NODE features this defines the POINT_ID of the point layer object - to which this node corresponds. Generally speaking the nodes don't - carry a geometry of their own. The node must be related to a point - to establish its position. - - GEOM_ID_OF_LINK: - A _list_ of _LINK or _LINE features to end/start at a node. Nodes, - and this field are generally only of value when establishing - connectivity of line features for network analysis. Note that this - should be related to the target features GEOM_ID, not its LINE_ID. - - On the BOUNDARYLINE_POLY layer this attribute contains the GEOM_IDs - of the lines which form the edge of the polygon. - - POLY_ID: - A list of POLY_ID's from the BOUNDARYLINE_POLY layer associated with - a given collection in the BOUNDARYLINE_COLLECTIONS layer. - -Generic Products -~~~~~~~~~~~~~~~~ - -In situations where a file is not identified as being part of an -existing known product it will be treated generically. In this case the -entire dataset is scanned to establish what features have what -attributes. Because of this, opening a generic dataset can be much -slower than opening a recognised dataset. Based on this scan a list of -generic features (layers) are defined from the following set: - -:: - - GENERIC_POINT - GENERIC_LINE - GENERIC_NAME - GENERIC_TEXT - GENERIC_POLY - GENERIC_NODE - GENERIC_COLLECTION - -Generic products are primarily handled by the ntf_generic.cpp module -whereas specific products are handled in ntf_estlayers.cpp. - -Because some data products (OSNI datasets) not from the Ordnance Survey -were found to have record groups in unusual orders compared to what the -UK Ordnance Survey does, it was found necessary to cache all the records -of level 3 and higher generic products, and construct record groups by -id reference from within this cache rather than depending on convenient -record orderings. This is accomplished by the NTFFileReader "indexing" -capability near the bottom of ntffilereader.cpp. Because of this in -memory indexing accessing generic datasets can be much more memory -intensive than accessing known data products, though it isn't necessary -for generic level 1 and 2 products. - -It is possible to force a known product to be treated as generic by -setting the FORCE_GENERIC option to "ON" using -OGRNTFDataSource::SetOptionsList() as is demonstrated in ntfdump.cpp. -This may also be accomplished from outside OGR applications by setting -the OGR_NTF_OPTIONS environment variable to "FORCE_GENERIC=ON". diff --git a/doc/source/drivers/vector/oci.rst b/doc/source/drivers/vector/oci.rst index 2c367b394faf..f88b50caeecf 100644 --- a/doc/source/drivers/vector/oci.rst +++ b/doc/source/drivers/vector/oci.rst @@ -331,17 +331,6 @@ created with the features from abc.shp and attributes from abc.dbf. % ogr2ogr -f OCI OCI:warmerda/password@gdal800.dreadfest.com abc.shp -This second example loads a political boundaries layer from VPF (via the -:ref:`OGDI driver `), and renames the layer from the cryptic -OGDI layer name to something more sensible. If an existing table of the -desired name exists it is overwritten. - -:: - - % ogr2ogr -f OCI OCI:warmerda/password \ - gltp:/vrf/usr4/mpp1/v0eur/vmaplv0/eurnasia \ - -lco OVERWRITE=yes -nln polbndl_bnd 'polbndl@bnd(*)_line' - This example shows using ogrinfo to evaluate an SQL query statement within Oracle. More sophisticated Oracle Spatial specific queries may also be used via the -sql commandline switch to ogrinfo. diff --git a/doc/source/drivers/vector/ogdi.rst b/doc/source/drivers/vector/ogdi.rst deleted file mode 100644 index 6d5119f81ec4..000000000000 --- a/doc/source/drivers/vector/ogdi.rst +++ /dev/null @@ -1,116 +0,0 @@ -.. _vector.ogdi: - -OGDI Vectors -============ - -.. shortname:: OGDI - -.. build_dependencies:: OGDI library - -OGDI vector support is optional in OGR, and is normally only configured -if OGDI is installed on the build system. If available OGDI vectors are -supported for read access for the following family types: - -- Point -- Line -- Area -- Text (Currently returned as points with the text in the "text" - attribute) - -OGDI can (among other formats) read VPF products, such as DCW and VMAP. - -If an OGDI gltp url is opened directly the OGDI 3.1 capabilities for the -driver/server are queried to get a list of layers. One OGR layer is -created for each OGDI family available for each layer in the datastore. -For drivers such as VRF this can result in a lot of layers. Each of the -layers has an OGR name based on the OGDI name plus an underscore and the -family name. For instance a layer might be called -**watrcrsl@hydro(*)_line** if coming out of the VRF driver. -(layer names can be simplified with :config:`OGR_OGDI_LAUNDER_LAYER_NAMES=YES`) - -Alternatively to accessing all the layers in a datastore, it is possible -to open a particular layer using a customized filename consisting of the -regular GLTP URL to which you append the layer name and family type -(separated by colons). This mechanism must be used to access layers of -pre OGDI 3.1 drivers as before OGDI 3.1 there was no regular way to -discover available layers in OGDI. - -:: - - gltp:[//]//:: - -Where is the OGDI Layer name, and is one of: -"line", "area", "point", or "text". - -OGDI coordinate system information is supported for most coordinate -systems. A warning will be produced when a layer is opened if the -coordinate system cannot be translated. - -There is no update or creation support in the OGDI driver. - -Driver capabilities -------------------- - -.. supports_georeferencing:: - -Error handling --------------- - -Starting with GDAL 2.2 and OGDI > 3.2.0beta2, if the OGDI_STOP_ON_ERROR -environment variable is set to NO, some errors can be gracefully -recovered by OGDI (in VPF driver). They will still be caught by GDAL and -emitted as regular GDAL errors. - -Note: be aware that this is a work in progress. Not all recoverable -errors can be recovered, and some errors might be recovered silently. - -Configuration options ---------------------- - -|about-config-options| -The following configuration options are available: - -- .. config:: OGR_OGDI_LAUNDER_LAYER_NAMES - :choices: YES, NO - :default: NO - - If ``YES``, simplify layer names. For example : *watrcrsl_hydro* instead - of 'watrcrsl@hydro(*)_line' - - -Examples --------- - -| Usage example 'ogrinfo': - -:: - - ogrinfo gltp:/vrf/usr4/mpp1/v0eur/vmaplv0/eurnasia 'watrcrsl@hydro(*)_line' - -In the dataset name 'gltp:/vrf/usr4/mpp1/v0eur/vmaplv0/eurnasia' the -gltp:/vrf part is not really in the filesystem, but has to be added. The -VPF data was at /usr4/mpp1/v0eur/. The 'eurnasia' directory should be at -the same level as the dht. and lat. files. The 'hydro' reference is a -subdirectory of 'eurnasia/' where watrcrsl.\* is found. - -| Usage examples VMAP0 to SHAPE conversion with 'ogr2ogr': - -:: - - ogr2ogr watrcrsl.shp gltp:/vrf/usr4/mpp1/v0eur/vmaplv0/eurnasia 'watrcrsl@hydro(*)_line' - ogr2ogr polbnda.shp gltp:/vrf/usr4/mpp1/v0eur/vmaplv0/eurnasia 'polbnda@bnd(*)_area' - -An OGR SQL query against a VMAP dataset. Again, note the careful quoting -of the layer name. - -:: - - ogrinfo -ro gltp:/vrf/usr4/mpp1/v0noa/vmaplv0/noamer \ - -sql 'select * from "polbndl@bnd(*)_line" where use=26' - -See Also --------- - -- `OGDI.SourceForge.Net `__ -- `VMap0 - Coverages `__ diff --git a/doc/source/drivers/vector/pg.rst b/doc/source/drivers/vector/pg.rst index 199031017b06..d8f45e2c798b 100644 --- a/doc/source/drivers/vector/pg.rst +++ b/doc/source/drivers/vector/pg.rst @@ -500,17 +500,6 @@ Examples ogr2ogr -f PostgreSQL PG:dbname=warmerda abc.shp -- This second example loads a political boundaries layer from VPF (via - the :ref:`OGDI driver `), and renames the layer from the - cryptic OGDI layer name to something more sensible. If an existing - table of the desired name exists it is overwritten. - - :: - - ogr2ogr -f PostgreSQL PG:dbname=warmerda \ - gltp:/vrf/usr4/mpp1/v0eur/vmaplv0/eurnasia \ - -lco OVERWRITE=yes -nln polbndl_bnd 'polbndl@bnd(*)_line' - - Export a single Postgres table to GeoPackage: :: diff --git a/doc/source/drivers/vector/sdts.rst b/doc/source/drivers/vector/sdts.rst deleted file mode 100644 index e963c9a13a85..000000000000 --- a/doc/source/drivers/vector/sdts.rst +++ /dev/null @@ -1,44 +0,0 @@ -.. _vector.sdts: - -SDTS -==== - -.. shortname:: SDTS - -.. built_in_by_default:: - -SDTS TVP (Topological Vector Profile) and Point Profile datasets are -supported for read access. Each primary attribute, node (point), line -and polygon module is treated as a distinct layer. - -To select an SDTS transfer, the name of the catalog file should be used. -For instance ``TR01CATD.DDF`` where the first four characters are all -that typically varies. - -SDTS coordinate system information is properly supported for most -coordinate systems defined in SDTS. - -There is no update or creation support in the SDTS driver. - -Note that in TVP datasets the polygon geometry is formed from the -geometry in the line modules. Primary attribute module attributes should -be properly attached to their related node, line or polygon features, -but can be accessed separately as their own layers. - -This driver has no support for raster (DEM) SDTS datasets. - -Driver capabilities -------------------- - -.. supports_georeferencing:: - -.. supports_virtualio:: - -See Also --------- - -- `SDTS Abstraction - Library `__: The base - library used to implement this driver. -- `http://mcmcweb.er.usgs.gov/sdts `__: - Main USGS SDTS web page. diff --git a/doc/source/drivers/vector/tiger.rst b/doc/source/drivers/vector/tiger.rst deleted file mode 100644 index f94136c5dbfb..000000000000 --- a/doc/source/drivers/vector/tiger.rst +++ /dev/null @@ -1,245 +0,0 @@ -.. _vector.tiger: - -U.S. Census TIGER/Line -====================== - -.. shortname:: TIGER - -.. built_in_by_default:: - -TIGER/Line file sets are support for read access. - -TIGER/Line files are a digital database of geographic features, such as -roads, railroads, rivers, lakes, political boundaries, census -statistical boundaries, etc. covering the entire United States. The data -base contains information about these features such as their location in -latitude and longitude, the name, the type of feature, address ranges -for most streets, the geographic relationship to other features, and -other related information. They are the public product created from the -Census Bureau's TIGER (Topologically Integrated Geographic Encoding and -Referencing) data base of geographic information. TIGER was developed at -the Census Bureau to support the mapping and related geographic -activities required by the decennial census and sample survey programs. - -Note that the TIGER/Line product does not include census demographic -statistics. Those are sold by the Census Bureau in a separate format -(not directly supported by FME), but those statistics do relate back to -census blocks in TIGER/Line files. - -To open a TIGER/Line dataset, select the directory containing one or -more sets of data files. The regions are counties, or county -equivalents. Each county consists of a series of files with a common -basename, and different extensions. For instance, county 1 in state 26 -(Michigan) consists of the following file set in Tiger98. - -:: - - TGR26001.RT1 - TGR26001.RT2 - TGR26001.RT3 - TGR26001.RT4 - TGR26001.RT5 - TGR26001.RT6 - TGR26001.RT7 - TGR26001.RT8 - TGR26001.RT9 - TGR26001.RTA - TGR26001.RTC - TGR26001.RTH - TGR26001.RTI - TGR26001.RTP - TGR26001.RTR - TGR26001.RTS - TGR26001.RTZ - -The TIGER/Line coordinate system is hardcoded to NAD83 lat/long degrees. -This should be appropriate for all recent years of TIGER/Line -production. - -There is no update or creation support in the TIGER/Line driver. - -The reader was implemented for TIGER/Line 1998 files, but some effort -has gone into ensuring compatibility with 1992, 1995, 1997, 1999, 2000, -2002, 2003 and 2004 TIGER/Line products as well. The 2005 products have -also been reported to work fine. It is believe that any TIGER/Line -product from the 1990's should work with the reader, with the possible -loss of some version specific information. - -Driver capabilities -------------------- - -.. supports_georeferencing:: - -.. supports_virtualio:: - -Feature Representation ----------------------- - -With a few exceptions, a feature is created for each record of a -TIGER/Line data file. Each file (i.e. .RT1, .RTA) is translated to an -appropriate OGR feature type, with attribute names matching those in the -TIGER/Line product manual. - -The TIGER/Line RT (record type), and VERSION attributes are generally -discarded, but the MODULE attribute is added to each feature. The MODULE -attribute contains the basename (eg. TGR26001) of the county module from -which the feature originated. For some keys (such as LAND, POLYID, and -CENID) this MODULE attribute is needed to make the key unique when the -dataset (directory) consists of more than one county of data. - -Following is a list of feature types, and their relationship to the -TIGER/Line product. - -CompleteChain -^^^^^^^^^^^^^ - -A CompleteChain is a polyline with an associated TLID (TIGER/Line ID). -The CompleteChain features are established from a type 1 record -(Complete Chain Basic Data Record), and if available it is associated -type 3 record (Complete Chain Geographic Entity Codes). As well, any -type 2 records (Complete Chain Shape Coordinates) available are used to -fill in intermediate shape points on the arc. The TLID is the primary -key, and is unique within the entire national TIGER/Line coverage. - -These features always have a line geometry. - -AltName -^^^^^^^ - -These features are derived from the type 4 record (Index to Alternate -Feature Identifiers), and relate a TLID to 1 to 4 alternate feature name -numbers (the FEAT attribute) which are kept separately as FeatureIds -features. The standard reader pipeline attaches the names from the -FeatureIds features as array attributes ALT_FEDIRS{}, ALT_FEDIRP{}, -ALT_FENAME{} and ALT_FETYPE{}. The ALT_FENAME{} is a list of feature -names associated with the TLID on the AltName feature. - -Note that zero, one or more AltName records may exist for a given TLID, -and each AltName record can contain between one and four alternate -names. Because it is still very difficult to utilize AltName features to -relate altername names to CompleteChains, it is anticipated that the -standard reader pipeline for TIGER/Line files will be upgraded in the -future, resulting in a simplification of alternate names. - -These features have no associated geometry. - -FeatureIds -^^^^^^^^^^ - -These features are derived from type 5 (Complete Chain Feature -Identifiers) records. Each feature contains a feature name (FENAME), and -it is associated feature id code (FEAT). The FEAT attribute is the -primary key, and is unique within the county module. FeatureIds have a -one to many relationship with AltName features, and KeyFeatures -features. - -These features have no associated geometry. - -ZipCodes -^^^^^^^^ - -These features are derived from type 6 (Additional Address Range and ZIP -Code Data) records. These features are intended to augment the ZIP Code -information kept directly on CompleteChain features, and there is a many -to one relationship between ZipCodes features and CompleteChain -features. - -These features have no associated geometry. - -Landmarks -^^^^^^^^^ - -These features are derived from type 7 (Landmark Features) records. They -relate to point, or area landmarks. For area landmarks there is a one to -one relationship with an AreaLandmark record. The LAND attribute is the -primary key, and is unique within the county module. - -These features may have an associated point geometry. Landmarks -associated with polygons will not have the polygon geometry attached. It -would need to be collected (via the AreaLandmark feature) from a Polygon -feature. - -AreaLandmarks -^^^^^^^^^^^^^ - -These features are derived from type 8 (Polygons Linked to Area -Landmarks) records. Each associates a Landmark feature (attribute LAND) -with a Polygon feature (attribute POLYID). This feature has a many to -many relationship with Polygon features. - -These features have no associated geometry. - -KeyFeatures -^^^^^^^^^^^ - -These features are derived from type 9 (Polygon Geographic Entity Codes) -records. They may be associated with a FeatureIds feature (via the FEAT -attribute), and a Polygon feature (via the POLYID attribute). - -These features have no associated geometry. - -Polygon -^^^^^^^ - -These features are derived from type A (Polygon Geographic Entity Codes) -records and if available the related type S (Polygon Additional -Geographic Entity Codes) records. The POLYID attribute is the primary -key, uniquely identifying a polygon within a county module. - -These features do not have any geometry associated with them as read by -the OGR TIGER driver. It needs to be externally related using the -PolyChainLink. The gdal/pymod/samples/tigerpoly.py script may be used to -read a TIGER dataset and extract the polygon layer **with geometry** as -a shapefile. - -EntityNames -^^^^^^^^^^^ - -These features are derived from type C (Geographic Entity Names) -records. - -These features have no associated geometry. - -IDHistory -^^^^^^^^^ - -These features are derived from type H (TIGER/Line ID History) records. -They can be used to trace the splitting, merging, creation and deletion -of CompleteChain features. - -These features have no associated geometry. - -PolyChainLink -^^^^^^^^^^^^^ - -These features are derived from type I (Link Between Complete Chains and -Polygons) records. They are normally all consumed by the standard reader -pipeline while attaching CompleteChain geometries to Polygon features to -establish their polygon geometries. PolyChainLink features have a many -to one relationship with Polygon features, and a one to one relationship -with CompleteChain features. - -These features have no associated geometry. - -PIP -^^^ - -These features are derived from type P (Polygon Internal Point) records. -They relate to a Polygon feature via the POLYID attribute, and can be -used to establish an internal point for Polygon features. - -These features have a point geometry. - -ZipPlus4 -^^^^^^^^ - -These features are derived from type Z (ZIP+4 Codes) records. ZipPlus4 -features have a many to one relationship with CompleteChain features. - -These features have no associated geometry. - -See Also --------- - -http://www.census.gov/geo/www/tiger/: More information on the TIGER/Line -file format, and data product can be found on this U.S. Census web page. diff --git a/docker/alpine-normal/Dockerfile b/docker/alpine-normal/Dockerfile index c8679a3c7fee..8e0111d88dab 100644 --- a/docker/alpine-normal/Dockerfile +++ b/docker/alpine-normal/Dockerfile @@ -69,7 +69,6 @@ RUN apk add --no-cache \ netcdf-dev \ ninja-build \ odbc-cpp-wrapper-dev \ - ogdi-dev \ openexr-dev \ openjpeg-dev \ openssl-dev \ @@ -375,7 +374,6 @@ RUN apk add --no-cache \ minizip \ musl \ odbc-cpp-wrapper \ - ogdi \ openexr-libopenexr \ openjpeg \ pcre2 \ diff --git a/docker/ubuntu-full/Dockerfile b/docker/ubuntu-full/Dockerfile index ccb808d1bcdd..062f5a731293 100644 --- a/docker/ubuntu-full/Dockerfile +++ b/docker/ubuntu-full/Dockerfile @@ -72,7 +72,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ libspatialite-dev${APT_ARCH_SUFFIX} librasterlite2-dev${APT_ARCH_SUFFIX} swig ant libhdf4-alt-dev${APT_ARCH_SUFFIX} libhdf5-serial-dev${APT_ARCH_SUFFIX} \ libfreexl-dev${APT_ARCH_SUFFIX} unixodbc-dev${APT_ARCH_SUFFIX} mdbtools-dev${APT_ARCH_SUFFIX} libwebp-dev${APT_ARCH_SUFFIX} \ liblcms2-2 libpcre3-dev${APT_ARCH_SUFFIX} libcrypto++-dev${APT_ARCH_SUFFIX} libfyba-dev${APT_ARCH_SUFFIX} \ - libkml-dev${APT_ARCH_SUFFIX} libmysqlclient-dev${APT_ARCH_SUFFIX} libogdi-dev${APT_ARCH_SUFFIX} \ + libkml-dev${APT_ARCH_SUFFIX} libmysqlclient-dev${APT_ARCH_SUFFIX} \ libcfitsio-dev${APT_ARCH_SUFFIX} openjdk-"$JAVA_VERSION"-jdk${APT_ARCH_SUFFIX} libzstd-dev${APT_ARCH_SUFFIX} \ libpq-dev${APT_ARCH_SUFFIX} libssl-dev${APT_ARCH_SUFFIX} libboost-dev${APT_ARCH_SUFFIX} \ autoconf automake bash-completion libarmadillo-dev${APT_ARCH_SUFFIX} \ @@ -539,7 +539,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ libhdf4-0-alt libhdf5-103-1 libhdf5-cpp-103-1 poppler-utils libfreexl1 unixodbc mdbtools libwebp7 \ liblcms2-2 libpcre3 libcrypto++8 libfyba0 \ libkmlbase1 libkmlconvenience1 libkmldom1 libkmlengine1 libkmlregionator1 libkmlxsd1 \ - libmysqlclient21 libogdi4.1 libcfitsio10 \ + libmysqlclient21 libcfitsio10 \ libzstd1 bash bash-completion libpq5 \ libarmadillo12 libpython3.12 libopenexr-3-1-30 libheif1 \ libdeflate0 libblosc1 liblz4-1 \ @@ -554,8 +554,6 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ python3-pil \ # Install JRE with --no-install-recommends, otherwise it draws default-jre, which draws systemd, which fails to install when running the arm64v8/ubuntu:24.04 image on a 64bit host && apt-get install -y --no-install-recommends openjdk-"$JAVA_VERSION"-jre \ - # Worksround OGDI packaging bug for Ubuntu 24.04 - && ln -s /usr/lib/$(uname -p)-linux-gnu/ogdi/4.1/libvrf.so /usr/lib/$(uname -p)-linux-gnu \ # Install Arrow C++ && apt-get install -y -V ca-certificates lsb-release wget \ && curl -LO -fsS https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb \ diff --git a/frmts/CMakeLists.txt b/frmts/CMakeLists.txt index 950eba3d1f14..8c84e7557635 100644 --- a/frmts/CMakeLists.txt +++ b/frmts/CMakeLists.txt @@ -81,24 +81,19 @@ endif () gdal_optional_format(libertiff "GeoTIFF support through libertiff library") gdal_optional_format(hfa "Erdas Imagine .img") -gdal_optional_format(sdts "SDTS translator") gdal_optional_format(nitf "National Imagery Transmission Format") gdal_optional_format(gxf "GXF") gdal_optional_format(aaigrid "Arc/Info ASCII Grid Format.") gdal_optional_format(ceos "CEOS translator") gdal_optional_format(ceos2 "ASI CEOS translator" DRIVER_NAME_OPTION "SAR_CEOS") -gdal_optional_format(xpm "XPM image format") gdal_optional_format(dted "Military Elevation Data") gdal_optional_format(jdem "JDEM driver") gdal_optional_format(envisat "Envisat") -gdal_optional_format(elas "Earth Resources Laboratory Applications Software") -gdal_optional_format(fit "FIT driver") gdal_optional_format(l1b "NOAA Polar Orbiter Level 1b Data Set (AVHRR)") gdal_optional_format(rs2 "RS2 -- RadarSat 2 XML Product") gdal_optional_format(ilwis "Raster Map") gdal_optional_format(rmf "RMF --- Raster Matrix Format") gdal_optional_format(leveller "Daylon Leveller heightfield") -gdal_optional_format(sgi "SGI Image driver") gdal_optional_format(srtmhgt "SRTM HGT File Read Support") gdal_optional_format(idrisi "Idrisi Raster Format") gdal_optional_format(gsg "Implements the Golden Software Surfer 7 Binary Grid Format.") @@ -112,10 +107,8 @@ gdal_optional_format(adrg "ADRG reader and ASRP/USRP Reader") gdal_optional_format(coasp "DRDC Configurable Airborne SAR Processor (COASP) data reader") gdal_optional_format(tsx "TerraSAR-X XML Product Support") gdal_optional_format(terragen "Terragen™ Terrain File") -gdal_optional_format(blx "Magellan BLX Topo File Format") gdal_optional_format(msgn "Meteosat Second Generation (MSG) Native Archive Format (.nat)") gdal_optional_format(til "EarthWatch .TIL Driver") -gdal_optional_format(r "R Object Data Store") gdal_optional_format(northwood "NWT_GRD/NWT_GRC -- Northwood/Vertical Mapper File Format") gdal_optional_format(saga "SAGA GIS Binary Driver") gdal_optional_format(xyz "ASCII Gridded XYZ") @@ -175,7 +168,6 @@ gdal_dependent_format(ogcapi "OGCAPI" "GDAL_USE_CURL") gdal_dependent_format(gta "Generic Tagged Arrays" "GDAL_USE_GTA") gdal_dependent_format(webp "WebP" "GDAL_USE_WEBP") gdal_dependent_format(hdf4 "Hierarchical Data Format Release 4 (HDF4)" "GDAL_USE_HDF4") -gdal_dependent_format(rasterlite "Rasterlite - Rasters in SQLite DB" "GDAL_USE_SQLITE3;OGR_ENABLE_DRIVER_SQLITE") gdal_dependent_format(mbtiles "MBTile" "GDAL_USE_SQLITE3;OGR_ENABLE_DRIVER_GPKG;OGR_ENABLE_DRIVER_MVT") gdal_dependent_format(postgisraster "PostGIS Raster driver" "GDAL_USE_POSTGRESQL") gdal_dependent_format(dds "DirectDraw Surface" "GDAL_USE_CRNLIB") @@ -184,7 +176,6 @@ include(openjpeg/driver_declaration.cmake) include(tiledb/driver_declaration.cmake) gdal_dependent_format(exr "EXR support via OpenEXR library" "GDAL_USE_OPENEXR") gdal_dependent_format(pcraster "PCRaster CSF 2.0 raster file driver" "GDAL_USE_LIBCSF OR GDAL_USE_LIBCSF_INTERNAL") -gdal_dependent_format(rdb "RIEGL RDB Map Pixel (.mpx) driver" "rdb_FOUND") gdal_dependent_format(jpegxl "JPEG-XL" "GDAL_USE_JXL") gdal_dependent_format(basisu_ktx2 "Basis Universal and KTX2 texture formats" "GDAL_USE_BASISU") diff --git a/frmts/adrg/adrgdataset.cpp b/frmts/adrg/adrgdataset.cpp index dde59c560a9d..b46d7a86bbf2 100644 --- a/frmts/adrg/adrgdataset.cpp +++ b/frmts/adrg/adrgdataset.cpp @@ -42,16 +42,7 @@ class ADRGDataset final : public GDALPamDataset char **papszSubDatasets; - ADRGDataset *poOverviewDS; - - /* For creation */ - int bCreation; - VSILFILE *fdGEN; - VSILFILE *fdTHF; - int bGeoTransformValid; double adfGeoTransform[6]; - int nNextAvailableBlock; - CPLString osBaseFileName; static char **GetGENListFromTHF(const char *pszFileName); static char **GetIMGListFromGEN(const char *pszFileName, @@ -69,7 +60,6 @@ class ADRGDataset final : public GDALPamDataset const OGRSpatialReference *GetSpatialRef() const override; CPLErr GetGeoTransform(double *padfGeoTransform) override; - CPLErr SetGeoTransform(double *padfGeoTransform) override; char **GetMetadataDomainList() override; char **GetMetadata(const char *pszDomain = "") override; @@ -79,15 +69,9 @@ class ADRGDataset final : public GDALPamDataset void AddSubDataset(const char *pszGENFileName, const char *pszIMGFileName); static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszOptions); static double GetLongitudeFromString(const char *str); static double GetLatitudeFromString(const char *str); - - void WriteGENFile(); - void WriteTHFFile(); }; /************************************************************************/ @@ -105,7 +89,6 @@ class ADRGRasterBand final : public GDALPamRasterBand GDALColorInterp GetColorInterpretation() override; CPLErr IReadBlock(int, int, void *) override; - CPLErr IWriteBlock(int, int, void *) override; double GetNoDataValue(int *pbSuccess = nullptr) override; @@ -129,46 +112,6 @@ ADRGRasterBand::ADRGRasterBand(ADRGDataset *poDSIn, int nBandIn) nBlockYSize = 128; } -#if 0 - -/* We have a problem with the overview. Its geo bounding box doesn't match */ -/* exactly the one of the main image. We should handle the shift between */ -/* the two top level corners... */ - -/************************************************************************/ -/* GetOverviewCount() */ -/************************************************************************/ - -int ADRGRasterBand::GetOverviewCount() - -{ - ADRGDataset* poDS = (ADRGDataset*)this->poDS; - if( poDS->poOverviewDS ) - return 1; - - return GDALRasterBand::GetOverviewCount(); -} - -/************************************************************************/ -/* GetOverview() */ -/************************************************************************/ - -GDALRasterBand *ADRGRasterBand::GetOverview( int i ) - -{ - ADRGDataset* poDS = (ADRGDataset*)this->poDS; - if( poDS->poOverviewDS ) - { - if( i < 0 || i >= 1 ) - return NULL; - - return poDS->poOverviewDS->GetRasterBand(nBand); - } - - return GDALRasterBand::GetOverview( i ); -} -#endif - /************************************************************************/ /* GetNoDataValue() */ /************************************************************************/ @@ -249,299 +192,13 @@ CPLErr ADRGRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) return CE_None; } -/************************************************************************/ -/* IWriteBlock() */ -/************************************************************************/ - -CPLErr ADRGRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void *pImage) - -{ - ADRGDataset *l_poDS = (ADRGDataset *)this->poDS; - int nBlock = nBlockYOff * l_poDS->NFC + nBlockXOff; - if (l_poDS->eAccess != GA_Update) - { - return CE_Failure; - } - if (nBlockXOff >= l_poDS->NFC || nBlockYOff >= l_poDS->NFL) - { - CPLError(CE_Failure, CPLE_AppDefined, - "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d", nBlockXOff, - l_poDS->NFC, nBlockYOff, l_poDS->NFL); - return CE_Failure; - } - CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock); - - if (l_poDS->TILEINDEX[nBlock] == 0) - { - unsigned int i; - int *pi = (int *)pImage; - for (i = 0; i < 128 * 128 / sizeof(int); i++) - { - if (pi[i]) - break; - } - if (i == 128 * 128 / sizeof(int)) - { - return CE_None; - } - - l_poDS->TILEINDEX[nBlock] = l_poDS->nNextAvailableBlock++; - } - - const int offset = l_poDS->offsetInIMG + - (l_poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + - (nBand - 1) * 128 * 128; - - if (VSIFSeekL(l_poDS->fdIMG, offset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset); - return CE_Failure; - } - if (VSIFWriteL(pImage, 1, 128 * 128, l_poDS->fdIMG) != 128 * 128) - { - CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", - offset); - return CE_Failure; - } - - return CE_None; -} - -static unsigned int WriteSubFieldStr(VSILFILE *fd, const char *pszStr, - unsigned int size) -{ - char *str = (char *)CPLMalloc(size + 1); - memset(str, ' ', size); - str[size] = 0; - const size_t nStrLen = strlen(pszStr); - if (nStrLen > size) - { - CPLError(CE_Failure, CPLE_AppDefined, "strlen(pszStr) > size"); - CPLFree(str); - return size; - } - memcpy(str, pszStr, nStrLen); - VSIFWriteL(str, 1, size, fd); - CPLFree(str); - return size; -} - -static unsigned int WriteSubFieldInt(VSILFILE *fd, int val, unsigned int size) -{ - char *str = (char *)CPLMalloc(size + 1); - char formatStr[32]; - snprintf(formatStr, sizeof(formatStr), "%%0%ud", size); - snprintf(str, size + 1, formatStr, val); - VSIFWriteL(str, 1, size, fd); - CPLFree(str); - return size; -} - -static unsigned int WriteFieldTerminator(VSILFILE *fd) -{ - char fieldTerminator = 30; - VSIFWriteL(&fieldTerminator, 1, 1, fd); - return 1; -} - -static unsigned int WriteUnitTerminator(VSILFILE *fd) -{ - char fieldTerminator = 31; - VSIFWriteL(&fieldTerminator, 1, 1, fd); - return 1; -} - -static unsigned int WriteLongitude(VSILFILE *fd, double val) -{ - char str[11 + 1]; - const char sign = (val >= 0) ? '+' : '-'; - if (val < 0) - val = -val; - const int ddd = (int)val; - const int mm = (int)((val - ddd) * 60); - const double ssdotss = ((val - ddd) * 60 - mm) * 60; - snprintf(str, sizeof(str), "%c%03d%02d%05.2f", sign, ddd, mm, ssdotss); - CPLAssert((int)strlen(str) == 11); - VSIFWriteL(str, 1, 11, fd); - return 11; -} - -static unsigned int WriteLatitude(VSILFILE *fd, double val) -{ - char str[10 + 1]; - const char sign = (val >= 0) ? '+' : '-'; - if (val < 0) - val = -val; - const int dd = (int)val; - const int mm = (int)((val - dd) * 60); - const double ssdotss = ((val - dd) * 60 - mm) * 60; - snprintf(str, sizeof(str), "%c%02d%02d%05.2f", sign, dd, mm, ssdotss); - CPLAssert((int)strlen(str) == 10); - VSIFWriteL(str, 1, 10, fd); - return 10; -} - -static int BeginLeader(VSILFILE *fd, int sizeFieldLength, int sizeFieldPos, - int sizeFieldTag, int nFields) -{ - int pos = (int)VSIFTellL(fd); - VSIFSeekL(fd, - 24 + - (sizeFieldLength + sizeFieldPos + sizeFieldTag) * - (vsi_l_offset)nFields + - 1, - SEEK_CUR); - return pos; -} - -static void FinishWriteLeader(VSILFILE *fd, int beginPos, int sizeFieldLength, - int sizeFieldPos, int sizeFieldTag, int nFields, - int *sizeOfFields, const char **nameOfFields) -{ - const int endPos = (int)VSIFTellL(fd); - VSIFSeekL(fd, beginPos, SEEK_SET); - - int nLeaderSize = 24; - char szLeader[24 + 1]; - memset(szLeader, ' ', nLeaderSize); - - int nDataSize = 0; - int nFieldOffset = 0; - for (int i = 0; i < nFields; i++) - nDataSize += sizeOfFields[i]; - nFieldOffset = - (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1; - nDataSize += nFieldOffset; - - snprintf(szLeader + 0, sizeof(szLeader) - 0, "%05d", - (int)(nDataSize + nLeaderSize)); - szLeader[5] = ' '; - szLeader[6] = 'D'; - - snprintf(szLeader + 12, sizeof(szLeader) - 12, "%05d", - (int)(nFieldOffset + nLeaderSize)); - szLeader[17] = ' '; - - szLeader[20] = (char)('0' + sizeFieldLength); - szLeader[21] = (char)('0' + sizeFieldPos); - szLeader[22] = '0'; - szLeader[23] = (char)('0' + sizeFieldTag); - - VSIFWriteL(szLeader, 1, nLeaderSize, fd); - - int acc = 0; - for (int i = 0; i < nFields; i++) - { - VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd); - WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength); - WriteSubFieldInt(fd, acc, sizeFieldPos); - acc += sizeOfFields[i]; - } - WriteFieldTerminator(fd); - - VSIFSeekL(fd, endPos, SEEK_SET); -} - -static int BeginHeader(VSILFILE *fd, int sizeFieldLength, int sizeFieldPos, - int sizeFieldTag, int nFields) -{ - int pos = (int)VSIFTellL(fd); - VSIFSeekL( - fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1, - SEEK_CUR); - return pos; -} - -static void FinishWriteHeader(VSILFILE *fd, int beginPos, int sizeFieldLength, - int sizeFieldPos, int sizeFieldTag, int nFields, - int *sizeOfFields, const char **nameOfFields) -{ - int endPos = (int)VSIFTellL(fd); - VSIFSeekL(fd, beginPos, SEEK_SET); - - int nLeaderSize = 24; - char szLeader[24 + 1]; - memset(szLeader, ' ', nLeaderSize); - - int nDataSize = 0; - int nFieldOffset = 0; - for (int i = 0; i < nFields; i++) - nDataSize += sizeOfFields[i]; - nFieldOffset = - (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1; - nDataSize += nFieldOffset; - - snprintf(szLeader + 0, sizeof(szLeader) - 0, "%05d", - (int)(nDataSize + nLeaderSize)); - szLeader[5] = '2'; - szLeader[6] = 'L'; - - szLeader[10] = '0'; - szLeader[11] = '6'; - snprintf(szLeader + 12, sizeof(szLeader) - 12, "%05d", - (int)(nFieldOffset + nLeaderSize)); - szLeader[17] = ' '; - - szLeader[20] = (char)('0' + sizeFieldLength); - szLeader[21] = (char)('0' + sizeFieldPos); - szLeader[22] = '0'; - szLeader[23] = (char)('0' + sizeFieldTag); - - VSIFWriteL(szLeader, 1, nLeaderSize, fd); - - int acc = 0; - for (int i = 0; i < nFields; i++) - { - VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd); - WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength); - WriteSubFieldInt(fd, acc, sizeFieldPos); - acc += sizeOfFields[i]; - } - WriteFieldTerminator(fd); - - VSIFSeekL(fd, endPos, SEEK_SET); -} - -static int WriteFieldDecl(VSILFILE *fd, char _data_struct_code, - char _data_type_code, const char *_fieldName, - const char *_arrayDescr, const char *_formatControls) -{ - VSIFWriteL(&_data_struct_code, 1, 1, fd); - VSIFWriteL(&_data_type_code, 1, 1, fd); - if (_data_struct_code == ' ') - { - VSIFWriteL(" ", 1, 4, fd); - } - else - { - VSIFWriteL("00;&", 1, 4, fd); - } - int len = 6; - VSIFWriteL(_fieldName, 1, strlen(_fieldName), fd); - len += static_cast(strlen(_fieldName)); - if (_arrayDescr[0]) - { - len += WriteUnitTerminator(fd); - VSIFWriteL(_arrayDescr, 1, strlen(_arrayDescr), fd); - len += static_cast(strlen(_arrayDescr)); - - len += WriteUnitTerminator(fd); - VSIFWriteL(_formatControls, 1, strlen(_formatControls), fd); - len += static_cast(strlen(_formatControls)); - } - len += WriteFieldTerminator(fd); - return len; -} - /************************************************************************/ /* ADRGDataset() */ /************************************************************************/ ADRGDataset::ADRGDataset() : fdIMG(nullptr), TILEINDEX(nullptr), offsetInIMG(0), NFC(0), NFL(0), - LSO(0.0), PSO(0.0), ARV(0), BRV(0), papszSubDatasets(nullptr), - poOverviewDS(nullptr), bCreation(FALSE), fdGEN(nullptr), fdTHF(nullptr), - bGeoTransformValid(0), nNextAvailableBlock(0) + LSO(0.0), PSO(0.0), ARV(0), BRV(0), papszSubDatasets(nullptr) { m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); memset(adfGeoTransform, 0, sizeof(adfGeoTransform)); @@ -553,101 +210,13 @@ ADRGDataset::ADRGDataset() ADRGDataset::~ADRGDataset() { - if (poOverviewDS) - { - delete poOverviewDS; - } - CSLDestroy(papszSubDatasets); - if (bCreation) - { - GDALPamDataset::FlushCache(true); - - /* Write header and padding of image */ - VSIFSeekL(fdIMG, 0, SEEK_SET); - { - VSILFILE *fd = fdIMG; - { - int nFields = 0; - int sizeOfFields[] = {0, 0, 0, 0}; - const char *nameOfFields[] = {"000", "001", "PAD", "SCN"}; - int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields)); - - sizeOfFields[nFields++] += WriteFieldDecl( - fd, ' ', ' ', "GEO_DATA_FILE", "", ""); /* 000 */ - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */ - "RTY!RID", "(A(3),A(2))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '0', "PADDING_FIELD", /* PAD */ - "PAD", "(A)"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '2', '0', "PIXEL_FIELD", /* SCN */ - "*PIX", "(A(1))"); - - FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), - sizeOfFields, nameOfFields); - } - - /* Write IMAGE_RECORD */ - { - int nFields = 0; - int sizeOfFields[] = {0, 0, 0}; - const char *nameOfFields[] = {"001", "PAD", "SCN"}; - int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields)); - - /* Field 001 */ - sizeOfFields[nFields] += - WriteSubFieldStr(fd, "IMG", 3); /* RTY */ - sizeOfFields[nFields] += - WriteSubFieldStr(fd, "01", 2); /* RID */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field PAD */ - int endPos = (int)VSIFTellL(fd); - char *pad = (char *)CPLMalloc(2047 - endPos); - memset(pad, ' ', 2047 - endPos); - VSIFWriteL(pad, 1, 2047 - endPos, fd); - CPLFree(pad); - WriteFieldTerminator(fd); - sizeOfFields[nFields] += 2047 - endPos + 1; - nFields++; - - /* Field SCN */ - sizeOfFields[nFields] = - (nNextAvailableBlock - 1) * 128 * 128 * 3; - // nFields++; - - FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), - sizeOfFields, nameOfFields); - } - } - - /* Write terminal field terminator */ - int offset = offsetInIMG + (nNextAvailableBlock - 1) * 128 * 128 * 3; - VSIFSeekL(fdIMG, offset, SEEK_SET); - WriteFieldTerminator(fdIMG); - - WriteGENFile(); - WriteTHFFile(); - } - if (fdIMG) { VSIFCloseL(fdIMG); } - if (fdGEN) - { - VSIFCloseL(fdGEN); - } - if (fdTHF) - { - VSIFCloseL(fdTHF); - } - if (TILEINDEX) { delete[] TILEINDEX; @@ -756,18 +325,6 @@ CPLErr ADRGDataset::GetGeoTransform(double *padfGeoTransform) return CE_None; } -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr ADRGDataset::SetGeoTransform(double *padfGeoTransform) - -{ - memcpy(adfGeoTransform, padfGeoTransform, sizeof(double) * 6); - bGeoTransformValid = TRUE; - return CE_None; -} - /************************************************************************/ /* GetLongitudeFromString() */ /************************************************************************/ @@ -1198,7 +755,6 @@ ADRGDataset *ADRGDataset::OpenDataset(const char *pszGENFileName, poDS->TILEINDEX = TILEINDEX; poDS->fdIMG = fdIMG; poDS->offsetInIMG = offsetInIMG; - poDS->poOverviewDS = nullptr; if (ZNA == 9) { @@ -1663,730 +1219,6 @@ GDALDataset *ADRGDataset::Open(GDALOpenInfo *poOpenInfo) return nullptr; } -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *ADRGDataset::Create(const char *pszFilename, int nXSize, - int nYSize, int nBandsIn, GDALDataType eType, - CPL_UNUSED char **papszOptions) -{ - if (eType != GDT_Byte) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create ADRG dataset with an illegal " - "data type (%s), only Byte supported by the format.", - GDALGetDataTypeName(eType)); - - return nullptr; - } - - if (nBandsIn != 3) - { - CPLError(CE_Failure, CPLE_NotSupported, - "ADRG driver doesn't support %d bands. " - "Must be 3 (rgb) bands.", - nBandsIn); - return nullptr; - } - - if (nXSize < 1 || nYSize < 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Specified pixel dimensions (% d x %d) are bad.", nXSize, - nYSize); - } - - if (!EQUAL(CPLGetExtensionSafe(pszFilename).c_str(), "gen")) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Invalid filename. Must be ABCDEF01.GEN"); - return nullptr; - } - - CPLString osBaseFileName(CPLGetBasenameSafe(pszFilename)); - if (osBaseFileName.size() != 8 || osBaseFileName[6] != DIGIT_ZERO || - osBaseFileName[7] != '1') - { - CPLError(CE_Failure, CPLE_NotSupported, - "Invalid filename. " - "Must be xxxxxx01.GEN where x is between A and Z"); - return nullptr; - } - - for (int i = 0; i < 6; i++) - { - if (!(osBaseFileName[i] >= 'A' && osBaseFileName[i] <= 'Z')) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Invalid filename. " - "Must be xxxxxx01.GEN where x is between A and Z"); - return nullptr; - } - } - - VSILFILE *fdGEN = VSIFOpenL(pszFilename, "wb"); - if (fdGEN == nullptr) - { - CPLError(CE_Failure, CPLE_FileIO, "Cannot create GEN file : %s.\n", - pszFilename); - return nullptr; - } - - CPLString osDirname(CPLGetDirnameSafe(pszFilename)); - CPLString osTransh01THF( - CPLFormFilenameSafe(osDirname.c_str(), "TRANSH01.THF", nullptr)); - VSILFILE *fdTHF = VSIFOpenL(osTransh01THF.c_str(), "wb"); - if (fdTHF == nullptr) - { - VSIFCloseL(fdGEN); - CPLError(CE_Failure, CPLE_FileIO, "Cannot create THF file : %s.\n", - osTransh01THF.c_str()); - return nullptr; - } - - CPLString osImgFilename = CPLResetExtensionSafe(pszFilename, "IMG"); - VSILFILE *fdIMG = VSIFOpenL(osImgFilename.c_str(), "w+b"); - if (fdIMG == nullptr) - { - VSIFCloseL(fdGEN); - VSIFCloseL(fdTHF); - CPLError(CE_Failure, CPLE_FileIO, "Cannot create image file : %s.\n", - osImgFilename.c_str()); - return nullptr; - } - - ADRGDataset *poDS = new ADRGDataset(); - - poDS->eAccess = GA_Update; - - poDS->fdGEN = fdGEN; - poDS->fdIMG = fdIMG; - poDS->fdTHF = fdTHF; - - poDS->osBaseFileName = std::move(osBaseFileName); - poDS->bCreation = TRUE; - poDS->nNextAvailableBlock = 1; - poDS->NFC = (nXSize + 127) / 128; - poDS->NFL = (nYSize + 127) / 128; - poDS->nRasterXSize = nXSize; - poDS->nRasterYSize = nYSize; - poDS->bGeoTransformValid = FALSE; - poDS->TILEINDEX = new int[poDS->NFC * poDS->NFL]; - memset(poDS->TILEINDEX, 0, sizeof(int) * poDS->NFC * poDS->NFL); - poDS->offsetInIMG = 2048; - poDS->poOverviewDS = nullptr; - - poDS->nBands = 3; - for (int i = 0; i < poDS->nBands; i++) - poDS->SetBand(i + 1, new ADRGRasterBand(poDS, i + 1)); - - return poDS; -} - -/************************************************************************/ -/* WriteGENFile_Header() */ -/************************************************************************/ - -static void WriteGENFile_Header(VSILFILE *fd) -{ - int nFields = 0; - int sizeOfFields[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; - const char *nameOfFields[] = {"000", "001", "DRF", "DSI", "OVI", - "GEN", "SPR", "BDF", "TIM"}; - const int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields)); - - sizeOfFields[nFields++] += WriteFieldDecl( - fd, ' ', ' ', "GENERAL_INFORMATION_FILE", "", ""); /* 000 */ - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */ - "RTY!RID", "(A(3),A(2))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '1', "DATA_SET_DESCRIPTION_FIELD", /* DRF */ - "NSH!NSV!NOZ!NOS", "(4I(2))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '0', "DATA_SET-ID_FIELD", /* DSI */ - "PRT!NAM", "(A(4),A(8))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '6', "OVERVIEW_INFORMATION_FIELD", /* OVI */ - "STR!ARV!BRV!LSO!PSO", "(I(1),I(8),I(8),A(11),A(10))"); - sizeOfFields[nFields++] += WriteFieldDecl( - fd, '1', '6', "GENERAL_INFORMATION_FIELD", /* GEN */ - "STR!LOD!LAD!UNIloa!SWO!SWA!NWO!NWA!NEO!NEA!SEO!SEA!SCA!ZNA!PSP!IMR!" - "ARV!BRV!LSO!PSO!TXT", - "(I(1),2R(6),I(3),A(11),A(10),A(11),A(10),A(11),A(10),A(11),A(10),I(9)," - "I(2),R(5),A(1),2I(8),A(11),A(10),A(64))"); - sizeOfFields[nFields++] += WriteFieldDecl( - fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */ - "NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF", - "(4I(6),2I(3),2I(6),5I(1),A(12),A(1))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */ - "*BID!WS1!WS2", "(A(5),I(5),I(5))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '2', '1', "TILE_INDEX_MAP_FIELD", /* TIM */ - "*TSI", "(I(5))"); - - FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, - nameOfFields); -} - -/************************************************************************/ -/* WriteGENFile_DataSetDescriptionRecord() */ -/************************************************************************/ - -/* Write DATA_SET_DESCRIPTION_RECORD */ -static void WriteGENFile_DataSetDescriptionRecord(VSILFILE *fd) -{ - int nFields = 0; - int sizeOfFields[] = {0, 0}; - const char *nameOfFields[] = {"001", "DRF"}; - const int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields)); - - /* Field 001 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "DSS", 3); /* RTY */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field DRF */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSH */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSV */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOZ */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOS */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - /* nFields++; */ - - FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, - nameOfFields); -} - -/************************************************************************/ -/* WriteGENFile_OverviewRecord() */ -/************************************************************************/ - -/* Write OVERVIEW_RECORD */ -static void WriteGENFile_OverviewRecord(VSILFILE *fd, CPLString &osBaseFileName, - int ARV, int BRV, double LSO, - double PSO, int nOvSizeX, int nOvSizeY, - int NFL, int NFC, int *TILEINDEX) -{ - int nFields = 0; - int sizeOfFields[] = {0, 0, 0, 0, 0, 0}; - const char *nameOfFields[] = {"001", "DSI", "OVI", "SPR", "BDF", "TIM"}; - const int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields)); - - /* Field 001 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "OVV", 3); /* RTY */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field DSI */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field OVI */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); // ARV - FIXME - sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); // BRV - FIXME - sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */ /* FIXME */ - sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */ /* FIXME */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field SPR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeX - 1, 6); /* NUS */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeY - 1, 6); /* NLL */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, (nOvSizeY + 127) / 128, 3); /* NFL */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, (nOvSizeX + 127) / 128, 3); /* NFC */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */ - char tmp[12 + 1]; - snprintf(tmp, sizeof(tmp), "%s.IMG", osBaseFileName.c_str()); /* FIXME */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 12); /* BAD */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field BDF */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field TIM */ - for (int i = 0; i < NFL * NFC; i++) - { - sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); // TSI - } - sizeOfFields[nFields] += WriteFieldTerminator(fd); - /* nFields++; */ - - FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, - nameOfFields); -} - -/************************************************************************/ -/* WriteGENFile_GeneralInformationRecord() */ -/************************************************************************/ - -/* Write GENERAL_INFORMATION_RECORD */ -static void WriteGENFile_GeneralInformationRecord( - VSILFILE *fd, CPLString &osNAM, CPLString &osBAD, int ARV, int BRV, - double LSO, double PSO, double *adfGeoTransform, int SCA, int nRasterXSize, - int nRasterYSize, int NFL, int NFC, int *TILEINDEX) - -{ - int nFields = 0; - int sizeOfFields[] = {0, 0, 0, 0, 0, 0}; - const char *nameOfFields[] = {"001", "DSI", "GEN", "SPR", "BDF", "TIM"}; - int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields)); - - /* Field 001 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "GIN", 3); /* RTY */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field DSI */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, osNAM.c_str(), 8); /* NAM */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field `GEN */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); // LOD - FIXME - sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); // LAD - FIXME - sizeOfFields[nFields] += WriteSubFieldInt(fd, 16, 3); // UNIloa - FIXME - sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */ - sizeOfFields[nFields] += - WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */ - sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* NWO */ - sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NWA */ - sizeOfFields[nFields] += - WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */ - sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */ - sizeOfFields[nFields] += - WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* SEO */ - sizeOfFields[nFields] += - WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SEA */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, SCA, 9); /* SCA */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* ZNA */ /* FIXME */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "100.0", 5); /* PSP */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* IMR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */ - sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */ - sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 64); /* TXT */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field SPR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, nRasterXSize - 1, 6); /* NUS */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, nRasterYSize - 1, 6); /* NLL */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, (nRasterYSize + 127) / 128, 3); /* NFL */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, (nRasterXSize + 127) / 128, 3); /* NFC */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, osBAD.c_str(), 12); /* BAD */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field BDF */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field TIM */ - for (int i = 0; i < NFL * NFC; i++) - { - sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); // TSI - } - sizeOfFields[nFields] += WriteFieldTerminator(fd); - /* nFields++; */ - - FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, - nameOfFields); -} - -/************************************************************************/ -/* WriteGENFile() */ -/************************************************************************/ - -void ADRGDataset::WriteGENFile() -{ - if (!bGeoTransformValid) - { - CPLError(CE_Failure, CPLE_AppDefined, "No geo transform available !"); - adfGeoTransform[0] = 0; - adfGeoTransform[3] = 0; - adfGeoTransform[1] = 1; - adfGeoTransform[5] = 1; - } - - LSO = adfGeoTransform[0]; - PSO = adfGeoTransform[3]; - ARV = (int)floor(360. / adfGeoTransform[1] + .5); - BRV = (int)floor(-360. / adfGeoTransform[5] + .5); - - /*ARV = ((ARV + 255) / 512) * 512; - BRV = ((BRV + 255) / 512) * 512;*/ - - const int SCA = (int)floor(1000000. * 400384 / BRV + 0.5); - - const int nOvSizeX = nRasterXSize; // FIXME - const int nOvSizeY = nRasterYSize; // FIXME - - /* Write header */ - WriteGENFile_Header(fdGEN); - - /* Write DATA_SET_DESCRIPTION_RECORD */ - WriteGENFile_DataSetDescriptionRecord(fdGEN); - - /* Write OVERVIEW_RECORD */ - WriteGENFile_OverviewRecord(fdGEN, osBaseFileName, ARV, BRV, LSO, PSO, - nOvSizeX, nOvSizeY, NFL, NFC, TILEINDEX); - - /* Write GENERAL_INFORMATION_RECORD */ - CPLString osNAM = osBaseFileName; - char tmp[12 + 1] = {}; - snprintf(tmp, sizeof(tmp), "%s.IMG", osNAM.c_str()); - CPLString osBAD = tmp; - WriteGENFile_GeneralInformationRecord( - fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO, adfGeoTransform, SCA, - nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX); - - if (CPLTestBool(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))) - { - strncpy(tmp, osBaseFileName.c_str(), 6); - tmp[6] = '\0'; - strcat(tmp, "02"); - osNAM = tmp; - snprintf(tmp, sizeof(tmp), "%s.IMG", osNAM.c_str()); - osBAD = tmp; - WriteGENFile_GeneralInformationRecord( - fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO, adfGeoTransform, SCA, - nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX); - } -} - -/************************************************************************/ -/* WriteTHFFile() */ -/************************************************************************/ - -void ADRGDataset::WriteTHFFile() -{ - VSILFILE *fd = fdTHF; - - /* Write header */ - { - int nFields = 0; - int sizeOfFields[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - const char *nameOfFields[] = {"000", "001", "VDR", "FDR", "QSR", "QUV", - "CPS", "CPT", "SPR", "BDF", "VFF"}; - const int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields)); - - sizeOfFields[nFields++] += WriteFieldDecl( - fd, ' ', ' ', "TRANSMITTAL_HEADER_FILE", "", ""); /* 000 */ - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */ - "RTY!RID", "(A(3),A(2))"); - sizeOfFields[nFields++] += WriteFieldDecl( - fd, '1', '6', "TRANSMITTAL_HEADER_FIELD", /* VDR */ - "MSD!VOO!ADR!NOV!SQN!NOF!URF!END!DAT", - "(A(1),A(200),A(1),I(1),I(1),I(3),A(16),I(3),A(12))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '6', "DATA_SET_DESCRIPTION_FIELD", /* FDR */ - "NAM!STR!PRT!SWO!SWA!NEO!NEA", - "(A(8),I(1),A(4),A(11),A(10),A(11),A(10))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '1', '0', "SECURITY_AND_RELEASE_FIELD", /* QSR */ - "QSS!QOD!DAT!QLE", "(A(1),A(1),A(12),A(200))"); - sizeOfFields[nFields++] += WriteFieldDecl( - fd, '1', '0', "VOLUME_UP_TO_DATENESS_FIELD", /* QUV */ - "SRC!DAT!SPA", "(A(100),A(12),A(20))"); - sizeOfFields[nFields++] += WriteFieldDecl( - fd, '1', '6', "TEST_PATCH_IDENTIFIER_FIELD", /* CPS */ - "PNM!DWV!REF!PUR!PIR!PIG!PIB", - "(A(7),I(6),R(5),R(5),I(3),I(3),I(3))"); - sizeOfFields[nFields++] += WriteFieldDecl( - fd, '1', '6', "TEST_PATCH_INFORMATION_FIELD", /* CPT */ - "STR!SCR", "(I(1),A(100))"); - sizeOfFields[nFields++] += WriteFieldDecl( - fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */ - "NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF", - "(I(6),I(6),I(6),I(6),I(3),I(3),I(6),I(6),I(1),I(1),I(1),I(1)," - "I(1),A(12),A(1))"); - sizeOfFields[nFields++] += - WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */ - "*BID!WS1!WS2", "(A(5),I(5),I(5))"); - sizeOfFields[nFields++] += WriteFieldDecl( - fd, '1', '0', "TRANSMITTAL_FILENAMES_FIELD", "VFF", "(A(51))"); - - FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), - sizeOfFields, nameOfFields); - } - - /* Write TRANSMITTAL_DESCRIPTION_RECORD */ - { - int nFields = 0; - int sizeOfFields[] = {0, 0, 0}; - const char *nameOfFields[] = {"001", "VDR", "FDR"}; - int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields)); - - /* Field 001 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "VTH", 3); /* RTY */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field VDR */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* MSD */ - // VOO - Title and address of originator - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); - sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* ADR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* NOV */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* SQN */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* NOF */ - // URF - DMA stock number for this CDROM - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 16); - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* END */ - sizeOfFields[nFields] += - WriteSubFieldStr(fd, "017,19940101", 12); // DAT - Publication date - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field FDR */ - sizeOfFields[nFields] += - WriteSubFieldStr(fd, osBaseFileName, 8); // NAM - sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */ - sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */ - sizeOfFields[nFields] += - WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); // SWA - sizeOfFields[nFields] += - WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); // NEO - sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - /* nFields++; */ - - FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), - sizeOfFields, nameOfFields); - } - - /* Write SECURITY_AND_UPDATE_RECORD */ - { - int nFields = 0; - int sizeOfFields[] = {0, 0, 0}; - const char *nameOfFields[] = {"001", "QSR", "QUV"}; - int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields)); - - /* Field 001 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "LCF", 3); /* RTY */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field VDR */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "U", 1); /* QSS */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* QOD */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 12); /* DAT */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* QLE */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field FDR */ - sizeOfFields[nFields] += WriteSubFieldStr( - fd, "MILITARY SPECIFICATION ARC DIGITIZED RASTER GRAPHICS (ADRG)", - 100); /* SRC */ - sizeOfFields[nFields] += - WriteSubFieldStr(fd, "022,19900222", 12); /* DAT */ - sizeOfFields[nFields] += - WriteSubFieldStr(fd, "MIL-A-89007", 20); /* SPA */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - /* nFields++; */ - - FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), - sizeOfFields, nameOfFields); - } - - /* Write TEST_PATCH_DATA_RECORD */ - { - int nFields = 0; - int sizeOfFields[] = {0, 0, 0, 0, 0}; - const char *nameOfFields[] = {"001", "CPS", "CPT", "SPR", "BDF"}; - const int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields)); - - /* Field 001 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "TPA", 3); /* RTY */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field CPS */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Black", 7); /* PNM */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 6); /* DMV */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* REF */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* PUR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIG */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIB */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field CPT */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 100); /* SCR */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - const int nPatchXSize = 512; - const int nPatchYSize = 512; - - /* Field SPR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, nPatchXSize - 1, 6); /* NUS */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, nPatchYSize - 1, 6); /* NLL */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, (nPatchYSize + 127) / 128, 3); /* NFL */ - sizeOfFields[nFields] += - WriteSubFieldInt(fd, (nPatchXSize + 127) / 128, 3); /* NFC */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */ - // BAD - sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 12); - sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* TIF */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field BDF */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */ - sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - /* nFields++; */ - - FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), - sizeOfFields, nameOfFields); - } - - /* Write TRANSMITTAL_FILENAMES_RECORD */ - { - int nFields = 0; - int sizeOfFields[] = {0, 0, 0, 0, 0, 0, 0}; - - /* Debug option to simulate ADRG datasets made of several images */ - int nTotalFields = - CPLTestBool(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF")) - ? 6 - : 5; - - const char *nameOfFields[] = {"001", "VFF", "VFF", "VFF", - "VFF", "VFF", "VFF"}; - const int pos = BeginLeader(fd, 9, 9, 3, nTotalFields); - - /* Field 001 */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "TFN", 3); /* RTY */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field VFF */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "TRANSH01.THF", 51); - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field VFF */ - sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 51); - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field VFF */ - char tmp[12 + 1] = {}; - snprintf(tmp, sizeof(tmp), "%s.GEN", osBaseFileName.c_str()); - sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - /* Field VFF */ - snprintf(tmp, sizeof(tmp), "%s.IMG", osBaseFileName.c_str()); - sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - nFields++; - - if (nTotalFields == 6) - { - /* Field VFF */ - strncpy(tmp, osBaseFileName.c_str(), 6); - tmp[6] = '\0'; - strcat(tmp, "02.IMG"); - sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */ - sizeOfFields[nFields] += WriteFieldTerminator(fd); - /* nFields++; */ - } - - FinishWriteLeader(fd, pos, 9, 9, 3, nTotalFields, sizeOfFields, - nameOfFields); - } -} - /************************************************************************/ /* GDALRegister_ADRG() */ /************************************************************************/ @@ -2405,12 +1237,10 @@ void GDALRegister_ADRG() "ARC Digitized Raster Graphics"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/adrg.html"); poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gen"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte"); poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES"); poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); poDriver->pfnOpen = ADRGDataset::Open; - poDriver->pfnCreate = ADRGDataset::Create; GetGDALDriverManager()->RegisterDriver(poDriver); } diff --git a/frmts/blx/CMakeLists.txt b/frmts/blx/CMakeLists.txt deleted file mode 100644 index c546749ab2e2..000000000000 --- a/frmts/blx/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_gdal_driver(TARGET gdal_BLX SOURCES blx.c blx.h blxdataset.cpp PLUGIN_CAPABLE NO_DEPS) -gdal_standard_includes(gdal_BLX) -target_compile_definitions(gdal_BLX PRIVATE -DGDALDRIVER) diff --git a/frmts/blx/blx.c b/frmts/blx/blx.c deleted file mode 100644 index ec0df53ab1d2..000000000000 --- a/frmts/blx/blx.c +++ /dev/null @@ -1,1545 +0,0 @@ -/* libblx - Magellan BLX topo reader/writer library - * - * Copyright (c) 2008, Henrik Johansson - * Copyright (c) 2008-2009, Even Rouault - * - * SPDX-License-Identifier: MIT - */ - -#include "blx.h" -#include -#include -#include - -#include "cpl_port.h" - -/* Constants */ -#define MAXLEVELS 5 -#define MAXCOMPONENTS 4 - -static const int table1[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, - 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, - 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, - 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255}; - -/* { byte, n of bits when compressed, bit pattern << (13-n of bits) } */ -static const int table2[][3] = { - {0, 2, 0}, {255, 3, 2048}, {1, 3, 3072}, {2, 4, 4096}, - {3, 4, 4608}, {254, 5, 5120}, {4, 5, 5376}, {5, 5, 5632}, - {253, 6, 5888}, {6, 6, 6016}, {252, 6, 6144}, {7, 6, 6272}, - {251, 6, 6400}, {8, 6, 6528}, {9, 7, 6656}, {250, 7, 6720}, - {10, 7, 6784}, {249, 7, 6848}, {11, 7, 6912}, {248, 7, 6976}, - {12, 8, 7040}, {247, 8, 7072}, {16, 8, 7104}, {246, 8, 7136}, - {13, 8, 7168}, {245, 8, 7200}, {14, 8, 7232}, {244, 8, 7264}, - {15, 8, 7296}, {243, 8, 7328}, {242, 8, 7360}, {241, 8, 7392}, - {17, 9, 7424}, {18, 9, 7440}, {240, 9, 7456}, {239, 9, 7472}, - {19, 9, 7488}, {238, 9, 7504}, {20, 9, 7520}, {237, 9, 7536}, - {21, 9, 7552}, {236, 9, 7568}, {22, 9, 7584}, {235, 9, 7600}, - {234, 9, 7616}, {23, 9, 7632}, {233, 9, 7648}, {24, 10, 7664}, - {232, 10, 7672}, {231, 10, 7680}, {25, 10, 7688}, {230, 10, 7696}, - {229, 10, 7704}, {26, 10, 7712}, {228, 10, 7720}, {27, 10, 7728}, - {227, 10, 7736}, {225, 10, 7744}, {226, 10, 7752}, {28, 10, 7760}, - {29, 10, 7768}, {224, 10, 7776}, {30, 10, 7784}, {31, 10, 7792}, - {223, 10, 7800}, {32, 10, 7808}, {222, 10, 7816}, {33, 10, 7824}, - {221, 11, 7832}, {220, 11, 7836}, {34, 11, 7840}, {219, 11, 7844}, - {35, 11, 7848}, {218, 11, 7852}, {256, 11, 7856}, {36, 11, 7860}, - {217, 11, 7864}, {216, 11, 7868}, {37, 11, 7872}, {215, 11, 7876}, - {38, 11, 7880}, {214, 11, 7884}, {193, 11, 7888}, {213, 11, 7892}, - {39, 11, 7896}, {128, 11, 7900}, {212, 11, 7904}, {40, 11, 7908}, - {194, 11, 7912}, {211, 11, 7916}, {210, 11, 7920}, {41, 11, 7924}, - {209, 11, 7928}, {208, 11, 7932}, {42, 11, 7936}, {207, 11, 7940}, - {43, 11, 7944}, {195, 11, 7948}, {206, 11, 7952}, {205, 11, 7956}, - {204, 11, 7960}, {44, 11, 7964}, {203, 11, 7968}, {192, 11, 7972}, - {196, 11, 7976}, {45, 11, 7980}, {201, 11, 7984}, {200, 11, 7988}, - {197, 11, 7992}, {202, 11, 7996}, {127, 11, 8000}, {199, 11, 8004}, - {198, 11, 8008}, {46, 12, 8012}, {47, 12, 8014}, {48, 12, 8016}, - {49, 12, 8018}, {50, 12, 8020}, {51, 12, 8022}, {191, 12, 8024}, - {52, 12, 8026}, {183, 12, 8028}, {53, 12, 8030}, {54, 12, 8032}, - {55, 12, 8034}, {190, 12, 8036}, {56, 12, 8038}, {57, 12, 8040}, - {189, 12, 8042}, {58, 12, 8044}, {176, 12, 8046}, {59, 12, 8048}, - {126, 12, 8050}, {60, 12, 8052}, {188, 12, 8054}, {61, 12, 8056}, - {63, 12, 8058}, {62, 12, 8060}, {64, 12, 8062}, {129, 12, 8064}, - {187, 12, 8066}, {186, 12, 8068}, {65, 12, 8070}, {66, 12, 8072}, - {185, 12, 8074}, {184, 12, 8076}, {68, 12, 8078}, {174, 12, 8080}, - {67, 12, 8082}, {182, 13, 8084}, {69, 13, 8085}, {180, 13, 8086}, - {181, 13, 8087}, {71, 13, 8088}, {70, 13, 8089}, {179, 13, 8090}, - {125, 13, 8091}, {72, 13, 8092}, {130, 13, 8093}, {178, 13, 8094}, - {177, 13, 8095}, {73, 13, 8096}, {74, 13, 8097}, {124, 13, 8098}, - {76, 13, 8099}, {175, 13, 8100}, {75, 13, 8101}, {131, 13, 8102}, - {132, 13, 8103}, {79, 13, 8104}, {77, 13, 8105}, {123, 13, 8106}, - {80, 13, 8107}, {172, 13, 8108}, {171, 13, 8109}, {78, 13, 8110}, - {173, 13, 8111}, {81, 13, 8112}, {169, 13, 8113}, {122, 13, 8114}, - {82, 13, 8115}, {133, 13, 8116}, {168, 13, 8117}, {84, 13, 8118}, - {164, 13, 8119}, {167, 13, 8120}, {85, 13, 8121}, {170, 13, 8122}, - {166, 13, 8123}, {165, 13, 8124}, {121, 13, 8125}, {160, 13, 8126}, - {134, 13, 8127}, {136, 13, 8128}, {161, 13, 8129}, {120, 13, 8130}, - {88, 13, 8131}, {83, 13, 8132}, {119, 13, 8133}, {163, 13, 8134}, - {162, 13, 8135}, {159, 13, 8136}, {91, 13, 8137}, {135, 13, 8138}, - {90, 13, 8139}, {86, 13, 8140}, {137, 13, 8141}, {87, 13, 8142}, - {89, 13, 8143}, {158, 13, 8144}, {152, 13, 8145}, {138, 13, 8146}, - {139, 13, 8147}, {116, 13, 8148}, {140, 13, 8149}, {92, 13, 8150}, - {96, 13, 8151}, {157, 13, 8152}, {153, 13, 8153}, {97, 13, 8154}, - {94, 13, 8155}, {93, 13, 8156}, {117, 13, 8157}, {156, 13, 8158}, - {155, 13, 8159}, {95, 13, 8160}, {118, 13, 8161}, {143, 13, 8162}, - {151, 13, 8163}, {142, 13, 8164}, {104, 13, 8165}, {100, 13, 8166}, - {148, 13, 8167}, {144, 13, 8168}, {154, 13, 8169}, {115, 13, 8170}, - {113, 13, 8171}, {98, 13, 8172}, {146, 13, 8173}, {112, 13, 8174}, - {145, 13, 8175}, {149, 13, 8176}, {141, 13, 8177}, {150, 13, 8178}, - {103, 13, 8179}, {147, 13, 8180}, {99, 13, 8181}, {108, 13, 8182}, - {101, 13, 8183}, {114, 13, 8184}, {105, 13, 8185}, {102, 13, 8186}, - {107, 13, 8187}, {109, 13, 8188}, {110, 13, 8189}, {111, 13, 8190}, - {106, 13, 8191}, {0, 0, 8192}}; - -static const int table3[] = {0x20, 0x2f, 0x44, 0x71, 0x95, 0x101}; - -STATIC int compress_chunk(unsigned char *inbuf, int inlen, - unsigned char *outbuf, int outbuflen) -{ - int next, m = 0, j, outlen = 0; - unsigned reg = 0; - - next = *inbuf++; - inlen--; - while (next >= 0) - { - /* Find index of input byte in table2 and put it in j */ - j = 0; - while (next != table2[j][0]) - j++; - - if (inlen) - { - next = *inbuf++; - inlen--; - } - else - { - if (next == 0x100) - next = -1; - else - next = 0x100; - } - reg = (reg << table2[j][1]) | (table2[j][2] >> (13 - table2[j][1])); - m += table2[j][1]; - - while (m >= 8) - { - if (outlen >= outbuflen) - return -1; - *outbuf++ = (unsigned char)((reg >> (m - 8)) & 0xff); - outlen++; - m -= 8; - } - } - if (outlen >= outbuflen) - return -1; - *outbuf++ = (unsigned char)((reg << (8 - m)) & 0xff); - - return outlen + 1; -} - -STATIC int uncompress_chunk(unsigned char *inbuf, int inlen, - unsigned char *outbuf, int outbuflen) -{ - int i, j, k, m = 0, outlen = 0; - unsigned reg, newdata; - - if (inlen < 4) - return -1; - - reg = *(inbuf + 3) | (*(inbuf + 2) << 8) | (*(inbuf + 1) << 16) | - ((unsigned)*(inbuf + 0) << 24); - inbuf += 4; - inlen -= 4; - - newdata = (reg >> 19) & 0x1fff; - - while (1) - { - j = newdata >> 5; - - if (table1[j] == 0xff) - { - i = 1; - while ((int)newdata >= table2[table3[i]][2]) - i++; - - j = table3[i - 1]; - - k = j + ((newdata - table2[j][2]) >> (13 - table2[j][1])); - - if (table2[k][0] == 0x100) - break; - else - { - if (outlen >= outbuflen) - return -1; - *outbuf++ = (unsigned char)table2[k][0]; - outlen++; - } - } - else - { - j = table1[j]; - if (outlen >= outbuflen) - return -1; - *outbuf++ = (unsigned char)table2[j][0]; - outlen++; - } - - m += table2[j][1]; - - if (m >= 19) - { - if (m >= 8) - { - for (i = m >> 3; i; i--) - { - if (inlen) - { - reg = (reg << 8) | *inbuf++; - inlen--; - } - else - reg = reg << 8; - } - } - m = m & 7; - } - newdata = (reg >> (19 - m)) & 0x1fff; - } - return outlen; -} - -/* - Reconstruct a new detail level with double resolution in the horizontal - direction from data from the previous detail level and plus new differential - data. -*/ -STATIC blxdata *reconstruct_horiz(blxdata *base, blxdata *diff, unsigned rows, - unsigned cols, blxdata *out) -{ - unsigned int i, j; - blxdata tmp; - - /* Last column */ - for (i = 0; i < rows; i++) - out[2 * (cols * i + cols - 1)] = - diff[cols * i + cols - 1] + - (((short)(base[cols * i + cols - 2] - base[cols * i + cols - 1] - - 1)) >> - 2); - - /* Intermediate columns */ - for (i = 0; i < rows; i++) - for (j = cols - 2; j > 0; j--) - out[2 * (cols * i + j)] = - diff[cols * i + j] + - (((short)(base[cols * i + j] + - 2 * (base[cols * i + j - 1] - - out[2 * (cols * i + j + 1)]) - - 3 * base[cols * i + j + 1] + 1)) >> - 3); - - /* First column */ - for (i = 0; i < rows; i++) - out[2 * cols * i] = - diff[cols * i] + - (((short)(base[cols * i] - base[cols * i + 1] + 1)) >> 2); - - for (i = 0; i < rows; i++) - for (j = 0; j < cols; j++) - { - tmp = base[cols * i + j] + - (((short)(out[2 * (cols * i + j)] + 1)) >> 1); - out[2 * cols * i + 2 * j + 1] = tmp - out[2 * (cols * i + j)]; - out[2 * cols * i + 2 * j] = tmp; - } - - return out; -} - -/* - Reconstruct a new detail level with double resolution in the vertical - direction from data from the previous detail level and plus new differential - data. -*/ -STATIC blxdata *reconstruct_vert(blxdata *base, blxdata *diff, unsigned rows, - unsigned cols, blxdata *out) -{ - unsigned int i, j; - blxdata tmp; - - /* Last row */ - for (i = 0; i < cols; i++) - out[2 * cols * (rows - 1) + i] = - diff[cols * (rows - 1) + i] + - (((short)(base[cols * (rows - 2) + i] - - base[cols * (rows - 1) + i] - 1)) >> - 2); - - /* Intermediate rows */ - for (i = 0; i < cols; i++) - for (j = rows - 2; j > 0; j--) - out[2 * cols * j + i] = - diff[cols * j + i] + - ((short)((base[cols * j + i] + - 2 * (base[cols * (j - 1) + i] - - out[2 * cols * (j + 1) + i]) - - 3 * base[cols * (j + 1) + i] + 1)) >> - 3); - - /* First row */ - for (i = 0; i < cols; i++) - out[i] = diff[i] + (((short)(base[i] - base[i + cols] + 1)) >> 2); - - for (i = 0; i < cols; i++) - for (j = 0; j < rows; j++) - { - tmp = base[cols * j + i] + - (((short)(out[2 * cols * j + i] + 1)) >> 1); - out[cols * (2 * j + 1) + i] = tmp - out[2 * cols * j + i]; - out[cols * 2 * j + i] = tmp; - } - return out; -} - -/* - Inverse of reconstruct_horiz - */ -STATIC void decimate_horiz(blxdata *in, unsigned int rows, unsigned int cols, - blxdata *base, blxdata *diff) -{ - unsigned int i, j; - blxdata tmp; - - for (i = 0; i < rows; i++) - { - for (j = 0; j < cols; j += 2) - { - tmp = in[i * cols + j] - in[i * cols + j + 1]; - diff[i * cols / 2 + j / 2] = tmp; - base[i * cols / 2 + j / 2] = - in[i * cols + j] - (((short)(tmp + 1)) >> 1); - } - } - - /* First column */ - for (i = 0; i < rows; i++) - { - diff[cols / 2 * i] -= - ((short)(base[i * cols / 2] - base[i * cols / 2 + 1] + 1)) >> 2; - } - - /* Intermediate columns */ - for (i = 0; i < rows; i++) - for (j = 1; j < cols / 2 - 1; j++) - diff[cols / 2 * i + j] -= - ((short)(base[cols / 2 * i + j] + - 2 * (base[cols / 2 * i + j - 1] - - diff[cols / 2 * i + j + 1]) - - 3 * base[cols / 2 * i + j + 1] + 1)) >> - 3; - - /* Last column */ - for (i = 0; i < rows; i++) - diff[cols / 2 * i + cols / 2 - 1] -= - ((short)(base[i * cols / 2 + cols / 2 - 2] - - base[i * cols / 2 + cols / 2 - 1] - 1)) >> - 2; -} - -/* - Inverse of reconstruct_vert - */ -STATIC void decimate_vert(blxdata *in, unsigned int rows, unsigned int cols, - blxdata *base, blxdata *diff) -{ - unsigned int i, j; - blxdata tmp; - - for (i = 0; i < rows; i += 2) - for (j = 0; j < cols; j++) - { - tmp = in[i * cols + j] - in[(i + 1) * cols + j]; - diff[i / 2 * cols + j] = tmp; - base[i / 2 * cols + j] = - in[i * cols + j] - (((short)(tmp + 1)) >> 1); - } - - /* First row */ - for (j = 0; j < cols; j++) - diff[j] -= ((short)(base[j] - base[cols + j] + 1)) >> 2; - - /* Intermediate rows */ - for (i = 1; i < rows / 2 - 1; i++) - for (j = 0; j < cols; j++) - diff[cols * i + j] -= ((short)(base[cols * i + j] + - 2 * (base[cols * (i - 1) + j] - - diff[cols * (i + 1) + j]) - - 3 * base[cols * (i + 1) + j] + 1)) >> - 3; - - /* Last row */ - for (j = 0; j < cols; j++) - diff[cols * (rows / 2 - 1) + j] -= - ((short)(base[cols * (rows / 2 - 2) + j] - - base[cols * (rows / 2 - 1) + j] - 1)) >> - 2; -} - -typedef union -{ - short s; - unsigned short u; -} unionshort; - -static int get_short_le(const unsigned char **data) -{ - /* We assume two's complement representation for this to work */ - unionshort result = {0}; - result.u = (unsigned short)(*(*data) | (*(*data + 1) << 8)); - *data += 2; - return result.s; -} - -static int get_short_be(const unsigned char **data) -{ - /* We assume two's complement representation for this to work */ - unionshort result = {0}; - result.u = (unsigned short)(*(*data + 1) | (*(*data) << 8)); - *data += 2; - return result.s; -} - -static void put_short_le(short data, unsigned char **bufptr) -{ - /* We assume two's complement representation for this to work */ - unionshort us = {0}; - us.s = data; - *(*bufptr)++ = (unsigned char)(us.u & 0xff); - *(*bufptr)++ = (unsigned char)((us.u >> 8) & 0xff); -} - -static void put_short_be(short data, unsigned char **bufptr) -{ - /* We assume two's complement representation for this to work */ - unionshort us = {0}; - us.s = data; - *(*bufptr)++ = (unsigned char)((us.u >> 8) & 0xff); - *(*bufptr)++ = (unsigned char)(us.u & 0xff); -} - -static int get_unsigned_short_le(const unsigned char **data) -{ - int result; - - result = *(*data) | (*(*data + 1) << 8); - *data += 2; - return result; -} - -static int get_unsigned_short_be(const unsigned char **data) -{ - int result; - - result = *(*data + 1) | (*(*data) << 8); - *data += 2; - return result; -} - -static void put_unsigned_short_le(unsigned short data, unsigned char **bufptr) -{ - *(*bufptr)++ = (unsigned char)(data & 0xff); - *(*bufptr)++ = (unsigned char)((data >> 8) & 0xff); -} - -static void put_unsigned_short_be(unsigned short data, unsigned char **bufptr) -{ - *(*bufptr)++ = (unsigned char)((data >> 8) & 0xff); - *(*bufptr)++ = (unsigned char)(data & 0xff); -} - -static int get_short(blxcontext_t *ctx, const unsigned char **data) -{ - - if (ctx->endian == LITTLEENDIAN) - return get_short_le(data); - else - return get_short_be(data); -} - -static int get_unsigned_short(blxcontext_t *ctx, const unsigned char **data) -{ - - if (ctx->endian == LITTLEENDIAN) - return get_unsigned_short_le(data); - else - return get_unsigned_short_be(data); -} - -static void put_short(blxcontext_t *ctx, short data, unsigned char **bufptr) -{ - if (ctx->endian == LITTLEENDIAN) - put_short_le(data, bufptr); - else - put_short_be(data, bufptr); -} - -static void put_unsigned_short(blxcontext_t *ctx, unsigned short data, - unsigned char **bufptr) -{ - if (ctx->endian == LITTLEENDIAN) - put_unsigned_short_le(data, bufptr); - else - put_unsigned_short_be(data, bufptr); -} - -typedef union -{ - int i; - unsigned int u; -} unionint; - -static int get_int32(blxcontext_t *ctx, const unsigned char **data) -{ - /* We assume two's complement representation for this to work */ - unionint result = {0}; - - if (ctx->endian == LITTLEENDIAN) - result.u = *(*data) | (*(*data + 1) << 8) | (*(*data + 2) << 16) | - ((unsigned)*(*data + 3) << 24); - else - result.u = *(*data + 3) | (*(*data + 2) << 8) | (*(*data + 1) << 16) | - ((unsigned)*(*data) << 24); - *data += 4; - return result.i; -} - -static void put_int32(blxcontext_t *ctx, int data, unsigned char **bufptr) -{ - /* We assume two's complement representation for this to work */ - unionint ui = {0}; - ui.i = data; - if (ctx->endian == LITTLEENDIAN) - { - *(*bufptr)++ = (unsigned char)(ui.u & 0xff); - *(*bufptr)++ = (unsigned char)((ui.u >> 8) & 0xff); - *(*bufptr)++ = (unsigned char)((ui.u >> 16) & 0xff); - *(*bufptr)++ = (unsigned char)((ui.u >> 24) & 0xff); - } - else - { - *(*bufptr)++ = (unsigned char)((ui.u >> 24) & 0xff); - *(*bufptr)++ = (unsigned char)((ui.u >> 16) & 0xff); - *(*bufptr)++ = (unsigned char)((ui.u >> 8) & 0xff); - *(*bufptr)++ = (unsigned char)(ui.u & 0xff); - } -} - -static int get_unsigned32(blxcontext_t *ctx, const unsigned char **data) -{ - int result; - - if (ctx->endian == LITTLEENDIAN) - result = *(*data) | (*(*data + 1) << 8) | (*(*data + 2) << 16) | - ((unsigned)*(*data + 3) << 24); - else - result = *(*data + 3) | (*(*data + 2) << 8) | (*(*data + 1) << 16) | - ((unsigned)*(*data) << 24); - *data += 4; - return result; -} - -/* Check native endian order */ -static int is_big_endian(void) -{ - short int word = 0x0001; - char *byte = (char *)&word; - return (byte[0] ? 0 : 1); -} - -static double doubleSWAP(double df) -{ - CPL_SWAP64PTR(&df); - return df; -} - -static double get_double(blxcontext_t *ctx, const unsigned char **data) -{ - double result; - memcpy(&result, *data, sizeof(double)); - if ((is_big_endian() && ctx->endian == LITTLEENDIAN) || - (!is_big_endian() && ctx->endian == BIGENDIAN)) - result = doubleSWAP(result); - - *data += sizeof(double); - - return result; -} - -static void put_double(blxcontext_t *ctx, double data, unsigned char **bufptr) -{ - if ((is_big_endian() && ctx->endian == LITTLEENDIAN) || - (!is_big_endian() && ctx->endian == BIGENDIAN)) - data = doubleSWAP(data); - memcpy(*bufptr, &data, sizeof(double)); - *bufptr += sizeof(double); -} - -static void put_cellindex_entry(blxcontext_t *ctx, struct cellindex_s *ci, - unsigned char **buffer) -{ - put_int32(ctx, (int)ci->offset, buffer); - put_unsigned_short(ctx, (unsigned short)ci->datasize, buffer); - put_unsigned_short(ctx, (unsigned short)ci->compdatasize, buffer); -} - -/* Transpose matrix in-place */ -static void transpose(blxdata *data, int rows, int cols) -{ - int i, j; - blxdata tmp; - - for (i = 0; i < rows; i++) - for (j = i + 1; j < cols; j++) - { - tmp = data[i * cols + j]; - data[i * cols + j] = data[j * cols + i]; - data[j * cols + i] = tmp; - } -} - -struct lutentry_s -{ - blxdata value; - int frequency; -}; - -static int lutcmp(const void *aa, const void *bb) -{ - const struct lutentry_s *a = aa, *b = bb; - - return b->frequency - a->frequency; -} - -int blx_encode_celldata(blxcontext_t *ctx, blxdata *indata, int side, - unsigned char *outbuf, CPL_UNUSED int outbufsize) -{ - unsigned char *p = outbuf, *tmpdata, *coutstart, *cout = NULL; - int level, cn, coutsize, zeros; - blxdata *vdec = NULL, *vdiff = NULL, *c[4] = {NULL}, *tc1, *clut, - *indata_scaled; - - struct lutentry_s lut[256]; - int lutsize = 0; - - int i, j; - - memset(&lut, 0, sizeof(lut)); - lut[0].value = 0; - - *p++ = (unsigned char)(side / 32 - 4); /* Resolution */ - - /* Allocated memory for buffers */ - indata_scaled = BLXmalloc(sizeof(blxdata) * side * side); - vdec = BLXmalloc(sizeof(blxdata) * side * side / 2); - vdiff = BLXmalloc(sizeof(blxdata) * side * side / 2); - for (cn = 0; cn < 4; cn++) - c[cn] = BLXmalloc(sizeof(blxdata) * side * side / 4); - tc1 = BLXmalloc(sizeof(blxdata) * side * side / 4); - tmpdata = BLXmalloc(5 * 4 * side * side / 4); - - /* Scale indata and process undefined values*/ - for (i = 0; i < side * side; i++) - { - if ((indata[i] == BLX_UNDEF) && ctx->fillundef) - indata[i] = (blxdata)ctx->fillundefval; - /* cppcheck-suppress uninitdata */ - indata_scaled[i] = (blxdata)(indata[i] / ctx->zscale); - } - - indata = indata_scaled; - - cout = tmpdata; - - for (level = 0; level < 5; level++) - { - if (ctx->debug) - { - BLXdebug1("\nlevel=%d\n", level); - } - decimate_vert(indata, side, side, vdec, vdiff); - decimate_horiz(vdec, side / 2, side, c[0], c[1]); - decimate_horiz(vdiff, side / 2, side, c[2], c[3]); - - /* For some reason the matrix is transposed if the lut is used for - * vdec_hdiff */ - for (i = 0; i < side / 2; i++) - for (j = 0; j < side / 2; j++) - { - tc1[j * side / 2 + i] = c[1][i * side / 2 + j]; - tc1[i * side / 2 + j] = c[1][j * side / 2 + i]; - } - - for (cn = 1; cn < 4; cn++) - { - /* Use the possibly transposed version of c when building lut */ - if (cn == 1) - clut = tc1; - else - clut = c[cn]; - - lutsize = 0; - coutstart = cout; - for (i = 0; i < side * side / 4; i++) - { - /* Find element in lookup table */ - for (j = 0; (j < lutsize) && (lut[j].value != clut[i]); j++) - ; - - if (clut[i] != 0) - { - if (j == lutsize) - { - lut[lutsize].value = clut[i]; - lut[lutsize].frequency = 1; - lutsize++; - if (lutsize >= 255) - break; - } - else - lut[j].frequency++; - } - } - if (lutsize < 255) - { - /* Since the Huffman table is arranged to let smaller number - occupy less bits after the compression, the lookup table is sorted on - frequency */ - qsort(lut, lutsize, sizeof(struct lutentry_s), lutcmp); - - zeros = 0; - for (i = 0; i < side * side / 4; i++) - { - if (clut[i] == 0) - zeros++; - if (((zeros > 0) && (clut[i] != 0)) || - (zeros >= 0x100 - lutsize)) - { - *cout++ = (unsigned char)(0x100 - zeros); - zeros = 0; - } - if (clut[i] != 0) - { - for (j = 0; (j < lutsize) && (lut[j].value != clut[i]); - j++) - ; - *cout++ = (unsigned char)j; - } - } - if (zeros > 0) - *cout++ = (unsigned char)(0x100 - zeros); - } - /* Use the lookuptable only when it pays off to do do. - For some reason there cannot be lookup tables in level 4. - Otherwise Mapsend crashes. */ - coutsize = (int)(cout - coutstart); - if ((lutsize < 255) && - (coutsize + 2 * lutsize + 1 < 2 * side * side / 4) && - (level < 4)) - { - *p++ = (unsigned char)(lutsize + 1); - for (j = 0; j < lutsize; j++) - put_short_le(lut[j].value, &p); - put_short_le((short)coutsize, &p); - - if (ctx->debug) - { - BLXdebug2("n=%d dlen=%d\n", lutsize + 1, coutsize); - BLXdebug0("lut={"); - for (i = 0; i < lutsize; i++) - BLXdebug1("%d, ", lut[i].value); - BLXdebug0("}\n"); - } - } - else - { - *p++ = 0; - cout = coutstart; - for (i = 0; i < side * side / 4; i++) - put_short(ctx, c[cn][i], &cout); - } - } - - side >>= 1; - indata = c[0]; - } - - memcpy(p, tmpdata, cout - tmpdata); - p += cout - tmpdata; - - for (i = 0; i < side * side; i++) - put_short(ctx, indata[i], &p); - - *p++ = 0; - - BLXfree(indata_scaled); - BLXfree(vdec); - BLXfree(vdiff); - for (cn = 0; cn < 4; cn++) - BLXfree(c[cn]); - BLXfree(tc1); - BLXfree(tmpdata); - - return (int)(p - outbuf); -} - -STATIC blxdata *decode_celldata(blxcontext_t *ctx, const unsigned char *inbuf, - int len, int *side, blxdata *outbuf, - int outbufsize, int overviewlevel) -{ - const unsigned char *inptr = inbuf; - int resolution, l_div, level, c, n, i, j, dpos, tmp, a, value, l_index, - step, cellsize; - int baseside[12] = {0}; - blxdata *base, *diff; - struct component_s linfo[MAXLEVELS][MAXCOMPONENTS]; - - if (len < 1) - { - BLXerror0("Cell corrupt"); - return NULL; - } - resolution = *inptr++; - len--; - - tmp = (resolution + 4) * 32; - for (l_div = 1; l_div < 12; l_div++) - baseside[l_div - 1] = tmp >> l_div; - - if (side != NULL) - *side = tmp >> overviewlevel; - - cellsize = tmp * tmp; - if (outbufsize < cellsize * (int)sizeof(blxdata)) - { - BLXerror0("Cell will not fit in output buffer\n"); - return NULL; - } - - if (outbuf == NULL) - { - BLXerror0("outbuf is NULL"); - return NULL; - } - - if (ctx->debug) - { - BLXdebug0("==============================\n"); - } - - /* Clear level info structure */ - memset(linfo, 0, sizeof(linfo)); - - base = BLXmalloc(sizeof(blxdata) * 2 * baseside[0] * baseside[0]); - diff = BLXmalloc(sizeof(blxdata) * 2 * baseside[0] * baseside[0]); - if (base == NULL || diff == NULL) - { - BLXerror0("Not enough memory\n"); - outbuf = NULL; - goto error; - } - - for (level = 0; level < 5; level++) - { - for (c = 1; c < 4; c++) - { - if (len < 1) - { - BLXerror0("Cell corrupt"); - outbuf = NULL; - goto error; - } - n = *inptr++; - len--; - linfo[level][c].n = n; - if (n > 0) - { - linfo[level][c].lut = BLXmalloc(sizeof(blxdata) * (n - 1)); - if (len < (int)sizeof(short) * n) - { - BLXerror0("Cell corrupt"); - outbuf = NULL; - goto error; - } - for (i = 0; i < n - 1; i++) - linfo[level][c].lut[i] = (blxdata)get_short_le(&inptr); - linfo[level][c].dlen = get_short_le(&inptr); - if (linfo[level][c].dlen < 0) - { - BLXerror0("Cell corrupt"); - outbuf = NULL; - goto error; - } - len -= sizeof(short) * n; - } - else - { - linfo[level][c].dlen = 0; - } - } - } - - for (level = 0; level < 5; level++) - { - if (ctx->debug) - { - BLXdebug1("\nlevel=%d\n", level); - } - - linfo[level][0].data = - BLXmalloc(sizeof(blxdata) * baseside[level] * baseside[level]); - if (linfo[level][0].data == NULL) - { - BLXerror0("Not enough memory\n"); - outbuf = NULL; - goto error; - } - - for (c = 1; c < 4; c++) - { - if (ctx->debug) - { - BLXdebug2("n=%d dlen=%d\n", linfo[level][c].n, - linfo[level][c].dlen); - BLXdebug0("lut={"); - for (i = 0; i < linfo[level][c].n - 1; i++) - BLXdebug1("%d, ", linfo[level][c].lut[i]); - BLXdebug0("}\n"); - } - - linfo[level][c].data = - BLXmalloc(sizeof(blxdata) * baseside[level] * baseside[level]); - if (linfo[level][c].data == NULL) - { - BLXerror0("Not enough memory\n"); - outbuf = NULL; - goto error; - } - - if (linfo[level][c].n == 0) - { - if (len < - (int)sizeof(short) * baseside[level] * baseside[level]) - { - BLXerror0("Cell corrupt"); - outbuf = NULL; - goto error; - } - for (i = 0; i < baseside[level] * baseside[level]; i++) - linfo[level][c].data[i] = (blxdata)get_short(ctx, &inptr); - len -= sizeof(short) * baseside[level] * baseside[level]; - } - else - { - dpos = 0; - if (len < linfo[level][c].dlen) - { - BLXerror0("Cell corrupt"); - outbuf = NULL; - goto error; - } - for (i = 0; i < linfo[level][c].dlen; i++) - { - unsigned char v = *inptr++; - if (v >= linfo[level][c].n - 1) - { - if (dpos + 256 - v > baseside[level] * baseside[level]) - { - BLXerror0("Cell corrupt\n"); - outbuf = NULL; - goto error; - } - /* coverity[tainted_data] */ - for (j = 0; j < 256 - v; j++) - linfo[level][c].data[dpos++] = 0; - } - else - { - if (dpos + 1 > baseside[level] * baseside[level]) - { - BLXerror0("Cell corrupt\n"); - outbuf = NULL; - goto error; - } - linfo[level][c].data[dpos++] = linfo[level][c].lut[v]; - } - } - len -= linfo[level][c].dlen; - if (c == 1) - transpose(linfo[level][c].data, baseside[level], - baseside[level]); - } - if (0 && ctx->debug) - { - BLXdebug1("baseside:%d\n", baseside[level]); - BLXdebug0("data={"); - for (i = 0; i < baseside[level] * baseside[level]; i++) - BLXdebug1("%d, ", linfo[level][c].data[i]); - BLXdebug0("}\n"); - } - } - } - - if (len < (int)sizeof(short) * baseside[4] * baseside[4]) - { - BLXerror0("Cell corrupt"); - outbuf = NULL; - goto error; - } - for (i = 0; i < baseside[4] * baseside[4]; i++) - linfo[4][0].data[i] = (blxdata)get_short(ctx, &inptr); - len -= sizeof(short) * baseside[4] * baseside[4]; - - for (level = 4; level >= overviewlevel; level--) - { - if (ctx->debug) - { - BLXdebug1("baseside:%d\n", baseside[level]); - BLXdebug0("inbase={"); - for (i = 0; i < baseside[level] * baseside[level]; i++) - BLXdebug1("%d, ", linfo[level][0].data[i]); - BLXdebug0("}\n"); - BLXdebug0("indiff={"); - for (i = 0; i < baseside[level] * baseside[level]; i++) - BLXdebug1("%d, ", linfo[level][1].data[i]); - BLXdebug0("}\n"); - } - - reconstruct_horiz(linfo[level][0].data, linfo[level][1].data, - baseside[level], baseside[level], base); - if (ctx->debug) - { - BLXdebug0("base={"); - for (i = 0; i < baseside[level] * baseside[level]; i++) - BLXdebug1("%d, ", base[i]); - BLXdebug0("}\n"); - } - - reconstruct_horiz(linfo[level][2].data, linfo[level][3].data, - baseside[level], baseside[level], diff); - if (ctx->debug) - { - BLXdebug0("diff={"); - for (i = 0; i < baseside[level] * baseside[level]; i++) - BLXdebug1("%d, ", diff[i]); - BLXdebug0("}\n"); - } - if (level > overviewlevel) - reconstruct_vert(base, diff, baseside[level], 2 * baseside[level], - linfo[level - 1][0].data); - else - reconstruct_vert(base, diff, baseside[level], 2 * baseside[level], - outbuf); - } - - if (overviewlevel == 0) - { - if (len < 1) - { - BLXerror0("Cell corrupt"); - outbuf = NULL; - goto error; - } - a = *((char *)inptr++); - len--; - l_index = 0; - while (len >= 3) - { - step = inptr[0] | (inptr[1] << 8); - inptr += 2; - value = *((char *)inptr++); - len -= 3; - - l_index += step; - - if (value & 1) - value = (value - 1) / 2 - a; - else - value = value / 2 + a; - - if (l_index >= cellsize) - { - BLXerror0("Cell data corrupt\n"); - outbuf = NULL; - goto error; - } - - outbuf[l_index] = outbuf[l_index] + (blxdata)value; - } - - if (len != 0) - BLXdebug1("remaining len=%d", len); - } - else - { - if (len != 1) - BLXdebug1("remaining len=%d", len); - } - - /* Scale data */ - for (i = 0; i < cellsize; i++) - { - int val = outbuf[i] * (blxdata)ctx->zscale; - if (val < SHRT_MIN) - outbuf[i] = SHRT_MIN; - else if (val > SHRT_MAX) - outbuf[i] = SHRT_MAX; - else - outbuf[i] = (blxdata)val; - } - -error: - if (base != NULL) - BLXfree(base); - if (diff != NULL) - BLXfree(diff); - - /* Free allocated memory */ - for (level = 4; level >= 0; level--) - for (c = 0; c < 4; c++) - { - if (linfo[level][c].lut) - BLXfree(linfo[level][c].lut); - if (linfo[level][c].data) - BLXfree(linfo[level][c].data); - } - - return outbuf; -} - -blxcontext_t *blx_create_context() -{ - blxcontext_t *c; - - c = BLXmalloc(sizeof(blxcontext_t)); - - memset(c, 0, sizeof(blxcontext_t)); - - c->cell_ysize = c->cell_xsize = 128; - - c->minval = 32767; - c->maxval = -32768; - - c->debug = 0; - - c->zscale = 1; - - c->fillundef = 1; - c->fillundefval = 0; - - return c; -} - -void blx_free_context(blxcontext_t *ctx) -{ - if (ctx->cellindex) - BLXfree(ctx->cellindex); - - BLXfree(ctx); -} - -void blxprintinfo(blxcontext_t *ctx) -{ - BLXnotice2("Lat: %f Lon: %f\n", ctx->lat, ctx->lon); - BLXnotice2("Pixelsize: Lat: %f Lon: %f\n", 3600 * ctx->pixelsize_lat, - 3600 * ctx->pixelsize_lon); - BLXnotice2("Size %dx%d\n", ctx->xsize, ctx->ysize); - BLXnotice2("Cell size %dx%d\n", ctx->cell_xsize, ctx->cell_ysize); - BLXnotice2("Cell grid %dx%d\n", ctx->cell_cols, ctx->cell_rows); - BLXnotice1("Ysize scale factor: %d\n", ctx->zscale); - BLXnotice1("Max Ysize: %d\n", ctx->zscale * ctx->maxval); - BLXnotice1("Min Ysize: %d\n", ctx->zscale * ctx->minval); - BLXnotice1("Max chunksize: %d\n", ctx->maxchunksize); -} - -int blx_checkheader(const char *header) -{ - const short *signature = (const short *)header; - - return ((signature[0] == 0x4) && (signature[1] == 0x66)) || - ((signature[0] == 0x400) && (signature[1] == 0x6600)); -} - -static void blx_generate_header(blxcontext_t *ctx, unsigned char *header) -{ - unsigned char *hptr = header; - - memset(header, 0, 102); - - /* Write signature */ - put_short(ctx, 0x4, &hptr); // 0 - put_short(ctx, 0x66, &hptr); // 2 - - put_int32(ctx, ctx->cell_xsize * ctx->cell_cols, &hptr); // 4 - put_int32(ctx, ctx->cell_ysize * ctx->cell_rows, &hptr); // 8 - - put_short(ctx, (short)ctx->cell_xsize, &hptr); // 12 - put_short(ctx, (short)ctx->cell_ysize, &hptr); // 14 - - put_short(ctx, (short)ctx->cell_cols, &hptr); // 16 - put_short(ctx, (short)ctx->cell_rows, &hptr); // 18 - - put_double(ctx, ctx->lon, &hptr); // 20 - put_double(ctx, -ctx->lat, &hptr); // 28 - - put_double(ctx, ctx->pixelsize_lon, &hptr); // 36 - put_double(ctx, -ctx->pixelsize_lat, &hptr); // 44 - - put_short(ctx, (short)ctx->minval, &hptr); // 52 - put_short(ctx, (short)ctx->maxval, &hptr); // 54 - put_short(ctx, (short)ctx->zscale, &hptr); // 56 - put_int32(ctx, ctx->maxchunksize, &hptr); // 58 - // 62 -} - -int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol) -{ - unsigned char *uncompbuf = NULL, *outbuf = NULL; - int bufsize, uncompsize, compsize; - int status = 0; - int i, allundef; - - /* Calculate statistics and find out if all elements have undefined values - */ - allundef = 1; - for (i = 0; i < ctx->cell_xsize * ctx->cell_ysize; i++) - { - if (cell[i] > ctx->maxval) - ctx->maxval = cell[i]; - if (cell[i] < ctx->minval) - ctx->minval = cell[i]; - if (cell[i] != BLX_UNDEF) - allundef = 0; - } - - if (allundef) - return status; - - if (ctx->debug) - BLXdebug2("Writing cell (%d,%d)\n", cellrow, cellcol); - - if (!ctx->open) - { - status = -3; - goto error; - } - - if ((cellrow >= ctx->cell_rows) || (cellcol >= ctx->cell_cols)) - { - status = -2; - goto error; - } - - bufsize = sizeof(blxdata) * ctx->cell_xsize * ctx->cell_ysize + 1024; - uncompbuf = BLXmalloc(bufsize); - outbuf = BLXmalloc(bufsize); - - uncompsize = - blx_encode_celldata(ctx, cell, ctx->cell_xsize, uncompbuf, bufsize); - compsize = compress_chunk(uncompbuf, uncompsize, outbuf, bufsize); - if (compsize < 0) - { - BLXerror0("Couldn't compress chunk"); - status = -1; - goto error; - } - - if (uncompsize > ctx->maxchunksize) - ctx->maxchunksize = uncompsize; - - ctx->cellindex[cellrow * ctx->cell_cols + cellcol].offset = - (int)BLXftell(ctx->fh); - ctx->cellindex[cellrow * ctx->cell_cols + cellcol].datasize = uncompsize; - ctx->cellindex[cellrow * ctx->cell_cols + cellcol].compdatasize = compsize; - - if ((int)BLXfwrite(outbuf, 1, compsize, ctx->fh) != compsize) - { - status = -1; - goto error; - } - -error: - if (uncompbuf) - BLXfree(uncompbuf); - if (outbuf) - BLXfree(outbuf); - return status; -} - -int blxopen(blxcontext_t *ctx, const char *filename, const char *rw) -{ - unsigned char header[102]; - int signature[2] = {0}; - int i, j; - struct cellindex_s *ci; - - if (!strcmp(rw, "r") || !strcmp(rw, "rb")) - ctx->write = 0; - else if (!strcmp(rw, "w") || !strcmp(rw, "wb")) - ctx->write = 1; - else - goto error; - - ctx->fh = BLXfopen(filename, rw); - - if (ctx->fh == NULL) - goto error; - - if (ctx->write) - { - unsigned char *hptr = header; - blx_generate_header(ctx, header); - - if (BLXfwrite(header, 1, 102, ctx->fh) != 102) - goto error; - - ctx->cellindex = BLXmalloc(sizeof(struct cellindex_s) * ctx->cell_rows * - ctx->cell_cols); - if (ctx->cellindex == NULL) - { - goto error; - } - memset(ctx->cellindex, 0, - sizeof(struct cellindex_s) * ctx->cell_rows * ctx->cell_cols); - - /* Write the empty cell index (this will be overwritten when we have - * actual data)*/ - for (i = 0; i < ctx->cell_rows; i++) - for (j = 0; j < ctx->cell_cols; j++) - { - hptr = header; - put_cellindex_entry( - ctx, ctx->cellindex + i * ctx->cell_cols + j, &hptr); - if ((int)BLXfwrite(header, 1, hptr - header, ctx->fh) != - (int)(hptr - header)) - goto error; - } - } - else - { - const unsigned char *hptr = header; - - /* Read header */ - if (BLXfread(header, 1, 102, ctx->fh) != 102) - goto error; - - signature[0] = get_short_le(&hptr); - signature[1] = get_short_le(&hptr); - - /* Determine if the endianness of the BLX file */ - if ((signature[0] == 0x4) && (signature[1] == 0x66)) - ctx->endian = LITTLEENDIAN; - else - { - hptr = header; - signature[0] = get_short_be(&hptr); - signature[1] = get_short_be(&hptr); - if ((signature[0] == 0x4) && (signature[1] == 0x66)) - ctx->endian = BIGENDIAN; - else - goto error; - } - - ctx->xsize = get_int32(ctx, &hptr); - ctx->ysize = get_int32(ctx, &hptr); - if (ctx->xsize <= 0 || ctx->ysize <= 0) - { - BLXerror0("Invalid raster size"); - goto error; - } - - ctx->cell_xsize = get_short(ctx, &hptr); - ctx->cell_ysize = get_short(ctx, &hptr); - if (ctx->cell_xsize <= 0 || ctx->cell_ysize <= 0) - { - BLXerror0("Invalid cell size"); - goto error; - } - - ctx->cell_cols = get_short(ctx, &hptr); - ctx->cell_rows = get_short(ctx, &hptr); - if (ctx->cell_cols <= 0 || ctx->cell_cols > 10000 || - ctx->cell_rows <= 0 || ctx->cell_rows > 10000) - { - BLXerror0("Invalid cell number"); - goto error; - } - - ctx->lon = get_double(ctx, &hptr); - ctx->lat = -get_double(ctx, &hptr); - - ctx->pixelsize_lon = get_double(ctx, &hptr); - ctx->pixelsize_lat = -get_double(ctx, &hptr); - - ctx->minval = get_short(ctx, &hptr); - ctx->maxval = get_short(ctx, &hptr); - ctx->zscale = get_short(ctx, &hptr); - ctx->maxchunksize = get_int32(ctx, &hptr); - - ctx->cellindex = BLXmalloc(sizeof(struct cellindex_s) * ctx->cell_rows * - ctx->cell_cols); - if (ctx->cellindex == NULL) - { - goto error; - } - - for (i = 0; i < ctx->cell_rows; i++) - for (j = 0; j < ctx->cell_cols; j++) - { - /* Read cellindex entry */ - if (BLXfread(header, 1, 8, ctx->fh) != 8) - goto error; - hptr = header; - - ci = &ctx->cellindex[i * ctx->cell_cols + j]; - ci->offset = get_unsigned32(ctx, &hptr); - ci->datasize = get_unsigned_short(ctx, &hptr); - ci->compdatasize = get_unsigned_short(ctx, &hptr); - } - } - ctx->open = 1; - - return 0; - -error: - return -1; -} - -int blxclose(blxcontext_t *ctx) -{ - unsigned char header[102], *hptr; - int i, j, status = 0; - - if (ctx->write) - { - /* Write updated header and cellindex */ - if (BLXfseek(ctx->fh, 0, SEEK_SET) != 0) - { - status = -1; - goto error; - } - - blx_generate_header(ctx, header); - - if (BLXfwrite(header, 1, 102, ctx->fh) != 102) - { - status = -1; - goto error; - } - for (i = 0; i < ctx->cell_rows; i++) - for (j = 0; j < ctx->cell_cols; j++) - { - hptr = header; - put_cellindex_entry( - ctx, ctx->cellindex + i * ctx->cell_cols + j, &hptr); - if ((int)BLXfwrite(header, 1, hptr - header, ctx->fh) != - (int)(hptr - header)) - { - status = -1; - break; - } - } - } - ctx->open = 1; - -error: - if (ctx->fh) - BLXfclose(ctx->fh); - - return status; -} - -short *blx_readcell(blxcontext_t *ctx, int row, int col, short *buffer, - int bufsize, int overviewlevel) -{ - struct cellindex_s *ci; - unsigned char *chunk = NULL, *cchunk = NULL; - blxdata *tmpbuf = NULL; - int tmpbufsize, i; - short *result = NULL; - int npoints; - - if ((ctx == NULL) || (row >= ctx->cell_rows) || (col >= ctx->cell_cols)) - return NULL; - - ci = &ctx->cellindex[row * ctx->cell_cols + col]; - - npoints = (ctx->cell_xsize * ctx->cell_ysize) >> (2 * overviewlevel); - if (bufsize < npoints * (int)sizeof(short)) - return NULL; - - if (ci->datasize == 0) - { - for (i = 0; i < npoints; i++) - buffer[i] = BLX_UNDEF; - } - else - { - if (BLXfseek(ctx->fh, ci->offset, SEEK_SET) != 0) - goto error; - - chunk = BLXmalloc(ci->datasize); - cchunk = BLXmalloc(ci->compdatasize); - - if ((chunk == NULL) || (cchunk == NULL)) - goto error; - - if (BLXfread(cchunk, 1, ci->compdatasize, ctx->fh) != ci->compdatasize) - goto error; - - if ((unsigned int)uncompress_chunk(cchunk, ci->compdatasize, chunk, - ci->datasize) != ci->datasize) - goto error; - - tmpbufsize = sizeof(blxdata) * ctx->cell_xsize * ctx->cell_ysize; - tmpbuf = BLXmalloc(tmpbufsize); - if (tmpbuf == NULL) - goto error; - - if (decode_celldata(ctx, chunk, ci->datasize, NULL, tmpbuf, tmpbufsize, - overviewlevel) == NULL) - goto error; - - for (i = 0; i < npoints; i++) - buffer[i] = tmpbuf[i]; - } - - result = buffer; - -error: - if (chunk) - BLXfree(chunk); - if (cchunk) - BLXfree(cchunk); - if (tmpbuf) - BLXfree(tmpbuf); - - return result; -} diff --git a/frmts/blx/blx.h b/frmts/blx/blx.h deleted file mode 100644 index 0a0de2a8ded8..000000000000 --- a/frmts/blx/blx.h +++ /dev/null @@ -1,150 +0,0 @@ -/* libblx - Magellan BLX topo reader/writer library - * - * Copyright (c) 2008, Henrik Johansson - * - * SPDX-License-Identifier: MIT - */ - -#ifndef BLX_H_INCLUDED -#define BLX_H_INCLUDED - -#include - -#ifdef GDALDRIVER -#include "cpl_conv.h" -#include "cpl_vsi.h" -#endif - -/* Constants */ -#define BLX_UNDEF -32768 -#define BLX_OVERVIEWLEVELS 4 - -/* Possible values of ctx.endian */ -#define BIGENDIAN 1 -#define LITTLEENDIAN 0 - -/* Data types */ - -typedef short int blxdata; - -struct cellindex_s -{ - int offset; - unsigned int datasize; /* Uncompressed size */ - unsigned int compdatasize; /* Compressed data size */ -}; - -struct blxcontext_s -{ - int xsize, ysize; - int cell_xsize, cell_ysize; - int cell_cols, cell_rows; - double lon, lat; - double pixelsize_lon, pixelsize_lat; - - int zscale; - int maxchunksize; - int minval, maxval; - - int endian; - - struct cellindex_s *cellindex; - - int debug; - - int fillundef; /* If non-zero, fillundefval will be used instead of -32768 - for undefined values in non-empty cells when a cell is - written */ - int fillundefval; - -#ifdef GDALDRIVER - VSILFILE *fh; -#else - FILE *fh; -#endif - int write; - int open; -}; - -typedef struct blxcontext_s blxcontext_t; - -struct component_s -{ - int n; - blxdata *lut; - int dlen; - blxdata *data; -}; - -/* Included all functions in the global name space when testing */ -#ifdef TEST -#define STATIC -#else -#define STATIC static -#endif - -/* Define memory allocation and I/O function macros */ -#ifdef GDALDRIVER -#define BLXfopen VSIFOpenL -#define BLXfclose VSIFCloseL -#define BLXfread VSIFReadL -#define BLXfwrite VSIFWriteL -#define BLXfseek VSIFSeekL -#define BLXftell VSIFTellL -#define BLXmalloc VSIMalloc -#define BLXfree CPLFree -#define BLXdebug0(text) CPLDebug("BLX", text) -#define BLXdebug1(text, arg1) CPLDebug("BLX", text, arg1) -#define BLXdebug2(text, arg1, arg2) CPLDebug("BLX", text, arg1, arg2) -#define BLXerror0(text) CPLError(CE_Failure, CPLE_AppDefined, text) -#define BLXnotice1(text, arg1) CPLDebug("BLX", text, arg1) -#define BLXnotice2(text, arg1, arg2) CPLDebug("BLX", text, arg1, arg2) -#else -#define BLXfopen fopen -#define BLXfclose fclose -#define BLXfread fread -#define BLXfwrite fwrite -#define BLXfseek fseek -#define BLXftell ftell -#define BLXmalloc malloc -#define BLXfree free -#define BLXdebug0 printf -#define BLXdebug1 printf -#define BLXdebug2 printf -#define BLXerror0 printf -#define BLXnotice1 printf -#define BLXnotice2 printf -#endif - -/* Function prototypes */ -#ifdef TEST -STATIC int compress_chunk(unsigned char *inbuf, int inlen, - unsigned char *outbuf, int outbuflen); -STATIC int uncompress_chunk(unsigned char *inbuf, int inlen, - unsigned char *outbuf, int outbuflen); -STATIC blxdata *reconstruct_horiz(blxdata *base, blxdata *diff, unsigned rows, - unsigned cols, blxdata *out); -STATIC blxdata *reconstruct_vert(blxdata *base, blxdata *diff, unsigned rows, - unsigned cols, blxdata *out); -STATIC void decimate_horiz(blxdata *in, unsigned rows, unsigned cols, - blxdata *base, blxdata *diff); -STATIC void decimate_vert(blxdata *in, unsigned int rows, unsigned int cols, - blxdata *base, blxdata *diff); -STATIC blxdata *decode_celldata(blxcontext_t *blxcontext, unsigned char *inbuf, - int len, int *side, blxdata *outbuf, - int outbufsize, int overviewlevel); -#endif - -blxcontext_t *blx_create_context(void); -void blx_free_context(blxcontext_t *ctx); -int blxopen(blxcontext_t *ctx, const char *filename, const char *rw); -int blxclose(blxcontext_t *ctx); -void blxprintinfo(blxcontext_t *ctx); -short *blx_readcell(blxcontext_t *ctx, int row, int col, short *buffer, - int bufsize, int overviewlevel); -int blx_encode_celldata(blxcontext_t *ctx, blxdata *indata, int side, - unsigned char *outbuf, int outbufsize); -int blx_checkheader(const char *header); -int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol); - -#endif diff --git a/frmts/blx/blxdataset.cpp b/frmts/blx/blxdataset.cpp deleted file mode 100644 index 9342391baa28..000000000000 --- a/frmts/blx/blxdataset.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/****************************************************************************** - * - * Project: BLX Driver - * Purpose: GDAL BLX support. - * Author: Henrik Johansson, henrik@johome.net - * - ****************************************************************************** - * Copyright (c) 2006, Henrik Johansson - * Copyright (c) 2008-2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************** - * - */ - -#include "cpl_string.h" -#include "gdal_frmts.h" -#include "gdal_pam.h" - -CPL_C_START -#include "blx.h" -CPL_C_END - -class BLXDataset final : public GDALPamDataset -{ - friend class BLXRasterBand; - - CPLErr GetGeoTransform(double *padfTransform) override; - const OGRSpatialReference *GetSpatialRef() const override; - - OGRSpatialReference m_oSRS{}; - blxcontext_t *blxcontext = nullptr; - - bool bIsOverview = false; - std::vector> apoOverviewDS{}; - - public: - BLXDataset(); - ~BLXDataset(); - - static GDALDataset *Open(GDALOpenInfo *); -}; - -class BLXRasterBand final : public GDALPamRasterBand -{ - int overviewLevel; - - public: - BLXRasterBand(BLXDataset *, int, int overviewLevel = 0); - - double GetNoDataValue(int *pbSuccess = nullptr) override; - GDALColorInterp GetColorInterpretation(void) override; - int GetOverviewCount() override; - GDALRasterBand *GetOverview(int) override; - - CPLErr IReadBlock(int, int, void *) override; -}; - -GDALDataset *BLXDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - // -------------------------------------------------------------------- - // First that the header looks like a BLX header - // -------------------------------------------------------------------- - if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes < 102) - return nullptr; - - if (!blx_checkheader((const char *)poOpenInfo->pabyHeader)) - return nullptr; - - // -------------------------------------------------------------------- - // Create a corresponding GDALDataset. - // -------------------------------------------------------------------- - BLXDataset *poDS = new BLXDataset(); - - // -------------------------------------------------------------------- - // Open BLX file - // -------------------------------------------------------------------- - poDS->blxcontext = blx_create_context(); - if (poDS->blxcontext == nullptr) - { - delete poDS; - return nullptr; - } - if (blxopen(poDS->blxcontext, poOpenInfo->pszFilename, "rb") != 0) - { - delete poDS; - return nullptr; - } - - if ((poDS->blxcontext->cell_xsize % (1 << (1 + BLX_OVERVIEWLEVELS))) != 0 || - (poDS->blxcontext->cell_ysize % (1 << (1 + BLX_OVERVIEWLEVELS))) != 0) - { - delete poDS; - return nullptr; - } - - // Update dataset header from BLX context - poDS->nRasterXSize = poDS->blxcontext->xsize; - poDS->nRasterYSize = poDS->blxcontext->ysize; - - // -------------------------------------------------------------------- - // Create band information objects. - // -------------------------------------------------------------------- - poDS->nBands = 1; - poDS->SetBand(1, new BLXRasterBand(poDS, 1)); - - // Create overview bands - for (int i = 0; i < BLX_OVERVIEWLEVELS; i++) - { - poDS->apoOverviewDS.emplace_back(std::make_unique()); - poDS->apoOverviewDS[i]->blxcontext = poDS->blxcontext; - poDS->apoOverviewDS[i]->bIsOverview = true; - poDS->apoOverviewDS[i]->nRasterXSize = poDS->nRasterXSize >> (i + 1); - poDS->apoOverviewDS[i]->nRasterYSize = poDS->nRasterYSize >> (i + 1); - poDS->nBands = 1; - poDS->apoOverviewDS[i]->SetBand( - 1, new BLXRasterBand(poDS->apoOverviewDS[i].get(), 1, i + 1)); - } - - /* -------------------------------------------------------------------- */ - /* Confirm the requested access is supported. */ - /* -------------------------------------------------------------------- */ - if (poOpenInfo->eAccess == GA_Update) - { - delete poDS; - CPLError(CE_Failure, CPLE_NotSupported, - "The BLX driver does not support update access to existing" - " datasets.\n"); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - return poDS; -} - -BLXDataset::BLXDataset() -{ - m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - m_oSRS.importFromWkt(SRS_WKT_WGS84_LAT_LONG); -} - -BLXDataset::~BLXDataset() -{ - if (!bIsOverview) - { - if (blxcontext) - { - blxclose(blxcontext); - blx_free_context(blxcontext); - } - } -} - -CPLErr BLXDataset::GetGeoTransform(double *padfTransform) - -{ - padfTransform[0] = blxcontext->lon; - padfTransform[1] = blxcontext->pixelsize_lon; - padfTransform[2] = 0.0; - padfTransform[3] = blxcontext->lat; - padfTransform[4] = 0.0; - padfTransform[5] = blxcontext->pixelsize_lat; - - return CE_None; -} - -const OGRSpatialReference *BLXDataset::GetSpatialRef() const -{ - return &m_oSRS; -} - -BLXRasterBand::BLXRasterBand(BLXDataset *poDSIn, int nBandIn, - int overviewLevelIn) - : overviewLevel(overviewLevelIn) -{ - BLXDataset *poGDS = poDSIn; - - poDS = poDSIn; - nBand = nBandIn; - - eDataType = GDT_Int16; - - nBlockXSize = poGDS->blxcontext->cell_xsize >> overviewLevel; - nBlockYSize = poGDS->blxcontext->cell_ysize >> overviewLevel; -} - -int BLXRasterBand::GetOverviewCount() -{ - BLXDataset *poGDS = cpl::down_cast(poDS); - return static_cast(poGDS->apoOverviewDS.size()); -} - -GDALRasterBand *BLXRasterBand::GetOverview(int i) -{ - BLXDataset *poGDS = cpl::down_cast(poDS); - - if (i < 0 || static_cast(i) >= poGDS->apoOverviewDS.size()) - return nullptr; - - return poGDS->apoOverviewDS[i]->GetRasterBand(nBand); -} - -CPLErr BLXRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) - -{ - BLXDataset *poGDS = reinterpret_cast(poDS); - - if (blx_readcell(poGDS->blxcontext, nBlockYOff, nBlockXOff, (short *)pImage, - nBlockXSize * nBlockYSize * 2, overviewLevel) == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Failed to read BLX cell"); - return CE_Failure; - } - - return CE_None; -} - -double BLXRasterBand::GetNoDataValue(int *pbSuccess) -{ - if (pbSuccess) - *pbSuccess = TRUE; - return BLX_UNDEF; -} - -GDALColorInterp BLXRasterBand::GetColorInterpretation(void) -{ - return GCI_GrayIndex; -} - -/* TODO: check if georeference is the same as for BLX files, WGS84 - */ -static GDALDataset *BLXCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) - -{ - // -------------------------------------------------------------------- - // Some rudimentary checks - // -------------------------------------------------------------------- - const int nBands = poSrcDS->GetRasterCount(); - if (nBands != 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "BLX driver doesn't support %d bands. Must be 1 (grey) ", - nBands); - return nullptr; - } - - if (poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Int16 && bStrict) - { - CPLError(CE_Failure, CPLE_NotSupported, - "BLX driver doesn't support data type %s. " - "Only 16 bit byte bands supported.\n", - GDALGetDataTypeName( - poSrcDS->GetRasterBand(1)->GetRasterDataType())); - - return nullptr; - } - - const int nXSize = poSrcDS->GetRasterXSize(); - const int nYSize = poSrcDS->GetRasterYSize(); - if ((nXSize % 128 != 0) || (nYSize % 128 != 0)) - { - CPLError(CE_Failure, CPLE_NotSupported, - "BLX driver doesn't support dimensions that are not a " - "multiple of 128.\n"); - - return nullptr; - } - - // -------------------------------------------------------------------- - // What options has the user selected? - // -------------------------------------------------------------------- - int zscale = 1; - if (CSLFetchNameValue(papszOptions, "ZSCALE") != nullptr) - { - zscale = atoi(CSLFetchNameValue(papszOptions, "ZSCALE")); - if (zscale < 1) - { - CPLError(CE_Failure, CPLE_IllegalArg, - "ZSCALE=%s is not a legal value in the range >= 1.", - CSLFetchNameValue(papszOptions, "ZSCALE")); - return nullptr; - } - } - - int fillundef = 1; - if (CSLFetchNameValue(papszOptions, "FILLUNDEF") != nullptr && - EQUAL(CSLFetchNameValue(papszOptions, "FILLUNDEF"), "NO")) - fillundef = 0; - - int fillundefval = 0; - if (CSLFetchNameValue(papszOptions, "FILLUNDEFVAL") != nullptr) - { - fillundefval = atoi(CSLFetchNameValue(papszOptions, "FILLUNDEFVAL")); - if ((fillundefval < -32768) || (fillundefval > 32767)) - { - CPLError(CE_Failure, CPLE_IllegalArg, - "FILLUNDEFVAL=%s is not a legal value in the range " - "-32768, 32767.", - CSLFetchNameValue(papszOptions, "FILLUNDEFVAL")); - return nullptr; - } - } - - int endian = LITTLEENDIAN; - if (CSLFetchNameValue(papszOptions, "BIGENDIAN") != nullptr && - !EQUAL(CSLFetchNameValue(papszOptions, "BIGENDIAN"), "NO")) - endian = BIGENDIAN; - - // -------------------------------------------------------------------- - // Create the dataset. - // -------------------------------------------------------------------- - - // Create a BLX context - blxcontext_t *ctx = blx_create_context(); - - // Setup BLX parameters - ctx->cell_rows = nYSize / ctx->cell_ysize; - ctx->cell_cols = nXSize / ctx->cell_xsize; - ctx->zscale = zscale; - ctx->fillundef = fillundef; - ctx->fillundefval = fillundefval; - ctx->endian = endian; - - if (blxopen(ctx, pszFilename, "wb")) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create blx file %s.\n", - pszFilename); - blx_free_context(ctx); - return nullptr; - } - - // -------------------------------------------------------------------- - // Loop over image, copying image data. - // -------------------------------------------------------------------- - - GInt16 *pabyTile = (GInt16 *)VSI_MALLOC_VERBOSE( - sizeof(GInt16) * ctx->cell_xsize * ctx->cell_ysize); - if (pabyTile == nullptr) - { - blxclose(ctx); - blx_free_context(ctx); - return nullptr; - } - - CPLErr eErr = CE_None; - if (!pfnProgress(0.0, nullptr, pProgressData)) - eErr = CE_Failure; - - for (int i = 0; (i < ctx->cell_rows) && (eErr == CE_None); i++) - for (int j = 0; j < ctx->cell_cols; j++) - { - GDALRasterBand *poBand = poSrcDS->GetRasterBand(1); - eErr = poBand->RasterIO(GF_Read, j * ctx->cell_xsize, - i * ctx->cell_ysize, ctx->cell_xsize, - ctx->cell_ysize, pabyTile, ctx->cell_xsize, - ctx->cell_ysize, GDT_Int16, 0, 0, nullptr); - if (eErr >= CE_Failure) - break; - blxdata *celldata = pabyTile; - if (blx_writecell(ctx, celldata, i, j) != 0) - { - eErr = CE_Failure; - break; - } - - if (!pfnProgress(1.0 * (i * ctx->cell_cols + j) / - (ctx->cell_rows * ctx->cell_cols), - nullptr, pProgressData)) - { - eErr = CE_Failure; - break; - } - } - - pfnProgress(1.0, nullptr, pProgressData); - - CPLFree(pabyTile); - - double adfGeoTransform[6]; - if (poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None) - { - ctx->lon = adfGeoTransform[0]; - ctx->lat = adfGeoTransform[3]; - ctx->pixelsize_lon = adfGeoTransform[1]; - ctx->pixelsize_lat = adfGeoTransform[5]; - } - - blxclose(ctx); - blx_free_context(ctx); - - if (eErr == CE_None) - return GDALDataset::FromHandle(GDALOpen(pszFilename, GA_ReadOnly)); - - return nullptr; -} - -void GDALRegister_BLX() - -{ - if (GDALGetDriverByName("BLX") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("BLX"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Magellan topo (.blx)"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/blx.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "blx"); - - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = BLXDataset::Open; - poDriver->pfnCreateCopy = BLXCreateCopy; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/drivers.ini b/frmts/drivers.ini index fb64b007f928..cbd89b3c44af 100644 --- a/frmts/drivers.ini +++ b/frmts/drivers.ini @@ -26,13 +26,11 @@ SAR_CEOS CEOS JAXAPALSAR GFF -ELAS ESRIC AIG AAIGrid GRASSASCIIGrid ISG -SDTS DTED PNG DDS @@ -46,7 +44,6 @@ BIGGIF ESAT FITS BSB -XPM BMP DIMAP AirSAR @@ -55,7 +52,6 @@ SAFE PCIDSK PCRaster ILWIS -SGI SRTMHGT Leveller Terragen @@ -86,8 +82,6 @@ WMS MSGN MSG RST -GSAG -GSBG GS7BG COSAR TSX @@ -124,7 +118,6 @@ LCP GTX LOSLAS NTv2 -CTable2 ACE2 SNODAS KRO @@ -146,7 +139,6 @@ NWT_GRD NWT_GRC ADRG SRP -BLX GeoRaster PostGISRaster SAGA @@ -185,7 +177,6 @@ ESRI Shapefile MapInfo File UK .NTF LVBAG -OGR_SDTS S57 DGN OGR_VRT diff --git a/frmts/elas/CMakeLists.txt b/frmts/elas/CMakeLists.txt deleted file mode 100644 index 1de55e6d65ec..000000000000 --- a/frmts/elas/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_gdal_driver(TARGET gdal_ELAS SOURCES elasdataset.cpp PLUGIN_CAPABLE NO_DEPS) -gdal_standard_includes(gdal_ELAS) diff --git a/frmts/elas/elasdataset.cpp b/frmts/elas/elasdataset.cpp deleted file mode 100644 index b7b356aca140..000000000000 --- a/frmts/elas/elasdataset.cpp +++ /dev/null @@ -1,684 +0,0 @@ -/****************************************************************************** - * - * Project: ELAS Translator - * Purpose: Complete implementation of ELAS translator module for GDAL. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2008-2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "gdal_frmts.h" -#include "gdal_pam.h" - -#include -#include -#include - -using std::fill; - -typedef struct ELASHeader -{ - ELASHeader(); - - GInt32 NBIH; /* bytes in header, normally 1024 */ - GInt32 NBPR; /* bytes per data record (all bands of scanline) */ - GInt32 IL; /* initial line - normally 1 */ - GInt32 LL; /* last line */ - GInt32 IE; /* initial element (pixel), normally 1 */ - GInt32 LE; /* last element (pixel) */ - GInt32 NC; /* number of channels (bands) */ - GUInt32 H4321; /* header record identifier - always 4321. */ - char YLabel[4]; /* Should be "NOR" for UTM */ - GInt32 YOffset; /* topleft pixel center northing */ - char XLabel[4]; /* Should be "EAS" for UTM */ - GInt32 XOffset; /* topleft pixel center easting */ - float YPixSize; /* height of pixel in georef units */ - float XPixSize; /* width of pixel in georef units */ - float Matrix[4]; /* 2x2 transformation matrix. Should be - 1,0,0,1 for pixel/line, or - 1,0,0,-1 for UTM */ - GByte IH19[4]; /* data type, and size flags */ - GInt32 IH20; /* number of secondary headers */ - char unused1[8]; - GInt32 LABL; /* used by LABL module */ - char HEAD; /* used by HEAD module */ - char Comment1[64]; - char Comment2[64]; - char Comment3[64]; - char Comment4[64]; - char Comment5[64]; - char Comment6[64]; - GUInt16 ColorTable[256]; /* RGB packed with 4 bits each */ - char unused2[32]; -} _ELASHeader; - -ELASHeader::ELASHeader() - : NBIH(0), NBPR(0), IL(0), LL(0), IE(0), LE(0), NC(0), H4321(0), YOffset(0), - XOffset(0), YPixSize(0.0), XPixSize(0.0), IH20(0), LABL(0), HEAD(0) -{ - fill(YLabel, YLabel + CPL_ARRAYSIZE(YLabel), static_cast(0)); - fill(XLabel, XLabel + CPL_ARRAYSIZE(XLabel), static_cast(0)); - fill(Matrix, Matrix + CPL_ARRAYSIZE(Matrix), 0.f); - fill(IH19, IH19 + CPL_ARRAYSIZE(IH19), static_cast(0)); - fill(unused1, unused1 + CPL_ARRAYSIZE(unused1), static_cast(0)); - fill(Comment1, Comment1 + CPL_ARRAYSIZE(Comment1), static_cast(0)); - fill(Comment2, Comment2 + CPL_ARRAYSIZE(Comment2), static_cast(0)); - fill(Comment3, Comment3 + CPL_ARRAYSIZE(Comment3), static_cast(0)); - fill(Comment4, Comment4 + CPL_ARRAYSIZE(Comment4), static_cast(0)); - fill(Comment5, Comment5 + CPL_ARRAYSIZE(Comment5), static_cast(0)); - fill(Comment6, Comment6 + CPL_ARRAYSIZE(Comment6), static_cast(0)); - fill(ColorTable, ColorTable + CPL_ARRAYSIZE(ColorTable), - static_cast(0)); - fill(unused2, unused2 + CPL_ARRAYSIZE(unused2), static_cast(0)); -} - -/************************************************************************/ -/* ==================================================================== */ -/* ELASDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class ELASRasterBand; - -class ELASDataset final : public GDALPamDataset -{ - friend class ELASRasterBand; - - VSILFILE *fp; - - ELASHeader sHeader; - int bHeaderModified; - - GDALDataType eRasterDataType; - - int nLineOffset; - int nBandOffset; // Within a line. - - double adfGeoTransform[6]; - - public: - ELASDataset(); - ~ELASDataset() override; - - CPLErr GetGeoTransform(double *) override; - CPLErr SetGeoTransform(double *) override; - - static GDALDataset *Open(GDALOpenInfo *); - static int Identify(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszParamList); - - CPLErr FlushCache(bool bAtClosing) override; -}; - -/************************************************************************/ -/* ==================================================================== */ -/* ELASRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class ELASRasterBand final : public GDALPamRasterBand -{ - friend class ELASDataset; - - public: - ELASRasterBand(ELASDataset *, int); - - // should override RasterIO eventually. - - CPLErr IReadBlock(int, int, void *) override; - CPLErr IWriteBlock(int, int, void *) override; -}; - -/************************************************************************/ -/* ELASRasterBand() */ -/************************************************************************/ - -ELASRasterBand::ELASRasterBand(ELASDataset *poDSIn, int nBandIn) - -{ - poDS = poDSIn; - nBand = nBandIn; - - eAccess = poDSIn->eAccess; - - eDataType = poDSIn->eRasterDataType; - - nBlockXSize = poDS->GetRasterXSize(); - nBlockYSize = 1; -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr ELASRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff, - void *pImage) -{ - CPLAssert(nBlockXOff == 0); - - ELASDataset *poGDS = (ELASDataset *)poDS; - - int nDataSize = - GDALGetDataTypeSizeBytes(eDataType) * poGDS->GetRasterXSize(); - long nOffset = - poGDS->nLineOffset * nBlockYOff + 1024 + (nBand - 1) * nDataSize; - - /* -------------------------------------------------------------------- */ - /* If we can't seek to the data, we will assume this is a newly */ - /* created file, and that the file hasn't been extended yet. */ - /* Just read as zeros. */ - /* -------------------------------------------------------------------- */ - if (VSIFSeekL(poGDS->fp, nOffset, SEEK_SET) != 0 || - VSIFReadL(pImage, 1, nDataSize, poGDS->fp) != (size_t)nDataSize) - { - CPLError(CE_Failure, CPLE_FileIO, - "Seek or read of %d bytes at %ld failed.\n", nDataSize, - nOffset); - return CE_Failure; - } - - return CE_None; -} - -/************************************************************************/ -/* IWriteBlock() */ -/************************************************************************/ - -CPLErr ELASRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff, - void *pImage) -{ - CPLAssert(nBlockXOff == 0); - CPLAssert(eAccess == GA_Update); - - ELASDataset *poGDS = (ELASDataset *)poDS; - - int nDataSize = - GDALGetDataTypeSizeBytes(eDataType) * poGDS->GetRasterXSize(); - long nOffset = - poGDS->nLineOffset * nBlockYOff + 1024 + (nBand - 1) * nDataSize; - - if (VSIFSeekL(poGDS->fp, nOffset, SEEK_SET) != 0 || - VSIFWriteL(pImage, 1, nDataSize, poGDS->fp) != (size_t)nDataSize) - { - CPLError(CE_Failure, CPLE_FileIO, - "Seek or write of %d bytes at %ld failed.\n", nDataSize, - nOffset); - return CE_Failure; - } - - return CE_None; -} - -/************************************************************************/ -/* ==================================================================== */ -/* ELASDataset */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* ELASDataset() */ -/************************************************************************/ - -ELASDataset::ELASDataset() - : fp(nullptr), bHeaderModified(0), eRasterDataType(GDT_Unknown), - nLineOffset(0), nBandOffset(0) -{ - adfGeoTransform[0] = 0.0; - adfGeoTransform[1] = 1.0; - adfGeoTransform[2] = 0.0; - adfGeoTransform[3] = 0.0; - adfGeoTransform[4] = 0.0; - adfGeoTransform[5] = 1.0; -} - -/************************************************************************/ -/* ~ELASDataset() */ -/************************************************************************/ - -ELASDataset::~ELASDataset() - -{ - ELASDataset::FlushCache(true); - - if (fp != nullptr) - { - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - } -} - -/************************************************************************/ -/* FlushCache() */ -/* */ -/* We also write out the header, if it is modified. */ -/************************************************************************/ - -CPLErr ELASDataset::FlushCache(bool bAtClosing) - -{ - CPLErr eErr = GDALDataset::FlushCache(bAtClosing); - - if (bHeaderModified) - { - if (VSIFSeekL(fp, 0, SEEK_SET) != 0 || - VSIFWriteL(&sHeader, 1024, 1, fp) != 1) - { - eErr = CE_Failure; - } - bHeaderModified = FALSE; - } - return eErr; -} - -/************************************************************************/ -/* Identify() */ -/************************************************************************/ - -int ELASDataset::Identify(GDALOpenInfo *poOpenInfo) - -{ - /* -------------------------------------------------------------------- */ - /* First we check to see if the file has the expected header */ - /* bytes. */ - /* -------------------------------------------------------------------- */ - if (poOpenInfo->nHeaderBytes < 256) - return FALSE; - - if (CPL_MSBWORD32(*((GInt32 *)(poOpenInfo->pabyHeader + 0))) != 1024 || - CPL_MSBWORD32(*((GInt32 *)(poOpenInfo->pabyHeader + 28))) != 4321) - { - return FALSE; - } - - return TRUE; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *ELASDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Create a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - - ELASDataset *poDS = new ELASDataset(); - poDS->eAccess = poOpenInfo->eAccess; - poDS->fp = poOpenInfo->fpL; - poOpenInfo->fpL = nullptr; - - /* -------------------------------------------------------------------- */ - /* Read the header information. */ - /* -------------------------------------------------------------------- */ - poDS->bHeaderModified = FALSE; - if (VSIFReadL(&(poDS->sHeader), 1024, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Attempt to read 1024 byte header filed on file %s\n", - poOpenInfo->pszFilename); - delete poDS; - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Extract information of interest from the header. */ - /* -------------------------------------------------------------------- */ - poDS->nLineOffset = CPL_MSBWORD32(poDS->sHeader.NBPR); - - int nStart = CPL_MSBWORD32(poDS->sHeader.IL); - int nEnd = CPL_MSBWORD32(poDS->sHeader.LL); - GIntBig nDiff = static_cast(nEnd) - nStart + 1; - - if (nDiff <= 0 || nDiff > std::numeric_limits::max()) - { - delete poDS; - return nullptr; - } - poDS->nRasterYSize = static_cast(nDiff); - - nStart = CPL_MSBWORD32(poDS->sHeader.IE); - nEnd = CPL_MSBWORD32(poDS->sHeader.LE); - nDiff = static_cast(nEnd) - nStart + 1; - if (nDiff <= 0 || nDiff > std::numeric_limits::max()) - { - delete poDS; - return nullptr; - } - poDS->nRasterXSize = static_cast(nDiff); - - poDS->nBands = CPL_MSBWORD32(poDS->sHeader.NC); - - if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || - !GDALCheckBandCount(poDS->nBands, FALSE)) - { - delete poDS; - return nullptr; - } - - const int nELASDataType = (poDS->sHeader.IH19[2] & 0x7e) >> 2; - const int nBytesPerSample = poDS->sHeader.IH19[3]; - - if (nELASDataType == 0 && nBytesPerSample == 1) - poDS->eRasterDataType = GDT_Byte; - else if (nELASDataType == 1 && nBytesPerSample == 1) - poDS->eRasterDataType = GDT_Byte; - else if (nELASDataType == 16 && nBytesPerSample == 4) - poDS->eRasterDataType = GDT_Float32; - else if (nELASDataType == 17 && nBytesPerSample == 8) - poDS->eRasterDataType = GDT_Float64; - else - { - delete poDS; - CPLError(CE_Failure, CPLE_AppDefined, - "Unrecognized image data type %d, with BytesPerSample=%d.\n", - nELASDataType, nBytesPerSample); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Band offsets are always multiples of 256 within a multi-band */ - /* scanline of data. */ - /* -------------------------------------------------------------------- */ - if (GDALGetDataTypeSizeBytes(poDS->eRasterDataType) > - (std::numeric_limits::max() - 256) / poDS->nRasterXSize) - { - delete poDS; - return nullptr; - } - poDS->nBandOffset = - (poDS->nRasterXSize * GDALGetDataTypeSizeBytes(poDS->eRasterDataType)); - - if (poDS->nBandOffset > 1000000) - { - VSIFSeekL(poDS->fp, 0, SEEK_END); - if (VSIFTellL(poDS->fp) < static_cast(poDS->nBandOffset)) - { - CPLError(CE_Failure, CPLE_FileIO, "File too short"); - delete poDS; - return nullptr; - } - } - - if (poDS->nBandOffset % 256 != 0) - { - poDS->nBandOffset = poDS->nBandOffset - (poDS->nBandOffset % 256) + 256; - } - - /* -------------------------------------------------------------------- */ - /* Create band information objects. */ - /* -------------------------------------------------------------------- */ - /* coverity[tainted_data] */ - for (int iBand = 0; iBand < poDS->nBands; iBand++) - { - poDS->SetBand(iBand + 1, new ELASRasterBand(poDS, iBand + 1)); - } - - /* -------------------------------------------------------------------- */ - /* Extract the projection coordinates, if present. */ - /* -------------------------------------------------------------------- */ - if (poDS->sHeader.XOffset != 0) - { - CPL_MSBPTR32(&(poDS->sHeader.XPixSize)); - CPL_MSBPTR32(&(poDS->sHeader.YPixSize)); - - poDS->adfGeoTransform[0] = (GInt32)CPL_MSBWORD32(poDS->sHeader.XOffset); - poDS->adfGeoTransform[1] = poDS->sHeader.XPixSize; - poDS->adfGeoTransform[2] = 0.0; - poDS->adfGeoTransform[3] = (GInt32)CPL_MSBWORD32(poDS->sHeader.YOffset); - poDS->adfGeoTransform[4] = 0.0; - poDS->adfGeoTransform[5] = -1.0 * std::abs(poDS->sHeader.YPixSize); - - CPL_MSBPTR32(&(poDS->sHeader.XPixSize)); - CPL_MSBPTR32(&(poDS->sHeader.YPixSize)); - - poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5; - poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5; - } - else - { - poDS->adfGeoTransform[0] = 0.0; - poDS->adfGeoTransform[1] = 1.0; - poDS->adfGeoTransform[2] = 0.0; - poDS->adfGeoTransform[3] = 0.0; - poDS->adfGeoTransform[4] = 0.0; - poDS->adfGeoTransform[5] = 1.0; - } - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for external overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename, - poOpenInfo->GetSiblingFiles()); - - return poDS; -} - -/************************************************************************/ -/* Create() */ -/* */ -/* Create a new GeoTIFF or TIFF file. */ -/************************************************************************/ - -GDALDataset *ELASDataset::Create(const char *pszFilename, int nXSize, - int nYSize, int nBandsIn, GDALDataType eType, - char ** /* notdef: papszParamList */) - -{ - /* -------------------------------------------------------------------- */ - /* Verify input options. */ - /* -------------------------------------------------------------------- */ - if (nBandsIn <= 0) - { - CPLError(CE_Failure, CPLE_NotSupported, - "ELAS driver does not support %d bands.\n", nBandsIn); - return nullptr; - } - - if (eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_Float64) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create an ELAS dataset with an illegal\n" - "data type (%d).\n", - eType); - - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Try to create the file. */ - /* -------------------------------------------------------------------- */ - FILE *fp = VSIFOpen(pszFilename, "w"); - - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file `%s' failed.\n", pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* How long will each band of a scanline be? */ - /* -------------------------------------------------------------------- */ - int nBandOffset = nXSize * GDALGetDataTypeSizeBytes(eType); - - if (nBandOffset % 256 != 0) - { - nBandOffset = nBandOffset - (nBandOffset % 256) + 256; - } - - /* -------------------------------------------------------------------- */ - /* Setup header data block. */ - /* */ - /* Note that CPL_MSBWORD32() will swap little endian words to */ - /* big endian on little endian platforms. */ - /* -------------------------------------------------------------------- */ - ELASHeader sHeader; - - sHeader.NBIH = CPL_MSBWORD32(1024); - - sHeader.NBPR = CPL_MSBWORD32(nBandsIn * nBandOffset); - - sHeader.IL = CPL_MSBWORD32(1); - sHeader.LL = CPL_MSBWORD32(nYSize); - - sHeader.IE = CPL_MSBWORD32(1); - sHeader.LE = CPL_MSBWORD32(nXSize); - - sHeader.NC = CPL_MSBWORD32(nBandsIn); - - sHeader.H4321 = CPL_MSBWORD32(4321); - - sHeader.IH19[0] = 0x04; - sHeader.IH19[1] = 0xd2; - sHeader.IH19[3] = (GByte)(GDALGetDataTypeSizeBytes(eType)); - - if (eType == GDT_Byte) - sHeader.IH19[2] = 1 << 2; - else if (eType == GDT_Float32) - sHeader.IH19[2] = 16 << 2; - else if (eType == GDT_Float64) - sHeader.IH19[2] = 17 << 2; - - /* -------------------------------------------------------------------- */ - /* Write the header data. */ - /* -------------------------------------------------------------------- */ - CPL_IGNORE_RET_VAL(VSIFWrite(&sHeader, 1024, 1, fp)); - - /* -------------------------------------------------------------------- */ - /* Now write out zero data for all the imagery. This is */ - /* inefficient, but simplifies IReadBlock() / IWriteBlock() logic. */ - /* -------------------------------------------------------------------- */ - GByte *pabyLine = (GByte *)CPLCalloc(nBandOffset, nBandsIn); - for (int iLine = 0; iLine < nYSize; iLine++) - { - if (VSIFWrite(pabyLine, 1, nBandOffset, fp) != (size_t)nBandOffset) - { - CPLError(CE_Failure, CPLE_FileIO, - "Error writing ELAS image data ... likely insufficient" - " disk space.\n"); - VSIFClose(fp); - CPLFree(pabyLine); - return nullptr; - } - } - - CPLFree(pabyLine); - - VSIFClose(fp); - - /* -------------------------------------------------------------------- */ - /* Try to return a regular handle on the file. */ - /* -------------------------------------------------------------------- */ - return (GDALDataset *)GDALOpen(pszFilename, GA_Update); -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr ELASDataset::GetGeoTransform(double *padfTransform) - -{ - memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6); - - return CE_None; -} - -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr ELASDataset::SetGeoTransform(double *padfTransform) - -{ - /* -------------------------------------------------------------------- */ - /* I don't think it supports rotation, but perhaps it is possible */ - /* for us to use the 2x2 transform matrix to accomplish some */ - /* sort of rotation. */ - /* -------------------------------------------------------------------- */ - if (padfTransform[2] != 0.0 || padfTransform[4] != 0.0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to set rotated geotransform on ELAS file.\n" - "ELAS does not support rotation.\n"); - - return CE_Failure; - } - - /* -------------------------------------------------------------------- */ - /* Remember the new transform, and update the header. */ - /* -------------------------------------------------------------------- */ - memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6); - - bHeaderModified = TRUE; - - const int nXOff = (int)(adfGeoTransform[0] + adfGeoTransform[1] * 0.5); - const int nYOff = (int)(adfGeoTransform[3] + adfGeoTransform[5] * 0.5); - - sHeader.XOffset = CPL_MSBWORD32(nXOff); - sHeader.YOffset = CPL_MSBWORD32(nYOff); - - sHeader.XPixSize = static_cast(std::abs(adfGeoTransform[1])); - sHeader.YPixSize = static_cast(std::abs(adfGeoTransform[5])); - - CPL_MSBPTR32(&(sHeader.XPixSize)); - CPL_MSBPTR32(&(sHeader.YPixSize)); - - memcpy(sHeader.YLabel, "NOR ", 4); - memcpy(sHeader.XLabel, "EAS ", 4); - - sHeader.Matrix[0] = 1.0; - sHeader.Matrix[1] = 0.0; - sHeader.Matrix[2] = 0.0; - sHeader.Matrix[3] = -1.0; - - CPL_MSBPTR32(&(sHeader.Matrix[0])); - CPL_MSBPTR32(&(sHeader.Matrix[1])); - CPL_MSBPTR32(&(sHeader.Matrix[2])); - CPL_MSBPTR32(&(sHeader.Matrix[3])); - - return CE_None; -} - -/************************************************************************/ -/* GDALRegister_ELAS() */ -/************************************************************************/ - -void GDALRegister_ELAS() - -{ - if (GDALGetDriverByName("ELAS") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("ELAS"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ELAS"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte Float32 Float64"); - - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = ELASDataset::Open; - poDriver->pfnIdentify = ELASDataset::Identify; - poDriver->pfnCreate = ELASDataset::Create; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/fit/CMakeLists.txt b/frmts/fit/CMakeLists.txt deleted file mode 100644 index 0df5dad09b1a..000000000000 --- a/frmts/fit/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_gdal_driver( - TARGET gdal_FIT - SOURCES fit.cpp - fit.h - fitdataset.cpp - gstEndian.h - gstTypes.h - PLUGIN_CAPABLE - NO_DEPS) -gdal_standard_includes(gdal_FIT) diff --git a/frmts/fit/fit.cpp b/frmts/fit/fit.cpp deleted file mode 100644 index c9df027f2bc5..000000000000 --- a/frmts/fit/fit.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/****************************************************************************** - * - * Project: FIT Driver - * Purpose: Implement FIT Support - not using the SGI iflFIT library. - * Author: Philip Nemec, nemec@keyholecorp.com - * - ****************************************************************************** - * Copyright (c) 2001, Keyhole, Inc. - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include -#include "fit.h" - -GDALDataType fitDataType(int dtype) -{ - switch (dtype) - { - case 1: // iflBit /* single-bit */ - CPLError(CE_Failure, CPLE_NotSupported, - "GDAL unsupported data type (single-bit) in fitDataType"); - return GDT_Unknown; - case 2: // iflUChar /* unsigned character (byte) */ - return GDT_Byte; - case 4: // iflChar /* signed character (byte) */ - CPLError(CE_Failure, CPLE_NotSupported, - "GDAL unsupported data type (signed char) in fitDataType"); - return GDT_Unknown; - // return Byte; - case 8: // iflUShort /* unsigned short integer (nominally 16 bits) */ - return GDT_UInt16; - case 16: // iflShort /* signed short integer */ - return GDT_Int16; - case 32: // iflUInt /* unsigned integer (nominally 32 bits) */ - // case 32: // iflULong /* deprecated, same as iflUInt */ - return GDT_UInt32; - break; - case 64: // iflInt /* integer */ - // case 64: // iflLong /* deprecated, same as iflULong */ - return GDT_Int32; - case 128: // iflFloat /* floating point */ - return GDT_Float32; - case 256: // iflDouble /* double precision floating point */ - return GDT_Float64; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - unknown data type %i in fitDataType", dtype); - return GDT_Unknown; - } // switch -} - -int fitGetDataType(GDALDataType eDataType) -{ - switch (eDataType) - { - case GDT_Byte: - return 2; // iflUChar - unsigned character (byte) - case GDT_UInt16: - return 8; // iflUShort - unsigned short integer (nominally 16 bits) - case GDT_Int16: - return 16; // iflShort - signed short integer - case GDT_UInt32: - return 32; // iflUInt - unsigned integer (nominally 32 bits) - case GDT_Int32: - return 64; // iflInt - integer - case GDT_Float32: - return 128; // iflFloat - floating point - case GDT_Float64: - return 256; // iflDouble - double precision floating point - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - unsupported GDALDataType %i in fitGetDataType", - eDataType); - return 0; - } // switch -} - -#define UNSUPPORTED_COMBO() \ - CPLError(CE_Failure, CPLE_NotSupported, \ - "FIT write - unsupported combination (band 1 = %s " \ - "and %i bands) - ignoring color model", \ - GDALGetColorInterpretationName(colorInterp), nBands); \ - return 0 - -int fitGetColorModel(GDALColorInterp colorInterp, int nBands) -{ - // XXX - Should check colorInterp for all bands, not just first one. - - switch (colorInterp) - { - case GCI_GrayIndex: - switch (nBands) - { - case 1: - return 2; // iflLuminance - luminance - case 2: - return 13; // iflLuminanceAlpha - Luminance plus alpha - default: - UNSUPPORTED_COMBO(); - } // switch - - case GCI_PaletteIndex: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT write - unsupported ColorInterp PaletteIndex\n"); - return 0; - - case GCI_RedBand: - switch (nBands) - { - case 3: - return 3; // iflRGB - full color (Red, Green, Blue - // triplets) - case 4: - return 5; // iflRGBA - full color with transparency (alpha - // channel) - default: - UNSUPPORTED_COMBO(); - } // switch - - case GCI_BlueBand: - switch (nBands) - { - case 3: - return 9; // iflBGR - full color (ordered Blue, Green, Red) - default: - UNSUPPORTED_COMBO(); - } // switch - - case GCI_AlphaBand: - switch (nBands) - { - case 4: - return 10; // iflABGR - Alpha, Blue, Green, Red (SGI frame - // buffers) - default: - UNSUPPORTED_COMBO(); - } // switch - - case GCI_HueBand: - switch (nBands) - { - case 3: - return 6; // iflHSV - Hue, Saturation, Value - default: - UNSUPPORTED_COMBO(); - } // switch - - case GCI_CyanBand: - switch (nBands) - { - case 3: - return 7; // iflCMY - Cyan, Magenta, Yellow - case 4: - return 8; // iflCMYK - Cyan, Magenta, Yellow, Black - default: - UNSUPPORTED_COMBO(); - } // switch - - case GCI_GreenBand: - case GCI_SaturationBand: - case GCI_LightnessBand: - case GCI_MagentaBand: - case GCI_YellowBand: - case GCI_BlackBand: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT write - unsupported combination (band 1 = %s) " - "- ignoring color model", - GDALGetColorInterpretationName(colorInterp)); - return 0; - - default: - CPLDebug("FIT write", - "unrecognized colorInterp %i - deriving from " - "number of bands (%i)", - colorInterp, nBands); - switch (nBands) - { - case 1: - return 2; // iflLuminance - luminance - case 2: - return 13; // iflLuminanceAlpha - Luminance plus alpha - case 3: - return 3; // iflRGB - full color (Red, Green, Blue - // triplets) - case 4: - return 5; // iflRGBA - full color with transparency (alpha - // channel) - } // switch - - CPLError(CE_Failure, CPLE_NotSupported, - "FIT write - unrecognized colorInterp %i and " - "unrecognized number of bands (%i)", - colorInterp, nBands); - - return 0; - } // switch -} diff --git a/frmts/fit/fit.h b/frmts/fit/fit.h deleted file mode 100644 index db52fe18ef41..000000000000 --- a/frmts/fit/fit.h +++ /dev/null @@ -1,101 +0,0 @@ -/****************************************************************************** - * - * Project: FIT Driver - * Purpose: Implement FIT Support - not using the SGI iflFIT library. - * Author: Philip Nemec, nemec@keyholecorp.com - * - ****************************************************************************** - * Copyright (c) 2001, Keyhole, Inc. - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef FIT_H_ -#define FIT_H_ - -#include "gdal.h" - -struct FITinfo -{ - unsigned short magic; // file ident - unsigned short version; // file version - unsigned int xSize; // image size - unsigned int ySize; - unsigned int zSize; - unsigned int cSize; - int dtype; // data type - int order; // RGBRGB.. or RR..GG..BB.. - int space; // coordinate space - int cm; // color model - unsigned int xPageSize; // page size - unsigned int yPageSize; - unsigned int zPageSize; - unsigned int cPageSize; - // NOTE: a word of padding is inserted here - // due to struct alignment rules - double minValue; // min/max pixel values - double maxValue; - unsigned int dataOffset; // offset to first page of data - - // non-header values - unsigned int userOffset; // offset to area of user data -}; - -struct FIThead02 -{ // file header for version 02 - unsigned short magic; // file ident - unsigned short version; // file version - unsigned int xSize; // image size - unsigned int ySize; - unsigned int zSize; - unsigned int cSize; - int dtype; // data type - int order; // RGBRGB.. or RR..GG..BB.. - int space; // coordinate space - int cm; // color model - unsigned int xPageSize; // page size - unsigned int yPageSize; - unsigned int zPageSize; - unsigned int cPageSize; - short _padding; // NOTE: a word of padding is inserted here - // due to struct alignment rules - double minValue; // min/max pixel values - double maxValue; - unsigned int dataOffset; // offset to first page of data - // user extensible area... -}; - -struct FIThead01 -{ // file header for version 01 - unsigned short magic; // file ident - unsigned short version; // file version - unsigned int xSize; // image size - unsigned int ySize; - unsigned int zSize; - unsigned int cSize; - int dtype; // data type - int order; // RGBRGB.. or RR..GG..BB.. - int space; // coordinate space - int cm; // color model - unsigned int xPageSize; // page size - unsigned int yPageSize; - unsigned int zPageSize; - unsigned int cPageSize; - unsigned int dataOffset; // offset to first page of data - // user extensible area... -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - - GDALDataType fitDataType(int dtype); - int fitGetDataType(GDALDataType eDataType); - int fitGetColorModel(GDALColorInterp colorInterp, int nBands); - -#ifdef __cplusplus -} -#endif - -#endif // FIT_H_ diff --git a/frmts/fit/fitdataset.cpp b/frmts/fit/fitdataset.cpp deleted file mode 100644 index 66281d1467d1..000000000000 --- a/frmts/fit/fitdataset.cpp +++ /dev/null @@ -1,1359 +0,0 @@ -/****************************************************************************** - * - * Project: FIT Driver - * Purpose: Implement FIT Support - not using the SGI iflFIT library. - * Author: Philip Nemec, nemec@keyholecorp.com - * - ****************************************************************************** - * Copyright (c) 2001, Keyhole, Inc. - * Copyright (c) 2007-2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "fit.h" -#include "gdal_frmts.h" -#include "gdal_pam.h" -#include "gstEndian.h" -#include "cpl_safemaths.hpp" - -#include -#include - -constexpr size_t FIT_PAGE_SIZE = 128; - -using namespace gstEndian; - -/************************************************************************/ -/* ==================================================================== */ -/* FITDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class FITRasterBand; - -class FITDataset final : public GDALPamDataset -{ - friend class FITRasterBand; - - VSILFILE *fp; - FITinfo *info; - double adfGeoTransform[6]; - - public: - FITDataset(); - ~FITDataset(); - static GDALDataset *Open(GDALOpenInfo *); - // virtual CPLErr GetGeoTransform( double * ); -}; - -static GDALDataset *FITCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); - -/************************************************************************/ -/* ==================================================================== */ -/* FITRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class FITRasterBand final : public GDALPamRasterBand -{ - friend class FITDataset; - - unsigned long recordSize; // number of bytes of a single page/block/record - unsigned long numXBlocks; // number of pages in the X direction - unsigned long numYBlocks; // number of pages in the Y direction - unsigned long bytesPerComponent; - unsigned long bytesPerPixel; - char *tmpImage; - - public: - FITRasterBand(FITDataset *, int nBandIn, int nBandsIn); - ~FITRasterBand() override; - - // should override RasterIO eventually. - - CPLErr IReadBlock(int, int, void *) override; - // virtual CPLErr WriteBlock( int, int, void * ); - double GetMinimum(int *pbSuccess) override; - double GetMaximum(int *pbSuccess) override; - GDALColorInterp GetColorInterpretation() override; -}; - -/************************************************************************/ -/* FITRasterBand() */ -/************************************************************************/ - -FITRasterBand::FITRasterBand(FITDataset *poDSIn, int nBandIn, int nBandsIn) - : recordSize(0), numXBlocks(0), numYBlocks(0), bytesPerComponent(0), - bytesPerPixel(0), tmpImage(nullptr) -{ - poDS = poDSIn; - nBand = nBandIn; - - /* -------------------------------------------------------------------- */ - /* Get the GDAL data type. */ - /* -------------------------------------------------------------------- */ - eDataType = fitDataType(poDSIn->info->dtype); - - /* -------------------------------------------------------------------- */ - /* Get the page sizes. */ - /* -------------------------------------------------------------------- */ - nBlockXSize = poDSIn->info->xPageSize; - nBlockYSize = poDSIn->info->yPageSize; - - /* -------------------------------------------------------------------- */ - /* Calculate the values for record offset calculations. */ - /* -------------------------------------------------------------------- */ - bytesPerComponent = GDALGetDataTypeSizeBytes(eDataType); - if (bytesPerComponent == 0) - return; - bytesPerPixel = nBandsIn * bytesPerComponent; - const auto knIntMax = std::numeric_limits::max(); - if (nBlockXSize <= 0 || nBlockYSize <= 0 || - nBlockXSize > knIntMax / static_cast(bytesPerPixel) || - nBlockYSize > - knIntMax / (nBlockXSize * static_cast(bytesPerPixel))) - return; - recordSize = bytesPerPixel * nBlockXSize * nBlockYSize; - numXBlocks = (unsigned long)ceil((double)poDSIn->info->xSize / nBlockXSize); - numYBlocks = (unsigned long)ceil((double)poDSIn->info->ySize / nBlockYSize); - - tmpImage = (char *)VSI_MALLOC_VERBOSE(recordSize); - /* -------------------------------------------------------------------- */ - /* Set the access flag. For now we set it the same as the */ - /* whole dataset, but eventually this should take account of */ - /* locked channels, or read-only secondary data files. */ - /* -------------------------------------------------------------------- */ - /* ... */ -} - -FITRasterBand::~FITRasterBand() -{ - VSIFree(tmpImage); -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -#define COPY_XFIRST(t) \ - { \ - t *dstp = (t *)pImage; \ - t *srcp = (t *)tmpImage; \ - srcp += nBand - 1; \ - long imacro = 0; \ - for (long y = ystart; y != ystop; y += yinc) \ - for (long x = xstart; x != xstop; x += xinc, imacro++) \ - { \ - dstp[imacro] = srcp[(y * nBlockXSize + x) * poFIT_DS->nBands]; \ - } \ - } - -#define COPY_YFIRST(t) \ - { \ - t *dstp = (t *)pImage; \ - t *srcp = (t *)tmpImage; \ - srcp += nBand - 1; \ - long imacro = 0; \ - for (long x = xstart; x != xstop; x += xinc, imacro++) \ - for (long y = ystart; y != ystop; y += yinc) \ - { \ - dstp[imacro] = srcp[(x * nBlockYSize + y) * poFIT_DS->nBands]; \ - } \ - } - -CPLErr FITRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) - -{ - FITDataset *poFIT_DS = (FITDataset *)poDS; - - uint64 tilenum = 0; - - switch (poFIT_DS->info->space) - { - case 1: - // iflUpperLeftOrigin - from upper left corner - // scan right then down - tilenum = nBlockYOff * numXBlocks + nBlockXOff; - break; - case 2: - // iflUpperRightOrigin - from upper right corner - // scan left then down - tilenum = numYBlocks * numXBlocks + (numXBlocks - 1 - nBlockXOff); - break; - case 3: - // iflLowerRightOrigin - from lower right corner - // scan left then up - tilenum = (numYBlocks - 1 - nBlockYOff) * numXBlocks + - (numXBlocks - 1 - nBlockXOff); - break; - case 4: - // iflLowerLeftOrigin - from lower left corner - // scan right then up - tilenum = (numYBlocks - 1 - nBlockYOff) * numXBlocks + nBlockXOff; - break; - case 5: - // iflLeftUpperOrigin -* from upper left corner - // scan down then right - tilenum = nBlockXOff * numYBlocks + nBlockYOff; - break; - case 6: - // iflRightUpperOrigin - from upper right corner - // scan down then left - tilenum = (numXBlocks - 1 - nBlockXOff) * numYBlocks + nBlockYOff; - break; - case 7: - // iflRightLowerOrigin - from lower right corner - // scan up then left - tilenum = nBlockXOff * numYBlocks + (numYBlocks - 1 - nBlockYOff); - break; - case 8: - // iflLeftLowerOrigin -* from lower left corner - // scan up then right - tilenum = (numXBlocks - 1 - nBlockXOff) * numYBlocks + - (numYBlocks - 1 - nBlockYOff); - break; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - unrecognized image space %i", - poFIT_DS->info->space); - return CE_Failure; - } // switch - - uint64 offset = poFIT_DS->info->dataOffset + recordSize * tilenum; - // CPLDebug("FIT", "%i RasterBand::IReadBlock %i %i (out of %i %i) -- - // %i", - // poFIT_DS->info->space, - // nBlockXOff, nBlockYOff, numXBlocks, numYBlocks, tilenum); - - if (VSIFSeekL(poFIT_DS->fp, offset, SEEK_SET) == -1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - 64bit file seek failure, handle=%p", poFIT_DS->fp); - return CE_Failure; - } - - // XXX - should handle status - // fast path is single component (ll?) - no copy needed - int fastpath = FALSE; - - if ((poFIT_DS->nBands == 1) && (poFIT_DS->info->space == 1)) // upper left - fastpath = TRUE; - - size_t nRead = 0; - char *p = nullptr; - if (!fastpath) - { - nRead = VSIFReadL(tmpImage, recordSize, 1, poFIT_DS->fp); - // offset to correct component to swap - p = (char *)tmpImage + nBand - 1; - } - else - { - nRead = VSIFReadL(pImage, recordSize, 1, poFIT_DS->fp); - p = (char *)pImage; - } - if (nRead != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Cannot read record"); - return CE_Failure; - } - -#ifdef swapping - unsigned long i = 0; - - switch (bytesPerComponent) - { - case 1: - // do nothing - break; - case 2: - for (i = 0; i < recordSize; i += bytesPerPixel) - gst_swap16(p + i); - break; - case 4: - for (i = 0; i < recordSize; i += bytesPerPixel) - gst_swap32(p + i); - break; - case 8: - for (i = 0; i < recordSize; i += bytesPerPixel) - gst_swap64(p + i); - break; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FITRasterBand::IReadBlock unsupported bytesPerPixel %lu", - bytesPerComponent); - } // switch -#else - (void)p; // avoid warnings. -#endif // swapping - - if (!fastpath) - { - long xinc, yinc, xstart, ystart, xstop, ystop; - if (poFIT_DS->info->space <= 4) - { - // scan left/right first - - switch (poFIT_DS->info->space) - { - case 1: - // iflUpperLeftOrigin - from upper left corner - // scan right then down - xinc = 1; - yinc = 1; - break; - case 2: - // iflUpperRightOrigin - from upper right corner - // scan left then down - xinc = -1; - yinc = 1; - break; - case 3: - // iflLowerRightOrigin - from lower right corner - // scan left then up - xinc = -1; - yinc = -1; - break; - case 4: - // iflLowerLeftOrigin - from lower left corner - // scan right then up - xinc = 1; - yinc = -1; - break; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - unrecognized image space %i", - poFIT_DS->info->space); - xinc = 1; - yinc = 1; - } // switch - - if (xinc == 1) - { - xstart = 0; - xstop = nBlockXSize; - } - else - { - xstart = nBlockXSize - 1; - xstop = -1; - } - if (yinc == 1) - { - ystart = 0; - ystop = nBlockYSize; - } - else - { - int localBlockYSize = nBlockYSize; - long maxy_full = - (long)floor(poFIT_DS->info->ySize / (double)nBlockYSize); - if (nBlockYOff >= maxy_full) - localBlockYSize = poFIT_DS->info->ySize % nBlockYSize; - ystart = localBlockYSize - 1; - ystop = -1; - } - - switch (bytesPerComponent) - { - case 1: - COPY_XFIRST(char); - break; - case 2: - COPY_XFIRST(uint16); - break; - case 4: - COPY_XFIRST(uint32); - break; - case 8: - COPY_XFIRST(uint64); - break; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FITRasterBand::IReadBlock unsupported " - "bytesPerComponent %lu", - bytesPerComponent); - } // switch - } // Scan left/right first. - else - { - // Scan up/down first. - switch (poFIT_DS->info->space) - { - case 5: - // iflLeftUpperOrigin -* from upper left corner - // scan down then right - xinc = 1; - yinc = 1; - break; - case 6: - // iflRightUpperOrigin - from upper right corner - // scan down then left - xinc = -1; - yinc = 1; - break; - case 7: - // iflRightLowerOrigin - from lower right corner - // scan up then left - xinc = -1; - yinc = -1; - break; - case 8: - // iflLeftLowerOrigin -* from lower left corner - // scan up then right - xinc = 1; - yinc = -1; - break; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - unrecognized image space %i", - poFIT_DS->info->space); - xinc = 1; - yinc = 1; - } // switch - - if (xinc == 1) - { - xstart = 0; - xstop = nBlockXSize; - } - else - { - int localBlockXSize = nBlockXSize; - long maxx_full = - (long)floor(poFIT_DS->info->xSize / (double)nBlockXSize); - if (nBlockXOff >= maxx_full) - localBlockXSize = poFIT_DS->info->xSize % nBlockXSize; - xstart = localBlockXSize - 1; - xstop = -1; - } - if (yinc == 1) - { - ystart = 0; - ystop = nBlockYSize; - } - else - { - ystart = nBlockYSize - 1; - ystop = -1; - } - - switch (bytesPerComponent) - { - case 1: - COPY_YFIRST(char); - break; - case 2: - COPY_YFIRST(uint16); - break; - case 4: - COPY_YFIRST(uint32); - break; - case 8: - COPY_YFIRST(uint64); - break; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FITRasterBand::IReadBlock unsupported " - "bytesPerComponent %lu", - bytesPerComponent); - } // switch - } // Scan up/down first. - } // !fastpath - return CE_None; -} - -#if 0 -/************************************************************************/ -/* ReadBlock() */ -/************************************************************************/ - -CPLErr FITRasterBand::ReadBlock( int nBlockXOff, int nBlockYOff, - void * pImage ) - -{ - FITDataset *poFIT_DS = (FITDataset *) poDS; - - return CE_None; -} - -/************************************************************************/ -/* WriteBlock() */ -/************************************************************************/ - -CPLErr FITRasterBand::WriteBlock( int nBlockXOff, int nBlockYOff, - void * pImage ) - -{ - FITDataset *poFIT_DS = (FITDataset *) poDS; - - return CE_None; -} -#endif - -/************************************************************************/ -/* GetMinimum() */ -/************************************************************************/ - -double FITRasterBand::GetMinimum(int *pbSuccess) -{ - FITDataset *poFIT_DS = (FITDataset *)poDS; - - if ((!poFIT_DS) || (!poFIT_DS->info)) - return GDALRasterBand::GetMinimum(pbSuccess); - - if (pbSuccess) - *pbSuccess = TRUE; - - if (poFIT_DS->info->version && - STARTS_WITH_CI((const char *)&(poFIT_DS->info->version), "02")) - { - return poFIT_DS->info->minValue; - } - - return GDALRasterBand::GetMinimum(pbSuccess); -} - -/************************************************************************/ -/* GetMaximum() */ -/************************************************************************/ - -double FITRasterBand::GetMaximum(int *pbSuccess) -{ - FITDataset *poFIT_DS = (FITDataset *)poDS; - - if ((!poFIT_DS) || (!poFIT_DS->info)) - return GDALRasterBand::GetMaximum(pbSuccess); - - if (pbSuccess) - *pbSuccess = TRUE; - - if (STARTS_WITH_CI((const char *)&poFIT_DS->info->version, "02")) - { - return poFIT_DS->info->maxValue; - } - - return GDALRasterBand::GetMaximum(pbSuccess); -} - -/************************************************************************/ -/* GetColorInterpretation() */ -/************************************************************************/ - -GDALColorInterp FITRasterBand::GetColorInterpretation() -{ - FITDataset *poFIT_DS = (FITDataset *)poDS; - - if ((!poFIT_DS) || (!poFIT_DS->info)) - return GCI_Undefined; - - switch (poFIT_DS->info->cm) - { - case 1: // iflNegative - inverted luminance (min value is white) - CPLError( - CE_Warning, CPLE_NotSupported, - "FIT - color model Negative not supported - ignoring model"); - return GCI_Undefined; - - case 2: // iflLuminance - luminance - if (poFIT_DS->nBands != 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model Luminance mismatch with %i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_GrayIndex; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model Luminance unknown band %i", - nBand); - return GCI_Undefined; - } // switch nBand - - case 3: // iflRGB - full color (Red, Green, Blue triplets) - if (poFIT_DS->nBands != 3) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model RGB mismatch with %i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_RedBand; - case 2: - return GCI_GreenBand; - case 3: - return GCI_BlueBand; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model RGB unknown band %i", nBand); - return GCI_Undefined; - } // switch nBand - - case 4: // iflRGBPalette - color mapped values - CPLError(CE_Warning, CPLE_NotSupported, - "FIT - color model RGBPalette not supported - " - "ignoring model"); - return GCI_Undefined; - - case 5: // iflRGBA - full color with transparency (alpha channel) - if (poFIT_DS->nBands != 4) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model RGBA mismatch with %i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_RedBand; - case 2: - return GCI_GreenBand; - case 3: - return GCI_BlueBand; - case 4: - return GCI_AlphaBand; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model RGBA unknown band %i", nBand); - return GCI_Undefined; - } // switch nBand - - case 6: // iflHSV - Hue, Saturation, Value - if (poFIT_DS->nBands != 3) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model HSV mismatch with %i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_HueBand; - case 2: - return GCI_SaturationBand; - case 3: - return GCI_LightnessBand; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model HSV unknown band %i", nBand); - return GCI_Undefined; - } // switch nBand - - case 7: // iflCMY - Cyan, Magenta, Yellow - if (poFIT_DS->nBands != 3) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model CMY mismatch with %i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_CyanBand; - case 2: - return GCI_MagentaBand; - case 3: - return GCI_YellowBand; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model CMY unknown band %i", nBand); - return GCI_Undefined; - } // switch nBand - - case 8: // iflCMYK - Cyan, Magenta, Yellow, Black - if (poFIT_DS->nBands != 4) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model CMYK mismatch with %i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_CyanBand; - case 2: - return GCI_MagentaBand; - case 3: - return GCI_YellowBand; - case 4: - return GCI_BlackBand; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model CMYK unknown band %i", nBand); - return GCI_Undefined; - } // switch nBand - - case 9: // iflBGR - full color (ordered Blue, Green, Red) - if (poFIT_DS->nBands != 3) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model BGR mismatch with %i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_BlueBand; - case 2: - return GCI_GreenBand; - case 3: - return GCI_RedBand; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model BGR unknown band %i", nBand); - return GCI_Undefined; - } // switch nBand - - case 10: // iflABGR - Alpha, Blue, Green, Red (SGI frame buffers) - if (poFIT_DS->nBands != 4) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model ABGR mismatch with %i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_AlphaBand; - case 2: - return GCI_BlueBand; - case 3: - return GCI_GreenBand; - case 4: - return GCI_RedBand; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model ABGR unknown band %i", nBand); - return GCI_Undefined; - } // switch nBand - - case 11: // iflMultiSpectral - multi-spectral data, arbitrary number of - // chans - return GCI_Undefined; - - case 12: // iflYCC PhotoCD color model (Luminance, Chrominance) - CPLError(CE_Warning, CPLE_NotSupported, - "FIT - color model YCC not supported - ignoring model"); - return GCI_Undefined; - - case 13: // iflLuminanceAlpha - Luminance plus alpha - if (poFIT_DS->nBands != 2) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model LuminanceAlpha mismatch with " - "%i bands", - poFIT_DS->nBands); - return GCI_Undefined; - } - switch (nBand) - { - case 1: - return GCI_GrayIndex; - case 2: - return GCI_AlphaBand; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - color model LuminanceAlpha unknown band %i", - nBand); - return GCI_Undefined; - } // switch nBand - - default: - CPLError(CE_Warning, CPLE_NotSupported, - "FIT - unrecognized color model %i - ignoring model", - poFIT_DS->info->cm); - return GCI_Undefined; - } // switch -} - -/************************************************************************/ -/* FITDataset() */ -/************************************************************************/ - -FITDataset::FITDataset() : fp(nullptr), info(nullptr) -{ - adfGeoTransform[0] = 0.0; // x origin (top left corner) - adfGeoTransform[1] = 1.0; // x pixel size - adfGeoTransform[2] = 0.0; - adfGeoTransform[3] = 0.0; // y origin (top left corner) - adfGeoTransform[4] = 0.0; - adfGeoTransform[5] = 1.0; // y pixel size -} - -/************************************************************************/ -/* ~FITDataset() */ -/************************************************************************/ - -FITDataset::~FITDataset() -{ - FlushCache(true); - if (info) - delete (info); - if (fp) - { - if (VSIFCloseL(fp) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, "I/O error"); - } - } -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *FITDataset::Open(GDALOpenInfo *poOpenInfo) -{ - /* -------------------------------------------------------------------- */ - /* First we check to see if the file has the expected header */ - /* bytes. */ - /* -------------------------------------------------------------------- */ - - if (poOpenInfo->nHeaderBytes < 5 || poOpenInfo->fpL == nullptr) - return nullptr; - - if (!STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "IT01") && - !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "IT02")) - return nullptr; - - if (poOpenInfo->eAccess == GA_Update) - { - CPLError(CE_Failure, CPLE_NotSupported, - "The FIT driver does not support update access to existing" - " files.\n"); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - auto poDS = std::make_unique(); - poDS->eAccess = poOpenInfo->eAccess; - poDS->fp = poOpenInfo->fpL; - poOpenInfo->fpL = nullptr; - - poDS->info = new FITinfo; - FITinfo *info = poDS->info; - - /* -------------------------------------------------------------------- */ - /* Read other header values. */ - /* -------------------------------------------------------------------- */ - FIThead02 *head = (FIThead02 *)poOpenInfo->pabyHeader; - - // extract the image attributes from the file header - if (STARTS_WITH_CI((const char *)&head->version, "02")) - { - // incomplete header - if (poOpenInfo->nHeaderBytes < (signed)sizeof(FIThead02)) - return nullptr; - - CPLDebug("FIT", "Loading file with header version 02"); - - gst_swapb(head->minValue); - info->minValue = head->minValue; - gst_swapb(head->maxValue); - info->maxValue = head->maxValue; - gst_swapb(head->dataOffset); - info->dataOffset = head->dataOffset; - - info->userOffset = sizeof(FIThead02); - } - else if (STARTS_WITH_CI((const char *)&head->version, "01")) - { - // incomplete header - if (poOpenInfo->nHeaderBytes < (signed)sizeof(FIThead01)) - return nullptr; - - CPLDebug("FIT", "Loading file with header version 01"); - - // map old style header into new header structure - FIThead01 *head01 = (FIThead01 *)head; - gst_swapb(head->dataOffset); - info->dataOffset = head01->dataOffset; - - info->userOffset = sizeof(FIThead01); - } - else - { - // unrecognized header version - CPLError(CE_Failure, CPLE_NotSupported, - "FIT - unsupported header version %.2s\n", - (const char *)&head->version); - return nullptr; - } - - CPLDebug("FIT", "userOffset %i, dataOffset %i", info->userOffset, - info->dataOffset); - - info->magic = head->magic; - info->version = head->version; - - gst_swapb(head->xSize); - info->xSize = head->xSize; - gst_swapb(head->ySize); - info->ySize = head->ySize; - gst_swapb(head->zSize); - info->zSize = head->zSize; - gst_swapb(head->cSize); - info->cSize = head->cSize; - gst_swapb(head->dtype); - info->dtype = head->dtype; - gst_swapb(head->order); - info->order = head->order; - gst_swapb(head->space); - info->space = head->space; - gst_swapb(head->cm); - info->cm = head->cm; - gst_swapb(head->xPageSize); - info->xPageSize = head->xPageSize; - gst_swapb(head->yPageSize); - info->yPageSize = head->yPageSize; - gst_swapb(head->zPageSize); - info->zPageSize = head->zPageSize; - gst_swapb(head->cPageSize); - info->cPageSize = head->cPageSize; - - CPLDebug("FIT", "size %i %i %i %i, pageSize %i %i %i %i", info->xSize, - info->ySize, info->zSize, info->cSize, info->xPageSize, - info->yPageSize, info->zPageSize, info->cPageSize); - - CPLDebug("FIT", "dtype %i order %i space %i cm %i", info->dtype, - info->order, info->space, info->cm); - - /**************************/ - - poDS->nRasterXSize = head->xSize; - poDS->nRasterYSize = head->ySize; - - if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || - !GDALCheckBandCount(head->cSize, FALSE) || head->xPageSize == 0 || - head->yPageSize == 0) - { - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Verify all "unused" header values. */ - /* -------------------------------------------------------------------- */ - - if (info->zSize != 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT driver - unsupported zSize %i\n", info->zSize); - return nullptr; - } - - if (info->order != 1) // interleaved - RGBRGB - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT driver - unsupported order %i\n", info->order); - return nullptr; - } - - if (info->zPageSize != 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT driver - unsupported zPageSize %i\n", info->zPageSize); - return nullptr; - } - - if (info->cPageSize != info->cSize) - { - CPLError(CE_Failure, CPLE_NotSupported, - "FIT driver - unsupported cPageSize %i (!= %i)\n", - info->cPageSize, info->cSize); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create band information objects. */ - /* -------------------------------------------------------------------- */ - // Verified by above GDALCheckBandCount() - // coverity[tainted_data] - for (int i = 0; i < (int)head->cSize; i++) - { - FITRasterBand *poBand = - new FITRasterBand(poDS.get(), i + 1, (int)head->cSize); - poDS->SetBand(i + 1, poBand); - if (poBand->tmpImage == nullptr) - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for external overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename, - poOpenInfo->GetSiblingFiles()); - - return poDS.release(); -} - -/************************************************************************/ -/* FITCreateCopy() */ -/************************************************************************/ - -static GDALDataset *FITCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - CPLDebug("FIT", "CreateCopy %s - %i", pszFilename, bStrict); - - int nBands = poSrcDS->GetRasterCount(); - if (nBands == 0) - { - CPLError( - CE_Failure, CPLE_NotSupported, - "FIT driver does not support source dataset with zero band.\n"); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create the dataset. */ - /* -------------------------------------------------------------------- */ - if (!pfnProgress(0.0, nullptr, pProgressData)) - { - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated"); - return nullptr; - } - - VSILFILE *fpImage = VSIFOpenL(pszFilename, "wb"); - if (fpImage == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "FIT - unable to create file %s.\n", pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Generate header. */ - /* -------------------------------------------------------------------- */ - // XXX - should FIT_PAGE_SIZE be based on file page size ?? - - const size_t size = std::max(sizeof(FIThead02), FIT_PAGE_SIZE); - std::vector abyHeader; - abyHeader.resize(size); - FIThead02 *head = reinterpret_cast(abyHeader.data()); - - // clean header so padding (past real header) is all zeros - memset(head, 0, size); - - memcpy((char *)&head->magic, "IT", 2); - memcpy((char *)&head->version, "02", 2); - - head->xSize = poSrcDS->GetRasterXSize(); - gst_swapb(head->xSize); - head->ySize = poSrcDS->GetRasterYSize(); - gst_swapb(head->ySize); - head->zSize = 1; - gst_swapb(head->zSize); - - head->cSize = nBands; - gst_swapb(head->cSize); - - GDALRasterBand *firstBand = poSrcDS->GetRasterBand(1); - if (!firstBand) - { - CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); - return nullptr; - } - - head->dtype = fitGetDataType(firstBand->GetRasterDataType()); - if (!head->dtype) - { - CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); - return nullptr; - } - gst_swapb(head->dtype); - head->order = 1; // interleaved - RGBRGB - gst_swapb(head->order); - head->space = 1; // upper left - gst_swapb(head->space); - - // XXX - need to check all bands - head->cm = fitGetColorModel(firstBand->GetColorInterpretation(), nBands); - gst_swapb(head->cm); - - int blockX, blockY; - firstBand->GetBlockSize(&blockX, &blockY); - blockX = std::min(blockX, poSrcDS->GetRasterXSize()); - blockY = std::min(blockY, poSrcDS->GetRasterYSize()); - int nDTSize = GDALGetDataTypeSizeBytes(firstBand->GetRasterDataType()); - try - { - CPL_IGNORE_RET_VAL(CPLSM(blockX) * CPLSM(blockY) * CPLSM(nDTSize) * - CPLSM(nBands)); - CPLDebug("FIT write", "inherited block size %ix%i", blockX, blockY); - } - catch (...) - { - blockX = std::min(256, poSrcDS->GetRasterXSize()); - blockY = std::min(256, poSrcDS->GetRasterYSize()); - } - - if (CSLFetchNameValue(papszOptions, "PAGESIZE") != nullptr) - { - const char *str = CSLFetchNameValue(papszOptions, "PAGESIZE"); - int newBlockX, newBlockY; - sscanf(str, "%i,%i", &newBlockX, &newBlockY); - if (newBlockX > 0 && newBlockY > 0) - { - blockX = newBlockX; - blockY = newBlockY; - try - { - CPL_IGNORE_RET_VAL(CPLSM(blockX) * CPLSM(blockY) * - CPLSM(nDTSize) * CPLSM(nBands)); - } - catch (...) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Too big values in PAGESIZE"); - CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); - return nullptr; - } - } - else - { - CPLError(CE_Failure, CPLE_OpenFailed, - "FIT - Unable to parse option PAGESIZE values [%s]", str); - } - } - - // XXX - need to do lots of checking of block size - // * provide ability to override block size with options - // * handle non-square block size (like scanline) - // - probably default from non-tiled image - have default block size - // * handle block size bigger than image size - // * undesirable block size (non power of 2, others?) - // * mismatched block sizes for different bands - // * image that isn't even pages (i.e. partially empty pages at edge) - CPLDebug("FIT write", "using block size %ix%i", blockX, blockY); - - head->xPageSize = blockX; - gst_swapb(head->xPageSize); - head->yPageSize = blockY; - gst_swapb(head->yPageSize); - head->zPageSize = 1; - gst_swapb(head->zPageSize); - head->cPageSize = nBands; - gst_swapb(head->cPageSize); - - // XXX - need to check all bands - head->minValue = firstBand->GetMinimum(); - gst_swapb(head->minValue); - // XXX - need to check all bands - head->maxValue = firstBand->GetMaximum(); - gst_swapb(head->maxValue); - head->dataOffset = static_cast(size); - gst_swapb(head->dataOffset); - - CPL_IGNORE_RET_VAL(VSIFWriteL(head, size, 1, fpImage)); - - /* -------------------------------------------------------------------- */ - /* Loop over image, copying image data. */ - /* -------------------------------------------------------------------- */ - const size_t bytesPerPixel = static_cast(nBands) * nDTSize; - - const size_t pageBytes = - static_cast(blockX) * blockY * bytesPerPixel; - std::vector output; - try - { - output.resize(pageBytes); - } - catch (const std::bad_alloc &) - { - CPLError(CE_Failure, CPLE_OutOfMemory, - "FITRasterBand couldn't allocate %lu bytes", - static_cast(pageBytes)); - CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); - return nullptr; - } - - long maxx = (long)ceil(poSrcDS->GetRasterXSize() / (double)blockX); - long maxy = (long)ceil(poSrcDS->GetRasterYSize() / (double)blockY); - long maxx_full = (long)floor(poSrcDS->GetRasterXSize() / (double)blockX); - long maxy_full = (long)floor(poSrcDS->GetRasterYSize() / (double)blockY); - - CPLDebug("FIT", "about to write %ld x %ld blocks", maxx, maxy); - - for (long y = 0; y < maxy; y++) - for (long x = 0; x < maxx; x++) - { - long readX = blockX; - long readY = blockY; - int do_clean = FALSE; - - // handle cases where image size isn't an exact multiple - // of page size - if (x >= maxx_full) - { - readX = poSrcDS->GetRasterXSize() % blockX; - do_clean = TRUE; - } - if (y >= maxy_full) - { - readY = poSrcDS->GetRasterYSize() % blockY; - do_clean = TRUE; - } - - // clean out image if only doing partial reads - if (do_clean) - memset(output.data(), 0, pageBytes); - - for (int iBand = 0; iBand < nBands; iBand++) - { - GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1); - CPLErr eErr = poBand->RasterIO( - GF_Read, // eRWFlag - static_cast(x * blockX), // nXOff - static_cast(y * blockY), // nYOff - static_cast(readX), // nXSize - static_cast(readY), // nYSize - output.data() + iBand * nDTSize, - // pData - blockX, // nBufXSize - blockY, // nBufYSize - firstBand->GetRasterDataType(), - // eBufType - bytesPerPixel, // nPixelSpace - bytesPerPixel * blockX, nullptr); // nLineSpace - if (eErr != CE_None) - { - CPLError(CE_Failure, CPLE_FileIO, - "FIT write - CreateCopy got read error %i", eErr); - CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); - VSIUnlink(pszFilename); - return nullptr; - } - } // for iBand - -#ifdef swapping - GByte *p = output.data(); - unsigned long i; - switch (nDTSize) - { - case 1: - // do nothing - break; - case 2: - for (i = 0; i < pageBytes; i += nDTSize) - { - CPL_SWAP16PTR(p + i); - } - break; - case 4: - for (i = 0; i < pageBytes; i += nDTSize) - { - CPL_SWAP32PTR(p + i); - } - break; - case 8: - for (i = 0; i < pageBytes; i += nDTSize) - { - CPL_SWAP64PTR(p + i); - } - break; - default: - CPLError(CE_Failure, CPLE_NotSupported, - "FIT write - unsupported bytesPerPixel %d", - nDTSize); - } // switch -#endif // swapping - - if (VSIFWriteL(output.data(), 1, pageBytes, fpImage) != pageBytes) - { - CPLError(CE_Failure, CPLE_FileIO, "Write failed"); - CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); - VSIUnlink(pszFilename); - return nullptr; - } - - double perc = ((double)(y * maxx + x)) / (maxx * maxy); - if (!pfnProgress(perc, nullptr, pProgressData)) - { - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated"); - CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); - VSIUnlink(pszFilename); - return nullptr; - } - } // for x - - CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); - - pfnProgress(1.0, nullptr, pProgressData); - - /* -------------------------------------------------------------------- */ - /* Re-open dataset, and copy any auxiliary pam information. */ - /* -------------------------------------------------------------------- */ - GDALPamDataset *poDS = (GDALPamDataset *)GDALOpen(pszFilename, GA_ReadOnly); - - if (poDS) - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - - return poDS; -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -// CPLErr FITDataset::GetGeoTransform( double * padfTransform ) -// { -// CPLDebug("FIT", "FITDataset::GetGeoTransform"); -// memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 ); -// return CE_None; -// } - -/************************************************************************/ -/* GDALRegister_FIT() */ -/************************************************************************/ - -void GDALRegister_FIT() - -{ - if (GDALGetDriverByName("FIT") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("FIT"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "FIT Image"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/fit.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, ""); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = FITDataset::Open; - poDriver->pfnCreateCopy = FITCreateCopy; - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte UInt16 Int16 UInt32 Int32 " - "Float32 Float64"); - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/fit/gstEndian.h b/frmts/fit/gstEndian.h deleted file mode 100644 index bc1fb813a25c..000000000000 --- a/frmts/fit/gstEndian.h +++ /dev/null @@ -1,109 +0,0 @@ -/****************************************************************************** - * - * Project: FIT Driver - * Purpose: Implement FIT Support - not using the SGI iflFIT library. - * Author: Philip Nemec, nemec@keyholecorp.com - * - ****************************************************************************** - * Copyright (c) 2001, Keyhole, Inc. - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef gstEndian_h_ -#define gstEndian_h_ - -// endian swapping tools - -#include -#include "cpl_port.h" - -#include "gstTypes.h" - -namespace gstEndian -{ - -// have to do swapping on Linux and Windows -#ifdef CPL_LSB -#define swapping -#else -#endif - -#ifdef swapping -size_t swapped_fread(void *ptr, size_t size, size_t nitems, FILE *stream); -size_t swapped_fwrite(const void *ptr, size_t size, size_t nitems, - FILE *stream); - -static inline void gst_swap64(void *value) -{ - // 0x1122334455667788 --> 0x8877665544332211 - - *(uint64 *)(value) = (((*(uint64 *)(value)&0x00000000000000ff) << 56) | - ((*(uint64 *)(value)&0x000000000000ff00) << 40) | - ((*(uint64 *)(value)&0x0000000000ff0000) << 24) | - ((*(uint64 *)(value)&0x00000000ff000000) << 8) | - ((*(uint64 *)(value) >> 8) & 0x00000000ff000000) | - ((*(uint64 *)(value) >> 24) & 0x0000000000ff0000) | - ((*(uint64 *)(value) >> 40) & 0x000000000000ff00) | - ((*(uint64 *)(value) >> 56) & 0x00000000000000ff)); -} - -static inline void gst_swap32(void *value) -{ - // 0x12 34 56 78 --> 0x78 56 34 12 - - *(uint32 *)(value) = (((*(uint32 *)(value)&0x000000ff) << 24) | - ((*(uint32 *)(value)&0x0000ff00) << 8) | - ((*(uint32 *)(value) >> 8) & 0x0000ff00) | - ((*(uint32 *)(value) >> 24) & 0x000000ff)); -} - -static inline void gst_swap16(void *value) -{ - *(uint16 *)(value) = (((*(uint16 *)(value)&0x00ff) << 8) | - ((*(uint16 *)(value) >> 8) & 0x00ff)); -} - -static inline void gst_swapbytes(void *value, int size) -{ - switch (size) - { - case 1: - // do nothing - break; - case 2: - gst_swap16(value); - break; - case 4: - gst_swap32(value); - break; - case 8: - gst_swap64(value); - break; - default: - fprintf(stderr, - "gst_swapbytes unsupported size %i - not swapping\n", size); - break; - } // switch -} - -#define gst_swapb(value) gst_swapbytes(&value, sizeof(value)) - -#else // swapping - -#define swapped_fread(ptr, size, nitems, stream) \ - fread(ptr, size, nitems, stream) -#define swapped_fwrite(ptr, size, nitems, stream) \ - fwrite(ptr, size, nitems, stream) - -#define gst_swap64(value) -#define gst_swap32(value) -#define gst_swap16(value) -#define gst_swapbytes(value, size) -#define gst_swapb(value) - -#endif // swapping - -} // namespace gstEndian - -#endif // ! gstEndian_h_ diff --git a/frmts/fit/gstTypes.h b/frmts/fit/gstTypes.h deleted file mode 100644 index 4c2ce3b44a03..000000000000 --- a/frmts/fit/gstTypes.h +++ /dev/null @@ -1,30 +0,0 @@ -/****************************************************************************** - * - * Project: FIT Driver - * Purpose: Implement FIT Support - not using the SGI iflFIT library. - * Author: Philip Nemec, nemec@keyholecorp.com - * - ****************************************************************************** - * Copyright (c) 2001, Keyhole, Inc. - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef gstTypes_h_ -#define gstTypes_h_ - -#include -#include "cpl_conv.h" - -typedef int (*gstItemGetFunc)(void *data, int tag, ...); - -typedef GUInt16 uint16; -typedef GInt16 int16; -typedef GUInt32 uint32; -typedef GInt32 int32; -typedef GUIntBig uint64; -typedef GIntBig int64; - -typedef unsigned char uchar; - -#endif // !gstTypes_h_ diff --git a/frmts/gdalallregister.cpp b/frmts/gdalallregister.cpp index c569711ba288..4681b0b7b438 100644 --- a/frmts/gdalallregister.cpp +++ b/frmts/gdalallregister.cpp @@ -362,10 +362,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_GFF(); #endif -#ifdef FRMT_elas - GDALRegister_ELAS(); -#endif - #ifdef FRMT_esric GDALRegister_ESRIC(); #endif @@ -381,10 +377,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_ISG(); #endif -#ifdef FRMT_sdts - GDALRegister_SDTS(); -#endif - #ifdef FRMT_dted GDALRegister_DTED(); #endif @@ -430,10 +422,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_BSB(); #endif -#ifdef FRMT_xpm - GDALRegister_XPM(); -#endif - #ifdef FRMT_bmp GDALRegister_BMP(); #endif @@ -466,10 +454,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_ILWIS(); #endif -#ifdef FRMT_sgi - GDALRegister_SGI(); -#endif - #ifdef FRMT_srtmhgt GDALRegister_SRTMHGT(); #endif @@ -531,10 +515,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_L1B(); #endif -#ifdef FRMT_fit - GDALRegister_FIT(); -#endif - #ifdef FRMT_grib GDALRegister_GRIB(); #endif @@ -568,8 +548,6 @@ void CPL_STDCALL GDALAllRegister() #endif #ifdef FRMT_gsg - GDALRegister_GSAG(); - GDALRegister_GSBG(); GDALRegister_GS7BG(); #endif @@ -605,10 +583,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_PDF(); #endif -#ifdef FRMT_rasterlite - GDALRegister_Rasterlite(); -#endif - #ifdef FRMT_mbtiles GDALRegister_MBTiles(); #endif @@ -692,10 +666,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_SRP(); #endif -#ifdef FRMT_blx - GDALRegister_BLX(); -#endif - #ifdef FRMT_georaster GDALRegister_GEOR(); #endif diff --git a/frmts/gsg/CMakeLists.txt b/frmts/gsg/CMakeLists.txt index 145da5e513de..d621cd8514d1 100644 --- a/frmts/gsg/CMakeLists.txt +++ b/frmts/gsg/CMakeLists.txt @@ -1,7 +1,6 @@ -# Driver gdal_GSAG and gdal_GSBG are built in add_gdal_driver( TARGET gdal_GSG - SOURCES gs7bgdataset.cpp gsagdataset.cpp gsbgdataset.cpp + SOURCES gs7bgdataset.cpp BUILTIN) # FIXME should be 'PLUGIN_CAPABLE NO_DEPS' but requires some code to glue the registration of the 3 drivers gdal_standard_includes(gdal_GSG) diff --git a/frmts/gsg/gsagdataset.cpp b/frmts/gsg/gsagdataset.cpp deleted file mode 100644 index c4b3af4ab895..000000000000 --- a/frmts/gsg/gsagdataset.cpp +++ /dev/null @@ -1,1715 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL - * Purpose: Implements the Golden Software ASCII Grid Format. - * Author: Kevin Locke, kwl7@cornell.edu - * (Based largely on aaigriddataset.cpp by Frank Warmerdam) - * - ****************************************************************************** - * Copyright (c) 2006, Kevin Locke - * Copyright (c) 2008-2012, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_conv.h" - -#include -#include -#include -#include -#include - -#include "gdal_frmts.h" -#include "gdal_pam.h" - -/************************************************************************/ -/* ==================================================================== */ -/* GSAGDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class GSAGRasterBand; - -class GSAGDataset final : public GDALPamDataset -{ - friend class GSAGRasterBand; - - static const double dfNODATA_VALUE; - static const int nFIELD_PRECISION; - static const size_t nMAX_HEADER_SIZE; - - static CPLErr ShiftFileContents(VSILFILE *, vsi_l_offset, int, - const char *); - - VSILFILE *fp; - size_t nMinMaxZOffset; - char szEOL[3]; - - CPLErr UpdateHeader(); - - public: - explicit GSAGDataset(const char *pszEOL = "\x0D\x0A"); - ~GSAGDataset(); - - static int Identify(GDALOpenInfo *); - static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *CreateCopy(const char *pszFilename, - GDALDataset *poSrcDS, int bStrict, - char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); - - CPLErr GetGeoTransform(double *padfGeoTransform) override; - CPLErr SetGeoTransform(double *padfGeoTransform) override; -}; - -/* NOTE: This is not mentioned in the spec, but Surfer 8 uses this value */ -const double GSAGDataset::dfNODATA_VALUE = 1.70141E+38; - -const int GSAGDataset::nFIELD_PRECISION = 14; -const size_t GSAGDataset::nMAX_HEADER_SIZE = 200; - -/************************************************************************/ -/* ==================================================================== */ -/* GSAGRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class GSAGRasterBand final : public GDALPamRasterBand -{ - friend class GSAGDataset; - - double dfMinX; - double dfMaxX; - double dfMinY; - double dfMaxY; - double dfMinZ; - double dfMaxZ; - - vsi_l_offset *panLineOffset; - int nLastReadLine; - size_t nMaxLineSize; - - double *padfRowMinZ; - double *padfRowMaxZ; - int nMinZRow; - int nMaxZRow; - - CPLErr ScanForMinMaxZ(); - - public: - GSAGRasterBand(GSAGDataset *, int, vsi_l_offset); - ~GSAGRasterBand(); - - CPLErr IReadBlock(int, int, void *) override; - CPLErr IWriteBlock(int, int, void *) override; - - double GetNoDataValue(int *pbSuccess = nullptr) override; - double GetMinimum(int *pbSuccess = nullptr) override; - double GetMaximum(int *pbSuccess = nullptr) override; -}; - -/************************************************************************/ -/* AlmostEqual() */ -/* This function is needed because in release mode "1.70141E+38" is not */ -/* parsed as 1.70141E+38 in the last bit of the mantissa. */ -/* See http://gcc.gnu.org/ml/gcc/2003-08/msg01195.html for some */ -/* explanation. */ -/************************************************************************/ - -static bool AlmostEqual(double dfVal1, double dfVal2) - -{ - const double dfTOLERANCE = 0.0000000001; - if (dfVal1 == 0.0 || dfVal2 == 0.0) - return fabs(dfVal1 - dfVal2) < dfTOLERANCE; - return fabs((dfVal1 - dfVal2) / dfVal1) < dfTOLERANCE; -} - -/************************************************************************/ -/* GSAGRasterBand() */ -/************************************************************************/ - -GSAGRasterBand::GSAGRasterBand(GSAGDataset *poDSIn, int nBandIn, - vsi_l_offset nDataStart) - : dfMinX(0.0), dfMaxX(0.0), dfMinY(0.0), dfMaxY(0.0), dfMinZ(0.0), - dfMaxZ(0.0), panLineOffset(nullptr), nLastReadLine(poDSIn->nRasterYSize), - nMaxLineSize(128), padfRowMinZ(nullptr), padfRowMaxZ(nullptr), - nMinZRow(-1), nMaxZRow(-1) -{ - poDS = poDSIn; - nBand = nBandIn; - - eDataType = GDT_Float64; - - nBlockXSize = poDS->GetRasterXSize(); - nBlockYSize = 1; - - if (poDSIn->nRasterYSize > 1000000) - { - // Sanity check to avoid excessive memory allocations - VSIFSeekL(poDSIn->fp, 0, SEEK_END); - vsi_l_offset nFileSize = VSIFTellL(poDSIn->fp); - if (static_cast(poDSIn->nRasterYSize) > nFileSize) - { - CPLError(CE_Failure, CPLE_FileIO, "Truncated file"); - return; - } - } - panLineOffset = static_cast( - VSI_CALLOC_VERBOSE(poDSIn->nRasterYSize + 1, sizeof(vsi_l_offset))); - if (panLineOffset == nullptr) - { - return; - } - - panLineOffset[poDSIn->nRasterYSize - 1] = nDataStart; -} - -/************************************************************************/ -/* ~GSAGRasterBand() */ -/************************************************************************/ - -GSAGRasterBand::~GSAGRasterBand() -{ - CPLFree(panLineOffset); - CPLFree(padfRowMinZ); - CPLFree(padfRowMaxZ); -} - -/************************************************************************/ -/* ScanForMinMaxZ() */ -/************************************************************************/ - -CPLErr GSAGRasterBand::ScanForMinMaxZ() - -{ - double *padfRowValues = - (double *)VSI_MALLOC2_VERBOSE(nBlockXSize, sizeof(double)); - if (padfRowValues == nullptr) - { - return CE_Failure; - } - - double dfNewMinZ = std::numeric_limits::max(); - double dfNewMaxZ = std::numeric_limits::lowest(); - int nNewMinZRow = 0; - int nNewMaxZRow = 0; - - /* Since we have to scan, lets calc. statistics too */ - double dfSum = 0.0; - double dfSum2 = 0.0; - unsigned long nValuesRead = 0; - for (int iRow = 0; iRow < nRasterYSize; iRow++) - { - CPLErr eErr = IReadBlock(0, iRow, padfRowValues); - if (eErr != CE_None) - { - VSIFree(padfRowValues); - return eErr; - } - - padfRowMinZ[iRow] = std::numeric_limits::max(); - padfRowMaxZ[iRow] = std::numeric_limits::lowest(); - for (int iCell = 0; iCell < nRasterXSize; iCell++) - { - if (AlmostEqual(padfRowValues[iCell], GSAGDataset::dfNODATA_VALUE)) - continue; - - if (padfRowValues[iCell] < padfRowMinZ[iRow]) - padfRowMinZ[iRow] = padfRowValues[iCell]; - - if (padfRowValues[iCell] > padfRowMaxZ[iRow]) - padfRowMaxZ[iRow] = padfRowValues[iCell]; - - dfSum += padfRowValues[iCell]; - dfSum2 += padfRowValues[iCell] * padfRowValues[iCell]; - nValuesRead++; - } - - if (padfRowMinZ[iRow] < dfNewMinZ) - { - dfNewMinZ = padfRowMinZ[iRow]; - nNewMinZRow = iRow; - } - - if (padfRowMaxZ[iRow] > dfNewMaxZ) - { - dfNewMaxZ = padfRowMaxZ[iRow]; - nNewMaxZRow = iRow; - } - } - - VSIFree(padfRowValues); - - if (nValuesRead == 0) - { - dfMinZ = 0.0; - dfMaxZ = 0.0; - nMinZRow = 0; - nMaxZRow = 0; - return CE_None; - } - - dfMinZ = dfNewMinZ; - dfMaxZ = dfNewMaxZ; - nMinZRow = nNewMinZRow; - nMaxZRow = nNewMaxZRow; - - double dfMean = dfSum / nValuesRead; - double dfStdDev = sqrt((dfSum2 / nValuesRead) - (dfMean * dfMean)); - SetStatistics(dfMinZ, dfMaxZ, dfMean, dfStdDev); - - return CE_None; -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr GSAGRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) -{ - GSAGDataset *poGDS = (GSAGDataset *)poDS; - assert(poGDS != nullptr); - - double *pdfImage = (double *)pImage; - - if (nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0) - return CE_Failure; - - if (panLineOffset[nBlockYOff] == 0) - { - // Discover the last read block - for (int iFoundLine = nLastReadLine - 1; iFoundLine > nBlockYOff; - iFoundLine--) - { - if (IReadBlock(nBlockXOff, iFoundLine, nullptr) != CE_None) - return CE_Failure; - } - } - - if (panLineOffset[nBlockYOff] == 0) - return CE_Failure; - if (VSIFSeekL(poGDS->fp, panLineOffset[nBlockYOff], SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Can't seek to offset %ld to read grid row %d.", - (long)panLineOffset[nBlockYOff], nBlockYOff); - return CE_Failure; - } - - size_t nLineBufSize = nMaxLineSize; - /* If we know the offsets, we can just read line directly */ - if ((nBlockYOff > 0) && (panLineOffset[nBlockYOff - 1] != 0)) - { - assert(panLineOffset[nBlockYOff - 1] > panLineOffset[nBlockYOff]); - nLineBufSize = (size_t)(panLineOffset[nBlockYOff - 1] - - panLineOffset[nBlockYOff] + 1); - } - - char *szLineBuf = (char *)VSI_MALLOC_VERBOSE(nLineBufSize); - if (szLineBuf == nullptr) - { - return CE_Failure; - } - - size_t nCharsRead = VSIFReadL(szLineBuf, 1, nLineBufSize - 1, poGDS->fp); - if (nCharsRead == 0) - { - VSIFree(szLineBuf); - CPLError(CE_Failure, CPLE_FileIO, - "Can't read grid row %d at offset %ld.\n", nBlockYOff, - (long)panLineOffset[nBlockYOff]); - return CE_Failure; - } - szLineBuf[nCharsRead] = '\0'; - - size_t nCharsExamined = 0; - char *szStart = szLineBuf; - char *szEnd = szStart; - for (int iCell = 0; iCell < nBlockXSize; szStart = szEnd) - { - while (isspace((unsigned char)*szStart)) - szStart++; - - double dfValue = CPLStrtod(szStart, &szEnd); - if (szStart == szEnd) - { - /* No number found */ - if (*szStart == '.') - { - CPLError(CE_Failure, CPLE_FileIO, - "Unexpected value in grid row %d (expected floating " - "point value, found \"%s\").\n", - nBlockYOff, szStart); - VSIFree(szLineBuf); - return CE_Failure; - } - - /* Check if this was an expected failure */ - - /* Found sign at end of input, seek back to re-read it */ - bool bOnlySign = false; - if ((*szStart == '-' || *szStart == '+') && - static_cast(szStart + 1 - szLineBuf) == nCharsRead) - { - if (VSIFSeekL(poGDS->fp, VSIFTellL(poGDS->fp) - 1, SEEK_SET) != - 0) - { - VSIFree(szLineBuf); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek in grid row %d " - "(offset %ld, seek %d).\n", - nBlockYOff, (long)VSIFTellL(poGDS->fp), -1); - - return CE_Failure; - } - bOnlySign = true; - } - else if (*szStart != '\0') - { - // cppcheck-suppress redundantAssignment - szEnd = szStart; - while (!isspace((unsigned char)*szEnd) && *szEnd != '\0') - szEnd++; - char cOldEnd = *szEnd; - *szEnd = '\0'; - - CPLError(CE_Warning, CPLE_FileIO, - "Unexpected value in grid row %d (expected floating " - "point value, found \"%s\").\n", - nBlockYOff, szStart); - - *szEnd = cOldEnd; - - szEnd = szStart; - while (!isdigit(static_cast(*szEnd)) && - *szEnd != '.' && *szEnd != '\0') - szEnd++; - - continue; - } - else if (static_cast(szStart - szLineBuf) != nCharsRead) - { - CPLError(CE_Warning, CPLE_FileIO, - "Unexpected ASCII null-character in grid row %d at " - "offset %ld.\n", - nBlockYOff, (long)(szStart - szLineBuf)); - - while (*szStart == '\0' && - static_cast(szStart - szLineBuf) < nCharsRead) - szStart++; - - szEnd = szStart; - continue; - } - - nCharsExamined += szStart - szLineBuf; - nCharsRead = VSIFReadL(szLineBuf, 1, nLineBufSize - 1, poGDS->fp); - if (nCharsRead == 0 || (bOnlySign && nCharsRead == 1)) - { - VSIFree(szLineBuf); - CPLError(CE_Failure, CPLE_FileIO, - "Can't read portion of grid row %d at offset %ld.", - nBlockYOff, (long)panLineOffset[nBlockYOff]); - return CE_Failure; - } - szLineBuf[nCharsRead] = '\0'; - szEnd = szLineBuf; - continue; - } - else if (*szEnd == '\0' || (*szEnd == '.' && *(szEnd + 1) == '\0') || - (*szEnd == '-' && *(szEnd + 1) == '\0') || - (*szEnd == '+' && *(szEnd + 1) == '\0') || - (*szEnd == 'E' && *(szEnd + 1) == '\0') || - (*szEnd == 'E' && *(szEnd + 1) == '-' && - *(szEnd + 2) == '\0') || - (*szEnd == 'E' && *(szEnd + 1) == '+' && - *(szEnd + 2) == '\0') || - (*szEnd == 'e' && *(szEnd + 1) == '\0') || - (*szEnd == 'e' && *(szEnd + 1) == '-' && - *(szEnd + 2) == '\0') || - (*szEnd == 'e' && *(szEnd + 1) == '+' && *(szEnd + 2) == '\0')) - { - /* Number was interrupted by a nul character */ - while (*szEnd != '\0') - szEnd++; - - if (static_cast(szEnd - szLineBuf) != nCharsRead) - { - CPLError(CE_Warning, CPLE_FileIO, - "Unexpected ASCII null-character in grid row %d at " - "offset %ld.\n", - nBlockYOff, (long)(szEnd - szLineBuf)); - - while (*szEnd == '\0' && - static_cast(szEnd - szLineBuf) < nCharsRead) - szEnd++; - - continue; - } - - /* End of buffer, could be interrupting a number */ - if (VSIFSeekL(poGDS->fp, VSIFTellL(poGDS->fp) + szStart - szEnd, - SEEK_SET) != 0) - { - VSIFree(szLineBuf); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek in grid row %d (offset %ld, seek %d)" - ".\n", - nBlockYOff, (long)VSIFTellL(poGDS->fp), - (int)(szStart - szEnd)); - - return CE_Failure; - } - nCharsExamined += szStart - szLineBuf; - nCharsRead = VSIFReadL(szLineBuf, 1, nLineBufSize - 1, poGDS->fp); - szLineBuf[nCharsRead] = '\0'; - - if (nCharsRead == 0) - { - VSIFree(szLineBuf); - CPLError(CE_Failure, CPLE_FileIO, - "Can't read portion of grid row %d at offset %ld.", - nBlockYOff, (long)panLineOffset[nBlockYOff]); - return CE_Failure; - } - else if (nCharsRead > static_cast(szEnd - szStart)) - { - /* Read new data, this was not really the end */ - szEnd = szLineBuf; - continue; - } - - /* This is really the last value and has no tailing newline */ - szEnd = szLineBuf + nCharsRead; - } - - if (pdfImage != nullptr) - { - *(pdfImage + iCell) = dfValue; - } - - iCell++; - } - - while (*szEnd == ' ') - szEnd++; - - if (*szEnd != '\0' && *szEnd != poGDS->szEOL[0]) - CPLDebug("GSAG", - "Grid row %d does not end with a newline. " - "Possible skew.\n", - nBlockYOff); - - while (isspace((unsigned char)*szEnd)) - szEnd++; - - nCharsExamined += szEnd - szLineBuf; - - if (nCharsExamined >= nMaxLineSize) - nMaxLineSize = nCharsExamined + 1; - - if (nBlockYOff > 0) - { - vsi_l_offset nNewOffset = panLineOffset[nBlockYOff] + nCharsExamined; - if (panLineOffset[nBlockYOff - 1] == 0) - { - panLineOffset[nBlockYOff - 1] = nNewOffset; - } - else if (panLineOffset[nBlockYOff - 1] != nNewOffset) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "Coding error: previous offset for line %d was " CPL_FRMT_GUIB - ", new offset would be " CPL_FRMT_GUIB, - nBlockYOff - 1, panLineOffset[nBlockYOff - 1], nNewOffset); - } - } - - nLastReadLine = nBlockYOff; - - VSIFree(szLineBuf); - - return CE_None; -} - -/************************************************************************/ -/* IWriteBlock() */ -/************************************************************************/ - -CPLErr GSAGRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void *pImage) - -{ - if (eAccess == GA_ReadOnly) - { - CPLError(CE_Failure, CPLE_NoWriteAccess, - "Unable to write block, dataset opened read only.\n"); - return CE_Failure; - } - - if (nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0) - return CE_Failure; - - GSAGDataset *poGDS = (GSAGDataset *)poDS; - assert(poGDS != nullptr); - - if (padfRowMinZ == nullptr || padfRowMaxZ == nullptr || nMinZRow < 0 || - nMaxZRow < 0) - { - padfRowMinZ = - (double *)VSI_MALLOC2_VERBOSE(nRasterYSize, sizeof(double)); - if (padfRowMinZ == nullptr) - { - return CE_Failure; - } - - padfRowMaxZ = - (double *)VSI_MALLOC2_VERBOSE(nRasterYSize, sizeof(double)); - if (padfRowMaxZ == nullptr) - { - VSIFree(padfRowMinZ); - padfRowMinZ = nullptr; - return CE_Failure; - } - - CPLErr eErr = ScanForMinMaxZ(); - if (eErr != CE_None) - return eErr; - } - - if (panLineOffset[nBlockYOff + 1] == 0) - IReadBlock(nBlockXOff, nBlockYOff, nullptr); - - if (panLineOffset[nBlockYOff + 1] == 0 || panLineOffset[nBlockYOff] == 0) - return CE_Failure; - - std::ostringstream ssOutBuf; - ssOutBuf.precision(GSAGDataset::nFIELD_PRECISION); - ssOutBuf.setf(std::ios::uppercase); - - double *pdfImage = (double *)pImage; - padfRowMinZ[nBlockYOff] = std::numeric_limits::max(); - padfRowMaxZ[nBlockYOff] = std::numeric_limits::lowest(); - for (int iCell = 0; iCell < nBlockXSize;) - { - for (int iCol = 0; iCol < 10 && iCell < nBlockXSize; iCol++, iCell++) - { - if (AlmostEqual(pdfImage[iCell], GSAGDataset::dfNODATA_VALUE)) - { - if (pdfImage[iCell] < padfRowMinZ[nBlockYOff]) - padfRowMinZ[nBlockYOff] = pdfImage[iCell]; - - if (pdfImage[iCell] > padfRowMaxZ[nBlockYOff]) - padfRowMaxZ[nBlockYOff] = pdfImage[iCell]; - } - - ssOutBuf << pdfImage[iCell] << " "; - } - ssOutBuf << poGDS->szEOL; - } - ssOutBuf << poGDS->szEOL; - - CPLString sOut = ssOutBuf.str(); - if (sOut.length() != - panLineOffset[nBlockYOff + 1] - panLineOffset[nBlockYOff]) - { - int nShiftSize = (int)(sOut.length() - (panLineOffset[nBlockYOff + 1] - - panLineOffset[nBlockYOff])); - if (nBlockYOff != poGDS->nRasterYSize && - GSAGDataset::ShiftFileContents(poGDS->fp, - panLineOffset[nBlockYOff + 1], - nShiftSize, poGDS->szEOL) != CE_None) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failure writing block, " - "unable to shift file contents.\n"); - return CE_Failure; - } - - for (size_t iLine = nBlockYOff + 1; - iLine < static_cast(poGDS->nRasterYSize + 1) && - panLineOffset[iLine] != 0; - iLine++) - panLineOffset[iLine] += nShiftSize; - } - - if (VSIFSeekL(poGDS->fp, panLineOffset[nBlockYOff], SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to seek to grid line.\n"); - return CE_Failure; - } - - if (VSIFWriteL(sOut.c_str(), 1, sOut.length(), poGDS->fp) != sOut.length()) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to write grid block.\n"); - return CE_Failure; - } - - /* Update header as needed */ - bool bHeaderNeedsUpdate = false; - if (nMinZRow == nBlockYOff && padfRowMinZ[nBlockYOff] > dfMinZ) - { - double dfNewMinZ = std::numeric_limits::lowest(); - for (int iRow = 0; iRow < nRasterYSize; iRow++) - { - if (padfRowMinZ[iRow] < dfNewMinZ) - { - dfNewMinZ = padfRowMinZ[iRow]; - nMinZRow = iRow; - } - } - - if (dfNewMinZ != dfMinZ) - { - dfMinZ = dfNewMinZ; - bHeaderNeedsUpdate = true; - } - } - - if (nMaxZRow == nBlockYOff && padfRowMaxZ[nBlockYOff] < dfMaxZ) - { - double dfNewMaxZ = std::numeric_limits::lowest(); - for (int iRow = 0; iRow < nRasterYSize; iRow++) - { - if (padfRowMaxZ[iRow] > dfNewMaxZ) - { - dfNewMaxZ = padfRowMaxZ[iRow]; - nMaxZRow = iRow; - } - } - - if (dfNewMaxZ != dfMaxZ) - { - dfMaxZ = dfNewMaxZ; - bHeaderNeedsUpdate = true; - } - } - - if (padfRowMinZ[nBlockYOff] < dfMinZ || padfRowMaxZ[nBlockYOff] > dfMaxZ) - { - if (padfRowMinZ[nBlockYOff] < dfMinZ) - { - dfMinZ = padfRowMinZ[nBlockYOff]; - nMinZRow = nBlockYOff; - } - - if (padfRowMaxZ[nBlockYOff] > dfMaxZ) - { - dfMaxZ = padfRowMaxZ[nBlockYOff]; - nMaxZRow = nBlockYOff; - } - - bHeaderNeedsUpdate = true; - } - - if (bHeaderNeedsUpdate && dfMaxZ > dfMinZ) - { - CPLErr eErr = poGDS->UpdateHeader(); - return eErr; - } - - return CE_None; -} - -/************************************************************************/ -/* GetNoDataValue() */ -/************************************************************************/ - -double GSAGRasterBand::GetNoDataValue(int *pbSuccess) -{ - if (pbSuccess) - *pbSuccess = TRUE; - - return GSAGDataset::dfNODATA_VALUE; -} - -/************************************************************************/ -/* GetMinimum() */ -/************************************************************************/ - -double GSAGRasterBand::GetMinimum(int *pbSuccess) -{ - if (pbSuccess) - *pbSuccess = TRUE; - - return dfMinZ; -} - -/************************************************************************/ -/* GetMaximum() */ -/************************************************************************/ - -double GSAGRasterBand::GetMaximum(int *pbSuccess) -{ - if (pbSuccess) - *pbSuccess = TRUE; - - return dfMaxZ; -} - -/************************************************************************/ -/* ==================================================================== */ -/* GSAGDataset */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* GSAGDataset() */ -/************************************************************************/ - -GSAGDataset::GSAGDataset(const char *pszEOL) : fp(nullptr), nMinMaxZOffset(0) -{ - if (pszEOL == nullptr || EQUAL(pszEOL, "")) - { - CPLDebug("GSAG", "GSAGDataset() created with invalid EOL string.\n"); - szEOL[0] = '\x0D'; - szEOL[1] = '\x0A'; - szEOL[2] = '\0'; - return; - } - - snprintf(szEOL, sizeof(szEOL), "%s", pszEOL); -} - -/************************************************************************/ -/* ~GSAGDataset() */ -/************************************************************************/ - -GSAGDataset::~GSAGDataset() - -{ - FlushCache(true); - if (fp != nullptr) - VSIFCloseL(fp); -} - -/************************************************************************/ -/* Identify() */ -/************************************************************************/ - -int GSAGDataset::Identify(GDALOpenInfo *poOpenInfo) - -{ - /* Check for signature */ - if (poOpenInfo->nHeaderBytes < 5 || - !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "DSAA") || - (poOpenInfo->pabyHeader[4] != '\x0D' && - poOpenInfo->pabyHeader[4] != '\x0A')) - { - return FALSE; - } - return TRUE; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *GSAGDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr) - { - return nullptr; - } - - /* Identify the end of line marker (should be \x0D\x0A, but try some others) - * (note that '\x0D' == '\r' and '\x0A' == '\n' on most systems) */ - char szEOL[3]; - szEOL[0] = poOpenInfo->pabyHeader[4]; - szEOL[1] = poOpenInfo->pabyHeader[5]; - szEOL[2] = '\0'; - if (szEOL[1] != '\x0D' && szEOL[1] != '\x0A') - szEOL[1] = '\0'; - - /* -------------------------------------------------------------------- */ - /* Create a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - GSAGDataset *poDS = new GSAGDataset(szEOL); - poDS->eAccess = poOpenInfo->eAccess; - poDS->fp = poOpenInfo->fpL; - poOpenInfo->fpL = nullptr; - - /* -------------------------------------------------------------------- */ - /* Read the header. */ - /* -------------------------------------------------------------------- */ - char *pabyHeader = nullptr; - bool bMustFreeHeader = false; - if (poOpenInfo->nHeaderBytes >= static_cast(nMAX_HEADER_SIZE)) - { - pabyHeader = (char *)poOpenInfo->pabyHeader; - } - else - { - bMustFreeHeader = true; - pabyHeader = (char *)VSI_MALLOC_VERBOSE(nMAX_HEADER_SIZE); - if (pabyHeader == nullptr) - { - delete poDS; - return nullptr; - } - - size_t nRead = VSIFReadL(pabyHeader, 1, nMAX_HEADER_SIZE - 1, poDS->fp); - pabyHeader[nRead] = '\0'; - } - - const char *szErrorMsg = nullptr; - const char *szStart = pabyHeader + 5; - char *szEnd = nullptr; - double dfTemp; - - /* Parse number of X axis grid rows */ - long nTemp = strtol(szStart, &szEnd, 10); - if (szStart == szEnd || nTemp < 0l) - { - szErrorMsg = "Unable to parse the number of X axis grid columns.\n"; - goto error; - } - else if (nTemp > std::numeric_limits::max()) - { - CPLError(CE_Warning, CPLE_AppDefined, - "Number of X axis grid columns not representable.\n"); - poDS->nRasterXSize = std::numeric_limits::max(); - } - else if (nTemp == 0) - { - szErrorMsg = - "Number of X axis grid columns is zero, which is invalid.\n"; - goto error; - } - else - { - poDS->nRasterXSize = static_cast(nTemp); - } - szStart = szEnd; - - /* Parse number of Y axis grid rows */ - nTemp = strtol(szStart, &szEnd, 10); - if (szStart == szEnd || nTemp < 0l) - { - szErrorMsg = "Unable to parse the number of Y axis grid rows.\n"; - goto error; - } - else if (nTemp > std::numeric_limits::max() - 1) - { - CPLError(CE_Warning, CPLE_AppDefined, - "Number of Y axis grid rows not representable.\n"); - poDS->nRasterYSize = std::numeric_limits::max() - 1; - } - else if (nTemp == 0) - { - szErrorMsg = "Number of Y axis grid rows is zero, which is invalid.\n"; - goto error; - } - else - { - poDS->nRasterYSize = static_cast(nTemp); - } - szStart = szEnd; - - /* Parse the minimum X value of the grid */ - double dfMinX; - dfTemp = CPLStrtod(szStart, &szEnd); - if (szStart == szEnd) - { - szErrorMsg = "Unable to parse the minimum X value.\n"; - goto error; - } - else - { - dfMinX = dfTemp; - } - szStart = szEnd; - - /* Parse the maximum X value of the grid */ - double dfMaxX; - dfTemp = CPLStrtod(szStart, &szEnd); - if (szStart == szEnd) - { - szErrorMsg = "Unable to parse the maximum X value.\n"; - goto error; - } - else - { - dfMaxX = dfTemp; - } - szStart = szEnd; - - /* Parse the minimum Y value of the grid */ - double dfMinY; - dfTemp = CPLStrtod(szStart, &szEnd); - if (szStart == szEnd) - { - szErrorMsg = "Unable to parse the minimum Y value.\n"; - goto error; - } - else - { - dfMinY = dfTemp; - } - szStart = szEnd; - - /* Parse the maximum Y value of the grid */ - double dfMaxY; - dfTemp = CPLStrtod(szStart, &szEnd); - if (szStart == szEnd) - { - szErrorMsg = "Unable to parse the maximum Y value.\n"; - goto error; - } - else - { - dfMaxY = dfTemp; - } - szStart = szEnd; - - /* Parse the minimum Z value of the grid */ - while (isspace((unsigned char)*szStart)) - szStart++; - poDS->nMinMaxZOffset = szStart - pabyHeader; - - double dfMinZ; - dfTemp = CPLStrtod(szStart, &szEnd); - if (szStart == szEnd) - { - szErrorMsg = "Unable to parse the minimum Z value.\n"; - goto error; - } - else - { - dfMinZ = dfTemp; - } - szStart = szEnd; - - /* Parse the maximum Z value of the grid */ - double dfMaxZ; - dfTemp = CPLStrtod(szStart, &szEnd); - if (szStart == szEnd) - { - szErrorMsg = "Unable to parse the maximum Z value.\n"; - goto error; - } - else - { - dfMaxZ = dfTemp; - } - - while (isspace((unsigned char)*szEnd)) - szEnd++; - - /* -------------------------------------------------------------------- */ - /* Create band information objects. */ - /* -------------------------------------------------------------------- */ - { - GSAGRasterBand *poBand = - new GSAGRasterBand(poDS, 1, szEnd - pabyHeader); - if (poBand->panLineOffset == nullptr) - { - delete poBand; - goto error; - } - - poBand->dfMinX = dfMinX; - poBand->dfMaxX = dfMaxX; - poBand->dfMinY = dfMinY; - poBand->dfMaxY = dfMaxY; - poBand->dfMinZ = dfMinZ; - poBand->dfMaxZ = dfMaxZ; - - poDS->SetBand(1, poBand); - } - - if (bMustFreeHeader) - { - CPLFree(pabyHeader); - } - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for external overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename, - poOpenInfo->GetSiblingFiles()); - - return poDS; - -error: - if (bMustFreeHeader) - { - CPLFree(pabyHeader); - } - - delete poDS; - - if (szErrorMsg) - CPLError(CE_Failure, CPLE_AppDefined, "%s", szErrorMsg); - return nullptr; -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr GSAGDataset::GetGeoTransform(double *padfGeoTransform) -{ - padfGeoTransform[0] = 0; - padfGeoTransform[1] = 1; - padfGeoTransform[2] = 0; - padfGeoTransform[3] = 0; - padfGeoTransform[4] = 0; - padfGeoTransform[5] = 1; - - GSAGRasterBand *poGRB = (GSAGRasterBand *)GetRasterBand(1); - - if (poGRB == nullptr) - { - return CE_Failure; - } - - /* check if we have a PAM GeoTransform stored */ - CPLPushErrorHandler(CPLQuietErrorHandler); - CPLErr eErr = GDALPamDataset::GetGeoTransform(padfGeoTransform); - CPLPopErrorHandler(); - - if (eErr == CE_None) - return CE_None; - - if (nRasterXSize == 1 || nRasterYSize == 1) - return CE_Failure; - - /* calculate pixel size first */ - padfGeoTransform[1] = (poGRB->dfMaxX - poGRB->dfMinX) / (nRasterXSize - 1); - padfGeoTransform[5] = (poGRB->dfMinY - poGRB->dfMaxY) / (nRasterYSize - 1); - - /* then calculate image origin */ - padfGeoTransform[0] = poGRB->dfMinX - padfGeoTransform[1] / 2; - padfGeoTransform[3] = poGRB->dfMaxY - padfGeoTransform[5] / 2; - - /* tilt/rotation does not supported by the GS grids */ - padfGeoTransform[4] = 0.0; - padfGeoTransform[2] = 0.0; - - return CE_None; -} - -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr GSAGDataset::SetGeoTransform(double *padfGeoTransform) -{ - if (eAccess == GA_ReadOnly) - { - CPLError(CE_Failure, CPLE_NoWriteAccess, - "Unable to set GeoTransform, dataset opened read only.\n"); - return CE_Failure; - } - - GSAGRasterBand *poGRB = (GSAGRasterBand *)GetRasterBand(1); - - if (poGRB == nullptr || padfGeoTransform == nullptr) - return CE_Failure; - - /* non-zero transform 2 or 4 or negative 1 or 5 not supported natively */ - /*if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0 - || padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 ) - eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform );*/ - // if( eErr != CE_None ) - // return eErr; - - const double dfOldMinX = poGRB->dfMinX; - const double dfOldMaxX = poGRB->dfMaxX; - const double dfOldMinY = poGRB->dfMinY; - const double dfOldMaxY = poGRB->dfMaxY; - - poGRB->dfMinX = padfGeoTransform[0] + padfGeoTransform[1] / 2; - poGRB->dfMaxX = - padfGeoTransform[1] * (nRasterXSize - 0.5) + padfGeoTransform[0]; - poGRB->dfMinY = - padfGeoTransform[5] * (nRasterYSize - 0.5) + padfGeoTransform[3]; - poGRB->dfMaxY = padfGeoTransform[3] + padfGeoTransform[5] / 2; - - CPLErr eErr = UpdateHeader(); - - if (eErr != CE_None) - { - poGRB->dfMinX = dfOldMinX; - poGRB->dfMaxX = dfOldMaxX; - poGRB->dfMinY = dfOldMinY; - poGRB->dfMaxY = dfOldMaxY; - } - - return eErr; -} - -/************************************************************************/ -/* ShiftFileContents() */ -/************************************************************************/ -CPLErr GSAGDataset::ShiftFileContents(VSILFILE *fp, vsi_l_offset nShiftStart, - int nShiftSize, const char *pszEOL) -{ - /* nothing to do for zero-shift */ - if (nShiftSize == 0) - return CE_None; - - /* make sure start location is sane */ - /* Tautology is always false. nShiftStart is unsigned. */ - if (/* nShiftStart < 0 - || */ - (nShiftSize < 0 && - nShiftStart < static_cast(-nShiftSize))) - nShiftStart = /*(nShiftSize > 0) ? 0 :*/ -nShiftSize; - - /* get offset at end of file */ - if (VSIFSeekL(fp, 0, SEEK_END) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to end of grid file.\n"); - return CE_Failure; - } - - vsi_l_offset nOldEnd = VSIFTellL(fp); - - /* If shifting past end, just zero-pad as necessary */ - if (nShiftStart >= nOldEnd) - { - if (nShiftSize < 0) - { - if (nShiftStart + nShiftSize >= nOldEnd) - return CE_None; - - VSIFTruncateL(fp, nShiftStart + nShiftSize); - - return CE_None; - } - else - { - for (vsi_l_offset nPos = nOldEnd; nPos < nShiftStart + nShiftSize; - nPos++) - { - if (VSIFWriteL((void *)" ", 1, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write padding to grid file " - "(Out of space?).\n"); - return CE_Failure; - } - } - return CE_None; - } - } - - /* prepare buffer for real shifting */ - size_t nBufferSize = - (1024 >= abs(nShiftSize) * 2) ? 1024 : abs(nShiftSize) * 2; - char *pabyBuffer = (char *)VSI_MALLOC_VERBOSE(nBufferSize); - if (pabyBuffer == nullptr) - { - return CE_Failure; - } - - if (VSIFSeekL(fp, nShiftStart, SEEK_SET) != 0) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to start of shift in grid file.\n"); - return CE_Failure; - } - - size_t nRead; - size_t nOverlap = (nShiftSize > 0) ? nShiftSize : 0; - /* If there is overlap, fill buffer with the overlap to start */ - if (nOverlap > 0) - { - nRead = VSIFReadL((void *)pabyBuffer, 1, nOverlap, fp); - if (nRead < nOverlap && !VSIFEofL(fp)) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, "Error reading grid file.\n"); - return CE_Failure; - } - - /* overwrite the new space with ' ' */ - if (VSIFSeekL(fp, nShiftStart, SEEK_SET) != 0) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to start of shift in grid file.\n"); - return CE_Failure; - } - - for (int iFill = 0; iFill < nShiftSize; iFill++) - { - if (VSIFWriteL((void *)" ", 1, 1, fp) != 1) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write padding to grid file " - "(Out of space?).\n"); - return CE_Failure; - } - } - - /* if we have already read the entire file, finish it off */ - if (VSIFTellL(fp) >= nOldEnd) - { - if (VSIFWriteL((void *)pabyBuffer, 1, nRead, fp) != nRead) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write to grid file (Out of space?).\n"); - return CE_Failure; - } - - VSIFree(pabyBuffer); - return CE_None; - } - } - - /* iterate over the remainder of the file and shift as requested */ - bool bEOF = false; - while (!bEOF) - { - nRead = VSIFReadL((void *)(pabyBuffer + nOverlap), 1, - nBufferSize - nOverlap, fp); - - if (VSIFEofL(fp)) - bEOF = true; - else - bEOF = false; - - if (nRead == 0 && !bEOF) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to read from grid file (possible corruption).\n"); - return CE_Failure; - } - - /* FIXME: Should use SEEK_CUR, review integer promotions... */ - vsi_l_offset nNewPos = - (nShiftSize >= 0) - ? VSIFTellL(fp) + nShiftSize - nRead - nOverlap - : VSIFTellL(fp) - (-nShiftSize) - nRead - nOverlap; - if (VSIFSeekL(fp, nNewPos, SEEK_SET) != 0) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek in grid file (possible corruption).\n"); - return CE_Failure; - } - - size_t nWritten = VSIFWriteL((void *)pabyBuffer, 1, nRead, fp); - if (nWritten != nRead) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write to grid file (out of space?).\n"); - return CE_Failure; - } - - /* shift overlapped contents to the front of the buffer if necessary */ - if (nOverlap > 0) - memmove(pabyBuffer, pabyBuffer + nRead, nOverlap); - } - - /* write the remainder of the buffer or overwrite leftovers and finish */ - if (nShiftSize > 0) - { - size_t nTailSize = nOverlap; - while (nTailSize > 0 && - isspace((unsigned char)pabyBuffer[nTailSize - 1])) - nTailSize--; - - if (VSIFWriteL((void *)pabyBuffer, 1, nTailSize, fp) != nTailSize) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write to grid file (out of space?).\n"); - return CE_Failure; - } - - if (VSIFWriteL((void *)pszEOL, 1, strlen(pszEOL), fp) != strlen(pszEOL)) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write to grid file (out of space?).\n"); - return CE_Failure; - } - } - else - { - /* FIXME: ftruncate()? */ - /* FIXME: Should use SEEK_CUR, review integer promotions... */ - if (VSIFSeekL(fp, VSIFTellL(fp) - strlen(pszEOL), SEEK_SET) != 0) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, "Unable to seek in grid file.\n"); - return CE_Failure; - } - - for (int iPadding = 0; iPadding < -nShiftSize; iPadding++) - { - if (VSIFWriteL((void *)" ", 1, 1, fp) != 1) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Error writing to grid file.\n"); - return CE_Failure; - } - } - - if (VSIFWriteL((void *)pszEOL, 1, strlen(pszEOL), fp) != strlen(pszEOL)) - { - VSIFree(pabyBuffer); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write to grid file (out of space?).\n"); - return CE_Failure; - } - } - - VSIFree(pabyBuffer); - return CE_None; -} - -/************************************************************************/ -/* UpdateHeader() */ -/************************************************************************/ - -CPLErr GSAGDataset::UpdateHeader() - -{ - GSAGRasterBand *poBand = (GSAGRasterBand *)GetRasterBand(1); - if (poBand == nullptr) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to open raster band.\n"); - return CE_Failure; - } - - std::ostringstream ssOutBuf; - ssOutBuf.precision(nFIELD_PRECISION); - ssOutBuf.setf(std::ios::uppercase); - - /* signature */ - ssOutBuf << "DSAA" << szEOL; - - /* columns rows */ - ssOutBuf << nRasterXSize << " " << nRasterYSize << szEOL; - - /* x range */ - ssOutBuf << poBand->dfMinX << " " << poBand->dfMaxX << szEOL; - - /* y range */ - ssOutBuf << poBand->dfMinY << " " << poBand->dfMaxY << szEOL; - - /* z range */ - ssOutBuf << poBand->dfMinZ << " " << poBand->dfMaxZ << szEOL; - - CPLString sOut = ssOutBuf.str(); - if (sOut.length() != poBand->panLineOffset[0]) - { - int nShiftSize = (int)(sOut.length() - poBand->panLineOffset[0]); - if (ShiftFileContents(fp, poBand->panLineOffset[0], nShiftSize, - szEOL) != CE_None) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to update grid header, " - "failure shifting file contents.\n"); - return CE_Failure; - } - - for (size_t iLine = 0; - iLine < static_cast(nRasterYSize + 1) && - poBand->panLineOffset[iLine] != 0; - iLine++) - poBand->panLineOffset[iLine] += nShiftSize; - } - - if (VSIFSeekL(fp, 0, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to start of grid file.\n"); - return CE_Failure; - } - - if (VSIFWriteL(sOut.c_str(), 1, sOut.length(), fp) != sOut.length()) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to update file header. Disk full?\n"); - return CE_Failure; - } - - return CE_None; -} - -/************************************************************************/ -/* CreateCopy() */ -/************************************************************************/ - -GDALDataset *GSAGDataset::CreateCopy(const char *pszFilename, - GDALDataset *poSrcDS, int bStrict, - CPL_UNUSED char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - if (pfnProgress == nullptr) - pfnProgress = GDALDummyProgress; - - int nBands = poSrcDS->GetRasterCount(); - if (nBands == 0) - { - CPLError( - CE_Failure, CPLE_NotSupported, - "GSAG driver does not support source dataset with zero band.\n"); - return nullptr; - } - else if (nBands > 1) - { - if (bStrict) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Unable to create copy, Golden Software ASCII Grid " - "format only supports one raster band.\n"); - return nullptr; - } - else - CPLError(CE_Warning, CPLE_NotSupported, - "Golden Software ASCII Grid format only supports one " - "raster band, first band will be copied.\n"); - } - - if (!pfnProgress(0.0, nullptr, pProgressData)) - { - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated\n"); - return nullptr; - } - - VSILFILE *fp = VSIFOpenL(pszFilename, "w+b"); - - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file '%s' failed.\n", pszFilename); - return nullptr; - } - - const int nXSize = poSrcDS->GetRasterXSize(); - const int nYSize = poSrcDS->GetRasterYSize(); - double adfGeoTransform[6]; - - poSrcDS->GetGeoTransform(adfGeoTransform); - - std::ostringstream ssHeader; - ssHeader.precision(nFIELD_PRECISION); - ssHeader.setf(std::ios::uppercase); - - ssHeader << "DSAA\x0D\x0A"; - - ssHeader << nXSize << " " << nYSize << "\x0D\x0A"; - - ssHeader << adfGeoTransform[0] + adfGeoTransform[1] / 2 << " " - << adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0] - << "\x0D\x0A"; - - ssHeader << adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3] << " " - << adfGeoTransform[3] + adfGeoTransform[5] / 2 << "\x0D\x0A"; - - if (VSIFWriteL((void *)ssHeader.str().c_str(), 1, ssHeader.str().length(), - fp) != ssHeader.str().length()) - { - VSIFCloseL(fp); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to create copy, writing header failed.\n"); - return nullptr; - } - - /* Save the location and write placeholders for the min/max Z value */ - vsi_l_offset nRangeStart = VSIFTellL(fp); - const char *szDummyRange = "0.0000000000001 0.0000000000001\x0D\x0A"; - size_t nDummyRangeLen = strlen(szDummyRange); - if (VSIFWriteL((void *)szDummyRange, 1, nDummyRangeLen, fp) != - nDummyRangeLen) - { - VSIFCloseL(fp); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to create copy, writing header failed.\n"); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Copy band data. */ - /* -------------------------------------------------------------------- */ - double *pdfData = (double *)VSI_MALLOC2_VERBOSE(nXSize, sizeof(double)); - if (pdfData == nullptr) - { - VSIFCloseL(fp); - return nullptr; - } - - GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1); - int bSrcHasNDValue; - double dfSrcNoDataValue = poSrcBand->GetNoDataValue(&bSrcHasNDValue); - double dfMin = std::numeric_limits::max(); - double dfMax = std::numeric_limits::lowest(); - for (int iRow = 0; iRow < nYSize; iRow++) - { - CPLErr eErr = - poSrcBand->RasterIO(GF_Read, 0, nYSize - iRow - 1, nXSize, 1, - pdfData, nXSize, 1, GDT_Float64, 0, 0, nullptr); - - if (eErr != CE_None) - { - VSIFCloseL(fp); - VSIFree(pdfData); - return nullptr; - } - - for (int iCol = 0; iCol < nXSize;) - { - for (int iCount = 0; iCount < 10 && iCol < nXSize; iCount++, iCol++) - { - double dfValue = pdfData[iCol]; - - if (bSrcHasNDValue && AlmostEqual(dfValue, dfSrcNoDataValue)) - { - dfValue = dfNODATA_VALUE; - } - else - { - if (dfValue > dfMax) - dfMax = dfValue; - - if (dfValue < dfMin) - dfMin = dfValue; - } - - std::ostringstream ssOut; - ssOut.precision(nFIELD_PRECISION); - ssOut.setf(std::ios::uppercase); - ssOut << dfValue << " "; - CPLString sOut = ssOut.str(); - - if (VSIFWriteL(sOut.c_str(), 1, sOut.length(), fp) != - sOut.length()) - { - VSIFCloseL(fp); - VSIFree(pdfData); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write grid cell. Disk full?\n"); - return nullptr; - } - } - - if (VSIFWriteL((void *)"\x0D\x0A", 1, 2, fp) != 2) - { - VSIFCloseL(fp); - VSIFree(pdfData); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to finish write of grid line. Disk full?\n"); - return nullptr; - } - } - - if (VSIFWriteL((void *)"\x0D\x0A", 1, 2, fp) != 2) - { - VSIFCloseL(fp); - VSIFree(pdfData); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to finish write of grid row. Disk full?\n"); - return nullptr; - } - - if (!pfnProgress(static_cast(iRow + 1) / nYSize, nullptr, - pProgressData)) - { - VSIFCloseL(fp); - VSIFree(pdfData); - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated"); - return nullptr; - } - } - - VSIFree(pdfData); - - /* write out the min and max values */ - std::ostringstream ssRange; - ssRange.precision(nFIELD_PRECISION); - ssRange.setf(std::ios::uppercase); - ssRange << dfMin << " " << dfMax << "\x0D\x0A"; - if (ssRange.str().length() != nDummyRangeLen) - { - int nShiftSize = static_cast(ssRange.str().length()) - - static_cast(nDummyRangeLen); - if (ShiftFileContents(fp, nRangeStart + nDummyRangeLen, nShiftSize, - "\x0D\x0A") != CE_None) - { - VSIFCloseL(fp); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to shift file contents.\n"); - return nullptr; - } - } - - if (VSIFSeekL(fp, nRangeStart, SEEK_SET) != 0) - { - VSIFCloseL(fp); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to start of grid file copy.\n"); - return nullptr; - } - - if (VSIFWriteL((void *)ssRange.str().c_str(), 1, ssRange.str().length(), - fp) != ssRange.str().length()) - { - VSIFCloseL(fp); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write range information.\n"); - return nullptr; - } - - VSIFCloseL(fp); - - GDALPamDataset *poDS = (GDALPamDataset *)GDALOpen(pszFilename, GA_Update); - if (poDS) - { - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - } - return poDS; -} - -/************************************************************************/ -/* GDALRegister_GSAG() */ -/************************************************************************/ - -void GDALRegister_GSAG() - -{ - if (GDALGetDriverByName("GSAG") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("GSAG"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, - "Golden Software ASCII Grid (.grd)"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gsag.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "grd"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte Int16 UInt16 Int32 UInt32 " - "Float32 Float64"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnIdentify = GSAGDataset::Identify; - poDriver->pfnOpen = GSAGDataset::Open; - poDriver->pfnCreateCopy = GSAGDataset::CreateCopy; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/gsg/gsbgdataset.cpp b/frmts/gsg/gsbgdataset.cpp deleted file mode 100644 index 3440464b359e..000000000000 --- a/frmts/gsg/gsbgdataset.cpp +++ /dev/null @@ -1,1063 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL - * Purpose: Implements the Golden Software Binary Grid Format. - * Author: Kevin Locke, kwl7@cornell.edu - * (Based largely on aaigriddataset.cpp by Frank Warmerdam) - * - ****************************************************************************** - * Copyright (c) 2006, Kevin Locke - * Copyright (c) 2008-2012, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_conv.h" - -#include -#include -#include -#include - -#include "gdal_frmts.h" -#include "gdal_pam.h" - -/************************************************************************/ -/* ==================================================================== */ -/* GSBGDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class GSBGRasterBand; - -class GSBGDataset final : public GDALPamDataset -{ - friend class GSBGRasterBand; - - static const float fNODATA_VALUE; - static const size_t nHEADER_SIZE; - - static CPLErr WriteHeader(VSILFILE *fp, int nXSize, int nYSize, - double dfMinX, double dfMaxX, double dfMinY, - double dfMaxY, double dfMinZ, double dfMaxZ); - - VSILFILE *fp; - - public: - GSBGDataset() : fp(nullptr) - { - } - - ~GSBGDataset(); - - static int Identify(GDALOpenInfo *); - static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBands, GDALDataType eType, - char **papszParamList); - static GDALDataset *CreateCopy(const char *pszFilename, - GDALDataset *poSrcDS, int bStrict, - char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); - - CPLErr GetGeoTransform(double *padfGeoTransform) override; - CPLErr SetGeoTransform(double *padfGeoTransform) override; -}; - -/* NOTE: This is not mentioned in the spec, but Surfer 8 uses this value */ -/* 0x7effffee (Little Endian: eeffff7e) */ -const float GSBGDataset::fNODATA_VALUE = 1.701410009187828e+38f; - -const size_t GSBGDataset::nHEADER_SIZE = 56; - -/************************************************************************/ -/* ==================================================================== */ -/* GSBGRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class GSBGRasterBand final : public GDALPamRasterBand -{ - friend class GSBGDataset; - - double dfMinX; - double dfMaxX; - double dfMinY; - double dfMaxY; - double dfMinZ; - double dfMaxZ; - - float *pafRowMinZ; - float *pafRowMaxZ; - int nMinZRow; - int nMaxZRow; - - CPLErr ScanForMinMaxZ(); - - public: - GSBGRasterBand(GSBGDataset *, int); - ~GSBGRasterBand(); - - CPLErr IReadBlock(int, int, void *) override; - CPLErr IWriteBlock(int, int, void *) override; - - double GetNoDataValue(int *pbSuccess = nullptr) override; - double GetMinimum(int *pbSuccess = nullptr) override; - double GetMaximum(int *pbSuccess = nullptr) override; -}; - -/************************************************************************/ -/* GSBGRasterBand() */ -/************************************************************************/ - -GSBGRasterBand::GSBGRasterBand(GSBGDataset *poDSIn, int nBandIn) - : dfMinX(0.0), dfMaxX(0.0), dfMinY(0.0), dfMaxY(0.0), dfMinZ(0.0), - dfMaxZ(0.0), pafRowMinZ(nullptr), pafRowMaxZ(nullptr), nMinZRow(-1), - nMaxZRow(-1) -{ - this->poDS = poDSIn; - this->nBand = nBandIn; - - eDataType = GDT_Float32; - - nBlockXSize = poDS->GetRasterXSize(); - nBlockYSize = 1; -} - -/************************************************************************/ -/* ~GSBGRasterBand() */ -/************************************************************************/ - -GSBGRasterBand::~GSBGRasterBand() - -{ - if (pafRowMinZ != nullptr) - CPLFree(pafRowMinZ); - if (pafRowMaxZ != nullptr) - CPLFree(pafRowMaxZ); -} - -/************************************************************************/ -/* ScanForMinMaxZ() */ -/************************************************************************/ - -CPLErr GSBGRasterBand::ScanForMinMaxZ() - -{ - float *pafRowVals = (float *)VSI_MALLOC2_VERBOSE(nRasterXSize, 4); - - if (pafRowVals == nullptr) - { - return CE_Failure; - } - - double dfNewMinZ = std::numeric_limits::max(); - double dfNewMaxZ = std::numeric_limits::lowest(); - int nNewMinZRow = 0; - int nNewMaxZRow = 0; - - /* Since we have to scan, lets calc. statistics too */ - double dfSum = 0.0; - double dfSum2 = 0.0; - unsigned long nValuesRead = 0; - for (int iRow = 0; iRow < nRasterYSize; iRow++) - { - CPLErr eErr = IReadBlock(0, iRow, pafRowVals); - if (eErr != CE_None) - { - VSIFree(pafRowVals); - return CE_Failure; - } - - pafRowMinZ[iRow] = std::numeric_limits::max(); - pafRowMaxZ[iRow] = std::numeric_limits::lowest(); - for (int iCol = 0; iCol < nRasterXSize; iCol++) - { - if (pafRowVals[iCol] == GSBGDataset::fNODATA_VALUE) - continue; - - if (pafRowVals[iCol] < pafRowMinZ[iRow]) - pafRowMinZ[iRow] = pafRowVals[iCol]; - - if (pafRowVals[iCol] > pafRowMinZ[iRow]) - pafRowMaxZ[iRow] = pafRowVals[iCol]; - - dfSum += pafRowVals[iCol]; - dfSum2 += static_cast(pafRowVals[iCol]) * pafRowVals[iCol]; - nValuesRead++; - } - - if (pafRowMinZ[iRow] < dfNewMinZ) - { - dfNewMinZ = pafRowMinZ[iRow]; - nNewMinZRow = iRow; - } - - if (pafRowMaxZ[iRow] > dfNewMaxZ) - { - dfNewMaxZ = pafRowMaxZ[iRow]; - nNewMaxZRow = iRow; - } - } - - VSIFree(pafRowVals); - - if (nValuesRead == 0) - { - dfMinZ = 0.0; - dfMaxZ = 0.0; - nMinZRow = 0; - nMaxZRow = 0; - return CE_None; - } - - dfMinZ = dfNewMinZ; - dfMaxZ = dfNewMaxZ; - nMinZRow = nNewMinZRow; - nMaxZRow = nNewMaxZRow; - - double dfMean = dfSum / nValuesRead; - double dfStdDev = sqrt((dfSum2 / nValuesRead) - (dfMean * dfMean)); - SetStatistics(dfMinZ, dfMaxZ, dfMean, dfStdDev); - - return CE_None; -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr GSBGRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) - -{ - if (nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0) - return CE_Failure; - - GSBGDataset *poGDS = reinterpret_cast(poDS); - if (VSIFSeekL(poGDS->fp, - GSBGDataset::nHEADER_SIZE + - 4 * static_cast(nRasterXSize) * - (nRasterYSize - nBlockYOff - 1), - SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to beginning of grid row.\n"); - return CE_Failure; - } - - if (VSIFReadL(pImage, sizeof(float), nBlockXSize, poGDS->fp) != - static_cast(nBlockXSize)) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to read block from grid file.\n"); - return CE_Failure; - } - -#ifdef CPL_MSB - float *pfImage = (float *)pImage; - for (int iPixel = 0; iPixel < nBlockXSize; iPixel++) - { - CPL_LSBPTR32(pfImage + iPixel); - } -#endif - - return CE_None; -} - -/************************************************************************/ -/* IWriteBlock() */ -/************************************************************************/ - -CPLErr GSBGRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void *pImage) - -{ - if (eAccess == GA_ReadOnly) - { - CPLError(CE_Failure, CPLE_NoWriteAccess, - "Unable to write block, dataset opened read only.\n"); - return CE_Failure; - } - - if (nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0) - return CE_Failure; - - GSBGDataset *poGDS = cpl::down_cast(poDS); - - if (pafRowMinZ == nullptr || pafRowMaxZ == nullptr || nMinZRow < 0 || - nMaxZRow < 0) - { - pafRowMinZ = (float *)VSI_MALLOC2_VERBOSE(nRasterYSize, sizeof(float)); - if (pafRowMinZ == nullptr) - { - return CE_Failure; - } - - pafRowMaxZ = (float *)VSI_MALLOC2_VERBOSE(nRasterYSize, sizeof(float)); - if (pafRowMaxZ == nullptr) - { - VSIFree(pafRowMinZ); - pafRowMinZ = nullptr; - return CE_Failure; - } - - CPLErr eErr = ScanForMinMaxZ(); - if (eErr != CE_None) - return eErr; - } - - if (VSIFSeekL(poGDS->fp, - GSBGDataset::nHEADER_SIZE + - static_cast(4) * nRasterXSize * - (nRasterYSize - nBlockYOff - 1), - SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to beginning of grid row.\n"); - return CE_Failure; - } - - float *pfImage = (float *)pImage; - pafRowMinZ[nBlockYOff] = std::numeric_limits::max(); - pafRowMaxZ[nBlockYOff] = std::numeric_limits::lowest(); - for (int iPixel = 0; iPixel < nBlockXSize; iPixel++) - { - if (pfImage[iPixel] != GSBGDataset::fNODATA_VALUE) - { - if (pfImage[iPixel] < pafRowMinZ[nBlockYOff]) - pafRowMinZ[nBlockYOff] = pfImage[iPixel]; - - if (pfImage[iPixel] > pafRowMaxZ[nBlockYOff]) - pafRowMaxZ[nBlockYOff] = pfImage[iPixel]; - } - - CPL_LSBPTR32(pfImage + iPixel); - } - - if (VSIFWriteL(pImage, sizeof(float), nBlockXSize, poGDS->fp) != - static_cast(nBlockXSize)) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write block to grid file.\n"); - return CE_Failure; - } - - /* Update min/max Z values as appropriate */ - bool bHeaderNeedsUpdate = false; - if (nMinZRow == nBlockYOff && pafRowMinZ[nBlockYOff] > dfMinZ) - { - double dfNewMinZ = std::numeric_limits::max(); - for (int iRow = 0; iRow < nRasterYSize; iRow++) - { - if (pafRowMinZ[iRow] < dfNewMinZ) - { - dfNewMinZ = pafRowMinZ[iRow]; - nMinZRow = iRow; - } - } - - if (dfNewMinZ != dfMinZ) - { - dfMinZ = dfNewMinZ; - bHeaderNeedsUpdate = true; - } - } - - if (nMaxZRow == nBlockYOff && pafRowMaxZ[nBlockYOff] < dfMaxZ) - { - double dfNewMaxZ = std::numeric_limits::lowest(); - for (int iRow = 0; iRow < nRasterYSize; iRow++) - { - if (pafRowMaxZ[iRow] > dfNewMaxZ) - { - dfNewMaxZ = pafRowMaxZ[iRow]; - nMaxZRow = iRow; - } - } - - if (dfNewMaxZ != dfMaxZ) - { - dfMaxZ = dfNewMaxZ; - bHeaderNeedsUpdate = true; - } - } - - if (pafRowMinZ[nBlockYOff] < dfMinZ || pafRowMaxZ[nBlockYOff] > dfMaxZ) - { - if (pafRowMinZ[nBlockYOff] < dfMinZ) - { - dfMinZ = pafRowMinZ[nBlockYOff]; - nMinZRow = nBlockYOff; - } - - if (pafRowMaxZ[nBlockYOff] > dfMaxZ) - { - dfMaxZ = pafRowMaxZ[nBlockYOff]; - nMaxZRow = nBlockYOff; - } - - bHeaderNeedsUpdate = true; - } - - if (bHeaderNeedsUpdate && dfMaxZ > dfMinZ) - { - CPLErr eErr = - poGDS->WriteHeader(poGDS->fp, nRasterXSize, nRasterYSize, dfMinX, - dfMaxX, dfMinY, dfMaxY, dfMinZ, dfMaxZ); - return eErr; - } - - return CE_None; -} - -/************************************************************************/ -/* GetNoDataValue() */ -/************************************************************************/ - -double GSBGRasterBand::GetNoDataValue(int *pbSuccess) -{ - if (pbSuccess) - *pbSuccess = TRUE; - - return GSBGDataset::fNODATA_VALUE; -} - -/************************************************************************/ -/* GetMinimum() */ -/************************************************************************/ - -double GSBGRasterBand::GetMinimum(int *pbSuccess) -{ - if (pbSuccess) - *pbSuccess = TRUE; - - return dfMinZ; -} - -/************************************************************************/ -/* GetMaximum() */ -/************************************************************************/ - -double GSBGRasterBand::GetMaximum(int *pbSuccess) -{ - if (pbSuccess) - *pbSuccess = TRUE; - - return dfMaxZ; -} - -/************************************************************************/ -/* ==================================================================== */ -/* GSBGDataset */ -/* ==================================================================== */ -/************************************************************************/ - -GSBGDataset::~GSBGDataset() - -{ - FlushCache(true); - if (fp != nullptr) - VSIFCloseL(fp); -} - -/************************************************************************/ -/* Identify() */ -/************************************************************************/ - -int GSBGDataset::Identify(GDALOpenInfo *poOpenInfo) - -{ - /* Check for signature */ - if (poOpenInfo->nHeaderBytes < 4 || - !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "DSBB")) - { - return FALSE; - } - - return TRUE; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *GSBGDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr) - { - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - auto poDS = std::make_unique(); - - poDS->eAccess = poOpenInfo->eAccess; - poDS->fp = poOpenInfo->fpL; - poOpenInfo->fpL = nullptr; - - /* -------------------------------------------------------------------- */ - /* Read the header. */ - /* -------------------------------------------------------------------- */ - if (VSIFSeekL(poDS->fp, 4, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to start of grid file header.\n"); - return nullptr; - } - - /* Parse number of X axis grid rows */ - GInt16 nTemp; - if (VSIFReadL((void *)&nTemp, 2, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to read raster X size.\n"); - return nullptr; - } - poDS->nRasterXSize = CPL_LSBWORD16(nTemp); - - if (VSIFReadL((void *)&nTemp, 2, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to read raster Y size.\n"); - return nullptr; - } - poDS->nRasterYSize = CPL_LSBWORD16(nTemp); - - if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) - { - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create band information objects. */ - /* -------------------------------------------------------------------- */ - GSBGRasterBand *poBand = new GSBGRasterBand(poDS.get(), 1); - poDS->SetBand(1, poBand); - - double dfTemp; - if (VSIFReadL((void *)&dfTemp, 8, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to read minimum X value.\n"); - return nullptr; - } - CPL_LSBPTR64(&dfTemp); - poBand->dfMinX = dfTemp; - - if (VSIFReadL((void *)&dfTemp, 8, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to read maximum X value.\n"); - return nullptr; - } - CPL_LSBPTR64(&dfTemp); - poBand->dfMaxX = dfTemp; - - if (VSIFReadL((void *)&dfTemp, 8, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to read minimum Y value.\n"); - return nullptr; - } - CPL_LSBPTR64(&dfTemp); - poBand->dfMinY = dfTemp; - - if (VSIFReadL((void *)&dfTemp, 8, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to read maximum Y value.\n"); - return nullptr; - } - CPL_LSBPTR64(&dfTemp); - poBand->dfMaxY = dfTemp; - - if (VSIFReadL((void *)&dfTemp, 8, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to read minimum Z value.\n"); - return nullptr; - } - CPL_LSBPTR64(&dfTemp); - poBand->dfMinZ = dfTemp; - - if (VSIFReadL((void *)&dfTemp, 8, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Unable to read maximum Z value.\n"); - return nullptr; - } - CPL_LSBPTR64(&dfTemp); - poBand->dfMaxZ = dfTemp; - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for external overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename, - poOpenInfo->GetSiblingFiles()); - - return poDS.release(); -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr GSBGDataset::GetGeoTransform(double *padfGeoTransform) -{ - if (padfGeoTransform == nullptr) - return CE_Failure; - - GSBGRasterBand *poGRB = cpl::down_cast(GetRasterBand(1)); - - /* check if we have a PAM GeoTransform stored */ - CPLPushErrorHandler(CPLQuietErrorHandler); - CPLErr eErr = GDALPamDataset::GetGeoTransform(padfGeoTransform); - CPLPopErrorHandler(); - - if (eErr == CE_None) - return CE_None; - - if (nRasterXSize == 1 || nRasterYSize == 1) - return CE_Failure; - - /* calculate pixel size first */ - padfGeoTransform[1] = (poGRB->dfMaxX - poGRB->dfMinX) / (nRasterXSize - 1); - padfGeoTransform[5] = (poGRB->dfMinY - poGRB->dfMaxY) / (nRasterYSize - 1); - - /* then calculate image origin */ - padfGeoTransform[0] = poGRB->dfMinX - padfGeoTransform[1] / 2; - padfGeoTransform[3] = poGRB->dfMaxY - padfGeoTransform[5] / 2; - - /* tilt/rotation does not supported by the GS grids */ - padfGeoTransform[4] = 0.0; - padfGeoTransform[2] = 0.0; - - return CE_None; -} - -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr GSBGDataset::SetGeoTransform(double *padfGeoTransform) -{ - if (eAccess == GA_ReadOnly) - { - CPLError(CE_Failure, CPLE_NoWriteAccess, - "Unable to set GeoTransform, dataset opened read only.\n"); - return CE_Failure; - } - - GSBGRasterBand *poGRB = cpl::down_cast(GetRasterBand(1)); - - if (padfGeoTransform == nullptr) - return CE_Failure; - - /* non-zero transform 2 or 4 or negative 1 or 5 not supported natively */ - // CPLErr eErr = CE_None; - /*if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0 - || padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 ) - eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform ); - - if( eErr != CE_None ) - return eErr;*/ - - double dfMinX = padfGeoTransform[0] + padfGeoTransform[1] / 2; - double dfMaxX = - padfGeoTransform[1] * (nRasterXSize - 0.5) + padfGeoTransform[0]; - double dfMinY = - padfGeoTransform[5] * (nRasterYSize - 0.5) + padfGeoTransform[3]; - double dfMaxY = padfGeoTransform[3] + padfGeoTransform[5] / 2; - - CPLErr eErr = - WriteHeader(fp, poGRB->nRasterXSize, poGRB->nRasterYSize, dfMinX, - dfMaxX, dfMinY, dfMaxY, poGRB->dfMinZ, poGRB->dfMaxZ); - - if (eErr == CE_None) - { - poGRB->dfMinX = dfMinX; - poGRB->dfMaxX = dfMaxX; - poGRB->dfMinY = dfMinY; - poGRB->dfMaxY = dfMaxY; - } - - return eErr; -} - -/************************************************************************/ -/* WriteHeader() */ -/************************************************************************/ - -CPLErr GSBGDataset::WriteHeader(VSILFILE *fp, int nXSize, int nYSize, - double dfMinX, double dfMaxX, double dfMinY, - double dfMaxY, double dfMinZ, double dfMaxZ) - -{ - if (VSIFSeekL(fp, 0, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to seek to start of grid file.\n"); - return CE_Failure; - } - - if (VSIFWriteL((void *)"DSBB", 1, 4, fp) != 4) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write signature to grid file.\n"); - return CE_Failure; - } - - assert(nXSize >= 0 && nXSize <= std::numeric_limits::max()); - GInt16 nTemp = CPL_LSBWORD16(static_cast(nXSize)); - if (VSIFWriteL((void *)&nTemp, 2, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write raster X size to grid file.\n"); - return CE_Failure; - } - - assert(nYSize >= 0 && nYSize <= std::numeric_limits::max()); - nTemp = CPL_LSBWORD16(static_cast(nYSize)); - if (VSIFWriteL((void *)&nTemp, 2, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write raster Y size to grid file.\n"); - return CE_Failure; - } - - double dfTemp = dfMinX; - CPL_LSBPTR64(&dfTemp); - if (VSIFWriteL((void *)&dfTemp, 8, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write minimum X value to grid file.\n"); - return CE_Failure; - } - - dfTemp = dfMaxX; - CPL_LSBPTR64(&dfTemp); - if (VSIFWriteL((void *)&dfTemp, 8, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write maximum X value to grid file.\n"); - return CE_Failure; - } - - dfTemp = dfMinY; - CPL_LSBPTR64(&dfTemp); - if (VSIFWriteL((void *)&dfTemp, 8, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write minimum Y value to grid file.\n"); - return CE_Failure; - } - - dfTemp = dfMaxY; - CPL_LSBPTR64(&dfTemp); - if (VSIFWriteL((void *)&dfTemp, 8, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write maximum Y value to grid file.\n"); - return CE_Failure; - } - - dfTemp = dfMinZ; - CPL_LSBPTR64(&dfTemp); - if (VSIFWriteL((void *)&dfTemp, 8, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write minimum Z value to grid file.\n"); - return CE_Failure; - } - - dfTemp = dfMaxZ; - CPL_LSBPTR64(&dfTemp); - if (VSIFWriteL((void *)&dfTemp, 8, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write maximum Z value to grid file.\n"); - return CE_Failure; - } - - return CE_None; -} - -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *GSBGDataset::Create(const char *pszFilename, int nXSize, - int nYSize, int /* nBands */, - GDALDataType eType, - CPL_UNUSED char **papszParamList) -{ - if (nXSize <= 0 || nYSize <= 0) - { - CPLError(CE_Failure, CPLE_IllegalArg, - "Unable to create grid, both X and Y size must be " - "non-negative.\n"); - - return nullptr; - } - else if (nXSize > std::numeric_limits::max() || - nYSize > std::numeric_limits::max()) - { - CPLError(CE_Failure, CPLE_IllegalArg, - "Unable to create grid, Golden Software Binary Grid format " - "only supports sizes up to %dx%d. %dx%d not supported.\n", - std::numeric_limits::max(), - std::numeric_limits::max(), nXSize, nYSize); - - return nullptr; - } - - if (eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16 && - eType != GDT_Int16) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Golden Software Binary Grid only supports Byte, Int16, " - "Uint16, and Float32 datatypes. Unable to create with " - "type %s.\n", - GDALGetDataTypeName(eType)); - - return nullptr; - } - - VSILFILE *fp = VSIFOpenL(pszFilename, "w+b"); - - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file '%s' failed.\n", pszFilename); - return nullptr; - } - - CPLErr eErr = - WriteHeader(fp, nXSize, nYSize, 0.0, nXSize, 0.0, nYSize, 0.0, 0.0); - if (eErr != CE_None) - { - VSIFCloseL(fp); - return nullptr; - } - - float fVal = fNODATA_VALUE; - CPL_LSBPTR32(&fVal); - for (int iRow = 0; iRow < nYSize; iRow++) - { - for (int iCol = 0; iCol < nXSize; iCol++) - { - if (VSIFWriteL((void *)&fVal, 4, 1, fp) != 1) - { - VSIFCloseL(fp); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write grid cell. Disk full?\n"); - return nullptr; - } - } - } - - VSIFCloseL(fp); - - return (GDALDataset *)GDALOpen(pszFilename, GA_Update); -} - -/************************************************************************/ -/* CreateCopy() */ -/************************************************************************/ - -GDALDataset *GSBGDataset::CreateCopy(const char *pszFilename, - GDALDataset *poSrcDS, int bStrict, - CPL_UNUSED char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - if (pfnProgress == nullptr) - pfnProgress = GDALDummyProgress; - - int nBands = poSrcDS->GetRasterCount(); - if (nBands == 0) - { - CPLError( - CE_Failure, CPLE_NotSupported, - "GSBG driver does not support source dataset with zero band.\n"); - return nullptr; - } - else if (nBands > 1) - { - if (bStrict) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Unable to create copy, Golden Software Binary Grid " - "format only supports one raster band.\n"); - return nullptr; - } - else - CPLError(CE_Warning, CPLE_NotSupported, - "Golden Software Binary Grid format only supports one " - "raster band, first band will be copied.\n"); - } - - GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1); - if (poSrcBand->GetXSize() > std::numeric_limits::max() || - poSrcBand->GetYSize() > std::numeric_limits::max()) - { - CPLError(CE_Failure, CPLE_IllegalArg, - "Unable to create grid, Golden Software Binary Grid format " - "only supports sizes up to %dx%d. %dx%d not supported.\n", - std::numeric_limits::max(), - std::numeric_limits::max(), poSrcBand->GetXSize(), - poSrcBand->GetYSize()); - - return nullptr; - } - - if (!pfnProgress(0.0, nullptr, pProgressData)) - { - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated\n"); - return nullptr; - } - - VSILFILE *fp = VSIFOpenL(pszFilename, "w+b"); - - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file '%s' failed.\n", pszFilename); - return nullptr; - } - - const int nXSize = poSrcBand->GetXSize(); - const int nYSize = poSrcBand->GetYSize(); - double adfGeoTransform[6]; - - poSrcDS->GetGeoTransform(adfGeoTransform); - - double dfMinX = adfGeoTransform[0] + adfGeoTransform[1] / 2; - double dfMaxX = adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0]; - double dfMinY = adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3]; - double dfMaxY = adfGeoTransform[3] + adfGeoTransform[5] / 2; - CPLErr eErr = WriteHeader(fp, nXSize, nYSize, dfMinX, dfMaxX, dfMinY, - dfMaxY, 0.0, 0.0); - - if (eErr != CE_None) - { - VSIFCloseL(fp); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Copy band data. */ - /* -------------------------------------------------------------------- */ - float *pfData = (float *)VSI_MALLOC2_VERBOSE(nXSize, sizeof(float)); - if (pfData == nullptr) - { - VSIFCloseL(fp); - return nullptr; - } - - int bSrcHasNDValue; - float fSrcNoDataValue = (float)poSrcBand->GetNoDataValue(&bSrcHasNDValue); - double dfMinZ = std::numeric_limits::max(); - double dfMaxZ = std::numeric_limits::lowest(); - for (int iRow = nYSize - 1; iRow >= 0; iRow--) - { - eErr = poSrcBand->RasterIO(GF_Read, 0, iRow, nXSize, 1, pfData, nXSize, - 1, GDT_Float32, 0, 0, nullptr); - - if (eErr != CE_None) - { - VSIFCloseL(fp); - VSIFree(pfData); - return nullptr; - } - - for (int iCol = 0; iCol < nXSize; iCol++) - { - if (bSrcHasNDValue && pfData[iCol] == fSrcNoDataValue) - { - pfData[iCol] = fNODATA_VALUE; - } - else - { - if (pfData[iCol] > dfMaxZ) - dfMaxZ = pfData[iCol]; - - if (pfData[iCol] < dfMinZ) - dfMinZ = pfData[iCol]; - } - - CPL_LSBPTR32(pfData + iCol); - } - - if (VSIFWriteL((void *)pfData, 4, nXSize, fp) != - static_cast(nXSize)) - { - VSIFCloseL(fp); - VSIFree(pfData); - CPLError(CE_Failure, CPLE_FileIO, - "Unable to write grid row. Disk full?\n"); - return nullptr; - } - - if (!pfnProgress(static_cast(nYSize - iRow) / nYSize, nullptr, - pProgressData)) - { - VSIFCloseL(fp); - VSIFree(pfData); - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated"); - return nullptr; - } - } - - VSIFree(pfData); - - /* write out the min and max values */ - eErr = WriteHeader(fp, nXSize, nYSize, dfMinX, dfMaxX, dfMinY, dfMaxY, - dfMinZ, dfMaxZ); - - if (eErr != CE_None) - { - VSIFCloseL(fp); - return nullptr; - } - - VSIFCloseL(fp); - - GDALPamDataset *poDS = (GDALPamDataset *)GDALOpen(pszFilename, GA_Update); - if (poDS) - { - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - } - return poDS; -} - -/************************************************************************/ -/* GDALRegister_GSBG() */ -/************************************************************************/ - -void GDALRegister_GSBG() - -{ - if (GDALGetDriverByName("GSBG") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("GSBG"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, - "Golden Software Binary Grid (.grd)"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gsbg.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "grd"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte Int16 UInt16 Float32"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnIdentify = GSBGDataset::Identify; - poDriver->pfnOpen = GSBGDataset::Open; - poDriver->pfnCreate = GSBGDataset::Create; - poDriver->pfnCreateCopy = GSBGDataset::CreateCopy; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/pds/isis2dataset.cpp b/frmts/pds/isis2dataset.cpp index 6a3ca5c83410..334842de587a 100644 --- a/frmts/pds/isis2dataset.cpp +++ b/frmts/pds/isis2dataset.cpp @@ -22,8 +22,6 @@ constexpr int NULL1 = 0; constexpr int NULL2 = -32768; constexpr double NULL3 = -3.4028226550889044521e+38; -constexpr int RECORD_SIZE = 512; - #include "cpl_string.h" #include "gdal_frmts.h" #include "nasakeywordhandler.h" @@ -72,35 +70,6 @@ class ISIS2Dataset final : public RawDataset virtual char **GetFileList() override; static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszParamList); - - // Write related. - static int WriteRaster(const std::string &osFilename, bool includeLabel, - GUIntBig iRecord, GUIntBig iLabelRecords, - GDALDataType eType, const char *pszInterleaving); - - static int WriteLabel(const std::string &osFilename, - const std::string &osRasterFile, - const std::string &sObjectTag, unsigned int nXSize, - unsigned int nYSize, unsigned int nBandsIn, - GDALDataType eType, GUIntBig iRecords, - const char *pszInterleaving, GUIntBig &iLabelRecords, - bool bRelaunch = false); - static int WriteQUBE_Information(VSILFILE *fpLabel, unsigned int iLevel, - unsigned int &nWritingBytes, - unsigned int nXSize, unsigned int nYSize, - unsigned int nBandsIn, GDALDataType eType, - const char *pszInterleaving); - - static unsigned int WriteKeyword(VSILFILE *fpLabel, unsigned int iLevel, - CPLString key, CPLString value); - static unsigned int WriteFormatting(VSILFILE *fpLabel, CPLString data); - static GUIntBig RecordSizeCalculation(unsigned int nXSize, - unsigned int nYSize, - unsigned int nBands, - GDALDataType eType); }; /************************************************************************/ @@ -833,416 +802,6 @@ void ISIS2Dataset::CleanString(CPLString &osInput) CPLFree(pszWrk); } -/************************************************************************/ -/* Create() */ -/************************************************************************/ -/** - * Hidden Creation Options: - * INTERLEAVE=BSQ/BIP/BIL: Force the generation specified type of interleaving. - * BSQ --- band sequental (default), - * BIP --- band interleaved by pixel, - * BIL --- band interleaved by line. - * OBJECT=QUBE/IMAGE/SPECTRAL_QUBE, if null default is QUBE - */ - -GDALDataset *ISIS2Dataset::Create(const char *pszFilename, int nXSize, - int nYSize, int nBandsIn, GDALDataType eType, - char **papszParamList) -{ - - /* Verify settings. In Isis 2 core pixel values can be represented in - * three different ways : 1, 2 4, or 8 Bytes */ - if (eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_Float32 && - eType != GDT_UInt16 && eType != GDT_Float64) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "The ISIS2 driver does not supporting creating files of type %s.", - GDALGetDataTypeName(eType)); - return nullptr; - } - - /* (SAMPLE, LINE, BAND) - Band Sequential (BSQ) - default choice - (SAMPLE, BAND, LINE) - Band Interleaved by Line (BIL) - (BAND, SAMPLE, LINE) - Band Interleaved by Pixel (BIP) */ - const char *pszInterleaving = "(SAMPLE,LINE,BAND)"; - const char *pszInterleavingParam = - CSLFetchNameValue(papszParamList, "INTERLEAVE"); - if (pszInterleavingParam) - { - if (STARTS_WITH_CI(pszInterleavingParam, "bip")) - pszInterleaving = "(BAND,SAMPLE,LINE)"; - else if (STARTS_WITH_CI(pszInterleavingParam, "bil")) - pszInterleaving = "(SAMPLE,BAND,LINE)"; - else - pszInterleaving = "(SAMPLE,LINE,BAND)"; - } - - /* default labeling method is attached */ - bool bAttachedLabelingMethod = true; - /* check if labeling method is set : check the all three first chars */ - const char *pszLabelingMethod = - CSLFetchNameValue(papszParamList, "LABELING_METHOD"); - if (pszLabelingMethod) - { - if (STARTS_WITH_CI(pszLabelingMethod, "det" /* "detached" */)) - { - bAttachedLabelingMethod = false; - } - if (STARTS_WITH_CI(pszLabelingMethod, "att" /* attached" */)) - { - bAttachedLabelingMethod = true; - } - } - - /* set the label and data files */ - CPLString osLabelFile, osRasterFile, osOutFile; - if (bAttachedLabelingMethod) - { - osLabelFile = ""; - osRasterFile = pszFilename; - osOutFile = osRasterFile; - } - else - { - CPLString sExtension = "cub"; - const char *pszExtension = - CSLFetchNameValue(papszParamList, "IMAGE_EXTENSION"); - if (pszExtension) - { - sExtension = pszExtension; - } - - if (EQUAL(CPLGetExtensionSafe(pszFilename).c_str(), sExtension)) - { - CPLError(CE_Failure, CPLE_AppDefined, - "IMAGE_EXTENSION (%s) cannot match LABEL file extension.", - sExtension.c_str()); - return nullptr; - } - - osLabelFile = pszFilename; - osRasterFile = CPLResetExtensionSafe(osLabelFile, sExtension); - osOutFile = osLabelFile; - } - - const char *pszObject = CSLFetchNameValue(papszParamList, "OBJECT"); - CPLString sObject = "QUBE"; // default choice - if (pszObject) - { - if (EQUAL(pszObject, "IMAGE")) - { - sObject = "IMAGE"; - } - if (EQUAL(pszObject, "SPECTRAL_QUBE")) - { - sObject = "SPECTRAL_QUBE"; - } - } - - GUIntBig iRecords = - ISIS2Dataset::RecordSizeCalculation(nXSize, nYSize, nBandsIn, eType); - GUIntBig iLabelRecords(2); - - CPLDebug("ISIS2", "irecord = %i", static_cast(iRecords)); - - if (bAttachedLabelingMethod) - { - ISIS2Dataset::WriteLabel(osRasterFile, "", sObject, nXSize, nYSize, - nBandsIn, eType, iRecords, pszInterleaving, - iLabelRecords, true); - } - else - { - ISIS2Dataset::WriteLabel(osLabelFile, osRasterFile, sObject, nXSize, - nYSize, nBandsIn, eType, iRecords, - pszInterleaving, iLabelRecords); - } - - if (!ISIS2Dataset::WriteRaster(osRasterFile, bAttachedLabelingMethod, - iRecords, iLabelRecords, eType, - pszInterleaving)) - return nullptr; - - return GDALDataset::FromHandle(GDALOpen(osOutFile, GA_Update)); -} - -/************************************************************************/ -/* WriteRaster() */ -/************************************************************************/ - -int ISIS2Dataset::WriteRaster(const std::string &osFilename, bool includeLabel, - GUIntBig iRecords, GUIntBig iLabelRecords, - CPL_UNUSED GDALDataType eType, - CPL_UNUSED const char *pszInterleaving) -{ - VSILFILE *fpBin = VSIFOpenL(osFilename.c_str(), includeLabel ? "ab" : "wb"); - if (fpBin == nullptr) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to create %s:\n%s", - osFilename.c_str(), VSIStrerror(errno)); - return FALSE; - } - - GUIntBig nSize = iRecords * RECORD_SIZE; - CPLDebug("ISIS2", "nSize = %i", static_cast(nSize)); - - if (includeLabel) - nSize = iLabelRecords * RECORD_SIZE + nSize; - - // write last byte - const GByte byZero(0); - if (VSIFSeekL(fpBin, nSize - 1, SEEK_SET) != 0 || - VSIFWriteL(&byZero, 1, 1, fpBin) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to write %s:\n%s", - osFilename.c_str(), VSIStrerror(errno)); - VSIFCloseL(fpBin); - return FALSE; - } - VSIFCloseL(fpBin); - - return TRUE; -} - -/************************************************************************/ -/* RecordSizeCalculation() */ -/************************************************************************/ -GUIntBig ISIS2Dataset::RecordSizeCalculation(unsigned int nXSize, - unsigned int nYSize, - unsigned int nBandsIn, - GDALDataType eType) - -{ - const GUIntBig n = static_cast(nXSize) * nYSize * nBandsIn * - (GDALGetDataTypeSize(eType) / 8); - // size of pds file is a multiple of RECORD_SIZE Bytes. - CPLDebug("ISIS2", "n = %i", static_cast(n)); - CPLDebug("ISIS2", "RECORD SIZE = %i", RECORD_SIZE); - CPLDebug("ISIS2", "nXSize = %i", nXSize); - CPLDebug("ISIS2", "nYSize = %i", nYSize); - CPLDebug("ISIS2", "nBands = %i", nBandsIn); - CPLDebug("ISIS2", "DataTypeSize = %i", GDALGetDataTypeSize(eType)); - return static_cast(ceil(static_cast(n) / RECORD_SIZE)); -} - -/************************************************************************/ -/* WriteQUBE_Information() */ -/************************************************************************/ - -int ISIS2Dataset::WriteQUBE_Information( - VSILFILE *fpLabel, unsigned int iLevel, unsigned int &nWritingBytes, - unsigned int nXSize, unsigned int nYSize, unsigned int nBandsIn, - GDALDataType eType, const char *pszInterleaving) - -{ - nWritingBytes += ISIS2Dataset::WriteFormatting(fpLabel, ""); - nWritingBytes += - ISIS2Dataset::WriteFormatting(fpLabel, "/* Qube structure */"); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "OBJECT", "QUBE"); - iLevel++; - nWritingBytes += ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "AXES", "3"); - nWritingBytes += ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "AXIS_NAME", - pszInterleaving); - nWritingBytes += - ISIS2Dataset::WriteFormatting(fpLabel, "/* Core description */"); - - CPLDebug("ISIS2", "%d,%d,%d", nXSize, nYSize, nBandsIn); - - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "CORE_ITEMS", - CPLString().Printf("(%d,%d,%d)", nXSize, nYSize, nBandsIn)); - nWritingBytes += ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_NAME", - "\"RAW DATA NUMBER\""); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_UNIT", "\"N/A\""); - // TODO change for eType - - if (eType == GDT_Byte) - { - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_UNSIGNED_INTEGER"); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_ITEM_BYTES", "1"); - } - else if (eType == GDT_UInt16) - { - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_UNSIGNED_INTEGER"); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_ITEM_BYTES", "2"); - } - else if (eType == GDT_Int16) - { - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_INTEGER"); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_ITEM_BYTES", "2"); - } - else if (eType == GDT_Float32) - { - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_REAL"); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_ITEM_BYTES", "4"); - } - else if (eType == GDT_Float64) - { - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_REAL"); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_ITEM_BYTES", "8"); - } - - // TODO add core null value - - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_BASE", "0.0"); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "CORE_MULTIPLIER", "1.0"); - nWritingBytes += - ISIS2Dataset::WriteFormatting(fpLabel, "/* Suffix description */"); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "SUFFIX_BYTES", "4"); - nWritingBytes += ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "SUFFIX_ITEMS", - "( 0, 0, 0)"); - iLevel--; - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "END_OBJECT", "QUBE"); - - return TRUE; -} - -/************************************************************************/ -/* WriteLabel() */ -/* */ -/* osRasterFile : name of raster file but if it is empty we */ -/* have only one file with an attached label */ -/* sObjectTag : QUBE, IMAGE or SPECTRAL_QUBE */ -/* bRelaunch : flag to allow recursive call */ -/************************************************************************/ - -int ISIS2Dataset::WriteLabel(const std::string &osFilename, - const std::string &osRasterFile, - const std::string &sObjectTag, unsigned int nXSize, - unsigned int nYSize, unsigned int nBandsIn, - GDALDataType eType, GUIntBig iRecords, - const char *pszInterleaving, - GUIntBig &iLabelRecords, CPL_UNUSED bool bRelaunch) -{ - CPLDebug("ISIS2", "Write Label filename = %s, rasterfile = %s", - osFilename.c_str(), osRasterFile.c_str()); - bool bAttachedLabel = EQUAL(osRasterFile.c_str(), ""); - - VSILFILE *fpLabel = VSIFOpenL(osFilename.c_str(), "w"); - - if (fpLabel == nullptr) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to create %s:\n%s", - osFilename.c_str(), VSIStrerror(errno)); - return FALSE; - } - - const unsigned int iLevel(0); - unsigned int nWritingBytes(0); - - /* write common header */ - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "PDS_VERSION_ID", "PDS3"); - nWritingBytes += ISIS2Dataset::WriteFormatting(fpLabel, ""); - nWritingBytes += ISIS2Dataset::WriteFormatting( - fpLabel, "/* File identification and structure */"); - nWritingBytes += ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "RECORD_TYPE", - "FIXED_LENGTH"); - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "RECORD_BYTES", CPLString().Printf("%d", RECORD_SIZE)); - nWritingBytes += - ISIS2Dataset::WriteKeyword(fpLabel, iLevel, "FILE_RECORDS", - CPLString().Printf(CPL_FRMT_GUIB, iRecords)); - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "LABEL_RECORDS", - CPLString().Printf(CPL_FRMT_GUIB, iLabelRecords)); - if (!bAttachedLabel) - { - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, "FILE_NAME", CPLGetFilename(osRasterFile.c_str())); - } - nWritingBytes += ISIS2Dataset::WriteFormatting(fpLabel, ""); - - nWritingBytes += ISIS2Dataset::WriteFormatting( - fpLabel, "/* Pointers to Data Objects */"); - - if (bAttachedLabel) - { - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, CPLString().Printf("^%s", sObjectTag.c_str()), - CPLString().Printf(CPL_FRMT_GUIB, iLabelRecords + 1)); - } - else - { - nWritingBytes += ISIS2Dataset::WriteKeyword( - fpLabel, iLevel, CPLString().Printf("^%s", sObjectTag.c_str()), - CPLString().Printf("(\"%s\",1)", - CPLGetFilename(osRasterFile.c_str()))); - } - - if (EQUAL(sObjectTag.c_str(), "QUBE")) - { - ISIS2Dataset::WriteQUBE_Information(fpLabel, iLevel, nWritingBytes, - nXSize, nYSize, nBandsIn, eType, - pszInterleaving); - } - - nWritingBytes += ISIS2Dataset::WriteFormatting(fpLabel, "END"); - - // check if file record is correct - const unsigned int q = nWritingBytes / RECORD_SIZE; - if (q <= iLabelRecords) - { - // correct we add space after the label end for complete from - // iLabelRecords - unsigned int nSpaceBytesToWrite = static_cast( - iLabelRecords * RECORD_SIZE - nWritingBytes); - VSIFPrintfL(fpLabel, "%*c", nSpaceBytesToWrite, ' '); - } - else - { - iLabelRecords = q + 1; - ISIS2Dataset::WriteLabel(osFilename, osRasterFile, sObjectTag, nXSize, - nYSize, nBandsIn, eType, iRecords, - pszInterleaving, iLabelRecords); - } - VSIFCloseL(fpLabel); - - return TRUE; -} - -/************************************************************************/ -/* WriteKeyword() */ -/************************************************************************/ - -unsigned int ISIS2Dataset::WriteKeyword(VSILFILE *fpLabel, unsigned int iLevel, - CPLString key, CPLString value) - -{ - CPLString tab = ""; - iLevel *= 4; // each struct is indented by 4 spaces. - - return VSIFPrintfL(fpLabel, "%*s%s=%s\n", iLevel, tab.c_str(), key.c_str(), - value.c_str()); -} - -/************************************************************************/ -/* WriteFormatting() */ -/************************************************************************/ - -unsigned int ISIS2Dataset::WriteFormatting(VSILFILE *fpLabel, CPLString data) - -{ - return VSIFPrintfL(fpLabel, "%s\n", data.c_str()); -} - /************************************************************************/ /* GDALRegister_ISIS2() */ /************************************************************************/ @@ -1257,7 +816,6 @@ void GDALRegister_ISIS2() ISIS2DriverSetCommonMetadata(poDriver); poDriver->pfnOpen = ISIS2Dataset::Open; - poDriver->pfnCreate = ISIS2Dataset::Create; GetGDALDriverManager()->RegisterDriver(poDriver); } diff --git a/frmts/pds/pdsdrivercore.cpp b/frmts/pds/pdsdrivercore.cpp index 1c036758f427..870549f280ae 100644 --- a/frmts/pds/pdsdrivercore.cpp +++ b/frmts/pds/pdsdrivercore.cpp @@ -347,23 +347,9 @@ void ISIS2DriverSetCommonMetadata(GDALDriver *poDriver) "USGS Astrogeology ISIS cube (Version 2)"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/isis2.html"); poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte Int16 UInt16 Float32 Float64"); - - poDriver->SetMetadataItem( - GDAL_DMD_CREATIONOPTIONLIST, - "\n" - " " - " \n"); poDriver->pfnIdentify = ISIS2DriverIdentify; poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); - poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES"); } /************************************************************************/ diff --git a/frmts/r/CMakeLists.txt b/frmts/r/CMakeLists.txt deleted file mode 100644 index 0d3eeb5a67a5..000000000000 --- a/frmts/r/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_gdal_driver(TARGET gdal_R SOURCES rdataset.h rcreatecopy.cpp rdataset.cpp PLUGIN_CAPABLE NO_DEPS) -gdal_standard_includes(gdal_R) diff --git a/frmts/r/rcreatecopy.cpp b/frmts/r/rcreatecopy.cpp deleted file mode 100644 index 54ff8dbada78..000000000000 --- a/frmts/r/rcreatecopy.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/****************************************************************************** - * - * Project: R Format Driver - * Purpose: CreateCopy() implementation for R stats package object format. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2009, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_port.h" -#include "rdataset.h" - -#include -#include -#include - -#include "cpl_conv.h" -#include "cpl_error.h" -#include "cpl_progress.h" -#include "cpl_string.h" -#include "cpl_vsi.h" -#include "gdal.h" -#include "gdal_pam.h" -#include "gdal_priv.h" - -GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, void *pProgressData); - -/************************************************************************/ -/* ==================================================================== */ -/* Writer Implementation */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* RWriteInteger() */ -/************************************************************************/ - -static void RWriteInteger(VSILFILE *fp, int bASCII, int nValue) - -{ - if (bASCII) - { - char szOutput[50] = {'\0'}; - snprintf(szOutput, sizeof(szOutput), "%d\n", nValue); - VSIFWriteL(szOutput, 1, strlen(szOutput), fp); - } - else - { - CPL_MSBPTR32(&nValue); - VSIFWriteL(&nValue, 4, 1, fp); - } -} - -/************************************************************************/ -/* RWriteString() */ -/************************************************************************/ - -static void RWriteString(VSILFILE *fp, int bASCII, const char *pszValue) - -{ - RWriteInteger(fp, bASCII, 4105); - RWriteInteger(fp, bASCII, static_cast(strlen(pszValue))); - - if (bASCII) - { - VSIFWriteL(pszValue, 1, strlen(pszValue), fp); - VSIFWriteL("\n", 1, 1, fp); - } - else - { - VSIFWriteL(pszValue, 1, static_cast(strlen(pszValue)), fp); - } -} - -/************************************************************************/ -/* RCreateCopy() */ -/************************************************************************/ - -GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - CPL_UNUSED int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, void *pProgressData) -{ - const int nBands = poSrcDS->GetRasterCount(); - const int nXSize = poSrcDS->GetRasterXSize(); - const int nYSize = poSrcDS->GetRasterYSize(); - const bool bASCII = CPLFetchBool(papszOptions, "ASCII", false); - const bool bCompressed = CPLFetchBool(papszOptions, "COMPRESS", !bASCII); - - vsi_l_offset nSize = static_cast(nBands) * nXSize * nYSize; - if (nSize > static_cast(INT_MAX)) - { - CPLError(CE_Failure, CPLE_NotSupported, "Too big raster"); - return nullptr; - } - - // Some some rudimentary checks. - - // Setup the filename to actually use. We prefix with - // /vsigzip/ if we want compressed output. - const CPLString osAdjustedFilename = - std::string(bCompressed ? "/vsigzip/" : "") + pszFilename; - - // Create the file. - VSILFILE *fp = VSIFOpenL(osAdjustedFilename, "wb"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create file %s.", - pszFilename); - return nullptr; - } - - // Write header with version, etc. - if (bASCII) - { - const char *pszHeader = "RDA2\nA\n"; - VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp); - } - else - { - const char *pszHeader = "RDX2\nX\n"; - VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp); - } - - RWriteInteger(fp, bASCII, 2); - RWriteInteger(fp, bASCII, 133377); - RWriteInteger(fp, bASCII, 131840); - - // Establish the primary pairlist with one component object. - RWriteInteger(fp, bASCII, 1026); - RWriteInteger(fp, bASCII, 1); - - // Write the object name. Eventually we should derive this - // from the filename, possible with override by a creation option. - RWriteString(fp, bASCII, "gg"); - - // For now we write the raster as a numeric array with attributes (526). - RWriteInteger(fp, bASCII, 526); - RWriteInteger(fp, bASCII, nXSize * nYSize * nBands); - - // Write the raster data. - CPLErr eErr = CE_None; - - double *padfScanline = - static_cast(CPLMalloc(nXSize * sizeof(double))); - - for (int iBand = 0; iBand < nBands; iBand++) - { - GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1); - - for (int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++) - { - eErr = poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfScanline, - nXSize, 1, GDT_Float64, sizeof(double), 0, - nullptr); - - if (bASCII) - { - for (int iValue = 0; iValue < nXSize; iValue++) - { - char szValue[128] = {'\0'}; - CPLsnprintf(szValue, sizeof(szValue), "%.16g\n", - padfScanline[iValue]); - VSIFWriteL(szValue, 1, strlen(szValue), fp); - } - } - else - { - for (int iValue = 0; iValue < nXSize; iValue++) - CPL_MSBPTR64(padfScanline + iValue); - - VSIFWriteL(padfScanline, 8, nXSize, fp); - } - - if (eErr == CE_None && - !pfnProgress((iLine + 1) / static_cast(nYSize), nullptr, - pProgressData)) - { - eErr = CE_Failure; - CPLError(CE_Failure, CPLE_UserInterrupt, - "User terminated CreateCopy()"); - } - } - } - - CPLFree(padfScanline); - - // Write out the dims attribute. - RWriteInteger(fp, bASCII, 1026); - RWriteInteger(fp, bASCII, 1); - - RWriteString(fp, bASCII, "dim"); - - RWriteInteger(fp, bASCII, 13); - RWriteInteger(fp, bASCII, 3); - RWriteInteger(fp, bASCII, nXSize); - RWriteInteger(fp, bASCII, nYSize); - RWriteInteger(fp, bASCII, nBands); - - RWriteInteger(fp, bASCII, 254); - - // Terminate overall pairlist. - RWriteInteger(fp, bASCII, 254); - - // Cleanup. - VSIFCloseL(fp); - - if (eErr != CE_None) - return nullptr; - - // Re-open dataset, and copy any auxiliary pam information. - GDALPamDataset *poDS = - static_cast(GDALOpen(pszFilename, GA_ReadOnly)); - - if (poDS) - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - - return poDS; -} diff --git a/frmts/r/rdataset.cpp b/frmts/r/rdataset.cpp deleted file mode 100644 index 6879b7cdcf27..000000000000 --- a/frmts/r/rdataset.cpp +++ /dev/null @@ -1,603 +0,0 @@ -/****************************************************************************** - * - * Project: R Format Driver - * Purpose: Read/write R stats package object format. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2009, Frank Warmerdam - * Copyright (c) 2009-2010, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_port.h" -#include "rdataset.h" - -#include -#include -#include -#if HAVE_FCNTL_H -#include -#endif - -#include -#include -#include -#include - -#include "cpl_conv.h" -#include "cpl_error.h" -#include "cpl_progress.h" -#include "cpl_string.h" -#include "cpl_vsi.h" -#include "gdal.h" -#include "gdal_frmts.h" -#include "gdal_pam.h" -#include "gdal_priv.h" - -// constexpr int R_NILSXP = 0; -constexpr int R_LISTSXP = 2; -constexpr int R_CHARSXP = 9; -constexpr int R_INTSXP = 13; -constexpr int R_REALSXP = 14; -constexpr int R_STRSXP = 16; - -namespace -{ - -// TODO(schwehr): Move this to port/? for general use. -bool SafeMult(GIntBig a, GIntBig b, GIntBig *result) -{ - if (a == 0 || b == 0) - { - *result = 0; - return true; - } - - bool result_positive = (a >= 0 && b >= 0) || (a < 0 && b < 0); - if (result_positive) - { - // Cannot convert min() to positive. - if (a == std::numeric_limits::min() || - b == std::numeric_limits::min()) - { - *result = 0; - return false; - } - if (a < 0) - { - a = -a; - b = -b; - } - if (a > std::numeric_limits::max() / b) - { - *result = 0; - return false; - } - *result = a * b; - return true; - } - - if (b < a) - std::swap(a, b); - if (a < (std::numeric_limits::min() + 1) / b) - { - *result = 0; - return false; - } - - *result = a * b; - return true; -} - -} // namespace - -/************************************************************************/ -/* RRasterBand() */ -/************************************************************************/ - -RRasterBand::RRasterBand(RDataset *poDSIn, int nBandIn, - const double *padfMatrixValuesIn) - : padfMatrixValues(padfMatrixValuesIn) -{ - poDS = poDSIn; - nBand = nBandIn; - - eDataType = GDT_Float64; - - nBlockXSize = poDSIn->nRasterXSize; - nBlockYSize = 1; -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr RRasterBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff, - void *pImage) -{ - memcpy(pImage, padfMatrixValues + nBlockYOff * nBlockXSize, - nBlockXSize * 8); - return CE_None; -} - -/************************************************************************/ -/* ==================================================================== */ -/* RDataset() */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* RDataset() */ -/************************************************************************/ - -RDataset::RDataset() - : fp(nullptr), bASCII(FALSE), nStartOfData(0), padfMatrixValues(nullptr) -{ -} - -/************************************************************************/ -/* ~RDataset() */ -/************************************************************************/ - -RDataset::~RDataset() -{ - FlushCache(true); - CPLFree(padfMatrixValues); - - if (fp) - VSIFCloseL(fp); -} - -/************************************************************************/ -/* ASCIIFGets() */ -/* */ -/* Fetch one line from an ASCII source into osLastStringRead. */ -/************************************************************************/ - -const char *RDataset::ASCIIFGets() - -{ - char chNextChar = '\0'; - - osLastStringRead.resize(0); - - do - { - chNextChar = '\n'; - VSIFReadL(&chNextChar, 1, 1, fp); - if (chNextChar != '\n') - osLastStringRead += chNextChar; - } while (chNextChar != '\n' && chNextChar != '\0'); - - return osLastStringRead; -} - -/************************************************************************/ -/* ReadInteger() */ -/************************************************************************/ - -int RDataset::ReadInteger() - -{ - if (bASCII) - { - return atoi(ASCIIFGets()); - } - - GInt32 nValue = 0; - - if (VSIFReadL(&nValue, 4, 1, fp) != 1) - return -1; - CPL_MSBPTR32(&nValue); - - return nValue; -} - -/************************************************************************/ -/* ReadFloat() */ -/************************************************************************/ - -double RDataset::ReadFloat() - -{ - if (bASCII) - { - return CPLAtof(ASCIIFGets()); - } - - double dfValue = 0.0; - - if (VSIFReadL(&dfValue, 8, 1, fp) != 1) - return -1; - CPL_MSBPTR64(&dfValue); - - return dfValue; -} - -/************************************************************************/ -/* ReadString() */ -/************************************************************************/ - -const char *RDataset::ReadString() - -{ - if (ReadInteger() % 256 != R_CHARSXP) - { - osLastStringRead = ""; - return ""; - } - - const int nLenSigned = ReadInteger(); - if (nLenSigned < 0) - { - osLastStringRead = ""; - return ""; - } - const size_t nLen = static_cast(nLenSigned); - - char *pachWrkBuf = static_cast(VSIMalloc(nLen)); - if (pachWrkBuf == nullptr) - { - osLastStringRead = ""; - return ""; - } - if (VSIFReadL(pachWrkBuf, 1, nLen, fp) != nLen) - { - osLastStringRead = ""; - CPLFree(pachWrkBuf); - return ""; - } - - if (bASCII) - { - // Suck up newline and any extra junk. - ASCIIFGets(); - } - - osLastStringRead.assign(pachWrkBuf, nLen); - CPLFree(pachWrkBuf); - - return osLastStringRead; -} - -/************************************************************************/ -/* ReadPair() */ -/************************************************************************/ - -bool RDataset::ReadPair(CPLString &osObjName, int &nObjCode) - -{ - nObjCode = ReadInteger(); - if (nObjCode == 254) - return true; - - if ((nObjCode % 256) != R_LISTSXP) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Did not find expected object pair object."); - return false; - } - - int nPairCount = ReadInteger(); - if (nPairCount != 1) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Did not find expected pair count of 1."); - return false; - } - - // Read the object name. - const char *pszName = ReadString(); - if (pszName == nullptr || pszName[0] == '\0') - return false; - - osObjName = pszName; - - // Confirm that we have a numeric matrix object. - nObjCode = ReadInteger(); - - return true; -} - -/************************************************************************/ -/* Identify() */ -/************************************************************************/ - -int RDataset::Identify(GDALOpenInfo *poOpenInfo) -{ - if (poOpenInfo->nHeaderBytes < 50) - return FALSE; - - // If the extension is .rda and the file type is gzip - // compressed we assume it is a gzipped R binary file. - if (memcmp(poOpenInfo->pabyHeader, "\037\213\b", 3) == 0 && - poOpenInfo->IsExtensionEqualToCI("rda")) - return TRUE; - - // Is this an ASCII or XDR binary R file? - if (!STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDA2\nA\n") && - !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDX2\nX\n")) - return FALSE; - - return TRUE; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *RDataset::Open(GDALOpenInfo *poOpenInfo) -{ -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (poOpenInfo->pabyHeader == nullptr) - return nullptr; -#else - // During fuzzing, do not use Identify to reject crazy content. - if (!Identify(poOpenInfo)) - return nullptr; -#endif - - // Confirm the requested access is supported. - if (poOpenInfo->eAccess == GA_Update) - { - CPLError(CE_Failure, CPLE_NotSupported, - "The R driver does not support update access to existing" - " datasets."); - return nullptr; - } - - // Do we need to route the file through the decompression machinery? - const bool bCompressed = - memcmp(poOpenInfo->pabyHeader, "\037\213\b", 3) == 0; - const CPLString osAdjustedFilename = - std::string(bCompressed ? "/vsigzip/" : "") + poOpenInfo->pszFilename; - - // Establish this as a dataset and open the file using VSI*L. - auto poDS = std::make_unique(); - - poDS->fp = VSIFOpenL(osAdjustedFilename, "r"); - if (poDS->fp == nullptr) - { - return nullptr; - } - - poDS->bASCII = STARTS_WITH_CI( - reinterpret_cast(poOpenInfo->pabyHeader), "RDA2\nA\n"); - - // Confirm this is a version 2 file. - VSIFSeekL(poDS->fp, 7, SEEK_SET); - if (poDS->ReadInteger() != R_LISTSXP) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "It appears %s is not a version 2 R object file after all!", - poOpenInfo->pszFilename); - return nullptr; - } - - // Skip the version values. - poDS->ReadInteger(); - poDS->ReadInteger(); - - // Confirm we have a numeric vector object in a pairlist. - CPLString osObjName; - int nObjCode = 0; - - if (!poDS->ReadPair(osObjName, nObjCode)) - { - return nullptr; - } - - if (nObjCode % 256 != R_REALSXP) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Failed to find expected numeric vector object."); - return nullptr; - } - - poDS->SetMetadataItem("R_OBJECT_NAME", osObjName); - - // Read the count. - const int nValueCount = poDS->ReadInteger(); - if (nValueCount < 0) - { - CPLError(CE_Failure, CPLE_AppDefined, "nValueCount < 0: %d", - nValueCount); - return nullptr; - } - - poDS->nStartOfData = VSIFTellL(poDS->fp); - - // TODO(schwehr): Factor in the size of doubles. - VSIStatBufL stat; - const int dStatSuccess = - VSIStatExL(osAdjustedFilename, &stat, VSI_STAT_SIZE_FLAG); - if (dStatSuccess != 0 || static_cast(nValueCount) > - stat.st_size - poDS->nStartOfData) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Corrupt file. " - "Object claims to be larger than available bytes. " - "%d > " CPL_FRMT_GUIB, - nValueCount, stat.st_size - poDS->nStartOfData); - return nullptr; - } - - // Read/Skip ahead to attributes. - if (poDS->bASCII) - { - poDS->padfMatrixValues = - static_cast(VSIMalloc2(nValueCount, sizeof(double))); - if (poDS->padfMatrixValues == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d doubles", - nValueCount); - return nullptr; - } - for (int iValue = 0; iValue < nValueCount; iValue++) - poDS->padfMatrixValues[iValue] = poDS->ReadFloat(); - } - else - { - VSIFSeekL(poDS->fp, 8 * nValueCount, SEEK_CUR); - } - - // Read pairs till we run out, trying to find a few items that - // have special meaning to us. - poDS->nRasterXSize = 0; - poDS->nRasterYSize = 0; - int nBandCount = 0; - - while (poDS->ReadPair(osObjName, nObjCode) && nObjCode != 254) - { - if (osObjName == "dim" && nObjCode % 256 == R_INTSXP) - { - const int nCount = poDS->ReadInteger(); - if (nCount == 2) - { - poDS->nRasterXSize = poDS->ReadInteger(); - poDS->nRasterYSize = poDS->ReadInteger(); - nBandCount = 1; - } - else if (nCount == 3) - { - poDS->nRasterXSize = poDS->ReadInteger(); - poDS->nRasterYSize = poDS->ReadInteger(); - nBandCount = poDS->ReadInteger(); - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "R 'dim' dimension wrong."); - return nullptr; - } - } - else if (nObjCode % 256 == R_REALSXP) - { - int nCount = poDS->ReadInteger(); - while (nCount > 0 && !VSIFEofL(poDS->fp)) - { - nCount--; - poDS->ReadFloat(); - } - } - else if (nObjCode % 256 == R_INTSXP) - { - int nCount = poDS->ReadInteger(); - while (nCount > 0 && !VSIFEofL(poDS->fp)) - { - nCount--; - poDS->ReadInteger(); - } - } - else if (nObjCode % 256 == R_STRSXP) - { - int nCount = poDS->ReadInteger(); - while (nCount > 0 && !VSIFEofL(poDS->fp)) - { - nCount--; - poDS->ReadString(); - } - } - else if (nObjCode % 256 == R_CHARSXP) - { - poDS->ReadString(); - } - } - - if (poDS->nRasterXSize == 0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Failed to find dim dimension information for R dataset."); - return nullptr; - } - - if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || - !GDALCheckBandCount(nBandCount, TRUE)) - { - return nullptr; - } - - GIntBig result = 0; - bool ok = SafeMult(nBandCount, poDS->nRasterXSize, &result); - ok &= SafeMult(result, poDS->nRasterYSize, &result); - - if (!ok || nValueCount < result) - { - CPLError(CE_Failure, CPLE_AppDefined, "Not enough pixel data."); - return nullptr; - } - - // Create the raster band object(s). - for (int iBand = 0; iBand < nBandCount; iBand++) - { - std::unique_ptr poBand; - - if (poDS->bASCII) - poBand = std::make_unique( - poDS.get(), iBand + 1, - poDS->padfMatrixValues + static_cast(iBand) * - poDS->nRasterXSize * - poDS->nRasterYSize); - else - { - poBand = RawRasterBand::Create( - poDS.get(), iBand + 1, poDS->fp, - poDS->nStartOfData + - static_cast(poDS->nRasterXSize) * - poDS->nRasterYSize * 8 * iBand, - 8, poDS->nRasterXSize * 8, GDT_Float64, - RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN, - RawRasterBand::OwnFP::NO); - if (!poBand) - return nullptr; - } - poDS->SetBand(iBand + 1, std::move(poBand)); - } - - // Initialize any PAM information. - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - // Check for overviews. - poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename); - - return poDS.release(); -} - -/************************************************************************/ -/* GDALRegister_R() */ -/************************************************************************/ - -void GDALRegister_R() - -{ - if (GDALGetDriverByName("R") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("R"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "R Object Data Store"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/r.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "rda"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32"); - poDriver->SetMetadataItem( - GDAL_DMD_CREATIONOPTIONLIST, - "" - " "); - - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = RDataset::Open; - poDriver->pfnIdentify = RDataset::Identify; - poDriver->pfnCreateCopy = RCreateCopy; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/r/rdataset.h b/frmts/r/rdataset.h deleted file mode 100644 index 94e1f8c46d00..000000000000 --- a/frmts/r/rdataset.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * - * Project: R Format Driver - * Purpose: Read/write R stats package object format. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2009, Frank Warmerdam - * Copyright (c) 2009-2010, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef RDATASET_H_INCLUDED -#define RDATASET_H_INCLUDED - -#include -#include -#include -#include -#if HAVE_FCNTL_H -#include -#endif - -#include "cpl_conv.h" -#include "cpl_error.h" -#include "cpl_port.h" -#include "cpl_progress.h" -#include "cpl_string.h" -#include "cpl_vsi.h" -#include "gdal.h" -#include "gdal_frmts.h" -#include "gdal_pam.h" -#include "gdal_priv.h" -#include "rawdataset.h" - -GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, void *pProgressData); - -/************************************************************************/ -/* ==================================================================== */ -/* RDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class RDataset final : public GDALPamDataset -{ - friend class RRasterBand; - VSILFILE *fp; - int bASCII; - CPLString osLastStringRead; - - vsi_l_offset nStartOfData; - - double *padfMatrixValues; - - const char *ASCIIFGets(); - int ReadInteger(); - double ReadFloat(); - const char *ReadString(); - bool ReadPair(CPLString &osItemName, int &nItemType); - - public: - RDataset(); - ~RDataset(); - - static GDALDataset *Open(GDALOpenInfo *); - static int Identify(GDALOpenInfo *); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* RRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class RRasterBand final : public GDALPamRasterBand -{ - friend class RDataset; - - const double *padfMatrixValues; - - public: - RRasterBand(RDataset *, int, const double *); - - virtual ~RRasterBand() - { - } - - virtual CPLErr IReadBlock(int, int, void *) override; -}; - -#endif /* RDATASET_H_INCLUDED */ diff --git a/frmts/rasterlite/CMakeLists.txt b/frmts/rasterlite/CMakeLists.txt deleted file mode 100644 index 0abf1a4fb754..000000000000 --- a/frmts/rasterlite/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_gdal_driver(TARGET gdal_Rasterlite - SOURCES - rasterlitedataset.h - rasterlitecreatecopy.cpp - rasterlitedataset.cpp - rasterliteoverviews.cpp - CORE_SOURCES - rasterlitedrivercore.cpp - PLUGIN_CAPABLE NO_DEPS - NO_SHARED_SYMBOL_WITH_CORE) - -if(NOT TARGET gdal_Rasterlite) - return() -endif() - -gdal_standard_includes(gdal_Rasterlite) -target_include_directories(gdal_Rasterlite PRIVATE ${GDAL_RASTER_FORMAT_SOURCE_DIR}/mem) diff --git a/frmts/rasterlite/rasterlitecreatecopy.cpp b/frmts/rasterlite/rasterlitecreatecopy.cpp deleted file mode 100644 index cb78648b3043..000000000000 --- a/frmts/rasterlite/rasterlitecreatecopy.cpp +++ /dev/null @@ -1,729 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2012, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "ogr_api.h" -#include "ogr_srs_api.h" -#include "memdataset.h" - -#include "rasterlitedataset.h" - -/************************************************************************/ -/* RasterliteGetTileDriverOptions () */ -/************************************************************************/ - -static char **RasterliteAddTileDriverOptionsForDriver( - CSLConstList papszOptions, char **papszTileDriverOptions, - const char *pszOptionName, const char *pszExpectedDriverName) -{ - const char *pszVal = CSLFetchNameValue(papszOptions, pszOptionName); - if (pszVal) - { - const char *pszDriverName = - CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff"); - if (EQUAL(pszDriverName, pszExpectedDriverName)) - { - papszTileDriverOptions = - CSLSetNameValue(papszTileDriverOptions, pszOptionName, pszVal); - } - else - { - CPLError(CE_Warning, CPLE_NotSupported, - "Unexpected option '%s' for driver '%s'", pszOptionName, - pszDriverName); - } - } - return papszTileDriverOptions; -} - -char **RasterliteGetTileDriverOptions(CSLConstList papszOptions) -{ - const char *pszDriverName = - CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff"); - - char **papszTileDriverOptions = nullptr; - - const char *pszQuality = CSLFetchNameValue(papszOptions, "QUALITY"); - if (pszQuality) - { - if (EQUAL(pszDriverName, "GTiff")) - { - papszTileDriverOptions = CSLSetNameValue( - papszTileDriverOptions, "JPEG_QUALITY", pszQuality); - } - else if (EQUAL(pszDriverName, "JPEG") || EQUAL(pszDriverName, "WEBP")) - { - papszTileDriverOptions = - CSLSetNameValue(papszTileDriverOptions, "QUALITY", pszQuality); - } - else - { - CPLError(CE_Warning, CPLE_NotSupported, - "Unexpected option '%s' for driver '%s'", "QUALITY", - pszDriverName); - } - } - - papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver( - papszOptions, papszTileDriverOptions, "COMPRESS", "GTiff"); - papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver( - papszOptions, papszTileDriverOptions, "PHOTOMETRIC", "GTiff"); - - return papszTileDriverOptions; -} - -/************************************************************************/ -/* RasterliteInsertSRID () */ -/************************************************************************/ - -static int RasterliteInsertSRID(GDALDatasetH hDS, const char *pszWKT) -{ - int nAuthorityCode = 0; - CPLString osAuthorityName, osProjCS, osProj4; - if (pszWKT != nullptr && strlen(pszWKT) != 0) - { - OGRSpatialReferenceH hSRS = OSRNewSpatialReference(pszWKT); - if (hSRS) - { - OSRSetAxisMappingStrategy(hSRS, OAMS_TRADITIONAL_GIS_ORDER); - - const char *pszAuthorityName = OSRGetAuthorityName(hSRS, nullptr); - if (pszAuthorityName) - osAuthorityName = pszAuthorityName; - - const char *pszProjCS = OSRGetAttrValue(hSRS, "PROJCS", 0); - if (pszProjCS) - osProjCS = pszProjCS; - - const char *pszAuthorityCode = OSRGetAuthorityCode(hSRS, nullptr); - if (pszAuthorityCode) - nAuthorityCode = atoi(pszAuthorityCode); - - char *pszProj4 = nullptr; - if (OSRExportToProj4(hSRS, &pszProj4) != OGRERR_NONE) - { - CPLFree(pszProj4); - pszProj4 = CPLStrdup(""); - } - osProj4 = pszProj4; - CPLFree(pszProj4); - } - OSRDestroySpatialReference(hSRS); - } - - CPLString osSQL; - int nSRSId = -1; - if (nAuthorityCode != 0 && !osAuthorityName.empty()) - { - osSQL.Printf("SELECT srid FROM spatial_ref_sys WHERE auth_srid = %d", - nAuthorityCode); - OGRLayerH hLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hLyr == nullptr) - { - nSRSId = nAuthorityCode; - - if (!osProjCS.empty()) - osSQL.Printf( - "INSERT INTO spatial_ref_sys " - "(srid, auth_name, auth_srid, ref_sys_name, proj4text) " - "VALUES (%d, '%s', '%d', '%s', '%s')", - nSRSId, osAuthorityName.c_str(), nAuthorityCode, - osProjCS.c_str(), osProj4.c_str()); - else - osSQL.Printf("INSERT INTO spatial_ref_sys " - "(srid, auth_name, auth_srid, proj4text) " - "VALUES (%d, '%s', '%d', '%s')", - nSRSId, osAuthorityName.c_str(), nAuthorityCode, - osProj4.c_str()); - - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - } - else - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr); - if (hFeat) - { - nSRSId = OGR_F_GetFieldAsInteger(hFeat, 0); - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hLyr); - } - } - - return nSRSId; -} - -/************************************************************************/ -/* RasterliteCreateTables () */ -/************************************************************************/ - -static GDALDatasetH RasterliteCreateTables(GDALDatasetH hDS, - const char *pszTableName, int nSRSId, - int bWipeExistingData) -{ - CPLString osSQL; - - const CPLString osDBName = GDALGetDescription(hDS); - - CPLString osRasterLayer; - osRasterLayer.Printf("%s_rasters", pszTableName); - - CPLString osMetadataLayer; - osMetadataLayer.Printf("%s_metadata", pszTableName); - - OGRLayerH hLyr; - - if (GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str()) == nullptr) - { - /* -------------------------------------------------------------------- - */ - /* The table don't exist. Create them */ - /* -------------------------------------------------------------------- - */ - - /* Create _rasters table */ - osSQL.Printf("CREATE TABLE \"%s\" (" - "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "raster BLOB NOT NULL)", - osRasterLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - /* Create _metadata table */ - osSQL.Printf("CREATE TABLE \"%s\" (" - "id INTEGER NOT NULL PRIMARY KEY," - "source_name TEXT NOT NULL," - "tile_id INTEGER NOT NULL," - "width INTEGER NOT NULL," - "height INTEGER NOT NULL," - "pixel_x_size DOUBLE NOT NULL," - "pixel_y_size DOUBLE NOT NULL)", - osMetadataLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - /* Add geometry column to _metadata table */ - osSQL.Printf( - "SELECT AddGeometryColumn('%s', 'geometry', %d, 'POLYGON', 2)", - osMetadataLayer.c_str(), nSRSId); - if ((hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, - nullptr)) == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Check that the OGR SQLite driver has Spatialite support"); - GDALClose(hDS); - return nullptr; - } - GDALDatasetReleaseResultSet(hDS, hLyr); - - /* Create spatial index on _metadata table */ - osSQL.Printf("SELECT CreateSpatialIndex('%s', 'geometry')", - osMetadataLayer.c_str()); - if ((hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, - nullptr)) == nullptr) - { - GDALClose(hDS); - return nullptr; - } - GDALDatasetReleaseResultSet(hDS, hLyr); - - /* Create statistics tables */ - osSQL.Printf("SELECT UpdateLayerStatistics()"); - CPLPushErrorHandler(CPLQuietErrorHandler); - hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - CPLPopErrorHandler(); - GDALDatasetReleaseResultSet(hDS, hLyr); - - /* Re-open the DB to take into account the new tables*/ - GDALClose(hDS); - - hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update); - } - else - { - /* Check that the existing SRS is consistent with the one of the new */ - /* data to be inserted */ - osSQL.Printf( - "SELECT srid FROM geometry_columns WHERE f_table_name = '%s'", - osMetadataLayer.c_str()); - hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hLyr) - { - int nExistingSRID = -1; - OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr); - if (hFeat) - { - nExistingSRID = OGR_F_GetFieldAsInteger(hFeat, 0); - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hLyr); - - if (nExistingSRID != nSRSId) - { - if (bWipeExistingData) - { - osSQL.Printf("UPDATE geometry_columns SET srid = %d " - "WHERE f_table_name = \"%s\"", - nSRSId, osMetadataLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - /* Re-open the DB to take into account the change of SRS */ - GDALClose(hDS); - - hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update); - } - else - { - CPLError(CE_Failure, CPLE_NotSupported, - "New data has not the same SRS as existing data"); - GDALClose(hDS); - return nullptr; - } - } - } - - if (bWipeExistingData) - { - osSQL.Printf("DELETE FROM \"%s\"", osRasterLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - osSQL.Printf("DELETE FROM \"%s\"", osMetadataLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - } - } - - return hDS; -} - -/************************************************************************/ -/* RasterliteCreateCopy () */ -/************************************************************************/ - -GDALDataset *RasterliteCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - CPL_UNUSED int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - const int nBands = poSrcDS->GetRasterCount(); - if (nBands == 0) - { - CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0"); - return nullptr; - } - - const char *pszDriverName = - CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff"); - if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT")) - { - CPLError(CE_Failure, CPLE_AppDefined, - "GDAL %s driver cannot be used as underlying driver", - pszDriverName); - return nullptr; - } - - GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName); - if (hTileDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", - pszDriverName); - return nullptr; - } - - GDALDriverH hMemDriver = GDALGetDriverByName("MEM"); - if (hMemDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver"); - return nullptr; - } - - const int nXSize = GDALGetRasterXSize(poSrcDS); - const int nYSize = GDALGetRasterYSize(poSrcDS); - - double adfGeoTransform[6]; - if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None) - { - adfGeoTransform[0] = 0; - adfGeoTransform[1] = 1; - adfGeoTransform[2] = 0; - adfGeoTransform[3] = 0; - adfGeoTransform[4] = 0; - adfGeoTransform[5] = -1; - } - else if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot use geotransform with rotational terms"); - return nullptr; - } - - const bool bTiled = - CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES")); - int nBlockXSize, nBlockYSize; - if (bTiled) - { - nBlockXSize = - atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256")); - nBlockYSize = - atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256")); - if (nBlockXSize < 64) - nBlockXSize = 64; - else if (nBlockXSize > 4096) - nBlockXSize = 4096; - if (nBlockYSize < 64) - nBlockYSize = 64; - else if (nBlockYSize > 4096) - nBlockYSize = 4096; - } - else - { - nBlockXSize = nXSize; - nBlockYSize = nYSize; - } - - /* -------------------------------------------------------------------- */ - /* Analyze arguments */ - /* -------------------------------------------------------------------- */ - - /* Skip optional RASTERLITE: prefix */ - const char *pszFilenameWithoutPrefix = pszFilename; - if (STARTS_WITH_CI(pszFilename, "RASTERLITE:")) - pszFilenameWithoutPrefix += 11; - - char **papszTokens = - CSLTokenizeStringComplex(pszFilenameWithoutPrefix, ",", FALSE, FALSE); - const int nTokens = CSLCount(papszTokens); - CPLString osDBName; - CPLString osTableName; - if (nTokens == 0) - { - osDBName = pszFilenameWithoutPrefix; - osTableName = CPLGetBasenameSafe(pszFilenameWithoutPrefix); - } - else - { - osDBName = papszTokens[0]; - - int i; - for (i = 1; i < nTokens; i++) - { - if (STARTS_WITH_CI(papszTokens[i], "table=")) - osTableName = papszTokens[i] + 6; - else - { - CPLError(CE_Warning, CPLE_AppDefined, "Invalid option : %s", - papszTokens[i]); - } - } - } - - CSLDestroy(papszTokens); - papszTokens = nullptr; - - VSIStatBuf sBuf; - const bool bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0); - - if (osTableName.empty()) - { - if (bExists) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Database already exists. Explicit table name must be " - "specified"); - return nullptr; - } - osTableName = CPLGetBasenameSafe(osDBName.c_str()); - } - - CPLString osRasterLayer; - osRasterLayer.Printf("%s_rasters", osTableName.c_str()); - - CPLString osMetadataLayer; - osMetadataLayer.Printf("%s_metadata", osTableName.c_str()); - - /* -------------------------------------------------------------------- */ - /* Create or open the SQLite DB */ - /* -------------------------------------------------------------------- */ - - GDALDriverH hSQLiteDriver = GDALGetDriverByName("SQLite"); - if (hSQLiteDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver"); - return nullptr; - } - - GDALDatasetH hDS; - - if (!bExists) - { - char **papszOGROptions = CSLAddString(nullptr, "SPATIALITE=YES"); - hDS = GDALCreate(hSQLiteDriver, osDBName.c_str(), 0, 0, 0, GDT_Unknown, - papszOGROptions); - CSLDestroy(papszOGROptions); - } - else - { - hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update); - } - - if (hDS == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot load or create SQLite database"); - return nullptr; - } - - CPLString osSQL; - - /* -------------------------------------------------------------------- */ - /* Get the SRID for the SRS */ - /* -------------------------------------------------------------------- */ - int nSRSId = RasterliteInsertSRID(hDS, poSrcDS->GetProjectionRef()); - - /* -------------------------------------------------------------------- */ - /* Create or wipe existing tables */ - /* -------------------------------------------------------------------- */ - const int bWipeExistingData = - CPLTestBool(CSLFetchNameValueDef(papszOptions, "WIPE", "NO")); - - hDS = RasterliteCreateTables(hDS, osTableName.c_str(), nSRSId, - bWipeExistingData); - if (hDS == nullptr) - return nullptr; - - OGRLayerH hRasterLayer = - GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str()); - OGRLayerH hMetadataLayer = - GDALDatasetGetLayerByName(hDS, osMetadataLayer.c_str()); - if (hRasterLayer == nullptr || hMetadataLayer == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot find metadata and/or raster tables"); - GDALClose(hDS); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Check if there is overlapping data and warn the user */ - /* -------------------------------------------------------------------- */ - double minx = adfGeoTransform[0]; - double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1]; - double maxy = adfGeoTransform[3]; - double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5]; - - osSQL.Printf( - "SELECT COUNT(geometry) FROM \"%s\" " - "WHERE rowid IN " - "(SELECT pkid FROM \"idx_%s_metadata_geometry\" " - "WHERE %s) AND %s", - osMetadataLayer.c_str(), osTableName.c_str(), - RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(), - RasterliteGetPixelSizeCond(adfGeoTransform[1], -adfGeoTransform[5]) - .c_str()); - - int nOverlappingGeoms = 0; - OGRLayerH hCountLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hCountLyr) - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hCountLyr); - if (hFeat) - { - nOverlappingGeoms = OGR_F_GetFieldAsInteger(hFeat, 0); - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hCountLyr); - } - - if (nOverlappingGeoms != 0) - { - CPLError(CE_Warning, CPLE_AppDefined, - "Raster tiles already exist in the %s table within " - "the extent of the data to be inserted in", - osTableName.c_str()); - } - - /* -------------------------------------------------------------------- */ - /* Iterate over blocks to add data into raster and metadata tables */ - /* -------------------------------------------------------------------- */ - int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize; - int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize; - - GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType(); - int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8; - GByte *pabyMEMDSBuffer = reinterpret_cast(VSIMalloc3( - nBlockXSize, nBlockYSize, cpl::fits_on(nBands * nDataTypeSize))); - if (pabyMEMDSBuffer == nullptr) - { - GDALClose(hDS); - return nullptr; - } - - const CPLString osTempFileName( - VSIMemGenerateHiddenFilename("rasterlite_tile")); - - int nTileId = 0; - int nBlocks = 0; - int nTotalBlocks = nXBlocks * nYBlocks; - - char **papszTileDriverOptions = - RasterliteGetTileDriverOptions(papszOptions); - - GDALDatasetExecuteSQL(hDS, "BEGIN", nullptr, nullptr); - - CPLErr eErr = CE_None; - for (int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks; - nBlockYOff++) - { - for (int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks; - nBlockXOff++) - { - /* -------------------------------------------------------------------- - */ - /* Create in-memory tile */ - /* -------------------------------------------------------------------- - */ - int nReqXSize = nBlockXSize; - int nReqYSize = nBlockYSize; - if ((nBlockXOff + 1) * nBlockXSize > nXSize) - nReqXSize = nXSize - nBlockXOff * nBlockXSize; - if ((nBlockYOff + 1) * nBlockYSize > nYSize) - nReqYSize = nYSize - nBlockYOff * nBlockYSize; - - eErr = poSrcDS->RasterIO( - GF_Read, nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize, - nReqXSize, nReqYSize, pabyMEMDSBuffer, nReqXSize, nReqYSize, - eDataType, nBands, nullptr, 0, 0, 0, nullptr); - if (eErr != CE_None) - { - break; - } - - auto poMEMDS = std::unique_ptr(MEMDataset::Create( - "", nReqXSize, nReqYSize, 0, eDataType, nullptr)); - for (int iBand = 0; iBand < nBands; iBand++) - { - auto hBand = MEMCreateRasterBandEx( - poMEMDS.get(), iBand + 1, - pabyMEMDSBuffer + - iBand * nDataTypeSize * nReqXSize * nReqYSize, - eDataType, 0, 0, false); - poMEMDS->AddMEMBand(hBand); - } - - GDALDatasetH hOutDS = GDALCreateCopy( - hTileDriver, osTempFileName.c_str(), poMEMDS.get(), FALSE, - papszTileDriverOptions, nullptr, nullptr); - - if (!hOutDS) - { - eErr = CE_Failure; - break; - } - GDALClose(hOutDS); - - /* -------------------------------------------------------------------- - */ - /* Insert new entry into raster table */ - /* -------------------------------------------------------------------- - */ - vsi_l_offset nDataLength = 0; - GByte *pabyData = VSIGetMemFileBuffer(osTempFileName.c_str(), - &nDataLength, FALSE); - - OGRFeatureH hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hRasterLayer)); - OGR_F_SetFieldBinary(hFeat, 0, static_cast(nDataLength), - pabyData); - - if (OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - /* Query raster ID to set it as the ID of the associated metadata */ - int nRasterID = static_cast(OGR_F_GetFID(hFeat)); - - OGR_F_Destroy(hFeat); - - VSIUnlink(osTempFileName.c_str()); - if (eErr == CE_Failure) - break; - - /* -------------------------------------------------------------------- - */ - /* Insert new entry into metadata table */ - /* -------------------------------------------------------------------- - */ - - hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hMetadataLayer)); - OGR_F_SetFID(hFeat, nRasterID); - OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS)); - OGR_F_SetFieldInteger(hFeat, 1, nTileId++); - OGR_F_SetFieldInteger(hFeat, 2, nReqXSize); - OGR_F_SetFieldInteger(hFeat, 3, nReqYSize); - OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]); - OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]); - - minx = adfGeoTransform[0] + - (nBlockXSize * nBlockXOff) * adfGeoTransform[1]; - maxx = adfGeoTransform[0] + - (nBlockXSize * nBlockXOff + nReqXSize) * adfGeoTransform[1]; - maxy = adfGeoTransform[3] + - (nBlockYSize * nBlockYOff) * adfGeoTransform[5]; - miny = adfGeoTransform[3] + - (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5]; - - OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon); - OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing); - OGR_G_AddPoint_2D(hLinearRing, minx, miny); - OGR_G_AddPoint_2D(hLinearRing, minx, maxy); - OGR_G_AddPoint_2D(hLinearRing, maxx, maxy); - OGR_G_AddPoint_2D(hLinearRing, maxx, miny); - OGR_G_AddPoint_2D(hLinearRing, minx, miny); - OGR_G_AddGeometryDirectly(hRectangle, hLinearRing); - - OGR_F_SetGeometryDirectly(hFeat, hRectangle); - - if (OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - OGR_F_Destroy(hFeat); - - nBlocks++; - if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks, - nullptr, pProgressData)) - eErr = CE_Failure; - } - } - - VSIUnlink(osTempFileName); - VSIUnlink((osTempFileName + ".aux.xml").c_str()); - - if (eErr == CE_None) - GDALDatasetExecuteSQL(hDS, "COMMIT", nullptr, nullptr); - else - GDALDatasetExecuteSQL(hDS, "ROLLBACK", nullptr, nullptr); - - CSLDestroy(papszTileDriverOptions); - - VSIFree(pabyMEMDSBuffer); - - GDALClose(hDS); - - if (eErr == CE_Failure) - return nullptr; - - return GDALDataset::FromHandle(GDALOpen(pszFilename, GA_Update)); -} - -/************************************************************************/ -/* RasterliteDelete () */ -/************************************************************************/ - -CPLErr RasterliteDelete(CPL_UNUSED const char *pszFilename) -{ - return CE_None; -} diff --git a/frmts/rasterlite/rasterlitedataset.cpp b/frmts/rasterlite/rasterlitedataset.cpp deleted file mode 100644 index 6709c2da0cb9..000000000000 --- a/frmts/rasterlite/rasterlitedataset.cpp +++ /dev/null @@ -1,1496 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "gdal_frmts.h" -#include "ogr_api.h" -#include "ogr_srs_api.h" - -#include "rasterlitedataset.h" -#include "rasterlitedrivercore.h" - -#include -#include - -/************************************************************************/ -/* RasterliteOpenSQLiteDB() */ -/************************************************************************/ - -GDALDatasetH RasterliteOpenSQLiteDB(const char *pszFilename, GDALAccess eAccess) -{ - const char *const apszAllowedDrivers[] = {"SQLITE", nullptr}; - return GDALOpenEx(pszFilename, - GDAL_OF_VECTOR | - ((eAccess == GA_Update) ? GDAL_OF_UPDATE : 0), - apszAllowedDrivers, nullptr, nullptr); -} - -/************************************************************************/ -/* RasterliteGetPixelSizeCond() */ -/************************************************************************/ - -CPLString RasterliteGetPixelSizeCond(double dfPixelXSize, double dfPixelYSize, - const char *pszTablePrefixWithDot) -{ - CPLString osCond; - osCond.Printf("((%spixel_x_size >= %s AND %spixel_x_size <= %s) AND " - "(%spixel_y_size >= %s AND %spixel_y_size <= %s))", - pszTablePrefixWithDot, - CPLString().FormatC(dfPixelXSize - 1e-15, "%.15f").c_str(), - pszTablePrefixWithDot, - CPLString().FormatC(dfPixelXSize + 1e-15, "%.15f").c_str(), - pszTablePrefixWithDot, - CPLString().FormatC(dfPixelYSize - 1e-15, "%.15f").c_str(), - pszTablePrefixWithDot, - CPLString().FormatC(dfPixelYSize + 1e-15, "%.15f").c_str()); - return osCond; -} - -/************************************************************************/ -/* RasterliteGetSpatialFilterCond() */ -/************************************************************************/ - -CPLString RasterliteGetSpatialFilterCond(double minx, double miny, double maxx, - double maxy) -{ - CPLString osCond; - osCond.Printf("(xmin < %s AND xmax > %s AND ymin < %s AND ymax > %s)", - CPLString().FormatC(maxx, "%.15f").c_str(), - CPLString().FormatC(minx, "%.15f").c_str(), - CPLString().FormatC(maxy, "%.15f").c_str(), - CPLString().FormatC(miny, "%.15f").c_str()); - return osCond; -} - -/************************************************************************/ -/* RasterliteBand() */ -/************************************************************************/ - -RasterliteBand::RasterliteBand(RasterliteDataset *poDSIn, int nBandIn, - GDALDataType eDataTypeIn, int nBlockXSizeIn, - int nBlockYSizeIn) -{ - poDS = poDSIn; - nBand = nBandIn; - eDataType = eDataTypeIn; - nBlockXSize = nBlockXSizeIn; - nBlockYSize = nBlockYSizeIn; -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -// #define RASTERLITE_DEBUG - -CPLErr RasterliteBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - - double minx = poGDS->adfGeoTransform[0] + - nBlockXOff * nBlockXSize * poGDS->adfGeoTransform[1]; - double maxx = poGDS->adfGeoTransform[0] + - (nBlockXOff + 1) * nBlockXSize * poGDS->adfGeoTransform[1]; - double maxy = poGDS->adfGeoTransform[3] + - nBlockYOff * nBlockYSize * poGDS->adfGeoTransform[5]; - double miny = poGDS->adfGeoTransform[3] + - (nBlockYOff + 1) * nBlockYSize * poGDS->adfGeoTransform[5]; - int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8; - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf("nBlockXOff = %d, nBlockYOff = %d, nBlockXSize = %d, " /*ok*/ - "nBlockYSize = %d\n" - "minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n", - nBlockXOff, nBlockYOff, nBlockXSize, nBlockYSize, minx, miny, - maxx, maxy); - } -#endif - - CPLString osSQL; - osSQL.Printf("SELECT m.geometry, r.raster, m.id, m.width, m.height FROM " - "\"%s_metadata\" AS m, " - "\"%s_rasters\" AS r WHERE m.rowid IN " - "(SELECT pkid FROM \"idx_%s_metadata_geometry\" " - "WHERE %s) AND %s AND r.id = m.id", - poGDS->osTableName.c_str(), poGDS->osTableName.c_str(), - poGDS->osTableName.c_str(), - RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(), - RasterliteGetPixelSizeCond(poGDS->adfGeoTransform[1], - -poGDS->adfGeoTransform[5], "m.") - .c_str()); - - OGRLayerH hSQLLyr = - GDALDatasetExecuteSQL(poGDS->hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - { - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * nDataTypeSize); - return CE_None; - } - - const CPLString osMemFileName( - VSIMemGenerateHiddenFilename("rasterlite_tile")); - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf("nTiles = %d\n", /*ok*/ - static_cast(OGR_L_GetFeatureCount(hSQLLyr, TRUE))); - } -#endif - - bool bHasFoundTile = false; - bool bHasMemsetTile = false; - - OGRFeatureH hFeat; - CPLErr eErr = CE_None; - while ((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != nullptr && - eErr == CE_None) - { - OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat); - if (hGeom == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "null geometry found"); - OGR_F_Destroy(hFeat); - GDALDatasetReleaseResultSet(poGDS->hDS, hSQLLyr); - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * - nDataTypeSize); - return CE_Failure; - } - - OGREnvelope oEnvelope; - OGR_G_GetEnvelope(hGeom, &oEnvelope); - - const int nTileId = OGR_F_GetFieldAsInteger(hFeat, 1); - if (poGDS->m_nLastBadTileId == nTileId) - { - OGR_F_Destroy(hFeat); - continue; - } - const int nTileXSize = OGR_F_GetFieldAsInteger(hFeat, 2); - const int nTileYSize = OGR_F_GetFieldAsInteger(hFeat, 3); - constexpr int MAX_INT_DIV_2 = std::numeric_limits::max() / 2; - if (nTileXSize <= 0 || nTileXSize >= MAX_INT_DIV_2 || nTileYSize <= 0 || - nTileYSize >= MAX_INT_DIV_2) - { - CPLError(CE_Failure, CPLE_AppDefined, "invalid tile size"); - OGR_F_Destroy(hFeat); - GDALDatasetReleaseResultSet(poGDS->hDS, hSQLLyr); - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * - nDataTypeSize); - return CE_Failure; - } - - const double dfDstXOff = - (oEnvelope.MinX - minx) / poGDS->adfGeoTransform[1]; - const double dfDstYOff = - (maxy - oEnvelope.MaxY) / (-poGDS->adfGeoTransform[5]); - constexpr int MIN_INT_DIV_2 = std::numeric_limits::min() / 2; - if (!(dfDstXOff >= MIN_INT_DIV_2 && dfDstXOff <= MAX_INT_DIV_2) || - !(dfDstYOff >= MIN_INT_DIV_2 && dfDstYOff <= MAX_INT_DIV_2)) - { - CPLError(CE_Failure, CPLE_AppDefined, "invalid geometry"); - OGR_F_Destroy(hFeat); - GDALDatasetReleaseResultSet(poGDS->hDS, hSQLLyr); - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * - nDataTypeSize); - return CE_Failure; - } - int nDstXOff = static_cast(dfDstXOff + 0.5); - int nDstYOff = static_cast(dfDstYOff + 0.5); - - int nReqXSize = nTileXSize; - int nReqYSize = nTileYSize; - - int nSrcXOff, nSrcYOff; - - if (nDstXOff >= 0) - { - nSrcXOff = 0; - } - else - { - nSrcXOff = -nDstXOff; - nReqXSize += nDstXOff; - nDstXOff = 0; - } - - if (nDstYOff >= 0) - { - nSrcYOff = 0; - } - else - { - nSrcYOff = -nDstYOff; - nReqYSize += nDstYOff; - nDstYOff = 0; - } - - if (nDstXOff + nReqXSize > nBlockXSize) - nReqXSize = nBlockXSize - nDstXOff; - - if (nDstYOff + nReqYSize > nBlockYSize) - nReqYSize = nBlockYSize - nDstYOff; - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf(/*ok*/ - "id = %d, minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n" - "nDstXOff = %d, nDstYOff = %d, nSrcXOff = %d, nSrcYOff = " - "%d, " - "nReqXSize=%d, nReqYSize=%d\n", - nTileId, oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, - oEnvelope.MaxY, nDstXOff, nDstYOff, nSrcXOff, nSrcYOff, - nReqXSize, nReqYSize); - } -#endif - - if (nReqXSize > 0 && nReqYSize > 0 && nSrcXOff < nTileXSize && - nSrcYOff < nTileYSize) - { - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf("id = %d, selected !\n", nTileId); /*ok*/ - } -#endif - int nDataSize = 0; - GByte *pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize); - - VSILFILE *fp = VSIFileFromMemBuffer(osMemFileName.c_str(), pabyData, - nDataSize, FALSE); - VSIFCloseL(fp); - - GDALDatasetH hDSTile = GDALOpenEx(osMemFileName.c_str(), - GDAL_OF_RASTER | GDAL_OF_INTERNAL, - nullptr, nullptr, nullptr); - int nTileBands = 0; - if (hDSTile && (nTileBands = GDALGetRasterCount(hDSTile)) == 0) - { - GDALClose(hDSTile); - hDSTile = nullptr; - } - if (hDSTile == nullptr) - { - poGDS->m_nLastBadTileId = nTileId; - CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d", - nTileId); - } - - int nReqBand = 1; - if (nTileBands == poGDS->nBands) - nReqBand = nBand; - else if (eDataType == GDT_Byte && nTileBands == 1 && - poGDS->nBands == 3) - nReqBand = 1; - else - { - poGDS->m_nLastBadTileId = nTileId; - GDALClose(hDSTile); - hDSTile = nullptr; - } - - if (hDSTile) - { - if (GDALGetRasterXSize(hDSTile) != nTileXSize || - GDALGetRasterYSize(hDSTile) != nTileYSize) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Invalid dimensions for tile %d", nTileId); - poGDS->m_nLastBadTileId = nTileId; - GDALClose(hDSTile); - hDSTile = nullptr; - } - } - - if (hDSTile) - { - bHasFoundTile = true; - - bool bHasJustMemsetTileBand1 = false; - - /* If the source tile doesn't fit the entire block size, then */ - /* we memset 0 before */ - if (!(nDstXOff == 0 && nDstYOff == 0 && - nReqXSize == nBlockXSize && nReqYSize == nBlockYSize) && - !bHasMemsetTile) - { - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * - nDataTypeSize); - bHasMemsetTile = true; - bHasJustMemsetTileBand1 = true; - } - - GDALColorTable *poTileCT = reinterpret_cast( - GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1))); - unsigned char *pabyTranslationTable = nullptr; - if (poGDS->nBands == 1 && poGDS->poCT != nullptr && - poTileCT != nullptr) - { - pabyTranslationTable = reinterpret_cast( - GDALGetRasterBand(hDSTile, 1)) - ->GetIndexColorTranslationTo( - this, nullptr, nullptr); - } - - /* -------------------------------------------------------------------- - */ - /* Read tile data */ - /* -------------------------------------------------------------------- - */ - eErr = GDALRasterIO( - GDALGetRasterBand(hDSTile, nReqBand), GF_Read, nSrcXOff, - nSrcYOff, nReqXSize, nReqYSize, - reinterpret_cast(pImage) + - (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize, - nReqXSize, nReqYSize, eDataType, nDataTypeSize, - nBlockXSize * nDataTypeSize); - - if (eDataType == GDT_Byte && pabyTranslationTable) - { - /* -------------------------------------------------------------------- - */ - /* Convert from tile CT to band CT */ - /* -------------------------------------------------------------------- - */ - for (int j = nDstYOff; j < nDstYOff + nReqYSize; j++) - { - for (int i = nDstXOff; i < nDstXOff + nReqXSize; i++) - { - GByte *pPixel = reinterpret_cast(pImage) + - i + j * nBlockXSize; - *pPixel = pabyTranslationTable[*pPixel]; - } - } - CPLFree(pabyTranslationTable); - pabyTranslationTable = nullptr; - } - else if (eDataType == GDT_Byte && nTileBands == 1 && - poGDS->nBands == 3 && poTileCT != nullptr) - { - /* -------------------------------------------------------------------- - */ - /* Expand from PCT to RGB */ - /* -------------------------------------------------------------------- - */ - GByte abyCT[256]; - const int nEntries = - std::min(256, poTileCT->GetColorEntryCount()); - for (int i = 0; i < nEntries; i++) - { - const GDALColorEntry *psEntry = - poTileCT->GetColorEntry(i); - if (nBand == 1) - abyCT[i] = static_cast(psEntry->c1); - else if (nBand == 2) - abyCT[i] = static_cast(psEntry->c2); - else - abyCT[i] = static_cast(psEntry->c3); - } - for (int i = nEntries; i < 256; i++) - abyCT[i] = 0; - - for (int j = nDstYOff; j < nDstYOff + nReqYSize; j++) - { - for (int i = nDstXOff; i < nDstXOff + nReqXSize; i++) - { - GByte *pPixel = reinterpret_cast(pImage) + - i + j * nBlockXSize; - *pPixel = abyCT[*pPixel]; - } - } - } - - /* -------------------------------------------------------------------- - */ - /* Put in the block cache the data for this block into - * other bands */ - /* while the underlying dataset is opened */ - /* -------------------------------------------------------------------- - */ - if (nBand == 1 && poGDS->nBands > 1) - { - for (int iOtherBand = 2; - iOtherBand <= poGDS->nBands && eErr == CE_None; - iOtherBand++) - { - GDALRasterBlock *poBlock = - poGDS->GetRasterBand(iOtherBand) - ->GetLockedBlockRef(nBlockXOff, nBlockYOff, - TRUE); - if (poBlock == nullptr) - break; - - GByte *pabySrcBlock = - reinterpret_cast(poBlock->GetDataRef()); - if (pabySrcBlock == nullptr) - { - poBlock->DropLock(); - break; - } - - if (nTileBands == 1) - nReqBand = 1; - else - nReqBand = iOtherBand; - - if (bHasJustMemsetTileBand1) - memset(pabySrcBlock, 0, - static_cast(nBlockXSize) * - nBlockYSize * nDataTypeSize); - - /* -------------------------------------------------------------------- - */ - /* Read tile data */ - /* -------------------------------------------------------------------- - */ - eErr = GDALRasterIO( - GDALGetRasterBand(hDSTile, nReqBand), GF_Read, - nSrcXOff, nSrcYOff, nReqXSize, nReqYSize, - reinterpret_cast(pabySrcBlock) + - (nDstXOff + nDstYOff * nBlockXSize) * - nDataTypeSize, - nReqXSize, nReqYSize, eDataType, nDataTypeSize, - nBlockXSize * nDataTypeSize); - - if (eDataType == GDT_Byte && nTileBands == 1 && - poGDS->nBands == 3 && poTileCT != nullptr) - { - /* -------------------------------------------------------------------- - */ - /* Expand from PCT to RGB */ - /* -------------------------------------------------------------------- - */ - - GByte abyCT[256]; - const int nEntries = - std::min(256, poTileCT->GetColorEntryCount()); - for (int i = 0; i < nEntries; i++) - { - const GDALColorEntry *psEntry = - poTileCT->GetColorEntry(i); - if (iOtherBand == 2) - abyCT[i] = static_cast(psEntry->c2); - else - abyCT[i] = static_cast(psEntry->c3); - } - for (int i = nEntries; i < 256; i++) - abyCT[i] = 0; - - for (int j = nDstYOff; j < nDstYOff + nReqYSize; - j++) - { - for (int i = nDstXOff; i < nDstXOff + nReqXSize; - i++) - { - GByte *pPixel = reinterpret_cast( - pabySrcBlock) + - i + j * nBlockXSize; - *pPixel = abyCT[*pPixel]; - } - } - } - - poBlock->DropLock(); - } - } - GDALClose(hDSTile); - } - - VSIUnlink(osMemFileName.c_str()); - } - else - { -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf("id = %d, NOT selected !\n", nTileId); /*ok*/ - } -#endif - } - OGR_F_Destroy(hFeat); - } - - VSIUnlink(osMemFileName.c_str()); - VSIUnlink((osMemFileName + ".aux.xml").c_str()); - - if (!bHasFoundTile) - { - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * nDataTypeSize); - } - - GDALDatasetReleaseResultSet(poGDS->hDS, hSQLLyr); - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - printf("\n"); /*ok*/ -#endif - - return eErr; -} - -/************************************************************************/ -/* GetOverviewCount() */ -/************************************************************************/ - -int RasterliteBand::GetOverviewCount() -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - - if (poGDS->nLimitOvrCount >= 0) - return poGDS->nLimitOvrCount; - else if (poGDS->nResolutions > 1) - return poGDS->nResolutions - 1; - else - return GDALPamRasterBand::GetOverviewCount(); -} - -/************************************************************************/ -/* GetOverview() */ -/************************************************************************/ - -GDALRasterBand *RasterliteBand::GetOverview(int nLevel) -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - - if (poGDS->nLimitOvrCount >= 0) - { - if (nLevel < 0 || nLevel >= poGDS->nLimitOvrCount) - return nullptr; - } - - if (poGDS->nResolutions == 1) - return GDALPamRasterBand::GetOverview(nLevel); - - if (nLevel < 0 || nLevel >= poGDS->nResolutions - 1) - return nullptr; - - GDALDataset *poOvrDS = poGDS->papoOverviews[nLevel]; - if (poOvrDS) - return poOvrDS->GetRasterBand(nBand); - - return nullptr; -} - -/************************************************************************/ -/* GetColorInterpretation() */ -/************************************************************************/ - -GDALColorInterp RasterliteBand::GetColorInterpretation() -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - if (poGDS->nBands == 1) - { - if (poGDS->poCT != nullptr) - return GCI_PaletteIndex; - - return GCI_GrayIndex; - } - else if (poGDS->nBands == 3) - { - if (nBand == 1) - return GCI_RedBand; - else if (nBand == 2) - return GCI_GreenBand; - else if (nBand == 3) - return GCI_BlueBand; - } - - return GCI_Undefined; -} - -/************************************************************************/ -/* GetColorTable() */ -/************************************************************************/ - -GDALColorTable *RasterliteBand::GetColorTable() -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - if (poGDS->nBands == 1) - return poGDS->poCT; - - return nullptr; -} - -/************************************************************************/ -/* RasterliteDataset() */ -/************************************************************************/ - -RasterliteDataset::RasterliteDataset() - : bMustFree(FALSE), poMainDS(nullptr), nLevel(0), papszMetadata(nullptr), - papszImageStructure(CSLAddString(nullptr, "INTERLEAVE=PIXEL")), - papszSubDatasets(nullptr), nResolutions(0), padfXResolutions(nullptr), - padfYResolutions(nullptr), papoOverviews(nullptr), nLimitOvrCount(-1), - bValidGeoTransform(FALSE), poCT(nullptr), bCheckForExistingOverview(TRUE), - hDS(nullptr) -{ - m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - memset(adfGeoTransform, 0, sizeof(adfGeoTransform)); -} - -/************************************************************************/ -/* RasterliteDataset() */ -/************************************************************************/ - -RasterliteDataset::RasterliteDataset(RasterliteDataset *poMainDSIn, - int nLevelIn) - : bMustFree(FALSE), poMainDS(poMainDSIn), nLevel(nLevelIn), - papszMetadata(poMainDSIn->papszMetadata), - papszImageStructure(poMainDSIn->papszImageStructure), - papszSubDatasets(poMainDS->papszSubDatasets), - nResolutions(poMainDSIn->nResolutions - nLevelIn), - padfXResolutions(poMainDSIn->padfXResolutions + nLevelIn), - padfYResolutions(poMainDSIn->padfYResolutions + nLevelIn), - papoOverviews(poMainDSIn->papoOverviews + nLevelIn), nLimitOvrCount(-1), - bValidGeoTransform(TRUE), m_oSRS(poMainDSIn->m_oSRS), - poCT(poMainDSIn->poCT), osTableName(poMainDSIn->osTableName), - osFileName(poMainDSIn->osFileName), bCheckForExistingOverview(TRUE), - // TODO: osOvrFileName? - hDS(poMainDSIn->hDS) -{ - nRasterXSize = static_cast( - poMainDS->nRasterXSize * - (poMainDS->padfXResolutions[0] / padfXResolutions[0]) + - 0.5); - nRasterYSize = static_cast( - poMainDS->nRasterYSize * - (poMainDS->padfYResolutions[0] / padfYResolutions[0]) + - 0.5); - - memcpy(adfGeoTransform, poMainDS->adfGeoTransform, 6 * sizeof(double)); - adfGeoTransform[1] = padfXResolutions[0]; - adfGeoTransform[5] = -padfYResolutions[0]; -} - -/************************************************************************/ -/* ~RasterliteDataset() */ -/************************************************************************/ - -RasterliteDataset::~RasterliteDataset() -{ - RasterliteDataset::CloseDependentDatasets(); -} - -/************************************************************************/ -/* CloseDependentDatasets() */ -/************************************************************************/ - -int RasterliteDataset::CloseDependentDatasets() -{ - int bRet = GDALPamDataset::CloseDependentDatasets(); - - if (poMainDS == nullptr && !bMustFree) - { - CSLDestroy(papszMetadata); - papszMetadata = nullptr; - CSLDestroy(papszSubDatasets); - papszSubDatasets = nullptr; - CSLDestroy(papszImageStructure); - papszImageStructure = nullptr; - - if (papoOverviews) - { - for (int i = 1; i < nResolutions; i++) - { - if (papoOverviews[i - 1] != nullptr && - papoOverviews[i - 1]->bMustFree) - { - papoOverviews[i - 1]->poMainDS = nullptr; - } - delete papoOverviews[i - 1]; - } - CPLFree(papoOverviews); - papoOverviews = nullptr; - nResolutions = 0; - bRet = TRUE; - } - - if (hDS != nullptr) - GDALClose(hDS); - hDS = nullptr; - - CPLFree(padfXResolutions); - CPLFree(padfYResolutions); - padfXResolutions = nullptr; - padfYResolutions = nullptr; - - delete poCT; - poCT = nullptr; - } - else if (poMainDS != nullptr && bMustFree) - { - poMainDS->papoOverviews[nLevel - 1] = nullptr; - delete poMainDS; - poMainDS = nullptr; - bRet = TRUE; - } - - return bRet; -} - -/************************************************************************/ -/* AddSubDataset() */ -/************************************************************************/ - -void RasterliteDataset::AddSubDataset(const char *pszDSName) -{ - char szName[80]; - const int nCount = CSLCount(papszSubDatasets) / 2; - - snprintf(szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount + 1); - papszSubDatasets = CSLSetNameValue(papszSubDatasets, szName, pszDSName); - - snprintf(szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount + 1); - papszSubDatasets = CSLSetNameValue(papszSubDatasets, szName, pszDSName); -} - -/************************************************************************/ -/* GetMetadataDomainList() */ -/************************************************************************/ - -char **RasterliteDataset::GetMetadataDomainList() -{ - return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(), - TRUE, "SUBDATASETS", "IMAGE_STRUCTURE", - nullptr); -} - -/************************************************************************/ -/* GetMetadata() */ -/************************************************************************/ - -char **RasterliteDataset::GetMetadata(const char *pszDomain) - -{ - if (pszDomain != nullptr && EQUAL(pszDomain, "SUBDATASETS")) - return papszSubDatasets; - - if (CSLCount(papszSubDatasets) < 2 && pszDomain != nullptr && - EQUAL(pszDomain, "IMAGE_STRUCTURE")) - return papszImageStructure; - - if (pszDomain == nullptr || EQUAL(pszDomain, "")) - return papszMetadata; - - return GDALPamDataset::GetMetadata(pszDomain); -} - -/************************************************************************/ -/* GetMetadataItem() */ -/************************************************************************/ - -const char *RasterliteDataset::GetMetadataItem(const char *pszName, - const char *pszDomain) -{ - if (pszDomain != nullptr && EQUAL(pszDomain, "OVERVIEWS")) - { - if (nResolutions > 1 || CSLCount(papszSubDatasets) > 2) - return nullptr; - - osOvrFileName.Printf("%s_%s", osFileName.c_str(), osTableName.c_str()); - if (bCheckForExistingOverview == FALSE || - CPLCheckForFile(const_cast(osOvrFileName.c_str()), nullptr)) - return osOvrFileName.c_str(); - - return nullptr; - } - - return GDALPamDataset::GetMetadataItem(pszName, pszDomain); -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr RasterliteDataset::GetGeoTransform(double *padfGeoTransform) -{ - if (bValidGeoTransform) - { - memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double)); - return CE_None; - } - - return CE_Failure; -} - -/************************************************************************/ -/* GetSpatialRef() */ -/************************************************************************/ - -const OGRSpatialReference *RasterliteDataset::GetSpatialRef() const -{ - return m_oSRS.IsEmpty() ? nullptr : &m_oSRS; -} - -/************************************************************************/ -/* GetFileList() */ -/************************************************************************/ - -char **RasterliteDataset::GetFileList() -{ - char **papszFileList = CSLAddString(nullptr, osFileName); - return papszFileList; -} - -/************************************************************************/ -/* GetBlockParams() */ -/************************************************************************/ - -int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevelIn, - int *pnBands, GDALDataType *peDataType, - int *pnBlockXSize, int *pnBlockYSize) -{ - CPLString osSQL; - osSQL.Printf("SELECT m.geometry, r.raster, m.id " - "FROM \"%s_metadata\" AS m, \"%s_rasters\" AS r " - "WHERE %s AND r.id = m.id", - osTableName.c_str(), osTableName.c_str(), - RasterliteGetPixelSizeCond(padfXResolutions[nLevelIn], - padfYResolutions[nLevelIn], "m.") - .c_str()); - - OGRLayerH hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - { - return FALSE; - } - - OGRFeatureH hFeat = OGR_L_GetNextFeature(hRasterLyr); - if (hFeat == nullptr) - { - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - return FALSE; - } - - int nDataSize; - GByte *pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize); - - if (nDataSize > 32 && - STARTS_WITH_CI(reinterpret_cast(pabyData), - "StartWaveletsImage$$")) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Rasterlite driver no longer support WAVELET compressed " - "images"); - OGR_F_Destroy(hFeat); - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - return FALSE; - } - - const CPLString osMemFileName( - VSIMemGenerateHiddenFilename("rasterlite_tile")); - VSILFILE *fp = - VSIFileFromMemBuffer(osMemFileName.c_str(), pabyData, nDataSize, FALSE); - VSIFCloseL(fp); - - GDALDatasetH hDSTile = GDALOpen(osMemFileName.c_str(), GA_ReadOnly); - if (hDSTile) - { - *pnBands = GDALGetRasterCount(hDSTile); - if (*pnBands == 0) - { - GDALClose(hDSTile); - hDSTile = nullptr; - } - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d", - OGR_F_GetFieldAsInteger(hFeat, 1)); - } - - if (hDSTile) - { - *peDataType = GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1)); - - for (int iBand = 2; iBand <= *pnBands; iBand++) - { - if (*peDataType != - GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1))) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Band types must be identical"); - GDALClose(hDSTile); - hDSTile = nullptr; - goto end; - } - } - - *pnBlockXSize = GDALGetRasterXSize(hDSTile); - *pnBlockYSize = GDALGetRasterYSize(hDSTile); - if (CSLFindName(papszImageStructure, "COMPRESSION") == -1) - { - const char *pszCompression = - GDALGetMetadataItem(hDSTile, "COMPRESSION", "IMAGE_STRUCTURE"); - if (pszCompression != nullptr && EQUAL(pszCompression, "JPEG")) - papszImageStructure = - CSLAddString(papszImageStructure, "COMPRESSION=JPEG"); - } - - if (CSLFindName(papszMetadata, "TILE_FORMAT") == -1) - { - papszMetadata = CSLSetNameValue( - papszMetadata, "TILE_FORMAT", - GDALGetDriverShortName(GDALGetDatasetDriver(hDSTile))); - } - - if (*pnBands == 1 && this->poCT == nullptr) - { - GDALColorTable *l_poCT = reinterpret_cast( - GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1))); - if (l_poCT) - this->poCT = l_poCT->Clone(); - } - - GDALClose(hDSTile); - } -end: - VSIUnlink(osMemFileName.c_str()); - VSIUnlink((osMemFileName + ".aux.xml").c_str()); - - OGR_F_Destroy(hFeat); - - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - - return hDSTile != nullptr; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *RasterliteDataset::Open(GDALOpenInfo *poOpenInfo) -{ - if (RasterliteDriverIdentify(poOpenInfo) == FALSE) - return nullptr; - - CPLString osFileName; - CPLString osTableName; - int nLevel = 0; - double minx = 0.0; - double miny = 0.0; - double maxx = 0.0; - double maxy = 0.0; - int bMinXSet = FALSE; - int bMinYSet = FALSE; - int bMaxXSet = FALSE; - int bMaxYSet = FALSE; - int nReqBands = 0; - -/* -------------------------------------------------------------------- */ -/* Parse "file name" */ -/* -------------------------------------------------------------------- */ -#ifdef ENABLE_SQL_SQLITE_FORMAT - if (poOpenInfo->pabyHeader && - STARTS_WITH((const char *)poOpenInfo->pabyHeader, "-- SQL RASTERLITE")) - { - osFileName = poOpenInfo->pszFilename; - } - else -#endif - if (poOpenInfo->nHeaderBytes >= 1024 && poOpenInfo->pabyHeader && - STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, - "SQLite Format 3")) - { - osFileName = poOpenInfo->pszFilename; - } - else - { - char **papszTokens = CSLTokenizeStringComplex( - poOpenInfo->pszFilename + 11, ",", FALSE, FALSE); - int nTokens = CSLCount(papszTokens); - if (nTokens == 0) - { - CSLDestroy(papszTokens); - return nullptr; - } - - osFileName = papszTokens[0]; - - for (int i = 1; i < nTokens; i++) - { - if (STARTS_WITH_CI(papszTokens[i], "table=")) - osTableName = papszTokens[i] + 6; - else if (STARTS_WITH_CI(papszTokens[i], "level=")) - nLevel = atoi(papszTokens[i] + 6); - else if (STARTS_WITH_CI(papszTokens[i], "minx=")) - { - bMinXSet = TRUE; - minx = CPLAtof(papszTokens[i] + 5); - } - else if (STARTS_WITH_CI(papszTokens[i], "miny=")) - { - bMinYSet = TRUE; - miny = CPLAtof(papszTokens[i] + 5); - } - else if (STARTS_WITH_CI(papszTokens[i], "maxx=")) - { - bMaxXSet = TRUE; - maxx = CPLAtof(papszTokens[i] + 5); - } - else if (STARTS_WITH_CI(papszTokens[i], "maxy=")) - { - bMaxYSet = TRUE; - maxy = CPLAtof(papszTokens[i] + 5); - } - else if (STARTS_WITH_CI(papszTokens[i], "bands=")) - { - nReqBands = atoi(papszTokens[i] + 6); - } - else - { - CPLError(CE_Warning, CPLE_AppDefined, "Invalid option : %s", - papszTokens[i]); - } - } - CSLDestroy(papszTokens); - } - - /* -------------------------------------------------------------------- */ - /* Open underlying OGR DB */ - /* -------------------------------------------------------------------- */ - - GDALDatasetH hDS = - RasterliteOpenSQLiteDB(osFileName.c_str(), poOpenInfo->eAccess); - CPLDebug("RASTERLITE", "SQLite DB Open"); - - RasterliteDataset *poDS = nullptr; - - if (hDS == nullptr) - goto end; - - if (osTableName.empty()) - { - int nCountSubdataset = 0; - const int nLayers = GDALDatasetGetLayerCount(hDS); - /* -------------------------------------------------------------------- - */ - /* Add raster layers as subdatasets */ - /* -------------------------------------------------------------------- - */ - for (int i = 0; i < nLayers; i++) - { - OGRLayerH hLyr = GDALDatasetGetLayer(hDS, i); - const std::string osLayerName = OGR_L_GetName(hLyr); - const auto nPosMetadata = osLayerName.find("_metadata"); - if (nPosMetadata != std::string::npos) - { - const std::string osShortName = - osLayerName.substr(0, nPosMetadata); - - const std::string osRasterTableName = - std::string(osShortName).append("_rasters"); - - if (GDALDatasetGetLayerByName(hDS, osRasterTableName.c_str()) != - nullptr) - { - if (poDS == nullptr) - { - poDS = new RasterliteDataset(); - osTableName = osShortName; - } - - std::string osSubdatasetName; - if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:")) - osSubdatasetName += "RASTERLITE:"; - osSubdatasetName += poOpenInfo->pszFilename; - osSubdatasetName += ",table="; - osSubdatasetName += osShortName; - poDS->AddSubDataset(osSubdatasetName.c_str()); - - nCountSubdataset++; - } - } - } - - if (nCountSubdataset == 0) - { - goto end; - } - else if (nCountSubdataset != 1) - { - poDS->SetDescription(poOpenInfo->pszFilename); - goto end; - } - - /* -------------------------------------------------------------------- - */ - /* If just one subdataset, then open it */ - /* -------------------------------------------------------------------- - */ - delete poDS; - poDS = nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Build dataset */ - /* -------------------------------------------------------------------- */ - { - GDALDataType eDataType; - - const CPLString osMetadataTableName = osTableName + "_metadata"; - - OGRLayerH hMetadataLyr = - GDALDatasetGetLayerByName(hDS, osMetadataTableName.c_str()); - if (hMetadataLyr == nullptr) - goto end; - - const CPLString osRasterTableName = osTableName + "_rasters"; - - OGRLayerH hRasterLyr = - GDALDatasetGetLayerByName(hDS, osRasterTableName.c_str()); - if (hRasterLyr == nullptr) - goto end; - - /* -------------------------------------------------------------------- - */ - /* Fetch resolutions */ - /* -------------------------------------------------------------------- - */ - CPLString osSQL; - OGRLayerH hSQLLyr; - int nResolutions = 0; - - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr) - { - osSQL.Printf("SELECT pixel_x_size, pixel_y_size " - "FROM raster_pyramids WHERE table_prefix = '%s' " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - - hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr != nullptr) - { - nResolutions = - static_cast(OGR_L_GetFeatureCount(hSQLLyr, TRUE)); - if (nResolutions == 0) - { - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - hSQLLyr = nullptr; - } - } - } - else - hSQLLyr = nullptr; - - if (hSQLLyr == nullptr) - { - osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size " - "FROM \"%s_metadata\" WHERE pixel_x_size != 0 " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - - hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - goto end; - - nResolutions = - static_cast(OGR_L_GetFeatureCount(hSQLLyr, TRUE)); - - if (nResolutions == 0) - { - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - goto end; - } - } - - /* -------------------------------------------------------------------- - */ - /* Set dataset attributes */ - /* -------------------------------------------------------------------- - */ - - poDS = new RasterliteDataset(); - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->eAccess = poOpenInfo->eAccess; - poDS->osTableName = osTableName; - poDS->osFileName = osFileName; - poDS->hDS = hDS; - - /* poDS will release it from now */ - hDS = nullptr; - - /* -------------------------------------------------------------------- - */ - /* Fetch spatial extent or use the one provided by the user */ - /* -------------------------------------------------------------------- - */ - OGREnvelope oEnvelope; - if (bMinXSet && bMinYSet && bMaxXSet && bMaxYSet) - { - oEnvelope.MinX = minx; - oEnvelope.MinY = miny; - oEnvelope.MaxX = maxx; - oEnvelope.MaxY = maxy; - } - else - { - CPLConfigOptionSetter oSetter("OGR_SQLITE_EXACT_EXTENT", "YES", - false); - OGR_L_GetExtent(hMetadataLyr, &oEnvelope, TRUE); - // printf("minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n", - // oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, - // oEnvelope.MaxY); - } - - /* -------------------------------------------------------------------- - */ - /* Store resolutions */ - /* -------------------------------------------------------------------- - */ - poDS->nResolutions = nResolutions; - poDS->padfXResolutions = reinterpret_cast( - CPLMalloc(sizeof(double) * poDS->nResolutions)); - poDS->padfYResolutions = reinterpret_cast( - CPLMalloc(sizeof(double) * poDS->nResolutions)); - - { - // Add a scope for i. - OGRFeatureH hFeat; - int i = 0; - while ((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != nullptr) - { - poDS->padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0); - poDS->padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1); - - OGR_F_Destroy(hFeat); - -#ifdef RASTERLITE_DEBUG - printf("[%d] xres=%.15f yres=%.15f\n", i, /*ok*/ - poDS->padfXResolutions[i], poDS->padfYResolutions[i]); -#endif - - if (poDS->padfXResolutions[i] <= 0 || - poDS->padfYResolutions[i] <= 0) - { - CPLError(CE_Failure, CPLE_NotSupported, - "res=%d, xres=%.15f, yres=%.15f", i, - poDS->padfXResolutions[i], - poDS->padfYResolutions[i]); - GDALDatasetReleaseResultSet(poDS->hDS, hSQLLyr); - delete poDS; - poDS = nullptr; - goto end; - } - i++; - } - } - - GDALDatasetReleaseResultSet(poDS->hDS, hSQLLyr); - hSQLLyr = nullptr; - - /* -------------------------------------------------------------------- - */ - /* Compute raster size, geotransform and projection */ - /* -------------------------------------------------------------------- - */ - const double dfRasterXSize = - (oEnvelope.MaxX - oEnvelope.MinX) / poDS->padfXResolutions[0] + 0.5; - const double dfRasterYSize = - (oEnvelope.MaxY - oEnvelope.MinY) / poDS->padfYResolutions[0] + 0.5; - if (!(dfRasterXSize >= 1 && dfRasterXSize <= INT_MAX) || - !(dfRasterYSize >= 1 && dfRasterYSize <= INT_MAX)) - { - delete poDS; - poDS = nullptr; - goto end; - } - poDS->nRasterXSize = static_cast(dfRasterXSize); - poDS->nRasterYSize = static_cast(dfRasterYSize); - - poDS->bValidGeoTransform = TRUE; - poDS->adfGeoTransform[0] = oEnvelope.MinX; - poDS->adfGeoTransform[1] = poDS->padfXResolutions[0]; - poDS->adfGeoTransform[2] = 0; - poDS->adfGeoTransform[3] = oEnvelope.MaxY; - poDS->adfGeoTransform[4] = 0; - poDS->adfGeoTransform[5] = -poDS->padfYResolutions[0]; - - OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef(hMetadataLyr); - if (hSRS) - { - poDS->m_oSRS = *(OGRSpatialReference::FromHandle(hSRS)); - } - - /* -------------------------------------------------------------------- - */ - /* Get number of bands and block size */ - /* -------------------------------------------------------------------- - */ - - int nBands; - int nBlockXSize, nBlockYSize; - if (poDS->GetBlockParams(hRasterLyr, 0, &nBands, &eDataType, - &nBlockXSize, &nBlockYSize) == FALSE) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot find block characteristics"); - delete poDS; - poDS = nullptr; - goto end; - } - - if (eDataType == GDT_Byte && nBands == 1 && nReqBands == 3) - nBands = 3; - else if (nReqBands != 0) - { - CPLError(CE_Warning, CPLE_NotSupported, - "Parameters bands=%d ignored", nReqBands); - } - - /* -------------------------------------------------------------------- - */ - /* Add bands */ - /* -------------------------------------------------------------------- - */ - - for (int iBand = 0; iBand < nBands; iBand++) - poDS->SetBand(iBand + 1, - new RasterliteBand(poDS, iBand + 1, eDataType, - nBlockXSize, nBlockYSize)); - - /* -------------------------------------------------------------------- - */ - /* Add overview levels as internal datasets */ - /* -------------------------------------------------------------------- - */ - if (nResolutions > 1) - { - poDS->papoOverviews = reinterpret_cast( - CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset *))); - for (int nLev = 1; nLev < nResolutions; nLev++) - { - int nOvrBands; - GDALDataType eOvrDataType; - if (poDS->GetBlockParams(hRasterLyr, nLev, &nOvrBands, - &eOvrDataType, &nBlockXSize, - &nBlockYSize) == FALSE) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "Cannot find block characteristics for overview %d", - nLev); - delete poDS; - poDS = nullptr; - goto end; - } - - if (eDataType == GDT_Byte && nOvrBands == 1 && nReqBands == 3) - nOvrBands = 3; - - if (nBands != nOvrBands || eDataType != eOvrDataType) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Overview %d has not the same number " - "characteristics as main band", - nLev); - delete poDS; - poDS = nullptr; - goto end; - } - - poDS->papoOverviews[nLev - 1] = - new RasterliteDataset(poDS, nLev); - - for (int iBand = 0; iBand < nBands; iBand++) - { - poDS->papoOverviews[nLev - 1]->SetBand( - iBand + 1, new RasterliteBand( - poDS->papoOverviews[nLev - 1], iBand + 1, - eDataType, nBlockXSize, nBlockYSize)); - } - } - } - - /* -------------------------------------------------------------------- - */ - /* Select an overview if the user has requested so */ - /* -------------------------------------------------------------------- - */ - if (nLevel == 0) - { - } - else if (nLevel >= 1 && nLevel <= nResolutions - 1) - { - poDS->papoOverviews[nLevel - 1]->bMustFree = TRUE; - poDS = poDS->papoOverviews[nLevel - 1]; - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "Invalid requested level : %d. Must be >= 0 and <= %d", - nLevel, nResolutions - 1); - delete poDS; - poDS = nullptr; - } - } - - if (poDS) - { - /* -------------------------------------------------------------------- - */ - /* Setup PAM info for this subdatasets */ - /* -------------------------------------------------------------------- - */ - poDS->SetPhysicalFilename(osFileName.c_str()); - - CPLString osSubdatasetName; - osSubdatasetName.Printf("RASTERLITE:%s:table=%s", osFileName.c_str(), - osTableName.c_str()); - poDS->SetSubdatasetName(osSubdatasetName.c_str()); - poDS->TryLoadXML(); - poDS->oOvManager.Initialize(poDS, ":::VIRTUAL:::"); - } - -end: - if (hDS) - GDALClose(hDS); - - return poDS; -} - -/************************************************************************/ -/* GDALRegister_Rasterlite() */ -/************************************************************************/ - -void GDALRegister_Rasterlite() - -{ - if (!GDAL_CHECK_VERSION("Rasterlite driver")) - return; - - if (GDALGetDriverByName(DRIVER_NAME) != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - RasterliteDriverSetCommonMetadata(poDriver); - - poDriver->pfnOpen = RasterliteDataset::Open; - poDriver->pfnCreateCopy = RasterliteCreateCopy; - poDriver->pfnDelete = RasterliteDelete; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/rasterlite/rasterlitedataset.h b/frmts/rasterlite/rasterlitedataset.h deleted file mode 100644 index 55a82c43df0d..000000000000 --- a/frmts/rasterlite/rasterlitedataset.h +++ /dev/null @@ -1,142 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef RASTERLITE_DATASET_INCLUDED -#define RASTERLITE_DATASET_INCLUDED - -#include "gdal_pam.h" -#include "ogr_api.h" - -char **RasterliteGetTileDriverOptions(CSLConstList papszOptions); - -GDALDatasetH RasterliteOpenSQLiteDB(const char *pszFilename, - GDALAccess eAccess); -CPLString RasterliteGetPixelSizeCond(double dfPixelXSize, double dfPixelYSize, - const char *pszTablePrefixWithDot = ""); -CPLString RasterliteGetSpatialFilterCond(double minx, double miny, double maxx, - double maxy); - -class RasterliteBand; - -/************************************************************************/ -/* ==================================================================== */ -/* RasterliteDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class RasterliteDataset final : public GDALPamDataset -{ - friend class RasterliteBand; - - public: - RasterliteDataset(); - RasterliteDataset(RasterliteDataset *poMainDS, int nLevel); - - virtual ~RasterliteDataset(); - - virtual char **GetMetadataDomainList() override; - virtual char **GetMetadata(const char *pszDomain) override; - virtual const char *GetMetadataItem(const char *pszName, - const char *pszDomain) override; - virtual CPLErr GetGeoTransform(double *padfGeoTransform) override; - - const OGRSpatialReference *GetSpatialRef() const override; - - virtual char **GetFileList() override; - - virtual CPLErr IBuildOverviews(const char *pszResampling, int nOverviews, - const int *panOverviewList, int nBands, - const int *panBandList, - GDALProgressFunc pfnProgress, - void *pProgressData, - CSLConstList papszOptions) override; - - static GDALDataset *Open(GDALOpenInfo *); - - protected: - virtual int CloseDependentDatasets() override; - - private: - int bMustFree; - RasterliteDataset *poMainDS; - int nLevel; - - char **papszMetadata; - char **papszImageStructure; - char **papszSubDatasets; - - int nResolutions; - double *padfXResolutions; - double *padfYResolutions; - RasterliteDataset **papoOverviews; - int nLimitOvrCount; - - int bValidGeoTransform; - double adfGeoTransform[6]; - OGRSpatialReference m_oSRS{}; - - GDALColorTable *poCT; - - CPLString osTableName; - CPLString osFileName; - - int bCheckForExistingOverview; - CPLString osOvrFileName; - - GDALDatasetH hDS; - - int m_nLastBadTileId = -1; - - void AddSubDataset(const char *pszDSName); - int GetBlockParams(OGRLayerH hRasterLyr, int nLevel, int *pnBands, - GDALDataType *peDataType, int *pnBlockXSize, - int *pnBlockYSize); - CPLErr CleanOverviews(); - CPLErr CleanOverviewLevel(int nOvrFactor); - CPLErr ReloadOverviews(); - CPLErr CreateOverviewLevel(const char *pszResampling, int nOvrFactor, - CSLConstList papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* RasterliteBand */ -/* ==================================================================== */ -/************************************************************************/ - -class RasterliteBand final : public GDALPamRasterBand -{ - friend class RasterliteDataset; - - public: - RasterliteBand(RasterliteDataset *poDS, int nBand, GDALDataType eDataType, - int nBlockXSize, int nBlockYSize); - - virtual GDALColorInterp GetColorInterpretation() override; - virtual GDALColorTable *GetColorTable() override; - - virtual int GetOverviewCount() override; - virtual GDALRasterBand *GetOverview(int nLevel) override; - - virtual CPLErr IReadBlock(int, int, void *) override; -}; - -GDALDataset *RasterliteCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); - -CPLErr RasterliteDelete(const char *pszFilename); - -#endif // RASTERLITE_DATASET_INCLUDED diff --git a/frmts/rasterlite/rasterlitedrivercore.cpp b/frmts/rasterlite/rasterlitedrivercore.cpp deleted file mode 100644 index f3377f9fdb13..000000000000 --- a/frmts/rasterlite/rasterlitedrivercore.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "rasterlitedrivercore.h" - -/************************************************************************/ -/* RasterliteDriverIdentify() */ -/************************************************************************/ - -int RasterliteDriverIdentify(GDALOpenInfo *poOpenInfo) - -{ -#ifdef ENABLE_SQL_SQLITE_FORMAT - if (poOpenInfo->pabyHeader && - STARTS_WITH((const char *)poOpenInfo->pabyHeader, "-- SQL RASTERLITE")) - { - return TRUE; - } -#endif - - if (!poOpenInfo->IsExtensionEqualToCI("MBTILES") && - !poOpenInfo->IsExtensionEqualToCI("GPKG") && - poOpenInfo->nHeaderBytes >= 1024 && poOpenInfo->pabyHeader && - STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, - "SQLite Format 3") && - // Do not match direct Amazon S3 signed URLs that contains .mbtiles in - // the middle of the URL - strstr(poOpenInfo->pszFilename, ".mbtiles") == nullptr) - { - // Could be a SQLite/Spatialite file as well - return -1; - } - else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:")) - { - return TRUE; - } - - return FALSE; -} - -/************************************************************************/ -/* RasterliteDriverSetCommonMetadata() */ -/************************************************************************/ - -void RasterliteDriverSetCommonMetadata(GDALDriver *poDriver) -{ - poDriver->SetDescription(DRIVER_NAME); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Rasterlite"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, - "drivers/raster/rasterlite.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "sqlite"); - poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte UInt16 Int16 UInt32 Int32 Float32 " - "Float64 CInt16 CInt32 CFloat32 CFloat64"); - poDriver->SetMetadataItem( - GDAL_DMD_CREATIONOPTIONLIST, - "" - " " - ""); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - -#ifdef ENABLE_SQL_SQLITE_FORMAT - poDriver->SetMetadataItem("ENABLE_SQL_SQLITE_FORMAT", "YES"); -#endif - - poDriver->pfnIdentify = RasterliteDriverIdentify; - poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); - poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES"); -} - -/************************************************************************/ -/* DeclareDeferredRasterlitePlugin() */ -/************************************************************************/ - -#ifdef PLUGIN_FILENAME -void DeclareDeferredRasterlitePlugin() -{ - if (GDALGetDriverByName(DRIVER_NAME) != nullptr) - { - return; - } - auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME); -#ifdef PLUGIN_INSTALLATION_MESSAGE - poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE, - PLUGIN_INSTALLATION_MESSAGE); -#endif - RasterliteDriverSetCommonMetadata(poDriver); - GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); -} -#endif diff --git a/frmts/rasterlite/rasterlitedrivercore.h b/frmts/rasterlite/rasterlitedrivercore.h deleted file mode 100644 index 9433130ed389..000000000000 --- a/frmts/rasterlite/rasterlitedrivercore.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef RASTERLITEDRIVERCORE_H -#define RASTERLITEDRIVERCORE_H - -#include "gdal_priv.h" - -#if defined(DEBUG) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || \ - defined(ALLOW_FORMAT_DUMPS) -// Enable accepting a SQL dump (starting with a "-- SQL SQLITE" or -// "-- SQL RASTERLITE" line) as a valid -// file. This makes fuzzer life easier -#define ENABLE_SQL_SQLITE_FORMAT -#endif - -constexpr const char *DRIVER_NAME = "Rasterlite"; - -#define RasterliteDriverIdentify PLUGIN_SYMBOL_NAME(RasterliteDriverIdentify) -#define RasterliteDriverSetCommonMetadata \ - PLUGIN_SYMBOL_NAME(RasterliteDriverSetCommonMetadata) - -int RasterliteDriverIdentify(GDALOpenInfo *poOpenInfo); - -void RasterliteDriverSetCommonMetadata(GDALDriver *poDriver); - -#endif diff --git a/frmts/rasterlite/rasterliteoverviews.cpp b/frmts/rasterlite/rasterliteoverviews.cpp deleted file mode 100644 index 62707d8b1ed7..000000000000 --- a/frmts/rasterlite/rasterliteoverviews.cpp +++ /dev/null @@ -1,828 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2012, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "ogr_api.h" -#include "ogr_srs_api.h" -#include "memdataset.h" - -#include "rasterlitedataset.h" - -/************************************************************************/ -/* ReloadOverviews() */ -/************************************************************************/ - -CPLErr RasterliteDataset::ReloadOverviews() -{ - if (nLevel != 0) - return CE_Failure; - - /* -------------------------------------------------------------------- */ - /* Fetch resolutions */ - /* -------------------------------------------------------------------- */ - - CPLString osSQL; - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr) - { - osSQL.Printf("SELECT pixel_x_size, pixel_y_size " - "FROM raster_pyramids WHERE table_prefix = '%s' " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - } - else - { - osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size " - "FROM \"%s_metadata\" WHERE pixel_x_size != 0 " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - } - - OGRLayerH hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - { - if (hRasterPyramidsLyr == nullptr) - return CE_Failure; - - osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size " - "FROM \"%s_metadata\" WHERE pixel_x_size != 0 " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - - hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - return CE_Failure; - } - - /* -------------------------------------------------------------------- */ - /* Cleanup */ - /* -------------------------------------------------------------------- */ - for (int i = 1; i < nResolutions; i++) - delete papoOverviews[i - 1]; - CPLFree(papoOverviews); - papoOverviews = nullptr; - CPLFree(padfXResolutions); - padfXResolutions = nullptr; - CPLFree(padfYResolutions); - padfYResolutions = nullptr; - - /* -------------------------------------------------------------------- */ - /* Rebuild arrays */ - /* -------------------------------------------------------------------- */ - - nResolutions = static_cast(OGR_L_GetFeatureCount(hSQLLyr, TRUE)); - - padfXResolutions = - reinterpret_cast(CPLMalloc(sizeof(double) * nResolutions)); - padfYResolutions = - reinterpret_cast(CPLMalloc(sizeof(double) * nResolutions)); - - { - // Exstra scope for i. - int i = 0; - OGRFeatureH hFeat; - while ((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != nullptr) - { - padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0); - padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1); - - OGR_F_Destroy(hFeat); - - i++; - } - } - - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - hSQLLyr = nullptr; - - /* -------------------------------------------------------------------- */ - /* Add overview levels as internal datasets */ - /* -------------------------------------------------------------------- */ - if (nResolutions > 1) - { - CPLString osRasterTableName = osTableName; - osRasterTableName += "_rasters"; - - OGRLayerH hRasterLyr = - GDALDatasetGetLayerByName(hDS, osRasterTableName.c_str()); - - papoOverviews = reinterpret_cast( - CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset *))); - for (int nLev = 1; nLev < nResolutions; nLev++) - { - int nOvrBands; - GDALDataType eOvrDataType; - int nBlockXSize, nBlockYSize; - if (GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType, - &nBlockXSize, &nBlockYSize)) - { - if (eOvrDataType == GDT_Byte && nOvrBands == 1 && nBands == 3) - nOvrBands = 3; - - papoOverviews[nLev - 1] = new RasterliteDataset(this, nLev); - - for (int iBand = 0; iBand < nBands; iBand++) - { - papoOverviews[nLev - 1]->SetBand( - iBand + 1, new RasterliteBand( - papoOverviews[nLev - 1], iBand + 1, - eOvrDataType, nBlockXSize, nBlockYSize)); - } - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot find block characteristics for overview %d", - nLev); - papoOverviews[nLev - 1] = nullptr; - } - } - } - - return CE_None; -} - -/************************************************************************/ -/* CleanOverviews() */ -/************************************************************************/ - -CPLErr RasterliteDataset::CleanOverviews() -{ - if (nLevel != 0) - return CE_Failure; - - CPLString osSQL("BEGIN"); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - const CPLString osResolutionCond = - "NOT " + - RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]); - - osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id " - "IN(SELECT id FROM \"%s_metadata\" WHERE %s)", - osTableName.c_str(), osTableName.c_str(), - osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s", osTableName.c_str(), - osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr) - { - osSQL.Printf( - "DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s", - osTableName.c_str(), osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - } - - osSQL = "COMMIT"; - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - for (int i = 1; i < nResolutions; i++) - delete papoOverviews[i - 1]; - CPLFree(papoOverviews); - papoOverviews = nullptr; - nResolutions = 1; - - return CE_None; -} - -/************************************************************************/ -/* CleanOverviewLevel() */ -/************************************************************************/ - -CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor) -{ - if (nLevel != 0) - return CE_Failure; - - /* -------------------------------------------------------------------- */ - /* Find the index of the overview matching the overview factor */ - /* -------------------------------------------------------------------- */ - int iLev = 1; - for (; iLev < nResolutions; iLev++) - { - if (fabs(padfXResolutions[0] * nOvrFactor - padfXResolutions[iLev]) < - 1e-15 && - fabs(padfYResolutions[0] * nOvrFactor - padfYResolutions[iLev]) < - 1e-15) - break; - } - - if (iLev == nResolutions) - return CE_None; - - /* -------------------------------------------------------------------- */ - /* Now clean existing overviews at that resolution */ - /* -------------------------------------------------------------------- */ - - CPLString osSQL("BEGIN"); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - CPLString osResolutionCond = RasterliteGetPixelSizeCond( - padfXResolutions[iLev], padfYResolutions[iLev]); - - osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id " - "IN(SELECT id FROM \"%s_metadata\" WHERE %s)", - osTableName.c_str(), osTableName.c_str(), - osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s", osTableName.c_str(), - osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr) - { - osSQL.Printf( - "DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s", - osTableName.c_str(), osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - } - - osSQL = "COMMIT"; - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - return CE_None; -} - -/************************************************************************/ -/* CleanOverviewLevel() */ -/************************************************************************/ - -CPLErr RasterliteDataset::CreateOverviewLevel(const char *pszResampling, - int nOvrFactor, - CSLConstList papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - const int nOvrXSize = nRasterXSize / nOvrFactor; - const int nOvrYSize = nRasterYSize / nOvrFactor; - - if (nOvrXSize == 0 || nOvrYSize == 0) - return CE_Failure; - - const bool bTiled = - CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES")); - int nBlockXSize, nBlockYSize; - if (bTiled) - { - nBlockXSize = - atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256")); - nBlockYSize = - atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256")); - if (nBlockXSize < 64) - nBlockXSize = 64; - else if (nBlockXSize > 4096) - nBlockXSize = 4096; - if (nBlockYSize < 64) - nBlockYSize = 64; - else if (nBlockYSize > 4096) - nBlockYSize = 4096; - } - else - { - nBlockXSize = nOvrXSize; - nBlockYSize = nOvrYSize; - } - - const char *pszDriverName = - CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff"); - if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT")) - { - CPLError(CE_Failure, CPLE_AppDefined, - "GDAL %s driver cannot be used as underlying driver", - pszDriverName); - return CE_Failure; - } - GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName); - if (hTileDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", - pszDriverName); - return CE_Failure; - } - - GDALDriverH hMemDriver = GDALGetDriverByName("MEM"); - if (hMemDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver"); - return CE_Failure; - } - - const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType(); - int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8; - GByte *pabyMEMDSBuffer = reinterpret_cast(VSIMalloc3( - nBlockXSize, nBlockYSize, cpl::fits_on(nBands * nDataTypeSize))); - if (pabyMEMDSBuffer == nullptr) - { - return CE_Failure; - } - - const CPLString osTempFileName( - VSIMemGenerateHiddenFilename("rasterlite_tile")); - - int nTileId = 0; - int nBlocks = 0; - - const int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize; - const int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize; - int nTotalBlocks = nXBlocks * nYBlocks; - - CPLString osRasterLayer; - osRasterLayer.Printf("%s_rasters", osTableName.c_str()); - - CPLString osMetatadataLayer; - osMetatadataLayer.Printf("%s_metadata", osTableName.c_str()); - - OGRLayerH hRasterLayer = - GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str()); - OGRLayerH hMetadataLayer = - GDALDatasetGetLayerByName(hDS, osMetatadataLayer.c_str()); - - CPLString osSourceName = "unknown"; - - const double dfXResolution = padfXResolutions[0] * nOvrFactor; - const double dfYResolution = padfXResolutions[0] * nOvrFactor; - - CPLString osSQL; - osSQL.Printf( - "SELECT source_name FROM \"%s\" WHERE " - "%s LIMIT 1", - osMetatadataLayer.c_str(), - RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]) - .c_str()); - OGRLayerH hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr) - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr); - if (hFeat) - { - const char *pszVal = OGR_F_GetFieldAsString(hFeat, 0); - if (pszVal) - osSourceName = pszVal; - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - } - - /* -------------------------------------------------------------------- */ - /* Compute up to which existing overview level we can use for */ - /* computing the requested overview */ - /* -------------------------------------------------------------------- */ - nLimitOvrCount = 0; - int iLev = 1; - for (; iLev < nResolutions; iLev++) - { - if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 && - padfYResolutions[iLev] < dfYResolution - 1e-10)) - { - break; - } - nLimitOvrCount++; - } - /* -------------------------------------------------------------------- */ - /* Allocate buffer for tile of previous overview level */ - /* -------------------------------------------------------------------- */ - - GDALDataset *poPrevOvrLevel = - (papoOverviews != nullptr && iLev >= 2 && iLev <= nResolutions && - papoOverviews[iLev - 2]) - ? papoOverviews[iLev - 2] - : this; - const double dfRatioPrevOvr = - static_cast(poPrevOvrLevel->GetRasterBand(1)->GetXSize()) / - nOvrXSize; - const int nPrevOvrBlockXSize = - static_cast(nBlockXSize * dfRatioPrevOvr + 0.5); - const int nPrevOvrBlockYSize = - static_cast(nBlockYSize * dfRatioPrevOvr + 0.5); - GByte *pabyPrevOvrMEMDSBuffer = nullptr; - - if (!STARTS_WITH_CI(pszResampling, "NEAR")) - { - pabyPrevOvrMEMDSBuffer = reinterpret_cast( - VSIMalloc3(nPrevOvrBlockXSize, nPrevOvrBlockYSize, - cpl::fits_on(nBands * nDataTypeSize))); - if (pabyPrevOvrMEMDSBuffer == nullptr) - { - VSIFree(pabyMEMDSBuffer); - return CE_Failure; - } - } - - /* -------------------------------------------------------------------- */ - /* Iterate over blocks to add data into raster and metadata tables */ - /* -------------------------------------------------------------------- */ - - char **papszTileDriverOptions = - RasterliteGetTileDriverOptions(papszOptions); - - GDALDatasetExecuteSQL(hDS, "BEGIN", nullptr, nullptr); - - CPLErr eErr = CE_None; - for (int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks; - nBlockYOff++) - { - for (int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks; - nBlockXOff++) - { - std::unique_ptr poPrevOvrMemDS; - - /* -------------------------------------------------------------------- - */ - /* Create in-memory tile */ - /* -------------------------------------------------------------------- - */ - int nReqXSize = nBlockXSize; - int nReqYSize = nBlockYSize; - if ((nBlockXOff + 1) * nBlockXSize > nOvrXSize) - nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize; - if ((nBlockYOff + 1) * nBlockYSize > nOvrYSize) - nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize; - - if (pabyPrevOvrMEMDSBuffer != nullptr) - { - int nPrevOvrReqXSize = - static_cast(nReqXSize * dfRatioPrevOvr + 0.5); - int nPrevOvrReqYSize = - static_cast(nReqYSize * dfRatioPrevOvr + 0.5); - - eErr = RasterIO(GF_Read, nBlockXOff * nBlockXSize * nOvrFactor, - nBlockYOff * nBlockYSize * nOvrFactor, - nReqXSize * nOvrFactor, nReqYSize * nOvrFactor, - pabyPrevOvrMEMDSBuffer, nPrevOvrReqXSize, - nPrevOvrReqYSize, eDataType, nBands, nullptr, 0, - 0, 0, nullptr); - - if (eErr != CE_None) - { - break; - } - - poPrevOvrMemDS.reset(MEMDataset::Create("", nPrevOvrReqXSize, - nPrevOvrReqYSize, 0, - eDataType, nullptr)); - - for (int iBand = 0; iBand < nBands; iBand++) - { - auto hBand = MEMCreateRasterBandEx( - poPrevOvrMemDS.get(), iBand + 1, - pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize * - nPrevOvrReqXSize * - nPrevOvrReqYSize, - eDataType, 0, 0, false); - poPrevOvrMemDS->AddMEMBand(hBand); - } - } - else - { - eErr = RasterIO(GF_Read, nBlockXOff * nBlockXSize * nOvrFactor, - nBlockYOff * nBlockYSize * nOvrFactor, - nReqXSize * nOvrFactor, nReqYSize * nOvrFactor, - pabyMEMDSBuffer, nReqXSize, nReqYSize, - eDataType, nBands, nullptr, 0, 0, 0, nullptr); - if (eErr != CE_None) - { - break; - } - } - - auto poMemDS = std::unique_ptr(MEMDataset::Create( - "", nReqXSize, nReqYSize, 0, eDataType, nullptr)); - for (int iBand = 0; iBand < nBands; iBand++) - { - auto hBand = MEMCreateRasterBandEx( - poMemDS.get(), iBand + 1, - pabyMEMDSBuffer + - iBand * nDataTypeSize * nReqXSize * nReqYSize, - eDataType, 0, 0, false); - poMemDS->AddMEMBand(hBand); - } - - auto hMemDS = GDALDataset::ToHandle(poMemDS.get()); - if (poPrevOvrMemDS != nullptr) - { - for (int iBand = 0; iBand < nBands; iBand++) - { - GDALRasterBandH hDstOvrBand = - GDALGetRasterBand(hMemDS, iBand + 1); - - auto hPrevOvrMEMDS = - GDALDataset::ToHandle(poPrevOvrMemDS.get()); - eErr = GDALRegenerateOverviews( - GDALGetRasterBand(hPrevOvrMEMDS, iBand + 1), 1, - &hDstOvrBand, pszResampling, nullptr, nullptr); - if (eErr != CE_None) - break; - } - - poPrevOvrMemDS.reset(); - } - - GDALDatasetH hOutDS = - GDALCreateCopy(hTileDriver, osTempFileName.c_str(), hMemDS, - FALSE, papszTileDriverOptions, nullptr, nullptr); - - poMemDS.reset(); - if (!hOutDS) - { - eErr = CE_Failure; - break; - } - - GDALClose(hOutDS); - - /* -------------------------------------------------------------------- - */ - /* Insert new entry into raster table */ - /* -------------------------------------------------------------------- - */ - - vsi_l_offset nDataLength; - GByte *pabyData = VSIGetMemFileBuffer(osTempFileName.c_str(), - &nDataLength, FALSE); - - OGRFeatureH hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hRasterLayer)); - OGR_F_SetFieldBinary(hFeat, 0, static_cast(nDataLength), - pabyData); - - if (OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - /* Query raster ID to set it as the ID of the associated metadata */ - const int nRasterID = static_cast(OGR_F_GetFID(hFeat)); - - OGR_F_Destroy(hFeat); - - VSIUnlink(osTempFileName.c_str()); - if (eErr == CE_Failure) - break; - - /* -------------------------------------------------------------------- - */ - /* Insert new entry into metadata table */ - /* -------------------------------------------------------------------- - */ - - hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hMetadataLayer)); - OGR_F_SetFID(hFeat, nRasterID); - OGR_F_SetFieldString(hFeat, 0, osSourceName); - OGR_F_SetFieldInteger(hFeat, 1, nTileId++); - OGR_F_SetFieldInteger(hFeat, 2, nReqXSize); - OGR_F_SetFieldInteger(hFeat, 3, nReqYSize); - OGR_F_SetFieldDouble(hFeat, 4, dfXResolution); - OGR_F_SetFieldDouble(hFeat, 5, dfYResolution); - - const double minx = - adfGeoTransform[0] + (nBlockXSize * nBlockXOff) * dfXResolution; - const double maxx = - adfGeoTransform[0] + - (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution; - const double maxy = adfGeoTransform[3] + - (nBlockYSize * nBlockYOff) * (-dfYResolution); - const double miny = - adfGeoTransform[3] + - (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution); - - OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon); - OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing); - OGR_G_AddPoint_2D(hLinearRing, minx, miny); - OGR_G_AddPoint_2D(hLinearRing, minx, maxy); - OGR_G_AddPoint_2D(hLinearRing, maxx, maxy); - OGR_G_AddPoint_2D(hLinearRing, maxx, miny); - OGR_G_AddPoint_2D(hLinearRing, minx, miny); - OGR_G_AddGeometryDirectly(hRectangle, hLinearRing); - - OGR_F_SetGeometryDirectly(hFeat, hRectangle); - - if (OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - OGR_F_Destroy(hFeat); - - nBlocks++; - if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks, - nullptr, pProgressData)) - eErr = CE_Failure; - } - } - - nLimitOvrCount = -1; - - VSIUnlink(osTempFileName); - VSIUnlink((osTempFileName + ".aux.xml").c_str()); - - if (eErr == CE_None) - GDALDatasetExecuteSQL(hDS, "COMMIT", nullptr, nullptr); - else - GDALDatasetExecuteSQL(hDS, "ROLLBACK", nullptr, nullptr); - - VSIFree(pabyMEMDSBuffer); - VSIFree(pabyPrevOvrMEMDSBuffer); - - CSLDestroy(papszTileDriverOptions); - papszTileDriverOptions = nullptr; - - /* -------------------------------------------------------------------- */ - /* Update raster_pyramids table */ - /* -------------------------------------------------------------------- */ - if (eErr != CE_None) - return eErr; - - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr == nullptr) - { - osSQL.Printf("CREATE TABLE raster_pyramids (" - "table_prefix TEXT NOT NULL," - "pixel_x_size DOUBLE NOT NULL," - "pixel_y_size DOUBLE NOT NULL," - "tile_count INTEGER NOT NULL)"); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - /* Re-open the DB to take into account the new tables*/ - GDALClose(hDS); - - hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update); - - hRasterPyramidsLyr = GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr == nullptr) - return CE_Failure; - } - OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr); - - /* Insert base resolution into raster_pyramids if not already done */ - bool bHasBaseResolution = false; - osSQL.Printf( - "SELECT * FROM raster_pyramids WHERE " - "table_prefix = '%s' AND %s", - osTableName.c_str(), - RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]) - .c_str()); - hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr) - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr); - if (hFeat) - { - bHasBaseResolution = true; - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - } - - if (!bHasBaseResolution) - { - osSQL.Printf( - "SELECT COUNT(*) FROM \"%s\" WHERE %s", osMetatadataLayer.c_str(), - RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]) - .c_str()); - - int nBlocksMainRes = 0; - - hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr) - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr); - if (hFeat) - { - nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0); - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - } - - OGRFeatureH hFeat = OGR_F_Create(hFDefn); - OGR_F_SetFieldString(hFeat, - OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), - osTableName.c_str()); - OGR_F_SetFieldDouble(hFeat, - OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), - padfXResolutions[0]); - OGR_F_SetFieldDouble(hFeat, - OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), - padfYResolutions[0]); - OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), - nBlocksMainRes); - if (OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - OGR_F_Destroy(hFeat); - } - - OGRFeatureH hFeat = OGR_F_Create(hFDefn); - OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), - osTableName.c_str()); - OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), - dfXResolution); - OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), - dfYResolution); - OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), - nTotalBlocks); - if (OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - OGR_F_Destroy(hFeat); - - return eErr; -} - -/************************************************************************/ -/* IBuildOverviews() */ -/************************************************************************/ - -CPLErr RasterliteDataset::IBuildOverviews( - const char *pszResampling, int nOverviews, const int *panOverviewList, - int nBandsIn, const int *panBandList, GDALProgressFunc pfnProgress, - void *pProgressData, CSLConstList papszOptions) -{ - if (nLevel != 0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Overviews can only be computed on the base dataset"); - return CE_Failure; - } - - if (osTableName.empty()) - return CE_Failure; - - /* -------------------------------------------------------------------- */ - /* If we don't have read access, then create the overviews */ - /* externally. */ - /* -------------------------------------------------------------------- */ - if (GetAccess() != GA_Update) - { - CPLDebug("Rasterlite", "File open for read-only accessing, " - "creating overviews externally."); - - if (nResolutions != 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Cannot add external overviews to a " - "dataset with internal overviews"); - return CE_Failure; - } - - bCheckForExistingOverview = FALSE; - CPLErr eErr = GDALDataset::IBuildOverviews( - pszResampling, nOverviews, panOverviewList, nBandsIn, panBandList, - pfnProgress, pProgressData, papszOptions); - bCheckForExistingOverview = TRUE; - return eErr; - } - - /* -------------------------------------------------------------------- */ - /* If zero overviews were requested, we need to clear all */ - /* existing overviews. */ - /* -------------------------------------------------------------------- */ - if (nOverviews == 0) - { - return CleanOverviews(); - } - - if (nBandsIn != GetRasterCount()) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Generation of overviews in RASTERLITE only" - " supported when operating on all bands.\n" - "Operation failed.\n"); - return CE_Failure; - } - - const char *pszOvrOptions = - CPLGetConfigOption("RASTERLITE_OVR_OPTIONS", nullptr); - const CPLStringList aosCreationOptions( - pszOvrOptions ? CSLTokenizeString2(pszOvrOptions, ",", 0) : nullptr); - GDALValidateCreationOptions(GetDriver(), aosCreationOptions.List()); - - CPLErr eErr = CE_None; - for (int i = 0; i < nOverviews && eErr == CE_None; i++) - { - if (panOverviewList[i] <= 1) - continue; - - eErr = CleanOverviewLevel(panOverviewList[i]); - if (eErr == CE_None) - eErr = CreateOverviewLevel(pszResampling, panOverviewList[i], - aosCreationOptions.List(), pfnProgress, - pProgressData); - - ReloadOverviews(); - } - - return eErr; -} diff --git a/frmts/raw/CMakeLists.txt b/frmts/raw/CMakeLists.txt index 740facae3d42..89fac928f1ae 100644 --- a/frmts/raw/CMakeLists.txt +++ b/frmts/raw/CMakeLists.txt @@ -3,10 +3,7 @@ add_gdal_driver( SOURCES atlsci_spheroid.h ace2dataset.cpp atlsci_spheroid.cpp - btdataset.cpp cpgdataset.cpp - ctable2dataset.cpp - dipxdataset.cpp doq1dataset.cpp doq2dataset.cpp ehdrdataset.cpp diff --git a/frmts/raw/btdataset.cpp b/frmts/raw/btdataset.cpp deleted file mode 100644 index 7b7e5dc09ffb..000000000000 --- a/frmts/raw/btdataset.cpp +++ /dev/null @@ -1,961 +0,0 @@ -/****************************************************************************** - * - * Project: VTP .bt Driver - * Purpose: Implementation of VTP .bt elevation format read/write support. - * http://www.vterrain.org/Implementation/Formats/BT.html - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2003, Frank Warmerdam - * Copyright (c) 2007-2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "gdal_frmts.h" -#include "ogr_spatialref.h" -#include "rawdataset.h" -#include -#include - -/************************************************************************/ -/* ==================================================================== */ -/* BTDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class BTDataset final : public GDALPamDataset -{ - friend class BTRasterBand; - - VSILFILE *fpImage; // image data file. - - int bGeoTransformValid; - double adfGeoTransform[6]; - - OGRSpatialReference m_oSRS{}; - - int nVersionCode; // version times 10. - - int bHeaderModified; - unsigned char abyHeader[256]; - - float m_fVscale; - - CPL_DISALLOW_COPY_ASSIGN(BTDataset) - - public: - BTDataset(); - ~BTDataset() override; - - const OGRSpatialReference *GetSpatialRef() const override - { - return m_oSRS.IsEmpty() ? nullptr : &m_oSRS; - } - - CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override; - CPLErr GetGeoTransform(double *) override; - CPLErr SetGeoTransform(double *) override; - - CPLErr FlushCache(bool bAtClosing) override; - - static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszOptions); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* BTRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class BTRasterBand final : public GDALPamRasterBand -{ - VSILFILE *fpImage; - - CPL_DISALLOW_COPY_ASSIGN(BTRasterBand) - - public: - BTRasterBand(GDALDataset *poDS, VSILFILE *fp, GDALDataType eType); - - ~BTRasterBand() override - { - } - - CPLErr IReadBlock(int, int, void *) override; - CPLErr IWriteBlock(int, int, void *) override; - - const char *GetUnitType() override; - CPLErr SetUnitType(const char *) override; - double GetNoDataValue(int * = nullptr) override; - CPLErr SetNoDataValue(double) override; -}; - -/************************************************************************/ -/* BTRasterBand() */ -/************************************************************************/ - -BTRasterBand::BTRasterBand(GDALDataset *poDSIn, VSILFILE *fp, - GDALDataType eType) - : fpImage(fp) -{ - poDS = poDSIn; - nBand = 1; - eDataType = eType; - - nBlockXSize = 1; - nBlockYSize = poDS->GetRasterYSize(); -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr BTRasterBand::IReadBlock(int nBlockXOff, CPL_UNUSED int nBlockYOff, - void *pImage) -{ - CPLAssert(nBlockYOff == 0); - - const int nDataSize = GDALGetDataTypeSizeBytes(eDataType); - - /* -------------------------------------------------------------------- */ - /* Seek to profile. */ - /* -------------------------------------------------------------------- */ - if (VSIFSeekL(fpImage, - 256 + static_cast(nBlockXOff) * nDataSize * - nRasterYSize, - SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, ".bt Seek failed:%s", - VSIStrerror(errno)); - return CE_Failure; - } - - /* -------------------------------------------------------------------- */ - /* Read the profile. */ - /* -------------------------------------------------------------------- */ - if (VSIFReadL(pImage, nDataSize, nRasterYSize, fpImage) != - static_cast(nRasterYSize)) - { - CPLError(CE_Failure, CPLE_FileIO, ".bt Read failed:%s", - VSIStrerror(errno)); - return CE_Failure; - } - -/* -------------------------------------------------------------------- */ -/* Swap on MSB platforms. */ -/* -------------------------------------------------------------------- */ -#ifdef CPL_MSB - GDALSwapWords(pImage, nDataSize, nRasterYSize, nDataSize); -#endif - - /* -------------------------------------------------------------------- */ - /* Vertical flip, since GDAL expects values from top to bottom, */ - /* but in .bt they are bottom to top. */ - /* -------------------------------------------------------------------- */ - GByte abyWrk[8] = {0}; - CPLAssert(nDataSize <= 8); - for (int i = 0; i < nRasterYSize / 2; i++) - { - memcpy(abyWrk, reinterpret_cast(pImage) + i * nDataSize, - nDataSize); - memcpy(reinterpret_cast(pImage) + i * nDataSize, - reinterpret_cast(pImage) + - (nRasterYSize - i - 1) * nDataSize, - nDataSize); - memcpy(reinterpret_cast(pImage) + - (nRasterYSize - i - 1) * nDataSize, - abyWrk, nDataSize); - } - - return CE_None; -} - -/************************************************************************/ -/* IWriteBlock() */ -/************************************************************************/ - -CPLErr BTRasterBand::IWriteBlock(int nBlockXOff, CPL_UNUSED int nBlockYOff, - void *pImage) - -{ - CPLAssert(nBlockYOff == 0); - - const int nDataSize = GDALGetDataTypeSizeBytes(eDataType); - - /* -------------------------------------------------------------------- */ - /* Seek to profile. */ - /* -------------------------------------------------------------------- */ - if (VSIFSeekL(fpImage, 256 + nBlockXOff * nDataSize * nRasterYSize, - SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, ".bt Seek failed:%s", - VSIStrerror(errno)); - return CE_Failure; - } - - /* -------------------------------------------------------------------- */ - /* Allocate working buffer. */ - /* -------------------------------------------------------------------- */ - GByte *pabyWrkBlock = static_cast( - CPLMalloc(static_cast(nDataSize) * nRasterYSize)); - - /* -------------------------------------------------------------------- */ - /* Vertical flip data into work buffer, since GDAL expects */ - /* values from top to bottom, but in .bt they are bottom to */ - /* top. */ - /* -------------------------------------------------------------------- */ - for (int i = 0; i < nRasterYSize; i++) - { - memcpy(pabyWrkBlock + - static_cast(nRasterYSize - i - 1) * nDataSize, - reinterpret_cast(pImage) + i * nDataSize, nDataSize); - } - -/* -------------------------------------------------------------------- */ -/* Swap on MSB platforms. */ -/* -------------------------------------------------------------------- */ -#ifdef CPL_MSB - GDALSwapWords(pabyWrkBlock, nDataSize, nRasterYSize, nDataSize); -#endif - - /* -------------------------------------------------------------------- */ - /* Read the profile. */ - /* -------------------------------------------------------------------- */ - if (VSIFWriteL(pabyWrkBlock, nDataSize, nRasterYSize, fpImage) != - static_cast(nRasterYSize)) - { - CPLFree(pabyWrkBlock); - CPLError(CE_Failure, CPLE_FileIO, ".bt Write failed:%s", - VSIStrerror(errno)); - return CE_Failure; - } - - CPLFree(pabyWrkBlock); - - return CE_None; -} - -double BTRasterBand::GetNoDataValue(int *pbSuccess /*= NULL */) -{ - // First check in PAM - int bSuccess = FALSE; - double dfRet = GDALPamRasterBand::GetNoDataValue(&bSuccess); - if (bSuccess) - { - if (pbSuccess != nullptr) - *pbSuccess = TRUE; - return dfRet; - } - - // Otherwise defaults to -32768 - if (pbSuccess != nullptr) - *pbSuccess = TRUE; - - return -32768; -} - -CPLErr BTRasterBand::SetNoDataValue(double dfNoDataValue) - -{ - // First check if there's an existing nodata value in PAM - int bSuccess = FALSE; - GDALPamRasterBand::GetNoDataValue(&bSuccess); - if (bSuccess) - { - // if so override it in PAM - return GDALPamRasterBand::SetNoDataValue(dfNoDataValue); - } - - // if nothing in PAM yet and the nodatavalue is the default one, do - // nothing - if (dfNoDataValue == -32768.0) - return CE_None; - // other nodata value ? then go to PAM - return GDALPamRasterBand::SetNoDataValue(dfNoDataValue); -} - -/************************************************************************/ -/* GetUnitType() */ -/************************************************************************/ - -static bool approx_equals(float a, float b) -{ - const float epsilon = 1e-5f; - return fabs(a - b) <= epsilon; -} - -const char *BTRasterBand::GetUnitType(void) -{ - const BTDataset &ds = *cpl::down_cast(poDS); - float f = ds.m_fVscale; - if (f == 1.0f) - return "m"; - if (approx_equals(f, 0.3048f)) - return "ft"; - if (approx_equals(f, 1200.0f / 3937.0f)) - return "sft"; - - // todo: the BT spec allows for any value for - // ds.m_fVscale, so rigorous adherence would - // require testing for all possible units you - // may want to support, such as km, yards, miles, etc. - // But m/ft/sft seem to be the top three. - - return ""; -} - -/************************************************************************/ -/* SetUnitType() */ -/************************************************************************/ - -CPLErr BTRasterBand::SetUnitType(const char *psz) -{ - BTDataset &ds = *cpl::down_cast(poDS); - if (EQUAL(psz, "m")) - ds.m_fVscale = 1.0f; - else if (EQUAL(psz, "ft")) - ds.m_fVscale = 0.3048f; - else if (EQUAL(psz, "sft")) - ds.m_fVscale = 1200.0f / 3937.0f; - else - return CE_Failure; - - float fScale = ds.m_fVscale; - - CPL_LSBPTR32(&fScale); - - // Update header's elevation scale field. - memcpy(ds.abyHeader + 62, &fScale, sizeof(fScale)); - - ds.bHeaderModified = TRUE; - return CE_None; -} - -/************************************************************************/ -/* ==================================================================== */ -/* BTDataset */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* BTDataset() */ -/************************************************************************/ - -BTDataset::BTDataset() - : fpImage(nullptr), bGeoTransformValid(FALSE), nVersionCode(0), - bHeaderModified(FALSE), m_fVscale(0.0) -{ - m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - - adfGeoTransform[0] = 0.0; - adfGeoTransform[1] = 1.0; - adfGeoTransform[2] = 0.0; - adfGeoTransform[3] = 0.0; - adfGeoTransform[4] = 0.0; - adfGeoTransform[5] = 1.0; - memset(abyHeader, 0, sizeof(abyHeader)); -} - -/************************************************************************/ -/* ~BTDataset() */ -/************************************************************************/ - -BTDataset::~BTDataset() - -{ - BTDataset::FlushCache(true); - if (fpImage != nullptr) - { - if (VSIFCloseL(fpImage) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, "I/O error"); - } - } -} - -/************************************************************************/ -/* FlushCache() */ -/* */ -/* We override this to include flush out the header block. */ -/************************************************************************/ - -CPLErr BTDataset::FlushCache(bool bAtClosing) - -{ - CPLErr eErr = GDALDataset::FlushCache(bAtClosing); - - if (!bHeaderModified) - return eErr; - - bHeaderModified = FALSE; - - if (VSIFSeekL(fpImage, 0, SEEK_SET) != 0 || - VSIFWriteL(abyHeader, 256, 1, fpImage) != 1) - { - eErr = CE_Failure; - } - return eErr; -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr BTDataset::GetGeoTransform(double *padfTransform) - -{ - memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6); - - if (bGeoTransformValid) - return CE_None; - else - return CE_Failure; -} - -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr BTDataset::SetGeoTransform(double *padfTransform) - -{ - CPLErr eErr = CE_None; - - memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6); - if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0) - { - CPLError(CE_Failure, CPLE_AppDefined, - ".bt format does not support rotational coefficients " - "in geotransform, ignoring."); - eErr = CE_Failure; - } - - /* -------------------------------------------------------------------- */ - /* Compute bounds, and update header info. */ - /* -------------------------------------------------------------------- */ - const double dfLeft = adfGeoTransform[0]; - const double dfRight = dfLeft + adfGeoTransform[1] * nRasterXSize; - const double dfTop = adfGeoTransform[3]; - const double dfBottom = dfTop + adfGeoTransform[5] * nRasterYSize; - - memcpy(abyHeader + 28, &dfLeft, 8); - memcpy(abyHeader + 36, &dfRight, 8); - memcpy(abyHeader + 44, &dfBottom, 8); - memcpy(abyHeader + 52, &dfTop, 8); - - CPL_LSBPTR64(abyHeader + 28); - CPL_LSBPTR64(abyHeader + 36); - CPL_LSBPTR64(abyHeader + 44); - CPL_LSBPTR64(abyHeader + 52); - - bHeaderModified = TRUE; - - return eErr; -} - -/************************************************************************/ -/* SetSpatialRef() */ -/************************************************************************/ - -CPLErr BTDataset::SetSpatialRef(const OGRSpatialReference *poSRS) - -{ - CPLErr eErr = CE_None; - - if (poSRS) - m_oSRS = *poSRS; - else - m_oSRS.Clear(); - - bHeaderModified = TRUE; - -/* -------------------------------------------------------------------- */ -/* Parse projection. */ -/* -------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------- */ -/* Linear units. */ -/* -------------------------------------------------------------------- */ -#if 0 - if( m_oSRS.IsGeographic() ) - { - // nShortTemp = 0; - } - else - { - const double dfLinear = m_oSRS.GetLinearUnits(); - - if( std::abs(dfLinear - 0.3048) < 0.0000001 ) - nShortTemp = 2; - else if( std::abs(dfLinear - CPLAtof(SRS_UL_US_FOOT_CONV)) - < 0.00000001 ) - nShortTemp = 3; - else - nShortTemp = 1; - } -#endif - GInt16 nShortTemp = CPL_LSBWORD16(1); - memcpy(abyHeader + 22, &nShortTemp, 2); - - /* -------------------------------------------------------------------- */ - /* UTM Zone */ - /* -------------------------------------------------------------------- */ - int bNorth = FALSE; - - nShortTemp = static_cast(m_oSRS.GetUTMZone(&bNorth)); - if (bNorth) - nShortTemp = -nShortTemp; - - CPL_LSBPTR16(&nShortTemp); - memcpy(abyHeader + 24, &nShortTemp, 2); - - /* -------------------------------------------------------------------- */ - /* Datum */ - /* -------------------------------------------------------------------- */ - if (m_oSRS.GetAuthorityName("GEOGCS|DATUM") != nullptr && - EQUAL(m_oSRS.GetAuthorityName("GEOGCS|DATUM"), "EPSG")) - nShortTemp = static_cast( - atoi(m_oSRS.GetAuthorityCode("GEOGCS|DATUM")) + 2000); - else - nShortTemp = -2; - CPL_LSBPTR16(&nShortTemp); /* datum unknown */ - memcpy(abyHeader + 26, &nShortTemp, 2); - - /* -------------------------------------------------------------------- */ - /* Write out the projection to a .prj file. */ - /* -------------------------------------------------------------------- */ - char *pszProjection = nullptr; - const char *const apszOptions[] = {"FORMAT=WKT1", nullptr}; - m_oSRS.exportToWkt(&pszProjection, apszOptions); - if (pszProjection) - { - const std::string osPrjFile = - CPLResetExtensionSafe(GetDescription(), "prj"); - VSILFILE *fp = VSIFOpenL(osPrjFile.c_str(), "wt"); - if (fp != nullptr) - { - CPL_IGNORE_RET_VAL(VSIFPrintfL(fp, "%s\n", pszProjection)); - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - abyHeader[60] = 1; - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "Unable to write out .prj file."); - eErr = CE_Failure; - } - CPLFree(pszProjection); - } - - return eErr; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *BTDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - /* -------------------------------------------------------------------- */ - /* Verify that this is some form of binterr file. */ - /* -------------------------------------------------------------------- */ - if (poOpenInfo->nHeaderBytes < 256 || poOpenInfo->fpL == nullptr) - return nullptr; - - if (!STARTS_WITH((const char *)poOpenInfo->pabyHeader, "binterr")) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Create the dataset. */ - /* -------------------------------------------------------------------- */ - BTDataset *poDS = new BTDataset(); - - memcpy(poDS->abyHeader, poOpenInfo->pabyHeader, 256); - - /* -------------------------------------------------------------------- */ - /* Get the version. */ - /* -------------------------------------------------------------------- */ - char szVersion[4] = {}; - - strncpy(szVersion, reinterpret_cast(poDS->abyHeader + 7), 3); - szVersion[3] = '\0'; - poDS->nVersionCode = static_cast(CPLAtof(szVersion) * 10); - - /* -------------------------------------------------------------------- */ - /* Extract core header information, being careful about the */ - /* version. */ - /* -------------------------------------------------------------------- */ - - GInt32 nIntTemp = 0; - memcpy(&nIntTemp, poDS->abyHeader + 10, 4); - poDS->nRasterXSize = CPL_LSBWORD32(nIntTemp); - - memcpy(&nIntTemp, poDS->abyHeader + 14, 4); - poDS->nRasterYSize = CPL_LSBWORD32(nIntTemp); - - if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) - { - delete poDS; - return nullptr; - } - - GInt16 nDataSize = 0; - memcpy(&nDataSize, poDS->abyHeader + 18, 2); - CPL_LSBPTR16(&nDataSize); - - GDALDataType eType = GDT_Unknown; - if (poDS->abyHeader[20] != 0 && nDataSize == 4) - eType = GDT_Float32; - else if (poDS->abyHeader[20] == 0 && nDataSize == 4) - eType = GDT_Int32; - else if (poDS->abyHeader[20] == 0 && nDataSize == 2) - eType = GDT_Int16; - else - { - CPLError(CE_Failure, CPLE_AppDefined, - ".bt file data type unknown, got datasize=%d.", nDataSize); - delete poDS; - return nullptr; - } - - /* - rcg, apr 7/06: read offset 62 for vert. units. - If zero, assume 1.0 as per spec. - - */ - memcpy(&poDS->m_fVscale, poDS->abyHeader + 62, 4); - CPL_LSBPTR32(&poDS->m_fVscale); - if (poDS->m_fVscale == 0.0f) - poDS->m_fVscale = 1.0f; - - /* -------------------------------------------------------------------- */ - /* Try to read a .prj file if it is indicated. */ - /* -------------------------------------------------------------------- */ - OGRSpatialReference oSRS; - oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - - if (poDS->nVersionCode >= 12 && poDS->abyHeader[60] != 0) - { - const std::string osPrjFile = - CPLResetExtensionSafe(poOpenInfo->pszFilename, "prj"); - VSILFILE *fp = VSIFOpenL(osPrjFile.c_str(), "rt"); - if (fp != nullptr) - { - const int nBufMax = 10000; - - char *pszBuffer = static_cast(CPLMalloc(nBufMax)); - const int nBytes = - static_cast(VSIFReadL(pszBuffer, 1, nBufMax - 1, fp)); - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - - pszBuffer[nBytes] = '\0'; - - if (oSRS.importFromWkt(pszBuffer) != OGRERR_NONE) - { - CPLError(CE_Warning, CPLE_AppDefined, - "Unable to parse .prj file, " - "coordinate system missing."); - } - CPLFree(pszBuffer); - } - } - - /* -------------------------------------------------------------------- */ - /* If we didn't find a .prj file, try to use internal info. */ - /* -------------------------------------------------------------------- */ - if (oSRS.GetRoot() == nullptr) - { - GInt16 nUTMZone = 0; - memcpy(&nUTMZone, poDS->abyHeader + 24, 2); - CPL_LSBPTR16(&nUTMZone); - - GInt16 nDatum = 0; - memcpy(&nDatum, poDS->abyHeader + 26, 2); - CPL_LSBPTR16(&nDatum); - - GInt16 nHUnits = 0; - memcpy(&nHUnits, poDS->abyHeader + 22, 2); - CPL_LSBPTR16(&nHUnits); - - if (nUTMZone != 0) - oSRS.SetUTM(std::abs(static_cast(nUTMZone)), nUTMZone > 0); - else if (nHUnits != 0) - oSRS.SetLocalCS("Unknown"); - - if (nHUnits == 1) - oSRS.SetLinearUnits(SRS_UL_METER, 1.0); - else if (nHUnits == 2) - oSRS.SetLinearUnits(SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV)); - else if (nHUnits == 3) - oSRS.SetLinearUnits(SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV)); - - // Translate some of the more obvious old USGS datum codes - if (nDatum == 0) - nDatum = 6201; - else if (nDatum == 1) - nDatum = 6209; - else if (nDatum == 2) - nDatum = 6210; - else if (nDatum == 3) - nDatum = 6202; - else if (nDatum == 4) - nDatum = 6203; - else if (nDatum == 6) - nDatum = 6222; - else if (nDatum == 7) - nDatum = 6230; - else if (nDatum == 13) - nDatum = 6267; - else if (nDatum == 14) - nDatum = 6269; - else if (nDatum == 17) - nDatum = 6277; - else if (nDatum == 19) - nDatum = 6284; - else if (nDatum == 21) - nDatum = 6301; - else if (nDatum == 22) - nDatum = 6322; - else if (nDatum == 23) - nDatum = 6326; - - if (!oSRS.IsLocal()) - { - if (nDatum >= 6000) - { - char szName[32]; - snprintf(szName, sizeof(szName), "EPSG:%d", nDatum - 2000); - oSRS.SetWellKnownGeogCS(szName); - } - else - oSRS.SetWellKnownGeogCS("WGS84"); - } - } - - /* -------------------------------------------------------------------- */ - /* Convert coordinate system back to WKT. */ - /* -------------------------------------------------------------------- */ - if (oSRS.GetRoot() != nullptr) - poDS->m_oSRS = std::move(oSRS); - - /* -------------------------------------------------------------------- */ - /* Get georeferencing bounds. */ - /* -------------------------------------------------------------------- */ - if (poDS->nVersionCode >= 11) - { - double dfLeft = 0.0; - memcpy(&dfLeft, poDS->abyHeader + 28, 8); - CPL_LSBPTR64(&dfLeft); - - double dfRight = 0.0; - memcpy(&dfRight, poDS->abyHeader + 36, 8); - CPL_LSBPTR64(&dfRight); - - double dfBottom = 0.0; - memcpy(&dfBottom, poDS->abyHeader + 44, 8); - CPL_LSBPTR64(&dfBottom); - - double dfTop = 0.0; - memcpy(&dfTop, poDS->abyHeader + 52, 8); - CPL_LSBPTR64(&dfTop); - - poDS->adfGeoTransform[0] = dfLeft; - poDS->adfGeoTransform[1] = (dfRight - dfLeft) / poDS->nRasterXSize; - poDS->adfGeoTransform[2] = 0.0; - poDS->adfGeoTransform[3] = dfTop; - poDS->adfGeoTransform[4] = 0.0; - poDS->adfGeoTransform[5] = (dfBottom - dfTop) / poDS->nRasterYSize; - - poDS->bGeoTransformValid = TRUE; - } - - poDS->eAccess = poOpenInfo->eAccess; - poDS->fpImage = poOpenInfo->fpL; - poOpenInfo->fpL = nullptr; - - /* -------------------------------------------------------------------- */ - /* Create band information objects */ - /* -------------------------------------------------------------------- */ - poDS->SetBand(1, new BTRasterBand(poDS, poDS->fpImage, eType)); - -#ifdef notdef - poDS->bGeoTransformValid = GDALReadWorldFile(poOpenInfo->pszFilename, - ".wld", poDS->adfGeoTransform); -#endif - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename); - - return poDS; -} - -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *BTDataset::Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - CPL_UNUSED char **papszOptions) -{ - - /* -------------------------------------------------------------------- */ - /* Verify input options. */ - /* -------------------------------------------------------------------- */ - if (eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_Float32) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create .bt dataset with an illegal " - "data type (%s), only Int16, Int32 and Float32 supported.", - GDALGetDataTypeName(eType)); - - return nullptr; - } - - if (nBandsIn != 1) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "Attempt to create .bt dataset with %d bands, only 1 supported", - nBandsIn); - - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Try to create the file. */ - /* -------------------------------------------------------------------- */ - VSILFILE *fp = VSIFOpenL(pszFilename, "wb"); - - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file `%s' failed.", pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Setup base header. */ - /* -------------------------------------------------------------------- */ - unsigned char abyHeader[256] = {}; - - memcpy(abyHeader, "binterr1.3", 10); - - GInt32 nTemp = CPL_LSBWORD32(nXSize); - memcpy(abyHeader + 10, &nTemp, 4); - - nTemp = CPL_LSBWORD32(nYSize); - memcpy(abyHeader + 14, &nTemp, 4); - - GInt16 nShortTemp = static_cast( - CPL_LSBWORD16((GInt16)(GDALGetDataTypeSize(eType) / 8))); - memcpy(abyHeader + 18, &nShortTemp, 2); - - if (eType == GDT_Float32) - abyHeader[20] = 1; - else - abyHeader[20] = 0; - - nShortTemp = CPL_LSBWORD16(1); /* meters */ - memcpy(abyHeader + 22, &nShortTemp, 2); - - nShortTemp = CPL_LSBWORD16(0); /* not utm */ - memcpy(abyHeader + 24, &nShortTemp, 2); - - nShortTemp = CPL_LSBWORD16(-2); /* datum unknown */ - memcpy(abyHeader + 26, &nShortTemp, 2); - - /* -------------------------------------------------------------------- */ - /* Set dummy extents. */ - /* -------------------------------------------------------------------- */ - double dfLeft = 0.0; - double dfRight = nXSize; - double dfTop = nYSize; - double dfBottom = 0.0; - - memcpy(abyHeader + 28, &dfLeft, 8); - memcpy(abyHeader + 36, &dfRight, 8); - memcpy(abyHeader + 44, &dfBottom, 8); - memcpy(abyHeader + 52, &dfTop, 8); - - CPL_LSBPTR64(abyHeader + 28); - CPL_LSBPTR64(abyHeader + 36); - CPL_LSBPTR64(abyHeader + 44); - CPL_LSBPTR64(abyHeader + 52); - - /* -------------------------------------------------------------------- */ - /* Set dummy scale. */ - /* -------------------------------------------------------------------- */ - float fScale = 1.0; - - memcpy(abyHeader + 62, &fScale, 4); - CPL_LSBPTR32(abyHeader + 62); - - /* -------------------------------------------------------------------- */ - /* Write to disk. */ - /* -------------------------------------------------------------------- */ - if (VSIFWriteL(abyHeader, 256, 1, fp) != 1 || - VSIFSeekL(fp, - static_cast(GDALGetDataTypeSizeBytes(eType)) * - nXSize * nYSize - - 1, - SEEK_CUR) != 0 || - VSIFWriteL(abyHeader + 255, 1, 1, fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to extent file to its full size, out of disk space?"); - - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - VSIUnlink(pszFilename); - return nullptr; - } - - if (VSIFCloseL(fp) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to extent file to its full size, out of disk space?"); - VSIUnlink(pszFilename); - return nullptr; - } - - return GDALDataset::Open(pszFilename, GDAL_OF_RASTER | GDAL_OF_UPDATE); -} - -/************************************************************************/ -/* GDALRegister_BT() */ -/************************************************************************/ - -void GDALRegister_BT() - -{ - if (GDALGetDriverByName("BT") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("BT"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, - "VTP .bt (Binary Terrain) 1.3 Format"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/bt.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "bt"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Int16 Int32 Float32"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = BTDataset::Open; - poDriver->pfnCreate = BTDataset::Create; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/raw/byndataset.cpp b/frmts/raw/byndataset.cpp index 406e2e7eb98c..4a9c12f951b0 100644 --- a/frmts/raw/byndataset.cpp +++ b/frmts/raw/byndataset.cpp @@ -91,17 +91,6 @@ double BYNRasterBand::GetScale(int *pbSuccess) return (dfFactor != 0.0) ? 1.0 / dfFactor : 0.0; } -/************************************************************************/ -/* SetScale() */ -/************************************************************************/ - -CPLErr BYNRasterBand::SetScale(double dfNewValue) -{ - BYNDataset *poIDS = reinterpret_cast(poDS); - poIDS->hHeader.dfFactor = 1.0 / dfNewValue; - return CE_None; -} - /************************************************************************/ /* ==================================================================== */ /* BYNDataset */ @@ -143,9 +132,6 @@ CPLErr BYNDataset::Close() if (BYNDataset::FlushCache(true) != CE_None) eErr = CE_Failure; - if (GetAccess() == GA_Update) - UpdateHeader(); - if (fpImage != nullptr) { if (VSIFCloseL(fpImage) != 0) @@ -253,7 +239,8 @@ int BYNDataset::Identify(GDALOpenInfo *poOpenInfo) GDALDataset *BYNDataset::Open(GDALOpenInfo *poOpenInfo) { - if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr) + if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr || + poOpenInfo->eAccess == GA_Update) return nullptr; /* -------------------------------------------------------------------- */ @@ -388,23 +375,6 @@ CPLErr BYNDataset::GetGeoTransform(double *padfTransform) return CE_None; } -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr BYNDataset::SetGeoTransform(double *padfTransform) - -{ - if (padfTransform[2] != 0.0 || padfTransform[4] != 0.0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to write skewed or rotated geotransform to byn."); - return CE_Failure; - } - memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6); - return CE_None; -} - /************************************************************************/ /* GetSpatialRef() */ /************************************************************************/ @@ -488,76 +458,6 @@ const OGRSpatialReference *BYNDataset::GetSpatialRef() const return nullptr; } -/************************************************************************/ -/* SetSpatialRef() */ -/************************************************************************/ - -CPLErr BYNDataset::SetSpatialRef(const OGRSpatialReference *poSRS) - -{ - if (poSRS == nullptr) - return CE_Failure; - - m_oSRS = *poSRS; - - /* Try to recognize prefefined EPSG compound CS */ - - if (poSRS->IsCompound()) - { - const char *pszAuthName = poSRS->GetAuthorityName("COMPD_CS"); - const char *pszAuthCode = poSRS->GetAuthorityCode("COMPD_CS"); - - if (pszAuthName != nullptr && pszAuthCode != nullptr && - EQUAL(pszAuthName, "EPSG") && - atoi(pszAuthCode) == BYN_DATUM_1_VDATUM_2) - { - hHeader.nVDatum = 2; - hHeader.nDatum = 1; - return CE_None; - } - } - - OGRSpatialReference oSRSTemp; - - /* Try to match GEOGCS */ - - if (poSRS->IsGeographic()) - { - oSRSTemp.importFromEPSG(BYN_DATUM_0); - if (poSRS->IsSameGeogCS(&oSRSTemp)) - hHeader.nDatum = 0; - else - { - oSRSTemp.importFromEPSG(BYN_DATUM_1); - if (poSRS->IsSameGeogCS(&oSRSTemp)) - hHeader.nDatum = 1; - } - } - - /* Try to match VERT_CS */ - - if (poSRS->IsVertical()) - { - oSRSTemp.importFromEPSG(BYN_VDATUM_1); - if (poSRS->IsSameVertCS(&oSRSTemp)) - hHeader.nVDatum = 1; - else - { - oSRSTemp.importFromEPSG(BYN_VDATUM_2); - if (poSRS->IsSameVertCS(&oSRSTemp)) - hHeader.nVDatum = 2; - else - { - oSRSTemp.importFromEPSG(BYN_VDATUM_3); - if (poSRS->IsSameVertCS(&oSRSTemp)) - hHeader.nVDatum = 3; - } - } - } - - return CE_None; -} - /*----------------------------------------------------------------------*/ /* buffer2header() */ /*----------------------------------------------------------------------*/ @@ -642,230 +542,6 @@ void BYNDataset::buffer2header(const GByte *pabyBuf, BYNHeader *pohHeader) #endif } -/*----------------------------------------------------------------------*/ -/* header2buffer() */ -/*----------------------------------------------------------------------*/ - -void BYNDataset::header2buffer(const BYNHeader *pohHeader, GByte *pabyBuf) - -{ - memcpy(pabyBuf, &pohHeader->nSouth, 4); - memcpy(pabyBuf + 4, &pohHeader->nNorth, 4); - memcpy(pabyBuf + 8, &pohHeader->nWest, 4); - memcpy(pabyBuf + 12, &pohHeader->nEast, 4); - memcpy(pabyBuf + 16, &pohHeader->nDLat, 2); - memcpy(pabyBuf + 18, &pohHeader->nDLon, 2); - memcpy(pabyBuf + 20, &pohHeader->nGlobal, 2); - memcpy(pabyBuf + 22, &pohHeader->nType, 2); - memcpy(pabyBuf + 24, &pohHeader->dfFactor, 8); - memcpy(pabyBuf + 32, &pohHeader->nSizeOf, 2); - memcpy(pabyBuf + 34, &pohHeader->nVDatum, 2); - memcpy(pabyBuf + 40, &pohHeader->nDescrip, 2); - memcpy(pabyBuf + 42, &pohHeader->nSubType, 2); - memcpy(pabyBuf + 44, &pohHeader->nDatum, 2); - memcpy(pabyBuf + 46, &pohHeader->nEllipsoid, 2); - memcpy(pabyBuf + 48, &pohHeader->nByteOrder, 2); - memcpy(pabyBuf + 50, &pohHeader->nScale, 2); - memcpy(pabyBuf + 52, &pohHeader->dfWo, 8); - memcpy(pabyBuf + 60, &pohHeader->dfGM, 8); - memcpy(pabyBuf + 68, &pohHeader->nTideSys, 2); - memcpy(pabyBuf + 70, &pohHeader->nRealiz, 2); - memcpy(pabyBuf + 72, &pohHeader->dEpoch, 4); - memcpy(pabyBuf + 76, &pohHeader->nPtType, 2); - -#if defined(CPL_MSB) - CPL_LSBPTR32(pabyBuf); - CPL_LSBPTR32(pabyBuf + 4); - CPL_LSBPTR32(pabyBuf + 8); - CPL_LSBPTR32(pabyBuf + 12); - CPL_LSBPTR16(pabyBuf + 16); - CPL_LSBPTR16(pabyBuf + 18); - CPL_LSBPTR16(pabyBuf + 20); - CPL_LSBPTR16(pabyBuf + 22); - CPL_LSBPTR64(pabyBuf + 24); - CPL_LSBPTR16(pabyBuf + 32); - CPL_LSBPTR16(pabyBuf + 34); - CPL_LSBPTR16(pabyBuf + 40); - CPL_LSBPTR16(pabyBuf + 42); - CPL_LSBPTR16(pabyBuf + 44); - CPL_LSBPTR16(pabyBuf + 46); - CPL_LSBPTR16(pabyBuf + 48); - CPL_LSBPTR16(pabyBuf + 50); - CPL_LSBPTR64(pabyBuf + 52); - CPL_LSBPTR64(pabyBuf + 60); - CPL_LSBPTR16(pabyBuf + 68); - CPL_LSBPTR16(pabyBuf + 70); - CPL_LSBPTR32(pabyBuf + 72); - CPL_LSBPTR16(pabyBuf + 76); -#endif -} - -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *BYNDataset::Create(const char *pszFilename, int nXSize, int nYSize, - int /* nBands */, GDALDataType eType, - char ** /* papszOptions */) -{ - if (eType != GDT_Int16 && eType != GDT_Int32) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create byn file with unsupported data type '%s'.", - GDALGetDataTypeName(eType)); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Check file extension (.byn/.err) */ - /* -------------------------------------------------------------------- */ - - const std::string osExt = CPLGetExtensionSafe(pszFilename); - - if (!EQUAL(osExt.c_str(), "byn") && !EQUAL(osExt.c_str(), "err")) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "Attempt to create byn file with extension other than byn/err."); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Try to create the file. */ - /* -------------------------------------------------------------------- */ - - VSILFILE *fp = VSIFOpenL(pszFilename, "wb+"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file `%s' failed.\n", pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Write an empty header. */ - /* -------------------------------------------------------------------- */ - - GByte abyBuf[BYN_HDR_SZ] = {'\0'}; - - /* Load header with some commum values */ - - BYNHeader hHeader = {0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0, 0, - 0, 0, 0, 0, 0, 0.0, 0.0, 0, 0, 0.0, 0}; - - /* Set temporary values on header */ - - hHeader.nSouth = 0; - hHeader.nNorth = nYSize - 2; - hHeader.nWest = 0; - hHeader.nEast = nXSize - 2; - hHeader.nDLat = 1; - hHeader.nDLon = 1; - hHeader.nSizeOf = static_cast(GDALGetDataTypeSizeBytes(eType)); - - /* Prepare buffer for writing */ - - header2buffer(&hHeader, abyBuf); - - /* Write initial header */ - - VSIFWriteL(abyBuf, BYN_HDR_SZ, 1, fp); - VSIFCloseL(fp); - - return GDALDataset::FromHandle(GDALOpen(pszFilename, GA_Update)); -} - -/************************************************************************/ -/* UpdateHeader() */ -/************************************************************************/ - -void BYNDataset::UpdateHeader() -{ - double dfDLon = (adfGeoTransform[1] * 3600.0); - double dfDLat = (adfGeoTransform[5] * 3600.0 * -1); - double dfWest = (adfGeoTransform[0] * 3600.0) + (dfDLon / 2); - double dfNorth = (adfGeoTransform[3] * 3600.0) - (dfDLat / 2); - double dfSouth = dfNorth - ((nRasterYSize - 1) * dfDLat); - double dfEast = dfWest + ((nRasterXSize - 1) * dfDLon); - - if (hHeader.nScale == 1) - { - dfSouth /= BYN_SCALE; - dfNorth /= BYN_SCALE; - dfWest /= BYN_SCALE; - dfEast /= BYN_SCALE; - dfDLat /= BYN_SCALE; - dfDLon /= BYN_SCALE; - } - - hHeader.nSouth = static_cast(dfSouth); - hHeader.nNorth = static_cast(dfNorth); - hHeader.nWest = static_cast(dfWest); - hHeader.nEast = static_cast(dfEast); - hHeader.nDLat = static_cast(dfDLat); - hHeader.nDLon = static_cast(dfDLon); - - GByte abyBuf[BYN_HDR_SZ]; - - header2buffer(&hHeader, abyBuf); - - const char *pszValue = GetMetadataItem("GLOBAL"); - if (pszValue != nullptr) - hHeader.nGlobal = static_cast(atoi(pszValue)); - - pszValue = GetMetadataItem("TYPE"); - if (pszValue != nullptr) - hHeader.nType = static_cast(atoi(pszValue)); - - pszValue = GetMetadataItem("DESCRIPTION"); - if (pszValue != nullptr) - hHeader.nDescrip = static_cast(atoi(pszValue)); - - pszValue = GetMetadataItem("SUBTYPE"); - if (pszValue != nullptr) - hHeader.nSubType = static_cast(atoi(pszValue)); - - pszValue = GetMetadataItem("WO"); - if (pszValue != nullptr) - hHeader.dfWo = CPLAtof(pszValue); - - pszValue = GetMetadataItem("GM"); - if (pszValue != nullptr) - hHeader.dfGM = CPLAtof(pszValue); - - pszValue = GetMetadataItem("TIDESYSTEM"); - if (pszValue != nullptr) - hHeader.nTideSys = static_cast(atoi(pszValue)); - - pszValue = GetMetadataItem("REALIZATION"); - if (pszValue != nullptr) - hHeader.nRealiz = static_cast(atoi(pszValue)); - - pszValue = GetMetadataItem("EPOCH"); - if (pszValue != nullptr) - hHeader.dEpoch = static_cast(CPLAtof(pszValue)); - - pszValue = GetMetadataItem("PTTYPE"); - if (pszValue != nullptr) - hHeader.nPtType = static_cast(atoi(pszValue)); - - CPL_IGNORE_RET_VAL(VSIFSeekL(fpImage, 0, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFWriteL(abyBuf, BYN_HDR_SZ, 1, fpImage)); - - /* GDALPam metadata update */ - - SetMetadataItem("GLOBAL", CPLSPrintf("%d", hHeader.nGlobal), "BYN"); - SetMetadataItem("TYPE", CPLSPrintf("%d", hHeader.nType), "BYN"); - SetMetadataItem("DESCRIPTION", CPLSPrintf("%d", hHeader.nDescrip), "BYN"); - SetMetadataItem("SUBTYPE", CPLSPrintf("%d", hHeader.nSubType), "BYN"); - SetMetadataItem("WO", CPLSPrintf("%g", hHeader.dfWo), "BYN"); - SetMetadataItem("GM", CPLSPrintf("%g", hHeader.dfGM), "BYN"); - SetMetadataItem("TIDESYSTEM", CPLSPrintf("%d", hHeader.nTideSys), "BYN"); - SetMetadataItem("REALIZATION", CPLSPrintf("%d", hHeader.nRealiz), "BYN"); - SetMetadataItem("EPOCH", CPLSPrintf("%g", hHeader.dEpoch), "BYN"); - SetMetadataItem("PTTYPE", CPLSPrintf("%d", hHeader.nPtType), "BYN"); -} - /************************************************************************/ /* GDALRegister_BYN() */ /************************************************************************/ @@ -885,11 +561,9 @@ void GDALRegister_BYN() poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "byn err"); poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/byn.html"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Int16 Int32"); poDriver->pfnOpen = BYNDataset::Open; poDriver->pfnIdentify = BYNDataset::Identify; - poDriver->pfnCreate = BYNDataset::Create; GetGDALDriverManager()->RegisterDriver(poDriver); } diff --git a/frmts/raw/byndataset.h b/frmts/raw/byndataset.h index ef2ecf8eaf71..42c49f513423 100644 --- a/frmts/raw/byndataset.h +++ b/frmts/raw/byndataset.h @@ -194,11 +194,8 @@ class BYNDataset final : public RawDataset mutable OGRSpatialReference m_oSRS{}; BYNHeader hHeader; - void UpdateHeader(); - CPL_DISALLOW_COPY_ASSIGN(BYNDataset) - static void header2buffer(const BYNHeader *pohHeader, GByte *pabyBuf); static void buffer2header(const GByte *pabyBuf, BYNHeader *pohHeader); CPLErr Close() override; @@ -208,16 +205,11 @@ class BYNDataset final : public RawDataset ~BYNDataset(); CPLErr GetGeoTransform(double *padfTransform) override; - CPLErr SetGeoTransform(double *padfTransform) override; const OGRSpatialReference *GetSpatialRef() const override; - CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override; static GDALDataset *Open(GDALOpenInfo *); static int Identify(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBands, GDALDataType eType, - char **papszOptions); }; /************************************************************************/ @@ -240,7 +232,6 @@ class BYNRasterBand final : public RawRasterBand double GetNoDataValue(int *pbSuccess = nullptr) override; double GetScale(int *pbSuccess = nullptr) override; - CPLErr SetScale(double dfNewValue) override; }; #endif // GDAL_FRMTS_RAW_BYNDATASET_H_INCLUDED diff --git a/frmts/raw/cpgdataset.cpp b/frmts/raw/cpgdataset.cpp index 9e65d4334f3f..d0207bf8b3e2 100644 --- a/frmts/raw/cpgdataset.cpp +++ b/frmts/raw/cpgdataset.cpp @@ -18,13 +18,6 @@ #include -enum Interleave -{ - BSQ, - BIL, - BIP -}; - /************************************************************************/ /* ==================================================================== */ /* CPGDataset */ @@ -53,7 +46,7 @@ class CPGDataset final : public RawDataset int nLoadedStokesLine; float *padfStokesMatrix; - int nInterleave; + Interleave eInterleave = Interleave::BSQ; static int AdjustFilename(char **, const char *, const char *); static int FindType1(const char *pszWorkname); static int FindType2(const char *pszWorkname); @@ -101,7 +94,7 @@ class CPGDataset final : public RawDataset CPGDataset::CPGDataset() : nGCPCount(0), pasGCPList(nullptr), nLoadedStokesLine(-1), - padfStokesMatrix(nullptr), nInterleave(0) + padfStokesMatrix(nullptr) { m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); m_oGCPSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); @@ -377,7 +370,7 @@ CPLErr CPGDataset::LoadStokesLine(int iLine, int bNativeOrder) /* Load all the pixel data associated with this scanline. */ /* Retains same interleaving as original dataset. */ /* -------------------------------------------------------------------- */ - if (nInterleave == BIP) + if (eInterleave == Interleave::BIP) { const int offset = nRasterXSize * iLine * nDataSize * 16; const int nBytesToRead = nDataSize * nRasterXSize * 16; @@ -396,7 +389,7 @@ CPLErr CPGDataset::LoadStokesLine(int iLine, int bNativeOrder) return CE_Failure; } } - else if (nInterleave == BIL) + else if (eInterleave == Interleave::BIL) { for (int band_index = 0; band_index < 16; band_index++) { @@ -810,7 +803,8 @@ GDALDataset *CPGDataset::InitializeType1Or2Dataset(const char *pszFilename) GDALDataset *CPGDataset::InitializeType3Dataset(const char *pszFilename) { int iBytesPerPixel = 0; - int iInterleave = -1; + Interleave::eInterleave = Interleave::BSQ; + bool bInterleaveSpecified = false; int nLines = 0; int nSamples = 0; int nBands = 0; @@ -845,11 +839,20 @@ GDALDataset *CPGDataset::InitializeType3Dataset(const char *pszFilename) { if (STARTS_WITH_CI(papszTokens[2], "BSQ")) - iInterleave = BSQ; + { + bInterleaveSpecified = true; + eInterleave = Interleave::BSQ; + } else if (STARTS_WITH_CI(papszTokens[2], "BIL")) - iInterleave = BIL; + { + bInterleaveSpecified = true; + eInterleave = Interleave::BIL; + } else if (STARTS_WITH_CI(papszTokens[2], "BIP")) - iInterleave = BIP; + { + bInterleaveSpecified = true; + eInterleave = Interleave::BIP; + } else { CPLError( @@ -979,7 +982,7 @@ GDALDataset *CPGDataset::InitializeType3Dataset(const char *pszFilename) } if (!GDALCheckDatasetDimensions(nSamples, nLines) || - !GDALCheckBandCount(nBands, FALSE) || iInterleave == -1 || + !GDALCheckBandCount(nBands, FALSE) || !bInterleaveSpecified || iBytesPerPixel == 0) { CPLError(CE_Failure, CPLE_AppDefined, @@ -998,13 +1001,7 @@ GDALDataset *CPGDataset::InitializeType3Dataset(const char *pszFilename) poDS->nRasterXSize = nSamples; poDS->nRasterYSize = nLines; - - if (iInterleave == BSQ) - poDS->nInterleave = BSQ; - else if (iInterleave == BIL) - poDS->nInterleave = BIL; - else - poDS->nInterleave = BIP; + poDS->eInterleave = eInterleave; /* -------------------------------------------------------------------- */ /* Open the 16 bands. */ @@ -1395,7 +1392,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, float *M = poGDS->padfStokesMatrix; float *pafLine = reinterpret_cast(pImage); - if (poGDS->nInterleave == BIP) + if (poGDS->eInterleave == RawDataset::Interleave::BIP) { step = 16; m11 = M11; diff --git a/frmts/raw/ctable2dataset.cpp b/frmts/raw/ctable2dataset.cpp deleted file mode 100644 index f1e1250751e4..000000000000 --- a/frmts/raw/ctable2dataset.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/****************************************************************************** - * - * Project: Horizontal Datum Formats - * Purpose: Implementation of the CTable2 format, a PROJ.4 specific format - * that is more compact (due to a lack of unused error band) than NTv2 - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2012, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "gdal_frmts.h" -#include "ogr_srs_api.h" -#include "rawdataset.h" - -#include - -/************************************************************************/ -/* ==================================================================== */ -/* CTable2Dataset */ -/* ==================================================================== */ -/************************************************************************/ - -class CTable2Dataset final : public RawDataset -{ - VSILFILE *fpImage; // image data file. - - double adfGeoTransform[6]; - OGRSpatialReference m_oSRS{}; - - CPL_DISALLOW_COPY_ASSIGN(CTable2Dataset) - - CPLErr Close() override; - - public: - CTable2Dataset(); - ~CTable2Dataset() override; - - CPLErr SetGeoTransform(double *padfTransform) override; - CPLErr GetGeoTransform(double *padfTransform) override; - - const OGRSpatialReference *GetSpatialRef() const override - { - return &m_oSRS; - } - - static GDALDataset *Open(GDALOpenInfo *); - static int Identify(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBands, GDALDataType eType, - char **papszOptions); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* CTable2Dataset */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* CTable2Dataset() */ -/************************************************************************/ - -CTable2Dataset::CTable2Dataset() : fpImage(nullptr) -{ - m_oSRS.SetFromUserInput(SRS_WKT_WGS84_LAT_LONG); - m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - - memset(adfGeoTransform, 0, sizeof(adfGeoTransform)); -} - -/************************************************************************/ -/* ~CTable2Dataset() */ -/************************************************************************/ - -CTable2Dataset::~CTable2Dataset() - -{ - CTable2Dataset::Close(); -} - -/************************************************************************/ -/* Close() */ -/************************************************************************/ - -CPLErr CTable2Dataset::Close() -{ - CPLErr eErr = CE_None; - if (nOpenFlags != OPEN_FLAGS_CLOSED) - { - if (CTable2Dataset::FlushCache(true) != CE_None) - eErr = CE_Failure; - - if (fpImage != nullptr) - { - if (VSIFCloseL(fpImage) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, "I/O error"); - eErr = CE_Failure; - } - } - - if (GDALPamDataset::Close() != CE_None) - eErr = CE_Failure; - } - return eErr; -} - -/************************************************************************/ -/* Identify() */ -/************************************************************************/ - -int CTable2Dataset::Identify(GDALOpenInfo *poOpenInfo) - -{ - if (poOpenInfo->nHeaderBytes < 64) - return FALSE; - - if (!STARTS_WITH_CI( - reinterpret_cast(poOpenInfo->pabyHeader + 0), - "CTABLE V2")) - return FALSE; - - return TRUE; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *CTable2Dataset::Open(GDALOpenInfo *poOpenInfo) - -{ - if (!Identify(poOpenInfo) || !poOpenInfo->fpL) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Create a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - auto poDS = std::make_unique(); - poDS->eAccess = poOpenInfo->eAccess; - std::swap(poDS->fpImage, poOpenInfo->fpL); - - /* -------------------------------------------------------------------- */ - /* Read the file header. */ - /* -------------------------------------------------------------------- */ - - CPL_IGNORE_RET_VAL(VSIFSeekL(poDS->fpImage, 0, SEEK_SET)); - - char achHeader[160] = {'\0'}; - CPL_IGNORE_RET_VAL(VSIFReadL(achHeader, 1, 160, poDS->fpImage)); - achHeader[16 + 79] = '\0'; - - CPLString osDescription = reinterpret_cast(achHeader + 16); - osDescription.Trim(); - poDS->SetMetadataItem("DESCRIPTION", osDescription); - - /* -------------------------------------------------------------------- */ - /* Convert from LSB to local machine byte order. */ - /* -------------------------------------------------------------------- */ - CPL_LSBPTR64(achHeader + 96); - CPL_LSBPTR64(achHeader + 104); - CPL_LSBPTR64(achHeader + 112); - CPL_LSBPTR64(achHeader + 120); - CPL_LSBPTR32(achHeader + 128); - CPL_LSBPTR32(achHeader + 132); - - /* -------------------------------------------------------------------- */ - /* Extract size, and geotransform. */ - /* -------------------------------------------------------------------- */ - int nRasterXSize, nRasterYSize; - memcpy(&nRasterXSize, achHeader + 128, 4); - memcpy(&nRasterYSize, achHeader + 132, 4); - if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) || - /* to avoid overflow in later -8 * nRasterXSize computation */ - nRasterXSize >= INT_MAX / 8) - { - return nullptr; - } - - poDS->nRasterXSize = nRasterXSize; - poDS->nRasterYSize = nRasterYSize; - - double adfValues[4]; - memcpy(adfValues, achHeader + 96, sizeof(double) * 4); - - for (int i = 0; i < 4; i++) - adfValues[i] *= 180 / M_PI; // Radians to degrees. - - poDS->adfGeoTransform[0] = adfValues[0] - adfValues[2] * 0.5; - poDS->adfGeoTransform[1] = adfValues[2]; - poDS->adfGeoTransform[2] = 0.0; - poDS->adfGeoTransform[3] = - adfValues[1] + adfValues[3] * (nRasterYSize - 0.5); - poDS->adfGeoTransform[4] = 0.0; - poDS->adfGeoTransform[5] = -adfValues[3]; - - /* -------------------------------------------------------------------- */ - /* Setup the bands. */ - /* -------------------------------------------------------------------- */ - auto poBand = - RawRasterBand::Create(poDS.get(), 1, poDS->fpImage, - 160 + 4 + - static_cast(nRasterXSize) * - (nRasterYSize - 1) * 2 * 4, - 8, -8 * nRasterXSize, GDT_Float32, - RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN, - RawRasterBand::OwnFP::NO); - if (!poBand) - return nullptr; - poBand->SetDescription("Latitude Offset (radians)"); - poDS->SetBand(1, std::move(poBand)); - - poBand = - RawRasterBand::Create(poDS.get(), 2, poDS->fpImage, - 160 + static_cast(nRasterXSize) * - (nRasterYSize - 1) * 2 * 4, - 8, -8 * nRasterXSize, GDT_Float32, - RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN, - RawRasterBand::OwnFP::NO); - if (!poBand) - return nullptr; - poBand->SetDescription("Longitude Offset (radians)"); - poBand->SetMetadataItem("positive_value", "west"); - poDS->SetBand(2, std::move(poBand)); - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename); - - return poDS.release(); -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr CTable2Dataset::GetGeoTransform(double *padfTransform) - -{ - memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6); - return CE_None; -} - -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr CTable2Dataset::SetGeoTransform(double *padfTransform) - -{ - if (eAccess == GA_ReadOnly) - { - CPLError(CE_Failure, CPLE_NoWriteAccess, - "Unable to update geotransform on readonly file."); - return CE_Failure; - } - - if (padfTransform[2] != 0.0 || padfTransform[4] != 0.0) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "Rotated and sheared geotransforms not supported for CTable2."); - return CE_Failure; - } - - memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6); - - /* -------------------------------------------------------------------- */ - /* Update grid header. */ - /* -------------------------------------------------------------------- */ - const double dfDegToRad = M_PI / 180.0; - - // read grid header - CPL_IGNORE_RET_VAL(VSIFSeekL(fpImage, 0, SEEK_SET)); - - char achHeader[160] = {'\0'}; - CPL_IGNORE_RET_VAL(VSIFReadL(achHeader, 1, sizeof(achHeader), fpImage)); - - // lower left origin (longitude, center of pixel, radians) - double dfValue = - (adfGeoTransform[0] + adfGeoTransform[1] * 0.5) * dfDegToRad; - CPL_LSBPTR64(&dfValue); - memcpy(achHeader + 96, &dfValue, 8); - - // lower left origin (latitude, center of pixel, radians) - dfValue = (adfGeoTransform[3] + adfGeoTransform[5] * (nRasterYSize - 0.5)) * - dfDegToRad; - CPL_LSBPTR64(&dfValue); - memcpy(achHeader + 104, &dfValue, 8); - - // pixel width (radians) - dfValue = adfGeoTransform[1] * dfDegToRad; - CPL_LSBPTR64(&dfValue); - memcpy(achHeader + 112, &dfValue, 8); - - // pixel height (radians) - dfValue = adfGeoTransform[5] * -1 * dfDegToRad; - CPL_LSBPTR64(&dfValue); - memcpy(achHeader + 120, &dfValue, 8); - - // write grid header. - CPL_IGNORE_RET_VAL(VSIFSeekL(fpImage, 0, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFWriteL(achHeader, 1, sizeof(achHeader), fpImage)); - - return CE_None; -} - -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *CTable2Dataset::Create(const char *pszFilename, int nXSize, - int nYSize, int /* nBandsIn */, - GDALDataType eType, char **papszOptions) -{ - if (eType != GDT_Float32) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "Attempt to create CTable2 file with unsupported data type '%s'.", - GDALGetDataTypeName(eType)); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Try to open or create file. */ - /* -------------------------------------------------------------------- */ - VSILFILE *fp = VSIFOpenL(pszFilename, "wb"); - - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file `%s' failed.\n", pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create a file header, with a defaulted georeferencing. */ - /* -------------------------------------------------------------------- */ - char achHeader[160] = {'\0'}; - - memset(achHeader, 0, sizeof(achHeader)); - - memcpy(achHeader + 0, "CTABLE V2.0 ", 16); - - if (CSLFetchNameValue(papszOptions, "DESCRIPTION") != nullptr) - strncpy(achHeader + 16, CSLFetchNameValue(papszOptions, "DESCRIPTION"), - 80); - - // lower left origin (longitude, center of pixel, radians) - double dfValue = 0; - CPL_LSBPTR64(&dfValue); - memcpy(achHeader + 96, &dfValue, 8); - - // lower left origin (latitude, center of pixel, radians) - dfValue = 0; - CPL_LSBPTR64(&dfValue); - memcpy(achHeader + 104, &dfValue, 8); - - // pixel width (radians) - dfValue = 0.01 * M_PI / 180.0; - CPL_LSBPTR64(&dfValue); - memcpy(achHeader + 112, &dfValue, 8); - - // pixel height (radians) - dfValue = 0.01 * M_PI / 180.0; - CPL_LSBPTR64(&dfValue); - memcpy(achHeader + 120, &dfValue, 8); - - // raster width in pixels - int nValue32 = nXSize; - CPL_LSBPTR32(&nValue32); - memcpy(achHeader + 128, &nValue32, 4); - - // raster width in pixels - nValue32 = nYSize; - CPL_LSBPTR32(&nValue32); - memcpy(achHeader + 132, &nValue32, 4); - - CPL_IGNORE_RET_VAL(VSIFWriteL(achHeader, 1, sizeof(achHeader), fp)); - - /* -------------------------------------------------------------------- */ - /* Write zeroed grid data. */ - /* -------------------------------------------------------------------- */ - float *pafLine = static_cast(CPLCalloc(sizeof(float) * 2, nXSize)); - - for (int i = 0; i < nYSize; i++) - { - if (static_cast( - VSIFWriteL(pafLine, sizeof(float) * 2, nXSize, fp)) != nXSize) - { - CPLError(CE_Failure, CPLE_FileIO, - "Write failed at line %d, perhaps the disk is full?", i); - return nullptr; - } - } - - /* -------------------------------------------------------------------- */ - /* Cleanup and return. */ - /* -------------------------------------------------------------------- */ - CPLFree(pafLine); - - if (VSIFCloseL(fp) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, "I/O error"); - return nullptr; - } - - return static_cast(GDALOpen(pszFilename, GA_Update)); -} - -/************************************************************************/ -/* GDALRegister_CTable2() */ -/************************************************************************/ - -void GDALRegister_CTable2() - -{ - if (GDALGetDriverByName("CTable2") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("CTable2"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "CTable2 Datum Grid Shift"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32"); - - poDriver->pfnOpen = CTable2Dataset::Open; - poDriver->pfnIdentify = CTable2Dataset::Identify; - poDriver->pfnCreate = CTable2Dataset::Create; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/raw/dipxdataset.cpp b/frmts/raw/dipxdataset.cpp deleted file mode 100644 index 5b9fdcddff8d..000000000000 --- a/frmts/raw/dipxdataset.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL - * Purpose: Implementation for ELAS DIPEx format variant. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2006, Frank Warmerdam - * Copyright (c) 2008-2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "gdal_frmts.h" -#include "ogr_spatialref.h" -#include "rawdataset.h" - -#include -#include - -using std::fill; - -/************************************************************************/ -/* ==================================================================== */ -/* DIPExDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class DIPExDataset final : public GDALPamDataset -{ - struct DIPExHeader - { - GInt32 NBIH = {0}; /* bytes in header, normally 1024 */ - GInt32 NBPR = {0}; /* bytes per data record (all bands of scanline) */ - GInt32 IL = {0}; /* initial line - normally 1 */ - GInt32 LL = {0}; /* last line */ - GInt32 IE = {0}; /* initial element (pixel), normally 1 */ - GInt32 LE = {0}; /* last element (pixel) */ - GInt32 NC = {0}; /* number of channels (bands) */ - GInt32 H4322 = {0}; /* header record identifier - always 4322. */ - char unused1[40] = {0}; - GByte IH19[4] = {0}; /* data type, and size flags */ - GInt32 IH20 = {0}; /* number of secondary headers */ - GInt32 SRID = {0}; - char unused2[12] = {0}; - double YOffset = {0}; - double XOffset = {0}; - double YPixSize = {0}; - double XPixSize = {0}; - double Matrix[4] = {0}; - char unused3[344] = {0}; - GUInt16 ColorTable[256] = {0}; /* RGB packed with 4 bits each */ - char unused4[32] = {0}; - }; - - VSILFILE *fp; - OGRSpatialReference m_oSRS{}; - - DIPExHeader sHeader{}; - - GDALDataType eRasterDataType; - - double adfGeoTransform[6]; - - CPL_DISALLOW_COPY_ASSIGN(DIPExDataset) - - public: - DIPExDataset(); - ~DIPExDataset() override; - - CPLErr GetGeoTransform(double *) override; - - const OGRSpatialReference *GetSpatialRef() const override - { - return m_oSRS.IsEmpty() ? nullptr : &m_oSRS; - } - - static GDALDataset *Open(GDALOpenInfo *); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* DIPExDataset */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* DIPExDataset() */ -/************************************************************************/ - -DIPExDataset::DIPExDataset() : fp(nullptr), eRasterDataType(GDT_Unknown) -{ - m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - adfGeoTransform[0] = 0.0; - adfGeoTransform[1] = 1.0; - adfGeoTransform[2] = 0.0; - adfGeoTransform[3] = 0.0; - adfGeoTransform[4] = 0.0; - adfGeoTransform[5] = 1.0; -} - -/************************************************************************/ -/* ~DIPExDataset() */ -/************************************************************************/ - -DIPExDataset::~DIPExDataset() - -{ - if (fp) - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - fp = nullptr; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *DIPExDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - /* -------------------------------------------------------------------- */ - /* First we check to see if the file has the expected header */ - /* bytes. */ - /* -------------------------------------------------------------------- */ - if (poOpenInfo->nHeaderBytes < 256 || poOpenInfo->fpL == nullptr) - return nullptr; - - if (CPL_LSBWORD32( - *(reinterpret_cast(poOpenInfo->pabyHeader + 0))) != 1024) - return nullptr; - - if (CPL_LSBWORD32( - *(reinterpret_cast(poOpenInfo->pabyHeader + 28))) != 4322) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Create a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - auto poDS = std::make_unique(); - - poDS->eAccess = poOpenInfo->eAccess; - poDS->fp = poOpenInfo->fpL; - poOpenInfo->fpL = nullptr; - - /* -------------------------------------------------------------------- */ - /* Read the header information. */ - /* -------------------------------------------------------------------- */ - if (VSIFReadL(&(poDS->sHeader), 1024, 1, poDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Attempt to read 1024 byte header filed on file %s\n", - poOpenInfo->pszFilename); - return nullptr; - } - - // To avoid cppcheck warnings about unused members - CPL_IGNORE_RET_VAL(poDS->sHeader.NBIH); - CPL_IGNORE_RET_VAL(poDS->sHeader.H4322); - CPL_IGNORE_RET_VAL(poDS->sHeader.unused1); - CPL_IGNORE_RET_VAL(poDS->sHeader.IH20); - CPL_IGNORE_RET_VAL(poDS->sHeader.unused2); - CPL_IGNORE_RET_VAL(poDS->sHeader.Matrix); - CPL_IGNORE_RET_VAL(poDS->sHeader.unused3); - CPL_IGNORE_RET_VAL(poDS->sHeader.ColorTable); - CPL_IGNORE_RET_VAL(poDS->sHeader.unused4); - - /* -------------------------------------------------------------------- */ - /* Extract information of interest from the header. */ - /* -------------------------------------------------------------------- */ - const int nLineOffset = CPL_LSBWORD32(poDS->sHeader.NBPR); - - int nStart = CPL_LSBWORD32(poDS->sHeader.IL); - int nEnd = CPL_LSBWORD32(poDS->sHeader.LL); - GIntBig nDiff = static_cast(nEnd) - nStart + 1; - if (nDiff <= 0 || nDiff > INT_MAX) - { - return nullptr; - } - poDS->nRasterYSize = static_cast(nDiff); - - nStart = CPL_LSBWORD32(poDS->sHeader.IE); - nEnd = CPL_LSBWORD32(poDS->sHeader.LE); - nDiff = static_cast(nEnd) - nStart + 1; - if (nDiff <= 0 || nDiff > INT_MAX) - { - return nullptr; - } - poDS->nRasterXSize = static_cast(nDiff); - - const int nBands = CPL_LSBWORD32(poDS->sHeader.NC); - - if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || - !GDALCheckBandCount(nBands, FALSE)) - { - return nullptr; - } - - const int nDIPExDataType = (poDS->sHeader.IH19[1] & 0x7e) >> 2; - const int nBytesPerSample = poDS->sHeader.IH19[0]; - - if (nDIPExDataType == 0 && nBytesPerSample == 1) - poDS->eRasterDataType = GDT_Byte; - else if (nDIPExDataType == 1 && nBytesPerSample == 1) - poDS->eRasterDataType = GDT_Byte; - else if (nDIPExDataType == 16 && nBytesPerSample == 4) - poDS->eRasterDataType = GDT_Float32; - else if (nDIPExDataType == 17 && nBytesPerSample == 8) - poDS->eRasterDataType = GDT_Float64; - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "Unrecognized image data type %d, with BytesPerSample=%d.", - nDIPExDataType, nBytesPerSample); - return nullptr; - } - - if (nLineOffset <= 0 || nLineOffset > INT_MAX / nBands) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Invalid values: nLineOffset = %d, nBands = %d.", nLineOffset, - nBands); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create band information objects. */ - /* -------------------------------------------------------------------- */ - CPLErrorReset(); - for (int iBand = 0; iBand < nBands; iBand++) - { - auto poBand = RawRasterBand::Create( - poDS.get(), iBand + 1, poDS->fp, 1024 + iBand * nLineOffset, - nBytesPerSample, nLineOffset * nBands, poDS->eRasterDataType, - RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN, - RawRasterBand::OwnFP::NO); - if (!poBand) - return nullptr; - poDS->SetBand(iBand + 1, std::move(poBand)); - } - - /* -------------------------------------------------------------------- */ - /* Extract the projection coordinates, if present. */ - /* -------------------------------------------------------------------- */ - CPL_LSBPTR64(&(poDS->sHeader.XPixSize)); - CPL_LSBPTR64(&(poDS->sHeader.YPixSize)); - CPL_LSBPTR64(&(poDS->sHeader.XOffset)); - CPL_LSBPTR64(&(poDS->sHeader.YOffset)); - - if (poDS->sHeader.XOffset != 0) - { - poDS->adfGeoTransform[0] = poDS->sHeader.XOffset; - poDS->adfGeoTransform[1] = poDS->sHeader.XPixSize; - poDS->adfGeoTransform[2] = 0.0; - poDS->adfGeoTransform[3] = poDS->sHeader.YOffset; - poDS->adfGeoTransform[4] = 0.0; - poDS->adfGeoTransform[5] = -1.0 * std::abs(poDS->sHeader.YPixSize); - - poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5; - poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5; - } - else - { - poDS->adfGeoTransform[0] = 0.0; - poDS->adfGeoTransform[1] = 1.0; - poDS->adfGeoTransform[2] = 0.0; - poDS->adfGeoTransform[3] = 0.0; - poDS->adfGeoTransform[4] = 0.0; - poDS->adfGeoTransform[5] = 1.0; - } - - /* -------------------------------------------------------------------- */ - /* Look for SRID. */ - /* -------------------------------------------------------------------- */ - CPL_LSBPTR32(&(poDS->sHeader.SRID)); - - if (poDS->sHeader.SRID > 0 && poDS->sHeader.SRID < 33000) - { - OGRSpatialReference oSR; - oSR.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - if (oSR.importFromEPSG(poDS->sHeader.SRID) == OGRERR_NONE) - { - poDS->m_oSRS = std::move(oSR); - } - } - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for external overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename, - poOpenInfo->GetSiblingFiles()); - - return poDS.release(); -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr DIPExDataset::GetGeoTransform(double *padfTransform) - -{ - memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6); - - return CE_None; -} - -/************************************************************************/ -/* GDALRegister_DIPEx() */ -/************************************************************************/ - -void GDALRegister_DIPEx() - -{ - if (GDALGetDriverByName("DIPEx") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("DIPEx"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "DIPEx"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = DIPExDataset::Open; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/raw/envidataset.cpp b/frmts/raw/envidataset.cpp index 184682e29b62..f63c82f1fb44 100644 --- a/frmts/raw/envidataset.cpp +++ b/frmts/raw/envidataset.cpp @@ -85,8 +85,7 @@ static int ITTVISToUSGSZone(int nITTVISZone) ENVIDataset::ENVIDataset() : fpImage(nullptr), fp(nullptr), pszHDRFilename(nullptr), - bFoundMapinfo(false), bHeaderDirty(false), bFillFile(false), - interleave(BSQ) + bFoundMapinfo(false), bHeaderDirty(false), bFillFile(false) { adfGeoTransform[0] = 0.0; adfGeoTransform[1] = 1.0; @@ -217,15 +216,15 @@ CPLErr ENVIDataset::FlushCache(bool bAtClosing) const int iENVIType = GetEnviType(band->GetRasterDataType()); bOK &= VSIFPrintfL(fp, "data type = %d\n", iENVIType) >= 0; const char *pszInterleaving = nullptr; - switch (interleave) + switch (eInterleave) { - case BIP: + case Interleave::BIP: pszInterleaving = "bip"; // Interleaved by pixel. break; - case BIL: + case Interleave::BIL: pszInterleaving = "bil"; // Interleaved by line. break; - case BSQ: + case Interleave::BSQ: pszInterleaving = "bsq"; // Band sequential by default. break; default: @@ -2294,7 +2293,7 @@ ENVIDataset *ENVIDataset::Open(GDALOpenInfo *poOpenInfo, bool bFileSizeCheck) if (STARTS_WITH_CI(osInterleave, "bil")) { - poDS->interleave = BIL; + poDS->eInterleave = Interleave::BIL; poDS->SetMetadataItem("INTERLEAVE", "LINE", "IMAGE_STRUCTURE"); if (nSamples > std::numeric_limits::max() / (nDataSize * nBands)) { @@ -2307,7 +2306,7 @@ ENVIDataset *ENVIDataset::Open(GDALOpenInfo *poOpenInfo, bool bFileSizeCheck) } else if (STARTS_WITH_CI(osInterleave, "bip")) { - poDS->interleave = BIP; + poDS->eInterleave = Interleave::BIP; poDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE"); if (nSamples > std::numeric_limits::max() / (nDataSize * nBands)) { @@ -2320,7 +2319,7 @@ ENVIDataset *ENVIDataset::Open(GDALOpenInfo *poOpenInfo, bool bFileSizeCheck) } else { - poDS->interleave = BSQ; + poDS->eInterleave = Interleave::BSQ; poDS->SetMetadataItem("INTERLEAVE", "BAND", "IMAGE_STRUCTURE"); if (nSamples > std::numeric_limits::max() / nDataSize) { diff --git a/frmts/raw/envidataset.h b/frmts/raw/envidataset.h index b42b50f5759d..6e7588b05eeb 100644 --- a/frmts/raw/envidataset.h +++ b/frmts/raw/envidataset.h @@ -65,6 +65,8 @@ class ENVIDataset final : public RawDataset std::vector m_asGCPs{}; + Interleave eInterleave = Interleave::BSQ; + bool ReadHeader(VSILFILE *); bool ProcessMapinfo(const char *); void ProcessRPCinfo(const char *, int, int); @@ -88,13 +90,6 @@ class ENVIDataset final : public RawDataset static char **SplitList(const char *); - enum Interleave - { - BSQ, - BIL, - BIP - } interleave; - static int GetEnviType(GDALDataType eType); CPL_DISALLOW_COPY_ASSIGN(ENVIDataset) diff --git a/frmts/raw/hkvdataset.cpp b/frmts/raw/hkvdataset.cpp index 5dc12dfd9357..31b579e533c3 100644 --- a/frmts/raw/hkvdataset.cpp +++ b/frmts/raw/hkvdataset.cpp @@ -43,8 +43,6 @@ class HKVRasterBand final : public RawRasterBand ~HKVRasterBand() override { } - - CPLErr SetNoDataValue(double) override; }; /************************************************************************/ @@ -186,10 +184,6 @@ HKVSpheroidList ::HKVSpheroidList() 299.1976073); } -CPLErr SaveHKVAttribFile(const char *pszFilenameIn, int nXSize, int nYSize, - int nBands, GDALDataType eType, int bNoDataSet, - double dfNoDataValue); - /************************************************************************/ /* ==================================================================== */ /* HKVDataset */ @@ -227,7 +221,6 @@ class HKVDataset final : public RawDataset char **papszAttrib; - bool bGeorefChanged; char **papszGeoref; // NOTE: The MFF2 format goes against GDAL's API in that nodata values are @@ -236,7 +229,6 @@ class HKVDataset final : public RawDataset // the raster bands. bool bNoDataSet; - bool bNoDataChanged; double dfNoDataValue; CPL_DISALLOW_COPY_ASSIGN(HKVDataset) @@ -266,20 +258,7 @@ class HKVDataset final : public RawDataset CPLErr GetGeoTransform(double *) override; - CPLErr SetGeoTransform(double *) override; - CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override; - static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBands, GDALDataType eType, - char **papszParamList); - static GDALDataset *CreateCopy(const char *pszFilename, - GDALDataset *poSrcDS, int bStrict, - char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); - - static CPLErr Delete(const char *pszName); }; /************************************************************************/ @@ -308,20 +287,6 @@ HKVRasterBand::HKVRasterBand(HKVDataset *poDSIn, int nBandIn, VSILFILE *fpRawIn, nBlockYSize = 1; } -/************************************************************************/ -/* SetNoDataValue() */ -/************************************************************************/ - -CPLErr HKVRasterBand::SetNoDataValue(double dfNewValue) - -{ - HKVDataset *poHKVDS = reinterpret_cast(poDS); - RawRasterBand::SetNoDataValue(dfNewValue); - poHKVDS->SetNoDataValue(dfNewValue); - - return CE_None; -} - /************************************************************************/ /* ==================================================================== */ /* HKVDataset */ @@ -336,8 +301,7 @@ HKVDataset::HKVDataset() : pszPath(nullptr), fpBlob(nullptr), nGCPCount(0), pasGCPList(nullptr), // Initialize datasets to new version; change if necessary. MFF2version(1.1f), eRasterType(GDT_Unknown), papszAttrib(nullptr), - bGeorefChanged(false), papszGeoref(nullptr), bNoDataSet(false), - bNoDataChanged(false), dfNoDataValue(0.0) + papszGeoref(nullptr), bNoDataSet(false), dfNoDataValue(0.0) { m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); m_oGCPSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); @@ -371,19 +335,6 @@ CPLErr HKVDataset::Close() if (HKVDataset::FlushCache(true) != CE_None) eErr = CE_Failure; - if (bGeorefChanged) - { - const std::string osFilename = - CPLFormFilenameSafe(pszPath, "georef", nullptr); - CSLSave(papszGeoref, osFilename.c_str()); - } - - if (bNoDataChanged) - { - SaveHKVAttribFile(pszPath, nRasterXSize, nRasterYSize, nBands, - eRasterType, bNoDataSet, dfNoDataValue); - } - if (fpBlob) { if (VSIFCloseL(fpBlob) != 0) @@ -409,94 +360,6 @@ CPLErr HKVDataset::Close() return eErr; } -/************************************************************************/ -/* SetNoDataValue() */ -/************************************************************************/ - -void HKVDataset::SetNoDataValue(double dfNewValue) - -{ - bNoDataSet = true; - bNoDataChanged = true; - dfNoDataValue = dfNewValue; -} - -/************************************************************************/ -/* SaveHKVAttribFile() */ -/************************************************************************/ - -CPLErr SaveHKVAttribFile(const char *pszFilenameIn, int nXSize, int nYSize, - int nBands, GDALDataType eType, int bNoDataSet, - double dfNoDataValue) - -{ - const std::string osFilename = - CPLFormFilenameSafe(pszFilenameIn, "attrib", nullptr); - - FILE *fp = VSIFOpen(osFilename.c_str(), "wt"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Couldn't create %s.", - osFilename.c_str()); - return CE_Failure; - } - - fprintf(fp, "channel.enumeration = %d\n", nBands); - fprintf(fp, "channel.interleave = { *pixel tile sequential }\n"); - fprintf(fp, "extent.cols = %d\n", nXSize); - fprintf(fp, "extent.rows = %d\n", nYSize); - - switch (eType) - { - case GDT_Byte: - fprintf(fp, "pixel.encoding = " - "{ *unsigned twos-complement ieee-754 }\n"); - break; - - case GDT_UInt16: - fprintf(fp, "pixel.encoding = " - "{ *unsigned twos-complement ieee-754 }\n"); - break; - - case GDT_CInt16: - case GDT_Int16: - fprintf(fp, "pixel.encoding = " - "{ unsigned *twos-complement ieee-754 }\n"); - break; - - case GDT_CFloat32: - case GDT_Float32: - fprintf(fp, "pixel.encoding = " - "{ unsigned twos-complement *ieee-754 }\n"); - break; - - default: - CPLAssert(false); - } - - fprintf(fp, "pixel.size = %d\n", GDALGetDataTypeSizeBits(eType)); - if (GDALDataTypeIsComplex(eType)) - fprintf(fp, "pixel.field = { real *complex }\n"); - else - fprintf(fp, "pixel.field = { *real complex }\n"); - -#ifdef CPL_MSB - fprintf(fp, "pixel.order = { lsbf *msbf }\n"); -#else - fprintf(fp, "pixel.order = { *lsbf msbf }\n"); -#endif - - if (bNoDataSet) - fprintf(fp, "pixel.no_data = %s\n", CPLSPrintf("%f", dfNoDataValue)); - - // Version information- only create the new style. - fprintf(fp, "version = 1.1"); - - if (VSIFClose(fp) != 0) - return CE_Failure; - return CE_None; -} - /************************************************************************/ /* GetGeoTransform() */ /************************************************************************/ @@ -508,397 +371,6 @@ CPLErr HKVDataset::GetGeoTransform(double *padfTransform) return CE_None; } -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr HKVDataset::SetGeoTransform(double *padfTransform) - -{ - // NOTE: Geotransform coordinates must match the current projection - // of the dataset being changed (not the geotransform source). - // i.e. be in lat/longs for LL projected; UTM for UTM projected. - // SET PROJECTION BEFORE SETTING GEOTRANSFORM TO AVOID SYNCHRONIZATION - // PROBLEMS. - - // Update the geotransform itself. - memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6); - - // Clear previous gcps. - if (nGCPCount > 0) - { - GDALDeinitGCPs(nGCPCount, pasGCPList); - CPLFree(pasGCPList); - } - nGCPCount = 0; - pasGCPList = nullptr; - - // Return if the identity transform is set. - if (adfGeoTransform[0] == 0.0 && adfGeoTransform[1] == 1.0 && - adfGeoTransform[2] == 0.0 && adfGeoTransform[3] == 0.0 && - adfGeoTransform[4] == 0.0 && adfGeoTransform[5] == 1.0) - return CE_None; - - // Update georef text info for saving later, and update GCPs to match - // geotransform. - - OGRCoordinateTransformation *poTransform = nullptr; - bool bSuccess = true; - - // Projection parameter checking will have been done in SetProjection. - if ((CSLFetchNameValue(papszGeoref, "projection.name") != nullptr) && - (EQUAL(CSLFetchNameValue(papszGeoref, "projection.name"), "UTM"))) - { - auto poLLSRS = m_oSRS.CloneGeogCS(); - if (poLLSRS) - { - poLLSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - poTransform = OGRCreateCoordinateTransformation(&m_oSRS, poLLSRS); - delete poLLSRS; - if (poTransform == nullptr) - { - bSuccess = false; - CPLErrorReset(); - } - } - else - { - bSuccess = false; - } - } - else if (((CSLFetchNameValue(papszGeoref, "projection.name") != nullptr) && - (!EQUAL(CSLFetchNameValue(papszGeoref, "projection.name"), - "LL"))) || - (CSLFetchNameValue(papszGeoref, "projection.name") == nullptr)) - { - return CE_Failure; - } - - nGCPCount = 0; - pasGCPList = static_cast(CPLCalloc(sizeof(GDAL_GCP), 5)); - - /* -------------------------------------------------------------------- */ - /* top left */ - /* -------------------------------------------------------------------- */ - GDALInitGCPs(1, pasGCPList + nGCPCount); - CPLFree(pasGCPList[nGCPCount].pszId); - pasGCPList[nGCPCount].pszId = CPLStrdup("top_left"); - - double temp_lat = 0.0; - double temp_long = 0.0; - if (MFF2version > 1.0) - { - temp_lat = padfTransform[3]; - temp_long = padfTransform[0]; - pasGCPList[nGCPCount].dfGCPPixel = 0.0; - pasGCPList[nGCPCount].dfGCPLine = 0.0; - } - else - { - temp_lat = - padfTransform[3] + 0.5 * padfTransform[4] + 0.5 * padfTransform[5]; - temp_long = - padfTransform[0] + 0.5 * padfTransform[1] + 0.5 * padfTransform[2]; - pasGCPList[nGCPCount].dfGCPPixel = 0.5; - pasGCPList[nGCPCount].dfGCPLine = 0.5; - } - pasGCPList[nGCPCount].dfGCPX = temp_long; - pasGCPList[nGCPCount].dfGCPY = temp_lat; - pasGCPList[nGCPCount].dfGCPZ = 0.0; - nGCPCount++; - - if (poTransform != nullptr) - { - if (!bSuccess || !poTransform->Transform(1, &temp_long, &temp_lat)) - bSuccess = false; - } - - if (bSuccess) - { - char szValue[128] = {'\0'}; - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_lat); - papszGeoref = - CSLSetNameValue(papszGeoref, "top_left.latitude", szValue); - - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_long); - papszGeoref = - CSLSetNameValue(papszGeoref, "top_left.longitude", szValue); - } - - /* -------------------------------------------------------------------- */ - /* top_right */ - /* -------------------------------------------------------------------- */ - GDALInitGCPs(1, pasGCPList + nGCPCount); - CPLFree(pasGCPList[nGCPCount].pszId); - pasGCPList[nGCPCount].pszId = CPLStrdup("top_right"); - - if (MFF2version > 1.0) - { - temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4]; - temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1]; - pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize(); - pasGCPList[nGCPCount].dfGCPLine = 0.0; - } - else - { - temp_lat = padfTransform[3] + - (GetRasterXSize() - 0.5) * padfTransform[4] + - 0.5 * padfTransform[5]; - temp_long = padfTransform[0] + - (GetRasterXSize() - 0.5) * padfTransform[1] + - 0.5 * padfTransform[2]; - pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize() - 0.5; - pasGCPList[nGCPCount].dfGCPLine = 0.5; - } - pasGCPList[nGCPCount].dfGCPX = temp_long; - pasGCPList[nGCPCount].dfGCPY = temp_lat; - pasGCPList[nGCPCount].dfGCPZ = 0.0; - nGCPCount++; - - if (poTransform != nullptr) - { - if (!bSuccess || !poTransform->Transform(1, &temp_long, &temp_lat)) - bSuccess = false; - } - - if (bSuccess) - { - char szValue[128] = {'\0'}; - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_lat); - papszGeoref = - CSLSetNameValue(papszGeoref, "top_right.latitude", szValue); - - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_long); - papszGeoref = - CSLSetNameValue(papszGeoref, "top_right.longitude", szValue); - } - - /* -------------------------------------------------------------------- */ - /* bottom_left */ - /* -------------------------------------------------------------------- */ - GDALInitGCPs(1, pasGCPList + nGCPCount); - CPLFree(pasGCPList[nGCPCount].pszId); - pasGCPList[nGCPCount].pszId = CPLStrdup("bottom_left"); - - if (MFF2version > 1.0) - { - temp_lat = padfTransform[3] + GetRasterYSize() * padfTransform[5]; - temp_long = padfTransform[0] + GetRasterYSize() * padfTransform[2]; - pasGCPList[nGCPCount].dfGCPPixel = 0.0; - pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize(); - } - else - { - temp_lat = padfTransform[3] + 0.5 * padfTransform[4] + - (GetRasterYSize() - 0.5) * padfTransform[5]; - temp_long = padfTransform[0] + 0.5 * padfTransform[1] + - (GetRasterYSize() - 0.5) * padfTransform[2]; - pasGCPList[nGCPCount].dfGCPPixel = 0.5; - pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize() - 0.5; - } - pasGCPList[nGCPCount].dfGCPX = temp_long; - pasGCPList[nGCPCount].dfGCPY = temp_lat; - pasGCPList[nGCPCount].dfGCPZ = 0.0; - nGCPCount++; - - if (poTransform != nullptr) - { - if (!bSuccess || !poTransform->Transform(1, &temp_long, &temp_lat)) - bSuccess = false; - } - - if (bSuccess) - { - char szValue[128] = {'\0'}; - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_lat); - papszGeoref = - CSLSetNameValue(papszGeoref, "bottom_left.latitude", szValue); - - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_long); - papszGeoref = - CSLSetNameValue(papszGeoref, "bottom_left.longitude", szValue); - } - - /* -------------------------------------------------------------------- */ - /* bottom_right */ - /* -------------------------------------------------------------------- */ - GDALInitGCPs(1, pasGCPList + nGCPCount); - CPLFree(pasGCPList[nGCPCount].pszId); - pasGCPList[nGCPCount].pszId = CPLStrdup("bottom_right"); - - if (MFF2version > 1.0) - { - temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] + - GetRasterYSize() * padfTransform[5]; - temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] + - GetRasterYSize() * padfTransform[2]; - pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize(); - pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize(); - } - else - { - temp_lat = padfTransform[3] + - (GetRasterXSize() - 0.5) * padfTransform[4] + - (GetRasterYSize() - 0.5) * padfTransform[5]; - temp_long = padfTransform[0] + - (GetRasterXSize() - 0.5) * padfTransform[1] + - (GetRasterYSize() - 0.5) * padfTransform[2]; - pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize() - 0.5; - pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize() - 0.5; - } - pasGCPList[nGCPCount].dfGCPX = temp_long; - pasGCPList[nGCPCount].dfGCPY = temp_lat; - pasGCPList[nGCPCount].dfGCPZ = 0.0; - nGCPCount++; - - if (poTransform != nullptr) - { - if (!bSuccess || !poTransform->Transform(1, &temp_long, &temp_lat)) - bSuccess = false; - } - - if (bSuccess) - { - char szValue[128] = {'\0'}; - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_lat); - papszGeoref = - CSLSetNameValue(papszGeoref, "bottom_right.latitude", szValue); - - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_long); - papszGeoref = - CSLSetNameValue(papszGeoref, "bottom_right.longitude", szValue); - } - - /* -------------------------------------------------------------------- */ - /* Center */ - /* -------------------------------------------------------------------- */ - GDALInitGCPs(1, pasGCPList + nGCPCount); - CPLFree(pasGCPList[nGCPCount].pszId); - pasGCPList[nGCPCount].pszId = CPLStrdup("centre"); - - temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] * 0.5 + - GetRasterYSize() * padfTransform[5] * 0.5; - temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] * 0.5 + - GetRasterYSize() * padfTransform[2] * 0.5; - pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize() / 2.0; - pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize() / 2.0; - - pasGCPList[nGCPCount].dfGCPX = temp_long; - pasGCPList[nGCPCount].dfGCPY = temp_lat; - pasGCPList[nGCPCount].dfGCPZ = 0.0; - nGCPCount++; - - if (poTransform != nullptr) - { - if (!bSuccess || !poTransform->Transform(1, &temp_long, &temp_lat)) - bSuccess = false; - } - - if (bSuccess) - { - char szValue[128] = {'\0'}; - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_lat); - papszGeoref = CSLSetNameValue(papszGeoref, "centre.latitude", szValue); - - CPLsnprintf(szValue, sizeof(szValue), "%.10f", temp_long); - papszGeoref = CSLSetNameValue(papszGeoref, "centre.longitude", szValue); - } - - if (!bSuccess) - { - CPLError(CE_Warning, CPLE_AppDefined, - "Error setting header info in SetGeoTransform. " - "Changes may not be saved properly."); - } - - if (poTransform != nullptr) - delete poTransform; - - bGeorefChanged = true; - - return CE_None; -} - -/************************************************************************/ -/* SetSpatialRef() */ -/* */ -/* We provide very limited support for setting the projection. */ -/************************************************************************/ - -CPLErr HKVDataset::SetSpatialRef(const OGRSpatialReference *poSRS) - -{ - // Update a georef file. - if (poSRS == nullptr) - { - m_oSRS.Clear(); - return CE_None; - } - m_oSRS = *poSRS; - - if ((m_oSRS.GetAttrValue("PROJECTION") != nullptr) && - (EQUAL(m_oSRS.GetAttrValue("PROJECTION"), SRS_PT_TRANSVERSE_MERCATOR))) - { - papszGeoref = CSLSetNameValue(papszGeoref, "projection.name", "utm"); - OGRErr ogrerrorOl = OGRERR_NONE; - papszGeoref = CSLSetNameValue( - papszGeoref, "projection.origin_longitude", - CPLSPrintf("%f", m_oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0, - &ogrerrorOl))); - } - else if (m_oSRS.GetAttrValue("PROJECTION") == nullptr && - m_oSRS.IsGeographic()) - { - papszGeoref = CSLSetNameValue(papszGeoref, "projection.name", "LL"); - } - else - { - CPLError(CE_Warning, CPLE_AppDefined, "Unrecognized projection."); - return CE_Failure; - } - - OGRErr ogrerrorEq = OGRERR_NONE; - const double eq_radius = m_oSRS.GetSemiMajor(&ogrerrorEq); - - OGRErr ogrerrorInvf = OGRERR_NONE; - const double inv_flattening = m_oSRS.GetInvFlattening(&ogrerrorInvf); - - if ((ogrerrorEq == OGRERR_NONE) && (ogrerrorInvf == OGRERR_NONE)) - { - HKVSpheroidList *hkvEllipsoids = new HKVSpheroidList; - char *spheroid_name = - hkvEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening( - eq_radius, inv_flattening); - if (spheroid_name != nullptr) - { - papszGeoref = - CSLSetNameValue(papszGeoref, "spheroid.name", spheroid_name); - } - CPLFree(spheroid_name); - delete hkvEllipsoids; - } - else - { - // Default to previous behavior if spheroid not found by radius and - // inverse flattening. - char *pszProjection = nullptr; - m_oSRS.exportToWkt(&pszProjection); - if (pszProjection && strstr(pszProjection, "Bessel") != nullptr) - { - papszGeoref = - CSLSetNameValue(papszGeoref, "spheroid.name", "ev-bessel"); - } - else - { - papszGeoref = - CSLSetNameValue(papszGeoref, "spheroid.name", "ev-wgs-84"); - } - CPLFree(pszProjection); - } - bGeorefChanged = true; - return CE_None; -} - /************************************************************************/ /* GetGCP() */ /************************************************************************/ @@ -1500,327 +972,6 @@ GDALDataset *HKVDataset::Open(GDALOpenInfo *poOpenInfo) return poDS.release(); } -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *HKVDataset::Create(const char *pszFilenameIn, int nXSize, - int nYSize, int nBandsIn, GDALDataType eType, - char ** /* papszParamList */) - -{ - /* -------------------------------------------------------------------- */ - /* Verify input options. */ - /* -------------------------------------------------------------------- */ - if (nBandsIn <= 0) - { - CPLError(CE_Failure, CPLE_NotSupported, - "HKV driver does not support %d bands.", nBandsIn); - return nullptr; - } - - if (eType != GDT_Byte && eType != GDT_UInt16 && eType != GDT_Int16 && - eType != GDT_CInt16 && eType != GDT_Float32 && eType != GDT_CFloat32) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create HKV file with currently unsupported\n" - "data type (%s).", - GDALGetDataTypeName(eType)); - - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Establish the name of the directory we will be creating the */ - /* new HKV directory in. Verify that this is a directory. */ - /* -------------------------------------------------------------------- */ - char *pszBaseDir = nullptr; - - if (strlen(CPLGetPathSafe(pszFilenameIn).c_str()) == 0) - pszBaseDir = CPLStrdup("."); - else - pszBaseDir = CPLStrdup(CPLGetPathSafe(pszFilenameIn).c_str()); - - VSIStatBuf sStat; - if (CPLStat(pszBaseDir, &sStat) != 0 || !VSI_ISDIR(sStat.st_mode)) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create HKV dataset under %s,\n" - "but this is not a valid directory.", - pszBaseDir); - CPLFree(pszBaseDir); - return nullptr; - } - - CPLFree(pszBaseDir); - pszBaseDir = nullptr; - - if (VSIMkdir(pszFilenameIn, 0755) != 0) - { - CPLError(CE_Failure, CPLE_AppDefined, "Unable to create directory %s.", - pszFilenameIn); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create the header file. */ - /* -------------------------------------------------------------------- */ - CPLErr CEHeaderCreated = SaveHKVAttribFile(pszFilenameIn, nXSize, nYSize, - nBandsIn, eType, FALSE, 0.0); - - if (CEHeaderCreated != CE_None) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Create the blob file. */ - /* -------------------------------------------------------------------- */ - - const std::string osFilename = - CPLFormFilenameSafe(pszFilenameIn, "image_data", nullptr); - FILE *fp = VSIFOpen(osFilename.c_str(), "wb"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Couldn't create %s.\n", - osFilename.c_str()); - return nullptr; - } - - bool bOK = VSIFWrite(reinterpret_cast(const_cast("")), 1, 1, - fp) == 1; - if (VSIFClose(fp) != 0) - bOK &= false; - - if (!bOK) - return nullptr; - /* -------------------------------------------------------------------- */ - /* Open the dataset normally. */ - /* -------------------------------------------------------------------- */ - return GDALDataset::FromHandle(GDALOpen(pszFilenameIn, GA_Update)); -} - -/************************************************************************/ -/* Delete() */ -/* */ -/* An HKV Blob dataset consists of a bunch of files in a */ -/* directory. Try to delete all the files, then the */ -/* directory. */ -/************************************************************************/ - -CPLErr HKVDataset::Delete(const char *pszName) - -{ - VSIStatBuf sStat; - if (CPLStat(pszName, &sStat) != 0 || !VSI_ISDIR(sStat.st_mode)) - { - CPLError(CE_Failure, CPLE_AppDefined, - "%s does not appear to be an HKV Dataset, as it is not " - "a path to a directory.", - pszName); - return CE_Failure; - } - - char **papszFiles = VSIReadDir(pszName); - for (int i = 0; i < CSLCount(papszFiles); i++) - { - if (EQUAL(papszFiles[i], ".") || EQUAL(papszFiles[i], "..")) - continue; - - const std::string osTarget = - CPLFormFilenameSafe(pszName, papszFiles[i], nullptr); - if (VSIUnlink(osTarget.c_str()) != 0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Unable to delete file %s," - "HKVDataset Delete(%s) failed.", - osTarget.c_str(), pszName); - CSLDestroy(papszFiles); - return CE_Failure; - } - } - - CSLDestroy(papszFiles); - - if (VSIRmdir(pszName) != 0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Unable to delete directory %s," - "HKVDataset Delete() failed.", - pszName); - return CE_Failure; - } - - return CE_None; -} - -/************************************************************************/ -/* CreateCopy() */ -/************************************************************************/ - -GDALDataset *HKVDataset::CreateCopy(const char *pszFilename, - GDALDataset *poSrcDS, - CPL_UNUSED int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - int nBands = poSrcDS->GetRasterCount(); - if (nBands == 0) - { - CPLError(CE_Failure, CPLE_NotSupported, - "HKV driver does not support source dataset with zero band."); - return nullptr; - } - - GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType(); - - if (!pfnProgress(0.0, nullptr, pProgressData)) - return nullptr; - - /* check that other bands match type- sets type */ - /* to unknown if they differ. */ - for (int iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++) - { - GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1); - eType = GDALDataTypeUnion(eType, poBand->GetRasterDataType()); - } - - HKVDataset *poDS = reinterpret_cast(Create( - pszFilename, poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), - poSrcDS->GetRasterCount(), eType, papszOptions)); - - /* Check that Create worked- return Null if it didn't */ - if (poDS == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Copy the image data. */ - /* -------------------------------------------------------------------- */ - const int nXSize = poDS->GetRasterXSize(); - const int nYSize = poDS->GetRasterYSize(); - - int nBlockXSize, nBlockYSize; - poDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize); - - const int nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize) * - ((nYSize + nBlockYSize - 1) / nBlockYSize) * - poSrcDS->GetRasterCount(); - - int nBlocksDone = 0; - for (int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++) - { - GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(iBand + 1); - GDALRasterBand *poDstBand = poDS->GetRasterBand(iBand + 1); - - /* Get nodata value, if relevant */ - int pbSuccess = FALSE; - double dfSrcNoDataValue = poSrcBand->GetNoDataValue(&pbSuccess); - if (pbSuccess) - poDS->SetNoDataValue(dfSrcNoDataValue); - - void *pData = CPLMalloc(nBlockXSize * nBlockYSize * - GDALGetDataTypeSize(eType) / 8); - - for (int iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize) - { - for (int iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize) - { - if (!pfnProgress((nBlocksDone++) / - static_cast(nBlockTotal), - nullptr, pProgressData)) - { - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated"); - delete poDS; - CPLFree(pData); - - GDALDriver *poHKVDriver = reinterpret_cast( - GDALGetDriverByName("MFF2")); - poHKVDriver->Delete(pszFilename); - return nullptr; - } - - const int nTBXSize = std::min(nBlockXSize, nXSize - iXOffset); - const int nTBYSize = std::min(nBlockYSize, nYSize - iYOffset); - - CPLErr eErr = poSrcBand->RasterIO( - GF_Read, iXOffset, iYOffset, nTBXSize, nTBYSize, pData, - nTBXSize, nTBYSize, eType, 0, 0, nullptr); - if (eErr != CE_None) - { - delete poDS; - CPLFree(pData); - return nullptr; - } - - eErr = poDstBand->RasterIO(GF_Write, iXOffset, iYOffset, - nTBXSize, nTBYSize, pData, nTBXSize, - nTBYSize, eType, 0, 0, nullptr); - - if (eErr != CE_None) - { - delete poDS; - CPLFree(pData); - return nullptr; - } - } - } - - CPLFree(pData); - } - - /* -------------------------------------------------------------------- */ - /* Copy georeferencing information, if enough is available. */ - /* Only copy geotransform-style info (won't work for slant range). */ - /* -------------------------------------------------------------------- */ - - double *tempGeoTransform = - static_cast(CPLMalloc(6 * sizeof(double))); - - if ((poSrcDS->GetGeoTransform(tempGeoTransform) == CE_None) && - (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0 || - tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0 || - tempGeoTransform[4] != 0.0 || std::abs(tempGeoTransform[5]) != 1.0)) - { - auto poSrcSRS = poSrcDS->GetSpatialRef(); - if (poSrcSRS) - { - poDS->SetSpatialRef(poSrcSRS); - poDS->m_oGCPSRS = *poSrcSRS; - } - poDS->SetGeoTransform(tempGeoTransform); - - CPLFree(tempGeoTransform); - - // georef file will be saved automatically when dataset is deleted - // because SetProjection sets a flag to indicate it is necessary. - } - else - { - CPLFree(tempGeoTransform); - } - - // Make sure image data gets flushed. - for (int iBand = 0; iBand < poDS->GetRasterCount(); iBand++) - { - RawRasterBand *poDstBand = - reinterpret_cast(poDS->GetRasterBand(iBand + 1)); - poDstBand->FlushCache(false); - } - - if (!pfnProgress(1.0, nullptr, pProgressData)) - { - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated"); - delete poDS; - - GDALDriver *poHKVDriver = - reinterpret_cast(GDALGetDriverByName("MFF2")); - poHKVDriver->Delete(pszFilename); - return nullptr; - } - - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - - return poDS; -} - /************************************************************************/ /* GDALRegister_HKV() */ /************************************************************************/ @@ -1837,14 +988,8 @@ void GDALRegister_HKV() poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Vexcel MFF2 (HKV) Raster"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/mff2.html"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte Int16 UInt16 Int32 UInt32 CInt16 " - "CInt32 Float32 Float64 CFloat32 CFloat64"); poDriver->pfnOpen = HKVDataset::Open; - poDriver->pfnCreate = HKVDataset::Create; - poDriver->pfnDelete = HKVDataset::Delete; - poDriver->pfnCreateCopy = HKVDataset::CreateCopy; GetGDALDriverManager()->RegisterDriver(poDriver); } diff --git a/frmts/raw/landataset.cpp b/frmts/raw/landataset.cpp index 6ac32d4f1ec8..c83182bff5b2 100644 --- a/frmts/raw/landataset.cpp +++ b/frmts/raw/landataset.cpp @@ -139,15 +139,10 @@ class LANDataset final : public RawDataset ~LANDataset() override; CPLErr GetGeoTransform(double *padfTransform) override; - CPLErr SetGeoTransform(double *padfTransform) override; const OGRSpatialReference *GetSpatialRef() const override; - CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override; static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszOptions); }; /************************************************************************/ @@ -633,48 +628,6 @@ CPLErr LANDataset::GetGeoTransform(double *padfTransform) return GDALPamDataset::GetGeoTransform(padfTransform); } -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr LANDataset::SetGeoTransform(double *padfTransform) - -{ - unsigned char abyHeader[128] = {'\0'}; - - memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6); - - CPL_IGNORE_RET_VAL(VSIFSeekL(fpImage, 0, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFReadL(abyHeader, 128, 1, fpImage)); - - // Upper Left X. - float f32Val = - static_cast(adfGeoTransform[0] + 0.5 * adfGeoTransform[1]); - memcpy(abyHeader + 112, &f32Val, 4); - - // Upper Left Y. - f32Val = static_cast(adfGeoTransform[3] + 0.5 * adfGeoTransform[5]); - memcpy(abyHeader + 116, &f32Val, 4); - - // Width of pixel. - f32Val = static_cast(adfGeoTransform[1]); - memcpy(abyHeader + 120, &f32Val, 4); - - // Height of pixel. - f32Val = static_cast(std::abs(adfGeoTransform[5])); - memcpy(abyHeader + 124, &f32Val, 4); - - if (VSIFSeekL(fpImage, 0, SEEK_SET) != 0 || - VSIFWriteL(abyHeader, 128, 1, fpImage) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "File IO Error writing header with new geotransform."); - return CE_Failure; - } - - return CE_None; -} - /************************************************************************/ /* GetSpatialRef() */ /* */ @@ -692,83 +645,6 @@ const OGRSpatialReference *LANDataset::GetSpatialRef() const return m_poSRS; } -/************************************************************************/ -/* SetSpatialRef() */ -/************************************************************************/ - -CPLErr LANDataset::SetSpatialRef(const OGRSpatialReference *poSRS) - -{ - if (poSRS == nullptr) - return GDALPamDataset::SetSpatialRef(poSRS); - - unsigned char abyHeader[128] = {'\0'}; - - CPL_IGNORE_RET_VAL(VSIFSeekL(fpImage, 0, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFReadL(abyHeader, 128, 1, fpImage)); - - GUInt16 nProjCode = 0; - - if (poSRS->IsGeographic()) - { - nProjCode = 0; - } - else if (poSRS->GetUTMZone() != 0) - { - nProjCode = 1; - } - // Too bad we have no way of recognising state plane projections. - else - { - const char *l_pszProjection = poSRS->GetAttrValue("PROJECTION"); - - if (l_pszProjection == nullptr) - ; - else if (EQUAL(l_pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA)) - nProjCode = 3; - else if (EQUAL(l_pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP)) - nProjCode = 4; - else if (EQUAL(l_pszProjection, SRS_PT_MERCATOR_1SP)) - nProjCode = 5; - else if (EQUAL(l_pszProjection, SRS_PT_POLAR_STEREOGRAPHIC)) - nProjCode = 6; - else if (EQUAL(l_pszProjection, SRS_PT_POLYCONIC)) - nProjCode = 7; - else if (EQUAL(l_pszProjection, SRS_PT_EQUIDISTANT_CONIC)) - nProjCode = 8; - else if (EQUAL(l_pszProjection, SRS_PT_TRANSVERSE_MERCATOR)) - nProjCode = 9; - else if (EQUAL(l_pszProjection, SRS_PT_STEREOGRAPHIC)) - nProjCode = 10; - else if (EQUAL(l_pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA)) - nProjCode = 11; - else if (EQUAL(l_pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT)) - nProjCode = 12; - else if (EQUAL(l_pszProjection, SRS_PT_GNOMONIC)) - nProjCode = 13; - else if (EQUAL(l_pszProjection, SRS_PT_ORTHOGRAPHIC)) - nProjCode = 14; - // We do not have GVNP. - else if (EQUAL(l_pszProjection, SRS_PT_SINUSOIDAL)) - nProjCode = 16; - else if (EQUAL(l_pszProjection, SRS_PT_EQUIRECTANGULAR)) - nProjCode = 17; - else if (EQUAL(l_pszProjection, SRS_PT_MILLER_CYLINDRICAL)) - nProjCode = 18; - else if (EQUAL(l_pszProjection, SRS_PT_VANDERGRINTEN)) - nProjCode = 19; - else if (EQUAL(l_pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR)) - nProjCode = 20; - } - - memcpy(abyHeader + 88, &nProjCode, 2); - - CPL_IGNORE_RET_VAL(VSIFSeekL(fpImage, 0, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFWriteL(abyHeader, 128, 1, fpImage)); - - return GDALPamDataset::SetSpatialRef(poSRS); -} - /************************************************************************/ /* GetFileList() */ /************************************************************************/ @@ -855,142 +731,6 @@ void LANDataset::CheckForStatistics() CPL_IGNORE_RET_VAL(VSIFCloseL(fpSTA)); } -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *LANDataset::Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char ** /* papszOptions */) -{ - if (eType != GDT_Byte && eType != GDT_Int16) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create .GIS file with unsupported data type '%s'.", - GDALGetDataTypeName(eType)); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Try to create the file. */ - /* -------------------------------------------------------------------- */ - VSILFILE *fp = VSIFOpenL(pszFilename, "wb"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file `%s' failed.\n", pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Write out the header. */ - /* -------------------------------------------------------------------- */ - unsigned char abyHeader[128] = {'\0'}; - - memset(abyHeader, 0, sizeof(abyHeader)); - - memcpy(abyHeader + 0, "HEAD74", 6); - - // Pixel type. - GInt16 n16Val = 0; - if (eType == GDT_Byte) // Do we want 4bit? - n16Val = 0; - else - n16Val = 2; - memcpy(abyHeader + 6, &n16Val, 2); - - // Number of Bands. - n16Val = static_cast(nBandsIn); - memcpy(abyHeader + 8, &n16Val, 2); - - // Unknown (6). - - // Width. - GInt32 n32Val = nXSize; - memcpy(abyHeader + 16, &n32Val, 4); - - // Height. - n32Val = nYSize; - memcpy(abyHeader + 20, &n32Val, 4); - - // X Start (4). - // Y Start (4). - - // Unknown (56). - - // Coordinate System. - n16Val = 0; - memcpy(abyHeader + 88, &n16Val, 2); - - // Classes in coverage. - n16Val = 0; - memcpy(abyHeader + 90, &n16Val, 2); - - // Unknown (14). - - // Area Unit. - n16Val = 0; - memcpy(abyHeader + 106, &n16Val, 2); - - // Pixel Area. - float f32Val = 0.0f; - memcpy(abyHeader + 108, &f32Val, 4); - - // Upper Left X. - f32Val = 0.5f; - memcpy(abyHeader + 112, &f32Val, 4); - - // Upper Left Y - f32Val = static_cast(nYSize - 0.5); - memcpy(abyHeader + 116, &f32Val, 4); - - // Width of pixel. - f32Val = 1.0f; - memcpy(abyHeader + 120, &f32Val, 4); - - // Height of pixel. - f32Val = 1.0f; - memcpy(abyHeader + 124, &f32Val, 4); - - CPL_IGNORE_RET_VAL(VSIFWriteL(abyHeader, sizeof(abyHeader), 1, fp)); - - /* -------------------------------------------------------------------- */ - /* Extend the file to the target size. */ - /* -------------------------------------------------------------------- */ - vsi_l_offset nImageBytes = 0; - - if (eType != GDT_Byte) - nImageBytes = nXSize * static_cast(nYSize) * 2; - else - nImageBytes = nXSize * static_cast(nYSize); - - memset(abyHeader, 0, sizeof(abyHeader)); - - while (nImageBytes > 0) - { - const vsi_l_offset nWriteThisTime = - std::min(static_cast(nImageBytes), sizeof(abyHeader)); - - if (VSIFWriteL(abyHeader, 1, static_cast(nWriteThisTime), fp) != - nWriteThisTime) - { - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - CPLError(CE_Failure, CPLE_FileIO, - "Failed to write whole Istar file."); - return nullptr; - } - nImageBytes -= nWriteThisTime; - } - - if (VSIFCloseL(fp) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to write whole Istar file."); - return nullptr; - } - - return static_cast(GDALOpen(pszFilename, GA_Update)); -} - /************************************************************************/ /* GDALRegister_LAN() */ /************************************************************************/ @@ -1008,10 +748,8 @@ void GDALRegister_LAN() poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Erdas .LAN/.GIS"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/lan.html"); poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte Int16"); poDriver->pfnOpen = LANDataset::Open; - poDriver->pfnCreate = LANDataset::Create; GetGDALDriverManager()->RegisterDriver(poDriver); } diff --git a/frmts/raw/mffdataset.cpp b/frmts/raw/mffdataset.cpp index 002c36d622ec..17e0a604a579 100644 --- a/frmts/raw/mffdataset.cpp +++ b/frmts/raw/mffdataset.cpp @@ -29,8 +29,6 @@ enum MFFPRJ_UNRECOGNIZED }; -static int GetMFFProjectionType(const OGRSpatialReference *poSRS); - /************************************************************************/ /* ==================================================================== */ /* MFFDataset */ @@ -81,14 +79,6 @@ class MFFDataset final : public RawDataset CPLErr GetGeoTransform(double *) override; static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszParamList); - static GDALDataset *CreateCopy(const char *pszFilename, - GDALDataset *poSrcDS, int bStrict, - char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); }; /************************************************************************/ @@ -1027,553 +1017,6 @@ GDALDataset *MFFDataset::Open(GDALOpenInfo *poOpenInfo) return poDS.release(); } -int GetMFFProjectionType(const OGRSpatialReference *poSRS) -{ - if (poSRS == nullptr) - { - return MFFPRJ_NONE; - } - if (poSRS->IsProjected() && poSRS->GetAttrValue("PROJECTION") && - EQUAL(poSRS->GetAttrValue("PROJECTION"), SRS_PT_TRANSVERSE_MERCATOR)) - { - return MFFPRJ_UTM; - } - else if (poSRS->IsGeographic()) - { - return MFFPRJ_LL; - } - else - { - return MFFPRJ_UNRECOGNIZED; - } -} - -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *MFFDataset::Create(const char *pszFilenameIn, int nXSize, - int nYSize, int nBandsIn, GDALDataType eType, - char **papszParamList) - -{ - /* -------------------------------------------------------------------- */ - /* Verify input options. */ - /* -------------------------------------------------------------------- */ - if (nBandsIn <= 0) - { - CPLError(CE_Failure, CPLE_NotSupported, - "MFF driver does not support %d bands.", nBandsIn); - return nullptr; - } - - if (eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16 && - eType != GDT_CInt16 && eType != GDT_CFloat32) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create MFF file with currently unsupported\n" - "data type (%s).\n", - GDALGetDataTypeName(eType)); - - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Establish the base filename (path+filename, less extension). */ - /* -------------------------------------------------------------------- */ - char *pszBaseFilename = - static_cast(CPLMalloc(strlen(pszFilenameIn) + 5)); - strcpy(pszBaseFilename, pszFilenameIn); - - for (int i = static_cast(strlen(pszBaseFilename)) - 1; i > 0; i--) - { - if (pszBaseFilename[i] == '.') - { - pszBaseFilename[i] = '\0'; - break; - } - - if (pszBaseFilename[i] == '/' || pszBaseFilename[i] == '\\') - break; - } - - /* -------------------------------------------------------------------- */ - /* Create the header file. */ - /* -------------------------------------------------------------------- */ - std::string osFilename = - CPLFormFilenameSafe(nullptr, pszBaseFilename, "hdr"); - - VSILFILE *fp = VSIFOpenL(osFilename.c_str(), "wt"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Couldn't create %s.\n", - osFilename.c_str()); - CPLFree(pszBaseFilename); - return nullptr; - } - - bool bOK = VSIFPrintfL(fp, "IMAGE_FILE_FORMAT = MFF\n") >= 0; - bOK &= VSIFPrintfL(fp, "FILE_TYPE = IMAGE\n") >= 0; - bOK &= VSIFPrintfL(fp, "IMAGE_LINES = %d\n", nYSize) >= 0; - bOK &= VSIFPrintfL(fp, "LINE_SAMPLES = %d\n", nXSize) >= 0; -#ifdef CPL_MSB - bOK &= VSIFPrintfL(fp, "BYTE_ORDER = MSB\n") >= 0; -#else - bOK &= VSIFPrintfL(fp, "BYTE_ORDER = LSB\n") >= 0; -#endif - - if (CSLFetchNameValue(papszParamList, "NO_END") == nullptr) - bOK &= VSIFPrintfL(fp, "END\n") >= 0; - - if (VSIFCloseL(fp) != 0) - bOK = false; - - /* -------------------------------------------------------------------- */ - /* Create the data files, but don't bother writing any data to them.*/ - /* -------------------------------------------------------------------- */ - for (int iBand = 0; bOK && iBand < nBandsIn; iBand++) - { - char szExtension[4] = {'\0'}; - - if (eType == GDT_Byte) - CPLsnprintf(szExtension, sizeof(szExtension), "b%02d", iBand); - else if (eType == GDT_UInt16) - CPLsnprintf(szExtension, sizeof(szExtension), "i%02d", iBand); - else if (eType == GDT_Float32) - CPLsnprintf(szExtension, sizeof(szExtension), "r%02d", iBand); - else if (eType == GDT_CInt16) - CPLsnprintf(szExtension, sizeof(szExtension), "j%02d", iBand); - else if (eType == GDT_CFloat32) - CPLsnprintf(szExtension, sizeof(szExtension), "x%02d", iBand); - - osFilename = CPLFormFilenameSafe(nullptr, pszBaseFilename, szExtension); - fp = VSIFOpenL(osFilename.c_str(), "wb"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Couldn't create %s.\n", - osFilename.c_str()); - CPLFree(pszBaseFilename); - return nullptr; - } - - bOK &= VSIFWriteL("", 1, 1, fp) == 1; - if (VSIFCloseL(fp) != 0) - bOK = false; - } - - if (!bOK) - { - CPLFree(pszBaseFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Open the dataset normally. */ - /* -------------------------------------------------------------------- */ - strcat(pszBaseFilename, ".hdr"); - GDALDataset *poDS = - GDALDataset::Open(pszBaseFilename, GDAL_OF_RASTER | GDAL_OF_UPDATE); - CPLFree(pszBaseFilename); - - return poDS; -} - -/************************************************************************/ -/* CreateCopy() */ -/************************************************************************/ - -GDALDataset *MFFDataset::CreateCopy(const char *pszFilename, - GDALDataset *poSrcDS, int /* bStrict */, - char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - const int nBands = poSrcDS->GetRasterCount(); - if (nBands == 0) - { - CPLError(CE_Failure, CPLE_NotSupported, - "MFF driver does not support source dataset with zero band."); - return nullptr; - } - - GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType(); - if (!pfnProgress(0.0, nullptr, pProgressData)) - return nullptr; - - // Check that other bands match type- sets type - // to unknown if they differ. - for (int iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++) - { - GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1); - eType = GDALDataTypeUnion(eType, poBand->GetRasterDataType()); - } - - char **newpapszOptions = CSLDuplicate(papszOptions); - newpapszOptions = CSLSetNameValue(newpapszOptions, "NO_END", "TRUE"); - - MFFDataset *poDS = reinterpret_cast(Create( - pszFilename, poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), - poSrcDS->GetRasterCount(), eType, newpapszOptions)); - - CSLDestroy(newpapszOptions); - - if (poDS == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Copy the image data. */ - /* -------------------------------------------------------------------- */ - const int nXSize = poDS->GetRasterXSize(); - const int nYSize = poDS->GetRasterYSize(); - - int nBlockXSize = 0; - int nBlockYSize = 0; - poDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize); - - const int nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize) * - ((nYSize + nBlockYSize - 1) / nBlockYSize) * - poSrcDS->GetRasterCount(); - - int nBlocksDone = 0; - for (int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++) - { - GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(iBand + 1); - GDALRasterBand *poDstBand = poDS->GetRasterBand(iBand + 1); - - void *pData = CPLMalloc(static_cast(nBlockXSize) * nBlockYSize * - GDALGetDataTypeSizeBytes(eType)); - - for (int iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize) - { - for (int iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize) - { - if (!pfnProgress((nBlocksDone++) / - static_cast(nBlockTotal), - nullptr, pProgressData)) - { - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated"); - delete poDS; - CPLFree(pData); - - GDALDriver *poMFFDriver = - static_cast(GDALGetDriverByName("MFF")); - poMFFDriver->Delete(pszFilename); - return nullptr; - } - - const int nTBXSize = std::min(nBlockXSize, nXSize - iXOffset); - const int nTBYSize = std::min(nBlockYSize, nYSize - iYOffset); - - CPLErr eErr = poSrcBand->RasterIO( - GF_Read, iXOffset, iYOffset, nTBXSize, nTBYSize, pData, - nTBXSize, nTBYSize, eType, 0, 0, nullptr); - - if (eErr != CE_None) - { - delete poDS; - CPLFree(pData); - return nullptr; - } - - eErr = poDstBand->RasterIO(GF_Write, iXOffset, iYOffset, - nTBXSize, nTBYSize, pData, nTBXSize, - nTBYSize, eType, 0, 0, nullptr); - - if (eErr != CE_None) - { - delete poDS; - CPLFree(pData); - return nullptr; - } - } - } - - CPLFree(pData); - } - - /* -------------------------------------------------------------------- */ - /* Copy georeferencing information, if enough is available. */ - /* -------------------------------------------------------------------- */ - - /* -------------------------------------------------------------------- */ - /* Establish the base filename (path+filename, less extension). */ - /* -------------------------------------------------------------------- */ - char *pszBaseFilename = - static_cast(CPLMalloc(strlen(pszFilename) + 5)); - strcpy(pszBaseFilename, pszFilename); - - for (int i = static_cast(strlen(pszBaseFilename)) - 1; i > 0; i--) - { - if (pszBaseFilename[i] == '.') - { - pszBaseFilename[i] = '\0'; - break; - } - - if (pszBaseFilename[i] == '/' || pszBaseFilename[i] == '\\') - break; - } - - const std::string osFilenameGEO = - CPLFormFilenameSafe(nullptr, pszBaseFilename, "hdr"); - - VSILFILE *fp = VSIFOpenL(osFilenameGEO.c_str(), "at"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Couldn't open %s for appending.\n", osFilenameGEO.c_str()); - CPLFree(pszBaseFilename); - return nullptr; - } - - /* MFF requires corner and center gcps */ - bool georef_created = false; - - double *padfTiepoints = - static_cast(CPLMalloc(2 * sizeof(double) * 5)); - - const int src_prj = GetMFFProjectionType(poSrcDS->GetSpatialRef()); - - if ((src_prj != MFFPRJ_NONE) && (src_prj != MFFPRJ_UNRECOGNIZED)) - { - double *tempGeoTransform = - static_cast(CPLMalloc(6 * sizeof(double))); - - if ((poSrcDS->GetGeoTransform(tempGeoTransform) == CE_None) && - (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0 || - tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0 || - tempGeoTransform[4] != 0.0 || - std::abs(tempGeoTransform[5]) != 1.0)) - { - padfTiepoints[0] = tempGeoTransform[0] + tempGeoTransform[1] * 0.5 + - tempGeoTransform[2] * 0.5; - - padfTiepoints[1] = tempGeoTransform[3] + tempGeoTransform[4] * 0.5 + - tempGeoTransform[5] * 0.5; - - padfTiepoints[2] = - tempGeoTransform[0] + tempGeoTransform[2] * 0.5 + - tempGeoTransform[1] * (poSrcDS->GetRasterXSize() - 0.5); - - padfTiepoints[3] = - tempGeoTransform[3] + tempGeoTransform[5] * 0.5 + - tempGeoTransform[4] * (poSrcDS->GetRasterXSize() - 0.5); - - padfTiepoints[4] = - tempGeoTransform[0] + tempGeoTransform[1] * 0.5 + - tempGeoTransform[2] * (poSrcDS->GetRasterYSize() - 0.5); - - padfTiepoints[5] = - tempGeoTransform[3] + tempGeoTransform[4] * 0.5 + - tempGeoTransform[5] * (poSrcDS->GetRasterYSize() - 0.5); - - padfTiepoints[6] = - tempGeoTransform[0] + - tempGeoTransform[1] * (poSrcDS->GetRasterXSize() - 0.5) + - tempGeoTransform[2] * (poSrcDS->GetRasterYSize() - 0.5); - - padfTiepoints[7] = - tempGeoTransform[3] + - tempGeoTransform[4] * (poSrcDS->GetRasterXSize() - 0.5) + - tempGeoTransform[5] * (poSrcDS->GetRasterYSize() - 0.5); - - padfTiepoints[8] = - tempGeoTransform[0] + - tempGeoTransform[1] * (poSrcDS->GetRasterXSize()) / 2.0 + - tempGeoTransform[2] * (poSrcDS->GetRasterYSize()) / 2.0; - - padfTiepoints[9] = - tempGeoTransform[3] + - tempGeoTransform[4] * (poSrcDS->GetRasterXSize()) / 2.0 + - tempGeoTransform[5] * (poSrcDS->GetRasterYSize()) / 2.0; - - OGRSpatialReference oUTMorLL; - const auto poSrcSRS = poSrcDS->GetSpatialRef(); - if (poSrcSRS) - oUTMorLL = *poSrcSRS; - auto poLLSRS = oUTMorLL.CloneGeogCS(); - if (poLLSRS && oUTMorLL.IsProjected()) - { - poLLSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - OGRCoordinateTransformation *poTransform = - OGRCreateCoordinateTransformation(&oUTMorLL, poLLSRS); - - // projected coordinate system- need to translate gcps */ - bool bSuccess = poTransform != nullptr; - - for (int index = 0; index < 5; index++) - { - // TODO: If bSuccess is false, set it to false? - if (!bSuccess || !poTransform->Transform( - 1, &(padfTiepoints[index * 2]), - &(padfTiepoints[index * 2 + 1]))) - bSuccess = false; - } - if (bSuccess) - georef_created = true; - } - else - { - georef_created = true; - } - delete poLLSRS; - } - CPLFree(tempGeoTransform); - } - - bool bOK = true; - if (georef_created) - { - /* -------------------------------------------------------------------- - */ - /* top left */ - /* -------------------------------------------------------------------- - */ - bOK &= VSIFPrintfL(fp, "TOP_LEFT_CORNER_LATITUDE = %.10f\n", - padfTiepoints[1]) >= 0; - bOK &= VSIFPrintfL(fp, "TOP_LEFT_CORNER_LONGITUDE = %.10f\n", - padfTiepoints[0]) >= 0; - /* -------------------------------------------------------------------- - */ - /* top_right */ - /* -------------------------------------------------------------------- - */ - bOK &= VSIFPrintfL(fp, "TOP_RIGHT_CORNER_LATITUDE = %.10f\n", - padfTiepoints[3]) >= 0; - bOK &= VSIFPrintfL(fp, "TOP_RIGHT_CORNER_LONGITUDE = %.10f\n", - padfTiepoints[2]) >= 0; - /* -------------------------------------------------------------------- - */ - /* bottom_left */ - /* -------------------------------------------------------------------- - */ - bOK &= VSIFPrintfL(fp, "BOTTOM_LEFT_CORNER_LATITUDE = %.10f\n", - padfTiepoints[5]) >= 0; - bOK &= VSIFPrintfL(fp, "BOTTOM_LEFT_CORNER_LONGITUDE = %.10f\n", - padfTiepoints[4]) >= 0; - /* -------------------------------------------------------------------- - */ - /* bottom_right */ - /* -------------------------------------------------------------------- - */ - bOK &= VSIFPrintfL(fp, "BOTTOM_RIGHT_CORNER_LATITUDE = %.10f\n", - padfTiepoints[7]) >= 0; - bOK &= VSIFPrintfL(fp, "BOTTOM_RIGHT_CORNER_LONGITUDE = %.10f\n", - padfTiepoints[6]) >= 0; - /* -------------------------------------------------------------------- - */ - /* Center */ - /* -------------------------------------------------------------------- - */ - bOK &= - VSIFPrintfL(fp, "CENTRE_LATITUDE = %.10f\n", padfTiepoints[9]) >= 0; - bOK &= VSIFPrintfL(fp, "CENTRE_LONGITUDE = %.10f\n", - padfTiepoints[8]) >= 0; - /* ------------------------------------------------------------------- - */ - /* Ellipsoid/projection */ - /* --------------------------------------------------------------------*/ - - const auto poSrcSRS = poSrcDS->GetSpatialRef(); - char *spheroid_name = nullptr; - - if (poSrcSRS != nullptr) - { - if (poSrcSRS->IsProjected() && - poSrcSRS->GetAttrValue("PROJECTION") != nullptr && - EQUAL(poSrcSRS->GetAttrValue("PROJECTION"), - SRS_PT_TRANSVERSE_MERCATOR)) - { - bOK &= VSIFPrintfL(fp, "PROJECTION_NAME = UTM\n") >= 0; - OGRErr ogrerrorOl = OGRERR_NONE; - bOK &= - VSIFPrintfL(fp, "PROJECTION_ORIGIN_LONGITUDE = %f\n", - poSrcSRS->GetProjParm(SRS_PP_CENTRAL_MERIDIAN, - 0.0, &ogrerrorOl)) >= 0; - } - else if (poSrcSRS->IsGeographic()) - { - bOK &= VSIFPrintfL(fp, "PROJECTION_NAME = LL\n") >= 0; - } - else - { - CPLError(CE_Warning, CPLE_AppDefined, - "Unrecognized projection- no georeferencing " - "information transferred."); - bOK &= VSIFPrintfL(fp, "PROJECTION_NAME = LL\n") >= 0; - } - OGRErr ogrerrorEq = OGRERR_NONE; - const double eq_radius = poSrcSRS->GetSemiMajor(&ogrerrorEq); - OGRErr ogrerrorInvf = OGRERR_NONE; - const double inv_flattening = - poSrcSRS->GetInvFlattening(&ogrerrorInvf); - if (ogrerrorEq == OGRERR_NONE && ogrerrorInvf == OGRERR_NONE) - { - MFFSpheroidList *mffEllipsoids = new MFFSpheroidList; - spheroid_name = - mffEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening( - eq_radius, inv_flattening); - if (spheroid_name != nullptr) - { - bOK &= VSIFPrintfL(fp, "SPHEROID_NAME = %s\n", - spheroid_name) >= 0; - } - else - { - bOK &= VSIFPrintfL(fp, - "SPHEROID_NAME = USER_DEFINED\n" - "SPHEROID_EQUATORIAL_RADIUS = %.10f\n" - "SPHEROID_POLAR_RADIUS = %.10f\n", - eq_radius, - eq_radius * - (1 - 1.0 / inv_flattening)) >= 0; - } - delete mffEllipsoids; - CPLFree(spheroid_name); - } - } - } - - CPLFree(padfTiepoints); - bOK &= VSIFPrintfL(fp, "END\n") >= 0; - if (VSIFCloseL(fp) != 0) - bOK = false; - - if (!bOK) - { - delete poDS; - CPLFree(pszBaseFilename); - return nullptr; - } - - /* End of georeferencing stuff */ - - /* Make sure image data gets flushed */ - for (int iBand = 0; iBand < poDS->GetRasterCount(); iBand++) - { - RawRasterBand *poDstBand = - reinterpret_cast(poDS->GetRasterBand(iBand + 1)); - poDstBand->FlushCache(false); - } - - if (!pfnProgress(1.0, nullptr, pProgressData)) - { - CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated"); - delete poDS; - - GDALDriver *poMFFDriver = - static_cast(GDALGetDriverByName("MFF")); - poMFFDriver->Delete(pszFilename); - CPLFree(pszBaseFilename); - return nullptr; - } - - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - CPLFree(pszBaseFilename); - - return poDS; -} - /************************************************************************/ /* GDALRegister_MFF() */ /************************************************************************/ @@ -1591,14 +1034,9 @@ void GDALRegister_MFF() poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Vexcel MFF Raster"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/mff.html"); poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdr"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte UInt16 Float32 CInt16 CFloat32"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); poDriver->pfnOpen = MFFDataset::Open; - poDriver->pfnCreate = MFFDataset::Create; - poDriver->pfnCreateCopy = MFFDataset::CreateCopy; GetGDALDriverManager()->RegisterDriver(poDriver); } diff --git a/frmts/raw/ntv2dataset.cpp b/frmts/raw/ntv2dataset.cpp index 811405761195..2cc69054ac11 100644 --- a/frmts/raw/ntv2dataset.cpp +++ b/frmts/raw/ntv2dataset.cpp @@ -102,7 +102,6 @@ class NTv2Dataset final : public RawDataset NTv2Dataset(); ~NTv2Dataset() override; - CPLErr SetGeoTransform(double *padfTransform) override; CPLErr GetGeoTransform(double *padfTransform) override; const OGRSpatialReference *GetSpatialRef() const override @@ -110,13 +109,8 @@ class NTv2Dataset final : public RawDataset return &m_oSRS; } - CPLErr FlushCache(bool bAtClosing) override; - static GDALDataset *Open(GDALOpenInfo *); static int Identify(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszOptions); }; /************************************************************************/ @@ -161,9 +155,6 @@ CPLErr NTv2Dataset::Close() CPLErr eErr = CE_None; if (nOpenFlags != OPEN_FLAGS_CLOSED) { - if (NTv2Dataset::FlushCache(true) != CE_None) - eErr = CE_Failure; - if (fpImage) { if (VSIFCloseL(fpImage) != 0) @@ -203,156 +194,6 @@ static void SwapPtr64IfNecessary(bool bMustSwap, void *ptr) } } -/************************************************************************/ -/* FlushCache() */ -/************************************************************************/ - -CPLErr NTv2Dataset::FlushCache(bool bAtClosing) - -{ - /* -------------------------------------------------------------------- */ - /* Nothing to do in readonly mode, or if nothing seems to have */ - /* changed metadata wise. */ - /* -------------------------------------------------------------------- */ - if (eAccess != GA_Update || !(GetPamFlags() & GPF_DIRTY)) - { - return RawDataset::FlushCache(bAtClosing); - } - - /* -------------------------------------------------------------------- */ - /* Load grid and file headers. */ - /* -------------------------------------------------------------------- */ - const int nRecords = 11; - char achFileHeader[nRecords * knMAX_RECORD_SIZE] = {'\0'}; - char achGridHeader[nRecords * knMAX_RECORD_SIZE] = {'\0'}; - - bool bOK = VSIFSeekL(fpImage, 0, SEEK_SET) == 0; - bOK &= - VSIFReadL(achFileHeader, nRecords, nRecordSize, fpImage) == nRecordSize; - - bOK &= VSIFSeekL(fpImage, nGridOffset, SEEK_SET) == 0; - bOK &= - VSIFReadL(achGridHeader, nRecords, nRecordSize, fpImage) == nRecordSize; - - /* -------------------------------------------------------------------- */ - /* Update the grid, and file headers with any available */ - /* metadata. If all available metadata is recognised then mark */ - /* things "clean" from a PAM point of view. */ - /* -------------------------------------------------------------------- */ - char **papszMD = GetMetadata(); - bool bSomeLeftOver = false; - - for (int i = 0; papszMD != nullptr && papszMD[i] != nullptr; i++) - { - const size_t nMinLen = 8; - char *pszKey = nullptr; - const char *pszValue = CPLParseNameValue(papszMD[i], &pszKey); - if (pszKey == nullptr) - continue; - - if (EQUAL(pszKey, "GS_TYPE")) - { - memcpy(achFileHeader + 3 * nRecordSize + 8, " ", 8); - memcpy(achFileHeader + 3 * nRecordSize + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - } - else if (EQUAL(pszKey, "VERSION")) - { - memcpy(achFileHeader + 4 * nRecordSize + 8, " ", 8); - memcpy(achFileHeader + 4 * nRecordSize + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - } - else if (EQUAL(pszKey, "SYSTEM_F")) - { - memcpy(achFileHeader + 5 * nRecordSize + 8, " ", 8); - memcpy(achFileHeader + 5 * nRecordSize + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - } - else if (EQUAL(pszKey, "SYSTEM_T")) - { - memcpy(achFileHeader + 6 * nRecordSize + 8, " ", 8); - memcpy(achFileHeader + 6 * nRecordSize + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - } - else if (EQUAL(pszKey, "MAJOR_F")) - { - double dfValue = CPLAtof(pszValue); - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achFileHeader + 7 * nRecordSize + 8, &dfValue, 8); - } - else if (EQUAL(pszKey, "MINOR_F")) - { - double dfValue = CPLAtof(pszValue); - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achFileHeader + 8 * nRecordSize + 8, &dfValue, 8); - } - else if (EQUAL(pszKey, "MAJOR_T")) - { - double dfValue = CPLAtof(pszValue); - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achFileHeader + 9 * nRecordSize + 8, &dfValue, 8); - } - else if (EQUAL(pszKey, "MINOR_T")) - { - double dfValue = CPLAtof(pszValue); - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achFileHeader + 10 * nRecordSize + 8, &dfValue, 8); - } - else if (EQUAL(pszKey, "SUB_NAME")) - { - memcpy(achGridHeader + /*0*nRecordSize+*/ 8, " ", 8); - memcpy(achGridHeader + /*0*nRecordSize+*/ 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - } - else if (EQUAL(pszKey, "PARENT")) - { - memcpy(achGridHeader + 1 * nRecordSize + 8, " ", 8); - memcpy(achGridHeader + 1 * nRecordSize + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - } - else if (EQUAL(pszKey, "CREATED")) - { - memcpy(achGridHeader + 2 * nRecordSize + 8, " ", 8); - memcpy(achGridHeader + 2 * nRecordSize + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - } - else if (EQUAL(pszKey, "UPDATED")) - { - memcpy(achGridHeader + 3 * nRecordSize + 8, " ", 8); - memcpy(achGridHeader + 3 * nRecordSize + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - } - else - { - bSomeLeftOver = true; - } - - CPLFree(pszKey); - } - - /* -------------------------------------------------------------------- */ - /* Load grid and file headers. */ - /* -------------------------------------------------------------------- */ - bOK &= VSIFSeekL(fpImage, 0, SEEK_SET) == 0; - bOK &= VSIFWriteL(achFileHeader, nRecords, nRecordSize, fpImage) == - nRecordSize; - - bOK &= VSIFSeekL(fpImage, nGridOffset, SEEK_SET) == 0; - bOK &= VSIFWriteL(achGridHeader, nRecords, nRecordSize, fpImage) == - nRecordSize; - - /* -------------------------------------------------------------------- */ - /* Clear flags if we got everything, then let pam and below do */ - /* their flushing. */ - /* -------------------------------------------------------------------- */ - if (!bSomeLeftOver) - SetPamFlags(GetPamFlags() & (~GPF_DIRTY)); - - if (RawDataset::FlushCache(bAtClosing) != CE_None) - bOK = false; - return bOK ? CE_None : CE_Failure; -} - /************************************************************************/ /* Identify() */ /************************************************************************/ @@ -385,7 +226,7 @@ int NTv2Dataset::Identify(GDALOpenInfo *poOpenInfo) GDALDataset *NTv2Dataset::Open(GDALOpenInfo *poOpenInfo) { - if (!Identify(poOpenInfo)) + if (!Identify(poOpenInfo) || poOpenInfo->eAccess == GA_Update) return nullptr; /* -------------------------------------------------------------------- */ @@ -710,321 +551,6 @@ CPLErr NTv2Dataset::GetGeoTransform(double *padfTransform) return CE_None; } -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr NTv2Dataset::SetGeoTransform(double *padfTransform) - -{ - if (eAccess == GA_ReadOnly) - { - CPLError(CE_Failure, CPLE_NoWriteAccess, - "Unable to update geotransform on readonly file."); - return CE_Failure; - } - - if (padfTransform[2] != 0.0 || padfTransform[4] != 0.0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Rotated and sheared geotransforms not supported for NTv2."); - return CE_Failure; - } - - memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6); - - /* -------------------------------------------------------------------- */ - /* Update grid header. */ - /* -------------------------------------------------------------------- */ - char achHeader[11 * knMAX_RECORD_SIZE] = {'\0'}; - - // read grid header - CPL_IGNORE_RET_VAL(VSIFSeekL(fpImage, nGridOffset, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFReadL(achHeader, 11, nRecordSize, fpImage)); - - // S_LAT - double dfValue = - 3600 * (adfGeoTransform[3] + (nRasterYSize - 0.5) * adfGeoTransform[5]); - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achHeader + 4 * nRecordSize + 8, &dfValue, 8); - - // N_LAT - dfValue = 3600 * (adfGeoTransform[3] + 0.5 * adfGeoTransform[5]); - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achHeader + 5 * nRecordSize + 8, &dfValue, 8); - - // E_LONG - dfValue = -3600 * - (adfGeoTransform[0] + (nRasterXSize - 0.5) * adfGeoTransform[1]); - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achHeader + 6 * nRecordSize + 8, &dfValue, 8); - - // W_LONG - dfValue = -3600 * (adfGeoTransform[0] + 0.5 * adfGeoTransform[1]); - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achHeader + 7 * nRecordSize + 8, &dfValue, 8); - - // LAT_INC - dfValue = -3600 * adfGeoTransform[5]; - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achHeader + 8 * nRecordSize + 8, &dfValue, 8); - - // LONG_INC - dfValue = 3600 * adfGeoTransform[1]; - SwapPtr64IfNecessary(m_bMustSwap, &dfValue); - memcpy(achHeader + 9 * nRecordSize + 8, &dfValue, 8); - - // write grid header. - CPL_IGNORE_RET_VAL(VSIFSeekL(fpImage, nGridOffset, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFWriteL(achHeader, 11, nRecordSize, fpImage)); - - return CE_None; -} - -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *NTv2Dataset::Create(const char *pszFilename, int nXSize, - int nYSize, int nBandsIn, GDALDataType eType, - char **papszOptions) -{ - if (eType != GDT_Float32) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create NTv2 file with unsupported data type '%s'.", - GDALGetDataTypeName(eType)); - return nullptr; - } - if (nBandsIn != 4) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create NTv2 file with unsupported " - "band number '%d'.", - nBandsIn); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Are we extending an existing file? */ - /* -------------------------------------------------------------------- */ - const bool bAppend = CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false); - - /* -------------------------------------------------------------------- */ - /* Try to open or create file. */ - /* -------------------------------------------------------------------- */ - VSILFILE *fp = nullptr; - if (bAppend) - fp = VSIFOpenL(pszFilename, "rb+"); - else - fp = VSIFOpenL(pszFilename, "wb"); - - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to open/create file `%s' failed.\n", pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create a file level header if we are creating new. */ - /* -------------------------------------------------------------------- */ - char achHeader[11 * 16] = {'\0'}; - const char *pszValue = nullptr; - GUInt32 nNumFile = 1; - bool bMustSwap = false; - bool bIsLE = false; - - if (!bAppend) - { - memset(achHeader, 0, sizeof(achHeader)); - - bIsLE = - EQUAL(CSLFetchNameValueDef(papszOptions, "ENDIANNESS", "LE"), "LE"); -#ifdef CPL_LSB - bMustSwap = !bIsLE; -#else - bMustSwap = bIsLE; -#endif - - memcpy(achHeader + 0 * 16, "NUM_OREC", 8); - int nNumOrec = 11; - SwapPtr32IfNecessary(bMustSwap, &nNumOrec); - memcpy(achHeader + 0 * 16 + 8, &nNumOrec, 4); - - memcpy(achHeader + 1 * 16, "NUM_SREC", 8); - int nNumSrec = 11; - SwapPtr32IfNecessary(bMustSwap, &nNumSrec); - memcpy(achHeader + 1 * 16 + 8, &nNumSrec, 4); - - memcpy(achHeader + 2 * 16, "NUM_FILE", 8); - SwapPtr32IfNecessary(bMustSwap, &nNumFile); - memcpy(achHeader + 2 * 16 + 8, &nNumFile, 4); - SwapPtr32IfNecessary(bMustSwap, &nNumFile); - - const size_t nMinLen = 16; - memcpy(achHeader + 3 * 16, "GS_TYPE ", 16); - pszValue = CSLFetchNameValueDef(papszOptions, "GS_TYPE", "SECONDS"); - memcpy(achHeader + 3 * 16 + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - - memcpy(achHeader + 4 * 16, "VERSION ", 16); - pszValue = CSLFetchNameValueDef(papszOptions, "VERSION", ""); - memcpy(achHeader + 4 * 16 + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - - memcpy(achHeader + 5 * 16, "SYSTEM_F ", 16); - pszValue = CSLFetchNameValueDef(papszOptions, "SYSTEM_F", ""); - memcpy(achHeader + 5 * 16 + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - - memcpy(achHeader + 6 * 16, "SYSTEM_T ", 16); - pszValue = CSLFetchNameValueDef(papszOptions, "SYSTEM_T", ""); - memcpy(achHeader + 6 * 16 + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - - memcpy(achHeader + 7 * 16, "MAJOR_F ", 8); - memcpy(achHeader + 8 * 16, "MINOR_F ", 8); - memcpy(achHeader + 9 * 16, "MAJOR_T ", 8); - memcpy(achHeader + 10 * 16, "MINOR_T ", 8); - - CPL_IGNORE_RET_VAL(VSIFWriteL(achHeader, 1, sizeof(achHeader), fp)); - } - - /* -------------------------------------------------------------------- */ - /* Otherwise update the header with an increased subfile count, */ - /* and advanced to the last record of the file. */ - /* -------------------------------------------------------------------- */ - else - { - CPL_IGNORE_RET_VAL(VSIFSeekL(fp, 0, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFReadL(achHeader, 1, 16, fp)); - - bIsLE = achHeader[8] == 11 && achHeader[9] == 0 && achHeader[10] == 0 && - achHeader[11] == 0; - const bool bIsBE = achHeader[8] == 0 && achHeader[9] == 0 && - achHeader[10] == 0 && achHeader[11] == 11; - if (!bIsLE && !bIsBE) - { - VSIFCloseL(fp); - return nullptr; - } -#ifdef CPL_LSB - bMustSwap = bIsBE; -#else - bMustSwap = bIsLE; -#endif - - CPL_IGNORE_RET_VAL(VSIFSeekL(fp, 2 * 16 + 8, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFReadL(&nNumFile, 1, 4, fp)); - SwapPtr32IfNecessary(bMustSwap, &nNumFile); - - nNumFile++; - - SwapPtr32IfNecessary(bMustSwap, &nNumFile); - CPL_IGNORE_RET_VAL(VSIFSeekL(fp, 2 * 16 + 8, SEEK_SET)); - CPL_IGNORE_RET_VAL(VSIFWriteL(&nNumFile, 1, 4, fp)); - SwapPtr32IfNecessary(bMustSwap, &nNumFile); - - CPL_IGNORE_RET_VAL(VSIFSeekL(fp, 0, SEEK_END)); - const vsi_l_offset nEnd = VSIFTellL(fp); - CPL_IGNORE_RET_VAL(VSIFSeekL(fp, nEnd - 16, SEEK_SET)); - } - - /* -------------------------------------------------------------------- */ - /* Write the grid header. */ - /* -------------------------------------------------------------------- */ - memset(achHeader, 0, sizeof(achHeader)); - - const size_t nMinLen = 16; - - memcpy(achHeader + 0 * 16, "SUB_NAME ", 16); - pszValue = CSLFetchNameValueDef(papszOptions, "SUB_NAME", ""); - memcpy(achHeader + 0 * 16 + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - - memcpy(achHeader + 1 * 16, "PARENT ", 16); - pszValue = CSLFetchNameValueDef(papszOptions, "PARENT", "NONE"); - memcpy(achHeader + 1 * 16 + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - - memcpy(achHeader + 2 * 16, "CREATED ", 16); - pszValue = CSLFetchNameValueDef(papszOptions, "CREATED", ""); - memcpy(achHeader + 2 * 16 + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - - memcpy(achHeader + 3 * 16, "UPDATED ", 16); - pszValue = CSLFetchNameValueDef(papszOptions, "UPDATED", ""); - memcpy(achHeader + 3 * 16 + 8, pszValue, - std::min(nMinLen, strlen(pszValue))); - - double dfValue; - - memcpy(achHeader + 4 * 16, "S_LAT ", 8); - dfValue = 0; - SwapPtr64IfNecessary(bMustSwap, &dfValue); - memcpy(achHeader + 4 * 16 + 8, &dfValue, 8); - - memcpy(achHeader + 5 * 16, "N_LAT ", 8); - dfValue = nYSize - 1; - SwapPtr64IfNecessary(bMustSwap, &dfValue); - memcpy(achHeader + 5 * 16 + 8, &dfValue, 8); - - memcpy(achHeader + 6 * 16, "E_LONG ", 8); - dfValue = -1 * (nXSize - 1); - SwapPtr64IfNecessary(bMustSwap, &dfValue); - memcpy(achHeader + 6 * 16 + 8, &dfValue, 8); - - memcpy(achHeader + 7 * 16, "W_LONG ", 8); - dfValue = 0; - SwapPtr64IfNecessary(bMustSwap, &dfValue); - memcpy(achHeader + 7 * 16 + 8, &dfValue, 8); - - memcpy(achHeader + 8 * 16, "LAT_INC ", 8); - dfValue = 1; - SwapPtr64IfNecessary(bMustSwap, &dfValue); - memcpy(achHeader + 8 * 16 + 8, &dfValue, 8); - - memcpy(achHeader + 9 * 16, "LONG_INC", 8); - memcpy(achHeader + 9 * 16 + 8, &dfValue, 8); - - memcpy(achHeader + 10 * 16, "GS_COUNT", 8); - GUInt32 nGSCount = nXSize * nYSize; - SwapPtr32IfNecessary(bMustSwap, &nGSCount); - memcpy(achHeader + 10 * 16 + 8, &nGSCount, 4); - - CPL_IGNORE_RET_VAL(VSIFWriteL(achHeader, 1, sizeof(achHeader), fp)); - - /* -------------------------------------------------------------------- */ - /* Write zeroed grid data. */ - /* -------------------------------------------------------------------- */ - memset(achHeader, 0, 16); - - // Use -1 (0x000080bf) as the default error value. - memset(achHeader + ((bIsLE) ? 10 : 9), 0x80, 1); - memset(achHeader + ((bIsLE) ? 11 : 8), 0xbf, 1); - memset(achHeader + ((bIsLE) ? 14 : 13), 0x80, 1); - memset(achHeader + ((bIsLE) ? 15 : 12), 0xbf, 1); - - for (int i = 0; i < nXSize * nYSize; i++) - CPL_IGNORE_RET_VAL(VSIFWriteL(achHeader, 1, 16, fp)); - - /* -------------------------------------------------------------------- */ - /* Write the end record. */ - /* -------------------------------------------------------------------- */ - memcpy(achHeader, "END ", 8); - memset(achHeader + 8, 0, 8); - CPL_IGNORE_RET_VAL(VSIFWriteL(achHeader, 1, 16, fp)); - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - - if (nNumFile == 1) - return GDALDataset::FromHandle(GDALOpen(pszFilename, GA_Update)); - - CPLString osSubDSName; - osSubDSName.Printf("NTv2:%d:%s", nNumFile - 1, pszFilename); - return GDALDataset::FromHandle(GDALOpen(osSubDSName, GA_Update)); -} - /************************************************************************/ /* GDALRegister_NTv2() */ /************************************************************************/ @@ -1043,11 +569,9 @@ void GDALRegister_NTv2() poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "gsb gvb"); poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32"); poDriver->pfnOpen = NTv2Dataset::Open; poDriver->pfnIdentify = NTv2Dataset::Identify; - poDriver->pfnCreate = NTv2Dataset::Create; GetGDALDriverManager()->RegisterDriver(poDriver); } diff --git a/frmts/raw/pauxdataset.cpp b/frmts/raw/pauxdataset.cpp index 34c044e76281..93cd74284f95 100644 --- a/frmts/raw/pauxdataset.cpp +++ b/frmts/raw/pauxdataset.cpp @@ -53,7 +53,6 @@ class PAuxDataset final : public RawDataset // TODO(schwehr): Why are these public? char *pszAuxFilename; char **papszAuxLines; - int bAuxUpdated; const OGRSpatialReference *GetSpatialRef() const override { @@ -61,7 +60,6 @@ class PAuxDataset final : public RawDataset } CPLErr GetGeoTransform(double *) override; - CPLErr SetGeoTransform(double *) override; int GetGCPCount() override; @@ -75,9 +73,6 @@ class PAuxDataset final : public RawDataset char **GetFileList() override; static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszParamList); }; /************************************************************************/ @@ -98,12 +93,9 @@ class PAuxRasterBand final : public RawRasterBand ~PAuxRasterBand() override; double GetNoDataValue(int *pbSuccess = nullptr) override; - CPLErr SetNoDataValue(double) override; GDALColorTable *GetColorTable() override; GDALColorInterp GetColorInterpretation() override; - - void SetDescription(const char *pszNewDescription) override; }; /************************************************************************/ @@ -198,60 +190,6 @@ double PAuxRasterBand::GetNoDataValue(int *pbSuccess) return CPLAtof(pszLine); } -/************************************************************************/ -/* SetNoDataValue() */ -/************************************************************************/ - -CPLErr PAuxRasterBand::SetNoDataValue(double dfNewValue) - -{ - if (GetAccess() == GA_ReadOnly) - { - CPLError(CE_Failure, CPLE_NoWriteAccess, - "Can't update readonly dataset."); - return CE_Failure; - } - - char szTarget[128] = {'\0'}; - char szValue[128] = {'\0'}; - snprintf(szTarget, sizeof(szTarget), "METADATA_IMG_%d_NO_DATA_VALUE", - nBand); - CPLsnprintf(szValue, sizeof(szValue), "%24.12f", dfNewValue); - - PAuxDataset *poPDS = reinterpret_cast(poDS); - poPDS->papszAuxLines = - CSLSetNameValue(poPDS->papszAuxLines, szTarget, szValue); - - poPDS->bAuxUpdated = TRUE; - - return CE_None; -} - -/************************************************************************/ -/* SetDescription() */ -/* */ -/* We override the set description so we can mark the auxfile */ -/* info as changed. */ -/************************************************************************/ - -void PAuxRasterBand::SetDescription(const char *pszNewDescription) - -{ - if (GetAccess() == GA_Update) - { - char szTarget[128] = {'\0'}; - snprintf(szTarget, sizeof(szTarget), "ChanDesc-%d", nBand); - - PAuxDataset *poPDS = reinterpret_cast(poDS); - poPDS->papszAuxLines = - CSLSetNameValue(poPDS->papszAuxLines, szTarget, pszNewDescription); - - poPDS->bAuxUpdated = TRUE; - } - - GDALRasterBand::SetDescription(pszNewDescription); -} - /************************************************************************/ /* GetColorTable() */ /************************************************************************/ @@ -287,7 +225,7 @@ GDALColorInterp PAuxRasterBand::GetColorInterpretation() PAuxDataset::PAuxDataset() : fpImage(nullptr), nGCPCount(0), pasGCPList(nullptr), - pszAuxFilename(nullptr), papszAuxLines(nullptr), bAuxUpdated(FALSE) + pszAuxFilename(nullptr), papszAuxLines(nullptr) { m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); m_oGCPSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); @@ -324,12 +262,6 @@ CPLErr PAuxDataset::Close() } } - if (bAuxUpdated) - { - CSLSetNameValueSeparator(papszAuxLines, ": "); - CSLSave(papszAuxLines, pszAuxFilename); - } - GDALDeinitGCPs(nGCPCount, pasGCPList); CPLFree(pasGCPList); @@ -534,52 +466,6 @@ CPLErr PAuxDataset::GetGeoTransform(double *padfGeoTransform) return CE_None; } -/************************************************************************/ -/* SetGeoTransform() */ -/************************************************************************/ - -CPLErr PAuxDataset::SetGeoTransform(double *padfGeoTransform) - -{ - char szUpLeftX[128] = {'\0'}; - char szUpLeftY[128] = {'\0'}; - char szLoRightX[128] = {'\0'}; - char szLoRightY[128] = {'\0'}; - - if (std::abs(padfGeoTransform[0]) < 181 && - std::abs(padfGeoTransform[1]) < 1) - { - CPLsnprintf(szUpLeftX, sizeof(szUpLeftX), "%.12f", padfGeoTransform[0]); - CPLsnprintf(szUpLeftY, sizeof(szUpLeftY), "%.12f", padfGeoTransform[3]); - CPLsnprintf(szLoRightX, sizeof(szLoRightX), "%.12f", - padfGeoTransform[0] + - padfGeoTransform[1] * GetRasterXSize()); - CPLsnprintf(szLoRightY, sizeof(szLoRightY), "%.12f", - padfGeoTransform[3] + - padfGeoTransform[5] * GetRasterYSize()); - } - else - { - CPLsnprintf(szUpLeftX, sizeof(szUpLeftX), "%.3f", padfGeoTransform[0]); - CPLsnprintf(szUpLeftY, sizeof(szUpLeftY), "%.3f", padfGeoTransform[3]); - CPLsnprintf(szLoRightX, sizeof(szLoRightX), "%.3f", - padfGeoTransform[0] + - padfGeoTransform[1] * GetRasterXSize()); - CPLsnprintf(szLoRightY, sizeof(szLoRightY), "%.3f", - padfGeoTransform[3] + - padfGeoTransform[5] * GetRasterYSize()); - } - - papszAuxLines = CSLSetNameValue(papszAuxLines, "UpLeftX", szUpLeftX); - papszAuxLines = CSLSetNameValue(papszAuxLines, "UpLeftY", szUpLeftY); - papszAuxLines = CSLSetNameValue(papszAuxLines, "LoRightX", szLoRightX); - papszAuxLines = CSLSetNameValue(papszAuxLines, "LoRightY", szLoRightY); - - bAuxUpdated = TRUE; - - return CE_None; -} - /************************************************************************/ /* Open() */ /************************************************************************/ @@ -821,230 +707,10 @@ GDALDataset *PAuxDataset::Open(GDALOpenInfo *poOpenInfo) poDS->oOvManager.Initialize(poDS.get(), osTarget); poDS->ScanForGCPs(); - poDS->bAuxUpdated = FALSE; return poDS.release(); } -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *PAuxDataset::Create(const char *pszFilename, int nXSize, - int nYSize, int nBandsIn, GDALDataType eType, - char **papszOptions) - -{ - const char *pszInterleave = CSLFetchNameValue(papszOptions, "INTERLEAVE"); - if (pszInterleave == nullptr) - pszInterleave = "BAND"; - - /* -------------------------------------------------------------------- */ - /* Verify input options. */ - /* -------------------------------------------------------------------- */ - if (eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16 && - eType != GDT_Int16) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create PCI .Aux labelled dataset with an illegal\n" - "data type (%s).\n", - GDALGetDataTypeName(eType)); - - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Sum the sizes of the band pixel types. */ - /* -------------------------------------------------------------------- */ - int nPixelSizeSum = 0; - - for (int iBand = 0; iBand < nBandsIn; iBand++) - nPixelSizeSum += GDALGetDataTypeSizeBytes(eType); - - /* -------------------------------------------------------------------- */ - /* Try to create the file. */ - /* -------------------------------------------------------------------- */ - VSILFILE *fp = VSIFOpenL(pszFilename, "w"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file `%s' failed.\n", pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Just write out a couple of bytes to establish the binary */ - /* file, and then close it. */ - /* -------------------------------------------------------------------- */ - CPL_IGNORE_RET_VAL(VSIFWriteL("\0\0", 2, 1, fp)); - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - - /* -------------------------------------------------------------------- */ - /* Create the aux filename. */ - /* -------------------------------------------------------------------- */ - char *pszAuxFilename = - static_cast(CPLMalloc(strlen(pszFilename) + 5)); - strcpy(pszAuxFilename, pszFilename); - - for (int i = static_cast(strlen(pszAuxFilename)) - 1; i > 0; i--) - { - if (pszAuxFilename[i] == '.') - { - pszAuxFilename[i] = '\0'; - break; - } - } - - strcat(pszAuxFilename, ".aux"); - - /* -------------------------------------------------------------------- */ - /* Open the file. */ - /* -------------------------------------------------------------------- */ - fp = VSIFOpenL(pszAuxFilename, "wt"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Attempt to create file `%s' failed.\n", pszAuxFilename); - return nullptr; - } - CPLFree(pszAuxFilename); - - /* -------------------------------------------------------------------- */ - /* We need to write out the original filename but without any */ - /* path components in the AuxilaryTarget line. Do so now. */ - /* -------------------------------------------------------------------- */ - int iStart = static_cast(strlen(pszFilename)) - 1; - while (iStart > 0 && pszFilename[iStart - 1] != '/' && - pszFilename[iStart - 1] != '\\') - iStart--; - - CPL_IGNORE_RET_VAL( - VSIFPrintfL(fp, "AuxilaryTarget: %s\n", pszFilename + iStart)); - - /* -------------------------------------------------------------------- */ - /* Write out the raw definition for the dataset as a whole. */ - /* -------------------------------------------------------------------- */ - CPL_IGNORE_RET_VAL( - VSIFPrintfL(fp, "RawDefinition: %d %d %d\n", nXSize, nYSize, nBandsIn)); - - /* -------------------------------------------------------------------- */ - /* Write out a definition for each band. We always write band */ - /* sequential files for now as these are pretty efficiently */ - /* handled by GDAL. */ - /* -------------------------------------------------------------------- */ - vsi_l_offset nImgOffset = 0; - - for (int iBand = 0; iBand < nBandsIn; iBand++) - { - int nPixelOffset = 0; - int nLineOffset = 0; - vsi_l_offset nNextImgOffset = 0; - - /* -------------------------------------------------------------------- - */ - /* Establish our file layout based on supplied interleaving. */ - /* -------------------------------------------------------------------- - */ - if (EQUAL(pszInterleave, "LINE")) - { - nPixelOffset = GDALGetDataTypeSizeBytes(eType); - nLineOffset = nXSize * nPixelSizeSum; - nNextImgOffset = - nImgOffset + static_cast(nPixelOffset) * nXSize; - } - else if (EQUAL(pszInterleave, "PIXEL")) - { - nPixelOffset = nPixelSizeSum; - nLineOffset = nXSize * nPixelOffset; - nNextImgOffset = nImgOffset + GDALGetDataTypeSizeBytes(eType); - } - else /* default to band */ - { - nPixelOffset = GDALGetDataTypeSize(eType) / 8; - nLineOffset = nXSize * nPixelOffset; - nNextImgOffset = - nImgOffset + nYSize * static_cast(nLineOffset); - } - - /* -------------------------------------------------------------------- - */ - /* Write out line indicating layout. */ - /* -------------------------------------------------------------------- - */ - const char *pszTypeName = nullptr; - if (eType == GDT_Float32) - pszTypeName = "32R"; - else if (eType == GDT_Int16) - pszTypeName = "16S"; - else if (eType == GDT_UInt16) - pszTypeName = "16U"; - else - pszTypeName = "8U"; - - CPL_IGNORE_RET_VAL(VSIFPrintfL( - fp, "ChanDefinition-%d: %s " CPL_FRMT_GIB " %d %d %s\n", iBand + 1, - pszTypeName, static_cast(nImgOffset), nPixelOffset, - nLineOffset, -#ifdef CPL_LSB - "Swapped" -#else - "Unswapped" -#endif - )); - - nImgOffset = nNextImgOffset; - } - - /* -------------------------------------------------------------------- */ - /* Cleanup */ - /* -------------------------------------------------------------------- */ - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - - return static_cast(GDALOpen(pszFilename, GA_Update)); -} - -/************************************************************************/ -/* PAuxDelete() */ -/************************************************************************/ - -static CPLErr PAuxDelete(const char *pszBasename) - -{ - VSILFILE *fp = - VSIFOpenL(CPLResetExtensionSafe(pszBasename, "aux").c_str(), "r"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "%s does not appear to be a PAux dataset: " - "there is no .aux file.", - pszBasename); - return CE_Failure; - } - - const char *pszLine = CPLReadLineL(fp); - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - - if (pszLine == nullptr || !STARTS_WITH_CI(pszLine, "AuxilaryTarget")) - { - CPLError(CE_Failure, CPLE_AppDefined, - "%s does not appear to be a PAux dataset:" - "the .aux file does not start with AuxilaryTarget", - pszBasename); - return CE_Failure; - } - - if (VSIUnlink(pszBasename) != 0) - { - CPLError(CE_Failure, CPLE_AppDefined, "OS unlinking file %s.", - pszBasename); - return CE_Failure; - } - - VSIUnlink(CPLResetExtensionSafe(pszBasename, "aux").c_str()); - - return CE_None; -} - /************************************************************************/ /* GDALRegister_PAux() */ /************************************************************************/ @@ -1061,22 +727,9 @@ void GDALRegister_PAux() poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "PCI .aux Labelled"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/paux.html"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte Int16 UInt16 Float32"); - poDriver->SetMetadataItem( - GDAL_DMD_CREATIONOPTIONLIST, - "" - " " - ""); poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); poDriver->pfnOpen = PAuxDataset::Open; - poDriver->pfnCreate = PAuxDataset::Create; - poDriver->pfnDelete = PAuxDelete; GetGDALDriverManager()->RegisterDriver(poDriver); } diff --git a/frmts/raw/rawdrivers.cpp b/frmts/raw/rawdrivers.cpp index 72193a1252e7..62d58dfa8032 100644 --- a/frmts/raw/rawdrivers.cpp +++ b/frmts/raw/rawdrivers.cpp @@ -14,17 +14,14 @@ void GDALRegister_raw_no_sidecar() GDALRegister_HKV(); GDALRegister_GSC(); GDALRegister_FAST(); - GDALRegister_BT(); GDALRegister_LAN(); GDALRegister_CPG(); GDALRegister_NDF(); GDALRegister_EIR(); - GDALRegister_DIPEx(); GDALRegister_LCP(); GDALRegister_GTX(); GDALRegister_LOSLAS(); GDALRegister_NTv2(); - GDALRegister_CTable2(); GDALRegister_ACE2(); GDALRegister_SNODAS(); GDALRegister_KRO(); diff --git a/frmts/rdb/CMakeLists.txt b/frmts/rdb/CMakeLists.txt deleted file mode 100644 index b212a5499596..000000000000 --- a/frmts/rdb/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_gdal_driver(TARGET gdal_RDB SOURCES rdbdataset.cpp PLUGIN_CAPABLE_IF "NOT GDAL_USE_JSONC_INTERNAL") -gdal_standard_includes(gdal_RDB) -target_include_directories(gdal_RDB PRIVATE ${GDAL_VECTOR_FORMAT_SOURCE_DIR}/geojson) -gdal_target_link_libraries(TARGET gdal_RDB PRIVATE LIBRARIES rdbcpp) - -if (GDAL_USE_JSONC_INTERNAL) - gdal_add_vendored_lib(gdal_RDB libjson) -else () - gdal_target_link_libraries(gdal_RDB PRIVATE ${JSONC_TARGET}) -endif () diff --git a/frmts/rdb/rdbdataset.cpp b/frmts/rdb/rdbdataset.cpp deleted file mode 100644 index d4c087404538..000000000000 --- a/frmts/rdb/rdbdataset.cpp +++ /dev/null @@ -1,788 +0,0 @@ -/****************************************************************************** - * - * Project: RIEGL RDB 2 driver - * Purpose: Add support for reading *.mpx RDB 2 files. - * Author: RIEGL Laser Measurement Systems GmbH (support@riegl.com) - * - ****************************************************************************** - * Copyright (c) 2019, RIEGL Laser Measurement Systems GmbH (support@riegl.com) - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogrgeojsonreader.h" - -#include "rdbdataset.hpp" - -#include -#include -#include -#include - -namespace rdb -{ -void RDBOverview::addRDBNode(RDBNode &oRDBNode, double dfXMin, double dfYMin, - double dfXMax, double dfYMax) -{ - adfMinimum[0] = std::min(adfMinimum[0], dfXMin); - adfMaximum[0] = std::max(adfMaximum[0], dfXMax); - - adfMinimum[1] = std::min(adfMinimum[1], dfYMin); - adfMaximum[1] = std::max(adfMaximum[1], dfYMax); - - aoRDBNodes.push_back(oRDBNode); -} - -void RDBOverview::setTileSize(double dfTileSizeIn) -{ - dfTileSize = dfTileSizeIn; - dfPixelSize = dfTileSize / 256.0; -} - -template struct CPLMallocGuard -{ - T *const pData = nullptr; - - explicit CPLMallocGuard(std::size_t count) - : pData(static_cast(CPLMalloc(sizeof(T) * count))) - { - } - - ~CPLMallocGuard() - { - CPLFree(pData); - } -}; - -template class RDBRasterBandInternal; - -template class RDBRasterBandInternal final : public RDBRasterBand -{ - std::vector>> aoOverviewBands; - std::vector aoVRTRasterBand; - - public: - RDBRasterBandInternal( - RDBDataset *poDSIn, const std::string &osAttributeNameIn, - const riegl::rdb::pointcloud::PointAttribute &oPointAttributeIn, - int nBandIn, GDALDataType eDataTypeIn, int nLevelIn) - : RDBRasterBand(poDSIn, osAttributeNameIn, oPointAttributeIn, nBandIn, - eDataTypeIn, nLevelIn) - { - poDS = poDSIn; - nBand = nBandIn; - - eDataType = eDataTypeIn; - eAccess = poDSIn->eAccess; - - auto &oRDBOverview = poDSIn->aoRDBOverviews[nLevelIn]; - - nRasterXSize = static_cast( - (oRDBOverview.adfMaximum[0] - oRDBOverview.adfMinimum[0]) * 256); - nRasterYSize = static_cast( - (oRDBOverview.adfMaximum[1] - oRDBOverview.adfMinimum[1]) * 256); - - nBlockXSize = 256; - nBlockYSize = 256; - } - - ~RDBRasterBandInternal() - { - } - - RDBRasterBandInternal( - RDBDataset *poDSIn, const std::string &osAttributeNameIn, - const riegl::rdb::pointcloud::PointAttribute &oPointAttributeIn, - int nBandIn, GDALDataType eDataTypeIn, int nLevelIn, - int nNumberOfLayers) - : RDBRasterBandInternal(poDSIn, osAttributeNameIn, oPointAttributeIn, - nBandIn, eDataTypeIn, nLevelIn) - { - aoOverviewBands.resize(nNumberOfLayers); - poDSIn->apoVRTDataset.resize(nNumberOfLayers); - - for (int i = nNumberOfLayers - 2; i >= 0; i--) - { - aoOverviewBands[i].reset(new RDBRasterBandInternal( - poDSIn, osAttributeNameIn, oPointAttributeIn, nBandIn, - eDataTypeIn, i)); - RDBOverview &oRDBOverview = poDSIn->aoRDBOverviews[i]; - - int nDatasetXSize = static_cast(std::round( - (poDSIn->dfXMax - poDSIn->dfXMin) / oRDBOverview.dfPixelSize)); - - int nDatasetYSize = static_cast(std::round( - (poDSIn->dfYMax - poDSIn->dfYMin) / oRDBOverview.dfPixelSize)); - - if (!poDSIn->apoVRTDataset[i]) - { - poDSIn->apoVRTDataset[i].reset( - new VRTDataset(nDatasetXSize, nDatasetYSize)); - } - - VRTAddBand(poDSIn->apoVRTDataset[i].get(), eDataType, nullptr); - - VRTSourcedRasterBand *hVRTBand(dynamic_cast( - poDSIn->apoVRTDataset[i]->GetRasterBand(nBandIn))); - - int bSuccess = FALSE; - double dfNoDataValue = - RDBRasterBandInternal::GetNoDataValue(&bSuccess); - if (bSuccess == FALSE) - { - dfNoDataValue = VRT_NODATA_UNSET; - } - - hVRTBand->AddSimpleSource( - aoOverviewBands[i].get(), - (poDSIn->dfXMin - - oRDBOverview.adfMinimum[0] * oRDBOverview.dfTileSize) / - (oRDBOverview.dfPixelSize), - (poDSIn->dfYMin - - oRDBOverview.adfMinimum[1] * oRDBOverview.dfTileSize) / - (oRDBOverview.dfPixelSize), - nDatasetXSize, nDatasetYSize, 0, 0, nDatasetXSize, - nDatasetYSize, "average", dfNoDataValue); - - aoVRTRasterBand.push_back(hVRTBand); - } - poDS = poDSIn; - nBand = nBandIn; - - eDataType = eDataTypeIn; - eAccess = poDSIn->eAccess; - nRasterXSize = poDSIn->nRasterXSize; - nRasterYSize = poDSIn->nRasterYSize; - nBlockXSize = 256; - nBlockYSize = 256; - } - - double GetNoDataValue(int *pbSuccess) override - { - double dfInvalidValue = RDBRasterBand::GetNoDataValue(pbSuccess); - - if (pbSuccess != nullptr && *pbSuccess == TRUE) - { - return dfInvalidValue; - } - else - { - if (oPointAttribute.maximumValue < std::numeric_limits::max()) - { - if (pbSuccess != nullptr) - { - *pbSuccess = TRUE; - } - return std::numeric_limits::max(); - } - else if (oPointAttribute.minimumValue > - std::numeric_limits::lowest()) - { - if (pbSuccess != nullptr) - { - *pbSuccess = TRUE; - } - return std::numeric_limits::lowest(); - } - // Another no data value could be any value that is actually not in - // the data but in the range of specified rdb attribute. However, - // this could maybe be a problem when combining multiple files. - - // Using always the maximum or minimum value in such cases might be - // at least consistent across multiple files. - if (pbSuccess != nullptr) - { - *pbSuccess = FALSE; - } - return 0.0; - } - } - - virtual CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, - void *pImageIn) override - { - T *pImage = reinterpret_cast(pImageIn); - - constexpr std::size_t nTileSize = 256 * 256; - if (std::isnan(oPointAttribute.invalidValue)) - { - memset(pImageIn, 0, sizeof(T) * nTileSize); - } - else - { - for (std::size_t i = 0; i < nTileSize; i++) - { - pImage[i] = static_cast(oPointAttribute.invalidValue); - } - } - - try - { - RDBDataset *poRDBDs = dynamic_cast(poDS); - if (poRDBDs != nullptr) - { - auto &oRDBOverview = poRDBDs->aoRDBOverviews[nLevel]; - auto &aoRDBNodes = oRDBOverview.aoRDBNodes; - - auto pIt = std::find_if( - aoRDBNodes.begin(), aoRDBNodes.end(), - [&](const RDBNode &poRDBNode) - { - return poRDBNode.nXBlockCoordinates == nBlockXOff && - poRDBNode.nYBlockCoordinates == nBlockYOff; - }); - - if (pIt != aoRDBNodes.end()) - { - using type = RDBCoordinatesPlusData; - CPLMallocGuard oData(pIt->nPointCount); - - uint32_t nPointsReturned = 0; - { - // is locking needed? - // std::lock_guard - // oGuard(poRDBDs->oLock); - auto oSelectQuery = - poRDBDs->oPointcloud.select(pIt->iID); - oSelectQuery.bindBuffer( - poRDBDs->oPointcloud.pointAttribute() - .primaryAttributeName(), - oData.pData[0].adfCoordinates[0], - static_cast(sizeof(type))); - - oSelectQuery.bindBuffer( - osAttributeName, oData.pData[0].data, - static_cast(sizeof(type))); - - nPointsReturned = oSelectQuery.next(pIt->nPointCount); - } - - if (nPointsReturned > 0) - { - double dfHalvePixel = oRDBOverview.dfPixelSize * 0.5; - - double dfTileMinX = - (std::floor((poRDBDs->dfXMin + dfHalvePixel) / - oRDBOverview.dfTileSize) + - nBlockXOff) * - oRDBOverview.dfTileSize; - double dfTileMinY = - (std::floor((poRDBDs->dfYMin + dfHalvePixel) / - oRDBOverview.dfTileSize) + - nBlockYOff) * - oRDBOverview.dfTileSize; - - for (uint32_t i = 0; i < nPointsReturned; i++) - { - int dfPixelX = static_cast( - std::floor((oData.pData[i].adfCoordinates[0] + - dfHalvePixel - dfTileMinX) / - oRDBOverview.dfPixelSize)); - - int dfPixelY = static_cast( - std::floor((oData.pData[i].adfCoordinates[1] + - dfHalvePixel - dfTileMinY) / - oRDBOverview.dfPixelSize)); - - pImage[dfPixelY * 256 + dfPixelX] = - oData.pData[i].data; - } - } - } - } - } - catch (const riegl::rdb::Error &oException) - { - CPLError(CE_Failure, CPLE_AppDefined, "RDB error: %s, %s", - oException.what(), oException.details()); - return CE_Failure; - } - catch (const std::exception &oException) - { - CPLError(CE_Failure, CPLE_AppDefined, "Error: %s", - oException.what()); - return CE_Failure; - } - catch (...) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Unknown error in IReadBlock."); - return CE_Failure; - } - return CE_None; - } - - virtual int GetOverviewCount() override - { - RDBDataset *poRDBDs = dynamic_cast(poDS); - if (poRDBDs == nullptr) - { - return 0; - } - return static_cast(aoVRTRasterBand.size()); - } - - virtual GDALRasterBand *GetOverview(int i) override - { - return aoVRTRasterBand[i]; - } -}; - -RDBDataset::~RDBDataset() -{ -} - -void RDBDataset::SetBandInternal( - RDBDataset *poDs, const std::string &osAttributeName, - const riegl::rdb::pointcloud::PointAttribute &oPointAttribute, - riegl::rdb::pointcloud::DataType eRDBDataType, int nLevel, - int nNumberOfLayers, int &nBandIndex) -{ - RDBRasterBand *poBand = nullptr; - // map riegl rdb datatype to gdal data type - switch (eRDBDataType) - { - case riegl::rdb::pointcloud::DataType::UINT8: - // Should I do ignore the other type? - case riegl::rdb::pointcloud::DataType::INT8: - poBand = new RDBRasterBandInternal( - poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Byte, - nLevel, nNumberOfLayers); - break; - case riegl::rdb::pointcloud::DataType::UINT16: - poBand = new RDBRasterBandInternal( - poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_UInt16, - nLevel, nNumberOfLayers); - break; - case riegl::rdb::pointcloud::DataType::INT16: - poBand = new RDBRasterBandInternal( - poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Int16, - nLevel, nNumberOfLayers); - break; - case riegl::rdb::pointcloud::DataType::UINT32: - poBand = new RDBRasterBandInternal( - poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_UInt32, - nLevel, nNumberOfLayers); - break; - case riegl::rdb::pointcloud::DataType::INT32: - poBand = new RDBRasterBandInternal( - poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Int32, - nLevel, nNumberOfLayers); - break; - case riegl::rdb::pointcloud::DataType::FLOAT32: - poBand = new RDBRasterBandInternal( - poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Float32, - nLevel, nNumberOfLayers); - break; - case riegl::rdb::pointcloud::DataType::FLOAT64: - poBand = new RDBRasterBandInternal( - poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Float64, - nLevel, nNumberOfLayers); - break; - default: - // for all reamining use double. e.g. u/int64_t - // an alternate option would be to check the data in the rdb and use - // the minimum required data type. could be a problem when working - // with multiple files. - poBand = new RDBRasterBandInternal( - poDs, osAttributeName, oPointAttribute, nBandIndex, GDT_Float64, - nLevel, nNumberOfLayers); - break; - } - - poDs->SetBand(nBandIndex, poBand); - nBandIndex++; -} - -void RDBDataset::addRDBNode(const riegl::rdb::pointcloud::GraphNode &oNode, - double dfTileSize, std::size_t nLevel) -{ - double adfNodeMinimum[2]; - double adfNodeMaximum[2]; - - oStatQuery.minimum(oNode.id, - oPointcloud.pointAttribute().primaryAttributeName(), - adfNodeMinimum[0]); - oStatQuery.maximum(oNode.id, - oPointcloud.pointAttribute().primaryAttributeName(), - adfNodeMaximum[0]); - - int dfXNodeMin = static_cast( - std::floor((adfNodeMinimum[0] + dfSizeOfPixel * 0.5) / dfTileSize)); - int dfYNodeMin = static_cast( - std::floor((adfNodeMinimum[1] + dfSizeOfPixel * 0.5) / dfTileSize)); - - int dfXNodeMax = static_cast( - std::ceil((adfNodeMaximum[0] + dfSizeOfPixel * 0.5) / dfTileSize)); - int dfYNodeMax = static_cast( - std::ceil((adfNodeMaximum[1] + dfSizeOfPixel * 0.5) / dfTileSize)); - - RDBNode oRDBNode; - - oRDBNode.iID = oNode.id; - oRDBNode.nPointCount = oNode.pointCountNode; - oRDBNode.nXBlockCoordinates = - dfXNodeMin - static_cast(std::floor( - (dfXMin + dfSizeOfPixel * 0.5) / dfTileSize)); - oRDBNode.nYBlockCoordinates = - dfYNodeMin - static_cast(std::floor( - (dfYMin + dfSizeOfPixel * 0.5) / dfTileSize)); - - if (aoRDBOverviews.size() <= nLevel) - { - aoRDBOverviews.resize(nLevel + 1); - } - aoRDBOverviews[nLevel].setTileSize(dfTileSize); - - aoRDBOverviews[nLevel].addRDBNode(oRDBNode, dfXNodeMin, dfYNodeMin, - dfXNodeMax, dfYNodeMax); -} - -double -RDBDataset::traverseRDBNodes(const riegl::rdb::pointcloud::GraphNode &oNode, - std::size_t nLevel) -{ - if (oNode.children.size() == 0) - { - addRDBNode(oNode, dfSizeOfTile, nLevel); - return dfSizeOfTile; - } - else - { - double dfSizeOfChildTile = 0.0; - for (auto &&oChild : oNode.children) - { - dfSizeOfChildTile = traverseRDBNodes(oChild, nLevel + 1); - } - if (dfSizeOfChildTile >= dfSizeOfTile && oNode.pointCountNode > 0) - { - double dfTileSizeCurrentLevel = dfSizeOfChildTile * 2.0; - - addRDBNode(oNode, dfTileSizeCurrentLevel, nLevel); - - return dfTileSizeCurrentLevel; - } - return 0.0; - } -} - -RDBDataset::RDBDataset(GDALOpenInfo *poOpenInfo) : oPointcloud(oContext) -{ - int nBandIndex = 1; - - riegl::rdb::pointcloud::OpenSettings oSettings(oContext); - oPointcloud.open(poOpenInfo->pszFilename, oSettings); - - oStatQuery = oPointcloud.stat(); - - std::string oPrimaryAttribute = - oPointcloud.pointAttribute().primaryAttributeName(); - - oStatQuery.minimum(1, oPrimaryAttribute, adfMinimumDs[0]); - oStatQuery.maximum(1, oPrimaryAttribute, adfMaximumDs[0]); - - dfResolution = - oPointcloud.pointAttribute().get(oPrimaryAttribute).resolution; - - nChunkSize = oPointcloud.management().getChunkSizeLOD(); - - std::string oPixelInfo = oPointcloud.metaData().get("riegl.pixel_info"); - - json_object *poObj = nullptr; - if (!OGRJSonParse(oPixelInfo.c_str(), &poObj, true)) - { - CPLError(CE_Failure, CPLE_AppDefined, - "riegl.pixel_info is invalid JSon: %s", oPixelInfo.c_str()); - } - JsonObjectUniquePtr oObj(poObj); - - json_object *poPixelSize = CPL_json_object_object_get(poObj, "size"); - - if (poPixelSize != nullptr) - { - json_object *poSize0 = json_object_array_get_idx(poPixelSize, 0); - if (poSize0 != nullptr) - { - dfSizeOfPixel = json_object_get_double(poSize0); - } - } - - ReadGeoreferencing(); - - dfSizeOfTile = dfSizeOfPixel * 256; // 2^8 - - double dfHalvePixel = dfSizeOfPixel * 0.5; - dfXMin = std::floor((adfMinimumDs[0] + dfHalvePixel) / dfSizeOfTile) * - dfSizeOfTile; - dfYMin = std::floor((adfMinimumDs[1] + dfHalvePixel) / dfSizeOfTile) * - dfSizeOfTile; - - dfXMax = std::ceil((adfMaximumDs[0] + dfHalvePixel) / dfSizeOfTile) * - dfSizeOfTile; - dfYMax = std::ceil((adfMaximumDs[1] + dfHalvePixel) / dfSizeOfTile) * - dfSizeOfTile; - - nRasterXSize = static_cast((dfXMax - dfXMin) / dfSizeOfPixel); - nRasterYSize = static_cast((dfYMax - dfYMin) / dfSizeOfPixel); - - traverseRDBNodes(oStatQuery.index()); - - aoRDBOverviews.erase( - std::remove_if(aoRDBOverviews.begin(), aoRDBOverviews.end(), - [](const RDBOverview &oRDBOverView) - { return oRDBOverView.aoRDBNodes.empty(); }), - aoRDBOverviews.end()); - - double dfLevelFactor = std::pow(2, aoRDBOverviews.size()); - nRasterXSize = static_cast(std::ceil(nRasterXSize / dfLevelFactor) * - dfLevelFactor); - nRasterYSize = static_cast(std::ceil(nRasterYSize / dfLevelFactor) * - dfLevelFactor); - - dfXMax = dfXMin + nRasterXSize * dfSizeOfPixel; - dfYMax = dfYMin + nRasterYSize * dfSizeOfPixel; - - riegl::rdb::pointcloud::PointAttributes &oPointAttribute = - oPointcloud.pointAttribute(); - - int nNumberOfLevels = static_cast(aoRDBOverviews.size()); - std::vector aoExistingPointAttributes = oPointAttribute.list(); - - for (auto &&osAttributeName : aoExistingPointAttributes) - { - riegl::rdb::pointcloud::PointAttribute oAttribute = - oPointAttribute.get(osAttributeName); - - if (osAttributeName == oPointAttribute.primaryAttributeName()) - { - continue; - } - if (oAttribute.length == 1) - { - SetBandInternal(this, osAttributeName, oAttribute, - oAttribute.dataType(), nNumberOfLevels - 1, - nNumberOfLevels, nBandIndex); - } - else - { - for (uint32_t i = 0; i < oAttribute.length; i++) - { - std::ostringstream oOss; - oOss << osAttributeName << '[' << i << ']'; - SetBandInternal(this, oOss.str(), oAttribute, - oAttribute.dataType(), nNumberOfLevels - 1, - nNumberOfLevels, nBandIndex); - } - } - } -} - -GDALDataset *RDBDataset::Open(GDALOpenInfo *poOpenInfo) -{ - if (!Identify(poOpenInfo)) - { - return nullptr; - } - - if (poOpenInfo->eAccess == GA_Update) - { - CPLError(CE_Failure, CPLE_NotSupported, - "The RDB driver does not support update access to existing " - "datasets."); - return nullptr; - } - - if (poOpenInfo->fpL == nullptr) - { - return nullptr; - } - try - { - std::unique_ptr poDS(new RDBDataset(poOpenInfo)); - // std::swap(poDS->fp, poOpenInfo->fpL); - // Initialize any PAM information. - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - return poDS.release(); - } - catch (const riegl::rdb::Error &oException) - { - CPLError(CE_Failure, CPLE_OpenFailed, "RDB error: %s, %s", - oException.what(), oException.details()); - return nullptr; - } - - catch (const std::exception &oException) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Error: %s", oException.what()); - return nullptr; - } - catch (...) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Unknown error in Open."); - return nullptr; - } - - return nullptr; -} - -int RDBDataset::Identify(GDALOpenInfo *poOpenInfo) -{ - const char *psHeader = reinterpret_cast(poOpenInfo->pabyHeader); - if (poOpenInfo->nHeaderBytes < 32) - { - return FALSE; - } - - constexpr int kSizeOfRDBHeaderIdentifier = 32; - constexpr char szRDBHeaderIdentifier[kSizeOfRDBHeaderIdentifier] = - "RIEGL LMS RDB 2 POINTCLOUD FILE"; - - if (strncmp(psHeader, szRDBHeaderIdentifier, kSizeOfRDBHeaderIdentifier)) - { - // A more comprehensive test could be done by the library. - // Should file -> library incompatibilities handled in Identify or - // in the Open function? - return FALSE; - } - return TRUE; -} - -CPLErr RDBDataset::GetGeoTransform(double *padfTransform) -{ - padfTransform[0] = dfXMin; - padfTransform[1] = dfSizeOfPixel; - padfTransform[2] = 0; - - padfTransform[3] = dfYMin; - padfTransform[4] = 0; - padfTransform[5] = dfSizeOfPixel; - - return CE_None; -} - -const OGRSpatialReference *RDBDataset::GetSpatialRef() const -{ - return &oSpatialReference; -} - -void RDBDataset::ReadGeoreferencing() -{ - if (osWktString.empty()) - { - try - { - std::string oPixelInfo = - oPointcloud.metaData().get("riegl.geo_tag"); - - json_object *poObj = nullptr; - if (!OGRJSonParse(oPixelInfo.c_str(), &poObj, true)) - { - CPLError(CE_Failure, CPLE_AppDefined, - "riegl.geo_tag is invalid JSon: %s", - oPixelInfo.c_str()); - } - JsonObjectUniquePtr oObj(poObj); - - json_object *poCrs = CPL_json_object_object_get(poObj, "crs"); - - if (poCrs != nullptr) - { - json_object *poWkt = CPL_json_object_object_get(poCrs, "wkt"); - - if (poWkt != nullptr) - { - osWktString = json_object_get_string(poWkt); - oSpatialReference.importFromWkt(osWktString.c_str()); - oSpatialReference.SetAxisMappingStrategy( - OAMS_TRADITIONAL_GIS_ORDER); - } - } - } - catch (const riegl::rdb::Error &oException) - { - CPLError(CE_Failure, CPLE_AppDefined, "RDB error: %s, %s", - oException.what(), oException.details()); - } - catch (const std::exception &oException) - { - CPLError(CE_Failure, CPLE_AppDefined, "Error: %s", - oException.what()); - } - catch (...) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Unknown error in IReadBlock."); - } - } -} - -RDBRasterBand::RDBRasterBand( - RDBDataset *poDSIn, const std::string &osAttributeNameIn, - const riegl::rdb::pointcloud::PointAttribute &oPointAttributeIn, - int nBandIn, GDALDataType eDataTypeIn, int nLevelIn) - : osAttributeName(osAttributeNameIn), oPointAttribute(oPointAttributeIn), - nLevel(nLevelIn) -{ - - osDescription.Printf("%s (%s)", oPointAttribute.title.c_str(), - osAttributeName.c_str()); - - poDS = poDSIn; - nBand = nBandIn; - - eDataType = eDataTypeIn; - eAccess = poDSIn->eAccess; - nRasterXSize = poDSIn->nRasterXSize; - nRasterYSize = poDSIn->nRasterYSize; - nBlockXSize = 256; - nBlockYSize = 256; -} - -double RDBRasterBand::GetNoDataValue(int *pbSuccess) -{ - if (!std::isnan(oPointAttribute.invalidValue)) - { - if (pbSuccess != nullptr) - { - *pbSuccess = TRUE; - } - return oPointAttribute.invalidValue; - } - else - { - if (pbSuccess != nullptr) - { - *pbSuccess = FALSE; - } - return 0.0; - } -} - -const char *RDBRasterBand::GetDescription() const -{ - return osDescription.c_str(); -} - -} // namespace rdb - -void GDALRegister_RDB() -{ - if (!GDAL_CHECK_VERSION("RDB")) - return; - if (GDALGetDriverByName("RDB") != NULL) - return; - GDALDriver *poDriver = new GDALDriver(); - poDriver->SetDescription("RDB"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "RIEGL RDB Map Pixel (.mpx)"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/rdb.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "mpx"); - poDriver->pfnOpen = rdb::RDBDataset::Open; - poDriver->pfnIdentify = rdb::RDBDataset::Identify; - GetGDALDriverManager()->RegisterDriver(poDriver); -} - -// includes the cpp wrapper of the rdb library -#include diff --git a/frmts/rdb/rdbdataset.hpp b/frmts/rdb/rdbdataset.hpp deleted file mode 100644 index 89a83b78d2c4..000000000000 --- a/frmts/rdb/rdbdataset.hpp +++ /dev/null @@ -1,135 +0,0 @@ -/****************************************************************************** - * Project: RIEGL RDB 2 driver - * Purpose: Add support for reading *.mpx RDB 2 files. - * Author: RIEGL Laser Measurement Systems GmbH (support@riegl.com) - * - ****************************************************************************** - * Copyright (c) 2019, RIEGL Laser Measurement Systems GmbH (support@riegl.com) - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef RDB_DATASET_INCLUDED -#define RDB_DATASET_INCLUDED - -#include "../frmts/vrt/vrtdataset.h" -#include "gdal_pam.h" - -#include - -#include -#include -#include -#include -#include - -namespace rdb -{ -class RDBRasterBand; - -struct RDBNode -{ - int nXBlockCoordinates = 0; - int nYBlockCoordinates = 0; - riegl::rdb::pointcloud::GraphNode::ID iID = 0; - uint64_t nPointCount = 0; -}; - -struct RDBOverview -{ - double dfTileSize = 0; - double dfPixelSize = 0; - double adfMinimum[2] = {std::numeric_limits::max(), - std::numeric_limits::max()}; - double adfMaximum[2] = {std::numeric_limits::lowest(), - std::numeric_limits::lowest()}; - std::vector aoRDBNodes; - void addRDBNode(RDBNode &oRDBNode, double dfXMin, double dfYMin, - double dfXMax, double dfYMax); - void setTileSize(double dfTileSizeIn); -}; - -template struct RDBCoordinatesPlusData -{ - double adfCoordinates[2]; - T data; -}; - -class RDBDataset final : public GDALPamDataset -{ - friend class RDBRasterBand; - template friend class RDBRasterBandInternal; - - // is locking needed? - // std::mutex oLock; - FILE *fp = nullptr; - riegl::rdb::Context oContext; - riegl::rdb::Pointcloud oPointcloud; - riegl::rdb::pointcloud::QueryStat oStatQuery; - - OGRSpatialReference oSpatialReference; - - double dfResolution = 0; - int nChunkSize = 0; - double dfSizeOfTile; - double dfSizeOfPixel; - CPLString osWktString; - - std::vector aoRDBOverviews; - std::vector> apoVRTDataset; - - double dfXMin; - double dfYMin; - - double dfXMax; - double dfYMax; - - double adfMinimumDs[2] = {}; - double adfMaximumDs[2] = {}; - - public: - explicit RDBDataset(GDALOpenInfo *poOpenInfo); - ~RDBDataset(); - - static GDALDataset *Open(GDALOpenInfo *poOpenInfo); - static int Identify(GDALOpenInfo *poOpenInfo); - - CPLErr GetGeoTransform(double *padfTransform) override; - const OGRSpatialReference *GetSpatialRef() const override; - - protected: - static void SetBandInternal( - RDBDataset *poDs, const std::string &osAttributeName, - const riegl::rdb::pointcloud::PointAttribute &oPointAttribute, - riegl::rdb::pointcloud::DataType eRDBDataType, int nLevel, - int nNumberOfLevels, int &nBandIndex); - void addRDBNode(const riegl::rdb::pointcloud::GraphNode &oNode, - double dfTileSize, std::size_t nLeve); - double traverseRDBNodes(const riegl::rdb::pointcloud::GraphNode &oNode, - std::size_t nLevel = 0); - - void ReadGeoreferencing(); -}; - -class RDBRasterBand CPL_NON_FINAL : public GDALPamRasterBand -{ - protected: - CPLString osAttributeName; - CPLString osDescription; - riegl::rdb::pointcloud::PointAttribute oPointAttribute; - int nLevel; - - public: - RDBRasterBand( - RDBDataset *poDSIn, const std::string &osAttributeName, - const riegl::rdb::pointcloud::PointAttribute &oPointAttributeIn, - int nBandIn, GDALDataType eDataTypeIn, int nLevelIn); - - virtual double GetNoDataValue(int *pbSuccess = nullptr) override; - virtual const char *GetDescription() const override; -}; -} // namespace rdb - -void GDALRegister_RDB(); - -#endif // RDB_DATASET_INCLUDED diff --git a/frmts/sdts/CMakeLists.txt b/frmts/sdts/CMakeLists.txt deleted file mode 100644 index ced38b88ff6e..000000000000 --- a/frmts/sdts/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# depends from ogr/sdts -add_gdal_driver( - TARGET gdal_SDTS - SOURCES sdts_al.h - sdtsiref.cpp - sdtscatd.cpp - sdtslinereader.cpp - sdtslib.cpp - sdtspointreader.cpp - sdtsattrreader.cpp - sdtstransfer.cpp - sdtspolygonreader.cpp - sdtsxref.cpp - sdtsrasterreader.cpp - sdtsindexedreader.cpp - sdtsdataset.cpp - BUILTIN) -gdal_standard_includes(gdal_SDTS) -target_include_directories(gdal_SDTS PRIVATE $) - -if (BROKEN) - add_executable(sdts2shp EXCLUDE_FROM_ALL sdts2shp.cpp) - gdal_standard_includes(sdts2shp) - target_include_directories(sdts2shp PRIVATE $ - $) - target_link_libraries(sdts2shp PRIVATE $ gdal_SDTS ogr_Shape gdal_iso8211) -endif () diff --git a/frmts/sdts/Doxyfile b/frmts/sdts/Doxyfile deleted file mode 100644 index 58242a9115de..000000000000 --- a/frmts/sdts/Doxyfile +++ /dev/null @@ -1,255 +0,0 @@ -# This file describes the settings to be used by doxygen for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# General configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of word surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = SDTS_AL - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each page. A value of NO (the default) enables the index and the -# value YES disables it. - -DISABLE_INDEX = NO - -# If the EXTRACT_ALL tag is set to YES all classes and functions will be -# included in the documentation, even if no documentation was available. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members inside documented classes or files. - -HIDE_UNDOC_MEMBERS = YES - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output - -GENERATE_HTML = YES - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the FULL_PATH_NAMES tag is set to YES Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used - -FULL_PATH_NAMES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = . ../iso8211 ../../port - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -FILE_PATTERNS = *.h *.cpp *.dox - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = . ../iso8211 - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. - -INPUT_FILTER = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. - -MACRO_EXPANSION = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). In the former case 1 is used as the -# definition. - -PREDEFINED = - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED tag. - -EXPAND_ONLY_PREDEF = NO - -#--------------------------------------------------------------------------- -# Configuration options related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES tag can be used to specify one or more tagfiles. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/local/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO - -# The CGI_NAME tag should be the name of the CGI script that -# starts the search engine (doxysearch) with the correct parameters. -# A script with this name will be generated by doxygen. - -CGI_NAME = search.cgi - -# The CGI_URL tag should be the absolute URL to the directory where the -# cgi binaries are located. See the documentation of your http daemon for -# details. - -CGI_URL = - -# The DOC_URL tag should be the absolute URL to the directory where the -# documentation is located. If left blank the absolute path to the -# documentation, with file:// prepended to it, will be used. - -DOC_URL = - -# The DOC_ABSPATH tag should be the absolute path to the directory where the -# documentation is located. If left blank the directory on the local machine -# will be used. - -DOC_ABSPATH = - -# The BIN_ABSPATH tag must point to the directory where the doxysearch binary -# is installed. - -BIN_ABSPATH = /usr/local/bin/ - -# The EXT_DOC_PATHS tag can be used to specify one or more paths to -# documentation generated for other projects. This allows doxysearch to search -# the documentation for these projects as well. - -EXT_DOC_PATHS = diff --git a/frmts/sdts/Makefile.in b/frmts/sdts/Makefile.in deleted file mode 100644 index 6d50b9d85386..000000000000 --- a/frmts/sdts/Makefile.in +++ /dev/null @@ -1,133 +0,0 @@ - -OBJ = sdtsiref.o sdtscatd.o sdtslinereader.o sdtslib.o \ - sdtspointreader.o sdtsattrreader.o sdtstransfer.o \ - sdtspolygonreader.o sdtsxref.o sdtsrasterreader.o \ - sdtsindexedreader.o \ - \ - ddfmodule.o ddfutils.o ddffielddefn.o ddfrecord.o ddffield.o \ - ddfsubfielddefn.o \ - \ - shpopen.o dbfopen.o \ - \ - cpl_error.o cpl_vsisimple.o cpl_string.o cpl_conv.o cpl_path.o - -CXXFLAGS = @CXXFLAGS@ @CXX_WFLAGS@ -LIBS = @LIBS@ -lm -CXX = @CXX@ - - -default: sdts2shp 8211view - -libsdts_al.a: $(OBJ) - ar r libsdts_al.a $(OBJ) - - -# -# SDTS library -# -sdtsiref.o: sdtsiref.cpp - $(CXX) -c $(CXXFLAGS) sdtsiref.cpp - -sdtscatd.o: sdtscatd.cpp - $(CXX) -c $(CXXFLAGS) sdtscatd.cpp - -sdtslinereader.o: sdtslinereader.cpp - $(CXX) -c $(CXXFLAGS) sdtslinereader.cpp - -sdtslib.o: sdtslib.cpp - $(CXX) -c $(CXXFLAGS) sdtslib.cpp - -sdtspointreader.o: sdtspointreader.cpp - $(CXX) -c $(CXXFLAGS) sdtspointreader.cpp - -sdtsattrreader.o: sdtsattrreader.cpp - $(CXX) -c $(CXXFLAGS) sdtsattrreader.cpp - -sdtstransfer.o: sdtstransfer.cpp - $(CXX) -c $(CXXFLAGS) sdtstransfer.cpp - -sdtspolygonreader.o: sdtspolygonreader.cpp - $(CXX) -c $(CXXFLAGS) sdtspolygonreader.cpp - -sdtsxref.o: sdtsxref.cpp - $(CXX) -c $(CXXFLAGS) sdtsxref.cpp - -sdtsrasterreader.o: sdtsrasterreader.cpp - $(CXX) -c $(CXXFLAGS) sdtsrasterreader.cpp - -sdtsindexedreader.o: sdtsindexedreader.cpp - $(CXX) -c $(CXXFLAGS) sdtsindexedreader.cpp - -# -# from iso8211 library -# - -ddfmodule.o: ddfmodule.cpp - $(CXX) -c $(CXXFLAGS) ddfmodule.cpp - -ddfutils.o: ddfutils.cpp - $(CXX) -c $(CXXFLAGS) ddfutils.cpp - -ddffielddefn.o: ddffielddefn.cpp - $(CXX) -c $(CXXFLAGS) ddffielddefn.cpp - -ddfrecord.o: ddfrecord.cpp - $(CXX) -c $(CXXFLAGS) ddfrecord.cpp - -ddffield.o: ddffield.cpp - $(CXX) -c $(CXXFLAGS) ddffield.cpp - -ddfsubfielddefn.o: ddfsubfielddefn.cpp - $(CXX) -c $(CXXFLAGS) ddfsubfielddefn.cpp - -# -# Common Portability Library -# - -cpl_error.o: cpl_error.cpp - $(CXX) -c $(CXXFLAGS) cpl_error.cpp - -cpl_string.o: cpl_string.cpp - $(CXX) -c $(CXXFLAGS) cpl_string.cpp - -cpl_conv.o: cpl_conv.cpp - $(CXX) -c $(CXXFLAGS) cpl_conv.cpp - -cpl_vsisimple.o: cpl_vsisimple.cpp - $(CXX) -c $(CXXFLAGS) cpl_vsisimple.cpp - -cpl_path.o: cpl_path.cpp - $(CXX) -c $(CXXFLAGS) cpl_path.cpp - -# -# Shapefile access -# -shpopen.o: shpopen.c - $(CXX) -c $(CXXFLAGS) shpopen.c - -dbfopen.o: dbfopen.c - $(CXX) -c $(CXXFLAGS) dbfopen.c - -# -# Mainlines -# - -sdts2shp.o: sdts2shp.cpp - $(CXX) -c $(CXXFLAGS) sdts2shp.cpp - -8211view.o: 8211view.cpp - $(CXX) -c $(CXXFLAGS) 8211view.cpp - -8211dump.o: 8211dump.cpp - $(CXX) -c $(CXXFLAGS) 8211dump.cpp - -sdts2shp: sdts2shp.o libsdts_al.a - $(CXX) $(CXXFLAGS) sdts2shp.o libsdts_al.a $(LIBS) -o sdts2shp - -8211view: 8211view.o libsdts_al.a - $(CXX) $(CXXFLAGS) 8211view.o libsdts_al.a $(LIBS) -o 8211view - -8211dump: 8211dump.o libsdts_al.a - $(CXX) $(CXXFLAGS) 8211dump.o libsdts_al.a $(LIBS) -o 8211dump - - diff --git a/frmts/sdts/aclocal.m4 b/frmts/sdts/aclocal.m4 deleted file mode 100644 index d4d18f50c903..000000000000 --- a/frmts/sdts/aclocal.m4 +++ /dev/null @@ -1,15 +0,0 @@ -AC_DEFUN(AC_COMPILER_WFLAGS, -[ - # Remove -g from compile flags, we will add via CFG variable if - # we need it. - CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-g //"` - CFLAGS=`echo "$CFLAGS " | sed "s/-g //"` - - # check for GNU compiler, and use -Wall - if test "$GXX" = "yes"; then - CXX_WFLAGS="-Wall" - AC_DEFINE(USE_GNUCC) - fi - AC_SUBST(CXX_WFLAGS,$CXX_WFLAGS) - AC_SUBST(C_WFLAGS,$C_WFLAGS) -]) diff --git a/frmts/sdts/configure.in b/frmts/sdts/configure.in deleted file mode 100644 index b3a8a31f25b9..000000000000 --- a/frmts/sdts/configure.in +++ /dev/null @@ -1,18 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -AC_INIT(Makefile.in) -AC_CONFIG_HEADER(cpl_config.h) - -dnl Checks for programs. -AC_PROG_CXX - -dnl Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h unistd.h) - -dnl Checks for library functions. -AC_C_BIGENDIAN -AC_FUNC_VPRINTF - -AC_COMPILER_WFLAGS - -AC_OUTPUT(Makefile) diff --git a/frmts/sdts/makefile.vc.dist b/frmts/sdts/makefile.vc.dist deleted file mode 100644 index 2e714253ec12..000000000000 --- a/frmts/sdts/makefile.vc.dist +++ /dev/null @@ -1,47 +0,0 @@ -CFLAGS = /W3 -CXXFLAGS = /W3 - -LIBNAME = sdts_al.lib - -OBJ = sdtsiref.obj sdtscatd.obj sdtslinereader.obj sdtslib.obj \ - sdtspointreader.obj sdtsattrreader.obj sdtstransfer.obj \ - sdtspolygonreader.obj sdtsxref.obj sdtsrasterreader.obj \ - sdtsindexedreader.obj \ - \ - ddfmodule.obj ddfutils.obj ddffielddefn.obj ddfrecord.obj \ - ddffield.obj ddfsubfielddefn.obj \ - \ - shpopen.obj dbfopen.obj \ - \ - cpl_error.obj cpl_vsisimple.obj cpl_string.obj cpl_conv.obj \ - cpl_path.obj - - -default: $(LIBNAME) sdts2shp.exe 8211view.exe 8211dump.exe - -clean: - del *.obj $(LIBNAME) - -.c.obj: - $(CC) $(CFLAGS) /c $*.c - -.cpp.obj: - $(CXX) $(CXXFLAGS) /c $*.cpp - -$(LIBNAME): $(OBJ) - if exist $(LIBNAME) del $(LIBNAME) - lib /out:$(LIBNAME) $(OBJ) - -# -# Mainlines -# -sdts2shp.exe: sdts2shp.cpp $(LIBNAME) - $(CXX) sdts2shp.cpp $(LIBNAME) - -8211view.exe: 8211view.cpp $(LIBNAME) - $(CXX) 8211view.cpp $(LIBNAME) - -8211dump.exe: 8211dump.cpp $(LIBNAME) - $(CXX) 8211dump.cpp $(LIBNAME) - - diff --git a/frmts/sdts/sdts2shp.cpp b/frmts/sdts/sdts2shp.cpp deleted file mode 100644 index 570308f9517e..000000000000 --- a/frmts/sdts/sdts2shp.cpp +++ /dev/null @@ -1,816 +0,0 @@ -/* **************************************************************************** - * - * Project: SDTS Translator - * Purpose: Mainline for converting to ArcView Shapefiles. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" -#include "shapefil.h" -#include "cpl_string.h" - -static int bVerbose = FALSE; - -static void WriteLineShapefile(const char *, SDTSTransfer *, const char *); -static void WritePointShapefile(const char *, SDTSTransfer *, const char *); -static void WriteAttributeDBF(const char *, SDTSTransfer *, const char *); -static void WritePolygonShapefile(const char *, SDTSTransfer *, const char *); - -static void AddPrimaryAttrToDBFSchema(DBFHandle hDBF, SDTSTransfer *poTransfer, - char **papszModuleList); -static void WritePrimaryAttrToDBF(DBFHandle hDBF, int nRecord, SDTSTransfer *, - SDTSFeature *poFeature); -static void WriteAttrRecordToDBF(DBFHandle hDBF, int nRecord, SDTSTransfer *, - DDFField *poAttributes); - -/* **********************************************************************/ -/* Usage() */ -/* **********************************************************************/ - -static void Usage() - -{ - printf("Usage: sdts2shp CATD_filename [-o shapefile_name]\n" /*ok*/ - " [-m module_name] [-v]\n" - "\n" - "Modules include `LE01', `PC01', `NP01' and `ARDF'\n"); - - exit(1); -} - -/* **********************************************************************/ -/* main() */ -/* **********************************************************************/ - -int main(int nArgc, char **papszArgv) - -{ - { - int i; - const char *pszCATDFilename = NULL; - const char *pszMODN = "LE01"; - char *pszShapefile = "sdts_out.shp"; - SDTSTransfer oTransfer; - - /* -------------------------------------------------------------------- - */ - /* Interpret commandline switches. */ - /* -------------------------------------------------------------------- - */ - if (nArgc < 2) - Usage(); - - pszCATDFilename = papszArgv[1]; - - for (i = 2; i < nArgc; i++) - { - if (EQUAL(papszArgv[i], "-m") && i + 1 < nArgc) - pszMODN = papszArgv[++i]; - else if (EQUAL(papszArgv[i], "-o") && i + 1 < nArgc) - pszShapefile = papszArgv[++i]; - else if (EQUAL(papszArgv[i], "-v")) - bVerbose = TRUE; - else - { - printf("Incomplete, or unsupported option `%s'\n\n", /*ok*/ - papszArgv[i]); - Usage(); - } - } - - /* -------------------------------------------------------------------- - */ - /* Massage shapefile name to have no extension. */ - /* -------------------------------------------------------------------- - */ - pszShapefile = CPLStrdup(pszShapefile); - for (i = strlen(pszShapefile) - 1; i >= 0; i--) - { - if (pszShapefile[i] == '.') - { - pszShapefile[i] = '\0'; - break; - } - else if (pszShapefile[i] == '/' || pszShapefile[i] == '\\') - break; - } - - /* -------------------------------------------------------------------- - */ - /* Open the transfer. */ - /* -------------------------------------------------------------------- - */ - if (!oTransfer.Open(pszCATDFilename)) - { - fprintf(stderr, "Failed to read CATD file `%s'\n", pszCATDFilename); - exit(100); - } - - /* -------------------------------------------------------------------- - */ - /* Dump available layer in verbose mode. */ - /* -------------------------------------------------------------------- - */ - if (bVerbose) - { - printf("Layers:\n"); /*ok*/ - for (i = 0; i < oTransfer.GetLayerCount(); i++) - { - int iCATDEntry = oTransfer.GetLayerCATDEntry(i); - - printf(" %s: `%s'\n", /*ok*/ - oTransfer.GetCATD()->GetEntryModule(iCATDEntry), - oTransfer.GetCATD()->GetEntryTypeDesc(iCATDEntry)); - } - printf("\n"); /*ok*/ - } - - /* -------------------------------------------------------------------- - */ - /* Check that module exists. */ - /* -------------------------------------------------------------------- - */ - if (oTransfer.FindLayer(pszMODN) == -1) - { - fprintf(stderr, "Unable to identify module: %s\n", pszMODN); - exit(1); - } - - /* -------------------------------------------------------------------- - */ - /* If the module is an LE module, write it to an Arc file. */ - /* -------------------------------------------------------------------- - */ - if (pszMODN[0] == 'L' || pszMODN[0] == 'l') - { - WriteLineShapefile(pszShapefile, &oTransfer, pszMODN); - } - - /* -------------------------------------------------------------------- - */ - /* If the module is an attribute primary one, dump to DBF. */ - /* -------------------------------------------------------------------- - */ - else if (pszMODN[0] == 'A' || pszMODN[0] == 'a' || pszMODN[0] == 'B' || - pszMODN[0] == 'b') - { - WriteAttributeDBF(pszShapefile, &oTransfer, pszMODN); - } - - /* -------------------------------------------------------------------- - */ - /* If the module is a point one, dump to Shapefile. */ - /* -------------------------------------------------------------------- - */ - else if (pszMODN[0] == 'N' || pszMODN[0] == 'n') - { - WritePointShapefile(pszShapefile, &oTransfer, pszMODN); - } - - /* -------------------------------------------------------------------- - */ - /* If the module is a polygon one, dump to Shapefile. */ - /* -------------------------------------------------------------------- - */ - else if (pszMODN[0] == 'P' || pszMODN[0] == 'p') - { - WritePolygonShapefile(pszShapefile, &oTransfer, pszMODN); - } - - else - { - fprintf(stderr, "Unrecognized module name: %s\n", pszMODN); - } - - CPLFree(pszShapefile); - } -} - -/* **********************************************************************/ -/* WriteLineShapefile() */ -/* **********************************************************************/ - -static void WriteLineShapefile(const char *pszShapefile, - SDTSTransfer *poTransfer, const char *pszMODN) - -{ - /* -------------------------------------------------------------------- */ - /* Fetch a reference to the indexed Pointgon reader. */ - /* -------------------------------------------------------------------- */ - SDTSLineReader *poLineReader = - (SDTSLineReader *)poTransfer->GetLayerIndexedReader( - poTransfer->FindLayer(pszMODN)); - - if (poLineReader == NULL) - { - fprintf(stderr, "Failed to open %s.\n", - poTransfer->GetCATD()->GetModuleFilePath(pszMODN)); - return; - } - - poLineReader->Rewind(); - - /* -------------------------------------------------------------------- */ - /* Create the Shapefile. */ - /* -------------------------------------------------------------------- */ - SHPHandle hSHP; - - hSHP = SHPCreate(pszShapefile, SHPT_ARC); - if (hSHP == NULL) - { - fprintf(stderr, "Unable to create shapefile `%s'\n", pszShapefile); - return; - } - - /* -------------------------------------------------------------------- */ - /* Create the database file, and our basic set of attributes. */ - /* -------------------------------------------------------------------- */ - DBFHandle hDBF; - int nLeftPolyField, nRightPolyField; - int nStartNodeField, nEndNodeField, nSDTSRecordField; - char szDBFFilename[1024]; - - sprintf(szDBFFilename, "%s.dbf", pszShapefile); - - hDBF = DBFCreate(szDBFFilename); - if (hDBF == NULL) - { - fprintf(stderr, "Unable to create shapefile .dbf for `%s'\n", - pszShapefile); - return; - } - - nSDTSRecordField = DBFAddField(hDBF, "SDTSRecId", FTInteger, 8, 0); - nLeftPolyField = DBFAddField(hDBF, "LeftPoly", FTString, 12, 0); - nRightPolyField = DBFAddField(hDBF, "RightPoly", FTString, 12, 0); - nStartNodeField = DBFAddField(hDBF, "StartNode", FTString, 12, 0); - nEndNodeField = DBFAddField(hDBF, "EndNode", FTString, 12, 0); - - char **papszModRefs = poLineReader->ScanModuleReferences(); - AddPrimaryAttrToDBFSchema(hDBF, poTransfer, papszModRefs); - CSLDestroy(papszModRefs); - - /* ==================================================================== */ - /* Process all the line features in the module. */ - /* ==================================================================== */ - SDTSRawLine *poRawLine = NULL; - - while ((poRawLine = poLineReader->GetNextLine()) != NULL) - { - /* -------------------------------------------------------------------- - */ - /* Write out a shape with the vertices. */ - /* -------------------------------------------------------------------- - */ - SHPObject *psShape = SHPCreateSimpleObject( - SHPT_ARC, poRawLine->nVertices, poRawLine->padfX, poRawLine->padfY, - poRawLine->padfZ); - - int iShape = SHPWriteObject(hSHP, -1, psShape); - - SHPDestroyObject(psShape); - - /* -------------------------------------------------------------------- - */ - /* Write out the attributes. */ - /* -------------------------------------------------------------------- - */ - char szID[13]; - - DBFWriteIntegerAttribute(hDBF, iShape, nSDTSRecordField, - poRawLine->oModId.nRecord); - - sprintf(szID, "%s:%d", poRawLine->oLeftPoly.szModule, - poRawLine->oLeftPoly.nRecord); - DBFWriteStringAttribute(hDBF, iShape, nLeftPolyField, szID); - - sprintf(szID, "%s:%d", poRawLine->oRightPoly.szModule, - poRawLine->oRightPoly.nRecord); - DBFWriteStringAttribute(hDBF, iShape, nRightPolyField, szID); - - sprintf(szID, "%s:%d", poRawLine->oStartNode.szModule, - poRawLine->oStartNode.nRecord); - DBFWriteStringAttribute(hDBF, iShape, nStartNodeField, szID); - - sprintf(szID, "%s:%d", poRawLine->oEndNode.szModule, - poRawLine->oEndNode.nRecord); - DBFWriteStringAttribute(hDBF, iShape, nEndNodeField, szID); - - WritePrimaryAttrToDBF(hDBF, iShape, poTransfer, poRawLine); - - if (!poLineReader->IsIndexed()) - delete poRawLine; - } - - /* -------------------------------------------------------------------- */ - /* Close, and cleanup. */ - /* -------------------------------------------------------------------- */ - DBFClose(hDBF); - SHPClose(hSHP); -} - -/* **********************************************************************/ -/* WritePointShapefile() */ -/* **********************************************************************/ - -static void WritePointShapefile(const char *pszShapefile, - SDTSTransfer *poTransfer, const char *pszMODN) - -{ - /* -------------------------------------------------------------------- */ - /* Fetch a reference to the indexed Pointgon reader. */ - /* -------------------------------------------------------------------- */ - SDTSPointReader *poPointReader = - (SDTSPointReader *)poTransfer->GetLayerIndexedReader( - poTransfer->FindLayer(pszMODN)); - - if (poPointReader == NULL) - { - fprintf(stderr, "Failed to open %s.\n", - poTransfer->GetCATD()->GetModuleFilePath(pszMODN)); - return; - } - - poPointReader->Rewind(); - - /* -------------------------------------------------------------------- */ - /* Create the Shapefile. */ - /* -------------------------------------------------------------------- */ - SHPHandle hSHP; - - hSHP = SHPCreate(pszShapefile, SHPT_POINT); - if (hSHP == NULL) - { - fprintf(stderr, "Unable to create shapefile `%s'\n", pszShapefile); - return; - } - - /* -------------------------------------------------------------------- */ - /* Create the database file, and our basic set of attributes. */ - /* -------------------------------------------------------------------- */ - DBFHandle hDBF; - int nAreaField, nSDTSRecordField; - char szDBFFilename[1024]; - - sprintf(szDBFFilename, "%s.dbf", pszShapefile); - - hDBF = DBFCreate(szDBFFilename); - if (hDBF == NULL) - { - fprintf(stderr, "Unable to create shapefile .dbf for `%s'\n", - pszShapefile); - return; - } - - nSDTSRecordField = DBFAddField(hDBF, "SDTSRecId", FTInteger, 8, 0); - nAreaField = DBFAddField(hDBF, "AreaId", FTString, 12, 0); - - char **papszModRefs = poPointReader->ScanModuleReferences(); - AddPrimaryAttrToDBFSchema(hDBF, poTransfer, papszModRefs); - CSLDestroy(papszModRefs); - - /* ==================================================================== */ - /* Process all the line features in the module. */ - /* ==================================================================== */ - SDTSRawPoint *poRawPoint = NULL; - - while ((poRawPoint = poPointReader->GetNextPoint()) != NULL) - { - /* -------------------------------------------------------------------- - */ - /* Write out a shape with the vertices. */ - /* -------------------------------------------------------------------- - */ - SHPObject *psShape = - SHPCreateSimpleObject(SHPT_POINT, 1, &(poRawPoint->dfX), - &(poRawPoint->dfY), &(poRawPoint->dfZ)); - - int iShape = SHPWriteObject(hSHP, -1, psShape); - - SHPDestroyObject(psShape); - - /* -------------------------------------------------------------------- - */ - /* Write out the attributes. */ - /* -------------------------------------------------------------------- - */ - char szID[13]; - - DBFWriteIntegerAttribute(hDBF, iShape, nSDTSRecordField, - poRawPoint->oModId.nRecord); - - sprintf(szID, "%s:%d", poRawPoint->oAreaId.szModule, - poRawPoint->oAreaId.nRecord); - DBFWriteStringAttribute(hDBF, iShape, nAreaField, szID); - - WritePrimaryAttrToDBF(hDBF, iShape, poTransfer, poRawPoint); - - if (!poPointReader->IsIndexed()) - delete poRawPoint; - } - - /* -------------------------------------------------------------------- */ - /* Close, and cleanup. */ - /* -------------------------------------------------------------------- */ - DBFClose(hDBF); - SHPClose(hSHP); -} - -/* **********************************************************************/ -/* WriteAttributeDBF() */ -/* **********************************************************************/ - -static void WriteAttributeDBF(const char *pszShapefile, - SDTSTransfer *poTransfer, const char *pszMODN) - -{ - /* -------------------------------------------------------------------- */ - /* Fetch a reference to the indexed Pointgon reader. */ - /* -------------------------------------------------------------------- */ - SDTSAttrReader *poAttrReader = - (SDTSAttrReader *)poTransfer->GetLayerIndexedReader( - poTransfer->FindLayer(pszMODN)); - - if (poAttrReader == NULL) - { - fprintf(stderr, "Failed to open %s.\n", - poTransfer->GetCATD()->GetModuleFilePath(pszMODN)); - return; - } - - poAttrReader->Rewind(); - - /* -------------------------------------------------------------------- */ - /* Create the database file, and our basic set of attributes. */ - /* -------------------------------------------------------------------- */ - DBFHandle hDBF; - char szDBFFilename[1024]; - - sprintf(szDBFFilename, "%s.dbf", pszShapefile); - - hDBF = DBFCreate(szDBFFilename); - if (hDBF == NULL) - { - fprintf(stderr, "Unable to create shapefile .dbf for `%s'\n", - pszShapefile); - return; - } - - DBFAddField(hDBF, "SDTSRecId", FTInteger, 8, 0); - - /* -------------------------------------------------------------------- */ - /* Prepare the schema. */ - /* -------------------------------------------------------------------- */ - char **papszMODNList = CSLAddString(NULL, pszMODN); - - AddPrimaryAttrToDBFSchema(hDBF, poTransfer, papszMODNList); - - CSLDestroy(papszMODNList); - - /* ==================================================================== */ - /* Process all the records in the module. */ - /* ==================================================================== */ - SDTSAttrRecord *poRecord = NULL; - int iRecord = 0; - - while ((poRecord = (SDTSAttrRecord *)poAttrReader->GetNextFeature()) != - NULL) - { - DBFWriteIntegerAttribute(hDBF, iRecord, 0, poRecord->oModId.nRecord); - - WriteAttrRecordToDBF(hDBF, iRecord, poTransfer, poRecord->poATTR); - - if (!poAttrReader->IsIndexed()) - delete poRecord; - - iRecord++; - } - - /* -------------------------------------------------------------------- */ - /* Close, and cleanup. */ - /* -------------------------------------------------------------------- */ - DBFClose(hDBF); -} - -/* **********************************************************************/ -/* WritePolygonShapefile() */ -/* **********************************************************************/ - -static void WritePolygonShapefile(const char *pszShapefile, - SDTSTransfer *poTransfer, const char *pszMODN) - -{ - /* -------------------------------------------------------------------- */ - /* Fetch a reference to the indexed polygon reader. */ - /* -------------------------------------------------------------------- */ - SDTSPolygonReader *poPolyReader = - (SDTSPolygonReader *)poTransfer->GetLayerIndexedReader( - poTransfer->FindLayer(pszMODN)); - - if (poPolyReader == NULL) - { - fprintf(stderr, "Failed to open %s.\n", - poTransfer->GetCATD()->GetModuleFilePath(pszMODN)); - return; - } - - /* -------------------------------------------------------------------- */ - /* Assemble polygon geometries from all the line layers. */ - /* -------------------------------------------------------------------- */ - poPolyReader->AssembleRings(poTransfer, poTransfer->FindLayer(pszMODN)); - - /* -------------------------------------------------------------------- */ - /* Create the Shapefile. */ - /* -------------------------------------------------------------------- */ - SHPHandle hSHP; - - hSHP = SHPCreate(pszShapefile, SHPT_POLYGON); - if (hSHP == NULL) - { - fprintf(stderr, "Unable to create shapefile `%s'\n", pszShapefile); - return; - } - - /* -------------------------------------------------------------------- */ - /* Create the database file, and our basic set of attributes. */ - /* -------------------------------------------------------------------- */ - DBFHandle hDBF; - int nSDTSRecordField; - char szDBFFilename[1024]; - - sprintf(szDBFFilename, "%s.dbf", pszShapefile); - - hDBF = DBFCreate(szDBFFilename); - if (hDBF == NULL) - { - fprintf(stderr, "Unable to create shapefile .dbf for `%s'\n", - pszShapefile); - return; - } - - nSDTSRecordField = DBFAddField(hDBF, "SDTSRecId", FTInteger, 8, 0); - - char **papszModRefs = poPolyReader->ScanModuleReferences(); - AddPrimaryAttrToDBFSchema(hDBF, poTransfer, papszModRefs); - CSLDestroy(papszModRefs); - - /* ==================================================================== */ - /* Process all the polygon features in the module. */ - /* ==================================================================== */ - poPolyReader->Rewind(); - - SDTSRawPolygon *poRawPoly = NULL; - while ((poRawPoly = (SDTSRawPolygon *)poPolyReader->GetNextFeature()) != - NULL) - { - /* -------------------------------------------------------------------- - */ - /* Write out a shape with the vertices. */ - /* -------------------------------------------------------------------- - */ - SHPObject *psShape = SHPCreateObject( - SHPT_POLYGON, -1, poRawPoly->nRings, poRawPoly->panRingStart, NULL, - poRawPoly->nVertices, poRawPoly->padfX, poRawPoly->padfY, - poRawPoly->padfZ, NULL); - - int iShape = SHPWriteObject(hSHP, -1, psShape); - - SHPDestroyObject(psShape); - - /* -------------------------------------------------------------------- - */ - /* Write out the attributes. */ - /* -------------------------------------------------------------------- - */ - DBFWriteIntegerAttribute(hDBF, iShape, nSDTSRecordField, - poRawPoly->oModId.nRecord); - WritePrimaryAttrToDBF(hDBF, iShape, poTransfer, poRawPoly); - - if (!poPolyReader->IsIndexed()) - delete poRawPoly; - } - - /* -------------------------------------------------------------------- */ - /* Close, and cleanup. */ - /* -------------------------------------------------------------------- */ - DBFClose(hDBF); - SHPClose(hSHP); -} - -/* **********************************************************************/ -/* AddPrimaryAttrToDBF() */ -/* */ -/* Add the fields from all the given primary attribute modules */ -/* to the schema of the passed DBF file. */ -/* **********************************************************************/ - -static void AddPrimaryAttrToDBFSchema(DBFHandle hDBF, SDTSTransfer *poTransfer, - char **papszModuleList) - -{ - for (int iModule = 0; - papszModuleList != NULL && papszModuleList[iModule] != NULL; iModule++) - { - /* -------------------------------------------------------------------- - */ - /* Get a reader on the desired module. */ - /* -------------------------------------------------------------------- - */ - SDTSAttrReader *poAttrReader = - (SDTSAttrReader *)poTransfer->GetLayerIndexedReader( - poTransfer->FindLayer(papszModuleList[iModule])); - - if (poAttrReader == NULL) - { - printf("Unable to open attribute module %s, skipping.\n", /*ok*/ - papszModuleList[iModule]); - continue; - } - - poAttrReader->Rewind(); - - /* -------------------------------------------------------------------- - */ - /* Read the first record so we can clone schema information off */ - /* of it. */ - /* -------------------------------------------------------------------- - */ - SDTSAttrRecord *poAttrFeature = - (SDTSAttrRecord *)poAttrReader->GetNextFeature(); - if (poAttrFeature == NULL) - { - fprintf(stderr, - "Didn't find any meaningful attribute records in %s.\n", - papszModuleList[iModule]); - - continue; - } - - /* -------------------------------------------------------------------- - */ - /* Clone schema off the first record. Eventually we need to */ - /* get the information out of the DDR record, but it isn't */ - /* clear to me how to accomplish that with the SDTS++ API. */ - /* */ - /* The following approach may fail (dramatically) if some */ - /* records do not include all subfields. Furthermore, no */ - /* effort is made to make DBF field names unique. The SDTS */ - /* attributes often have names much beyond the 14 character dbf */ - /* limit which may result in non-unique attributes. */ - /* -------------------------------------------------------------------- - */ - DDFFieldDefn *poFDefn = poAttrFeature->poATTR->GetFieldDefn(); - int iSF; - DDFField *poSR = poAttrFeature->poATTR; - - for (iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++) - { - DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield(iSF); - int nWidth = poSFDefn->GetWidth(); - - switch (poSFDefn->GetType()) - { - case DDFString: - if (nWidth == 0) - { - int nMaxBytes; - - const char *pachData = - poSR->GetSubfieldData(poSFDefn, &nMaxBytes); - - nWidth = strlen(poSFDefn->ExtractStringData( - pachData, nMaxBytes, NULL)); - } - - DBFAddField(hDBF, poSFDefn->GetName(), FTString, nWidth, 0); - break; - - case DDFInt: - if (nWidth == 0) - nWidth = 9; - - DBFAddField(hDBF, poSFDefn->GetName(), FTInteger, nWidth, - 0); - break; - - case DDFFloat: - DBFAddField(hDBF, poSFDefn->GetName(), FTDouble, 18, 6); - break; - - default: - fprintf(stderr, - "Dropping attribute `%s' of module `%s'. " - "Type unsupported\n", - poSFDefn->GetName(), papszModuleList[iModule]); - break; - } - } - - if (!poAttrReader->IsIndexed()) - delete poAttrFeature; - } /* next module */ -} - -/* **********************************************************************/ -/* WritePrimaryAttrToDBF() */ -/* **********************************************************************/ - -static void WritePrimaryAttrToDBF(DBFHandle hDBF, int iRecord, - SDTSTransfer *poTransfer, - SDTSFeature *poFeature) - -{ - /* ==================================================================== */ - /* Loop over all the attribute records linked to this feature. */ - /* ==================================================================== */ - for (int iAttrRecord = 0; iAttrRecord < poFeature->nAttributes; - iAttrRecord++) - { - DDFField *poSR = poTransfer->GetAttr(poFeature->paoATID + iAttrRecord); - - WriteAttrRecordToDBF(hDBF, iRecord, poTransfer, poSR); - } -} - -/* **********************************************************************/ -/* WriteAttrRecordToDBF() */ -/* **********************************************************************/ - -static void WriteAttrRecordToDBF(DBFHandle hDBF, int iRecord, - SDTSTransfer *poTransfer, DDFField *poSR) - -{ - /* -------------------------------------------------------------------- */ - /* Process each subfield in the record. */ - /* -------------------------------------------------------------------- */ - DDFFieldDefn *poFDefn = poSR->GetFieldDefn(); - - for (int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++) - { - DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield(iSF); - int iField; - int nMaxBytes; - const char *pachData = poSR->GetSubfieldData(poSFDefn, &nMaxBytes); - - /* -------------------------------------------------------------------- - */ - /* Identify the related DBF field, if any. */ - /* -------------------------------------------------------------------- - */ - for (iField = 0; iField < hDBF->nFields; iField++) - { - if (EQUALN(poSFDefn->GetName(), hDBF->pszHeader + iField * 32, 10)) - break; - } - - if (iField == hDBF->nFields) - iField = -1; - - /* -------------------------------------------------------------------- - */ - /* Handle each of the types. */ - /* -------------------------------------------------------------------- - */ - switch (poSFDefn->GetType()) - { - case DDFString: - { - const char *pszValue = - poSFDefn->ExtractStringData(pachData, nMaxBytes, NULL); - - if (iField != -1) - DBFWriteStringAttribute(hDBF, iRecord, iField, pszValue); - } - break; - - case DDFFloat: - { - double dfValue; - - dfValue = poSFDefn->ExtractFloatData(pachData, nMaxBytes, NULL); - - if (iField != -1) - DBFWriteDoubleAttribute(hDBF, iRecord, iField, dfValue); - } - break; - - case DDFInt: - { - int nValue; - - nValue = poSFDefn->ExtractIntData(pachData, nMaxBytes, NULL); - - if (iField != -1) - DBFWriteIntegerAttribute(hDBF, iRecord, iField, nValue); - } - break; - default: - break; - } - } /* next subfield */ -} diff --git a/frmts/sdts/sdts_al.h b/frmts/sdts/sdts_al.h deleted file mode 100644 index 5abad8fd3a82..000000000000 --- a/frmts/sdts/sdts_al.h +++ /dev/null @@ -1,706 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Include file for entire SDTS Abstraction Layer functions. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef SDTS_AL_H_INCLUDED -#define SDTS_AL_H_INCLUDED - -#include "cpl_conv.h" -#include "iso8211.h" - -class SDTS_IREF; -class SDTSModId; -class SDTSTransfer; - -#define SDTS_SIZEOF_SADR 8 - -char **SDTSScanModuleReferences(DDFModule *, const char *); - -/************************************************************************/ -/* SDTS_IREF */ -/************************************************************************/ - -/** - Class holding SDTS IREF (internal reference) information, internal - coordinate system format, scaling and resolution. This object isn't - normally needed by applications. -*/ -class SDTS_IREF -{ - int nDefaultSADRFormat; - - public: - SDTS_IREF(); - ~SDTS_IREF(); - - int Read(const char *pszFilename); - - char *pszXAxisName; /* XLBL */ - char *pszYAxisName; /* YLBL */ - - double dfXScale; /* SFAX */ - double dfYScale; /* SFAY */ - - double dfXOffset; /* XORG */ - double dfYOffset; /* YORG */ - - double dfXRes; /* XHRS */ - double dfYRes; /* YHRS */ - - char *pszCoordinateFormat; /* HFMT */ - - int GetSADRCount(DDFField *) const; - int GetSADR(DDFField *, int, double *, double *, double *); -}; - -/************************************************************************/ -/* SDTS_XREF */ -/************************************************************************/ - -/** - Class for reading the XREF (external reference) module containing the - data projection definition. -*/ - -class SDTS_XREF -{ - public: - SDTS_XREF(); - ~SDTS_XREF(); - - int Read(const char *pszFilename); - - /** Projection system name, from the RSNM field. One of GEO, SPCS, UTM, - UPS, OTHR, UNSP. */ - char *pszSystemName; - - /** Horizontal datum name, from the HDAT field. One of NAS, NAX, WGA, - WGB, WGC, WGE. */ - char *pszDatum; - - /** Zone number for UTM and SPCS projections, from the ZONE field. */ - int nZone; -}; - -/************************************************************************/ -/* SDTS_CATD */ -/************************************************************************/ -class SDTS_CATDEntry; - -/** - List of feature layer types. See SDTSTransfer::GetLayerType(). - */ - -typedef enum -{ - SLTUnknown, - SLTPoint, - SLTLine, - SLTAttr, - SLTPoly, - SLTRaster -} SDTSLayerType; - -/** - Class for accessing the CATD (Catalog Directory) file containing a list of - all other files (modules) in the transfer. -*/ -class SDTS_CATD -{ - char *pszPrefixPath; - - int nEntries; - SDTS_CATDEntry **papoEntries; - - public: - SDTS_CATD(); - ~SDTS_CATD(); - - int Read(const char *pszFilename); - - const char *GetModuleFilePath(const char *pszModule) const; - - int GetEntryCount() const - { - return nEntries; - } - - const char *GetEntryModule(int) const; - const char *GetEntryTypeDesc(int) const; - const char *GetEntryFilePath(int) const; - SDTSLayerType GetEntryType(int) const; - void SetEntryTypeUnknown(int); -}; - -/************************************************************************/ -/* SDTSModId */ -/************************************************************************/ - -/** - Object representing a unique module/record identifier within an SDTS - transfer. -*/ -class SDTSModId -{ - public: - SDTSModId() - { - szModule[0] = '\0'; - nRecord = -1; - szOBRP[0] = '\0'; - szName[0] = '\0'; - } - - int Set(DDFField *); - - const char *GetName(); - - /** The module name, such as PC01, containing the indicated record. */ - char szModule[8]; - - /** The record within the module referred to. This is -1 for unused - SDTSModIds. */ - int nRecord; - - /** The "role" of this record within the module. This is normally empty - for references, but set in the oModId member of a feature. */ - char szOBRP[8]; - - /** String "szModule:nRecord" */ - char szName[20]; -}; - -/************************************************************************/ -/* SDTSFeature */ -/************************************************************************/ - -/** - Base class for various SDTS features classes, providing a generic - module identifier, and list of attribute references. -*/ -class SDTSFeature -{ - public: - SDTSFeature(); - virtual ~SDTSFeature(); - - /** Unique identifier for this record/feature within transfer. */ - SDTSModId oModId; - - /** Number of attribute links (aoATID[]) on this feature. */ - int nAttributes; - - /** List of nAttributes attribute record identifiers related to this - feature. */ - SDTSModId *paoATID; - - void ApplyATID(DDFField *); - - /** Dump readable description of feature to indicated stream. */ - virtual void Dump(FILE *) = 0; -}; - -/************************************************************************/ -/* SDTSIndexedReader */ -/************************************************************************/ - -/** - Base class for all the SDTSFeature type readers. Provides feature - caching semantics and fetching based on a record number. - */ - -class SDTSIndexedReader -{ - int nIndexSize; - SDTSFeature **papoFeatures; - - int iCurrentFeature; - - protected: - DDFModule oDDFModule; - - public: - SDTSIndexedReader(); - virtual ~SDTSIndexedReader(); - - virtual SDTSFeature *GetNextRawFeature() = 0; - - SDTSFeature *GetNextFeature(); - - virtual void Rewind(); - - void FillIndex(); - void ClearIndex(); - int IsIndexed() const; - - SDTSFeature *GetIndexedFeatureRef(int); - char **ScanModuleReferences(const char * = "ATID"); - - DDFModule *GetModule() - { - return &oDDFModule; - } -}; - -/************************************************************************/ -/* SDTSRawLine */ -/************************************************************************/ - -/** SDTS line feature, as read from LE* modules by SDTSLineReader. */ - -class SDTSRawLine : public SDTSFeature -{ - public: - SDTSRawLine(); - virtual ~SDTSRawLine(); - - int Read(SDTS_IREF *, DDFRecord *); - - /** Number of vertices in the padfX, padfY and padfZ arrays. */ - int nVertices; - - /** List of nVertices X coordinates. */ - double *padfX; - /** List of nVertices Y coordinates. */ - double *padfY; - /** List of nVertices Z coordinates - currently always zero. */ - double *padfZ; - - /** Identifier of polygon to left of this line. This is the SDTS PIDL - subfield. */ - SDTSModId oLeftPoly; - - /** Identifier of polygon to right of this line. This is the SDTS PIDR - subfield. */ - SDTSModId oRightPoly; - - /** Identifier for the start node of this line. This is the SDTS SNID - subfield. */ - SDTSModId oStartNode; /* SNID */ - - /** Identifier for the end node of this line. This is the SDTS ENID - subfield. */ - SDTSModId oEndNode; /* ENID */ - - void Dump(FILE *) override; -}; - -/************************************************************************/ -/* SDTSLineReader */ -/* */ -/* Class for reading any of the files lines. */ -/************************************************************************/ - -/** - Reader for SDTS line modules. - - Returns SDTSRawLine features. Normally readers are instantiated with - the SDTSTransfer::GetIndexedReader() method. - - */ - -class SDTSLineReader : public SDTSIndexedReader -{ - SDTS_IREF *poIREF; - - public: - explicit SDTSLineReader(SDTS_IREF *); - ~SDTSLineReader(); - - int Open(const char *); - SDTSRawLine *GetNextLine(); - void Close(); - - SDTSFeature *GetNextRawFeature() override - { - return GetNextLine(); - } - - void AttachToPolygons(SDTSTransfer *, int iPolyLayer); -}; - -/************************************************************************/ -/* SDTSAttrRecord */ -/************************************************************************/ - -/** - SDTS attribute record feature, as read from A* modules by - SDTSAttrReader. - - Note that even though SDTSAttrRecord is derived from SDTSFeature, there - are never any attribute records associated with attribute records using - the aoATID[] mechanism. SDTSFeature::nAttributes will always be zero. - */ - -class SDTSAttrRecord : public SDTSFeature -{ - public: - SDTSAttrRecord(); - virtual ~SDTSAttrRecord(); - - /** The entire DDFRecord read from the file. */ - DDFRecord *poWholeRecord; - - /** The ATTR DDFField with the user attribute. Each subfield is a - attribute value. */ - - DDFField *poATTR; - - virtual void Dump(FILE *) override; -}; - -/************************************************************************/ -/* SDTSAttrReader */ -/************************************************************************/ - -/** - Class for reading SDTSAttrRecord features from a primary or secondary - attribute module. - */ - -class SDTSAttrReader : public SDTSIndexedReader -{ - int bIsSecondary; - - public: - SDTSAttrReader(); - virtual ~SDTSAttrReader(); - - int Open(const char *); - DDFField *GetNextRecord(SDTSModId * = nullptr, DDFRecord ** = nullptr, - int bDuplicate = FALSE); - SDTSAttrRecord *GetNextAttrRecord(); - void Close(); - - /** - Returns TRUE if this is a Attribute Secondary layer rather than - an Attribute Primary layer. - */ - int IsSecondary() const - { - return bIsSecondary; - } - - SDTSFeature *GetNextRawFeature() override - { - return GetNextAttrRecord(); - } -}; - -/************************************************************************/ -/* SDTSRawPoint */ -/************************************************************************/ - -/** - Object containing a point feature (type NA, NO or NP). - */ -class SDTSRawPoint : public SDTSFeature -{ - public: - SDTSRawPoint(); - virtual ~SDTSRawPoint(); - - int Read(SDTS_IREF *, DDFRecord *); - - /** X coordinate of point. */ - double dfX; - /** Y coordinate of point. */ - double dfY; - /** Z coordinate of point. */ - double dfZ; - - /** Optional identifier of area marked by this point (i.e. PC01:27). */ - SDTSModId oAreaId; /* ARID */ - - virtual void Dump(FILE *) override; -}; - -/************************************************************************/ -/* SDTSPointReader */ -/************************************************************************/ - -/** - Class for reading SDTSRawPoint features from a point module (type NA, NO - or NP). - */ - -class SDTSPointReader : public SDTSIndexedReader -{ - SDTS_IREF *poIREF; - - public: - explicit SDTSPointReader(SDTS_IREF *); - virtual ~SDTSPointReader(); - - int Open(const char *); - SDTSRawPoint *GetNextPoint(); - void Close(); - - SDTSFeature *GetNextRawFeature() override - { - return GetNextPoint(); - } -}; - -/************************************************************************/ -/* SDTSRawPolygon */ -/************************************************************************/ - -/** - Class for holding information about a polygon feature. - - When directly read from a polygon module, the polygon has no concept - of its geometry. Just its ID, and references to attribute records. - However, if the SDTSLineReader::AttachToPolygons() method is called on - the module containing the lines forming the polygon boundaries, then the - nEdges/papoEdges information on the SDTSRawPolygon will be filled in. - - Once this is complete the AssembleRings() method can be used to fill in the - nRings/nVertices/panRingStart/padfX/padfY/padfZ information defining the - ring geometry. - - Note that the rings may not appear in any particular order, nor with any - meaningful direction (clockwise or counterclockwise). - */ - -class SDTSRawPolygon : public SDTSFeature -{ - void AddEdgeToRing(int, double *, double *, double *, int, int); - - public: - SDTSRawPolygon(); - virtual ~SDTSRawPolygon(); - - int Read(DDFRecord *); - - int nEdges; - SDTSRawLine **papoEdges; - - void AddEdge(SDTSRawLine *); - - /** This method will assemble the edges associated with a polygon into - rings, returning FALSE if problems are encountered during assembly. */ - int AssembleRings(); - - /** Number of rings in assembled polygon. */ - int nRings; - /** Total number of vertices in all rings of assembled polygon. */ - int nVertices; - /** Offsets into padfX/padfY/padfZ for the beginning of each ring in the - polygon. This array is nRings long. */ - int *panRingStart; - - /** List of nVertices X coordinates for the polygon (split over multiple - rings via panRingStart. */ - double *padfX; - /** List of nVertices Y coordinates for the polygon (split over multiple - rings via panRingStart. */ - double *padfY; - /** List of nVertices Z coordinates for the polygon (split over multiple - rings via panRingStart. The values are almost always zero. */ - double *padfZ; - - virtual void Dump(FILE *) override; -}; - -/************************************************************************/ -/* SDTSPolygonReader */ -/************************************************************************/ - -/** Class for reading SDTSRawPolygon features from a polygon (PC*) module. */ - -class SDTSPolygonReader : public SDTSIndexedReader -{ - int bRingsAssembled; - - public: - SDTSPolygonReader(); - virtual ~SDTSPolygonReader(); - - int Open(const char *); - SDTSRawPolygon *GetNextPolygon(); - void Close(); - - SDTSFeature *GetNextRawFeature() override - { - return GetNextPolygon(); - } - - void AssembleRings(SDTSTransfer *, int iPolyLayer); -}; - -/************************************************************************/ -/* SDTSRasterReader */ -/************************************************************************/ - -/** - Class for reading raster data from a raster layer. - - This class is somewhat unique among the reader classes in that it isn't - derived from SDTSIndexedFeature, and it doesn't return "features". Instead - it is used to read raster blocks, in the natural block size of the dataset. - */ - -class SDTSRasterReader -{ - DDFModule oDDFModule; - - char szModule[20]; - - int nXSize; - int nYSize; - int nXBlockSize; - int nYBlockSize; - - int nXStart; /* SOCI */ - int nYStart; /* SORI */ - - double adfTransform[6]; - - public: - char szINTR[4]; /* CE is center, TL is top left */ - char szFMT[32]; - char szUNITS[64]; - char szLabel[64]; - - SDTSRasterReader(); - ~SDTSRasterReader(); - - int Open(SDTS_CATD *poCATD, SDTS_IREF *, const char *pszModule); - void Close(); - - int GetRasterType(); /* 1 = int16, see GDAL types */ -#define SDTS_RT_INT16 1 -#define SDTS_RT_FLOAT32 6 - - int GetTransform(double *); - - int GetMinMax(double *pdfMin, double *pdfMax, double dfNoData); - - /** - Fetch the raster width. - - @return the width in pixels. - */ - int GetXSize() const - { - return nXSize; - } - - /** - Fetch the raster height. - - @return the height in pixels. - */ - int GetYSize() const - { - return nYSize; - } - - /** Fetch the width of a source block (usually same as raster width). */ - int GetBlockXSize() const - { - return nXBlockSize; - } - - /** Fetch the height of a source block (usually one). */ - int GetBlockYSize() const - { - return nYBlockSize; - } - - int GetBlock(int nXOffset, int nYOffset, void *pData); -}; - -/************************************************************************/ -/* SDTSTransfer */ -/************************************************************************/ - -/** - Master class representing an entire SDTS transfer. - - This class is used to open the transfer, to get a list of available - feature layers, and to instantiate readers for those layers. - - */ - -class SDTSTransfer -{ - public: - SDTSTransfer(); - ~SDTSTransfer(); - - int Open(const char *); - void Close(); - - int FindLayer(const char *); - - int GetLayerCount() const - { - return nLayers; - } - - SDTSLayerType GetLayerType(int) const; - int GetLayerCATDEntry(int) const; - - SDTSLineReader *GetLayerLineReader(int); - SDTSPointReader *GetLayerPointReader(int); - SDTSPolygonReader *GetLayerPolygonReader(int); - SDTSAttrReader *GetLayerAttrReader(int); - SDTSRasterReader *GetLayerRasterReader(int); - DDFModule *GetLayerModuleReader(int); - - SDTSIndexedReader *GetLayerIndexedReader(int); - - /** - Fetch the catalog object for this transfer. - - @return pointer to the internally managed SDTS_CATD for the transfer. - */ - SDTS_CATD *GetCATD() - { - return &oCATD; - } - - SDTS_IREF *GetIREF() - { - return &oIREF; - } - - /** - Fetch the external reference object for this transfer. - - @return pointer to the internally managed SDTS_XREF for the transfer. - */ - SDTS_XREF *GetXREF() - { - return &oXREF; - } - - SDTSFeature *GetIndexedFeatureRef(SDTSModId *, - SDTSLayerType *peType = nullptr); - - DDFField *GetAttr(SDTSModId *); - - int GetBounds(double *pdfMinX, double *pdfMinY, double *pdfMaxX, - double *pdfMaxY); - - private: - SDTS_CATD oCATD; - SDTS_IREF oIREF; - SDTS_XREF oXREF; - - int nLayers; - int *panLayerCATDEntry; - SDTSIndexedReader **papoLayerReader; -}; - -#endif /* ifndef SDTS_AL_H_INCLUDED */ diff --git a/frmts/sdts/sdts_main.dox b/frmts/sdts/sdts_main.dox deleted file mode 100644 index 608d1efab7cc..000000000000 --- a/frmts/sdts/sdts_main.dox +++ /dev/null @@ -1,226 +0,0 @@ -/*! \page sdts_al_main - -
-SDTS Abstraction Library -
- -

Introduction

- -SDTS_AL, the SDTS Abstraction Library, is intended to be an relatively -easy to use library for reading vector from SDTS TVP (Topological Vector -Profile) files, primary DLG data from the USGS. It also include support -for reading raster data such as USGS DEMs in SDTS format. It consists -of open source, easy to compile and integrate C++ code.

- - - -

SDTS Background

- -The USGS SDTS Page at -http://mcmcweb.er.usgs.gov/sdts -is the definitive source of information on the SDTS format. The SDTS -format is based on the -ISO 8211 -encoding scheme for the underlying files, and the SDTS Abstraction Library -uses -ISO8211Lib -library to decode them. All references to DDF* classes are from ISO8211Lib.

- -An SDTS Transfer is a grouping of ISO8211 encoded files (ending in the -.DDF extension), normally with part of the basename in common. For instance -a USGS DLG SDTS transfer might consists of many files matching the -SC01????.DDF pattern. The key file in an SDTS transfer is the catalog -file, such as SC01CATD.DDF.

- - - -

Development Information

- -The sdts_al.h -include file contains the definitions for all public -SDTS classes, enumerations and other services.

- -The SDTSTransfer class is used to access a transfer as a whole. The -SDTSTransfer::Open() method is passed the name of the catalog file, -such as SC01CATD.DDF, to open.

- -The SDTSTransfer analyses the catalog, and some other aspects of the -transfer, and builds a list of feature layers. This list can be -accessed using the SDTSTransfer::GetLayerCount(), SDTSTransfer::GetLayerType(), -and SDTSTransfer::GetLayerIndexedReader() methods. A typical TVP (Topological -Vector Profile) transfer might include three point layers (of type -SLTPoint), a line layer (of type SLTLine), a polygon layer (of type SLTPoly) -as well as some additional attribute layers (of type SLTAttr). the -SDTSTransfer::GetLayerIndexedReader() method can be used to instantiate a -reader object for reading a particular layer. (NOTE: raster layers are -handled differently).

- -Each type of SDTSIndexedReader (SDTSPointReader, SDTSLineReader, -SDTSPolygonReader, and SDTSAttrReader) returns specific subclasses of -SDTSIndexedFeature from the SDTSIndexedReader::GetNextFeature() method. -These classes are SDTSRawPoint, SDTSRawLine, SDTSRawPolygon and -SDTSAttrRecord. These classes can be investigated for details on the -data available for each.

- -See the SDTS_AL Tutorial for more information -on how to use this library.

- - - -

Building the Source on Unix

- -
    - -
  1. First, fetch the source. The most recent source should be accessible -at an url such as - -ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.tar.gz.

    - - -

  2. Unpack the source.

    -

    -% gzip -d sdts_1_3.tar.gz
    -% tar xzvf sdts_1_3.tar.gz
    -
    - -
  3. Type ``configure'' to establish configuration -options.

    - -

  4. Type make to build sdts_al.a, and the sample -mainline sdts2shp.

    - -

- -See the SDTS_AL Tutorial for more information -on how to use this library.

- - - -

Building the Source on Windows

- -
    - -
  1. First, fetch the source. The most recent source should be accessible -at an url such as - -ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.zip.

    - - -

  2. Unpack the source.

    - -

    -C:\SDTS> unzip sdts_1_3.zip
    -
    - -
  3. Build using makefile.vc with VC++. You will need the VC++ runtime -environment variables (LIB/INCLUDE) set properly. This will build the -library (sdts_al.lib), and the executables sdts2shp.exe, 8211view.exe and -8211dump.exe.

    - -

    -C:\SDTS> nmake /f makefile.vc
    -
    - -
- -See the SDTS_AL Tutorial for more information -on how to use this library.

- - - -

The sdts2shp Sample Program

- -The sdts2shp program distributed with this toolkit is primary intended to -serve as an example of how to use the SDTS access library. However, it can -be useful to translate SDTS datasets into ESRI Shapefile format. - -
-Usage: sdts2shp CATD_filename [-o shapefile_name]
-                [-m module_name] [-v]
-
-Modules include `LE01', `PC01', `NP01' and `ARDF'
-
- -A typical session in which we inspect the contents of a transfer, and then -extract polygon and line layers might look like this:

- -

-warmerda[134]% sdts2shp data/SC01CATD.DDF -v
-Layers:
-  ASCF: `Attribute Primary         '
-  AHDR: `Attribute Primary         '
-  NP01: `Point-Node                '
-  NA01: `Point-Node                '
-  NO01: `Point-Node                '
-  LE01: `Line                      '
-  PC01: `Polygon                   '
-
-warmerda[135]% sdts2shp data/SC01CATD.DDF -m PC01 -o pc01.shp
-warmerda[136]% sdts2shp data/SC01CATD.DDF -m LE01 -o le01.shp
-
- -A prebuilt executable is available for -Windows.

- - - -

Licensing

- -This library is offered as Open Source. -In particular, it is offered under the X Consortium license which doesn't -attempt to impose any copyleft, or credit requirements on users of the code.

- -The precise license text is:

- - - Copyright (c) 1999, Frank Warmerdam -

- Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: -

- The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. -

- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -

- - - - -

Author and Acknowledgements

- -The primary author of SDTS_AL is -Frank Warmerdam, and I can be reached at -warmerdam@pobox.com. I am eager to -receive bug reports, and also open to praise or suggestions.

- -I would like to thank:

- -

    -
  • Safe Software -who funded development of this library, and agreed for it to be Open Source.

    - -

  • Mark Colletti, a primary author of -SDTS++ from -which I derived most of what I know about SDTS and ISO8211 and who was very -supportive, answering a variety of questions.

    - -

- -I would also like to dedicate this library to the memory of Sol Katz. -Sol released a variety of SDTS translators, at substantial -personal effort, to the GIS community along with the many other generous -contributions he made to the community. His example has been an inspiration -to me, and I hope similar efforts on my part will contribute to his memory.

- -*/ diff --git a/frmts/sdts/sdts_tut.dox b/frmts/sdts/sdts_tut.dox deleted file mode 100644 index afed1abcc752..000000000000 --- a/frmts/sdts/sdts_tut.dox +++ /dev/null @@ -1,469 +0,0 @@ -/*! \page SDTS_AL_TUT - -

-SDTS Abstraction Library Tutorial -
- -This page is a walk through of the polygon layer portion of the -sdts2shp.cpp example application. It is should -give sufficient information to utilize the SDTS_AL library to read SDTS -files.

- -

Opening the Transfer

- -The following statements will open an SDTS transfer. The filename -passed to SDTSTransfer::Open() should be the name of the catalog file, -such as palo_alto/SC01CATD.DDF. The Open() method returns FALSE -if it fails for any reason. In addition to the message we print out ourselves, -the SDTSTransfer::Open() method will also emit its own error message using -CPLError(). See the cpl_error.h page for more information on how to -capture and control CPLError() style error reporting.

- -

-#include "stds_al.h"
-
-...
-
-    SDTSTransfer oTransfer;
-
-    if( !oTransfer.Open( pszCATDFilename ) )
-    {
-        fprintf( stderr,
-                 "Failed to read CATD file `%s'\n",
-                 pszCATDFilename );
-        exit( 100 );
-    }
-
- -

Getting a Layer List

- -Once an SDTSTransfer has been opened, it is possible to establish what -layers are available. The sdts2shp example problem includes a -v argument -to dump a list of available layers. It isn't normally necessary to use the -SDTS_CATD (catalog) from an application to access SDTS files; however, in -this example we use it to fetch a module name, and description for each -of the available layers.

- -In particular, the SDTSTransfer::GetLayerCount() method returns the -number of feature layers in the transfer and the -SDTSTransfer::GetLayerCATDEntry() is used to translate layer indexes into -SDTS_CATD compatible CATD indexes.

- -

-        printf( "Layers:\n" );
-        for( i = 0; i < oTransfer.GetLayerCount(); i++ )
-        {
-            int		iCATDEntry = oTransfer.GetLayerCATDEntry(i);
-
-            printf( "  %s: `%s'\n",
-                    oTransfer.GetCATD()->GetEntryModule(iCATDEntry),
-                    oTransfer.GetCATD()->GetEntryTypeDesc(iCATDEntry) );
-        }
-        printf( "\n" );
-
- -The following would be a typical layer list. Note that there are many -other modules (files) registered with the catalog, but only these ones -are considered to be feature layers by the SDTSTransfer object. The -rest are supporting information, much of it, like data quality, is ignored -by the SDTS_AL library.

- -

-warmerda@cs46980-c[113]% sdts2shp data/SC01CATD.DDF -v
-Layers:
-  ASCF: `Attribute Primary         '
-  AHDR: `Attribute Primary         '
-  NP01: `Point-Node                '
-  NA01: `Point-Node                '
-  NO01: `Point-Node                '
-  LE01: `Line                      '
-  PC01: `Polygon                   '
-
- -

Getting a Reader

- -In order to read polygon features, it is necessary to instantiate a polygon -reader on the desired layer. The sdts2shp.cpp program allow the user to -select a module name (such as PC01, stored in pszMODN) to write to shape -format. Other application might just search for, and operate on all known -layers of a desired type.

- -The SDTSTransfer::GetLayerIndexedReader() method instantiates a reader of -the desired type. In this case we know we are instantiating a -SDTSPolygonReader so we can safely cast the returned SDTSIndexedReader -pointer to the more specific type SDTSPolygonReader.

- -

-    SDTSPolygonReader *poPolyReader;
-
-    poPolyReader = (SDTSPolygonReader *)
-        poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
-
-    if( poPolyReader == NULL )
-    {
-        fprintf( stderr, "Failed to open %s.\n",
-                 poTransfer->GetCATD()->GetModuleFilePath( pszMODN ) );
-        return;
-    }
-
- -Note that readers returned by SDTSTransfer::GetLayerIndexedReader() are -managed by the SDTSTransfer, and should not be deleted by the application.

- -

Collecting Polygon Geometry

- -The SDTS TVP format does not directly associate a polygons geometry (the -points forming its boundary) with the polygon feature. Instead it is -stored in separate line layers, and the lines contain references to the -right, and left polygons that the lines border.

- -The SDTS_AL library provides a convenient method for forming the polygon -geometry. Basically just call the SDTSPolygonReader::AssemblePolygons() -method. This method will scan all SLTLine layers in the transfer, indexing -them and attaching their line work to the polygons. Then it assembles the -line work into rings. It also ensures that the outer ring comes first, that -the outer ring is counter-clockwise and that the inner ring(s) are -clockwise. - -

-    poPolyReader->AssembleRings( poTransfer );
-
- -Upon completion the SDTSPolygonReader will have been "indexed". That means -that all the polygon information will have been read from disk, and the -polygon objects will now have information stored with them indicating the -list of edges that form their border.

- -

Identifying Attributes

- -In order to create the schema for the output shapefile dataset, it is -necessary to identify the attributes associated with the polygons. There -are two types of attributes which can occur. The first are hardcoded -attributes specific to the feature type, and the second are generic -user attributes stored in a separate primary attribute layer.

- -In the case of SDTSRawPolygon, there is only one attribute of interest, -and that is the record number of the polygon. This is actually stored within -the oModId data member of the SDTSIndexedFeature base class, as will be seen -in later examples when we write it to disk. For now we create a DBF -field for the record number. This record number is a unique identifier of -the polygon within this module/layer.

- -

-    nSDTSRecordField = DBFAddField( hDBF, "SDTSRecId", FTInteger, 8, 0 );
-
- -Identification of user attributes is more complicated. Any feature in a -layer can have associates with 0, 1, 2 or potentially more attribute records -in other primary attribute layers. In order to establish a schema for the -layer it is necessary to build up a list of all attribute layers (tables) -to which references appear. The SDTSIndexedReader::ScanModuleReferences() -method can be used to scan a whole module for references to attribute modules -via the ATID field. The return result is a list of referenced modules in the -form of a string list. In a typical case this is one or two modules, such -as "ASCF".

- -

-    char  **papszModRefs = poPolyReader->ScanModuleReferences();
-
- -In sdts2shp.cpp, a subroutine (AddPrimaryAttrToDBFSchema()) is defined -to add all the fields of all references attribute layers to the DBF file. -For each module in the list the following steps are executed.

- -

Fetch an Attribute Module Reader

- -The following code is similar to our code for create a polygon layer -reader. It creates a reader on one of the attribute layers referenced. -We explicitly rewind it since it may have been previously opened and -read by another part of the application.

- -

-        SDTSAttrReader	*poAttrReader;
-
-        poAttrReader = (SDTSAttrReader *)
-            poTransfer->GetLayerIndexedReader(
-                poTransfer->FindLayer( papszModuleList[iModule] ) );
-
-        if( poAttrReader == NULL )
-        {
-            printf( "Unable to open attribute module %s, skipping.\n" ,
-                    papszModuleList[iModule] );
-            continue;
-        }
-
-        poAttrReader->Rewind();
-
- -

Get a Prototype Record

- -In order to get access to field definitions, and in order to establish -some sort of reasonable default lengths for field without fixed lengths -the sdts2shp program fetches a prototype record from the attribute module. - -
-        SDTSAttrRecord 	*poAttrFeature;
-
-        poAttrFeature = (SDTSAttrRecord *) poAttrReader->GetNextFeature();
-        if( poAttrFeature == NULL )
-        {
-            fprintf( stderr,
-                     "Didn't find any meaningful attribute records in %s.\n",
-                     papszModuleList[iModule] );
-
-            continue;
-        }
-
- -When no longer needed, the attribute record may need to be explicitly -deleted if it is not part of an indexed cached.

- -

-        if( !poAttrReader->IsIndexed() )
-            delete poAttrFeature;
-
- -

Extract Field Definitions

- - -The Shapefile DBF fields are defined based on the information available for -each of the subfields of the attribute records ATTR DDFField (the poATTR -data member). The following code loops over each of the subfields, -getting a pointer to the DDBSubfieldDefn containing information about that -subfield.

- -

-        DDFFieldDefn 	*poFDefn = poAttrFeature->poATTR->GetFieldDefn();
-        int		iSF;
-        DDFField	*poSR = poAttrFeature->poATTR;
-
-        for( iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
-        {
-            DDFSubfieldDefn	*poSFDefn = poFDefn->GetSubfield( iSF );
-
- -Then each of the significant ISO8211 field types is translated to an -appropriate DBF field type. In cases where the nWidth field is zero, -indicating that the field is variable width, we use the length of the -field in the prototype record. Ideally we would scan the whole file to find -the longest value for each field, but that would be a significant amount of -work.

- -

-            int		nWidth = poSFDefn->GetWidth();
-
-            switch( poSFDefn->GetType() )
-            {
-              case DDFString:
-                if( nWidth == 0 )
-                {
-                    int		nMaxBytes;
-
-                    const char * pachData = poSR->GetSubfieldData(poSFDefn,
-                                                                  &nMaxBytes);
-
-                    nWidth = strlen(poSFDefn->ExtractStringData(pachData,
-                                                                nMaxBytes, NULL ));
-                }
-
-                DBFAddField( hDBF, poSFDefn->GetName(), FTString, nWidth, 0 );
-                break;
-
-              case DDFInt:
-                if( nWidth == 0 )
-                    nWidth = 9;
-
-                DBFAddField( hDBF, poSFDefn->GetName(), FTInteger, nWidth, 0 );
-                break;
-
-              case DDFFloat:
-                DBFAddField( hDBF, poSFDefn->GetName(), FTDouble, 18, 6 );
-                break;
-
-              default:
-                fprintf( stderr,
-                         "Dropping attribute `%s' of module `%s'.  "
-                         "Type unsupported\n",
-                         poSFDefn->GetName(),
-                         papszModuleList[iModule] );
-                break;
-            }
-        }
-
- -

Reading Polygon Features

- -With definition of the attribute schema out of the way, we return to the -main event, reading polygons from the polygon layer. We have already -instantiated the SDTSPolygonReader (poPolyReader), and now we loop reading -features from it. Note that we Rewind() the reader to ensure we are -starting at the beginning. After we are done process the polygon we -delete it, if and only if the layer does not have an index cache.

- -

-    SDTSRawPolygon	*poRawPoly;
-
-    poPolyReader->Rewind();
-    while( (poRawPoly = (SDTSRawPolygon *) poPolyReader->GetNextFeature())
-           != NULL )
-    {
-        ... process and write polygon ...
-
-        if( !poPolyReader->IsIndexed() )
-            delete poRawPoly;
-    }
-
- -

Translate Geometry

- -In an earlier step we used the SDTSPolygonReader::AssembleRings() method to -build ring geometry on the polygons from the linework in the line layers.

- -Coincidently (well, ok, maybe it isn't a coincidence) it so happens that the -ring organization exactly matches what is needed for the shapefile api. -The following call creates a polygon from the ring information in the -SDTSRawPolygon. See the SDTSRawPolygon reference help for a fuller -definition of the nRings, panRingStart, nVertices, and vertex fields.

- -

-        psShape = SHPCreateObject( SHPT_POLYGON, -1, poRawPoly->nRings,
-                                   poRawPoly->panRingStart, NULL,
-                                   poRawPoly->nVertices,
-                                   poRawPoly->padfX,
-                                   poRawPoly->padfY,
-                                   poRawPoly->padfZ,
-                                   NULL );
-
- -

Write Record Number

- -The following call is used to write out the record number of the polygon, -fetched from the SDTSIndexedFeature::oModId data member. The szModule value -in this data field will always match the module name for the whole layer. -While not shown here, there is also an szOBRP field on oModId which have -different values depending on whether the polygon is a universe or regular -polygon.

- -

-        DBFWriteIntegerAttribute( hDBF, iShape, nSDTSRecordField,
-                                  poRawPoly->oModId.nRecord );
-
- -

Fetch Associated User Records

- -In keeping with the setting up of the schema, accessing the user records -is somewhat complicated. In sdts2shp, the primary attribute records associated -with any feature (including SDTSRawPolygons) can be fetched with the -WriteAttrRecordToDBF() function defined as follows.

- -In particular, the poFeature->nAttributes member indicates how many -associated attribute records there are. The poFeature->aoATID[] array -contains the SDTSModId's for each record. This SDTSModId can be passed -to SDTSTransfer::GetAttr() to fetch the DDFField pointer for the user -attributes. The WriteAttrRecordToDBF() method is specific to sdts2shp -and will be define later.

- -

-    int		iAttrRecord;
-
-    for( iAttrRecord = 0; iAttrRecord < poFeature->nAttributes; iAttrRecord++)
-    {
-        DDFField	*poSR;
-
-        poSR = poTransfer->GetAttr( poFeature->aoATID+iAttrRecord );
-
-        WriteAttrRecordToDBF( hDBF, iRecord, poTransfer, poSR );
-    }
-
- -

Write User Attributes

- -In a manner analogous to the definition of the fields from the prototype -attribute record, the following code loops over the subfields, and fetches -the data for each. The data extraction via poSR->GetSubfieldData() is -a bit involved, and more information can be found on the DDFField reference -page.

- -

-/* -------------------------------------------------------------------- */
-/*      Process each subfield in the record.                            */
-/* -------------------------------------------------------------------- */
-    DDFFieldDefn 	*poFDefn = poSR->GetFieldDefn();
-
-    for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
-    {
-        DDFSubfieldDefn	*poSFDefn = poFDefn->GetSubfield( iSF );
-        int			iField;
-        int			nMaxBytes;
-        const char * 	pachData = poSR->GetSubfieldData(poSFDefn,
-                                                         &nMaxBytes);
-
-/* -------------------------------------------------------------------- */
-/*      Identify the related DBF field, if any.                         */
-/* -------------------------------------------------------------------- */
-        for( iField = 0; iField < hDBF->nFields; iField++ )
-        {
-            if( EQUALN(poSFDefn->GetName(),
-                       hDBF->pszHeader+iField*32,10) )
-                break;
-        }
-
-        if( iField == hDBF->nFields )
-            iField = -1;
-
-/* -------------------------------------------------------------------- */
-/*      Handle each of the types.                                       */
-/* -------------------------------------------------------------------- */
-        switch( poSFDefn->GetType() )
-        {
-          case DDFString:
-            const char	*pszValue;
-
-            pszValue = poSFDefn->ExtractStringData(pachData, nMaxBytes,
-                                                   NULL);
-
-            if( iField != -1 )
-                DBFWriteStringAttribute(hDBF, iRecord, iField, pszValue );
-            break;
-
-          case DDFFloat:
-            double	dfValue;
-
-            dfValue = poSFDefn->ExtractFloatData(pachData, nMaxBytes,
-                                                 NULL);
-
-            if( iField != -1 )
-                DBFWriteDoubleAttribute( hDBF, iRecord, iField, dfValue );
-            break;
-
-          case DDFInt:
-            int		nValue;
-
-            nValue = poSFDefn->ExtractIntData(pachData, nMaxBytes, NULL);
-
-            if( iField != -1 )
-                DBFWriteIntegerAttribute( hDBF, iRecord, iField, nValue );
-            break;
-
-          default:
-            break;
-        }
-    } /* next subfield */
-
- -

Cleanup

- -In the case of sdts2shp, the SDTSTransfer is created on the stack. When it -falls out of scope it is destroyed, and all the indexed readers, and their -indexed features caches are also cleaned up.

- -*/ - -/*! -\page sdts2shp.cpp -

-SDTS To Shape Example Application -
- -\include sdts2shp.cpp -*/ diff --git a/frmts/sdts/sdtsattrreader.cpp b/frmts/sdts/sdtsattrreader.cpp deleted file mode 100644 index 5faaa6d94712..000000000000 --- a/frmts/sdts/sdtsattrreader.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTSAttrReader class. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSAttrRecord */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSAttrRecord() */ -/************************************************************************/ - -SDTSAttrRecord::SDTSAttrRecord() : poWholeRecord(nullptr), poATTR(nullptr) -{ -} - -/************************************************************************/ -/* ~SDTSAttrRecord() */ -/************************************************************************/ - -SDTSAttrRecord::~SDTSAttrRecord() - -{ - if (poWholeRecord != nullptr) - delete poWholeRecord; -} - -/************************************************************************/ -/* Dump() */ -/************************************************************************/ - -void SDTSAttrRecord::Dump(FILE *fp) - -{ - if (poATTR != nullptr) - poATTR->Dump(fp); -} - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSAttrReader */ -/* */ -/* This is the class used to read a primary attribute module. */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSAttrReader() */ -/************************************************************************/ - -SDTSAttrReader::SDTSAttrReader() : bIsSecondary(FALSE) -{ -} - -/************************************************************************/ -/* ~SDTSAttrReader() */ -/************************************************************************/ - -SDTSAttrReader::~SDTSAttrReader() -{ - Close(); -} - -/************************************************************************/ -/* Close() */ -/************************************************************************/ - -void SDTSAttrReader::Close() - -{ - ClearIndex(); - oDDFModule.Close(); -} - -/************************************************************************/ -/* Open() */ -/* */ -/* Open the requested attr file, and prepare to start reading */ -/* data records. */ -/************************************************************************/ - -int SDTSAttrReader::Open(const char *pszFilename) - -{ - bool bSuccess = CPL_TO_BOOL(oDDFModule.Open(pszFilename)); - - if (bSuccess) - bIsSecondary = (oDDFModule.FindFieldDefn("ATTS") != nullptr); - - return bSuccess; -} - -/************************************************************************/ -/* GetNextRecord() */ -/************************************************************************/ - -DDFField *SDTSAttrReader::GetNextRecord(SDTSModId *poModId, - DDFRecord **ppoRecord, int bDuplicate) - -{ - /* -------------------------------------------------------------------- */ - /* Fetch a record. */ - /* -------------------------------------------------------------------- */ - if (ppoRecord != nullptr) - *ppoRecord = nullptr; - - if (oDDFModule.GetFP() == nullptr) - return nullptr; - - DDFRecord *poRecord = oDDFModule.ReadRecord(); - - if (poRecord == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Make a copy of the record for persistent use if requested by */ - /* the caller. */ - /* -------------------------------------------------------------------- */ - if (bDuplicate) - poRecord = poRecord->Clone(); - - /* -------------------------------------------------------------------- */ - /* Find the ATTP field. */ - /* -------------------------------------------------------------------- */ - DDFField *poATTP = poRecord->FindField("ATTP", 0); - if (poATTP == nullptr) - { - poATTP = poRecord->FindField("ATTS", 0); - } - - if (poATTP == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Update the module ID if required. */ - /* -------------------------------------------------------------------- */ - if (poModId != nullptr) - { - DDFField *poATPR = poRecord->FindField("ATPR"); - - if (poATPR == nullptr) - poATPR = poRecord->FindField("ATSC"); - - if (poATPR != nullptr) - poModId->Set(poATPR); - } - - /* -------------------------------------------------------------------- */ - /* return proper answer. */ - /* -------------------------------------------------------------------- */ - if (ppoRecord != nullptr) - *ppoRecord = poRecord; - - return poATTP; -} - -/************************************************************************/ -/* GetNextAttrRecord() */ -/************************************************************************/ - -SDTSAttrRecord *SDTSAttrReader::GetNextAttrRecord() - -{ - SDTSModId oModId; - DDFRecord *poRawRecord = nullptr; - - DDFField *poATTRField = GetNextRecord(&oModId, &poRawRecord, TRUE); - - if (poATTRField == nullptr) - return nullptr; - - SDTSAttrRecord *poAttrRecord = new SDTSAttrRecord(); - - poAttrRecord->poWholeRecord = poRawRecord; - poAttrRecord->poATTR = poATTRField; - memcpy(&(poAttrRecord->oModId), &oModId, sizeof(SDTSModId)); - - return poAttrRecord; -} diff --git a/frmts/sdts/sdtscatd.cpp b/frmts/sdts/sdtscatd.cpp deleted file mode 100644 index 5dc1bd964411..000000000000 --- a/frmts/sdts/sdtscatd.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTS_CATD and SDTS_CATDEntry classes for - * reading CATD files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -#include - -/************************************************************************/ -/* ==================================================================== */ -/* SDTS_CATDEntry */ -/* */ -/* This class is for internal use of the SDTS_CATD class only, */ -/* and represents one entry in the directory ... a reference */ -/* to another module file. */ -/* ==================================================================== */ -/************************************************************************/ - -class SDTS_CATDEntry - -{ - public: - char *pszModule; - char *pszType; - char *pszFile; - char *pszExternalFlag; - - char *pszFullPath; -}; - -/************************************************************************/ -/* ==================================================================== */ -/* SDTS_CATD */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTS_CATD() */ -/************************************************************************/ - -SDTS_CATD::SDTS_CATD() - : pszPrefixPath(nullptr), nEntries(0), papoEntries(nullptr) -{ -} - -/************************************************************************/ -/* ~SDTS_CATD() */ -/************************************************************************/ - -SDTS_CATD::~SDTS_CATD() -{ - for (int i = 0; i < nEntries; i++) - { - CPLFree(papoEntries[i]->pszModule); - CPLFree(papoEntries[i]->pszType); - CPLFree(papoEntries[i]->pszFile); - CPLFree(papoEntries[i]->pszExternalFlag); - CPLFree(papoEntries[i]->pszFullPath); - delete papoEntries[i]; - } - - CPLFree(papoEntries); - CPLFree(pszPrefixPath); -} - -/************************************************************************/ -/* Read() */ -/* */ -/* Read the named file to initialize this structure. */ -/************************************************************************/ - -int SDTS_CATD::Read(const char *pszFilename) - -{ - /* -------------------------------------------------------------------- */ - /* Open the file. */ - /* -------------------------------------------------------------------- */ - DDFModule oCATDFile; - if (!oCATDFile.Open(pszFilename)) - return FALSE; - - CPLErrorReset(); // Clear any ADRG "unrecognized data_struct_code" errors. - - /* -------------------------------------------------------------------- */ - /* Does this file have a CATD field? If not, it isn't an SDTS */ - /* record and we won't even try reading the first record for */ - /* fear it will we a huge honking ADRG data record or something. */ - /* -------------------------------------------------------------------- */ - if (oCATDFile.FindFieldDefn("CATD") == nullptr) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Strip off the filename, and keep the path prefix. */ - /* -------------------------------------------------------------------- */ - pszPrefixPath = CPLStrdup(pszFilename); - int i = static_cast(strlen(pszPrefixPath)) - 1; - for (; i > 0; i--) - { - if (pszPrefixPath[i] == '\\' || pszPrefixPath[i] == '/') - { - pszPrefixPath[i] = '\0'; - break; - } - } - - if (i <= 0) - { - strcpy(pszPrefixPath, "."); - } - - /* ==================================================================== */ - /* Loop reading CATD records, and adding to our list of entries */ - /* for each. */ - /* ==================================================================== */ - DDFRecord *poRecord = nullptr; - int nIters = 0; - std::set aoSetFiles; - while ((poRecord = oCATDFile.ReadRecord()) != nullptr && nIters < 1000) - { - nIters++; - - /* -------------------------------------------------------------------- - */ - /* Verify that we have a proper CATD record. */ - /* -------------------------------------------------------------------- - */ - if (poRecord->GetStringSubfield("CATD", 0, "MODN", 0) == nullptr) - continue; - - /* -------------------------------------------------------------------- - */ - /* Create a new entry, and get the module and file name. */ - /* -------------------------------------------------------------------- - */ - SDTS_CATDEntry *poEntry = new SDTS_CATDEntry; - - poEntry->pszModule = - CPLStrdup(poRecord->GetStringSubfield("CATD", 0, "NAME", 0)); - poEntry->pszFile = - CPLStrdup(poRecord->GetStringSubfield("CATD", 0, "FILE", 0)); - poEntry->pszExternalFlag = - CPLStrdup(poRecord->GetStringSubfield("CATD", 0, "EXTR", 0)); - poEntry->pszType = - CPLStrdup(poRecord->GetStringSubfield("CATD", 0, "TYPE", 0)); - - if (poEntry->pszModule[0] == '\0' || poEntry->pszFile[0] == '\0' || - // Exclude following one for performance reasons in oss-fuzz - (poEntry->pszFile[0] == '/' && poEntry->pszFile[1] == '\0') || - aoSetFiles.find(poEntry->pszFile) != aoSetFiles.end()) - { - CPLFree(poEntry->pszModule); - CPLFree(poEntry->pszFile); - CPLFree(poEntry->pszExternalFlag); - CPLFree(poEntry->pszType); - delete poEntry; - continue; - } - aoSetFiles.insert(poEntry->pszFile); - - /* -------------------------------------------------------------------- - */ - /* Create a full path to the file. */ - /* -------------------------------------------------------------------- - */ - poEntry->pszFullPath = CPLStrdup( - CPLFormCIFilenameSafe(pszPrefixPath, poEntry->pszFile, nullptr) - .c_str()); - - /* -------------------------------------------------------------------- - */ - /* Add the entry to the list. */ - /* -------------------------------------------------------------------- - */ - papoEntries = reinterpret_cast( - CPLRealloc(papoEntries, sizeof(void *) * ++nEntries)); - papoEntries[nEntries - 1] = poEntry; - } - - return nEntries > 0; -} - -/************************************************************************/ -/* GetModuleFilePath() */ -/************************************************************************/ - -const char *SDTS_CATD::GetModuleFilePath(const char *pszModule) const - -{ - for (int i = 0; i < nEntries; i++) - { - if (EQUAL(papoEntries[i]->pszModule, pszModule)) - return papoEntries[i]->pszFullPath; - } - - return nullptr; -} - -/************************************************************************/ -/* GetEntryModule() */ -/************************************************************************/ - -const char *SDTS_CATD::GetEntryModule(int iEntry) const - -{ - if (iEntry < 0 || iEntry >= nEntries) - return nullptr; - - return papoEntries[iEntry]->pszModule; -} - -/************************************************************************/ -/* GetEntryTypeDesc() */ -/************************************************************************/ - -/** - * Fetch the type description of a module in the catalog. - * - * @param iEntry The module index within the CATD catalog. A number from - * zero to GetEntryCount()-1. - * - * @return A pointer to an internal string with the type description for - * this module. This is from the CATD file (subfield TYPE of field CATD), - * and will be something like "Attribute Primary ". - */ - -const char *SDTS_CATD::GetEntryTypeDesc(int iEntry) const - -{ - if (iEntry < 0 || iEntry >= nEntries) - return nullptr; - - return papoEntries[iEntry]->pszType; -} - -/************************************************************************/ -/* GetEntryType() */ -/************************************************************************/ - -/** - * Fetch the enumerated type of a module in the catalog. - * - * @param iEntry The module index within the CATD catalog. A number from - * zero to GetEntryCount()-1. - * - * @return A value from the SDTSLayerType enumeration indicating the type of - * the module, and indicating the corresponding type of reader.

- * - *

    - *
  • SLTPoint: Read with SDTSPointReader, underlying type of - * Point-Node. - *
  • SLTLine: Read with SDTSLineReader, underlying type of - * Line. - *
  • SLTAttr: Read with SDTSAttrReader, underlying type of - * Attribute Primary or Attribute Secondary. - *
  • SLTPolygon: Read with SDTSPolygonReader, underlying type of - * Polygon. - *
- */ - -SDTSLayerType SDTS_CATD::GetEntryType(int iEntry) const - -{ - if (iEntry < 0 || iEntry >= nEntries) - return SLTUnknown; - - else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Attribute Primary")) - return SLTAttr; - - else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, - "Attribute Secondary")) - return SLTAttr; - - else if (EQUAL(papoEntries[iEntry]->pszType, "Line") || - STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Line ")) - return SLTLine; - - else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Point-Node")) - return SLTPoint; - - else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Polygon")) - return SLTPoly; - - else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Cell")) - return SLTRaster; - - else - return SLTUnknown; -} - -/************************************************************************/ -/* SetEntryTypeUnknown() */ -/************************************************************************/ - -void SDTS_CATD::SetEntryTypeUnknown(int iEntry) -{ - if (iEntry >= 0 && iEntry < nEntries) - { - CPLFree(papoEntries[iEntry]->pszType); - papoEntries[iEntry]->pszType = CPLStrdup("Unknown"); - } -} - -/************************************************************************/ -/* GetEntryFilePath() */ -/************************************************************************/ - -/** - * Fetch the full filename of the requested module. - * - * @param iEntry The module index within the CATD catalog. A number from - * zero to GetEntryCount()-1. - * - * @return A pointer to an internal string containing the filename. This - * string should not be altered, or freed by the application. - */ - -const char *SDTS_CATD::GetEntryFilePath(int iEntry) const - -{ - if (iEntry < 0 || iEntry >= nEntries) - return nullptr; - - return papoEntries[iEntry]->pszFullPath; -} diff --git a/frmts/sdts/sdtsdataset.cpp b/frmts/sdts/sdtsdataset.cpp deleted file mode 100644 index 29714be1a1f8..000000000000 --- a/frmts/sdts/sdtsdataset.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: GDALDataset driver for SDTS Raster translator. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2008-2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "gdal_frmts.h" -#include "gdal_pam.h" -#include "ogr_spatialref.h" -#include "sdts_al.h" - -/** - \file sdtsdataset.cpp - - exclude -*/ - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class SDTSRasterBand; - -class SDTSDataset final : public GDALPamDataset -{ - friend class SDTSRasterBand; - - SDTSTransfer *poTransfer; - SDTSRasterReader *poRL; - - OGRSpatialReference m_oSRS{}; - - public: - SDTSDataset(); - virtual ~SDTSDataset(); - - static GDALDataset *Open(GDALOpenInfo *); - - const OGRSpatialReference *GetSpatialRef() const override - { - return &m_oSRS; - } - - virtual CPLErr GetGeoTransform(double *) override; -}; - -class SDTSRasterBand final : public GDALPamRasterBand -{ - friend class SDTSDataset; - - SDTSRasterReader *poRL; - - public: - SDTSRasterBand(SDTSDataset *, int, SDTSRasterReader *); - - virtual CPLErr IReadBlock(int, int, void *) override; - - virtual double GetNoDataValue(int *pbSuccess) override; - virtual const char *GetUnitType() override; -}; - -/************************************************************************/ -/* SDTSDataset() */ -/************************************************************************/ - -SDTSDataset::SDTSDataset() : poTransfer(nullptr), poRL(nullptr) -{ - m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); -} - -/************************************************************************/ -/* ~SDTSDataset() */ -/************************************************************************/ - -SDTSDataset::~SDTSDataset() - -{ - FlushCache(true); - - if (poTransfer != nullptr) - delete poTransfer; - - if (poRL != nullptr) - delete poRL; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *SDTSDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - /* -------------------------------------------------------------------- */ - /* Before trying SDTSOpen() we first verify that the first */ - /* record is in fact a SDTS file descriptor record. */ - /* -------------------------------------------------------------------- */ - if (poOpenInfo->nHeaderBytes < 24) - return nullptr; - - char *pachLeader = reinterpret_cast(poOpenInfo->pabyHeader); - if (pachLeader[5] != '1' && pachLeader[5] != '2' && pachLeader[5] != '3') - return nullptr; - - if (pachLeader[6] != 'L') - return nullptr; - - if (pachLeader[8] != '1' && pachLeader[8] != ' ') - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Try opening the dataset. */ - /* -------------------------------------------------------------------- */ - SDTSTransfer *poTransfer = new SDTSTransfer; - - if (!poTransfer->Open(poOpenInfo->pszFilename)) - { - delete poTransfer; - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Confirm the requested access is supported. */ - /* -------------------------------------------------------------------- */ - if (poOpenInfo->eAccess == GA_Update) - { - delete poTransfer; - CPLError(CE_Failure, CPLE_NotSupported, - "The SDTS driver does not support update access to existing" - " datasets.\n"); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Find the first raster layer. If there are none, abort */ - /* returning an error. */ - /* -------------------------------------------------------------------- */ - SDTSRasterReader *poRL = nullptr; - - for (int i = 0; i < poTransfer->GetLayerCount(); i++) - { - if (poTransfer->GetLayerType(i) == SLTRaster) - { - poRL = poTransfer->GetLayerRasterReader(i); - break; - } - } - - if (poRL == nullptr) - { - delete poTransfer; - - CPLError(CE_Warning, CPLE_AppDefined, - "%s is an SDTS transfer, but has no raster cell layers.\n" - "Perhaps it is a vector transfer?\n", - poOpenInfo->pszFilename); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Initialize a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - SDTSDataset *poDS = new SDTSDataset(); - - poDS->poTransfer = poTransfer; - poDS->poRL = poRL; - - /* -------------------------------------------------------------------- */ - /* Capture some information from the file that is of interest. */ - /* -------------------------------------------------------------------- */ - poDS->nRasterXSize = poRL->GetXSize(); - poDS->nRasterYSize = poRL->GetYSize(); - - /* -------------------------------------------------------------------- */ - /* Create band information objects. */ - /* -------------------------------------------------------------------- */ - poDS->nBands = 1; - poDS->papoBands = reinterpret_cast( - VSICalloc(sizeof(GDALRasterBand *), poDS->nBands)); - - for (int i = 0; i < poDS->nBands; i++) - poDS->SetBand(i + 1, new SDTSRasterBand(poDS, i + 1, poRL)); - - /* -------------------------------------------------------------------- */ - /* Try to establish the projection string. For now we only */ - /* support UTM and GEO. */ - /* -------------------------------------------------------------------- */ - SDTS_XREF *poXREF = poTransfer->GetXREF(); - - if (EQUAL(poXREF->pszSystemName, "UTM")) - { - poDS->m_oSRS.SetUTM(poXREF->nZone); - } - else if (EQUAL(poXREF->pszSystemName, "GEO")) - { - /* we set datum later */ - } - else - poDS->m_oSRS.SetLocalCS(poXREF->pszSystemName); - - if (poDS->m_oSRS.IsLocal()) - /* don't try to set datum. */; - else if (EQUAL(poXREF->pszDatum, "NAS")) - poDS->m_oSRS.SetWellKnownGeogCS("NAD27"); - else if (EQUAL(poXREF->pszDatum, "NAX")) - poDS->m_oSRS.SetWellKnownGeogCS("NAD83"); - else if (EQUAL(poXREF->pszDatum, "WGC")) - poDS->m_oSRS.SetWellKnownGeogCS("WGS72"); - else /* if( EQUAL(poXREF->pszDatum, "WGE") ) or default */ - poDS->m_oSRS.SetWellKnownGeogCS("WGS84"); - - /* -------------------------------------------------------------------- */ - /* Get metadata from the IDEN file. */ - /* -------------------------------------------------------------------- */ - const char *pszIDENFilePath = - poTransfer->GetCATD()->GetModuleFilePath("IDEN"); - if (pszIDENFilePath) - { - DDFModule oIDENFile; - if (oIDENFile.Open(pszIDENFilePath)) - { - DDFRecord *poRecord = nullptr; - - while ((poRecord = oIDENFile.ReadRecord()) != nullptr) - { - - if (poRecord->GetStringSubfield("IDEN", 0, "MODN", 0) == - nullptr) - continue; - - static const char *const fields[][2] = { - {"TITL", "TITLE"}, - {"DAID", "DATASET_ID"}, - {"DAST", "DATA_STRUCTURE"}, - {"MPDT", "MAP_DATE"}, - {"DCDT", "DATASET_CREATION_DATE"}}; - - for (int i = 0; i < static_cast(sizeof(fields)) / - static_cast(sizeof(fields[0])); - i++) - { - const char *pszFieldValue = - poRecord->GetStringSubfield("IDEN", 0, fields[i][0], 0); - if (pszFieldValue) - poDS->SetMetadataItem(fields[i][1], pszFieldValue); - } - - break; - } - } - } - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for external overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename, - poOpenInfo->GetSiblingFiles()); - - return poDS; -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr SDTSDataset::GetGeoTransform(double *padfTransform) - -{ - if (poRL->GetTransform(padfTransform)) - return CE_None; - - return CE_Failure; -} - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSRasterBand() */ -/************************************************************************/ - -SDTSRasterBand::SDTSRasterBand(SDTSDataset *poDSIn, int nBandIn, - SDTSRasterReader *poRLIn) - : poRL(poRLIn) -{ - poDS = poDSIn; - nBand = nBandIn; - - if (poRL->GetRasterType() == SDTS_RT_INT16) - eDataType = GDT_Int16; - else - eDataType = GDT_Float32; - - nBlockXSize = poRL->GetBlockXSize(); - nBlockYSize = poRL->GetBlockYSize(); -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr SDTSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) - -{ - if (poRL->GetBlock(nBlockXOff, nBlockYOff, pImage)) - return CE_None; - - return CE_Failure; -} - -/************************************************************************/ -/* GetNoDataValue() */ -/************************************************************************/ - -double SDTSRasterBand::GetNoDataValue(int *pbSuccess) - -{ - if (pbSuccess != nullptr) - *pbSuccess = TRUE; - - return -32766.0; -} - -/************************************************************************/ -/* GetUnitType() */ -/************************************************************************/ - -const char *SDTSRasterBand::GetUnitType() - -{ - if (EQUAL(poRL->szUNITS, "FEET")) - return "ft"; - else if (STARTS_WITH_CI(poRL->szUNITS, "MET")) - return "m"; - - return poRL->szUNITS; -} - -/************************************************************************/ -/* GDALRegister_SDTS() */ -/************************************************************************/ - -void GDALRegister_SDTS() - -{ - if (GDALGetDriverByName("SDTS") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("SDTS"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "SDTS Raster"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/sdts.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "ddf"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = SDTSDataset::Open; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/sdts/sdtsindexedreader.cpp b/frmts/sdts/sdtsindexedreader.cpp deleted file mode 100644 index c652ab251efe..000000000000 --- a/frmts/sdts/sdtsindexedreader.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implmementation of SDTSIndexedReader class. This base class for - * various reader classes provides indexed caching of features for - * quick fetching when assembling composite features for other - * readers. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -/************************************************************************/ -/* SDTSIndexedReader() */ -/************************************************************************/ - -SDTSIndexedReader::SDTSIndexedReader() - : nIndexSize(-1), papoFeatures(nullptr), iCurrentFeature(0) -{ -} - -/************************************************************************/ -/* ~SDTSIndexedReader() */ -/************************************************************************/ - -SDTSIndexedReader::~SDTSIndexedReader() - -{ - ClearIndex(); -} - -/************************************************************************/ -/* IsIndexed() */ -/************************************************************************/ - -/** - Returns TRUE if the module is indexed, otherwise it returns FALSE. - - If the module is indexed all the feature have already been read into - memory, and searches based on the record number can be performed - efficiently. - */ - -int SDTSIndexedReader::IsIndexed() const - -{ - return nIndexSize >= 0; -} - -/************************************************************************/ -/* ClearIndex() */ -/************************************************************************/ - -/** - Free all features in the index (if filled). - - After this the reader is considered to not be indexed, and IsIndexed() - will return FALSE until the index is forcibly filled again. - */ - -void SDTSIndexedReader::ClearIndex() - -{ - for (int i = 0; i < nIndexSize; i++) - { - if (papoFeatures[i] != nullptr) - delete papoFeatures[i]; - } - - CPLFree(papoFeatures); - - papoFeatures = nullptr; - nIndexSize = 0; -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -/** - Fetch the next available feature from this reader. - - The returned SDTSFeature * is to an internal indexed object if the - IsIndexed() method returns TRUE, otherwise the returned feature becomes the - responsibility of the caller to destroy with delete. - - Note that the Rewind() method can be used to start over at the beginning of - the modules feature list. - - @return next feature, or NULL if no more are left. Please review above - ownership/delete semantics. - - */ - -SDTSFeature *SDTSIndexedReader::GetNextFeature() - -{ - if (nIndexSize < 0) - return GetNextRawFeature(); - - while (iCurrentFeature < nIndexSize) - { - if (papoFeatures[iCurrentFeature] != nullptr) - return papoFeatures[iCurrentFeature++]; - else - iCurrentFeature++; - } - - return nullptr; -} - -/************************************************************************/ -/* GetIndexedFeatureRef() */ -/************************************************************************/ - -/** - Fetch a feature based on its record number. - - This method will forcibly fill the feature cache, reading all the - features in the file into memory, if they haven't already been loaded. - The ClearIndex() method can be used to flush this cache when no longer - needed. - - @param iRecordId the record to fetch, normally based on the nRecord - field of an SDTSModId. - - @return a pointer to an internal feature (not to be deleted) or NULL - if there is no matching feature. -*/ - -SDTSFeature *SDTSIndexedReader::GetIndexedFeatureRef(int iRecordId) - -{ - if (nIndexSize < 0) - FillIndex(); - - if (iRecordId < 0 || iRecordId >= nIndexSize) - return nullptr; - - return papoFeatures[iRecordId]; -} - -/************************************************************************/ -/* FillIndex() */ -/************************************************************************/ - -/** - Read all features into a memory indexed cached. - - The ClearIndex() method can be used to free all indexed features. - FillIndex() does nothing, if an index has already been built. -*/ - -void SDTSIndexedReader::FillIndex() - -{ - if (nIndexSize >= 0) - return; - - Rewind(); - nIndexSize = 0; - - SDTSFeature *poFeature = nullptr; - while ((poFeature = GetNextRawFeature()) != nullptr) - { - const int iRecordId = poFeature->oModId.nRecord; - - if (iRecordId < 0 || iRecordId >= 1000000) - { - delete poFeature; - continue; - } - if (iRecordId < nIndexSize && papoFeatures[iRecordId] != nullptr) - { - delete poFeature; - continue; - } - - if (iRecordId >= nIndexSize) - { - const int nNewSize = static_cast(iRecordId * 1.25 + 100); - - papoFeatures = reinterpret_cast( - CPLRealloc(papoFeatures, sizeof(void *) * nNewSize)); - - for (int i = nIndexSize; i < nNewSize; i++) - papoFeatures[i] = nullptr; - - nIndexSize = nNewSize; - } - - papoFeatures[iRecordId] = poFeature; - } -} - -/************************************************************************/ -/* ScanModuleReferences() */ -/************************************************************************/ - -/** - Scan an entire SDTS module for record references with the given field - name. - - The fields are required to have a MODN subfield from which the - module is extracted. - - This method is normally used to find all the attribute modules referred - to by a point, line or polygon module to build a unified schema. - - This method will have the side effect of rewinding unindexed readers - because the scanning operation requires reading all records in the module - from disk. - - @param pszFName the field name to search for. By default "ATID" is - used. - - @return a NULL terminated list of module names. Free with CSLDestroy(). -*/ - -char **SDTSIndexedReader::ScanModuleReferences(const char *pszFName) - -{ - return SDTSScanModuleReferences(&oDDFModule, pszFName); -} - -/************************************************************************/ -/* Rewind() */ -/************************************************************************/ - -/** - Rewind so that the next feature returned by GetNextFeature() will be the - first in the module. - -*/ - -void SDTSIndexedReader::Rewind() - -{ - if (nIndexSize >= 0) - iCurrentFeature = 0; - else - oDDFModule.Rewind(); -} diff --git a/frmts/sdts/sdtsiref.cpp b/frmts/sdts/sdtsiref.cpp deleted file mode 100644 index 0e6990258cc5..000000000000 --- a/frmts/sdts/sdtsiref.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTS_IREF class for reading IREF module. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -/************************************************************************/ -/* SDTS_IREF() */ -/************************************************************************/ - -SDTS_IREF::SDTS_IREF() - : nDefaultSADRFormat(0), pszXAxisName(CPLStrdup("")), - pszYAxisName(CPLStrdup("")), dfXScale(1.0), dfYScale(1.0), dfXOffset(0.0), - dfYOffset(0.0), dfXRes(1.0), dfYRes(1.0), - pszCoordinateFormat(CPLStrdup("")) -{ -} - -/************************************************************************/ -/* ~SDTS_IREF() */ -/************************************************************************/ - -SDTS_IREF::~SDTS_IREF() -{ - CPLFree(pszXAxisName); - CPLFree(pszYAxisName); - CPLFree(pszCoordinateFormat); -} - -/************************************************************************/ -/* Read() */ -/* */ -/* Read the named file to initialize this structure. */ -/************************************************************************/ - -int SDTS_IREF::Read(const char *pszFilename) - -{ - /* -------------------------------------------------------------------- */ - /* Open the file, and read the header. */ - /* -------------------------------------------------------------------- */ - DDFModule oIREFFile; - if (!oIREFFile.Open(pszFilename)) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Read the first record, and verify that this is an IREF record. */ - /* -------------------------------------------------------------------- */ - DDFRecord *poRecord = oIREFFile.ReadRecord(); - if (poRecord == nullptr) - return FALSE; - - if (poRecord->GetStringSubfield("IREF", 0, "MODN", 0) == nullptr) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Get the labels. */ - /* -------------------------------------------------------------------- */ - CPLFree(pszXAxisName); - pszXAxisName = CPLStrdup(poRecord->GetStringSubfield("IREF", 0, "XLBL", 0)); - CPLFree(pszYAxisName); - pszYAxisName = CPLStrdup(poRecord->GetStringSubfield("IREF", 0, "YLBL", 0)); - - /* -------------------------------------------------------------------- */ - /* Get the coordinate encoding. */ - /* -------------------------------------------------------------------- */ - CPLFree(pszCoordinateFormat); - pszCoordinateFormat = - CPLStrdup(poRecord->GetStringSubfield("IREF", 0, "HFMT", 0)); - - /* -------------------------------------------------------------------- */ - /* Get the transformation information, and resolution. */ - /* -------------------------------------------------------------------- */ - dfXScale = poRecord->GetFloatSubfield("IREF", 0, "SFAX", 0); - dfYScale = poRecord->GetFloatSubfield("IREF", 0, "SFAY", 0); - - dfXOffset = poRecord->GetFloatSubfield("IREF", 0, "XORG", 0); - dfYOffset = poRecord->GetFloatSubfield("IREF", 0, "YORG", 0); - - dfXRes = poRecord->GetFloatSubfield("IREF", 0, "XHRS", 0); - dfYRes = poRecord->GetFloatSubfield("IREF", 0, "YHRS", 0); - - nDefaultSADRFormat = EQUAL(pszCoordinateFormat, "BI32"); - - return TRUE; -} - -/************************************************************************/ -/* GetSADRCount() */ -/* */ -/* Return the number of SADR'es in the passed field. */ -/************************************************************************/ - -int SDTS_IREF::GetSADRCount(DDFField *poField) const - -{ - if (nDefaultSADRFormat) - return poField->GetDataSize() / SDTS_SIZEOF_SADR; - - return poField->GetRepeatCount(); -} - -/************************************************************************/ -/* GetSADR() */ -/************************************************************************/ - -int SDTS_IREF::GetSADR(DDFField *poField, int nVertices, double *padfX, - double *padfY, double *padfZ) - -{ - /* -------------------------------------------------------------------- */ - /* For the sake of efficiency we depend on our knowledge that */ - /* the SADR field is a series of bigendian int32's and decode */ - /* them directly. */ - /* -------------------------------------------------------------------- */ - if (nDefaultSADRFormat && poField->GetFieldDefn()->GetSubfieldCount() == 2) - { - if (poField->GetDataSize() < nVertices * SDTS_SIZEOF_SADR) - { - return FALSE; - } - - GInt32 anXY[2]; - const char *pachRawData = poField->GetData(); - - for (int iVertex = 0; iVertex < nVertices; iVertex++) - { - // we copy to a temp buffer to ensure it is world aligned. - memcpy(anXY, pachRawData, 8); - pachRawData += 8; - - // possibly byte swap, and always apply scale factor - padfX[iVertex] = - dfXOffset + dfXScale * static_cast(CPL_MSBWORD32(anXY[0])); - padfY[iVertex] = - dfYOffset + dfYScale * static_cast(CPL_MSBWORD32(anXY[1])); - - padfZ[iVertex] = 0.0; - } - } - - /* -------------------------------------------------------------------- */ - /* This is the generic case. We assume either two or three */ - /* subfields, and treat these as X, Y and Z regardless of */ - /* name. */ - /* -------------------------------------------------------------------- */ - else - { - DDFFieldDefn *poFieldDefn = poField->GetFieldDefn(); - int nBytesRemaining = poField->GetDataSize(); - const char *pachFieldData = poField->GetData(); - - if (poFieldDefn->GetSubfieldCount() != 2 && - poFieldDefn->GetSubfieldCount() != 3) - { - return FALSE; - } - - for (int iVertex = 0; iVertex < nVertices; iVertex++) - { - double adfXYZ[3] = {0.0, 0.0, 0.0}; - - for (int iEntry = 0; nBytesRemaining > 0 && - iEntry < poFieldDefn->GetSubfieldCount(); - iEntry++) - { - int nBytesConsumed = 0; - DDFSubfieldDefn *poSF = poFieldDefn->GetSubfield(iEntry); - - switch (poSF->GetType()) - { - case DDFInt: - adfXYZ[iEntry] = poSF->ExtractIntData( - pachFieldData, nBytesRemaining, &nBytesConsumed); - break; - - case DDFFloat: - adfXYZ[iEntry] = poSF->ExtractFloatData( - pachFieldData, nBytesRemaining, &nBytesConsumed); - break; - - case DDFBinaryString: - { - GByte *pabyBString = reinterpret_cast( - const_cast(poSF->ExtractStringData( - pachFieldData, nBytesRemaining, - &nBytesConsumed))); - - if (EQUAL(pszCoordinateFormat, "BI32")) - { - if (nBytesConsumed < 4) - return FALSE; - GInt32 nValue; - memcpy(&nValue, pabyBString, 4); - adfXYZ[iEntry] = - static_cast(CPL_MSBWORD32(nValue)); - } - else if (EQUAL(pszCoordinateFormat, "BI16")) - { - if (nBytesConsumed < 2) - return FALSE; - GInt16 nValue; - memcpy(&nValue, pabyBString, 2); - adfXYZ[iEntry] = - static_cast(CPL_MSBWORD16(nValue)); - } - else if (EQUAL(pszCoordinateFormat, "BU32")) - { - if (nBytesConsumed < 4) - return FALSE; - GUInt32 nValue; - memcpy(&nValue, pabyBString, 4); - adfXYZ[iEntry] = - static_cast(CPL_MSBWORD32(nValue)); - } - else if (EQUAL(pszCoordinateFormat, "BU16")) - { - if (nBytesConsumed < 2) - return FALSE; - GUInt16 nValue; - memcpy(&nValue, pabyBString, 2); - adfXYZ[iEntry] = - static_cast(CPL_MSBWORD16(nValue)); - } - else if (EQUAL(pszCoordinateFormat, "BFP32")) - { - if (nBytesConsumed < 4) - return FALSE; - float fValue; - - memcpy(&fValue, pabyBString, 4); - CPL_MSBPTR32(&fValue); - adfXYZ[iEntry] = fValue; - } - else if (EQUAL(pszCoordinateFormat, "BFP64")) - { - if (nBytesConsumed < 8) - return FALSE; - double dfValue; - - memcpy(&dfValue, pabyBString, 8); - CPL_MSBPTR64(&dfValue); - adfXYZ[iEntry] = dfValue; - } - } - break; - - default: - adfXYZ[iEntry] = 0.0; - break; - } - - pachFieldData += nBytesConsumed; - nBytesRemaining -= nBytesConsumed; - } /* next iEntry */ - - padfX[iVertex] = dfXOffset + adfXYZ[0] * dfXScale; - padfY[iVertex] = dfYOffset + adfXYZ[1] * dfYScale; - padfZ[iVertex] = adfXYZ[2]; - } /* next iVertex */ - } - - return TRUE; -} diff --git a/frmts/sdts/sdtslib.cpp b/frmts/sdts/sdtslib.cpp deleted file mode 100644 index e57ce31a5f74..000000000000 --- a/frmts/sdts/sdtslib.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Various utility functions that apply to all SDTS profiles. - * SDTSModId, and SDTSFeature methods. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" -#include "cpl_string.h" - -#include - -/************************************************************************/ -/* SDTSFeature() */ -/************************************************************************/ - -SDTSFeature::SDTSFeature() : nAttributes(0), paoATID(nullptr) -{ -} - -/************************************************************************/ -/* SDTSFeature::ApplyATID() */ -/************************************************************************/ - -void SDTSFeature::ApplyATID(DDFField *poField) - -{ - DDFSubfieldDefn *poMODN = poField->GetFieldDefn()->FindSubfieldDefn("MODN"); - if (poMODN == nullptr) - { - // CPLAssert( false ); - return; - } - - bool bUsualFormat = poMODN->GetWidth() == 4; - const int nRepeatCount = poField->GetRepeatCount(); - for (int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++) - { - paoATID = reinterpret_cast( - CPLRealloc(paoATID, sizeof(SDTSModId) * (nAttributes + 1))); - - SDTSModId *poModId = paoATID + nAttributes; - *poModId = SDTSModId(); - - if (bUsualFormat) - { - const char *pabyData = - poField->GetSubfieldData(poMODN, nullptr, iRepeat); - if (pabyData == nullptr || strlen(pabyData) < 5) - return; - - memcpy(poModId->szModule, pabyData, 4); - poModId->szModule[4] = '\0'; - poModId->nRecord = atoi(pabyData + 4); - poModId->szOBRP[0] = '\0'; - } - else - { - poModId->Set(poField); - } - - nAttributes++; - } -} - -/************************************************************************/ -/* ~SDTSFeature() */ -/************************************************************************/ - -SDTSFeature::~SDTSFeature() - -{ - CPLFree(paoATID); - paoATID = nullptr; -} - -/************************************************************************/ -/* SDTSModId::Set() */ -/* */ -/* Set a module from a field. We depend on our pre-knowledge */ -/* of the data layout to fetch more efficiently. */ -/************************************************************************/ - -int SDTSModId::Set(DDFField *poField) - -{ - const char *pachData = poField->GetData(); - DDFFieldDefn *poDefn = poField->GetFieldDefn(); - - if (poDefn->GetSubfieldCount() >= 2 && - poDefn->GetSubfield(0)->GetWidth() == 4) - { - if (strlen(pachData) < 5) - return FALSE; - - memcpy(szModule, pachData, 4); - szModule[4] = '\0'; - - nRecord = atoi(pachData + 4); - } - else - { - DDFSubfieldDefn *poSF = - poField->GetFieldDefn()->FindSubfieldDefn("MODN"); - if (poSF == nullptr) - return FALSE; - int nBytesRemaining; - pachData = poField->GetSubfieldData(poSF, &nBytesRemaining); - if (pachData == nullptr) - return FALSE; - snprintf(szModule, sizeof(szModule), "%s", - poSF->ExtractStringData(pachData, nBytesRemaining, nullptr)); - - poSF = poField->GetFieldDefn()->FindSubfieldDefn("RCID"); - if (poSF != nullptr) - { - pachData = poField->GetSubfieldData(poSF, &nBytesRemaining); - if (pachData != nullptr) - nRecord = - poSF->ExtractIntData(pachData, nBytesRemaining, nullptr); - } - } - - if (poDefn->GetSubfieldCount() == 3) - { - DDFSubfieldDefn *poSF = - poField->GetFieldDefn()->FindSubfieldDefn("OBRP"); - if (poSF != nullptr) - { - int nBytesRemaining; - pachData = poField->GetSubfieldData(poSF, &nBytesRemaining); - if (pachData != nullptr) - { - snprintf(szOBRP, sizeof(szOBRP), "%s", - poSF->ExtractStringData(pachData, nBytesRemaining, - nullptr)); - } - } - } - - return FALSE; -} - -/************************************************************************/ -/* SDTSModId::GetName() */ -/************************************************************************/ - -const char *SDTSModId::GetName() - -{ - snprintf(szName, sizeof(szName), "%s:%d", szModule, nRecord); - - return szName; -} - -/************************************************************************/ -/* SDTSScanModuleReferences() */ -/* */ -/* Find all modules references by records in this module based */ -/* on a particular field name. That field must be in module */ -/* reference form (contain MODN/RCID subfields). */ -/************************************************************************/ - -char **SDTSScanModuleReferences(DDFModule *poModule, const char *pszFName) - -{ - /* -------------------------------------------------------------------- */ - /* Identify the field, and subfield we are interested in. */ - /* -------------------------------------------------------------------- */ - DDFFieldDefn *poIDField = poModule->FindFieldDefn(pszFName); - - if (poIDField == nullptr) - return nullptr; - - DDFSubfieldDefn *poMODN = poIDField->FindSubfieldDefn("MODN"); - if (poMODN == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Scan the file. */ - /* -------------------------------------------------------------------- */ - poModule->Rewind(); - - DDFRecord *poRecord = nullptr; - CPLStringList aosModnList; - std::set aoSetModNames; - while ((poRecord = poModule->ReadRecord()) != nullptr) - { - for (int iField = 0; iField < poRecord->GetFieldCount(); iField++) - { - DDFField *poField = poRecord->GetField(iField); - - if (poField->GetFieldDefn() == poIDField) - { - for (int i = 0; i < poField->GetRepeatCount(); i++) - { - const char *pszModName = - poField->GetSubfieldData(poMODN, nullptr, i); - - if (pszModName == nullptr || strlen(pszModName) < 4) - continue; - - char szName[5]; - strncpy(szName, pszModName, 4); - szName[4] = '\0'; - - if (aoSetModNames.find(szName) == aoSetModNames.end()) - { - aoSetModNames.insert(szName); - aosModnList.AddString(szName); - } - } - } - } - } - - poModule->Rewind(); - - return aosModnList.StealList(); -} diff --git a/frmts/sdts/sdtslinereader.cpp b/frmts/sdts/sdtslinereader.cpp deleted file mode 100644 index 73defe33befa..000000000000 --- a/frmts/sdts/sdtslinereader.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTSLineReader and SDTSRawLine classes. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSRawLine */ -/* */ -/* This is a simple class for holding the data related with a */ -/* line feature. */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSRawLine() */ -/************************************************************************/ - -SDTSRawLine::SDTSRawLine() - : nVertices(0), padfX(nullptr), padfY(nullptr), padfZ(nullptr) -{ - nAttributes = 0; -} - -/************************************************************************/ -/* ~STDSRawLine() */ -/************************************************************************/ - -SDTSRawLine::~SDTSRawLine() - -{ - CPLFree(padfX); -} - -/************************************************************************/ -/* Read() */ -/* */ -/* Read a record from the passed SDTSLineReader, and assign the */ -/* values from that record to this line. This is the bulk of */ -/* the work in this whole file. */ -/************************************************************************/ - -int SDTSRawLine::Read(SDTS_IREF *poIREF, DDFRecord *poRecord) - -{ - // E.Rouault: Not sure if this test is really useful - if (poRecord->GetStringSubfield("LINE", 0, "MODN", 0) == nullptr) - return FALSE; - - /* ==================================================================== */ - /* Loop over fields in this record, looking for those we */ - /* recognise, and need. I don't use the getSubfield() */ - /* interface on the record in order to retain some slight bit */ - /* of efficiency. */ - /* ==================================================================== */ - for (int iField = 0; iField < poRecord->GetFieldCount(); iField++) - { - DDFField *poField = poRecord->GetField(iField); - if (poField == nullptr) - return FALSE; - DDFFieldDefn *poFieldDefn = poField->GetFieldDefn(); - if (poFieldDefn == nullptr) - return FALSE; - - const char *pszFieldName = poFieldDefn->GetName(); - - if (EQUAL(pszFieldName, "LINE")) - oModId.Set(poField); - - else if (EQUAL(pszFieldName, "ATID")) - ApplyATID(poField); - - else if (EQUAL(pszFieldName, "PIDL")) - oLeftPoly.Set(poField); - - else if (EQUAL(pszFieldName, "PIDR")) - oRightPoly.Set(poField); - - else if (EQUAL(pszFieldName, "SNID")) - oStartNode.Set(poField); - - else if (EQUAL(pszFieldName, "ENID")) - oEndNode.Set(poField); - - else if (EQUAL(pszFieldName, "SADR")) - { - nVertices = poIREF->GetSADRCount(poField); - - padfX = reinterpret_cast( - CPLRealloc(padfX, sizeof(double) * nVertices * 3)); - padfY = padfX + nVertices; - padfZ = padfX + 2 * nVertices; - - if (!poIREF->GetSADR(poField, nVertices, padfX, padfY, padfZ)) - { - return FALSE; - } - } - } - - return TRUE; -} - -/************************************************************************/ -/* Dump() */ -/* */ -/* Write info about this object to a text file. */ -/************************************************************************/ - -void SDTSRawLine::Dump(FILE *fp) - -{ - fprintf(fp, "SDTSRawLine\n"); - fprintf(fp, " Module=%s, Record#=%d\n", oModId.szModule, oModId.nRecord); - if (oLeftPoly.nRecord != -1) - fprintf(fp, " LeftPoly (Module=%s, Record=%d)\n", oLeftPoly.szModule, - oLeftPoly.nRecord); - if (oRightPoly.nRecord != -1) - fprintf(fp, " RightPoly (Module=%s, Record=%d)\n", oRightPoly.szModule, - oRightPoly.nRecord); - if (oStartNode.nRecord != -1) - fprintf(fp, " StartNode (Module=%s, Record=%d)\n", oStartNode.szModule, - oStartNode.nRecord); - if (oEndNode.nRecord != -1) - fprintf(fp, " EndNode (Module=%s, Record=%d)\n", oEndNode.szModule, - oEndNode.nRecord); - for (int i = 0; i < nAttributes; i++) - fprintf(fp, " Attribute (Module=%s, Record=%d)\n", paoATID[i].szModule, - paoATID[i].nRecord); - - for (int i = 0; i < nVertices; i++) - { - fprintf(fp, " Vertex[%3d] = (%.2f,%.2f,%.2f)\n", i, padfX[i], padfY[i], - padfZ[i]); - } -} - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSLineReader */ -/* */ -/* This is the class used to read a line module. */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSLineReader() */ -/************************************************************************/ - -SDTSLineReader::SDTSLineReader(SDTS_IREF *poIREFIn) : poIREF(poIREFIn) -{ -} - -/************************************************************************/ -/* ~SDTSLineReader() */ -/************************************************************************/ - -SDTSLineReader::~SDTSLineReader() -{ - Close(); -} - -/************************************************************************/ -/* Close() */ -/************************************************************************/ - -void SDTSLineReader::Close() - -{ - oDDFModule.Close(); -} - -/************************************************************************/ -/* Open() */ -/* */ -/* Open the requested line file, and prepare to start reading */ -/* data records. */ -/************************************************************************/ - -int SDTSLineReader::Open(const char *pszFilename) - -{ - return oDDFModule.Open(pszFilename); -} - -/************************************************************************/ -/* GetNextLine() */ -/* */ -/* Fetch the next line feature as an STDSRawLine. */ -/************************************************************************/ - -SDTSRawLine *SDTSLineReader::GetNextLine() - -{ - /* -------------------------------------------------------------------- */ - /* Are we initialized? */ - /* -------------------------------------------------------------------- */ - if (oDDFModule.GetFP() == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Read the record. */ - /* -------------------------------------------------------------------- */ - DDFRecord *poRecord = oDDFModule.ReadRecord(); - - if (poRecord == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Transform into a line feature. */ - /* -------------------------------------------------------------------- */ - SDTSRawLine *poRawLine = new SDTSRawLine(); - - if (poRawLine->Read(poIREF, poRecord)) - { - return poRawLine; - } - - delete poRawLine; - return nullptr; -} - -/************************************************************************/ -/* AttachToPolygons() */ -/* */ -/* Attach line features to all the polygon features they relate */ -/* to. */ -/************************************************************************/ - -/** - Attach lines in this module to their polygons as the first step in - polygon formation. - - See also the SDTSRawPolygon::AssembleRings() method. - - @param poTransfer the SDTSTransfer of this SDTSLineReader, and from - which the related SDTSPolygonReader will be instantiated. - @param iTargetPolyLayer the polygon reader instance number, used to avoid - processing lines for other layers. - -*/ - -void SDTSLineReader::AttachToPolygons(SDTSTransfer *poTransfer, - int iTargetPolyLayer) - -{ - /* -------------------------------------------------------------------- */ - /* We force a filling of the index because when we attach the */ - /* lines we are just providing a pointer back to the line */ - /* features in this readers index. If they aren't cached in */ - /* the index then the pointer will be invalid. */ - /* -------------------------------------------------------------------- */ - FillIndex(); - - /* ==================================================================== */ - /* Loop over all lines, attaching them to the polygons they */ - /* have as right and left faces. */ - /* ==================================================================== */ - Rewind(); - SDTSRawLine *poLine = nullptr; - SDTSPolygonReader *poPolyReader = nullptr; - while ((poLine = reinterpret_cast(GetNextFeature())) != - nullptr) - { - /* -------------------------------------------------------------------- - */ - /* Skip lines with the same left and right polygon face. These */ - /* are dangles, and will not contribute in any useful fashion */ - /* to the resulting polygon. */ - /* -------------------------------------------------------------------- - */ - if (poLine->oLeftPoly.nRecord == poLine->oRightPoly.nRecord) - continue; - - /* -------------------------------------------------------------------- - */ - /* If we don't have our indexed polygon reader yet, try to get */ - /* it now. */ - /* -------------------------------------------------------------------- - */ - if (poPolyReader == nullptr) - { - int iPolyLayer; - - if (poLine->oLeftPoly.nRecord != -1) - { - iPolyLayer = poTransfer->FindLayer(poLine->oLeftPoly.szModule); - } - else /* if( poLine->oRightPoly.nRecord != -1 ) */ - { - iPolyLayer = poTransfer->FindLayer(poLine->oRightPoly.szModule); - } - - if (iPolyLayer == -1) - continue; - - if (iPolyLayer != iTargetPolyLayer) - continue; - - poPolyReader = reinterpret_cast( - poTransfer->GetLayerIndexedReader(iPolyLayer)); - - if (poPolyReader == nullptr) - return; - } - - /* -------------------------------------------------------------------- - */ - /* Attach line to right and/or left polygons. */ - /* -------------------------------------------------------------------- - */ - if (poLine->oLeftPoly.nRecord != -1) - { - SDTSRawPolygon *poPoly = reinterpret_cast( - poPolyReader->GetIndexedFeatureRef(poLine->oLeftPoly.nRecord)); - if (poPoly != nullptr) - poPoly->AddEdge(poLine); - } - - if (poLine->oRightPoly.nRecord != -1) - { - SDTSRawPolygon *poPoly = reinterpret_cast( - poPolyReader->GetIndexedFeatureRef(poLine->oRightPoly.nRecord)); - - if (poPoly != nullptr) - poPoly->AddEdge(poLine); - } - } -} diff --git a/frmts/sdts/sdtspointreader.cpp b/frmts/sdts/sdtspointreader.cpp deleted file mode 100644 index 6b3319c723cf..000000000000 --- a/frmts/sdts/sdtspointreader.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTSPointReader and SDTSRawPoint classes. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSRawPoint */ -/* */ -/* This is a simple class for holding the data related with a */ -/* point feature. */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSRawPoint() */ -/************************************************************************/ - -SDTSRawPoint::SDTSRawPoint() : dfX(0.0), dfY(0.0), dfZ(0.0) -{ - nAttributes = 0; -} - -/************************************************************************/ -/* ~STDSRawPoint() */ -/************************************************************************/ - -SDTSRawPoint::~SDTSRawPoint() -{ -} - -/************************************************************************/ -/* Read() */ -/* */ -/* Read a record from the passed SDTSPointReader, and assign the */ -/* values from that record to this point. This is the bulk of */ -/* the work in this whole file. */ -/************************************************************************/ - -int SDTSRawPoint::Read(SDTS_IREF *poIREF, DDFRecord *poRecord) - -{ - /* ==================================================================== */ - /* Loop over fields in this record, looking for those we */ - /* recognise, and need. */ - /* ==================================================================== */ - for (int iField = 0; iField < poRecord->GetFieldCount(); iField++) - { - DDFField *poField = poRecord->GetField(iField); - if (poField == nullptr) - return FALSE; - DDFFieldDefn *poFieldDefn = poField->GetFieldDefn(); - if (poFieldDefn == nullptr) - return FALSE; - - const char *pszFieldName = poFieldDefn->GetName(); - - if (EQUAL(pszFieldName, "PNTS")) - oModId.Set(poField); - - else if (EQUAL(pszFieldName, "ATID")) - ApplyATID(poField); - - else if (EQUAL(pszFieldName, "ARID")) - { - oAreaId.Set(poField); - } - else if (EQUAL(pszFieldName, "SADR")) - { - poIREF->GetSADR(poField, 1, &dfX, &dfY, &dfZ); - } - } - - return TRUE; -} - -/************************************************************************/ -/* Dump() */ -/************************************************************************/ - -void SDTSRawPoint::Dump(FILE *fp) - -{ - fprintf(fp, "SDTSRawPoint %s: ", oModId.GetName()); - - if (oAreaId.nRecord != -1) - fprintf(fp, " AreaId=%s", oAreaId.GetName()); - - for (int i = 0; i < nAttributes; i++) - fprintf(fp, " ATID[%d]=%s", i, paoATID[i].GetName()); - - fprintf(fp, " Vertex = (%.2f,%.2f,%.2f)\n", dfX, dfY, dfZ); -} - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSPointReader */ -/* */ -/* This is the class used to read a point module. */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSPointReader() */ -/************************************************************************/ - -SDTSPointReader::SDTSPointReader(SDTS_IREF *poIREFIn) : poIREF(poIREFIn) -{ -} - -/************************************************************************/ -/* ~SDTSLineReader() */ -/************************************************************************/ - -SDTSPointReader::~SDTSPointReader() -{ -} - -/************************************************************************/ -/* Close() */ -/************************************************************************/ - -void SDTSPointReader::Close() - -{ - oDDFModule.Close(); -} - -/************************************************************************/ -/* Open() */ -/* */ -/* Open the requested line file, and prepare to start reading */ -/* data records. */ -/************************************************************************/ - -int SDTSPointReader::Open(const char *pszFilename) - -{ - return oDDFModule.Open(pszFilename); -} - -/************************************************************************/ -/* GetNextPoint() */ -/* */ -/* Fetch the next feature as an STDSRawPoint. */ -/************************************************************************/ - -SDTSRawPoint *SDTSPointReader::GetNextPoint() - -{ - /* -------------------------------------------------------------------- */ - /* Read a record. */ - /* -------------------------------------------------------------------- */ - if (oDDFModule.GetFP() == nullptr) - return nullptr; - - DDFRecord *poRecord = oDDFModule.ReadRecord(); - - if (poRecord == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Transform into a point feature. */ - /* -------------------------------------------------------------------- */ - SDTSRawPoint *poRawPoint = new SDTSRawPoint(); - - if (poRawPoint->Read(poIREF, poRecord)) - { - return poRawPoint; - } - - delete poRawPoint; - return nullptr; -} diff --git a/frmts/sdts/sdtspolygonreader.cpp b/frmts/sdts/sdtspolygonreader.cpp deleted file mode 100644 index 01cea6efc248..000000000000 --- a/frmts/sdts/sdtspolygonreader.cpp +++ /dev/null @@ -1,619 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTSPolygonReader and SDTSRawPolygon classes. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -#include - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSRawPolygon */ -/* */ -/* This is a simple class for holding the data related with a */ -/* polygon feature. */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSRawPolygon() */ -/************************************************************************/ - -SDTSRawPolygon::SDTSRawPolygon() - : nEdges(0), papoEdges(nullptr), nRings(0), nVertices(0), - panRingStart(nullptr), padfX(nullptr), padfY(nullptr), padfZ(nullptr) -{ - nAttributes = 0; -} - -/************************************************************************/ -/* ~SDTSRawPolygon() */ -/************************************************************************/ - -SDTSRawPolygon::~SDTSRawPolygon() - -{ - CPLFree(papoEdges); - CPLFree(panRingStart); - CPLFree(padfX); - CPLFree(padfY); - CPLFree(padfZ); -} - -/************************************************************************/ -/* Read() */ -/* */ -/* Read a record from the passed SDTSPolygonReader, and assign the */ -/* values from that record to this object. This is the bulk of */ -/* the work in this whole file. */ -/************************************************************************/ - -int SDTSRawPolygon::Read(DDFRecord *poRecord) - -{ - /* ==================================================================== */ - /* Loop over fields in this record, looking for those we */ - /* recognise, and need. */ - /* ==================================================================== */ - for (int iField = 0; iField < poRecord->GetFieldCount(); iField++) - { - DDFField *poField = poRecord->GetField(iField); - if (poField == nullptr) - return FALSE; - DDFFieldDefn *poFieldDefn = poField->GetFieldDefn(); - if (poFieldDefn == nullptr) - return FALSE; - - const char *pszFieldName = poFieldDefn->GetName(); - - if (EQUAL(pszFieldName, "POLY")) - { - oModId.Set(poField); - } - - else if (EQUAL(pszFieldName, "ATID")) - { - ApplyATID(poField); - } - } - - return TRUE; -} - -/************************************************************************/ -/* AddEdge() */ -/************************************************************************/ - -void SDTSRawPolygon::AddEdge(SDTSRawLine *poNewLine) - -{ - nEdges++; - - papoEdges = reinterpret_cast( - CPLRealloc(papoEdges, sizeof(void *) * nEdges)); - papoEdges[nEdges - 1] = poNewLine; -} - -/************************************************************************/ -/* AddEdgeToRing() */ -/************************************************************************/ - -void SDTSRawPolygon::AddEdgeToRing(int nVertToAdd, double *padfXToAdd, - double *padfYToAdd, double *padfZToAdd, - int bReverse, int bDropVertex) - -{ - int iStart = 0; - int iEnd = nVertToAdd - 1; - int iStep = 1; - - if (bDropVertex && bReverse) - { - iStart = nVertToAdd - 2; - iEnd = 0; - iStep = -1; - } - else if (bDropVertex && !bReverse) - { - iStart = 1; - iEnd = nVertToAdd - 1; - iStep = 1; - } - else if (!bDropVertex && !bReverse) - { - iStart = 0; - iEnd = nVertToAdd - 1; - iStep = 1; - } - else if (!bDropVertex && bReverse) - { - iStart = nVertToAdd - 1; - iEnd = 0; - iStep = -1; - } - - for (int i = iStart; i != (iEnd + iStep); i += iStep) - { - padfX[nVertices] = padfXToAdd[i]; - padfY[nVertices] = padfYToAdd[i]; - padfZ[nVertices] = padfZToAdd[i]; - - nVertices++; - } -} - -/************************************************************************/ -/* AssembleRings() */ -/************************************************************************/ - -/** - * Form border lines (arcs) into outer and inner rings. - * - * See SDTSPolygonReader::AssemblePolygons() for a simple one step process - * to assembling geometry for all polygons in a transfer. - * - * This method will assemble the lines attached to a polygon into - * an outer ring, and zero or more inner rings. Before calling it is - * necessary that all the lines associated with this polygon have already - * been attached. Normally this is accomplished by calling - * SDTSLineReader::AttachToPolygons() on all line layers that might - * contain edges related to this layer. - * - * This method then forms the lines into rings. Rings are formed by: - *
    - *
  1. Take a previously unconsumed line, and start a ring with it. Mark - * it as consumed, and keep track of its start and end node ids as - * being the start and end node ids of the ring. - *
  2. If the rings start id is the same as the end node id then this ring - * is completely formed, return to step 1. - *
  3. Search all unconsumed lines for a line with the same start or end - * node id as the rings current node id. If none are found then the - * assembly has failed. Return to step 1 but report failure on - * completion. - *
  4. Once found, add the line to the current ring, dropping the duplicated - * vertex and reverse order if necessary. Mark the line as consumed, - * and update the rings end node id accordingly. - *
  5. go to step 2. - *
- * - * Once ring assembly from lines is complete, another pass is made to - * order the rings such that the exterior ring is first, the first ring - * has counter-clockwise vertex ordering and the inner rings have clockwise - * vertex ordering. This is accomplished based on the assumption that the - * outer ring has the largest area, and using the +/- sign of area to establish - * direction of rings. - * - * @return TRUE if all rings assembled without problems or FALSE if a problem - * occurred. If a problem occurs rings are still formed from all lines, but - * some of the rings will not be closed, and rings will have no particular - * order or direction. - */ - -int SDTSRawPolygon::AssembleRings() - -{ - if (nRings > 0) - return TRUE; - - if (nEdges == 0) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Setup array of line markers indicating if they have been */ - /* added to a ring yet. */ - /* -------------------------------------------------------------------- */ - int nRemainingEdges = nEdges; - - int *panEdgeConsumed = - reinterpret_cast(CPLCalloc(sizeof(int), nEdges)); - - /* -------------------------------------------------------------------- */ - /* Allocate ring arrays. */ - /* -------------------------------------------------------------------- */ - panRingStart = reinterpret_cast(CPLMalloc(sizeof(int) * nEdges)); - - nVertices = 0; - for (int iEdge = 0; iEdge < nEdges; iEdge++) - { - if (papoEdges[iEdge]->nVertices < 2) - { - panEdgeConsumed[iEdge] = TRUE; - nRemainingEdges--; - } - else - { - nVertices += papoEdges[iEdge]->nVertices; - } - } - - padfX = reinterpret_cast(CPLMalloc(sizeof(double) * nVertices)); - padfY = reinterpret_cast(CPLMalloc(sizeof(double) * nVertices)); - padfZ = reinterpret_cast(CPLMalloc(sizeof(double) * nVertices)); - - nVertices = 0; - - /* ==================================================================== */ - /* Loop generating rings. */ - /* ==================================================================== */ - bool bSuccess = true; - - while (nRemainingEdges > 0) - { - /* -------------------------------------------------------------------- - */ - /* Find the first unconsumed edge. */ - /* -------------------------------------------------------------------- - */ - int iEdge = 0; - for (; panEdgeConsumed[iEdge]; iEdge++) - { - } - - SDTSRawLine *poEdge = papoEdges[iEdge]; - - /* -------------------------------------------------------------------- - */ - /* Start a new ring, copying in the current line directly */ - /* -------------------------------------------------------------------- - */ - panRingStart[nRings++] = nVertices; - - AddEdgeToRing(poEdge->nVertices, poEdge->padfX, poEdge->padfY, - poEdge->padfZ, FALSE, FALSE); - - panEdgeConsumed[iEdge] = TRUE; - nRemainingEdges--; - - const int nStartNode = poEdge->oStartNode.nRecord; - int nLinkNode = poEdge->oEndNode.nRecord; - - /* ==================================================================== - */ - /* Loop adding edges to this ring until we make a whole pass */ - /* within finding anything to add. */ - /* ==================================================================== - */ - bool bWorkDone = true; - - while (nLinkNode != nStartNode && nRemainingEdges > 0 && bWorkDone) - { - bWorkDone = false; - - for (iEdge = 0; iEdge < nEdges; iEdge++) - { - if (panEdgeConsumed[iEdge]) - continue; - - poEdge = papoEdges[iEdge]; - if (poEdge->oStartNode.nRecord == nLinkNode) - { - AddEdgeToRing(poEdge->nVertices, poEdge->padfX, - poEdge->padfY, poEdge->padfZ, FALSE, TRUE); - nLinkNode = poEdge->oEndNode.nRecord; - } - else if (poEdge->oEndNode.nRecord == nLinkNode) - { - AddEdgeToRing(poEdge->nVertices, poEdge->padfX, - poEdge->padfY, poEdge->padfZ, TRUE, TRUE); - nLinkNode = poEdge->oStartNode.nRecord; - } - else - { - continue; - } - - panEdgeConsumed[iEdge] = TRUE; - nRemainingEdges--; - bWorkDone = true; - } - } - - /* -------------------------------------------------------------------- - */ - /* Did we fail to complete the ring? */ - /* -------------------------------------------------------------------- - */ - if (nLinkNode != nStartNode) - bSuccess = false; - } /* next ring */ - - CPLFree(panEdgeConsumed); - - if (!bSuccess) - return bSuccess; - - /* ==================================================================== */ - /* Compute the area of each ring. The sign will be positive */ - /* for counter clockwise rings, otherwise negative. */ - /* */ - /* The algorithm used in this function was taken from _Graphics */ - /* Gems II_, James Arvo, 1991, Academic Press, Inc., section 1.1, */ - /* "The Area of a Simple Polygon", Jon Rokne, pp. 5-6. */ - /* ==================================================================== */ - double dfMaxArea = 0.0; - int iBiggestRing = -1; - - double *padfRingArea = - reinterpret_cast(CPLCalloc(sizeof(double), nRings)); - - for (int iRing = 0; iRing < nRings; iRing++) - { - int nRingVertices; - if (iRing == nRings - 1) - nRingVertices = nVertices - panRingStart[iRing]; - else - nRingVertices = panRingStart[iRing + 1] - panRingStart[iRing]; - - double dfSum1 = 0.0; - double dfSum2 = 0.0; - for (int i = panRingStart[iRing]; - i < panRingStart[iRing] + nRingVertices - 1; i++) - { - dfSum1 += padfX[i] * padfY[i + 1]; - dfSum2 += padfY[i] * padfX[i + 1]; - } - - padfRingArea[iRing] = (dfSum1 - dfSum2) / 2; - - if (std::abs(padfRingArea[iRing]) > dfMaxArea) - { - dfMaxArea = std::abs(padfRingArea[iRing]); - iBiggestRing = iRing; - } - } - - if (iBiggestRing < 0) - { - CPLFree(padfRingArea); - return FALSE; - } - - /* ==================================================================== */ - /* Make a new set of vertices, and copy the largest ring into */ - /* it, adjusting the direction if necessary to ensure that this */ - /* outer ring is counter clockwise. */ - /* ==================================================================== */ - double *padfXRaw = padfX; - double *padfYRaw = padfY; - double *padfZRaw = padfZ; - int *panRawRingStart = panRingStart; - int nRawVertices = nVertices; - int nRawRings = nRings; - - padfX = reinterpret_cast(CPLMalloc(sizeof(double) * nVertices)); - padfY = reinterpret_cast(CPLMalloc(sizeof(double) * nVertices)); - padfZ = reinterpret_cast(CPLMalloc(sizeof(double) * nVertices)); - panRingStart = reinterpret_cast(CPLMalloc(sizeof(int) * nRawRings)); - nVertices = 0; - nRings = 0; - - int nRingVertices; - if (iBiggestRing == nRawRings - 1) - nRingVertices = nRawVertices - panRawRingStart[iBiggestRing]; - else - nRingVertices = - panRawRingStart[iBiggestRing + 1] - panRawRingStart[iBiggestRing]; - - panRingStart[nRings++] = 0; - AddEdgeToRing(nRingVertices, padfXRaw + panRawRingStart[iBiggestRing], - padfYRaw + panRawRingStart[iBiggestRing], - padfZRaw + panRawRingStart[iBiggestRing], - padfRingArea[iBiggestRing] < 0.0, FALSE); - - /* ==================================================================== */ - /* Add the rest of the rings, which must be holes, in clockwise */ - /* order. */ - /* ==================================================================== */ - for (int iRing = 0; iRing < nRawRings; iRing++) - { - if (iRing == iBiggestRing) - continue; - - if (iRing == nRawRings - 1) - nRingVertices = nRawVertices - panRawRingStart[iRing]; - else - nRingVertices = panRawRingStart[iRing + 1] - panRawRingStart[iRing]; - - panRingStart[nRings++] = nVertices; - AddEdgeToRing(nRingVertices, padfXRaw + panRawRingStart[iRing], - padfYRaw + panRawRingStart[iRing], - padfZRaw + panRawRingStart[iRing], - padfRingArea[iRing] > 0.0, FALSE); - } - - /* -------------------------------------------------------------------- */ - /* Cleanup */ - /* -------------------------------------------------------------------- */ - CPLFree(padfXRaw); - CPLFree(padfYRaw); - CPLFree(padfZRaw); - CPLFree(padfRingArea); - CPLFree(panRawRingStart); - - CPLFree(papoEdges); - papoEdges = nullptr; - nEdges = 0; - - return TRUE; -} - -/************************************************************************/ -/* Dump() */ -/************************************************************************/ - -void SDTSRawPolygon::Dump(FILE *fp) - -{ - fprintf(fp, "SDTSRawPolygon %s: ", oModId.GetName()); - - for (int i = 0; i < nAttributes; i++) - fprintf(fp, " ATID[%d]=%s", i, paoATID[i].GetName()); - - fprintf(fp, "\n"); -} - -/************************************************************************/ -/* ==================================================================== */ -/* SDTSPolygonReader */ -/* */ -/* This is the class used to read a Polygon module. */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SDTSPolygonReader() */ -/************************************************************************/ - -SDTSPolygonReader::SDTSPolygonReader() : bRingsAssembled(FALSE) -{ -} - -/************************************************************************/ -/* ~SDTSPolygonReader() */ -/************************************************************************/ - -SDTSPolygonReader::~SDTSPolygonReader() -{ -} - -/************************************************************************/ -/* Close() */ -/************************************************************************/ - -void SDTSPolygonReader::Close() - -{ - oDDFModule.Close(); -} - -/************************************************************************/ -/* Open() */ -/* */ -/* Open the requested line file, and prepare to start reading */ -/* data records. */ -/************************************************************************/ - -int SDTSPolygonReader::Open(const char *pszFilename) - -{ - return oDDFModule.Open(pszFilename); -} - -/************************************************************************/ -/* GetNextPolygon() */ -/* */ -/* Fetch the next feature as an STDSRawPolygon. */ -/************************************************************************/ - -SDTSRawPolygon *SDTSPolygonReader::GetNextPolygon() - -{ - /* -------------------------------------------------------------------- */ - /* Read a record. */ - /* -------------------------------------------------------------------- */ - if (oDDFModule.GetFP() == nullptr) - return nullptr; - - DDFRecord *poRecord = oDDFModule.ReadRecord(); - - if (poRecord == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Transform into a Polygon feature. */ - /* -------------------------------------------------------------------- */ - SDTSRawPolygon *poRawPolygon = new SDTSRawPolygon(); - - if (poRawPolygon->Read(poRecord)) - { - return poRawPolygon; - } - - delete poRawPolygon; - return nullptr; -} - -/************************************************************************/ -/* AssembleRings() */ -/************************************************************************/ - -/** - * Assemble geometry for a polygon transfer. - * - * This method takes care of attaching lines from all the line layers in - * this transfer to this polygon layer, assembling the lines into rings on - * the polygons, and then cleaning up unnecessary intermediate results. - * - * Currently this method will leave the line layers rewound to the beginning - * but indexed, and the polygon layer rewound but indexed. In the future - * it may restore reading positions, and possibly flush line indexes if they - * were not previously indexed. - * - * This method does nothing if the rings have already been assembled on - * this layer using this method. - * - * See SDTSRawPolygon::AssembleRings() for more information on how the lines - * are assembled into rings. - * - * @param poTransfer the SDTSTransfer that this reader is a part of. Used - * to get a list of line layers that might be needed. - * @param iPolyLayer the polygon reader instance number, used to avoid - * processing lines for other layers. - */ - -void SDTSPolygonReader::AssembleRings(SDTSTransfer *poTransfer, int iPolyLayer) - -{ - if (bRingsAssembled) - return; - - bRingsAssembled = TRUE; - - /* -------------------------------------------------------------------- */ - /* To write polygons we need to build them from their related */ - /* arcs. We don't know off hand which arc (line) layers */ - /* contribute so we process all line layers, attaching them to */ - /* polygons as appropriate. */ - /* -------------------------------------------------------------------- */ - for (int iLineLayer = 0; iLineLayer < poTransfer->GetLayerCount(); - iLineLayer++) - { - if (poTransfer->GetLayerType(iLineLayer) != SLTLine) - continue; - - SDTSLineReader *poLineReader = reinterpret_cast( - poTransfer->GetLayerIndexedReader(iLineLayer)); - if (poLineReader == nullptr) - continue; - - poLineReader->AttachToPolygons(poTransfer, iPolyLayer); - poLineReader->Rewind(); - } - - if (!IsIndexed()) - return; - - /* -------------------------------------------------------------------- */ - /* Scan all polygons indexed on this reader, and assemble their */ - /* rings. */ - /* -------------------------------------------------------------------- */ - Rewind(); - - SDTSFeature *poFeature = nullptr; - while ((poFeature = GetNextFeature()) != nullptr) - { - SDTSRawPolygon *poPoly = reinterpret_cast(poFeature); - - poPoly->AssembleRings(); - } - - Rewind(); -} diff --git a/frmts/sdts/sdtsrasterreader.cpp b/frmts/sdts/sdtsrasterreader.cpp deleted file mode 100644 index bcb9d4bd32bc..000000000000 --- a/frmts/sdts/sdtsrasterreader.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTSRasterReader class. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2008-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -#include - -/************************************************************************/ -/* SDTSRasterReader() */ -/************************************************************************/ - -SDTSRasterReader::SDTSRasterReader() - : nXSize(0), nYSize(0), nXBlockSize(0), nYBlockSize(0), nXStart(0), - nYStart(0) -{ - strcpy(szINTR, "CE"); - memset(szModule, 0, sizeof(szModule)); - memset(adfTransform, 0, sizeof(adfTransform)); - memset(szFMT, 0, sizeof(szFMT)); - memset(szUNITS, 0, sizeof(szUNITS)); - memset(szLabel, 0, sizeof(szLabel)); -} - -/************************************************************************/ -/* ~SDTSRasterReader() */ -/************************************************************************/ - -SDTSRasterReader::~SDTSRasterReader() -{ -} - -/************************************************************************/ -/* Close() */ -/************************************************************************/ - -void SDTSRasterReader::Close() - -{ - oDDFModule.Close(); -} - -/************************************************************************/ -/* Open() */ -/* */ -/* Open the requested cell file, and collect required */ -/* information. */ -/************************************************************************/ - -int SDTSRasterReader::Open(SDTS_CATD *poCATD, SDTS_IREF *poIREF, - const char *pszModule) - -{ - snprintf(szModule, sizeof(szModule), "%s", pszModule); - - /* ==================================================================== */ - /* Search the LDEF module for the requested cell module. */ - /* ==================================================================== */ - - /* -------------------------------------------------------------------- */ - /* Open the LDEF module, and report failure if it is missing. */ - /* -------------------------------------------------------------------- */ - if (poCATD->GetModuleFilePath("LDEF") == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find LDEF entry in CATD module ... " - "can't treat as raster.\n"); - return FALSE; - } - - DDFModule oLDEF; - if (!oLDEF.Open(poCATD->GetModuleFilePath("LDEF"))) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Read each record, till we find what we want. */ - /* -------------------------------------------------------------------- */ - DDFRecord *poRecord = nullptr; - while ((poRecord = oLDEF.ReadRecord()) != nullptr) - { - const char *pszCandidateModule = - poRecord->GetStringSubfield("LDEF", 0, "CMNM", 0); - if (pszCandidateModule == nullptr) - { - poRecord = nullptr; - break; - } - if (EQUAL(pszCandidateModule, pszModule)) - break; - } - - if (poRecord == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find module `%s' in LDEF file.\n", pszModule); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Extract raster dimensions, and origin offset (0/1). */ - /* -------------------------------------------------------------------- */ - nXSize = poRecord->GetIntSubfield("LDEF", 0, "NCOL", 0); - nYSize = poRecord->GetIntSubfield("LDEF", 0, "NROW", 0); - - nXStart = poRecord->GetIntSubfield("LDEF", 0, "SOCI", 0); - nYStart = poRecord->GetIntSubfield("LDEF", 0, "SORI", 0); - - /* -------------------------------------------------------------------- */ - /* Get the point in the pixel that the origin defines. We only */ - /* support top left and center. */ - /* -------------------------------------------------------------------- */ - const char *pszINTR = poRecord->GetStringSubfield("LDEF", 0, "INTR", 0); - if (pszINTR == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find INTR subfield of LDEF field"); - return FALSE; - } - snprintf(szINTR, sizeof(szINTR), "%s", pszINTR); - if (EQUAL(szINTR, "")) - snprintf(szINTR, sizeof(szINTR), "%s", "CE"); - - if (!EQUAL(szINTR, "CE") && !EQUAL(szINTR, "TL")) - { - CPLError(CE_Warning, CPLE_AppDefined, - "Unsupported INTR value of `%s', assume CE.\n" - "Positions may be off by one pixel.\n", - szINTR); - snprintf(szINTR, sizeof(szINTR), "%s", "CE"); - } - - /* -------------------------------------------------------------------- */ - /* Record the LDEF record number we used so we can find the */ - /* corresponding RSDF record. */ - /* -------------------------------------------------------------------- */ - int nLDEF_RCID = poRecord->GetIntSubfield("LDEF", 0, "RCID", 0); - - oLDEF.Close(); - - /* ==================================================================== */ - /* Search the RSDF module for the requested cell module. */ - /* ==================================================================== */ - - /* -------------------------------------------------------------------- */ - /* Open the RSDF module, and report failure if it is missing. */ - /* -------------------------------------------------------------------- */ - if (poCATD->GetModuleFilePath("RSDF") == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find RSDF entry in CATD module ... " - "can't treat as raster.\n"); - return FALSE; - } - - DDFModule oRSDF; - if (!oRSDF.Open(poCATD->GetModuleFilePath("RSDF"))) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Read each record, till we find what we want. */ - /* -------------------------------------------------------------------- */ - while ((poRecord = oRSDF.ReadRecord()) != nullptr) - { - if (poRecord->GetIntSubfield("LYID", 0, "RCID", 0) == nLDEF_RCID) - break; - } - - if (poRecord == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find LDEF:%d record in RSDF file.\n", nLDEF_RCID); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Establish the raster pixel/line to georef transformation. */ - /* -------------------------------------------------------------------- */ - - if (poRecord->FindField("SADR") == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find SADR field in RSDF record.\n"); - return FALSE; - } - - double dfZ; - poIREF->GetSADR(poRecord->FindField("SADR"), 1, adfTransform + 0, - adfTransform + 3, &dfZ); - - adfTransform[1] = poIREF->dfXRes; - adfTransform[2] = 0.0; - adfTransform[4] = 0.0; - adfTransform[5] = -1 * poIREF->dfYRes; - - /* -------------------------------------------------------------------- */ - /* If the origin is the center of the pixel, then shift it back */ - /* half a pixel to the top left of the top left. */ - /* -------------------------------------------------------------------- */ - if (EQUAL(szINTR, "CE")) - { - adfTransform[0] -= adfTransform[1] * 0.5; - adfTransform[3] -= adfTransform[5] * 0.5; - } - - /* -------------------------------------------------------------------- */ - /* Verify some other assumptions. */ - /* -------------------------------------------------------------------- */ - const char *pszString = poRecord->GetStringSubfield("RSDF", 0, "OBRP", 0); - if (pszString == nullptr) - pszString = ""; - if (!EQUAL(pszString, "G2")) - { - CPLError(CE_Failure, CPLE_AppDefined, - "OBRP value of `%s' not expected 2D raster code (G2).\n", - pszString); - return FALSE; - } - - pszString = poRecord->GetStringSubfield("RSDF", 0, "SCOR", 0); - if (pszString == nullptr) - pszString = ""; - if (!EQUAL(pszString, "TL")) - { - CPLError(CE_Warning, CPLE_AppDefined, - "SCOR (origin) is `%s' instead of expected top left.\n" - "Georef coordinates will likely be incorrect.\n", - pszString); - } - - oRSDF.Close(); - - /* -------------------------------------------------------------------- */ - /* For now we will assume that the block size is one scanline. */ - /* We will blow a gasket later while reading the cell file if */ - /* this isn't the case. */ - /* */ - /* This isn't a very flexible raster implementation! */ - /* -------------------------------------------------------------------- */ - nXBlockSize = nXSize; - nYBlockSize = 1; - - /* ==================================================================== */ - /* Fetch the data type used for the raster, and the units from */ - /* the data dictionary/schema record (DDSH). */ - /* ==================================================================== */ - - /* -------------------------------------------------------------------- */ - /* Open the DDSH module, and report failure if it is missing. */ - /* -------------------------------------------------------------------- */ - if (poCATD->GetModuleFilePath("DDSH") == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find DDSH entry in CATD module ... " - "can't treat as raster.\n"); - return FALSE; - } - - DDFModule oDDSH; - if (!oDDSH.Open(poCATD->GetModuleFilePath("DDSH"))) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Read each record, till we find what we want. */ - /* -------------------------------------------------------------------- */ - while ((poRecord = oDDSH.ReadRecord()) != nullptr) - { - const char *pszName = poRecord->GetStringSubfield("DDSH", 0, "NAME", 0); - if (pszName == nullptr) - { - poRecord = nullptr; - break; - } - if (EQUAL(pszName, pszModule)) - break; - } - - if (poRecord == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find DDSH record for %s.\n", pszModule); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Get some values we are interested in. */ - /* -------------------------------------------------------------------- */ - if (poRecord->GetStringSubfield("DDSH", 0, "FMT", 0) != nullptr) - snprintf(szFMT, sizeof(szFMT), "%s", - poRecord->GetStringSubfield("DDSH", 0, "FMT", 0)); - else - snprintf(szFMT, sizeof(szFMT), "%s", "BI16"); - if (!EQUAL(szFMT, "BI16") && !EQUAL(szFMT, "BFP32")) - { - CPLError(CE_Failure, CPLE_AppDefined, "Unhandled FMT=%s", szFMT); - return FALSE; - } - - if (poRecord->GetStringSubfield("DDSH", 0, "UNIT", 0) != nullptr) - snprintf(szUNITS, sizeof(szUNITS), "%s", - poRecord->GetStringSubfield("DDSH", 0, "UNIT", 0)); - else - snprintf(szUNITS, sizeof(szUNITS), "%s", "METERS"); - - if (poRecord->GetStringSubfield("DDSH", 0, "ATLB", 0) != nullptr) - snprintf(szLabel, sizeof(szLabel), "%s", - poRecord->GetStringSubfield("DDSH", 0, "ATLB", 0)); - else - strcpy(szLabel, ""); - - /* -------------------------------------------------------------------- */ - /* Open the cell file. */ - /* -------------------------------------------------------------------- */ - return oDDFModule.Open(poCATD->GetModuleFilePath(pszModule)); -} - -/************************************************************************/ -/* GetBlock() */ -/* */ -/* Read a requested block of raster data from the file. */ -/* */ -/* Currently we will always use sequential access. In the */ -/* future we should modify the iso8211 library to support */ -/* seeking, and modify this to seek directly to the right */ -/* record once its location is known. */ -/************************************************************************/ - -/** - Read a block of raster data from the file. - - @param nXOffset X block offset into the file. Normally zero for scanline - organized raster files. - - @param nYOffset Y block offset into the file. Normally the scanline offset - from top of raster for scanline organized raster files. - - @param pData pointer to GInt16 (signed short) buffer of data into which to - read the raster. - - @return TRUE on success and FALSE on error. - - */ - -int SDTSRasterReader::GetBlock(CPL_UNUSED int nXOffset, int nYOffset, - void *pData) -{ - CPLAssert(nXOffset == 0); - - /* -------------------------------------------------------------------- */ - /* Analyse the datatype. */ - /* -------------------------------------------------------------------- */ - CPLAssert(EQUAL(szFMT, "BI16") || EQUAL(szFMT, "BFP32")); - - int nBytesPerValue; - if (EQUAL(szFMT, "BI16")) - nBytesPerValue = 2; - else - nBytesPerValue = 4; - - DDFRecord *poRecord = nullptr; - - for (int iTry = 0; iTry < 2; iTry++) - { - /* -------------------------------------------------------------------- - */ - /* Read through till we find the desired record. */ - /* -------------------------------------------------------------------- - */ - CPLErrorReset(); - while ((poRecord = oDDFModule.ReadRecord()) != nullptr) - { - if (poRecord->GetIntSubfield("CELL", 0, "ROWI", 0) == - nYOffset + nYStart) - { - break; - } - } - - if (CPLGetLastErrorType() == CE_Failure) - return FALSE; - - /* -------------------------------------------------------------------- - */ - /* If we didn't get what we needed just start over. */ - /* -------------------------------------------------------------------- - */ - if (poRecord == nullptr) - { - if (iTry == 0) - oDDFModule.Rewind(); - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot read scanline %d. Raster access failed.\n", - nYOffset); - return FALSE; - } - } - else - { - break; - } - } - - /* -------------------------------------------------------------------- */ - /* Validate the records size. Does it represent exactly one */ - /* scanline? */ - /* -------------------------------------------------------------------- */ - DDFField *poCVLS = poRecord->FindField("CVLS"); - if (poCVLS == nullptr) - return FALSE; - - if (poCVLS->GetRepeatCount() != nXSize) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cell record is %d long, but we expected %d, the number\n" - "of pixels in a scanline. Raster access failed.\n", - poCVLS->GetRepeatCount(), nXSize); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Does the CVLS field consist of exactly 1 B(16) field? */ - /* -------------------------------------------------------------------- */ - if (poCVLS->GetDataSize() < nBytesPerValue * nXSize || - poCVLS->GetDataSize() > nBytesPerValue * nXSize + 1) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cell record is not of expected format. Raster access " - "failed.\n"); - - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Copy the data to the application buffer, and byte swap if */ - /* required. */ - /* -------------------------------------------------------------------- */ - memcpy(pData, poCVLS->GetData(), - static_cast(nXSize) * nBytesPerValue); - -#ifdef CPL_LSB - if (nBytesPerValue == 2) - { - for (int i = 0; i < nXSize; i++) - { - reinterpret_cast(pData)[i] = - CPL_MSBWORD16(reinterpret_cast(pData)[i]); - } - } - else - { - for (int i = 0; i < nXSize; i++) - { - CPL_MSBPTR32(reinterpret_cast(pData) + i * 4); - } - } -#endif - - return TRUE; -} - -/************************************************************************/ -/* GetTransform() */ -/************************************************************************/ - -/** - Fetch the transformation between pixel/line coordinates and georeferenced - coordinates. - - @param padfTransformOut pointer to an array of six doubles which will be - filled with the georeferencing transform. - - @return TRUE is returned, indicating success. - - The padfTransformOut array consists of six values. The pixel/line coordinate - (Xp,Yp) can be related to a georeferenced coordinate (Xg,Yg) or (Easting, - Northing). - -
-  Xg = padfTransformOut[0] + Xp * padfTransform[1] + Yp * padfTransform[2]
-  Yg = padfTransformOut[3] + Xp * padfTransform[4] + Yp * padfTransform[5]
-  
- - In other words, for a north up image the top left corner of the top left - pixel is at georeferenced coordinate (padfTransform[0],padfTransform[3]) - the pixel width is padfTransform[1], the pixel height is padfTransform[5] - and padfTransform[2] and padfTransform[4] will be zero. - - */ - -int SDTSRasterReader::GetTransform(double *padfTransformOut) - -{ - memcpy(padfTransformOut, adfTransform, sizeof(double) * 6); - - return TRUE; -} - -/************************************************************************/ -/* GetRasterType() */ -/************************************************************************/ - -/** - * Fetch the pixel data type. - * - * Returns one of SDTS_RT_INT16 (1) or SDTS_RT_FLOAT32 (6) indicating the - * type of buffer that should be passed to GetBlock(). - */ - -int SDTSRasterReader::GetRasterType() - -{ - if (EQUAL(szFMT, "BFP32")) - return SDTS_RT_FLOAT32; - - return SDTS_RT_INT16; -} - -/************************************************************************/ -/* GetMinMax() */ -/************************************************************************/ - -/** - * Fetch the minimum and maximum raster values that occur in the file. - * - * Note this operation current results in a scan of the entire file. - * - * @param pdfMin variable in which the minimum value encountered is returned. - * @param pdfMax variable in which the maximum value encountered is returned. - * @param dfNoData a value to ignore when computing min/max, defaults to - * -32766. - * - * @return TRUE on success, or FALSE if an error occurs. - */ - -int SDTSRasterReader::GetMinMax(double *pdfMin, double *pdfMax, double dfNoData) - -{ - CPLAssert(GetBlockXSize() == GetXSize() && GetBlockYSize() == 1); - - bool bFirst = true; - const bool b32Bit = GetRasterType() == SDTS_RT_FLOAT32; - void *pBuffer = CPLMalloc(sizeof(float) * GetXSize()); - - for (int iLine = 0; iLine < GetYSize(); iLine++) - { - if (!GetBlock(0, iLine, pBuffer)) - { - CPLFree(pBuffer); - return FALSE; - } - - for (int iPixel = 0; iPixel < GetXSize(); iPixel++) - { - double dfValue; - - if (b32Bit) - dfValue = reinterpret_cast(pBuffer)[iPixel]; - else - dfValue = reinterpret_cast(pBuffer)[iPixel]; - - if (dfValue != dfNoData) - { - if (bFirst) - { - *pdfMin = dfValue; - *pdfMax = dfValue; - bFirst = false; - } - else - { - *pdfMin = std::min(*pdfMin, dfValue); - *pdfMax = std::max(*pdfMax, dfValue); - } - } - } - } - - CPLFree(pBuffer); - - return !bFirst; -} diff --git a/frmts/sdts/sdtstransfer.cpp b/frmts/sdts/sdtstransfer.cpp deleted file mode 100644 index fc629e13da4e..000000000000 --- a/frmts/sdts/sdtstransfer.cpp +++ /dev/null @@ -1,619 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTSTransfer class. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -#include - -/************************************************************************/ -/* SDTSTransfer() */ -/************************************************************************/ - -SDTSTransfer::SDTSTransfer() - : nLayers(0), panLayerCATDEntry(nullptr), papoLayerReader(nullptr) -{ -} - -/************************************************************************/ -/* ~SDTSTransfer() */ -/************************************************************************/ - -SDTSTransfer::~SDTSTransfer() - -{ - Close(); -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -/** - * Open an SDTS transfer, and establish a list of data layers in the - * transfer. - * - * @param pszFilename The name of the CATD file within the transfer. - * - * @return TRUE if the open success, or FALSE if it fails. - */ - -int SDTSTransfer::Open(const char *pszFilename) - -{ - /* -------------------------------------------------------------------- */ - /* Open the catalog. */ - /* -------------------------------------------------------------------- */ - if (!oCATD.Read(pszFilename)) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Read the IREF file. */ - /* -------------------------------------------------------------------- */ - if (oCATD.GetModuleFilePath("IREF") == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Can't find IREF module in transfer `%s'.\n", pszFilename); - return FALSE; - } - - if (!oIREF.Read(oCATD.GetModuleFilePath("IREF"))) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Read the XREF file. */ - /* -------------------------------------------------------------------- */ - if (oCATD.GetModuleFilePath("XREF") == nullptr) - { - CPLError(CE_Warning, CPLE_AppDefined, - "Can't find XREF module in transfer `%s'.\n", pszFilename); - } - else if (!oXREF.Read(oCATD.GetModuleFilePath("XREF"))) - { - CPLError( - CE_Warning, CPLE_AppDefined, - "Can't read XREF module, even though found in transfer `%s'.\n", - pszFilename); - } - - /* -------------------------------------------------------------------- */ - /* Build an index of layer types we recognise and care about. */ - /* -------------------------------------------------------------------- */ - panLayerCATDEntry = - reinterpret_cast(CPLMalloc(sizeof(int) * oCATD.GetEntryCount())); - - for (int iCATDLayer = 0; iCATDLayer < oCATD.GetEntryCount(); iCATDLayer++) - { - switch (oCATD.GetEntryType(iCATDLayer)) - { - case SLTPoint: - case SLTLine: - case SLTAttr: - case SLTPoly: - case SLTRaster: - panLayerCATDEntry[nLayers++] = iCATDLayer; - break; - - default: - /* ignore */ - break; - } - } - - /* -------------------------------------------------------------------- */ - /* Initialized the related indexed readers list. */ - /* -------------------------------------------------------------------- */ - papoLayerReader = reinterpret_cast( - CPLCalloc(sizeof(SDTSIndexedReader *), oCATD.GetEntryCount())); - - return TRUE; -} - -/************************************************************************/ -/* Close() */ -/************************************************************************/ - -void SDTSTransfer::Close() - -{ - for (int i = 0; i < nLayers; i++) - { - if (papoLayerReader[i] != nullptr) - delete papoLayerReader[i]; - } - CPLFree(papoLayerReader); - papoLayerReader = nullptr; - CPLFree(panLayerCATDEntry); - panLayerCATDEntry = nullptr; - nLayers = 0; -} - -/************************************************************************/ -/* GetLayerType() */ -/************************************************************************/ - -/** - Fetch type of requested feature layer. - - @param iEntry the index of the layer to fetch information on. A value - from zero to GetLayerCount()-1. - - @return the layer type. - -
    -
  • SLTPoint: A point layer. An SDTSPointReader is returned by - SDTSTransfer::GetLayerIndexedReader(). - -
  • SLTLine: A line layer. An SDTSLineReader is returned by - SDTSTransfer::GetLayerIndexedReader(). - -
  • SLTAttr: An attribute primary or secondary layer. An SDTSAttrReader - is returned by SDTSTransfer::GetLayerIndexedReader(). - -
  • SLTPoly: A polygon layer. An SDTSPolygonReader is returned by - SDTSTransfer::GetLayerIndexedReader(). - -
  • SLTRaster: A raster layer. SDTSTransfer::GetLayerIndexedReader() - is not implemented. Use SDTSTransfer::GetLayerRasterReader() instead. -
- */ - -SDTSLayerType SDTSTransfer::GetLayerType(int iEntry) const - -{ - if (iEntry < 0 || iEntry >= nLayers) - return SLTUnknown; - - return oCATD.GetEntryType(panLayerCATDEntry[iEntry]); -} - -/************************************************************************/ -/* GetLayerCATDEntry() */ -/************************************************************************/ - -/** - Fetch the CATD module index for a layer. This can be used to fetch - details about the layer/module from the SDTS_CATD object, such as its - filename, and description. - - @param iEntry the layer index from 0 to GetLayerCount()-1. - - @return the module index suitable for use with the various SDTS_CATD - methods. - */ - -int SDTSTransfer::GetLayerCATDEntry(int iEntry) const - -{ - if (iEntry < 0 || iEntry >= nLayers) - return -1; - - return panLayerCATDEntry[iEntry]; -} - -/************************************************************************/ -/* GetLayerLineReader() */ -/************************************************************************/ - -SDTSLineReader *SDTSTransfer::GetLayerLineReader(int iEntry) - -{ - if (iEntry < 0 || iEntry >= nLayers || - oCATD.GetEntryType(panLayerCATDEntry[iEntry]) != SLTLine) - { - return nullptr; - } - - SDTSLineReader *poLineReader = new SDTSLineReader(&oIREF); - - if (!poLineReader->Open(oCATD.GetEntryFilePath(panLayerCATDEntry[iEntry]))) - { - oCATD.SetEntryTypeUnknown(iEntry); // to prevent further attempt - delete poLineReader; - return nullptr; - } - - return poLineReader; -} - -/************************************************************************/ -/* GetLayerPointReader() */ -/************************************************************************/ - -SDTSPointReader *SDTSTransfer::GetLayerPointReader(int iEntry) - -{ - if (iEntry < 0 || iEntry >= nLayers || - oCATD.GetEntryType(panLayerCATDEntry[iEntry]) != SLTPoint) - { - return nullptr; - } - - SDTSPointReader *poPointReader = new SDTSPointReader(&oIREF); - - if (!poPointReader->Open(oCATD.GetEntryFilePath(panLayerCATDEntry[iEntry]))) - { - oCATD.SetEntryTypeUnknown(iEntry); // to prevent further attempt - delete poPointReader; - return nullptr; - } - - return poPointReader; -} - -/************************************************************************/ -/* GetLayerPolygonReader() */ -/************************************************************************/ - -SDTSPolygonReader *SDTSTransfer::GetLayerPolygonReader(int iEntry) - -{ - if (iEntry < 0 || iEntry >= nLayers || - oCATD.GetEntryType(panLayerCATDEntry[iEntry]) != SLTPoly) - { - return nullptr; - } - - SDTSPolygonReader *poPolyReader = new SDTSPolygonReader(); - - if (!poPolyReader->Open(oCATD.GetEntryFilePath(panLayerCATDEntry[iEntry]))) - { - oCATD.SetEntryTypeUnknown(iEntry); // to prevent further attempt - delete poPolyReader; - return nullptr; - } - - return poPolyReader; -} - -/************************************************************************/ -/* GetLayerAttrReader() */ -/************************************************************************/ - -SDTSAttrReader *SDTSTransfer::GetLayerAttrReader(int iEntry) - -{ - if (iEntry < 0 || iEntry >= nLayers || - oCATD.GetEntryType(panLayerCATDEntry[iEntry]) != SLTAttr) - { - return nullptr; - } - - SDTSAttrReader *poAttrReader = new SDTSAttrReader(); - - if (!poAttrReader->Open(oCATD.GetEntryFilePath(panLayerCATDEntry[iEntry]))) - { - oCATD.SetEntryTypeUnknown(iEntry); // to prevent further attempt - delete poAttrReader; - return nullptr; - } - - return poAttrReader; -} - -/************************************************************************/ -/* GetLayerRasterReader() */ -/************************************************************************/ - -/** - Instantiate an SDTSRasterReader for the indicated layer. - - @param iEntry the index of the layer to instantiate a reader for. A - value between 0 and GetLayerCount()-1. - - @return a pointer to a new SDTSRasterReader object, or NULL if the method - fails. - - NOTE: The reader returned from GetLayerRasterReader() becomes the - responsibility of the caller to delete, and isn't automatically deleted - when the SDTSTransfer is destroyed. This method is different from - the GetLayerIndexedReader() method in this regard. - */ - -SDTSRasterReader *SDTSTransfer::GetLayerRasterReader(int iEntry) - -{ - if (iEntry < 0 || iEntry >= nLayers || - oCATD.GetEntryType(panLayerCATDEntry[iEntry]) != SLTRaster) - { - return nullptr; - } - - SDTSRasterReader *poRasterReader = new SDTSRasterReader(); - - if (!poRasterReader->Open(&oCATD, &oIREF, - oCATD.GetEntryModule(panLayerCATDEntry[iEntry]))) - { - oCATD.SetEntryTypeUnknown(iEntry); // to prevent further attempt - delete poRasterReader; - return nullptr; - } - - return poRasterReader; -} - -/************************************************************************/ -/* GetLayerModuleReader() */ -/************************************************************************/ - -DDFModule *SDTSTransfer::GetLayerModuleReader(int iEntry) - -{ - if (iEntry < 0 || iEntry >= nLayers) - { - return nullptr; - } - - DDFModule *poModuleReader = new DDFModule; - - if (!poModuleReader->Open( - oCATD.GetEntryFilePath(panLayerCATDEntry[iEntry]))) - { - oCATD.SetEntryTypeUnknown(iEntry); // to prevent further attempt - delete poModuleReader; - return nullptr; - } - - return poModuleReader; -} - -/************************************************************************/ -/* GetLayerIndexedReader() */ -/************************************************************************/ - -/** - Returns a pointer to a reader of the appropriate type to the requested - layer. - - Notes: -
    -
  • The returned reader remains owned by the SDTSTransfer, and will be - destroyed when the SDTSTransfer is destroyed. It should not be - destroyed by the application. - -
  • If an indexed reader was already created for this layer using - GetLayerIndexedReader(), it will be returned instead of creating a new - reader. Among other things this means that the returned reader may not - be positioned to read from the beginning of the module, and may already - have its index filled. - -
  • The returned reader will be of a type appropriate to the layer. - See SDTSTransfer::GetLayerType() to see what reader classes correspond - to what layer types, so it can be cast accordingly (if necessary). -
- - @param iEntry the index of the layer to instantiate a reader for. A - value between 0 and GetLayerCount()-1. - - @return a pointer to an appropriate reader or NULL if the method fails. - */ - -SDTSIndexedReader *SDTSTransfer::GetLayerIndexedReader(int iEntry) - -{ - if (papoLayerReader[iEntry] == nullptr) - { - switch (oCATD.GetEntryType(panLayerCATDEntry[iEntry])) - { - case SLTAttr: - papoLayerReader[iEntry] = GetLayerAttrReader(iEntry); - break; - - case SLTPoint: - papoLayerReader[iEntry] = GetLayerPointReader(iEntry); - break; - - case SLTLine: - papoLayerReader[iEntry] = GetLayerLineReader(iEntry); - break; - - case SLTPoly: - papoLayerReader[iEntry] = GetLayerPolygonReader(iEntry); - break; - - default: - break; - } - } - - return papoLayerReader[iEntry]; -} - -/************************************************************************/ -/* FindLayer() */ -/************************************************************************/ - -/** - Fetch the SDTSTransfer layer number corresponding to a module name. - - @param pszModule the name of the module to search for, such as "PC01". - - @return the layer number (between 0 and GetLayerCount()-1 corresponding to - the module, or -1 if it doesn't correspond to a layer. - */ - -int SDTSTransfer::FindLayer(const char *pszModule) - -{ - for (int iLayer = 0; iLayer < nLayers; iLayer++) - { - if (EQUAL(pszModule, oCATD.GetEntryModule(panLayerCATDEntry[iLayer]))) - { - return iLayer; - } - } - - return -1; -} - -/************************************************************************/ -/* GetIndexedFeatureRef() */ -/************************************************************************/ - -SDTSFeature *SDTSTransfer::GetIndexedFeatureRef(SDTSModId *poModId, - SDTSLayerType *peType) - -{ - /* -------------------------------------------------------------------- */ - /* Find the desired layer ... this is likely a significant slow */ - /* point in the whole process ... perhaps the last found could */ - /* be cached or something. */ - /* -------------------------------------------------------------------- */ - const int iLayer = FindLayer(poModId->szModule); - if (iLayer == -1) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Get the reader, and read a feature from it. */ - /* -------------------------------------------------------------------- */ - SDTSIndexedReader *poReader = GetLayerIndexedReader(iLayer); - if (poReader == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* return type, if requested. */ - /* -------------------------------------------------------------------- */ - if (peType != nullptr) - *peType = GetLayerType(iLayer); - - return poReader->GetIndexedFeatureRef(poModId->nRecord); -} - -/************************************************************************/ -/* GetAttr() */ -/* */ -/* Fetch the attribute information corresponding to a given */ -/* SDTSModId. */ -/************************************************************************/ - -/** - Fetch the attribute fields given a particular module/record id. - - @param poModId an attribute record identifier, normally taken from the - aoATID[] array of an SDTSIndexedFeature. - - @return a pointer to the DDFField containing the user attribute values as - subfields. - */ - -DDFField *SDTSTransfer::GetAttr(SDTSModId *poModId) - -{ - SDTSAttrRecord *poAttrRecord = - dynamic_cast(GetIndexedFeatureRef(poModId)); - - if (poAttrRecord == nullptr) - return nullptr; - - return poAttrRecord->poATTR; -} - -/************************************************************************/ -/* GetBounds() */ -/************************************************************************/ - -/** - Fetch approximate bounds for a transfer by scanning all point layers - and raster layers. - - For TVP datasets (where point layers are scanned) the results can, in - theory miss some lines that go outside the bounds of the point layers. - However, this isn't common since most TVP sets contain a bounding rectangle - whose corners will define the most extreme extents. - - @param pdfMinX western edge of dataset - @param pdfMinY southern edge of dataset - @param pdfMaxX eastern edge of dataset - @param pdfMaxY northern edge of dataset - - @return TRUE if success, or FALSE on a failure. - */ - -int SDTSTransfer::GetBounds(double *pdfMinX, double *pdfMinY, double *pdfMaxX, - double *pdfMaxY) - -{ - bool bFirst = true; - - for (int iLayer = 0; iLayer < GetLayerCount(); iLayer++) - { - if (GetLayerType(iLayer) == SLTPoint) - { - - SDTSPointReader *poLayer = reinterpret_cast( - GetLayerIndexedReader(iLayer)); - if (poLayer == nullptr) - continue; - - poLayer->Rewind(); - - SDTSRawPoint *poPoint = nullptr; - while ((poPoint = reinterpret_cast( - poLayer->GetNextFeature())) != nullptr) - { - if (bFirst) - { - *pdfMinX = poPoint->dfX; - *pdfMaxX = poPoint->dfX; - *pdfMinY = poPoint->dfY; - *pdfMaxY = poPoint->dfY; - bFirst = false; - } - else - { - *pdfMinX = std::min(*pdfMinX, poPoint->dfX); - *pdfMaxX = std::max(*pdfMaxX, poPoint->dfX); - *pdfMinY = std::min(*pdfMinY, poPoint->dfY); - *pdfMaxY = std::max(*pdfMaxY, poPoint->dfY); - } - - if (!poLayer->IsIndexed()) - delete poPoint; - } - } - else if (GetLayerType(iLayer) == SLTRaster) - { - SDTSRasterReader *poRL = GetLayerRasterReader(iLayer); - if (poRL == nullptr) - continue; - - double adfGeoTransform[6]; - poRL->GetTransform(adfGeoTransform); - - const double dfMinX = adfGeoTransform[0]; - const double dfMaxY = adfGeoTransform[3]; - const double dfMaxX = - adfGeoTransform[0] + poRL->GetXSize() * adfGeoTransform[1]; - const double dfMinY = - adfGeoTransform[3] + poRL->GetYSize() * adfGeoTransform[5]; - - if (bFirst) - { - *pdfMinX = dfMinX; - *pdfMaxX = dfMaxX; - *pdfMinY = dfMinY; - *pdfMaxY = dfMaxY; - bFirst = false; - } - else - { - *pdfMinX = std::min(dfMinX, *pdfMinX); - *pdfMaxX = std::max(dfMaxX, *pdfMaxX); - *pdfMinY = std::min(dfMinY, *pdfMinY); - *pdfMaxY = std::max(dfMaxY, *pdfMaxY); - } - - delete poRL; - } - } - - return !bFirst; -} diff --git a/frmts/sdts/sdtsxref.cpp b/frmts/sdts/sdtsxref.cpp deleted file mode 100644 index 1d3eede06e1d..000000000000 --- a/frmts/sdts/sdtsxref.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implementation of SDTS_XREF class for reading XREF module. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "sdts_al.h" - -/************************************************************************/ -/* SDTS_XREF() */ -/************************************************************************/ - -SDTS_XREF::SDTS_XREF() - : pszSystemName(CPLStrdup("")), pszDatum(CPLStrdup("")), nZone(0) -{ -} - -/************************************************************************/ -/* ~SDTS_XREF() */ -/************************************************************************/ - -SDTS_XREF::~SDTS_XREF() -{ - CPLFree(pszSystemName); - CPLFree(pszDatum); -} - -/************************************************************************/ -/* Read() */ -/* */ -/* Read the named file to initialize this structure. */ -/************************************************************************/ - -int SDTS_XREF::Read(const char *pszFilename) - -{ - /* -------------------------------------------------------------------- */ - /* Open the file, and read the header. */ - /* -------------------------------------------------------------------- */ - DDFModule oXREFFile; - if (!oXREFFile.Open(pszFilename)) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Read the first record, and verify that this is an XREF record. */ - /* -------------------------------------------------------------------- */ - DDFRecord *poRecord = oXREFFile.ReadRecord(); - if (poRecord == nullptr) - return FALSE; - - if (poRecord->GetStringSubfield("XREF", 0, "MODN", 0) == nullptr) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Read fields of interest. */ - /* -------------------------------------------------------------------- */ - - CPLFree(pszSystemName); - pszSystemName = - CPLStrdup(poRecord->GetStringSubfield("XREF", 0, "RSNM", 0)); - - CPLFree(pszDatum); - pszDatum = CPLStrdup(poRecord->GetStringSubfield("XREF", 0, "HDAT", 0)); - - nZone = poRecord->GetIntSubfield("XREF", 0, "ZONE", 0); - - return TRUE; -} diff --git a/frmts/sgi/CMakeLists.txt b/frmts/sgi/CMakeLists.txt deleted file mode 100644 index 1c13c34b3acf..000000000000 --- a/frmts/sgi/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_gdal_driver(TARGET gdal_SGI SOURCES sgidataset.cpp PLUGIN_CAPABLE NO_DEPS) -gdal_standard_includes(gdal_SGI) diff --git a/frmts/sgi/sgidataset.cpp b/frmts/sgi/sgidataset.cpp deleted file mode 100644 index 7837e3d18ab1..000000000000 --- a/frmts/sgi/sgidataset.cpp +++ /dev/null @@ -1,820 +0,0 @@ -/****************************************************************************** - * - * Project: SGI Image Driver - * Purpose: Implement SGI Image Support based on Paul Bourke's SGI Image code. - * http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/ - * ftp://ftp.sgi.com/graphics/SGIIMAGESPEC - * Authors: Mike Mazzella (GDAL driver) - * Paul Bourke (original SGI format code) - * Frank Warmerdam (write support) - * - ****************************************************************************** - * Copyright (c) 2005, Frank Warmerdam - * Copyright (c) 2008-2010, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_port.h" -#include "cpl_string.h" -#include "gdal_frmts.h" -#include "gdal_pam.h" - -#include - -struct ImageRec -{ - GUInt16 imagic; - GByte type; - GByte bpc; - GUInt16 dim; - GUInt16 xsize; - GUInt16 ysize; - GUInt16 zsize; - GUInt32 min; - GUInt32 max; - char wasteBytes[4]; - char name[80]; - GUInt32 colorMap; - - VSILFILE *file; - std::string fileName; - int tmpSize; - unsigned char *tmp; - GUInt32 rleEnd; - int rleTableDirty; - GUInt32 *rowStart; - GInt32 *rowSize; - - ImageRec() - : imagic(0), type(0), bpc(1), dim(0), xsize(0), ysize(0), zsize(0), - min(0), max(0), colorMap(0), file(nullptr), fileName(""), tmpSize(0), - tmp(nullptr), rleEnd(0), rleTableDirty(FALSE), rowStart(nullptr), - rowSize(nullptr) - { - memset(wasteBytes, 0, 4); - memset(name, 0, 80); - } - - void Swap() - { -#ifdef CPL_LSB - CPL_SWAP16PTR(&imagic); - CPL_SWAP16PTR(&dim); - CPL_SWAP16PTR(&xsize); - CPL_SWAP16PTR(&ysize); - CPL_SWAP16PTR(&zsize); - CPL_SWAP32PTR(&min); - CPL_SWAP32PTR(&max); -#endif - } -}; - -/************************************************************************/ -/* ConvertLong() */ -/************************************************************************/ -#ifdef CPL_LSB -static void ConvertLong(GUInt32 *array, GInt32 length) -{ - GUInt32 *ptr = reinterpret_cast(array); - while (length--) - { - CPL_SWAP32PTR(ptr); - ptr++; - } -} -#else -static void ConvertLong(GUInt32 * /*array*/, GInt32 /*length */) -{ -} -#endif - -/************************************************************************/ -/* ImageGetRow() */ -/************************************************************************/ -static CPLErr ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) -{ - y = image->ysize - 1 - y; - - if (static_cast(image->type) != 1) - { - VSIFSeekL(image->file, - 512 + (y * static_cast(image->xsize)) + - (z * static_cast(image->xsize) * - static_cast(image->ysize)), - SEEK_SET); - if (VSIFReadL(buf, 1, image->xsize, image->file) != image->xsize) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "file read error: row (%d) of (%s)\n", y, - image->fileName.empty() ? "none" - : image->fileName.c_str()); - return CE_Failure; - } - return CE_None; - } - - // Image type 1. - - // reads row - if (image->rowSize[y + z * image->ysize] < 0 || - image->rowSize[y + z * image->ysize] > image->tmpSize) - { - return CE_Failure; - } - VSIFSeekL(image->file, - static_cast(image->rowStart[y + z * image->ysize]), - SEEK_SET); - if (VSIFReadL(image->tmp, 1, - static_cast(image->rowSize[y + z * image->ysize]), - image->file) != - static_cast(image->rowSize[y + z * image->ysize])) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "file read error: row (%d) of (%s)\n", y, - image->fileName.empty() ? "none" : image->fileName.c_str()); - return CE_Failure; - } - - // expands row - unsigned char *iPtr = image->tmp; - unsigned char *oPtr = buf; - int xsizeCount = 0; - for (;;) - { - unsigned char pixel = *iPtr++; - int count = static_cast(pixel & 0x7F); - if (!count) - { - if (xsizeCount != image->xsize) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "file read error: row (%d) of (%s)\n", y, - image->fileName.empty() ? "none" - : image->fileName.c_str()); - return CE_Failure; - } - else - { - break; - } - } - - if (xsizeCount + count > image->xsize) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Wrong repetition number that would overflow data " - "at line %d", - y); - return CE_Failure; - } - - if (pixel & 0x80) - { - memcpy(oPtr, iPtr, count); - iPtr += count; - } - else - { - pixel = *iPtr++; - memset(oPtr, pixel, count); - } - oPtr += count; - xsizeCount += count; - } - - return CE_None; -} - -/************************************************************************/ -/* ==================================================================== */ -/* SGIDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class SGIRasterBand; - -class SGIDataset final : public GDALPamDataset -{ - friend class SGIRasterBand; - - VSILFILE *fpImage; - - int bGeoTransformValid; - double adfGeoTransform[6]; - - ImageRec image; - - public: - SGIDataset(); - virtual ~SGIDataset(); - - virtual CPLErr GetGeoTransform(double *) override; - static GDALDataset *Open(GDALOpenInfo *); - static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - char **papszOptions); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* SGIRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class SGIRasterBand final : public GDALPamRasterBand -{ - friend class SGIDataset; - - public: - SGIRasterBand(SGIDataset *, int); - - virtual CPLErr IReadBlock(int, int, void *) override; - virtual CPLErr IWriteBlock(int, int, void *) override; - virtual GDALColorInterp GetColorInterpretation() override; -}; - -/************************************************************************/ -/* SGIRasterBand() */ -/************************************************************************/ - -SGIRasterBand::SGIRasterBand(SGIDataset *poDSIn, int nBandIn) - -{ - poDS = poDSIn; - nBand = nBandIn; - - if (static_cast(poDSIn->image.bpc) == 1) - eDataType = GDT_Byte; - else - eDataType = GDT_Int16; - - nBlockXSize = poDSIn->nRasterXSize; - nBlockYSize = 1; -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr SGIRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff, - void *pImage) -{ - SGIDataset *poGDS = reinterpret_cast(poDS); - - CPLAssert(nBlockXOff == 0); - - /* -------------------------------------------------------------------- */ - /* Load the desired data into the working buffer. */ - /* -------------------------------------------------------------------- */ - return ImageGetRow(&(poGDS->image), - reinterpret_cast(pImage), nBlockYOff, - nBand - 1); -} - -/************************************************************************/ -/* IWritelock() */ -/************************************************************************/ - -CPLErr SGIRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff, - void *pImage) -{ - CPLAssert(nBlockXOff == 0); - - SGIDataset *poGDS = reinterpret_cast(poDS); - ImageRec *image = &(poGDS->image); - - /* -------------------------------------------------------------------- */ - /* Handle the fairly trivial non-RLE case. */ - /* -------------------------------------------------------------------- */ - if (image->type == 0) - { - VSIFSeekL(image->file, - 512 + (nBlockYOff * static_cast(image->xsize)) + - ((nBand - 1) * static_cast(image->xsize) * - static_cast(image->ysize)), - SEEK_SET); - if (VSIFWriteL(pImage, 1, image->xsize, image->file) != image->xsize) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "file write error: row (%d)\n", nBlockYOff); - return CE_Failure; - } - return CE_None; - } - - /* -------------------------------------------------------------------- */ - /* Handle RLE case. */ - /* -------------------------------------------------------------------- */ - const GByte *pabyRawBuf = reinterpret_cast(pImage); - GByte *pabyRLEBuf = - reinterpret_cast(CPLMalloc(image->xsize * 2 + 6)); - - int iX = 0; - int nRLEBytes = 0; - - while (iX < image->xsize) - { - int nRepeatCount = 1; - - while (iX + nRepeatCount < image->xsize && nRepeatCount < 127 && - pabyRawBuf[iX + nRepeatCount] == pabyRawBuf[iX]) - nRepeatCount++; - - if (nRepeatCount > 2 || iX + nRepeatCount == image->xsize || - (iX + nRepeatCount < image->xsize - 3 && - pabyRawBuf[iX + nRepeatCount + 1] == - pabyRawBuf[iX + nRepeatCount + 2] && - pabyRawBuf[iX + nRepeatCount + 1] == - pabyRawBuf[iX + nRepeatCount + 3])) - { // encode a constant run. - pabyRLEBuf[nRLEBytes++] = static_cast(nRepeatCount); - pabyRLEBuf[nRLEBytes++] = pabyRawBuf[iX]; - iX += nRepeatCount; - } - else - { // copy over mixed data. - for (nRepeatCount = 1; - iX + nRepeatCount < image->xsize && nRepeatCount < 127; - nRepeatCount++) - { - if (iX + nRepeatCount + 3 >= image->xsize) - continue; - - // quit if the next 3 pixels match - if (pabyRawBuf[iX + nRepeatCount] == - pabyRawBuf[iX + nRepeatCount + 1] && - pabyRawBuf[iX + nRepeatCount] == - pabyRawBuf[iX + nRepeatCount + 2]) - break; - } - - pabyRLEBuf[nRLEBytes++] = static_cast(0x80 | nRepeatCount); - memcpy(pabyRLEBuf + nRLEBytes, pabyRawBuf + iX, nRepeatCount); - - nRLEBytes += nRepeatCount; - iX += nRepeatCount; - } - } - - // EOL marker. - pabyRLEBuf[nRLEBytes++] = 0; - - /* -------------------------------------------------------------------- */ - /* Write RLE Buffer at end of file. */ - /* -------------------------------------------------------------------- */ - const int row = - (image->ysize - nBlockYOff - 1) + (nBand - 1) * image->ysize; - - VSIFSeekL(image->file, 0, SEEK_END); - - image->rowStart[row] = static_cast(VSIFTellL(image->file)); - image->rowSize[row] = nRLEBytes; - image->rleTableDirty = TRUE; - - if (static_cast(VSIFWriteL(pabyRLEBuf, 1, nRLEBytes, image->file)) != - nRLEBytes) - { - CPLFree(pabyRLEBuf); - CPLError(CE_Failure, CPLE_OpenFailed, "file write error: row (%d)\n", - nBlockYOff); - return CE_Failure; - } - - CPLFree(pabyRLEBuf); - - return CE_None; -} - -/************************************************************************/ -/* GetColorInterpretation() */ -/************************************************************************/ - -GDALColorInterp SGIRasterBand::GetColorInterpretation() - -{ - SGIDataset *poGDS = reinterpret_cast(poDS); - - if (poGDS->nBands == 1) - return GCI_GrayIndex; - else if (poGDS->nBands == 2) - { - if (nBand == 1) - return GCI_GrayIndex; - else - return GCI_AlphaBand; - } - else if (poGDS->nBands == 3) - { - if (nBand == 1) - return GCI_RedBand; - else if (nBand == 2) - return GCI_GreenBand; - else - return GCI_BlueBand; - } - else if (poGDS->nBands == 4) - { - if (nBand == 1) - return GCI_RedBand; - else if (nBand == 2) - return GCI_GreenBand; - else if (nBand == 3) - return GCI_BlueBand; - else - return GCI_AlphaBand; - } - return GCI_Undefined; -} - -/************************************************************************/ -/* ==================================================================== */ -/* SGIDataset */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* SGIDataset() */ -/************************************************************************/ - -SGIDataset::SGIDataset() : fpImage(nullptr), bGeoTransformValid(FALSE) -{ - adfGeoTransform[0] = 0.0; - adfGeoTransform[1] = 1.0; - adfGeoTransform[2] = 0.0; - adfGeoTransform[3] = 0.0; - adfGeoTransform[4] = 0.0; - adfGeoTransform[5] = 1.0; -} - -/************************************************************************/ -/* ~SGIDataset() */ -/************************************************************************/ - -SGIDataset::~SGIDataset() - -{ - FlushCache(true); - - // Do we need to write out rle table? - if (image.rleTableDirty) - { - CPLDebug("SGI", "Flushing RLE offset table."); - ConvertLong(image.rowStart, image.ysize * image.zsize); - ConvertLong(reinterpret_cast(image.rowSize), - image.ysize * image.zsize); - - VSIFSeekL(fpImage, 512, SEEK_SET); - size_t nSize = - static_cast(image.ysize) * static_cast(image.zsize); - VSIFWriteL(image.rowStart, 4, nSize, fpImage); - VSIFWriteL(image.rowSize, 4, nSize, fpImage); - image.rleTableDirty = FALSE; - } - - if (fpImage != nullptr) - VSIFCloseL(fpImage); - - CPLFree(image.tmp); - CPLFree(image.rowSize); - CPLFree(image.rowStart); -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr SGIDataset::GetGeoTransform(double *padfTransform) - -{ - if (bGeoTransformValid) - { - memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6); - return CE_None; - } - - return GDALPamDataset::GetGeoTransform(padfTransform); -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *SGIDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - /* -------------------------------------------------------------------- */ - /* First we check to see if the file has the expected header */ - /* bytes. */ - /* -------------------------------------------------------------------- */ - if (poOpenInfo->nHeaderBytes < 12 || poOpenInfo->fpL == nullptr) - return nullptr; - - ImageRec tmpImage; - memcpy(&tmpImage.imagic, poOpenInfo->pabyHeader + 0, 2); - memcpy(&tmpImage.type, poOpenInfo->pabyHeader + 2, 1); - memcpy(&tmpImage.bpc, poOpenInfo->pabyHeader + 3, 1); - memcpy(&tmpImage.dim, poOpenInfo->pabyHeader + 4, 2); - memcpy(&tmpImage.xsize, poOpenInfo->pabyHeader + 6, 2); - memcpy(&tmpImage.ysize, poOpenInfo->pabyHeader + 8, 2); - memcpy(&tmpImage.zsize, poOpenInfo->pabyHeader + 10, 2); - tmpImage.Swap(); - - if (tmpImage.imagic != 474) - return nullptr; - - if (tmpImage.type != 0 && tmpImage.type != 1) - return nullptr; - - if (tmpImage.bpc != 1 && tmpImage.bpc != 2) - return nullptr; - - if (tmpImage.dim != 1 && tmpImage.dim != 2 && tmpImage.dim != 3) - return nullptr; - - if (tmpImage.bpc != 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "The SGI driver only supports 1 byte channel values.\n"); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - SGIDataset *poDS = new SGIDataset(); - poDS->eAccess = poOpenInfo->eAccess; - poDS->fpImage = poOpenInfo->fpL; - poOpenInfo->fpL = nullptr; - - /* -------------------------------------------------------------------- */ - /* Read pre-image data after ensuring the file is rewound. */ - /* -------------------------------------------------------------------- */ - VSIFSeekL(poDS->fpImage, 0, SEEK_SET); - if (VSIFReadL(reinterpret_cast(&(poDS->image)), 1, 12, - poDS->fpImage) != 12) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "file read error while reading header in sgidataset.cpp"); - delete poDS; - return nullptr; - } - poDS->image.Swap(); - poDS->image.file = poDS->fpImage; - poDS->image.fileName = poOpenInfo->pszFilename; - - /* -------------------------------------------------------------------- */ - /* Capture some information from the file that is of interest. */ - /* -------------------------------------------------------------------- */ - poDS->nRasterXSize = poDS->image.xsize; - poDS->nRasterYSize = poDS->image.ysize; - if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Invalid image dimensions : %d x %d", poDS->nRasterXSize, - poDS->nRasterYSize); - delete poDS; - return nullptr; - } - poDS->nBands = std::max(static_cast(1), poDS->image.zsize); - if (poDS->nBands > 256) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Too many bands : %d", - poDS->nBands); - delete poDS; - return nullptr; - } - - const int numItems = (static_cast(poDS->image.bpc) == 1) ? 256 : 65536; - if (poDS->image.xsize > INT_MAX / numItems) - { - delete poDS; - return nullptr; - } - poDS->image.tmpSize = poDS->image.xsize * numItems; - poDS->image.tmp = - (unsigned char *)VSI_CALLOC_VERBOSE(poDS->image.xsize, numItems); - if (poDS->image.tmp == nullptr) - { - delete poDS; - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Read RLE Pointer tables. */ - /* -------------------------------------------------------------------- */ - if (static_cast(poDS->image.type) == 1) // RLE compressed - { - const size_t x = static_cast(poDS->image.ysize) * poDS->nBands * - sizeof(GUInt32); - poDS->image.rowStart = reinterpret_cast(VSI_MALLOC2_VERBOSE( - poDS->image.ysize, poDS->nBands * sizeof(GUInt32))); - poDS->image.rowSize = reinterpret_cast(VSI_MALLOC2_VERBOSE( - poDS->image.ysize, poDS->nBands * sizeof(GUInt32))); - if (poDS->image.rowStart == nullptr || poDS->image.rowSize == nullptr) - { - delete poDS; - return nullptr; - } - memset(poDS->image.rowStart, 0, x); - memset(poDS->image.rowSize, 0, x); - poDS->image.rleEnd = static_cast(512 + (2 * x)); - VSIFSeekL(poDS->fpImage, 512, SEEK_SET); - if (VSIFReadL(poDS->image.rowStart, 1, x, poDS->image.file) != x) - { - delete poDS; - CPLError(CE_Failure, CPLE_OpenFailed, - "file read error while reading start positions in " - "sgidataset.cpp"); - return nullptr; - } - if (VSIFReadL(poDS->image.rowSize, 1, x, poDS->image.file) != x) - { - delete poDS; - CPLError( - CE_Failure, CPLE_OpenFailed, - "file read error while reading row lengths in sgidataset.cpp"); - return nullptr; - } - ConvertLong(poDS->image.rowStart, - static_cast(x / static_cast(sizeof(GUInt32)))); - ConvertLong(reinterpret_cast(poDS->image.rowSize), - static_cast(x / static_cast(sizeof(GInt32)))); - } - else // uncompressed. - { - poDS->image.rowStart = nullptr; - poDS->image.rowSize = nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create band information objects. */ - /* -------------------------------------------------------------------- */ - for (int iBand = 0; iBand < poDS->nBands; iBand++) - poDS->SetBand(iBand + 1, new SGIRasterBand(poDS, iBand + 1)); - - /* -------------------------------------------------------------------- */ - /* Check for world file. */ - /* -------------------------------------------------------------------- */ - poDS->bGeoTransformValid = GDALReadWorldFile(poOpenInfo->pszFilename, - ".wld", poDS->adfGeoTransform); - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Check for overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename); - - return poDS; -} - -/************************************************************************/ -/* Create() */ -/************************************************************************/ - -GDALDataset *SGIDataset::Create(const char *pszFilename, int nXSize, int nYSize, - int nBandsIn, GDALDataType eType, - CPL_UNUSED char **papszOptions) -{ - if (eType != GDT_Byte) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to create SGI dataset with an illegal\n" - "data type (%s), only Byte supported by the format.\n", - GDALGetDataTypeName(eType)); - - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Open the file for output. */ - /* -------------------------------------------------------------------- */ - VSILFILE *fp = VSIFOpenL(pszFilename, "w"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create file '%s': %s", - pszFilename, VSIStrerror(errno)); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Prepare and write 512 byte header. */ - /* -------------------------------------------------------------------- */ - GByte abyHeader[512]; - - memset(abyHeader, 0, 512); - - abyHeader[0] = 1; - abyHeader[1] = 218; - abyHeader[2] = 1; // RLE - abyHeader[3] = 1; // 8bit - - GInt16 nShortValue; - if (nBandsIn == 1) - nShortValue = CPL_MSBWORD16(2); - else - nShortValue = CPL_MSBWORD16(3); - memcpy(abyHeader + 4, &nShortValue, 2); - - nShortValue = CPL_MSBWORD16(nXSize); - memcpy(abyHeader + 6, &nShortValue, 2); - - nShortValue = CPL_MSBWORD16(nYSize); - memcpy(abyHeader + 8, &nShortValue, 2); - - nShortValue = CPL_MSBWORD16(nBandsIn); - memcpy(abyHeader + 10, &nShortValue, 2); - - GInt32 nIntValue = CPL_MSBWORD32(0); - memcpy(abyHeader + 12, &nIntValue, 4); - - GUInt32 nUIntValue = CPL_MSBWORD32(255); - memcpy(abyHeader + 16, &nUIntValue, 4); - - VSIFWriteL(abyHeader, 1, 512, fp); - - /* -------------------------------------------------------------------- */ - /* Create our RLE compressed zero-ed dummy line. */ - /* -------------------------------------------------------------------- */ - GByte *pabyRLELine = - reinterpret_cast(CPLMalloc((nXSize / 127) * 2 + 4)); - - int nPixelsRemaining = nXSize; - GInt32 nRLEBytes = 0; - while (nPixelsRemaining > 0) - { - pabyRLELine[nRLEBytes] = - static_cast(std::min(127, nPixelsRemaining)); - pabyRLELine[nRLEBytes + 1] = 0; - nPixelsRemaining -= pabyRLELine[nRLEBytes]; - - nRLEBytes += 2; - } - - /* -------------------------------------------------------------------- */ - /* Prepare and write RLE offset/size tables with everything */ - /* zeroed indicating dummy lines. */ - /* -------------------------------------------------------------------- */ - const int nTableLen = nYSize * nBandsIn; - GInt32 nDummyRLEOffset = 512 + 4 * nTableLen * 2; - - CPL_MSBPTR32(&nRLEBytes); - CPL_MSBPTR32(&nDummyRLEOffset); - - for (int i = 0; i < nTableLen; i++) - VSIFWriteL(&nDummyRLEOffset, 1, 4, fp); - - for (int i = 0; i < nTableLen; i++) - VSIFWriteL(&nRLEBytes, 1, 4, fp); - - /* -------------------------------------------------------------------- */ - /* write the dummy RLE blank line. */ - /* -------------------------------------------------------------------- */ - CPL_MSBPTR32(&nRLEBytes); - if (static_cast(VSIFWriteL(pabyRLELine, 1, nRLEBytes, fp)) != - nRLEBytes) - { - CPLError(CE_Failure, CPLE_FileIO, "Failure writing SGI file '%s'.\n%s", - pszFilename, VSIStrerror(errno)); - VSIFCloseL(fp); - CPLFree(pabyRLELine); - return nullptr; - } - - VSIFCloseL(fp); - CPLFree(pabyRLELine); - - return GDALDataset::FromHandle(GDALOpen(pszFilename, GA_Update)); -} - -/************************************************************************/ -/* GDALRegister_SGI() */ -/************************************************************************/ - -void GDALRegister_SGI() - -{ - if (GDALGetDriverByName("SGI") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("SGI"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "SGI Image File Format 1.0"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "rgb"); - poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/rgb"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/sgi.html"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = SGIDataset::Open; - poDriver->pfnCreate = SGIDataset::Create; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/usgsdem/CMakeLists.txt b/frmts/usgsdem/CMakeLists.txt index 40d8686db262..d584bd56c3dc 100644 --- a/frmts/usgsdem/CMakeLists.txt +++ b/frmts/usgsdem/CMakeLists.txt @@ -1,3 +1,3 @@ -add_gdal_driver(TARGET gdal_USGSDEM SOURCES usgsdem_create.cpp usgsdemdataset.cpp PLUGIN_CAPABLE NO_DEPS) +add_gdal_driver(TARGET gdal_USGSDEM SOURCES usgsdemdataset.cpp PLUGIN_CAPABLE NO_DEPS) gdal_standard_includes(gdal_USGSDEM) target_include_directories(gdal_USGSDEM PRIVATE $ ${GDAL_RASTER_FORMAT_SOURCE_DIR}/mem) diff --git a/frmts/usgsdem/usgsdem_create.cpp b/frmts/usgsdem/usgsdem_create.cpp deleted file mode 100644 index 8083dbcda336..000000000000 --- a/frmts/usgsdem/usgsdem_create.cpp +++ /dev/null @@ -1,1533 +0,0 @@ -/****************************************************************************** - * - * Project: USGS DEM Driver - * Purpose: CreateCopy() implementation. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - * This writing code based on the format specification: - * Canadian Digital Elevation Data Product Specification - Edition 2.0 - * - ****************************************************************************** - * Copyright (c) 2004, Frank Warmerdam - * Copyright (c) 2007-2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_csv.h" -#include "cpl_string.h" -#include "gdal_pam.h" -#include "gdalwarper.h" -#include "memdataset.h" -#include "ogr_spatialref.h" - -#include - -#include - -/* used by usgsdemdataset.cpp */ -GDALDataset *USGSDEMCreateCopy(const char *, GDALDataset *, int, char **, - GDALProgressFunc pfnProgress, - void *pProgressData); - -typedef struct -{ - GDALDataset *poSrcDS; - char *pszFilename; - int nXSize, nYSize; - - char *pszDstSRS; - - double dfLLX, dfLLY; // These are adjusted in to center of - double dfULX, dfULY; // corner pixels, and in decimal degrees. - double dfURX, dfURY; - double dfLRX, dfLRY; - - int utmzone; - char horizdatum[2]; - - double dfHorizStepSize; - double dfVertStepSize; - double dfElevStepSize; - - char **papszOptions; - int bStrict; - - VSILFILE *fp; - - GInt16 *panData; -} USGSDEMWriteInfo; - -#define DEM_NODATA -32767 - -/************************************************************************/ -/* USGSDEMWriteCleanup() */ -/************************************************************************/ - -static void USGSDEMWriteCleanup(USGSDEMWriteInfo *psWInfo) - -{ - CSLDestroy(psWInfo->papszOptions); - CPLFree(psWInfo->pszDstSRS); - CPLFree(psWInfo->pszFilename); - if (psWInfo->fp != nullptr) - { - if (VSIFCloseL(psWInfo->fp) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, "I/O error"); - } - } - if (psWInfo->panData != nullptr) - VSIFree(psWInfo->panData); -} - -/************************************************************************/ -/* USGSDEMDectoPackedDMS() */ -/************************************************************************/ -static const char *USGSDEMDecToPackedDMS(double dfDec) -{ - const int nSign = (dfDec < 0.0) ? -1 : 1; - - dfDec = std::abs(dfDec); - /* If the difference between the value and the nearest degree - is less than 1e-5 second, then we force to round to the - nearest degree, to avoid result strings like '40 59 60.0000' instead of - '41'. This is of general interest, but was mainly done to workaround a - strange Valgrind bug when running usgsdem_6 where the value of - psDInfo->dfULCornerY computed in DTEDOpen() differ between Valgrind and - non-Valgrind executions. - */ - int nDegrees; - if (std::abs(dfDec - static_cast(std::floor(dfDec + .5))) < - 1e-5 / 3600) - { - nDegrees = static_cast(std::floor(dfDec + .5)); - dfDec = nDegrees; - } - else - nDegrees = static_cast(std::floor(dfDec)); - const int nMinutes = - static_cast(std::floor((dfDec - nDegrees) * 60.0)); - const double dfSeconds = (dfDec - nDegrees) * 3600.0 - nMinutes * 60.0; - - static char szPackBuf[100]; - CPLsnprintf(szPackBuf, sizeof(szPackBuf), "%4d%2d%7.4f", nSign * nDegrees, - nMinutes, dfSeconds); - return szPackBuf; -} - -/************************************************************************/ -/* TextFill() */ -/************************************************************************/ - -static void TextFill(char *pszTarget, unsigned int nMaxChars, - const char *pszSrc) - -{ - if (strlen(pszSrc) < nMaxChars) - { - memcpy(pszTarget, pszSrc, strlen(pszSrc)); - memset(pszTarget + strlen(pszSrc), ' ', nMaxChars - strlen(pszSrc)); - } - else - { - memcpy(pszTarget, pszSrc, nMaxChars); - } -} - -/************************************************************************/ -/* TextFillR() */ -/* */ -/* Right justified. */ -/************************************************************************/ - -static void TextFillR(char *pszTarget, unsigned int nMaxChars, - const char *pszSrc) - -{ - if (strlen(pszSrc) < nMaxChars) - { - memset(pszTarget, ' ', nMaxChars - strlen(pszSrc)); - memcpy(pszTarget + nMaxChars - strlen(pszSrc), pszSrc, strlen(pszSrc)); - } - else - memcpy(pszTarget, pszSrc, nMaxChars); -} - -/************************************************************************/ -/* USGSDEMPrintDouble() */ -/* */ -/* The MSVC C runtime library uses 3 digits */ -/* for the exponent. This causes various problems, so we try */ -/* to correct it here. */ -/************************************************************************/ - -#if defined(_MSC_VER) || defined(__MSVCRT__) -#define MSVC_HACK -#endif - -static void USGSDEMPrintDouble(char *pszBuffer, double dfValue) - -{ - if (!pszBuffer) - return; - -#ifdef MSVC_HACK - const char *pszFormat = "%25.15e"; -#else - const char *pszFormat = "%24.15e"; -#endif - - const int DOUBLE_BUFFER_SIZE = 64; - char szTemp[DOUBLE_BUFFER_SIZE]; - int nOffset = 0; - if (CPLsnprintf(szTemp, DOUBLE_BUFFER_SIZE, pszFormat, dfValue) == 25 && - szTemp[0] == ' ') - { - nOffset = 1; - } - szTemp[DOUBLE_BUFFER_SIZE - 1] = '\0'; - - for (int i = 0; szTemp[i] != '\0'; i++) - { - if (szTemp[i] == 'E' || szTemp[i] == 'e') - szTemp[i] = 'D'; -#ifdef MSVC_HACK - if ((szTemp[i] == '+' || szTemp[i] == '-') && szTemp[i + 1] == '0' && - isdigit(static_cast(szTemp[i + 2])) && - isdigit(static_cast(szTemp[i + 3])) && - szTemp[i + 4] == '\0') - { - szTemp[i + 1] = szTemp[i + 2]; - szTemp[i + 2] = szTemp[i + 3]; - szTemp[i + 3] = '\0'; - break; - } -#endif - } - - TextFillR(pszBuffer, 24, szTemp + nOffset); -} - -/************************************************************************/ -/* USGSDEMPrintSingle() */ -/* */ -/* The MSVC C runtime library uses 3 digits */ -/* for the exponent. This causes various problems, so we try */ -/* to correct it here. */ -/************************************************************************/ - -static void USGSDEMPrintSingle(char *pszBuffer, double dfValue) - -{ - if (!pszBuffer) - return; - -#ifdef MSVC_HACK - const char *pszFormat = "%13.6e"; -#else - const char *pszFormat = "%12.6e"; -#endif - - const int DOUBLE_BUFFER_SIZE = 64; - char szTemp[DOUBLE_BUFFER_SIZE]; - int nOffset = 0; - if (CPLsnprintf(szTemp, DOUBLE_BUFFER_SIZE, pszFormat, dfValue) == 13 && - szTemp[0] == ' ') - { - nOffset = 1; - } - szTemp[DOUBLE_BUFFER_SIZE - 1] = '\0'; - - for (int i = 0; szTemp[i] != '\0'; i++) - { - if (szTemp[i] == 'E' || szTemp[i] == 'e') - szTemp[i] = 'D'; -#ifdef MSVC_HACK - if ((szTemp[i] == '+' || szTemp[i] == '-') && szTemp[i + 1] == '0' && - isdigit(static_cast(szTemp[i + 2])) && - isdigit(static_cast(szTemp[i + 3])) && - szTemp[i + 4] == '\0') - { - szTemp[i + 1] = szTemp[i + 2]; - szTemp[i + 2] = szTemp[i + 3]; - szTemp[i + 3] = '\0'; - break; - } -#endif - } - - TextFillR(pszBuffer, 12, szTemp + nOffset); -} - -/************************************************************************/ -/* USGSDEMWriteARecord() */ -/************************************************************************/ - -static int USGSDEMWriteARecord(USGSDEMWriteInfo *psWInfo) - -{ - /* -------------------------------------------------------------------- */ - /* Init to blanks. */ - /* -------------------------------------------------------------------- */ - char achARec[1024]; - memset(achARec, ' ', sizeof(achARec)); - - /* -------------------------------------------------------------------- */ - /* Load template file, if one is indicated. */ - /* -------------------------------------------------------------------- */ - const char *pszTemplate = - CSLFetchNameValue(psWInfo->papszOptions, "TEMPLATE"); - if (pszTemplate != nullptr) - { - VSILFILE *fpTemplate = VSIFOpenL(pszTemplate, "rb"); - if (fpTemplate == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Unable to open template file '%s'.\n%s", pszTemplate, - VSIStrerror(errno)); - return FALSE; - } - - if (VSIFReadL(achARec, 1, 1024, fpTemplate) != 1024) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to read 1024 byte A Record from template file " - "'%s'.\n%s", - pszTemplate, VSIStrerror(errno)); - return FALSE; - } - CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemplate)); - } - - /* -------------------------------------------------------------------- */ - /* Filename (right justify) */ - /* -------------------------------------------------------------------- */ - TextFillR(achARec + 0, 40, CPLGetFilename(psWInfo->pszFilename)); - - /* -------------------------------------------------------------------- */ - /* Producer */ - /* -------------------------------------------------------------------- */ - const char *pszOption = - CSLFetchNameValue(psWInfo->papszOptions, "PRODUCER"); - - if (pszOption != nullptr) - TextFillR(achARec + 40, 60, pszOption); - - else if (pszTemplate == nullptr) - TextFill(achARec + 40, 60, ""); - - /* -------------------------------------------------------------------- */ - /* Filler */ - /* -------------------------------------------------------------------- */ - TextFill(achARec + 100, 9, ""); - - /* -------------------------------------------------------------------- */ - /* SW Geographic Corner - SDDDMMSS.SSSS - longitude then latitude */ - /* -------------------------------------------------------------------- */ - if (!psWInfo->utmzone) - { - TextFill(achARec + 109, 13, - USGSDEMDecToPackedDMS(psWInfo->dfLLX)); // longitude - TextFill(achARec + 122, 13, - USGSDEMDecToPackedDMS(psWInfo->dfLLY)); // latitude - } - /* this may not be best according to the spec. But for now, - * we won't try to convert the UTM coordinates to lat/lon - */ - - /* -------------------------------------------------------------------- */ - /* Process code. */ - /* -------------------------------------------------------------------- */ - pszOption = CSLFetchNameValue(psWInfo->papszOptions, "ProcessCode"); - - if (pszOption != nullptr) - TextFill(achARec + 135, 1, pszOption); - - else if (pszTemplate == nullptr) - TextFill(achARec + 135, 1, " "); - - /* -------------------------------------------------------------------- */ - /* Filler */ - /* -------------------------------------------------------------------- */ - TextFill(achARec + 136, 1, ""); - - /* -------------------------------------------------------------------- */ - /* Sectional indicator */ - /* -------------------------------------------------------------------- */ - if (pszTemplate == nullptr) - TextFill(achARec + 137, 3, ""); - - /* -------------------------------------------------------------------- */ - /* Origin code */ - /* -------------------------------------------------------------------- */ - pszOption = CSLFetchNameValue(psWInfo->papszOptions, "OriginCode"); - - if (pszOption != nullptr) - TextFill(achARec + 140, 4, pszOption); // Should be YT for Yukon. - - else if (pszTemplate == nullptr) - TextFill(achARec + 140, 4, ""); - - /* -------------------------------------------------------------------- */ - /* DEM level code (right justify) */ - /* -------------------------------------------------------------------- */ - pszOption = CSLFetchNameValue(psWInfo->papszOptions, "DEMLevelCode"); - - if (pszOption != nullptr) - TextFillR(achARec + 144, 6, pszOption); // 1, 2 or 3. - - else if (pszTemplate == nullptr) - TextFillR(achARec + 144, 6, "1"); // 1, 2 or 3. - /* some DEM readers require a value, 1 seems to be a - * default - */ - - /* -------------------------------------------------------------------- */ - /* Elevation Pattern */ - /* -------------------------------------------------------------------- */ - TextFillR(achARec + 150, 6, "1"); // "1" for regular (random is 2) - - /* -------------------------------------------------------------------- */ - /* Horizontal Reference System. */ - /* */ - /* 0 = Geographic */ - /* 1 = UTM */ - /* 2 = Stateplane */ - /* -------------------------------------------------------------------- */ - if (!psWInfo->utmzone) - { - TextFillR(achARec + 156, 6, "0"); - } - else - { - TextFillR(achARec + 156, 6, "1"); - } - - /* -------------------------------------------------------------------- */ - /* UTM / State Plane zone. */ - /* -------------------------------------------------------------------- */ - if (!psWInfo->utmzone) - { - TextFillR(achARec + 162, 6, "0"); - } - else - { - TextFillR(achARec + 162, 6, CPLSPrintf("%02d", psWInfo->utmzone)); - } - - /* -------------------------------------------------------------------- */ - /* Map Projection Parameters (all 0.0). */ - /* -------------------------------------------------------------------- */ - for (int i = 0; i < 15; i++) - TextFillR(achARec + 168 + i * 24, 24, "0.0"); - - /* -------------------------------------------------------------------- */ - /* Horizontal Unit of Measure */ - /* 0 = radians */ - /* 1 = feet */ - /* 2 = meters */ - /* 3 = arc seconds */ - /* -------------------------------------------------------------------- */ - if (!psWInfo->utmzone) - { - TextFillR(achARec + 528, 6, "3"); - } - else - { - TextFillR(achARec + 528, 6, "2"); - } - - /* -------------------------------------------------------------------- */ - /* Vertical unit of measure. */ - /* 1 = feet */ - /* 2 = meters */ - /* -------------------------------------------------------------------- */ - TextFillR(achARec + 534, 6, "2"); - - /* -------------------------------------------------------------------- */ - /* Number of sides in coverage polygon (always 4) */ - /* -------------------------------------------------------------------- */ - TextFillR(achARec + 540, 6, "4"); - - /* -------------------------------------------------------------------- */ - /* 4 corner coordinates: SW, NW, NE, SE */ - /* Corners are in 24.15 format in arc seconds. */ - /* -------------------------------------------------------------------- */ - if (!psWInfo->utmzone) - { - // SW - longitude - USGSDEMPrintDouble(achARec + 546, psWInfo->dfLLX * 3600.0); - // SW - latitude - USGSDEMPrintDouble(achARec + 570, psWInfo->dfLLY * 3600.0); - - // NW - longitude - USGSDEMPrintDouble(achARec + 594, psWInfo->dfULX * 3600.0); - // NW - latitude - USGSDEMPrintDouble(achARec + 618, psWInfo->dfULY * 3600.0); - - // NE - longitude - USGSDEMPrintDouble(achARec + 642, psWInfo->dfURX * 3600.0); - // NE - latitude - USGSDEMPrintDouble(achARec + 666, psWInfo->dfURY * 3600.0); - - // SE - longitude - USGSDEMPrintDouble(achARec + 690, psWInfo->dfLRX * 3600.0); - // SE - latitude - USGSDEMPrintDouble(achARec + 714, psWInfo->dfLRY * 3600.0); - } - else - { - // SW - easting - USGSDEMPrintDouble(achARec + 546, psWInfo->dfLLX); - // SW - northing - USGSDEMPrintDouble(achARec + 570, psWInfo->dfLLY); - - // NW - easting - USGSDEMPrintDouble(achARec + 594, psWInfo->dfULX); - // NW - northing - USGSDEMPrintDouble(achARec + 618, psWInfo->dfULY); - - // NE - easting - USGSDEMPrintDouble(achARec + 642, psWInfo->dfURX); - // NE - northing - USGSDEMPrintDouble(achARec + 666, psWInfo->dfURY); - - // SE - easting - USGSDEMPrintDouble(achARec + 690, psWInfo->dfLRX); - // SE - northing - USGSDEMPrintDouble(achARec + 714, psWInfo->dfLRY); - } - - /* -------------------------------------------------------------------- */ - /* Minimum and Maximum elevations for this cell. */ - /* 24.15 format. */ - /* -------------------------------------------------------------------- */ - GInt16 nMin = DEM_NODATA; - GInt16 nMax = DEM_NODATA; - int nVoid = 0; - - for (int i = psWInfo->nXSize * psWInfo->nYSize - 1; i >= 0; i--) - { - if (psWInfo->panData[i] != DEM_NODATA) - { - if (nMin == DEM_NODATA) - { - nMin = psWInfo->panData[i]; - nMax = nMin; - } - else - { - nMin = std::min(nMin, psWInfo->panData[i]); - nMax = std::max(nMax, psWInfo->panData[i]); - } - } - else - nVoid++; - } - - /* take into account z resolutions that are not 1.0 */ - nMin = static_cast(std::floor(nMin * psWInfo->dfElevStepSize)); - nMax = static_cast(std::ceil(nMax * psWInfo->dfElevStepSize)); - - USGSDEMPrintDouble(achARec + 738, static_cast(nMin)); - USGSDEMPrintDouble(achARec + 762, static_cast(nMax)); - - /* -------------------------------------------------------------------- */ - /* Counter Clockwise angle (in radians). Normally 0 */ - /* -------------------------------------------------------------------- */ - TextFillR(achARec + 786, 24, "0.0"); - - /* -------------------------------------------------------------------- */ - /* Accuracy code for elevations. 0 means there will be no C */ - /* record. */ - /* -------------------------------------------------------------------- */ - TextFillR(achARec + 810, 6, "0"); - - /* -------------------------------------------------------------------- */ - /* Spatial Resolution (x, y and z). 12.6 format. */ - /* -------------------------------------------------------------------- */ - if (!psWInfo->utmzone) - { - USGSDEMPrintSingle(achARec + 816, psWInfo->dfHorizStepSize * 3600.0); - USGSDEMPrintSingle(achARec + 828, psWInfo->dfVertStepSize * 3600.0); - } - else - { - USGSDEMPrintSingle(achARec + 816, psWInfo->dfHorizStepSize); - USGSDEMPrintSingle(achARec + 828, psWInfo->dfVertStepSize); - } - - USGSDEMPrintSingle(achARec + 840, psWInfo->dfElevStepSize); - - /* -------------------------------------------------------------------- */ - /* Rows and Columns of profiles. */ - /* -------------------------------------------------------------------- */ - TextFillR(achARec + 852, 6, CPLSPrintf("%d", 1)); - TextFillR(achARec + 858, 6, CPLSPrintf("%d", psWInfo->nXSize)); - - /* -------------------------------------------------------------------- */ - /* Largest primary contour interval (blank). */ - /* -------------------------------------------------------------------- */ - TextFill(achARec + 864, 5, ""); - - /* -------------------------------------------------------------------- */ - /* Largest source contour internal unit (blank). */ - /* -------------------------------------------------------------------- */ - TextFill(achARec + 869, 1, ""); - - /* -------------------------------------------------------------------- */ - /* Smallest primary contour interval. */ - /* -------------------------------------------------------------------- */ - TextFill(achARec + 870, 5, ""); - - /* -------------------------------------------------------------------- */ - /* Smallest source contour interval unit. */ - /* -------------------------------------------------------------------- */ - TextFill(achARec + 875, 1, ""); - - /* -------------------------------------------------------------------- */ - /* Data source data - YYMM */ - /* -------------------------------------------------------------------- */ - if (pszTemplate == nullptr) - TextFill(achARec + 876, 4, ""); - - /* -------------------------------------------------------------------- */ - /* Data inspection/revision data (YYMM). */ - /* -------------------------------------------------------------------- */ - if (pszTemplate == nullptr) - TextFill(achARec + 880, 4, ""); - - /* -------------------------------------------------------------------- */ - /* Inspection revision flag (I or R) (blank) */ - /* -------------------------------------------------------------------- */ - if (pszTemplate == nullptr) - TextFill(achARec + 884, 1, ""); - - /* -------------------------------------------------------------------- */ - /* Data validation flag. */ - /* -------------------------------------------------------------------- */ - if (pszTemplate == nullptr) - TextFill(achARec + 885, 1, ""); - - /* -------------------------------------------------------------------- */ - /* Suspect and void area flag. */ - /* 0 = none */ - /* 1 = suspect areas */ - /* 2 = void areas */ - /* 3 = suspect and void areas */ - /* -------------------------------------------------------------------- */ - if (nVoid > 0) - TextFillR(achARec + 886, 2, "2"); - else - TextFillR(achARec + 886, 2, "0"); - - /* -------------------------------------------------------------------- */ - /* Vertical datum */ - /* 1 = MSL */ - /* 2 = NGVD29 */ - /* 3 = NAVD88 */ - /* -------------------------------------------------------------------- */ - if (pszTemplate == nullptr) - TextFillR(achARec + 888, 2, "1"); - - /* -------------------------------------------------------------------- */ - /* Horizontal Datum */ - /* 1 = NAD27 */ - /* 2 = WGS72 */ - /* 3 = WGS84 */ - /* 4 = NAD83 */ - /* -------------------------------------------------------------------- */ - if (strlen(psWInfo->horizdatum) == 0) - { - if (pszTemplate == nullptr) - TextFillR(achARec + 890, 2, "4"); - } - else - { - if (pszTemplate == nullptr) - TextFillR(achARec + 890, 2, psWInfo->horizdatum); - } - - /* -------------------------------------------------------------------- */ - /* Data edition/version, specification edition/version. */ - /* -------------------------------------------------------------------- */ - pszOption = CSLFetchNameValue(psWInfo->papszOptions, "DataSpecVersion"); - - if (pszOption != nullptr) - TextFill(achARec + 892, 4, pszOption); - - else if (pszTemplate == nullptr) - TextFill(achARec + 892, 4, ""); - - /* -------------------------------------------------------------------- */ - /* Percent void. */ - /* */ - /* Round to nearest integer percentage. */ - /* -------------------------------------------------------------------- */ - int nPercent = static_cast( - ((nVoid * 100.0) / (psWInfo->nXSize * psWInfo->nYSize)) + 0.5); - - TextFillR(achARec + 896, 4, CPLSPrintf("%4d", nPercent)); - - /* -------------------------------------------------------------------- */ - /* Edge matching flags. */ - /* -------------------------------------------------------------------- */ - if (pszTemplate == nullptr) - TextFill(achARec + 900, 8, ""); - - /* -------------------------------------------------------------------- */ - /* Vertical datum shift (F7.2). */ - /* -------------------------------------------------------------------- */ - TextFillR(achARec + 908, 7, ""); - - /* -------------------------------------------------------------------- */ - /* Write to file. */ - /* -------------------------------------------------------------------- */ - if (VSIFWriteL(achARec, 1, 1024, psWInfo->fp) != 1024) - { - CPLError(CE_Failure, CPLE_FileIO, - "Error writing DEM/CDED A record.\n%s", VSIStrerror(errno)); - return FALSE; - } - - return TRUE; -} - -/************************************************************************/ -/* USGSDEMWriteProfile() */ -/* */ -/* Write B logical record. Split into 1024 byte chunks. */ -/************************************************************************/ - -static int USGSDEMWriteProfile(USGSDEMWriteInfo *psWInfo, int iProfile) - -{ - char achBuffer[1024]; - - memset(achBuffer, ' ', sizeof(achBuffer)); - - /* -------------------------------------------------------------------- */ - /* Row #. */ - /* -------------------------------------------------------------------- */ - TextFillR(achBuffer + 0, 6, "1"); - - /* -------------------------------------------------------------------- */ - /* Column #. */ - /* -------------------------------------------------------------------- */ - TextFillR(achBuffer + 6, 6, CPLSPrintf("%d", iProfile + 1)); - - /* -------------------------------------------------------------------- */ - /* Number of data items. */ - /* -------------------------------------------------------------------- */ - TextFillR(achBuffer + 12, 6, CPLSPrintf("%d", psWInfo->nYSize)); - TextFillR(achBuffer + 18, 6, "1"); - - /* -------------------------------------------------------------------- */ - /* Location of center of bottom most sample in profile. */ - /* Format D24.15. In arc-seconds if geographic, meters */ - /* if UTM. */ - /* -------------------------------------------------------------------- */ - if (!psWInfo->utmzone) - { - // longitude - USGSDEMPrintDouble( - achBuffer + 24, - 3600 * (psWInfo->dfLLX + iProfile * psWInfo->dfHorizStepSize)); - - // latitude - USGSDEMPrintDouble(achBuffer + 48, psWInfo->dfLLY * 3600.0); - } - else - { - // easting - USGSDEMPrintDouble( - achBuffer + 24, - (psWInfo->dfLLX + iProfile * psWInfo->dfHorizStepSize)); - - // northing - USGSDEMPrintDouble(achBuffer + 48, psWInfo->dfLLY); - } - - /* -------------------------------------------------------------------- */ - /* Local vertical datum offset. */ - /* -------------------------------------------------------------------- */ - TextFillR(achBuffer + 72, 24, "0.000000D+00"); - - /* -------------------------------------------------------------------- */ - /* Min/Max elevation values for this profile. */ - /* -------------------------------------------------------------------- */ - GInt16 nMin = DEM_NODATA; - GInt16 nMax = DEM_NODATA; - - for (int iY = 0; iY < psWInfo->nYSize; iY++) - { - const int iData = - (psWInfo->nYSize - iY - 1) * psWInfo->nXSize + iProfile; - - if (psWInfo->panData[iData] != DEM_NODATA) - { - if (nMin == DEM_NODATA) - { - nMin = psWInfo->panData[iData]; - nMax = nMin; - } - else - { - nMin = std::min(nMin, psWInfo->panData[iData]); - nMax = std::max(nMax, psWInfo->panData[iData]); - } - } - } - - /* take into account z resolutions that are not 1.0 */ - nMin = static_cast(std::floor(nMin * psWInfo->dfElevStepSize)); - nMax = static_cast(std::ceil(nMax * psWInfo->dfElevStepSize)); - - USGSDEMPrintDouble(achBuffer + 96, static_cast(nMin)); - USGSDEMPrintDouble(achBuffer + 120, static_cast(nMax)); - - /* -------------------------------------------------------------------- */ - /* Output all the actually elevation values, flushing blocks */ - /* when they fill up. */ - /* -------------------------------------------------------------------- */ - int iOffset = 144; - - for (int iY = 0; iY < psWInfo->nYSize; iY++) - { - const int iData = - (psWInfo->nYSize - iY - 1) * psWInfo->nXSize + iProfile; - - if (iOffset + 6 > 1024) - { - if (VSIFWriteL(achBuffer, 1, 1024, psWInfo->fp) != 1024) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failure writing profile to disk.\n%s", - VSIStrerror(errno)); - return FALSE; - } - iOffset = 0; - memset(achBuffer, ' ', 1024); - } - - char szWord[10]; - snprintf(szWord, sizeof(szWord), "%d", psWInfo->panData[iData]); - TextFillR(achBuffer + iOffset, 6, szWord); - - iOffset += 6; - } - - /* -------------------------------------------------------------------- */ - /* Flush final partial block. */ - /* -------------------------------------------------------------------- */ - if (VSIFWriteL(achBuffer, 1, 1024, psWInfo->fp) != 1024) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failure writing profile to disk.\n%s", VSIStrerror(errno)); - return FALSE; - } - - return TRUE; -} - -/************************************************************************/ -/* USGSDEM_LookupNTSByLoc() */ -/************************************************************************/ - -static bool USGSDEM_LookupNTSByLoc(double dfULLong, double dfULLat, - char *pszTile, char *pszName) - -{ - /* -------------------------------------------------------------------- */ - /* Access NTS 1:50k sheet CSV file. */ - /* -------------------------------------------------------------------- */ - const char *pszNTSFilename = CSVFilename("NTS-50kindex.csv"); - - FILE *fpNTS = VSIFOpen(pszNTSFilename, "rb"); - if (fpNTS == nullptr) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to find NTS mapsheet lookup file: %s", pszNTSFilename); - return false; - } - - /* -------------------------------------------------------------------- */ - /* Skip column titles line. */ - /* -------------------------------------------------------------------- */ - CSLDestroy(CSVReadParseLine(fpNTS)); - - /* -------------------------------------------------------------------- */ - /* Find desired sheet. */ - /* -------------------------------------------------------------------- */ - bool bGotHit = false; - char **papszTokens = nullptr; - - while (!bGotHit && (papszTokens = CSVReadParseLine(fpNTS)) != nullptr) - { - if (CSLCount(papszTokens) != 4) - { - CSLDestroy(papszTokens); - continue; - } - - if (std::abs(dfULLong - CPLAtof(papszTokens[2])) < 0.01 && - std::abs(dfULLat - CPLAtof(papszTokens[3])) < 0.01) - { - bGotHit = true; - strncpy(pszTile, papszTokens[0], 7); - if (pszName != nullptr) - strncpy(pszName, papszTokens[1], 100); - } - - CSLDestroy(papszTokens); - } - - CPL_IGNORE_RET_VAL(VSIFClose(fpNTS)); - - return bGotHit; -} - -/************************************************************************/ -/* USGSDEM_LookupNTSByTile() */ -/************************************************************************/ - -static bool USGSDEM_LookupNTSByTile(const char *pszTile, char *pszName, - double *pdfULLong, double *pdfULLat) - -{ - /* -------------------------------------------------------------------- */ - /* Access NTS 1:50k sheet CSV file. */ - /* -------------------------------------------------------------------- */ - const char *pszNTSFilename = CSVFilename("NTS-50kindex.csv"); - FILE *fpNTS = VSIFOpen(pszNTSFilename, "rb"); - if (fpNTS == nullptr) - { - CPLError(CE_Failure, CPLE_FileIO, - "Unable to find NTS mapsheet lookup file: %s", pszNTSFilename); - return false; - } - - /* -------------------------------------------------------------------- */ - /* Skip column titles line. */ - /* -------------------------------------------------------------------- */ - CSLDestroy(CSVReadParseLine(fpNTS)); - - /* -------------------------------------------------------------------- */ - /* Find desired sheet. */ - /* -------------------------------------------------------------------- */ - bool bGotHit = false; - char **papszTokens = nullptr; - - while (!bGotHit && (papszTokens = CSVReadParseLine(fpNTS)) != nullptr) - { - if (CSLCount(papszTokens) != 4) - { - CSLDestroy(papszTokens); - continue; - } - - if (EQUAL(pszTile, papszTokens[0])) - { - bGotHit = true; - if (pszName != nullptr) - strncpy(pszName, papszTokens[1], 100); - *pdfULLong = CPLAtof(papszTokens[2]); - *pdfULLat = CPLAtof(papszTokens[3]); - } - - CSLDestroy(papszTokens); - } - - CPL_IGNORE_RET_VAL(VSIFClose(fpNTS)); - - return bGotHit; -} - -/************************************************************************/ -/* USGSDEMProductSetup_CDED50K() */ -/************************************************************************/ - -static int USGSDEMProductSetup_CDED50K(USGSDEMWriteInfo *psWInfo) - -{ - /* -------------------------------------------------------------------- */ - /* Fetch TOPLEFT location so we know what cell we are dealing */ - /* with. */ - /* -------------------------------------------------------------------- */ - const char *pszNTS = CSLFetchNameValue(psWInfo->papszOptions, "NTS"); - const char *pszTOPLEFT = - CSLFetchNameValue(psWInfo->papszOptions, "TOPLEFT"); - double dfULX = (psWInfo->dfULX + psWInfo->dfURX) * 0.5; - double dfULY = (psWInfo->dfULY + psWInfo->dfURY) * 0.5; - - // Have we been given an explicit NTS mapsheet name? - if (pszNTS != nullptr) - { - char szTrimmedTile[7]; - - strncpy(szTrimmedTile, pszNTS, 6); - szTrimmedTile[6] = '\0'; - - if (!USGSDEM_LookupNTSByTile(szTrimmedTile, nullptr, &dfULX, &dfULY)) - return FALSE; - - if (STARTS_WITH_CI(pszNTS + 6, "e")) - dfULX += ((dfULY < 68.1) ? 0.25 : (dfULY < 80.1) ? 0.5 : 1); - } - - // Try looking up TOPLEFT as a NTS mapsheet name. - else if (pszTOPLEFT != nullptr && strstr(pszTOPLEFT, ",") == nullptr && - (strlen(pszTOPLEFT) == 6 || strlen(pszTOPLEFT) == 7)) - { - char szTrimmedTile[7]; - - strncpy(szTrimmedTile, pszTOPLEFT, 6); - szTrimmedTile[6] = '\0'; - - if (!USGSDEM_LookupNTSByTile(szTrimmedTile, nullptr, &dfULX, &dfULY)) - return FALSE; - - if (EQUAL(pszTOPLEFT + 6, "e")) - dfULX += ((dfULY < 68.1) ? 0.25 : (dfULY < 80.1) ? 0.5 : 1); - } - - // Assume TOPLEFT is a long/lat corner. - else if (pszTOPLEFT != nullptr) - { - char **papszTokens = CSLTokenizeString2(pszTOPLEFT, ",", 0); - - if (CSLCount(papszTokens) != 2) - { - CSLDestroy(papszTokens); - CPLError(CE_Failure, CPLE_AppDefined, - "Failed to parse TOPLEFT, should have form like " - "'138d15W,59d0N'."); - return FALSE; - } - - dfULX = CPLDMSToDec(papszTokens[0]); - dfULY = CPLDMSToDec(papszTokens[1]); - CSLDestroy(papszTokens); - - if (std::abs(dfULX * 4 - floor(dfULX * 4 + 0.00005)) > 0.0001 || - std::abs(dfULY * 4 - floor(dfULY * 4 + 0.00005)) > 0.0001) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "TOPLEFT must be on a 15\" boundary for CDED50K, but is not."); - return FALSE; - } - } - else if (strlen(psWInfo->pszFilename) == 12 && - psWInfo->pszFilename[6] == '_' && - EQUAL(psWInfo->pszFilename + 8, ".dem")) - { - char szTrimmedTile[7]; - - strncpy(szTrimmedTile, psWInfo->pszFilename, 6); - szTrimmedTile[6] = '\0'; - - if (!USGSDEM_LookupNTSByTile(szTrimmedTile, nullptr, &dfULX, &dfULY)) - return FALSE; - - if (STARTS_WITH_CI(psWInfo->pszFilename + 7, "e")) - dfULX += ((dfULY < 68.1) ? 0.25 : (dfULY < 80.1) ? 0.5 : 1); - } - - else if (strlen(psWInfo->pszFilename) == 14 && - STARTS_WITH_CI(psWInfo->pszFilename + 6, "DEM") && - EQUAL(psWInfo->pszFilename + 10, ".dem")) - { - char szTrimmedTile[7]; - - strncpy(szTrimmedTile, psWInfo->pszFilename, 6); - szTrimmedTile[6] = '\0'; - - if (!USGSDEM_LookupNTSByTile(szTrimmedTile, nullptr, &dfULX, &dfULY)) - return FALSE; - - if (STARTS_WITH_CI(psWInfo->pszFilename + 9, "e")) - dfULX += ((dfULY < 68.1) ? 0.25 : (dfULY < 80.1) ? 0.5 : 1); - } - - /* -------------------------------------------------------------------- */ - /* Set resolution and size information. */ - /* -------------------------------------------------------------------- */ - - dfULX = floor(dfULX * 4 + 0.00005) / 4.0; - dfULY = floor(dfULY * 4 + 0.00005) / 4.0; - - psWInfo->nXSize = 1201; - psWInfo->nYSize = 1201; - psWInfo->dfVertStepSize = 0.75 / 3600.0; - - /* Region A */ - if (dfULY < 68.1) - { - psWInfo->dfHorizStepSize = 0.75 / 3600.0; - } - - /* Region B */ - else if (dfULY < 80.1) - { - psWInfo->dfHorizStepSize = 1.5 / 3600.0; - dfULX = floor(dfULX * 2 + 0.001) / 2.0; - } - - /* Region C */ - else - { - psWInfo->dfHorizStepSize = 3.0 / 3600.0; - dfULX = floor(dfULX + 0.001); - } - - /* -------------------------------------------------------------------- */ - /* Set bounds based on this top left anchor. */ - /* -------------------------------------------------------------------- */ - - psWInfo->dfULX = dfULX; - psWInfo->dfULY = dfULY; - psWInfo->dfLLX = dfULX; - psWInfo->dfLLY = dfULY - 0.25; - psWInfo->dfURX = dfULX + psWInfo->dfHorizStepSize * 1200.0; - psWInfo->dfURY = dfULY; - psWInfo->dfLRX = dfULX + psWInfo->dfHorizStepSize * 1200.0; - psWInfo->dfLRY = dfULY - 0.25; - - /* -------------------------------------------------------------------- */ - /* Can we find the NTS 50k tile name that corresponds with */ - /* this? */ - /* -------------------------------------------------------------------- */ - const char *pszINTERNAL = - CSLFetchNameValue(psWInfo->papszOptions, "INTERNALNAME"); - char szTile[10]; - char chEWFlag = ' '; - - if (USGSDEM_LookupNTSByLoc(dfULX, dfULY, szTile, nullptr)) - { - chEWFlag = 'w'; - } - else if (USGSDEM_LookupNTSByLoc(dfULX - 0.25, dfULY, szTile, nullptr)) - { - chEWFlag = 'e'; - } - - if (pszINTERNAL != nullptr) - { - CPLFree(psWInfo->pszFilename); - psWInfo->pszFilename = CPLStrdup(pszINTERNAL); - } - else if (chEWFlag != ' ') - { - CPLFree(psWInfo->pszFilename); - psWInfo->pszFilename = - CPLStrdup(CPLSPrintf("%sDEM%c", szTile, chEWFlag)); - } - else - { - const char *pszBasename = CPLGetFilename(psWInfo->pszFilename); - if (!STARTS_WITH_CI(pszBasename + 6, "DEM") || - strlen(pszBasename) != 10) - CPLError( - CE_Warning, CPLE_AppDefined, - "Internal filename required to be of 'nnnannDEMz', the output\n" - "filename is not of the required format, and the tile could " - "not be\n" - "identified in the NTS mapsheet list (or the NTS mapsheet " - "could not\n" - "be found). Correct output filename for correct CDED " - "production."); - } - - /* -------------------------------------------------------------------- */ - /* Set some specific options for CDED 50K. */ - /* -------------------------------------------------------------------- */ - psWInfo->papszOptions = - CSLSetNameValue(psWInfo->papszOptions, "DEMLevelCode", "1"); - - if (CSLFetchNameValue(psWInfo->papszOptions, "DataSpecVersion") == nullptr) - psWInfo->papszOptions = - CSLSetNameValue(psWInfo->papszOptions, "DataSpecVersion", "1020"); - - /* -------------------------------------------------------------------- */ - /* Set the destination coordinate system. */ - /* -------------------------------------------------------------------- */ - OGRSpatialReference oSRS; - oSRS.SetWellKnownGeogCS("NAD83"); - strncpy(psWInfo->horizdatum, "4", 2); // USGS DEM code for NAD83 - - oSRS.exportToWkt(&(psWInfo->pszDstSRS)); - - /* -------------------------------------------------------------------- */ - /* Cleanup. */ - /* -------------------------------------------------------------------- */ - CPLReadLine(nullptr); - - return TRUE; -} - -/************************************************************************/ -/* USGSDEMProductSetup_DEFAULT() */ -/* */ -/* Sets up the new DEM dataset parameters, using the source */ -/* dataset's parameters. If the source dataset uses UTM or */ -/* geographic coordinates, the coordinate system is carried over */ -/* to the new DEM file's parameters. If the source dataset has a */ -/* DEM compatible horizontal datum, the datum is carried over. */ -/* Otherwise, the DEM dataset is configured to use geographic */ -/* coordinates and a default datum. */ -/* (Hunter Blanks, 8/31/04, hblanks@artifex.org) */ -/************************************************************************/ - -static int USGSDEMProductSetup_DEFAULT(USGSDEMWriteInfo *psWInfo) - -{ - - /* -------------------------------------------------------------------- */ - /* Set the destination coordinate system. */ - /* -------------------------------------------------------------------- */ - OGRSpatialReference DstoSRS; - OGRSpatialReference SrcoSRS; - int bNorth = TRUE; - const int numdatums = 4; - const char DatumCodes[4][2] = {"1", "2", "3", "4"}; - const char Datums[4][6] = {"NAD27", "WGS72", "WGS84", "NAD83"}; - - /* get the source dataset's projection */ - const char *sourceWkt = psWInfo->poSrcDS->GetProjectionRef(); - if (SrcoSRS.importFromWkt(sourceWkt) != OGRERR_NONE) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "DEM Default Setup: Importing source dataset projection failed"); - return FALSE; - } - - /* Set the destination dataset's projection. If the source datum - * used is DEM compatible, just use it. Otherwise, default to the - * last datum in the Datums array. - */ - int i = 0; - for (; i < numdatums; i++) - { - if (DstoSRS.SetWellKnownGeogCS(Datums[i]) != OGRERR_NONE) - { - CPLError(CE_Failure, CPLE_AppDefined, - "DEM Default Setup: Failed to set datum of destination"); - return FALSE; - } - /* XXX Hopefully it is ok, to just keep changing the projection - * of our destination. If not, we'll want to reinitialize the - * OGRSpatialReference each time. - */ - if (DstoSRS.IsSameGeogCS(&SrcoSRS)) - { - break; - } - } - if (i == numdatums) - { - i = numdatums - 1; - } - CPLStrlcpy(psWInfo->horizdatum, DatumCodes[i], 2); - - /* get the UTM zone, if any */ - psWInfo->utmzone = SrcoSRS.GetUTMZone(&bNorth); - if (psWInfo->utmzone) - { - if (DstoSRS.SetUTM(psWInfo->utmzone, bNorth) != OGRERR_NONE) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "DEM Default Setup: Failed to set utm zone of destination"); - /* SetUTM isn't documented to return OGRERR_NONE - * on success, but it does, so, we'll check for it. - */ - return FALSE; - } - if (!bNorth) - psWInfo->utmzone = -psWInfo->utmzone; - } - - /* export the projection to sWInfo */ - if (DstoSRS.exportToWkt(&(psWInfo->pszDstSRS)) != OGRERR_NONE) - { - CPLError(CE_Failure, CPLE_AppDefined, - "UTMDEM: Failed to export destination Wkt to psWInfo"); - } - return TRUE; -} - -/************************************************************************/ -/* USGSDEMLoadRaster() */ -/* */ -/* Loads the raster from the source dataset (not normally USGS */ -/* DEM) into memory. If nodata is marked, a special effort is */ -/* made to translate it properly into the USGS nodata value. */ -/************************************************************************/ - -static int USGSDEMLoadRaster(CPL_UNUSED USGSDEMWriteInfo *psWInfo, - CPL_UNUSED GDALRasterBand *poSrcBand) -{ - /* -------------------------------------------------------------------- */ - /* Allocate output array, and pre-initialize to NODATA value. */ - /* -------------------------------------------------------------------- */ - psWInfo->panData = reinterpret_cast( - VSI_MALLOC3_VERBOSE(2, psWInfo->nXSize, psWInfo->nYSize)); - if (psWInfo->panData == nullptr) - { - return FALSE; - } - - for (int i = 0; i < psWInfo->nXSize * psWInfo->nYSize; i++) - psWInfo->panData[i] = DEM_NODATA; - - /* -------------------------------------------------------------------- */ - /* Make a "memory dataset" wrapper for this data array. */ - /* -------------------------------------------------------------------- */ - auto poMemDS = std::unique_ptr( - MEMDataset::Create("USGSDEM_temp", psWInfo->nXSize, psWInfo->nYSize, 0, - GDT_Int16, nullptr)); - - /* -------------------------------------------------------------------- */ - /* Now add the array itself as a band. */ - /* -------------------------------------------------------------------- */ - auto hBand = MEMCreateRasterBandEx( - poMemDS.get(), 1, reinterpret_cast(psWInfo->panData), - GDT_Int16, 0, 0, false); - poMemDS->AddMEMBand(hBand); - - /* -------------------------------------------------------------------- */ - /* Assign geotransform and nodata indicators. */ - /* -------------------------------------------------------------------- */ - double adfGeoTransform[6]; - - adfGeoTransform[0] = psWInfo->dfULX - psWInfo->dfHorizStepSize * 0.5; - adfGeoTransform[1] = psWInfo->dfHorizStepSize; - adfGeoTransform[2] = 0.0; - adfGeoTransform[3] = psWInfo->dfULY + psWInfo->dfVertStepSize * 0.5; - adfGeoTransform[4] = 0.0; - adfGeoTransform[5] = -psWInfo->dfVertStepSize; - - poMemDS->SetGeoTransform(adfGeoTransform); - - /* -------------------------------------------------------------------- */ - /* Set coordinate system if we have a special one to set. */ - /* -------------------------------------------------------------------- */ - if (psWInfo->pszDstSRS) - poMemDS->SetProjection(psWInfo->pszDstSRS); - - /* -------------------------------------------------------------------- */ - /* Establish the resampling kernel to use. */ - /* -------------------------------------------------------------------- */ - GDALResampleAlg eResampleAlg = GRA_Bilinear; - const char *pszResample = - CSLFetchNameValue(psWInfo->papszOptions, "RESAMPLE"); - - if (pszResample == nullptr) - /* bilinear */; - else if (EQUAL(pszResample, "Nearest")) - eResampleAlg = GRA_NearestNeighbour; - else if (EQUAL(pszResample, "Bilinear")) - eResampleAlg = GRA_Bilinear; - else if (EQUAL(pszResample, "Cubic")) - eResampleAlg = GRA_Cubic; - else if (EQUAL(pszResample, "CubicSpline")) - eResampleAlg = GRA_CubicSpline; - else - { - CPLError(CE_Failure, CPLE_NotSupported, - "RESAMPLE=%s, not a supported resampling kernel.", - pszResample); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Perform a warp from source dataset to destination buffer */ - /* (memory dataset). */ - /* -------------------------------------------------------------------- */ - CPLErr eErr = GDALReprojectImage( - (GDALDatasetH)psWInfo->poSrcDS, psWInfo->poSrcDS->GetProjectionRef(), - GDALDataset::ToHandle(poMemDS.get()), psWInfo->pszDstSRS, eResampleAlg, - 0.0, 0.0, nullptr, nullptr, nullptr); - - return eErr == CE_None; -} - -/************************************************************************/ -/* CreateCopy() */ -/************************************************************************/ - -GDALDataset *USGSDEMCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - CPL_UNUSED GDALProgressFunc pfnProgress, - CPL_UNUSED void *pProgressData) -{ - if (poSrcDS->GetRasterCount() != 1) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Unable to create multi-band USGS DEM / CDED files."); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Capture some preliminary information. */ - /* -------------------------------------------------------------------- */ - USGSDEMWriteInfo sWInfo; - memset(&sWInfo, 0, sizeof(sWInfo)); - - sWInfo.poSrcDS = poSrcDS; - sWInfo.pszFilename = CPLStrdup(pszFilename); - sWInfo.nXSize = poSrcDS->GetRasterXSize(); - sWInfo.nYSize = poSrcDS->GetRasterYSize(); - sWInfo.papszOptions = CSLDuplicate(papszOptions); - sWInfo.bStrict = bStrict; - sWInfo.utmzone = 0; - strncpy(sWInfo.horizdatum, "", 1); - - if (sWInfo.nXSize <= 1 || sWInfo.nYSize <= 1) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Source dataset dimensions must be at least 2x2."); - USGSDEMWriteCleanup(&sWInfo); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Work out corner coordinates. */ - /* -------------------------------------------------------------------- */ - double adfGeoTransform[6]; - - poSrcDS->GetGeoTransform(adfGeoTransform); - - sWInfo.dfLLX = adfGeoTransform[0] + adfGeoTransform[1] * 0.5; - sWInfo.dfLLY = - adfGeoTransform[3] + adfGeoTransform[5] * (sWInfo.nYSize - 0.5); - - sWInfo.dfULX = adfGeoTransform[0] + adfGeoTransform[1] * 0.5; - sWInfo.dfULY = adfGeoTransform[3] + adfGeoTransform[5] * 0.5; - - sWInfo.dfURX = - adfGeoTransform[0] + adfGeoTransform[1] * (sWInfo.nXSize - 0.5); - sWInfo.dfURY = adfGeoTransform[3] + adfGeoTransform[5] * 0.5; - - sWInfo.dfLRX = - adfGeoTransform[0] + adfGeoTransform[1] * (sWInfo.nXSize - 0.5); - sWInfo.dfLRY = - adfGeoTransform[3] + adfGeoTransform[5] * (sWInfo.nYSize - 0.5); - - sWInfo.dfHorizStepSize = - (sWInfo.dfURX - sWInfo.dfULX) / (sWInfo.nXSize - 1); - sWInfo.dfVertStepSize = (sWInfo.dfURY - sWInfo.dfLRY) / (sWInfo.nYSize - 1); - - /* -------------------------------------------------------------------- */ - /* Allow override of z resolution, but default to 1.0. */ - /* -------------------------------------------------------------------- */ - const char *zResolution = - CSLFetchNameValue(sWInfo.papszOptions, "ZRESOLUTION"); - - if (zResolution == nullptr || EQUAL(zResolution, "DEFAULT")) - { - sWInfo.dfElevStepSize = 1.0; - } - else - { - // XXX: We are using CPLAtof() here instead of CPLAtof() because - // zResolution value comes from user's input and supposed to be - // written according to user's current locale. CPLAtof() honors locale - // setting, CPLAtof() is not. - sWInfo.dfElevStepSize = CPLAtof(zResolution); - if (sWInfo.dfElevStepSize <= 0) - { - /* don't allow negative values */ - sWInfo.dfElevStepSize = 1.0; - } - } - - /* -------------------------------------------------------------------- */ - /* Initialize for special product configurations. */ - /* -------------------------------------------------------------------- */ - const char *pszProduct = CSLFetchNameValue(sWInfo.papszOptions, "PRODUCT"); - - if (pszProduct == nullptr || EQUAL(pszProduct, "DEFAULT")) - { - if (!USGSDEMProductSetup_DEFAULT(&sWInfo)) - { - USGSDEMWriteCleanup(&sWInfo); - return nullptr; - } - } - else if (EQUAL(pszProduct, "CDED50K")) - { - if (!USGSDEMProductSetup_CDED50K(&sWInfo)) - { - USGSDEMWriteCleanup(&sWInfo); - return nullptr; - } - } - else - { - CPLError(CE_Failure, CPLE_NotSupported, - "DEM PRODUCT='%s' not recognised.", pszProduct); - USGSDEMWriteCleanup(&sWInfo); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Read the whole area of interest into memory. */ - /* -------------------------------------------------------------------- */ - if (!USGSDEMLoadRaster(&sWInfo, poSrcDS->GetRasterBand(1))) - { - USGSDEMWriteCleanup(&sWInfo); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create the output file. */ - /* -------------------------------------------------------------------- */ - sWInfo.fp = VSIFOpenL(pszFilename, "wb"); - if (sWInfo.fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "%s", VSIStrerror(errno)); - USGSDEMWriteCleanup(&sWInfo); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Write the A record. */ - /* -------------------------------------------------------------------- */ - if (!USGSDEMWriteARecord(&sWInfo)) - { - USGSDEMWriteCleanup(&sWInfo); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Write profiles. */ - /* -------------------------------------------------------------------- */ - for (int iProfile = 0; iProfile < sWInfo.nXSize; iProfile++) - { - if (!USGSDEMWriteProfile(&sWInfo, iProfile)) - { - USGSDEMWriteCleanup(&sWInfo); - return nullptr; - } - } - - /* -------------------------------------------------------------------- */ - /* Cleanup. */ - /* -------------------------------------------------------------------- */ - USGSDEMWriteCleanup(&sWInfo); - - /* -------------------------------------------------------------------- */ - /* Re-open dataset, and copy any auxiliary pam information. */ - /* -------------------------------------------------------------------- */ - GDALPamDataset *poDS = - reinterpret_cast(GDALOpen(pszFilename, GA_ReadOnly)); - - if (poDS) - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - - return poDS; -} diff --git a/frmts/usgsdem/usgsdemdataset.cpp b/frmts/usgsdem/usgsdemdataset.cpp index ebc88a45f180..0ffdd5e284df 100644 --- a/frmts/usgsdem/usgsdemdataset.cpp +++ b/frmts/usgsdem/usgsdemdataset.cpp @@ -966,47 +966,10 @@ void GDALRegister_USGSDEM() "USGS Optional ASCII DEM (and CDED)"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/usgsdem.html"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Int16"); - poDriver->SetMetadataItem( - GDAL_DMD_CREATIONOPTIONLIST, - "" - " " - " " - " "); + poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); poDriver->pfnOpen = USGSDEMDataset::Open; - poDriver->pfnCreateCopy = USGSDEMCreateCopy; poDriver->pfnIdentify = USGSDEMDataset::Identify; GetGDALDriverManager()->RegisterDriver(poDriver); diff --git a/frmts/xpm/CMakeLists.txt b/frmts/xpm/CMakeLists.txt deleted file mode 100644 index a560b2967f98..000000000000 --- a/frmts/xpm/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_gdal_driver(TARGET gdal_XPM SOURCES xpmdataset.cpp PLUGIN_CAPABLE NO_DEPS) -gdal_standard_includes(gdal_XPM) -target_include_directories(gdal_XPM PRIVATE ${GDAL_RASTER_FORMAT_SOURCE_DIR}/mem) diff --git a/frmts/xpm/xpmdataset.cpp b/frmts/xpm/xpmdataset.cpp deleted file mode 100644 index 2623ce75eed1..000000000000 --- a/frmts/xpm/xpmdataset.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/****************************************************************************** - * - * Project: XPM Driver - * Purpose: Implement GDAL XPM Support - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2002, Frank Warmerdam - * Copyright (c) 2008-2010, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "gdal_pam.h" -#include "cpl_string.h" -#include "memdataset.h" -#include "gdal_frmts.h" - -#include -#include - -static unsigned char *ParseXPM(const char *pszInput, unsigned int nFileSize, - int *pnXSize, int *pnYSize, - GDALColorTable **ppoRetTable); - -/************************************************************************/ -/* ==================================================================== */ -/* XPMDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class XPMDataset final : public GDALPamDataset -{ - public: - XPMDataset() - { - } - - ~XPMDataset(); - - static GDALDataset *Open(GDALOpenInfo *); - static int Identify(GDALOpenInfo *); -}; - -/************************************************************************/ -/* ~XPMDataset() */ -/************************************************************************/ - -XPMDataset::~XPMDataset() - -{ - FlushCache(true); -} - -/************************************************************************/ -/* Identify() */ -/************************************************************************/ - -int XPMDataset::Identify(GDALOpenInfo *poOpenInfo) - -{ - /* -------------------------------------------------------------------- */ - /* First we check to see if the file has the expected header */ - /* bytes. For now we expect the XPM file to start with a line */ - /* containing the letters XPM, and to have "static" in the */ - /* header. */ - /* -------------------------------------------------------------------- */ - return poOpenInfo->nHeaderBytes >= 32 && - strstr(reinterpret_cast(poOpenInfo->pabyHeader), - "XPM") != nullptr && - strstr(reinterpret_cast(poOpenInfo->pabyHeader), - "static") != nullptr; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *XPMDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr) - return nullptr; - - if (poOpenInfo->eAccess == GA_Update) - { - CPLError(CE_Failure, CPLE_NotSupported, - "The XPM driver does not support update access to existing" - " files."); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Read the whole file into a memory strings. */ - /* -------------------------------------------------------------------- */ - VSILFILE *fp = poOpenInfo->fpL; - poOpenInfo->fpL = nullptr; - - if (VSIFSeekL(fp, 0, SEEK_END) != 0) - { - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - return nullptr; - } - unsigned int nFileSize = static_cast(VSIFTellL(fp)); - - char *pszFileContents = - reinterpret_cast(VSI_MALLOC_VERBOSE(nFileSize + 1)); - if (pszFileContents == nullptr) - { - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - return nullptr; - } - pszFileContents[nFileSize] = '\0'; - - if (VSIFSeekL(fp, 0, SEEK_SET) != 0 || - VSIFReadL(pszFileContents, 1, nFileSize, fp) != nFileSize) - { - CPLFree(pszFileContents); - CPLError(CE_Failure, CPLE_FileIO, - "Failed to read all %d bytes from file %s.", nFileSize, - poOpenInfo->pszFilename); - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - return nullptr; - } - - CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); - fp = nullptr; - - /* -------------------------------------------------------------------- */ - /* Convert into a binary image. */ - /* -------------------------------------------------------------------- */ - CPLErrorReset(); - - int nXSize; - int nYSize; - GDALColorTable *poCT = nullptr; - - GByte *pabyImage = - ParseXPM(pszFileContents, nFileSize, &nXSize, &nYSize, &poCT); - - CPLFree(pszFileContents); - - if (pabyImage == nullptr) - { - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Create a corresponding GDALDataset. */ - /* -------------------------------------------------------------------- */ - XPMDataset *poDS = new XPMDataset(); - - /* -------------------------------------------------------------------- */ - /* Capture some information from the file that is of interest. */ - /* -------------------------------------------------------------------- */ - poDS->nRasterXSize = nXSize; - poDS->nRasterYSize = nYSize; - - /* -------------------------------------------------------------------- */ - /* Create band information objects. */ - /* -------------------------------------------------------------------- */ - MEMRasterBand *poBand = - new MEMRasterBand(poDS, 1, pabyImage, GDT_Byte, 1, nXSize, TRUE); - poBand->SetColorTable(poCT); - poDS->SetBand(1, poBand); - - delete poCT; - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Support overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename); - - return poDS; -} - -/************************************************************************/ -/* XPMCreateCopy() */ -/************************************************************************/ - -static GDALDataset *XPMCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char ** /* papszOptions */, - GDALProgressFunc /* pfnProgress */, - void * /* pProgressData */) -{ - /* -------------------------------------------------------------------- */ - /* Some some rudimentary checks */ - /* -------------------------------------------------------------------- */ - const int nBands = poSrcDS->GetRasterCount(); - if (nBands != 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "XPM driver only supports one band images.\n"); - - return nullptr; - } - - if (poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte && bStrict) - { - CPLError(CE_Failure, CPLE_NotSupported, - "XPM driver doesn't support data type %s. " - "Only eight bit bands supported.\n", - GDALGetDataTypeName( - poSrcDS->GetRasterBand(1)->GetRasterDataType())); - - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* If there is no colortable on the source image, create a */ - /* greyscale one with 64 levels of grey. */ - /* -------------------------------------------------------------------- */ - GDALRasterBand *poBand = poSrcDS->GetRasterBand(1); - - GDALColorTable oGreyTable; - GDALColorTable *poCT = poBand->GetColorTable(); - - if (poCT == nullptr) - { - poCT = &oGreyTable; - - for (int i = 0; i < 256; i++) - { - GDALColorEntry sColor; - - sColor.c1 = (short)i; - sColor.c2 = (short)i; - sColor.c3 = (short)i; - sColor.c4 = 255; - - poCT->SetColorEntry(i, &sColor); - } - } - - /* -------------------------------------------------------------------- */ - /* Build list of active colors, and the mapping from pixels to */ - /* our active colormap. */ - /* -------------------------------------------------------------------- */ - const char *pszColorCodes = - " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@" - "#$%^&*()-+=[]|:;,.<>?/"; - - int anPixelMapping[256]; - GDALColorEntry asPixelColor[256]; - int nActiveColors = std::min(poCT->GetColorEntryCount(), 256); - - // Setup initial colortable and pixel value mapping. - memset(anPixelMapping + 0, 0, sizeof(int) * 256); - for (int i = 0; i < nActiveColors; i++) - { - poCT->GetColorEntryAsRGB(i, asPixelColor + i); - anPixelMapping[i] = i; - } - - /* ==================================================================== */ - /* Iterate merging colors until we are under our limit (about 85). */ - /* ==================================================================== */ - while (nActiveColors > static_cast(strlen(pszColorCodes))) - { - int nClosestDistance = 768; - int iClose1 = -1; - int iClose2 = -1; - - // Find the closest pair of colors. - for (int iColor1 = 0; iColor1 < nActiveColors; iColor1++) - { - for (int iColor2 = iColor1 + 1; iColor2 < nActiveColors; iColor2++) - { - int nDistance; - - if (asPixelColor[iColor1].c4 < 128 && - asPixelColor[iColor2].c4 < 128) - nDistance = 0; - else - nDistance = std::abs(asPixelColor[iColor1].c1 - - asPixelColor[iColor2].c1) + - std::abs(asPixelColor[iColor1].c2 - - asPixelColor[iColor2].c2) + - std::abs(asPixelColor[iColor1].c3 - - asPixelColor[iColor2].c3); - - if (nDistance < nClosestDistance) - { - nClosestDistance = nDistance; - iClose1 = iColor1; - iClose2 = iColor2; - } - } - - if (nClosestDistance < 8) - break; - } - - // This should never happen! - if (iClose1 == -1) - break; - - // Merge two selected colors - shift icolor2 into icolor1 and - // move the last active color into icolor2's slot. - for (int i = 0; i < 256; i++) - { - if (anPixelMapping[i] == iClose2) - anPixelMapping[i] = iClose1; - else if (anPixelMapping[i] == nActiveColors - 1) - anPixelMapping[i] = iClose2; - } - - asPixelColor[iClose2] = asPixelColor[nActiveColors - 1]; - nActiveColors--; - } - - /* ==================================================================== */ - /* Write the output image. */ - /* ==================================================================== */ - VSILFILE *fpPBM = VSIFOpenL(pszFilename, "wb+"); - if (fpPBM == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create file `%s'.", - pszFilename); - - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Write the header lines. */ - /* -------------------------------------------------------------------- */ - bool bOK = VSIFPrintfL(fpPBM, "/* XPM */\n") >= 0; - bOK &= VSIFPrintfL(fpPBM, "static char *%s[] = {\n", - CPLGetBasenameSafe(pszFilename).c_str()) >= 0; - bOK &= VSIFPrintfL(fpPBM, - "/* width height num_colors chars_per_pixel */\n") >= 0; - - const int nXSize = poSrcDS->GetRasterXSize(); - const int nYSize = poSrcDS->GetRasterYSize(); - - bOK &= VSIFPrintfL(fpPBM, "\" %3d %3d %3d 1\",\n", - nXSize, nYSize, nActiveColors) >= 0; - - bOK &= VSIFPrintfL(fpPBM, "/* colors */\n") >= 0; - - /* -------------------------------------------------------------------- */ - /* Write the color table. */ - /* -------------------------------------------------------------------- */ - for (int i = 0; bOK && i < nActiveColors; i++) - { - if (asPixelColor[i].c4 < 128) - bOK &= - VSIFPrintfL(fpPBM, "\"%c c None\",\n", pszColorCodes[i]) >= 0; - else - bOK &= VSIFPrintfL(fpPBM, "\"%c c #%02x%02x%02x\",\n", - pszColorCodes[i], asPixelColor[i].c1, - asPixelColor[i].c2, asPixelColor[i].c3) >= 0; - } - - /* -------------------------------------------------------------------- */ - /* Dump image. */ - /* -------------------------------------------------------------------- */ - GByte *pabyScanline = reinterpret_cast(CPLMalloc(nXSize)); - - for (int iLine = 0; bOK && iLine < nYSize; iLine++) - { - if (poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, - reinterpret_cast(pabyScanline), nXSize, 1, - GDT_Byte, 0, 0, nullptr) != CE_None) - { - CPLFree(pabyScanline); - CPL_IGNORE_RET_VAL(VSIFCloseL(fpPBM)); - return nullptr; - } - - bOK &= VSIFPutcL('"', fpPBM) >= 0; - for (int iPixel = 0; iPixel < nXSize; iPixel++) - bOK &= - VSIFPutcL(pszColorCodes[anPixelMapping[pabyScanline[iPixel]]], - fpPBM) >= 0; - bOK &= VSIFPrintfL(fpPBM, "\",\n") >= 0; - } - - CPLFree(pabyScanline); - - /* -------------------------------------------------------------------- */ - /* cleanup */ - /* -------------------------------------------------------------------- */ - bOK &= VSIFPrintfL(fpPBM, "};\n") >= 0; - if (VSIFCloseL(fpPBM) != 0) - bOK = false; - - if (!bOK) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Re-open dataset, and copy any auxiliary pam information. */ - /* -------------------------------------------------------------------- */ - GDALPamDataset *poDS = - reinterpret_cast(GDALOpen(pszFilename, GA_ReadOnly)); - - if (poDS) - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - - return poDS; -} - -/************************************************************************/ -/* GDALRegister_XPM() */ -/************************************************************************/ - -void GDALRegister_XPM() - -{ - if (GDALGetDriverByName("XPM") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("XPM"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "X11 PixMap Format"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/xpm.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xpm"); - poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/x-xpixmap"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = XPMDataset::Open; - poDriver->pfnIdentify = XPMDataset::Identify; - poDriver->pfnCreateCopy = XPMCreateCopy; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} - -/************************************************************************/ -/* ParseXPM() */ -/************************************************************************/ - -static unsigned char *ParseXPM(const char *pszInput, unsigned int nFileSize, - int *pnXSize, int *pnYSize, - GDALColorTable **ppoRetTable) - -{ - /* ==================================================================== */ - /* Parse input into an array of strings from within the first C */ - /* initializer (list os comma separated strings in braces). */ - /* ==================================================================== */ - const char *pszNext = pszInput; - - // Skip till after open brace. - while (*pszNext != '\0' && *pszNext != '{') - pszNext++; - - if (*pszNext == '\0') - return nullptr; - - pszNext++; - - // Read lines till close brace. - - char **papszXPMList = nullptr; - int i = 0; - - while (*pszNext != '\0' && *pszNext != '}') - { - // skip whole comment. - if (STARTS_WITH_CI(pszNext, "/*")) - { - pszNext += 2; - while (*pszNext != '\0' && !STARTS_WITH_CI(pszNext, "*/")) - pszNext++; - } - - // reading string constants - else if (*pszNext == '"') - { - pszNext++; - i = 0; - - while (pszNext[i] != '\0' && pszNext[i] != '"') - i++; - - if (pszNext[i] == '\0') - { - CSLDestroy(papszXPMList); - return nullptr; - } - - char *pszLine = reinterpret_cast(CPLMalloc(i + 1)); - strncpy(pszLine, pszNext, i); - pszLine[i] = '\0'; - - papszXPMList = CSLAddString(papszXPMList, pszLine); - CPLFree(pszLine); - pszNext = pszNext + i + 1; - } - - // just ignore everything else (whitespace, commas, newlines, etc). - else - pszNext++; - } - - if (papszXPMList == nullptr || CSLCount(papszXPMList) < 3 || - *pszNext != '}') - { - CSLDestroy(papszXPMList); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Get the image information. */ - /* -------------------------------------------------------------------- */ - int nColorCount, nCharsPerPixel; - - if (sscanf(papszXPMList[0], "%d %d %d %d", pnXSize, pnYSize, &nColorCount, - &nCharsPerPixel) != 4 || - *pnXSize <= 0 || *pnYSize <= 0 || nColorCount <= 0 || - nColorCount > 256 || - static_cast(*pnXSize) * static_cast(*pnYSize) > - nFileSize) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Image definition (%s) not well formed.", papszXPMList[0]); - CSLDestroy(papszXPMList); - return nullptr; - } - - if (nCharsPerPixel != 1) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Only one character per pixel XPM images supported by GDAL at " - "this time."); - CSLDestroy(papszXPMList); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Parse out colors. */ - /* -------------------------------------------------------------------- */ - int anCharLookup[256]; - GDALColorTable oCTable; - - for (i = 0; i < 256; i++) - anCharLookup[i] = -1; - - for (int iColor = 0; iColor < nColorCount; iColor++) - { - if (papszXPMList[iColor + 1] == nullptr || - papszXPMList[iColor + 1][0] == '\0') - { - CPLError(CE_Failure, CPLE_AppDefined, - "Missing color definition for %d in XPM header.", - iColor + 1); - CSLDestroy(papszXPMList); - return nullptr; - } - - char **papszTokens = CSLTokenizeString(papszXPMList[iColor + 1] + 1); - - if (CSLCount(papszTokens) != 2 || !EQUAL(papszTokens[0], "c")) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Ill formed color definition (%s) in XPM header.", - papszXPMList[iColor + 1]); - CSLDestroy(papszXPMList); - CSLDestroy(papszTokens); - return nullptr; - } - - anCharLookup[*(reinterpret_cast(papszXPMList[iColor + 1]))] = - iColor; - - GDALColorEntry sColor; - unsigned int nRed, nGreen, nBlue; - - if (EQUAL(papszTokens[1], "None")) - { - sColor.c1 = 0; - sColor.c2 = 0; - sColor.c3 = 0; - sColor.c4 = 0; - } - else if (sscanf(papszTokens[1], "#%02x%02x%02x", &nRed, &nGreen, - &nBlue) != 3) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Ill formed color definition (%s) in XPM header.", - papszXPMList[iColor + 1]); - CSLDestroy(papszXPMList); - CSLDestroy(papszTokens); - return nullptr; - } - else - { - sColor.c1 = static_cast(nRed); - sColor.c2 = static_cast(nGreen); - sColor.c3 = static_cast(nBlue); - sColor.c4 = 255; - } - - oCTable.SetColorEntry(iColor, &sColor); - - CSLDestroy(papszTokens); - } - - /* -------------------------------------------------------------------- */ - /* Prepare image buffer. */ - /* -------------------------------------------------------------------- */ - GByte *pabyImage = - reinterpret_cast(VSI_CALLOC_VERBOSE(*pnXSize, *pnYSize)); - if (pabyImage == nullptr) - { - CSLDestroy(papszXPMList); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Parse image. */ - /* -------------------------------------------------------------------- */ - for (int iLine = 0; iLine < *pnYSize; iLine++) - { - const GByte *pabyInLine = - reinterpret_cast(papszXPMList[iLine + nColorCount + 1]); - - if (pabyInLine == nullptr) - { - CPLFree(pabyImage); - CSLDestroy(papszXPMList); - CPLError(CE_Failure, CPLE_AppDefined, - "Insufficient imagery lines in XPM image."); - return nullptr; - } - - for (int iPixel = 0; iPixel < *pnXSize; iPixel++) - { - if (pabyInLine[iPixel] == '\0') - break; - const int nPixelValue = anCharLookup[pabyInLine[iPixel]]; - if (nPixelValue != -1) - pabyImage[iLine * *pnXSize + iPixel] = - static_cast(nPixelValue); - } - } - - CSLDestroy(papszXPMList); - - *ppoRetTable = oCTable.Clone(); - - return pabyImage; -} diff --git a/fuzzers/CMakeLists.txt b/fuzzers/CMakeLists.txt index 22347958d5d9..7dd1881ef009 100644 --- a/fuzzers/CMakeLists.txt +++ b/fuzzers/CMakeLists.txt @@ -75,7 +75,6 @@ function (build_ogr_specialized_fuzzer _format _registerFunc _memfile _gdalfile) endfunction () build_ogr_specialized_fuzzer(dxf RegisterOGRDXF "/vsimem/test" "/vsimem/test") -build_ogr_specialized_fuzzer(ogr_sdts RegisterOGRSDTS "/vsimem/test.tar" "/vsitar//vsimem/test.tar/TR01CATD.DDF") build_ogr_specialized_fuzzer(openfilegdb RegisterOGROpenFileGDB "/vsimem/test.gdb.tar" "/vsimem/test.gdb.tar") build_ogr_specialized_fuzzer(shape OGRRegisterAll "/vsimem/test.tar" "/vsitar//vsimem/test.tar/my.shp") build_ogr_specialized_fuzzer(mitab_mif OGRRegisterAll "/vsimem/test.tar" "/vsitar//vsimem/test.tar/my.mif") @@ -120,7 +119,6 @@ build_gdal_specialized_fuzzer(aig GDALRegister_AIGrid "/vsimem/test.tar" "/vsita # mrf can use indirectly the GTiff driver build_gdal_specialized_fuzzer(mrf "GDALRegister_mrf();GDALRegister_GTiff" "/vsimem/test.tar" "/vsitar//vsimem/test.tar/byte.mrf") -build_gdal_specialized_fuzzer(gdal_sdts GDALRegister_SDTS "/vsimem/test.tar" "/vsitar//vsimem/test.tar/1107CATD.DDF") build_gdal_specialized_fuzzer(gdal_vrt GDALAllRegister "/vsimem/test.tar" "/vsitar//vsimem/test.tar/test.vrt") build_gdal_specialized_fuzzer(ers GDALRegister_ERS "/vsimem/test.tar" "/vsitar//vsimem/test.tar/test.ers") diff --git a/fuzzers/build_google_oss_fuzzers.sh b/fuzzers/build_google_oss_fuzzers.sh index 3035cae6f5db..cd60ce99c311 100755 --- a/fuzzers/build_google_oss_fuzzers.sh +++ b/fuzzers/build_google_oss_fuzzers.sh @@ -80,7 +80,6 @@ for F in $fuzzerFiles; do done build_ogr_specialized_fuzzer dxf RegisterOGRDXF "/vsimem/test" "/vsimem/test" -build_ogr_specialized_fuzzer ogr_sdts RegisterOGRSDTS "/vsimem/test.tar" "/vsitar//vsimem/test.tar/TR01CATD.DDF" build_ogr_specialized_fuzzer openfilegdb RegisterOGROpenFileGDB "/vsimem/test.gdb.tar" "/vsimem/test.gdb.tar" build_ogr_specialized_fuzzer shape OGRRegisterAll "/vsimem/test.tar" "/vsitar//vsimem/test.tar/my.shp" build_ogr_specialized_fuzzer mitab_mif OGRRegisterAll "/vsimem/test.tar" "/vsitar//vsimem/test.tar/my.mif" @@ -114,7 +113,6 @@ build_gdal_specialized_fuzzer rraster GDALRegister_RRASTER "/vsimem/test.tar" "/ build_gdal_specialized_fuzzer aig GDALRegister_AIGrid "/vsimem/test.tar" "/vsitar//vsimem/test.tar/hdr.adf" # mrf can use indirectly the GTiff driver build_gdal_specialized_fuzzer mrf "GDALRegister_mrf();GDALRegister_GTiff" "/vsimem/test.tar" "/vsitar//vsimem/test.tar/byte.mrf" -build_gdal_specialized_fuzzer gdal_sdts GDALRegister_SDTS "/vsimem/test.tar" "/vsitar//vsimem/test.tar/1107CATD.DDF" build_gdal_specialized_fuzzer gdal_vrt GDALAllRegister "/vsimem/test.tar" "/vsitar//vsimem/test.tar/test.vrt" build_gdal_specialized_fuzzer ers GDALRegister_ERS "/vsimem/test.tar" "/vsitar//vsimem/test.tar/test.ers" build_gdal_specialized_fuzzer zarr GDALRegister_Zarr "/vsimem/test.tar" "/vsitar//vsimem/test.tar" diff --git a/fuzzers/build_seed_corpus.sh b/fuzzers/build_seed_corpus.sh index 291fc011250d..0b22d30973c6 100755 --- a/fuzzers/build_seed_corpus.sh +++ b/fuzzers/build_seed_corpus.sh @@ -291,20 +291,6 @@ cd $OLDPWD echo "Building gdal_filesystem_fuzzer_seed_corpus.zip" cp $OUT/gdal_fuzzer_seed_corpus.zip $OUT/gdal_filesystem_fuzzer_seed_corpus.zip -echo "Building gdal_sdts_fuzzer_seed_corpus.zip" -rm -f $OUT/gdal_sdts_fuzzer_seed_corpus.zip -CUR_DIR=$PWD -cd $(dirname $0)/../autotest/gdrivers/data/STDS_1107834_truncated -printf "FUZZER_FRIENDLY_ARCHIVE\\n" > $CUR_DIR/gdal_sdts.tar -for file in *.DDF; do - printf "***NEWFILE***:%s\\n" "$file" >> $CUR_DIR/gdal_sdts.tar - cat $file >> $CUR_DIR/gdal_sdts.tar -done -cd $CUR_DIR -zip -r $OUT/gdal_sdts_fuzzer_seed_corpus.zip gdal_sdts.tar >/dev/null -rm gdal_sdts.tar - - echo "Building ers_fuzzer_seed_corpus.zip" rm -f $OUT/ers_fuzzer_seed_corpus.zip CUR_DIR=$PWD @@ -369,19 +355,6 @@ cd $CUR_DIR zip -r $OUT/dimap_fuzzer_seed_corpus.zip dimap_*.tar >/dev/null rm dimap_*.tar -echo "Building ogr_sdts_fuzzer_seed_corpus.zip" -rm -f $OUT/ogr_sdts_fuzzer_seed_corpus.zip -CUR_DIR=$PWD -cd $(dirname $0)/../autotest/ogr/data/sdts/D3607551_rd0s_1_sdts_truncated -printf "FUZZER_FRIENDLY_ARCHIVE\\n" > $CUR_DIR/ogr_sdts.tar -for file in *.DDF; do - printf "***NEWFILE***:%s\\n" "$file" >> $CUR_DIR/ogr_sdts.tar - cat $file >> $CUR_DIR/ogr_sdts.tar -done -cd $CUR_DIR -zip -r $OUT/ogr_sdts_fuzzer_seed_corpus.zip ogr_sdts.tar >/dev/null -rm ogr_sdts.tar - echo "Building ogr_fuzzer_seed_corpus.zip" CUR_DIR=$PWD cd $(dirname $0)/../autotest/ogr/data diff --git a/gcore/gdal_frmts.h b/gcore/gdal_frmts.h index a2df6ad6da9e..6857162e24fe 100644 --- a/gcore/gdal_frmts.h +++ b/gcore/gdal_frmts.h @@ -28,8 +28,6 @@ void CPL_DLL GDALRegister_AIGrid(void); // void CPL_DLL GDALRegister_AIGrid2(void); void CPL_DLL GDALRegister_CEOS(void); void CPL_DLL GDALRegister_SAR_CEOS(void); -void CPL_DLL GDALRegister_SDTS(void); -void CPL_DLL GDALRegister_ELAS(void); void CPL_DLL GDALRegister_EHdr(void); void CPL_DLL GDALRegister_GenBin(void); void CPL_DLL GDALRegister_PAux(void); @@ -66,7 +64,6 @@ void DeclareDeferredECWPlugin(void); void CPL_DLL GDALRegister_JP2ECW(void); void CPL_DLL GDALRegister_ECW_JP2ECW(); void CPL_DLL GDALRegister_FujiBAS(void); -void CPL_DLL GDALRegister_FIT(void); void CPL_DLL GDALRegister_VRT(void); void CPL_DLL GDALRegister_GTI(void); void CPL_DLL GDALRegister_USGSDEM(void); @@ -77,7 +74,6 @@ void CPL_DLL GDALRegister_HDF4Image(void); void CPL_DLL GDALRegister_L1B(void); void CPL_DLL GDALRegister_LDF(void); void CPL_DLL GDALRegister_BSB(void); -void CPL_DLL GDALRegister_XPM(void); void CPL_DLL GDALRegister_BMP(void); void CPL_DLL GDALRegister_GSC(void); void CPL_DLL GDALRegister_NITF(void); @@ -114,7 +110,6 @@ void CPL_DLL GDALRegister_MSG(void); void DeclareDeferredMSGPlugin(void); void CPL_DLL GDALRegister_RIK(void); void CPL_DLL GDALRegister_Leveller(void); -void CPL_DLL GDALRegister_SGI(void); void CPL_DLL GDALRegister_SRTMHGT(void); void CPL_DLL GDALRegister_DIPEx(void); void CPL_DLL GDALRegister_ISIS3(void); @@ -130,8 +125,6 @@ void DeclareDeferredWCSPlugin(void); void CPL_DLL GDALRegister_WMS(void); void DeclareDeferredWMSPlugin(void); void CPL_DLL GDALRegister_HTTP(void); -void CPL_DLL GDALRegister_GSAG(void); -void CPL_DLL GDALRegister_GSBG(void); void CPL_DLL GDALRegister_GS7BG(void); void CPL_DLL GDALRegister_GRIB(void); void DeclareDeferredGRIBPlugin(void); @@ -145,7 +138,6 @@ void CPL_DLL GDALRegister_TSX(void); void CPL_DLL GDALRegister_ADRG(void); void CPL_DLL GDALRegister_SRP(void); void CPL_DLL GDALRegister_COASP(void); -void CPL_DLL GDALRegister_BLX(void); void CPL_DLL GDALRegister_LCP(void); void CPL_DLL GDALRegister_EIR(void); void CPL_DLL GDALRegister_ESRIC(void); @@ -153,8 +145,6 @@ void CPL_DLL GDALRegister_GEOR(void); void DeclareDeferredGEORPlugin(void); void CPL_DLL GDALRegister_TIL(void); void CPL_DLL GDALRegister_R(void); -void CPL_DLL GDALRegister_Rasterlite(void); -void DeclareDeferredRasterlitePlugin(void); void CPL_DLL GDALRegister_PostGISRaster(void); void DeclareDeferredPostGISRasterPlugin(void); void CPL_DLL GDALRegister_NWT_GRD(void); @@ -164,7 +154,6 @@ void CPL_DLL GDALRegister_KMLSUPEROVERLAY(void); void CPL_DLL GDALRegister_GTX(void); void CPL_DLL GDALRegister_LOSLAS(void); void CPL_DLL GDALRegister_NTv2(void); -void CPL_DLL GDALRegister_CTable2(void); void CPL_DLL GDALRegister_JP2OpenJPEG(void); void DeclareDeferredOPENJPEGPlugin(void); void CPL_DLL GDALRegister_XYZ(void); diff --git a/gcore/rawdataset.h b/gcore/rawdataset.h index 77e92c646ff3..2773ace6c6e5 100644 --- a/gcore/rawdataset.h +++ b/gcore/rawdataset.h @@ -46,6 +46,13 @@ class CPL_DLL RawDataset : public GDALPamDataset RawDataset(); virtual ~RawDataset() = 0; + enum class Interleave + { + BSQ, + BIL, + BIP, + }; + bool GetRawBinaryLayout(GDALDataset::RawBinaryLayout &) override; void ClearCachedConfigOption(void); diff --git a/ogr/ogrsf_frmts/CMakeLists.txt b/ogr/ogrsf_frmts/CMakeLists.txt index 15fc491e7665..ea205c327fd5 100644 --- a/ogr/ogrsf_frmts/CMakeLists.txt +++ b/ogr/ogrsf_frmts/CMakeLists.txt @@ -67,9 +67,7 @@ endif() ogr_optional_driver(csv CSV) ogr_optional_driver(dgn DGN) ogr_optional_driver(gmt GMT) -ogr_optional_driver(ntf NTF) ogr_optional_driver(s57 S57) -ogr_optional_driver(tiger "U.S. Census TIGER/Line") ogr_optional_driver(geoconcept GEOCONCEPT) ogr_optional_driver(georss GEORSS) ogr_optional_driver(dxf DXF) @@ -98,8 +96,6 @@ if (NOT OGR_ENABLE_DRIVER_GEOJSON_PLUGIN) ogr_dependent_driver(jsonfg JSONFG "OGR_ENABLE_DRIVER_GEOJSON") endif() -ogr_dependent_driver(sdts SDTS "GDAL_ENABLE_DRIVER_SDTS") - # XML drivers ogr_dependent_driver(gpx "GPX - GPS Exchange Format" "GDAL_USE_EXPAT") ogr_dependent_driver(gmlas GMLAS "GDAL_USE_XERCESC;OGR_ENABLE_DRIVER_PGDUMP") @@ -155,7 +151,6 @@ ogr_dependent_driver(gtfs "GTFS" "OGR_ENABLE_DRIVER_CSV") include(oci/driver_declaration.cmake) ogr_dependent_driver(idb "IDB" "GDAL_USE_IDB") ogr_dependent_driver(ods ODS "GDAL_USE_EXPAT") -ogr_dependent_driver(ogdi "OGDI" "GDAL_USE_OGDI") ogr_dependent_driver(lvbag "LVBAG" "GDAL_USE_EXPAT") ogr_dependent_driver(hana "SAP HANA" "GDAL_USE_ODBCCPP;GDAL_USE_ODBC") diff --git a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp index 843197c6dac5..35ada80be5aa 100644 --- a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp +++ b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp @@ -33,15 +33,9 @@ void OGRRegisterAllInternal() #ifdef MITAB_ENABLED RegisterOGRTAB(); #endif -#ifdef NTF_ENABLED - RegisterOGRNTF(); -#endif #ifdef LVBAG_ENABLED RegisterOGRLVBAG(); #endif -#ifdef SDTS_ENABLED - RegisterOGRSDTS(); -#endif #ifdef S57_ENABLED RegisterOGRS57(); #endif @@ -103,9 +97,6 @@ void OGRRegisterAllInternal() #ifdef MSSQLSPATIAL_ENABLED RegisterOGRMSSQLSpatial(); #endif -#ifdef OGDI_ENABLED - RegisterOGROGDI(); -#endif #ifdef PG_ENABLED RegisterOGRPG(); #endif @@ -264,10 +255,7 @@ void OGRRegisterAllInternal() // NOTE: frmts/drivers.ini in the same directory should be kept in same // order as this file -/* Put TIGER and AVCBIN at end since they need poOpenInfo->GetSiblingFiles() */ -#ifdef TIGER_ENABLED - RegisterOGRTiger(); -#endif +/* Put AVCBIN at end since they need poOpenInfo->GetSiblingFiles() */ #ifdef AVC_ENABLED RegisterOGRAVCBin(); RegisterOGRAVCE00(); diff --git a/ogr/ogrsf_frmts/miramon/mm_wrlayr.c b/ogr/ogrsf_frmts/miramon/mm_wrlayr.c index b333c9456b8d..3557731fd13f 100644 --- a/ogr/ogrsf_frmts/miramon/mm_wrlayr.c +++ b/ogr/ogrsf_frmts/miramon/mm_wrlayr.c @@ -2643,13 +2643,13 @@ int MMAppendBlockToBuffer(struct MM_FLUSH_INFO *FlushInfo) // Copy the contents of a temporary file to a final file. // Used everywhere when closing layers. int MMMoveFromFileToFile(FILE_TYPE *pSrcFile, FILE_TYPE *pDestFile, - MM_FILE_OFFSET *nOffset) + MM_FILE_OFFSET *pnOffset) { size_t bufferSize = 1024 * 1024; // 1 MB buffer; unsigned char *buffer; size_t bytesRead, bytesWritten; - if (!pSrcFile || !pDestFile || !nOffset) + if (!pSrcFile || !pDestFile || !pnOffset) return 0; buffer = (unsigned char *)calloc_function(bufferSize); @@ -2658,7 +2658,7 @@ int MMMoveFromFileToFile(FILE_TYPE *pSrcFile, FILE_TYPE *pDestFile, return 1; fseek_function(pSrcFile, 0, SEEK_SET); - fseek_function(pDestFile, *nOffset, SEEK_SET); + fseek_function(pDestFile, *pnOffset, SEEK_SET); while ((bytesRead = fread_function(buffer, sizeof(unsigned char), bufferSize, pSrcFile)) > 0) { @@ -2669,8 +2669,7 @@ int MMMoveFromFileToFile(FILE_TYPE *pSrcFile, FILE_TYPE *pDestFile, free_function(buffer); return 1; } - if (nOffset) - (*nOffset) += bytesWritten; + (*pnOffset) += bytesWritten; } free_function(buffer); return 0; diff --git a/ogr/ogrsf_frmts/ntf/CMakeLists.txt b/ogr/ogrsf_frmts/ntf/CMakeLists.txt deleted file mode 100644 index 8aedf5400930..000000000000 --- a/ogr/ogrsf_frmts/ntf/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -add_gdal_driver( - TARGET ogr_NTF - SOURCES ntf.h - ntffilereader.cpp - ntfrecord.cpp - ogrntfdatasource.cpp - ogrntfdriver.cpp - ogrntflayer.cpp - ntf_estlayers.cpp - ogrntffeatureclasslayer.cpp - ntf_generic.cpp - ntf_raster.cpp - ntf_codelist.cpp - ntfstroke.cpp - PLUGIN_CAPABLE - NO_DEPS) -gdal_standard_includes(ogr_NTF) - -if (BROKEN) - add_executable(ntfdump EXCLUDE_FROM_ALL ntfdump.cpp) - target_include_directories(ntfdump PRIVATE $) - target_link_libraries(ntfdump PRIVATE $ ogr_NTF) -endif () diff --git a/ogr/ogrsf_frmts/ntf/README.txt b/ogr/ogrsf_frmts/ntf/README.txt deleted file mode 100644 index ad1b1234f4d7..000000000000 --- a/ogr/ogrsf_frmts/ntf/README.txt +++ /dev/null @@ -1,213 +0,0 @@ - - NTF OGR Implementation Notes - ============================ - - -Products (and Layers) Supported -------------------------------- - -Landline (and Landline Plus): - LANDLINE_POINT - LANDLINE_LINE - LANDLINE_NAME - -Panorama Contours: - PANORAMA_POINT - PANORAMA_CONTOUR - - HEIGHT attribute holds elevation. - -Strategi: - STRATEGI_POINT - STRATEGI_LINE - STRATEGI_TEXT - STRATEGI_NODE - -Meridian: - MERIDIAN_POINT - MERIDIAN_LINE - MERIDIAN_TEXT - MERIDIAN_NODE - -Boundaryline: - BOUNDARYLINE_LINK - BOUNDARYLINE_POLY - BOUNDARYLINE_COLLECTIONS - - The _POLY layer has links to links allowing true polygons to - be formed (otherwise the _POLY's only have a seed point for geometry. - The collections are collections of polygons (also without geometry - as read). This is the only product from which polygons can be - constructed. - -Boundary Line 2000: - BL2000_LINK - BL2000_POLY - BL2000_COLLECTIONS - - Similar to Boundaryline, but with different attributes, feature code - is largely unused, and the _POLY layer doesn't have a seed point. - -BaseData.GB: - BASEDATA_POINT - BASEDATA_LINE - BASEDATA_TEXT - BASEDATA_NODE - -OSCAR Asset/Traffic: - OSCAR_POINT - OSCAR_LINE - OSCAR_NODE - -OSCAR Network: - OSCAR_NETWORK_POINT - OSCAR_NETWORK_LINE - OSCAR_NETWORK_NODE - -Address Point: - ADDRESS_POINT - -Code Point: - CODE_POINT - -Code Point Plus: - CODE_POINT_PLUS - -The dataset as a whole will also have a FEATURE_CLASSES layer containing a -pure table relating FEAT_CODE numbers with feature class names (FC_NAME). -This applies to all products in the dataset. A few layer types (such as -the Code Point, and Address Point products) don't include feature classes. -Some products use features classes that are not defined in the file, and -so they will not appear in the FEATURE_CLASSES layer. - - -Product Schemas ---------------- - -The approach taken in this reader is to treat one file, or a directory -of files as a single dataset. All files in the dataset are scanned on -open. For each particular product (listed above) a set of layers are -created; however, these layers may be extracted from several files of the -same product. - -The layers are based on a low level feature type in the NTF file, but will -generally contain features of many different feature codes (FEAT_CODE -attribute). Different features within a given layer may have a variety of -attributes in the file; however, the schema is established based on the -union of all attributes possible within features of a particular type -(i.e. POINT) of that product family (i.e. OSCAR Network). - -If an NTF product is read that doesn't match one of the known schema's -it will go through a different generic handler which has only -layers of type GENERIC_POINT and GENERIC_LINE. The features only have -a FEAT_CODE attribute. - -Details of what layers of what products have what attributes can be found -in the NTFFileReader::EstablishLayers() method at the end of ntf_estlayers.cpp. -This file also contains all the product specific translation code. - - -Special Attributes ------------------- - -FEAT_CODE: General feature code integer, can be used to lookup a name in the - FEATURE_CLASSES layer/table. - -TEXT_ID/POINT_ID/LINE_ID/NAME_ID/COLL_ID/POLY_ID/GEOM_ID: - Unique identifier for a feature of the appropriate type. - -TILE_REF: All layers (except FEATURE_CLASSES) contain a TILE_REF attribute - which indicates which tile (file) the features came from. Generally - speaking the id numbers are only unique within the tile and so - the TILE_REF can be used restrict id links within features from - the same file. - -FONT/TEXT_HT/DIG_POSTN/ORIENT: - Detailed information on the font, text height, digitizing position, - and orientation of text or name objects. Review the OS product - manuals to understand the units, and meaning of these codes. - -GEOM_ID_OF_POINT: - For _NODE features this defines the POINT_ID of the point layer object - to which this node corresponds. Generally speaking the nodes don't - carry a geometry of their own. The node must be related to a point - to establish its position. - -GEOM_ID_OF_LINK: - A _list_ of _LINK or _LINE features to end/start at a node. Nodes, - and this field are generally only of value when establishing - connectivity of line features for network analysis. Note that this - should be related to the target features GEOM_ID, not its LINE_ID. - - On the BOUNDARYLINE_POLY layer this attribute contains the GEOM_IDs - of the lines which form the edge of the polygon. - -POLY_ID: - A list of POLY_ID's from the BOUNDARYLINE_POLY layer associated with - a given collection in the BOUNDARYLINE_COLLECTIONS layer. - - -Adding a New Product --------------------- - -It is anticipated that over time the UK Ordnance Survey will define new -product formats, and to get decent mileage out of them this library should -be updated to support them. While I will endeavor to do this myself, it -seems prudent to define how it is done in case I am not available to do it, -or am unwilling to do it on a timely basis. To add a new product type the -following steps are required: - - o Add an NPC_ code for the product in ntf.h - o Add a case in NTFFileReader::Open() to translate the GetProduct() result - into the NPC_ code. - o Add a case in NTFFileReader::EstablishLayers() defining the layers found - on this product. - o Add translate functions for layers of this product. Generally they can - be cloned from an existing translate function, and the attribute mapping - in the NTFReader::ApplyAttributeValues() call can be modified. - -Occasionally existing products will change slightly. This may result in a -slight change to the detection logic in NTFFileReader::Open() and changes -in the list of user attributes associated with the layer. If the differences -are significant it may be necessary to define a whole new product family -type (as is done for Code Point Plus vs. Code Point). - -Generic Products ----------------- - -In situations where a file is not identified as being part of an existing -known product it will be treated generically. In this case the entire dataset -is scanned to establish what features have what attributes. Because of this, -opening a generic dataset can be much slower than opening a recognized dataset. -Based on this scan a list of generic features (layers) are defined from the -following set: - - GENERIC_POINT - GENERIC_LINE - GENERIC_NAME - GENERIC_TEXT - GENERIC_POLY - GENERIC_NODE - GENERIC_COLLECTION - -Generic products are primarily handled by the ntf_generic.cpp module whereas -specific products are handled in ntf_estlayers.cpp. - -Because some data products (OSNI datasets) not from the Ordnance Survey -were found to have record groups in unusual orders compared to what the -UK Ordnance Survey does, it was found necessary to cache all the records of -level 3 and higher generic products, and construct record groups by id -reference from within this cache rather than depending on convenient record -orderings. This is accomplished by the NTFFileReader "indexing" capability -near the bottom of ntffilereader.cpp. Because of this in memory indexing -accessing generic datasets can be much more memory intensive than accessing -known data products, though it isn't necessary for generic level 1 and 2 -products. - -It is possible to force a known product to be treated as generic by setting -the FORCE_GENERIC option to "ON" using OGRNTFDataSource::SetOptionsList() as -is demonstrated in ntfdump.cpp. - - - - diff --git a/ogr/ogrsf_frmts/ntf/ntf.h b/ogr/ogrsf_frmts/ntf/ntf.h deleted file mode 100644 index 2251a50ff25c..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntf.h +++ /dev/null @@ -1,687 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: Main declarations for NTF translator. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef NTF_H_INCLUDED -#define NTF_H_INCLUDED - -#include "cpl_conv.h" -#include "cpl_vsi.h" -#include "ogrsf_frmts.h" - -/* -------------------------------------------------------------------- */ -/* Record types. */ -/* -------------------------------------------------------------------- */ -#define NRT_VHR 1 /* Volume Header Record */ -#define NRT_DHR 2 /* Database Header Record */ -#define NRT_FCR 5 /* Feature Classification Record */ -#define NRT_SHR 7 /* Section Header Record */ -#define NRT_NAMEREC 11 /* Name Record */ -#define NRT_NAMEPOSTN 12 /* Name Position */ -#define NRT_ATTREC 14 /* Attribute Record */ -#define NRT_POINTREC 15 /* Point Record */ -#define NRT_NODEREC 16 /* Node Record */ -#define NRT_GEOMETRY 21 /* Geometry Record */ -#define NRT_GEOMETRY3D 22 /* 3D Geometry Record */ -#define NRT_LINEREC 23 /* Line Record */ -#define NRT_CHAIN 24 /* Chain */ -#define NRT_POLYGON 31 /* Polygon */ -#define NRT_CPOLY 33 /* Complex Polygon */ -#define NRT_COLLECT 34 /* Collection of features */ -#define NRT_ADR 40 /* Attribute Description Record */ -#define NRT_CODELIST 42 /* Codelist Record (i.e. BL2000) */ -#define NRT_TEXTREC 43 /* Text */ -#define NRT_TEXTPOS 44 /* Text position */ -#define NRT_TEXTREP 45 /* Text representation */ -#define NRT_GRIDHREC 50 /* Grid Header Record */ -#define NRT_GRIDREC 51 /* Grid Data Record */ -#define NRT_COMMENT 90 /* Comment record */ -#define NRT_VTR 99 /* Volume Termination Record */ - -/* -------------------------------------------------------------------- */ -/* Product names (DBNAME) and codes. */ -/* -------------------------------------------------------------------- */ - -#define NPC_UNKNOWN 0 - -#define NPC_LANDLINE 1 -#define NPC_LANDLINE99 2 -#define NTF_LANDLINE "LAND-LINE.93" -#define NTF_LANDLINE_PLUS "LAND-LINE.93+" - -#define NPC_STRATEGI 3 -#define NTF_STRATEGI "Strategi_02.96" - -#define NPC_MERIDIAN 4 -#define NTF_MERIDIAN "Meridian_01.95" - -#define NPC_BOUNDARYLINE 5 -#define NTF_BOUNDARYLINE "Boundary-Line" - -#define NPC_BASEDATA 6 -#define NTF_BASEDATA "BaseData.GB_01.96" - -#define NPC_OSCAR_ASSET 7 -#define NPC_OSCAR_TRAFFIC 8 -#define NPC_OSCAR_ROUTE 9 -#define NPC_OSCAR_NETWORK 10 - -#define NPC_ADDRESS_POINT 11 - -#define NPC_CODE_POINT 12 -#define NPC_CODE_POINT_PLUS 13 - -#define NPC_LANDFORM_PROFILE_CONT 14 - -#define NPC_LANDRANGER_CONT 15 -#define NTF_LANDRANGER_CONT "OS_LANDRANGER_CONT" - -#define NPC_LANDRANGER_DTM 16 -#define NPC_LANDFORM_PROFILE_DTM 17 - -#define NPC_BL2000 18 - -#define NPC_MERIDIAN2 19 -#define NTF_MERIDIAN2 "Meridian_02.01" - -constexpr int MAX_LINK = 5000; - -/************************************************************************/ -/* NTFRecord */ -/************************************************************************/ - -class NTFRecord -{ - int nType; - int nLength; - char *pszData; - - static int ReadPhysicalLine(VSILFILE *fp, char *pszLine); - - public: - explicit NTFRecord(VSILFILE *); - ~NTFRecord(); - - int GetType() - { - return nType; - } - - int GetLength() - { - return nLength; - } - - const char *GetData() - { - return pszData; - } - - const char *GetField(int, int); -}; - -/************************************************************************/ -/* NTFGenericClass */ -/************************************************************************/ - -class NTFGenericClass -{ - public: - int nFeatureCount; - - int b3D; - int nAttrCount; - char **papszAttrNames; - char **papszAttrFormats; - int *panAttrMaxWidth; - int *pabAttrMultiple; - - NTFGenericClass(); - ~NTFGenericClass(); - - void CheckAddAttr(const char *, const char *, int); - void SetMultiple(const char *); -}; - -/************************************************************************/ -/* NTFCodeList */ -/************************************************************************/ - -class NTFCodeList -{ - public: - explicit NTFCodeList(NTFRecord *); - ~NTFCodeList(); - - const char *Lookup(const char *); - - char szValType[3]; /* attribute code for list, i.e. AC */ - char szFInter[6]; /* format of code values */ - - int nNumCode; - char **papszCodeVal; /* Short code value */ - char **papszCodeDes; /* Long description of code */ -}; - -/************************************************************************/ -/* NTFAttDesc */ -/************************************************************************/ -typedef struct -{ - char val_type[2 + 1]; - char fwidth[3 + 1]; - char finter[5 + 1]; - char att_name[100]; - - NTFCodeList *poCodeList; - -} NTFAttDesc; - -class OGRNTFLayer; -class OGRNTFRasterLayer; -class OGRNTFDataSource; -class NTFFileReader; - -#define MAX_REC_GROUP 100 -typedef OGRFeature *(*NTFFeatureTranslator)(NTFFileReader *, OGRNTFLayer *, - NTFRecord **); -typedef int (*NTFRecordGrouper)(NTFFileReader *, NTFRecord **, NTFRecord *); - -/************************************************************************/ -/* NTFFileReader */ -/************************************************************************/ - -class NTFFileReader -{ - char *pszFilename; - OGRNTFDataSource *poDS; - - VSILFILE *fp; - - // feature class list. - int nFCCount; - char **papszFCNum; - char **papszFCName; - - // attribute definitions - int nAttCount; - NTFAttDesc *pasAttDesc; - - char *pszTileName; - int nCoordWidth; - int nZWidth; - int nNTFLevel; - - double dfXYMult; - double dfZMult; - - double dfXOrigin; - double dfYOrigin; - - double dfTileXSize; - double dfTileYSize; - - double dfScale; - double dfPaperToGround; - - vsi_l_offset nStartPos; - vsi_l_offset nPreSavedPos; - vsi_l_offset nPostSavedPos; - NTFRecord *poSavedRecord; - - long nSavedFeatureId; - long nBaseFeatureId; - long nFeatureCount; - - NTFRecord *apoCGroup[MAX_REC_GROUP + 1]; - - char *pszProduct; - char *pszPVName; - int nProduct; - - void EstablishLayers(); - - void ClearCGroup(); - void ClearDefs(); - - OGRNTFLayer *apoTypeTranslation[100]; - - NTFRecordGrouper pfnRecordGrouper; - - int anIndexSize[100]; - NTFRecord **apapoRecordIndex[100]; - int bIndexBuilt; - int bIndexNeeded; - - void EstablishRasterAccess(); - int nRasterXSize; - int nRasterYSize; - int nRasterDataType; - double adfGeoTransform[6]; - - OGRNTFRasterLayer *poRasterLayer; - - vsi_l_offset *panColumnOffset; - - int bCacheLines; - int nLineCacheSize; - OGRGeometry **papoLineCache; - - void AddToIndexGroup(NTFRecord *poRecord); - - public: - explicit NTFFileReader(OGRNTFDataSource *); - ~NTFFileReader(); - - int Open(const char *pszFilename = nullptr); - void Close(); - - VSILFILE *GetFP() - { - return fp; - } - - void GetFPPos(vsi_l_offset *pnPos, long *pnFeatureId); - int SetFPPos(vsi_l_offset nPos, long nFeatureId); - void Reset(); - void SetBaseFID(long nFeatureId); - - OGRGeometry *ProcessGeometry(NTFRecord *, int * = nullptr); - OGRGeometry *ProcessGeometry3D(NTFRecord *, int * = nullptr); - static int ProcessAttDesc(NTFRecord *, NTFAttDesc *); - int ProcessAttRec(NTFRecord *, int *, char ***, char ***); - int ProcessAttRecGroup(NTFRecord **, char ***, char ***); - - NTFAttDesc *GetAttDesc(const char *); - - void ApplyAttributeValues(OGRFeature *, NTFRecord **, ...); - - int ApplyAttributeValue(OGRFeature *, int, const char *, char **, char **); - - int ProcessAttValue(const char *pszValType, const char *pszRawValue, - const char **ppszAttName, const char **ppszAttValue, - const char **ppszCodeDesc); - - int TestForLayer(OGRNTFLayer *); - OGRFeature *ReadOGRFeature(OGRNTFLayer * = nullptr); - NTFRecord **ReadRecordGroup(); - NTFRecord *ReadRecord(); - void SaveRecord(NTFRecord *); - - void DumpReadable(FILE *); - - int GetXYLen() - { - return nCoordWidth; - } - - double GetXYMult() - { - return dfXYMult; - } - - double GetXOrigin() - { - return dfXOrigin; - } - - double GetYOrigin() - { - return dfYOrigin; - } - - double GetZMult() - { - return dfZMult; - } - - const char *GetTileName() - { - return pszTileName; - } - - const char *GetFilename() - { - return pszFilename; - } - - int GetNTFLevel() - { - return nNTFLevel; - } - - const char *GetProduct() - { - return pszProduct; - } - - const char *GetPVName() - { - return pszPVName; - } - - int GetProductId() - { - return nProduct; - } - - double GetScale() - { - return dfScale; - } - - double GetPaperToGround() - { - return dfPaperToGround; - } - - int GetFCCount() - { - return nFCCount; - } - - int GetFeatureClass(int, char **, char **); - - void OverrideTileName(const char *); - - // Generic file index - void IndexFile(); - void FreshenIndex(); - void DestroyIndex(); - NTFRecord *GetIndexedRecord(int, int); - NTFRecord **GetNextIndexedRecordGroup(NTFRecord **); - - // Line geometry cache - OGRGeometry *CacheGetByGeomId(int); - void CacheAddByGeomId(int, OGRGeometry *); - void CacheClean(); - void CacheLineGeometryInGroup(NTFRecord **); - - int FormPolygonFromCache(OGRFeature *); - - // just for use of OGRNTFDatasource - void EstablishLayer(const char *, OGRwkbGeometryType, NTFFeatureTranslator, - int, NTFGenericClass *, ...); - - // Raster related - int IsRasterProduct(); - - int GetRasterXSize() - { - return nRasterXSize; - } - - int GetRasterYSize() - { - return nRasterYSize; - } - - int GetRasterDataType() - { - return nRasterDataType; - } - - double *GetGeoTransform() - { - return adfGeoTransform; - } - - CPLErr ReadRasterColumn(int, float *); -}; - -/************************************************************************/ -/* OGRNTFLayer */ -/************************************************************************/ - -class OGRNTFLayer final : public OGRLayer -{ - OGRFeatureDefn *poFeatureDefn; - NTFFeatureTranslator pfnTranslator; - - OGRNTFDataSource *poDS; - - int iCurrentReader; - vsi_l_offset nCurrentPos; - long nCurrentFID; - - public: - OGRNTFLayer(OGRNTFDataSource *poDS, OGRFeatureDefn *poFeatureDefine, - NTFFeatureTranslator pfnTranslator); - - ~OGRNTFLayer(); - - void ResetReading() override; - OGRFeature *GetNextFeature() override; - -#ifdef notdef - OGRFeature *GetFeature(GIntBig nFeatureId); - OGRErr ISetFeature(OGRFeature *poFeature); - OGRErr ICreateFeature(OGRFeature *poFeature); -#endif - - OGRFeatureDefn *GetLayerDefn() override - { - return poFeatureDefn; - } - -#ifdef notdef - GIntBig GetFeatureCount(int); -#endif - - int TestCapability(const char *) override; - - // special to NTF - OGRFeature *FeatureTranslate(NTFFileReader *, NTFRecord **); -}; - -/************************************************************************/ -/* OGRNTFFeatureClassLayer */ -/************************************************************************/ - -class OGRNTFFeatureClassLayer final : public OGRLayer -{ - OGRFeatureDefn *poFeatureDefn; - OGRGeometry *poFilterGeom; - - OGRNTFDataSource *poDS; - - GIntBig iCurrentFC; - - public: - explicit OGRNTFFeatureClassLayer(OGRNTFDataSource *poDS); - ~OGRNTFFeatureClassLayer(); - - OGRGeometry *GetSpatialFilter() override - { - return poFilterGeom; - } - - void SetSpatialFilter(OGRGeometry *) override; - - virtual void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override - { - OGRLayer::SetSpatialFilter(iGeomField, poGeom); - } - - void ResetReading() override; - OGRFeature *GetNextFeature() override; - - OGRFeature *GetFeature(GIntBig nFeatureId) override; - - OGRFeatureDefn *GetLayerDefn() override - { - return poFeatureDefn; - } - - GIntBig GetFeatureCount(int = TRUE) override; - - int TestCapability(const char *) override; -}; - -/************************************************************************/ -/* OGRNTFRasterLayer */ -/************************************************************************/ - -class OGRNTFRasterLayer final : public OGRLayer -{ - OGRFeatureDefn *poFeatureDefn; - OGRGeometry *poFilterGeom; - - NTFFileReader *poReader; - - float *pafColumn; - int iColumnOffset; - - GIntBig iCurrentFC; - - int nDEMSample; - GIntBig nFeatureCount; - - public: - OGRNTFRasterLayer(OGRNTFDataSource *poDS, NTFFileReader *poReaderIn); - virtual ~OGRNTFRasterLayer(); - - OGRGeometry *GetSpatialFilter() override - { - return poFilterGeom; - } - - void SetSpatialFilter(OGRGeometry *) override; - - virtual void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override - { - OGRLayer::SetSpatialFilter(iGeomField, poGeom); - } - - void ResetReading() override; - OGRFeature *GetNextFeature() override; - - OGRFeature *GetFeature(GIntBig nFeatureId) override; - - OGRFeatureDefn *GetLayerDefn() override - { - return poFeatureDefn; - } - - GIntBig GetFeatureCount(int = TRUE) override; - - int TestCapability(const char *) override; -}; - -/************************************************************************/ -/* OGRNTFDataSource */ -/************************************************************************/ - -class OGRNTFDataSource final : public GDALDataset -{ - int nLayers; - OGRLayer **papoLayers; - - OGRNTFFeatureClassLayer *poFCLayer; - - int iCurrentFC; - int iCurrentReader; - vsi_l_offset nCurrentPos; - long nCurrentFID; - - int nNTFFileCount; - NTFFileReader **papoNTFFileReader; - - int nFCCount; - char **papszFCNum; - char **papszFCName; - - OGRSpatialReference *poSpatialRef; - - NTFGenericClass aoGenericClass[100]; - - char **papszOptions; - - void EnsureTileNameUnique(NTFFileReader *); - - CPL_DISALLOW_COPY_ASSIGN(OGRNTFDataSource) - - public: - OGRNTFDataSource(); - ~OGRNTFDataSource(); - - void SetOptionList(char **); - const char *GetOption(const char *); - - int Open(const char *pszName, int bTestOpen = FALSE, - char **papszFileList = nullptr); - - int GetLayerCount() override; - OGRLayer *GetLayer(int) override; - int TestCapability(const char *) override; - - // Note: these are specific to NTF for now, but eventually might - // might be available as part of a more object oriented approach to - // features like that in FME or SFCORBA. - virtual void ResetReading() override; - virtual OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer, - double *pdfProgressPct, - GDALProgressFunc pfnProgress, - void *pProgressData) override; - - // these are only for the use of the NTFFileReader class. - OGRNTFLayer *GetNamedLayer(const char *); - void AddLayer(OGRLayer *); - - // Mainly for OGRNTFLayer class - int GetFileCount() - { - return nNTFFileCount; - } - - NTFFileReader *GetFileReader(int i) - { - return papoNTFFileReader[i]; - } - - int GetFCCount() - { - return nFCCount; - } - - int GetFeatureClass(int, char **, char **); - - OGRSpatialReference *DSGetSpatialRef() - { - return poSpatialRef; - } - - NTFGenericClass *GetGClass(int i) - { - return aoGenericClass + i; - } - - void WorkupGeneric(NTFFileReader *); - void EstablishGenericLayers(); -}; - -/************************************************************************/ -/* Support functions. */ -/************************************************************************/ -int NTFArcCenterFromEdgePoints(double x_c0, double y_c0, double x_c1, - double y_c1, double x_c2, double y_c2, - double *x_center, double *y_center); -OGRGeometry *NTFStrokeArcToOGRGeometry_Points(double dfStartX, double dfStartY, - double dfAlongX, double dfAlongY, - double dfEndX, double dfEndY, - int nVertexCount); -OGRGeometry *NTFStrokeArcToOGRGeometry_Angles(double dfCenterX, - double dfCenterY, double dfRadius, - double dfStartAngle, - double dfEndAngle, - int nVertexCount); - -#endif /* ndef NTF_H_INCLUDED */ diff --git a/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp b/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp deleted file mode 100644 index 069ee36e9f95..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: NTFCodeList class implementation. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2001, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include -#include -#include "ntf.h" -#include "cpl_conv.h" -#include "cpl_string.h" - -/************************************************************************/ -/* NTFCodeList */ -/************************************************************************/ - -NTFCodeList::NTFCodeList(NTFRecord *poRecord) - : nNumCode(std::max(0, atoi(poRecord->GetField(20, 22)))), - papszCodeVal(static_cast(CPLMalloc(sizeof(char *) * nNumCode))), - papszCodeDes(static_cast(CPLMalloc(sizeof(char *) * nNumCode))) -{ - - CPLAssert(EQUAL(poRecord->GetField(1, 2), "42")); - - snprintf(szValType, sizeof(szValType), "%s", poRecord->GetField(13, 14)); - snprintf(szFInter, sizeof(szFInter), "%s", poRecord->GetField(15, 19)); - - const int nRecordLen = poRecord->GetLength(); - const char *pszText = poRecord->GetData() + 22; - int iThisField = 0; - for (; nRecordLen > 22 && *pszText != '\0' && iThisField < nNumCode; - iThisField++) - { - char szVal[128] = {}; - int iLen = 0; - while (iLen < static_cast(sizeof(szVal)) - 1 && *pszText != '\\' && - *pszText != '\0') - { - szVal[iLen++] = *(pszText++); - } - szVal[iLen] = '\0'; - - if (*pszText == '\\') - pszText++; - - iLen = 0; - char szDes[128] = {}; - while (iLen < static_cast(sizeof(szDes)) - 1 && *pszText != '\\' && - *pszText != '\0') - { - szDes[iLen++] = *(pszText++); - } - szDes[iLen] = '\0'; - - if (*pszText == '\\') - pszText++; - - papszCodeVal[iThisField] = CPLStrdup(szVal); - papszCodeDes[iThisField] = CPLStrdup(szDes); - } - - if (iThisField < nNumCode) - { - nNumCode = iThisField; - CPLDebug("NTF", "Didn't get all the expected fields from a CODELIST."); - } -} - -/************************************************************************/ -/* ~NTFCodeList() */ -/************************************************************************/ - -NTFCodeList::~NTFCodeList() - -{ - for (int i = 0; i < nNumCode; i++) - { - CPLFree(papszCodeVal[i]); - CPLFree(papszCodeDes[i]); - } - - CPLFree(papszCodeVal); - CPLFree(papszCodeDes); -} - -/************************************************************************/ -/* Lookup() */ -/************************************************************************/ - -const char *NTFCodeList::Lookup(const char *pszCode) - -{ - for (int i = 0; i < nNumCode; i++) - { - if (EQUAL(pszCode, papszCodeVal[i])) - return papszCodeDes[i]; - } - - return nullptr; -} diff --git a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp deleted file mode 100644 index 379f86f93cbf..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp +++ /dev/null @@ -1,2171 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: NTFFileReader methods related to establishing the schemas - * of features that could occur in this product and the functions - * for actually performing the NTFRecord to OGRFeature conversion. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include -#include "ntf.h" -#include "cpl_string.h" - -/************************************************************************/ -/* TranslateCodePoint() */ -/* */ -/* Used for code point, and code point plus. */ -/************************************************************************/ - -static OGRFeature *TranslateCodePoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - - // Attributes - if (EQUAL(poLayer->GetLayerDefn()->GetName(), "CODE_POINT")) - poReader->ApplyAttributeValues( - poFeature, papoGroup, "PC", 1, "PQ", 2, "PR", 3, "TP", 4, "DQ", 5, - "RP", 6, "BP", 7, "PD", 8, "MP", 9, "UM", 10, "RV", 11, NULL); - else - poReader->ApplyAttributeValues( - poFeature, papoGroup, "PC", 1, "PQ", 2, "PR", 3, "TP", 4, "DQ", 5, - "RP", 6, "BP", 7, "PD", 8, "MP", 9, "UM", 10, "RV", 11, "RH", 12, - "LH", 13, "CC", 14, "DC", 15, "WC", 16, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateAddressPoint() */ -/************************************************************************/ - -static OGRFeature *TranslateAddressPoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // CHG_TYPE - poFeature->SetField(17, papoGroup[0]->GetField(22, 22)); - - // CHG_DATE - poFeature->SetField(18, papoGroup[0]->GetField(23, 28)); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - - // Attributes - poReader->ApplyAttributeValues( - poFeature, papoGroup, "OA", 1, "ON", 2, "DP", 3, "PB", 4, "SB", 5, "BD", - 6, "BN", 7, "DR", 8, "TN", 9, "DD", 10, "DL", 11, "PT", 12, "CN", 13, - "PC", 14, "SF", 15, "RV", 16, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateOscarPoint() */ -/* */ -/* Used for OSCAR Traffic and Asset datasets. */ -/************************************************************************/ - -static OGRFeature *TranslateOscarPoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "JN", - 4, "SN", 5, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateOscarLine() */ -/************************************************************************/ - -static OGRFeature *TranslateOscarLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "PN", - 4, "LL", 5, "SC", 6, "FW", 7, "RN", 8, "TR", - 9, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateOscarRoutePoint() */ -/************************************************************************/ - -static OGRFeature *TranslateOscarRoutePoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "JN", - 4, "SN", 5, "NP", 6, "RT", 8, NULL); - - // PARENT_OSODR - char **papszTypes, **papszValues; - - if (poReader->ProcessAttRecGroup(papoGroup, &papszTypes, &papszValues)) - { - char **papszOSODRList = nullptr; - - for (int i = 0; papszTypes != nullptr && papszTypes[i] != nullptr; i++) - { - if (EQUAL(papszTypes[i], "PO")) - papszOSODRList = CSLAddString(papszOSODRList, papszValues[i]); - } - - poFeature->SetField(7, papszOSODRList); - CPLAssert(CSLCount(papszOSODRList) == poFeature->GetFieldAsInteger(6)); - - CSLDestroy(papszOSODRList); - CSLDestroy(papszTypes); - CSLDestroy(papszValues); - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateOscarRouteLine() */ -/************************************************************************/ - -static OGRFeature *TranslateOscarRouteLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "PN", - 4, "LL", 5, "RN", 6, "TR", 7, "NP", 8, NULL); - - // PARENT_OSODR - char **papszTypes, **papszValues; - - if (poReader->ProcessAttRecGroup(papoGroup, &papszTypes, &papszValues)) - { - char **papszOSODRList = nullptr; - - for (int i = 0; papszTypes != nullptr && papszTypes[i] != nullptr; i++) - { - if (EQUAL(papszTypes[i], "PO")) - papszOSODRList = CSLAddString(papszOSODRList, papszValues[i]); - } - - poFeature->SetField(9, papszOSODRList); - CPLAssert(CSLCount(papszOSODRList) == poFeature->GetFieldAsInteger(8)); - - CSLDestroy(papszOSODRList); - CSLDestroy(papszTypes); - CSLDestroy(papszValues); - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateOscarComment() */ -/************************************************************************/ - -static OGRFeature *TranslateOscarComment(CPL_UNUSED NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 1 || - papoGroup[0]->GetType() != NRT_COMMENT) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // RECORD_TYPE - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 4))); - - // RECORD_ID - poFeature->SetField(1, papoGroup[0]->GetField(5, 17)); - - // CHANGE_TYPE - poFeature->SetField(2, papoGroup[0]->GetField(18, 18)); - - return poFeature; -} - -/************************************************************************/ -/* TranslateOscarNetworkPoint() */ -/************************************************************************/ - -static OGRFeature *TranslateOscarNetworkPoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "JN", - 4, "SN", 5, "RT", 6, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateOscarNetworkLine() */ -/************************************************************************/ - -static OGRFeature *TranslateOscarNetworkLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "OD", 3, "PN", - 4, "LL", 5, "RN", 6, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateBasedataPoint() */ -/************************************************************************/ - -static OGRFeature *TranslateBasedataPoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "PN", 3, "NU", - 4, "CM", 5, "UN", 6, "OR", 7, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateBasedataLine() */ -/************************************************************************/ - -static OGRFeature *TranslateBasedataLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(2, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "PN", 3, "NU", - 4, "RB", 5, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateBoundarylineCollection() */ -/************************************************************************/ - -static OGRFeature *TranslateBoundarylineCollection(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 2 || - papoGroup[0]->GetType() != NRT_COLLECT || - papoGroup[1]->GetType() != NRT_ATTREC) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // COLL_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // NUM_PARTS - int nNumLinks = atoi(papoGroup[0]->GetField(9, 12)); - - if (nNumLinks > MAX_LINK) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_estlayers.cpp."); - return poFeature; - } - - poFeature->SetField(1, nNumLinks); - - // POLY_ID - int i, anList[MAX_LINK] = {0}; - - for (i = 0; i < nNumLinks; i++) - anList[i] = atoi(papoGroup[0]->GetField(15 + i * 8, 20 + i * 8)); - - poFeature->SetField(2, nNumLinks, anList); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "AI", 3, "OP", 4, "NM", - 5, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateBoundarylinePoly() */ -/************************************************************************/ - -static OGRFeature *TranslateBoundarylinePoly(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - /* ==================================================================== */ - /* Traditional POLYGON record groups. */ - /* ==================================================================== */ - if (CSLCount((char **)papoGroup) == 4 && - papoGroup[0]->GetType() == NRT_POLYGON && - papoGroup[1]->GetType() == NRT_ATTREC && - papoGroup[2]->GetType() == NRT_CHAIN && - papoGroup[3]->GetType() == NRT_GEOMETRY) - { - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POLY_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // NUM_PARTS - int nNumLinks = atoi(papoGroup[2]->GetField(9, 12)); - - if (nNumLinks > MAX_LINK) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_estlayers.cpp."); - return poFeature; - } - - poFeature->SetField(4, nNumLinks); - - // DIR - int i, anList[MAX_LINK] = {0}; - - for (i = 0; i < nNumLinks; i++) - anList[i] = atoi(papoGroup[2]->GetField(19 + i * 7, 19 + i * 7)); - - poFeature->SetField(5, nNumLinks, anList); - - // GEOM_ID_OF_LINK - for (i = 0; i < nNumLinks; i++) - anList[i] = atoi(papoGroup[2]->GetField(13 + i * 7, 18 + i * 7)); - - poFeature->SetField(6, nNumLinks, anList); - - // RingStart - int nRingList = 0; - poFeature->SetField(7, 1, &nRingList); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "PI", 2, - "HA", 3, NULL); - - // Read point geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[3])); - - // Try to assemble polygon geometry. - poReader->FormPolygonFromCache(poFeature); - - return poFeature; - } - - /* ==================================================================== */ - /* CPOLYGON Group */ - /* ==================================================================== */ - - /* -------------------------------------------------------------------- */ - /* First we do validation of the grouping. */ - /* -------------------------------------------------------------------- */ - int iRec = 0; // Used after for. - - for (; papoGroup[iRec] != nullptr && papoGroup[iRec + 1] != nullptr && - papoGroup[iRec]->GetType() == NRT_POLYGON && - papoGroup[iRec + 1]->GetType() == NRT_CHAIN; - iRec += 2) - { - } - - if (CSLCount((char **)papoGroup) != iRec + 3) - return nullptr; - - if (papoGroup[iRec]->GetType() != NRT_CPOLY || - papoGroup[iRec + 1]->GetType() != NRT_ATTREC || - papoGroup[iRec + 2]->GetType() != NRT_GEOMETRY) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Collect the chains for each of the rings, and just aggregate */ - /* these into the master list without any concept of where the */ - /* boundaries are. The boundary information will be emitted */ - /* in the RingStart field. */ - /* -------------------------------------------------------------------- */ - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - int nNumLink = 0; - int anDirList[MAX_LINK * 2] = {}; - int anGeomList[MAX_LINK * 2] = {}; - int anRingStart[MAX_LINK] = {}; - int nRings = 0; - - for (iRec = 0; - papoGroup[iRec] != nullptr && papoGroup[iRec + 1] != nullptr && - papoGroup[iRec]->GetType() == NRT_POLYGON && - papoGroup[iRec + 1]->GetType() == NRT_CHAIN; - iRec += 2) - { - const int nLineCount = atoi(papoGroup[iRec + 1]->GetField(9, 12)); - - anRingStart[nRings++] = nNumLink; - - for (int i = 0; i < nLineCount && nNumLink < MAX_LINK * 2; i++) - { - anDirList[nNumLink] = - atoi(papoGroup[iRec + 1]->GetField(19 + i * 7, 19 + i * 7)); - anGeomList[nNumLink] = - atoi(papoGroup[iRec + 1]->GetField(13 + i * 7, 18 + i * 7)); - nNumLink++; - } - - if (nNumLink == MAX_LINK * 2) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_estlayers.cpp."); - - delete poFeature; - return nullptr; - } - } - - // NUM_PART - poFeature->SetField(4, nNumLink); - - // DIR - poFeature->SetField(5, nNumLink, anDirList); - - // GEOM_ID_OF_LINK - poFeature->SetField(6, nNumLink, anGeomList); - - // RingStart - poFeature->SetField(7, nRings, anRingStart); - - /* -------------------------------------------------------------------- */ - /* collect information for whole complex polygon. */ - /* -------------------------------------------------------------------- */ - // POLY_ID - if (papoGroup[iRec] != nullptr) - poFeature->SetField(0, atoi(papoGroup[iRec]->GetField(3, 8))); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "PI", 2, "HA", - 3, NULL); - - // point geometry for seed. - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[iRec + 2])); - - // Try to assemble polygon geometry. - poReader->FormPolygonFromCache(poFeature); - - return poFeature; -} - -/************************************************************************/ -/* TranslateBoundarylineLink() */ -/************************************************************************/ - -static OGRFeature *TranslateBoundarylineLink(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 2 || - papoGroup[0]->GetType() != NRT_GEOMETRY || - papoGroup[1]->GetType() != NRT_ATTREC) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[0], &nGeomId)); - - // GEOM_ID - poFeature->SetField(0, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "LK", 2, "HW", - 3, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateBL2000Poly() */ -/************************************************************************/ - -static OGRFeature *TranslateBL2000Poly(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - /* ==================================================================== */ - /* Traditional POLYGON record groups. */ - /* ==================================================================== */ - if (CSLCount((char **)papoGroup) == 3 && - papoGroup[0]->GetType() == NRT_POLYGON && - papoGroup[1]->GetType() == NRT_ATTREC && - papoGroup[2]->GetType() == NRT_CHAIN) - { - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POLY_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // NUM_PARTS - int nNumLinks = atoi(papoGroup[2]->GetField(9, 12)); - - if (nNumLinks > MAX_LINK) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_estlayers.cpp."); - - return poFeature; - } - - poFeature->SetField(3, nNumLinks); - - // DIR - int i, anList[MAX_LINK] = {0}; - - for (i = 0; i < nNumLinks; i++) - anList[i] = atoi(papoGroup[2]->GetField(19 + i * 7, 19 + i * 7)); - - poFeature->SetField(4, nNumLinks, anList); - - // GEOM_ID_OF_LINK - for (i = 0; i < nNumLinks; i++) - anList[i] = atoi(papoGroup[2]->GetField(13 + i * 7, 18 + i * 7)); - - poFeature->SetField(5, nNumLinks, anList); - - // RingStart - int nRingList = 0; - poFeature->SetField(6, 1, &nRingList); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "PI", 1, "HA", 2, - NULL); - - // Try to assemble polygon geometry. - poReader->FormPolygonFromCache(poFeature); - - return poFeature; - } - - /* ==================================================================== */ - /* CPOLYGON Group */ - /* ==================================================================== */ - - /* -------------------------------------------------------------------- */ - /* First we do validation of the grouping. */ - /* -------------------------------------------------------------------- */ - int iRec = 0; // Used after for. - - for (; papoGroup[iRec] != nullptr && papoGroup[iRec + 1] != nullptr && - papoGroup[iRec]->GetType() == NRT_POLYGON && - papoGroup[iRec + 1]->GetType() == NRT_CHAIN; - iRec += 2) - { - } - - if (CSLCount((char **)papoGroup) != iRec + 2) - return nullptr; - - if (papoGroup[iRec]->GetType() != NRT_CPOLY || - papoGroup[iRec + 1]->GetType() != NRT_ATTREC) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Collect the chains for each of the rings, and just aggregate */ - /* these into the master list without any concept of where the */ - /* boundaries are. The boundary information will be emitted */ - /* in the RingStart field. */ - /* -------------------------------------------------------------------- */ - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - int nNumLink = 0; - int anDirList[MAX_LINK * 2] = {}; - int anGeomList[MAX_LINK * 2] = {}; - int anRingStart[MAX_LINK] = {}; - int nRings = 0; - - for (iRec = 0; - papoGroup[iRec] != nullptr && papoGroup[iRec + 1] != nullptr && - papoGroup[iRec]->GetType() == NRT_POLYGON && - papoGroup[iRec + 1]->GetType() == NRT_CHAIN; - iRec += 2) - { - const int nLineCount = atoi(papoGroup[iRec + 1]->GetField(9, 12)); - - anRingStart[nRings++] = nNumLink; - - for (int i = 0; i < nLineCount && nNumLink < MAX_LINK * 2; i++) - { - anDirList[nNumLink] = - atoi(papoGroup[iRec + 1]->GetField(19 + i * 7, 19 + i * 7)); - anGeomList[nNumLink] = - atoi(papoGroup[iRec + 1]->GetField(13 + i * 7, 18 + i * 7)); - nNumLink++; - } - - if (nNumLink == MAX_LINK * 2) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_estlayers.cpp."); - - delete poFeature; - return nullptr; - } - } - - // NUM_PART - poFeature->SetField(3, nNumLink); - - // DIR - poFeature->SetField(4, nNumLink, anDirList); - - // GEOM_ID_OF_LINK - poFeature->SetField(5, nNumLink, anGeomList); - - // RingStart - poFeature->SetField(6, nRings, anRingStart); - - /* -------------------------------------------------------------------- */ - /* collect information for whole complex polygon. */ - /* -------------------------------------------------------------------- */ - // POLY_ID - if (papoGroup[iRec] != nullptr) - poFeature->SetField(0, atoi(papoGroup[iRec]->GetField(3, 8))); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "PI", 1, "HA", 2, - NULL); - - // Try to assemble polygon geometry. - poReader->FormPolygonFromCache(poFeature); - - return poFeature; -} - -/************************************************************************/ -/* TranslateBL2000Link() */ -/************************************************************************/ - -static OGRFeature *TranslateBL2000Link(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 3 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY || - papoGroup[2]->GetType() != NRT_ATTREC) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "LK", 3, - NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateBL2000Collection() */ -/************************************************************************/ - -static OGRFeature *TranslateBL2000Collection(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_COLLECT || - papoGroup[1]->GetType() != NRT_ATTREC) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // COLL_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // NUM_PARTS - int nNumLinks = atoi(papoGroup[0]->GetField(9, 12)); - - if (nNumLinks > MAX_LINK) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_estlayers.cpp."); - - return poFeature; - } - - poFeature->SetField(1, nNumLinks); - - // POLY_ID / COLL_ID_REFS - int anList[MAX_LINK] = {0}, anCollList[MAX_LINK] = {0}; - int nPolys = 0, nCollections = 0; - - for (int i = 0; i < nNumLinks; i++) - { - if (atoi(papoGroup[0]->GetField(13 + i * 8, 14 + i * 8)) == 34) - anCollList[nCollections++] = - atoi(papoGroup[0]->GetField(15 + i * 8, 20 + i * 8)); - else - anList[nPolys++] = - atoi(papoGroup[0]->GetField(15 + i * 8, 20 + i * 8)); - } - - // coverity[uninit_use_in_call] - poFeature->SetField(2, nPolys, anList); - // coverity[uninit_use_in_call] - poFeature->SetField(10, nCollections, anCollList); - - // Attributes - // Node that _CODE_DESC values are automatically applied if - // the target fields exist. - poReader->ApplyAttributeValues(poFeature, papoGroup, "AI", 3, "OP", 4, "NM", - 5, "TY", 6, "AC", 7, "NB", 8, "NA", 9, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateMeridianPoint() */ -/************************************************************************/ - -static OGRFeature *TranslateMeridianPoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "PN", 3, "OS", - 4, "JN", 5, "RT", 6, "SI", 7, "PI", 8, "NM", - 9, "DA", 10, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateMeridianLine() */ -/************************************************************************/ - -static OGRFeature *TranslateMeridianLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(2, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "OM", 3, "RN", - 4, "TR", 5, "RI", 6, "LC", 7, "RC", 8, "LD", - 9, "RD", 10, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateMeridian2Point() */ -/************************************************************************/ - -static OGRFeature *TranslateMeridian2Point(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(1, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 2, "PN", 3, "OD", - 4, "PO", 5, "JN", 6, "RT", 7, "SN", 8, "SI", - 9, "PI", 10, "NM", 11, "DA", 12, "WA", 13, - "HT", 14, "FA", 15, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateMeridian2Line() */ -/************************************************************************/ - -static OGRFeature *TranslateMeridian2Line(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(2, nGeomId); - - // Attributes - poReader->ApplyAttributeValues( - poFeature, papoGroup, "FC", 1, "OD", 3, "PO", 4, "RN", 5, "TR", 6, "PN", - 7, "RI", 8, "LC", 9, "RC", 10, "LD", 11, "RD", 12, "WI", 14, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateStrategiNode() */ -/* */ -/* Also used for Meridian, Oscar and BaseData.GB nodes. */ -/************************************************************************/ - -static OGRFeature *TranslateStrategiNode(CPL_UNUSED NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 1 || - papoGroup[0]->GetType() != NRT_NODEREC) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // NODE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // GEOM_ID_OF_POINT - poFeature->SetField(1, atoi(papoGroup[0]->GetField(9, 14))); - - // NUM_LINKS - int nNumLinks = atoi(papoGroup[0]->GetField(15, 18)); - - if (nNumLinks < 0 || nNumLinks > MAX_LINK) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_estlayers.cpp."); - - return poFeature; - } - - poFeature->SetField(2, nNumLinks); - - // DIR - int i, anList[MAX_LINK] = {0}; - - for (i = 0; i < nNumLinks; i++) - anList[i] = atoi(papoGroup[0]->GetField(19 + i * 12, 19 + i * 12)); - - poFeature->SetField(3, nNumLinks, anList); - - // GEOM_ID_OF_POINT - for (i = 0; i < nNumLinks; i++) - anList[i] = - atoi(papoGroup[0]->GetField(19 + i * 12 + 1, 19 + i * 12 + 6)); - - poFeature->SetField(4, nNumLinks, anList); - - // LEVEL - for (i = 0; i < nNumLinks; i++) - anList[i] = - atoi(papoGroup[0]->GetField(19 + i * 12 + 11, 19 + i * 12 + 11)); - - poFeature->SetField(5, nNumLinks, anList); - - // ORIENT (optional) - if (EQUAL(poFeature->GetDefnRef()->GetFieldDefn(6)->GetNameRef(), "ORIENT")) - { - double adfList[MAX_LINK] = {0}; - - for (i = 0; i < nNumLinks; i++) - adfList[i] = atoi(papoGroup[0]->GetField(19 + i * 12 + 7, - 19 + i * 12 + 10)) * - 0.1; - - poFeature->SetField(6, nNumLinks, adfList); - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateStrategiText() */ -/* */ -/* Also used for Meridian, BaseData and Generic text. */ -/************************************************************************/ - -static OGRFeature *TranslateStrategiText(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 4 || - papoGroup[0]->GetType() != NRT_TEXTREC || - papoGroup[1]->GetType() != NRT_TEXTPOS || - papoGroup[2]->GetType() != NRT_TEXTREP || - papoGroup[3]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // FONT - poFeature->SetField(2, atoi(papoGroup[2]->GetField(9, 12))); - - // TEXT_HT - poFeature->SetField(3, atoi(papoGroup[2]->GetField(13, 15)) * 0.1); - - // DIG_POSTN - poFeature->SetField(4, atoi(papoGroup[2]->GetField(16, 16))); - - // ORIENT - poFeature->SetField(5, atoi(papoGroup[2]->GetField(17, 20)) * 0.1); - - // TEXT_HT_GROUND - poFeature->SetField(7, poFeature->GetFieldAsDouble(3) * - poReader->GetPaperToGround()); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[3])); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "TX", 6, "DE", - 8, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateStrategiPoint() */ -/************************************************************************/ - -static OGRFeature *TranslateStrategiPoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(10, nGeomId); - - // Attributes - poReader->ApplyAttributeValues( - poFeature, papoGroup, "FC", 1, "PN", 2, "NU", 3, "RB", 4, "RU", 5, "AN", - 6, "AO", 7, "CM", 8, "UN", 9, "DE", 11, "DN", 12, "FM", 13, "GS", 14, - "HI", 15, "HM", 16, "LO", 17, "OR", 18, "OW", 19, "RJ", 20, "RL", 21, - "RM", 22, "RQ", 23, "RW", 24, "RZ", 25, "UE", 26, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateStrategiLine() */ -/************************************************************************/ - -static OGRFeature *TranslateStrategiLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - int nGeomId = 0; - - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[1], &nGeomId)); - - // GEOM_ID - poFeature->SetField(3, nGeomId); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "FC", 1, "PN", 2, "DE", - 4, "FE", 5, "FF", 6, "FI", 7, "FM", 8, "FP", - 9, "FR", 10, "FT", 11, "GS", 12, "NU", 13, - "TX", 14, NULL); - - return poFeature; -} - -/************************************************************************/ -/* TranslateLandrangerPoint() */ -/************************************************************************/ - -static OGRFeature *TranslateLandrangerPoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // FEAT_CODE - poFeature->SetField(1, papoGroup[0]->GetField(17, 20)); - - // HEIGHT - poFeature->SetField(2, atoi(papoGroup[0]->GetField(11, 16))); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - - return poFeature; -} - -/************************************************************************/ -/* TranslateLandrangerLine() */ -/************************************************************************/ - -static OGRFeature *TranslateLandrangerLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // FEAT_CODE - poFeature->SetField(1, papoGroup[0]->GetField(17, 20)); - - // HEIGHT - poFeature->SetField(2, atoi(papoGroup[0]->GetField(11, 16))); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - - return poFeature; -} - -/************************************************************************/ -/* TranslateProfilePoint() */ -/************************************************************************/ - -static OGRFeature *TranslateProfilePoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - (papoGroup[1]->GetType() != NRT_GEOMETRY && - papoGroup[1]->GetType() != NRT_GEOMETRY3D)) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // FEAT_CODE - poFeature->SetField(1, papoGroup[0]->GetField(17, 20)); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "HT", 2, NULL); - - // Set HEIGHT/elevation - OGRPoint *poPoint = dynamic_cast(poFeature->GetGeometryRef()); - - if (poPoint != nullptr && poPoint->getCoordinateDimension() == 3) - { - poFeature->SetField(2, poPoint->getZ()); - } - else if (poPoint != nullptr) - { - poFeature->SetField(2, poFeature->GetFieldAsDouble(2) * 0.01); - poPoint->setZ(poFeature->GetFieldAsDouble(2)); - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateProfileLine() */ -/************************************************************************/ - -static OGRFeature *TranslateProfileLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - (papoGroup[1]->GetType() != NRT_GEOMETRY && - papoGroup[1]->GetType() != NRT_GEOMETRY3D)) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // FEAT_CODE - poFeature->SetField(1, papoGroup[0]->GetField(17, 20)); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - - // Attributes - poReader->ApplyAttributeValues(poFeature, papoGroup, "HT", 2, NULL); - - // Set HEIGHT/elevation - OGRLineString *poLine = - dynamic_cast(poFeature->GetGeometryRef()); - - poFeature->SetField(2, poFeature->GetFieldAsDouble(2) * 0.01); - if (poLine != nullptr && poLine->getCoordinateDimension() == 2) - { - for (int i = 0; i < poLine->getNumPoints(); i++) - { - poLine->setPoint(i, poLine->getX(i), poLine->getY(i), - poFeature->GetFieldAsDouble(2)); - } - } - else if (poLine != nullptr) - { - double dfAccum = 0.0; - - for (int i = 0; i < poLine->getNumPoints(); i++) - { - dfAccum += poLine->getZ(i); - } - poFeature->SetField(2, dfAccum / poLine->getNumPoints()); - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateLandlinePoint() */ -/************************************************************************/ - -static OGRFeature *TranslateLandlinePoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // FEAT_CODE - poFeature->SetField(1, papoGroup[0]->GetField(17, 20)); - - // ORIENT - poFeature->SetField(2, atoi(papoGroup[0]->GetField(11, 16)) * 0.1); - - // DISTANCE - poReader->ApplyAttributeValues(poFeature, papoGroup, "DT", 3, NULL); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - - // CHG_DATE (optional) - if (poFeature->GetFieldIndex("CHG_DATE") == 4) - { - poFeature->SetField(4, papoGroup[0]->GetField(23, 28)); - } - - // CHG_TYPE (optional) - if (poFeature->GetFieldIndex("CHG_TYPE") == 5) - { - poFeature->SetField(5, papoGroup[0]->GetField(22, 22)); - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateLandlineLine() */ -/************************************************************************/ - -static OGRFeature *TranslateLandlineLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - papoGroup[1]->GetType() != NRT_GEOMETRY) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // FEAT_CODE - poFeature->SetField(1, papoGroup[0]->GetField(17, 20)); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - - // CHG_DATE (optional) - if (poFeature->GetFieldIndex("CHG_DATE") == 2) - { - poFeature->SetField(2, papoGroup[0]->GetField(23, 28)); - } - - // CHG_TYPE (optional) - if (poFeature->GetFieldIndex("CHG_TYPE") == 3) - { - poFeature->SetField(3, papoGroup[0]->GetField(22, 22)); - } - return poFeature; -} - -/************************************************************************/ -/* TranslateLandlineName() */ -/************************************************************************/ - -static OGRFeature *TranslateLandlineName(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) != 3 || - papoGroup[0]->GetType() != NRT_NAMEREC || - papoGroup[1]->GetType() != NRT_NAMEPOSTN || - papoGroup[2]->GetType() != NRT_GEOMETRY) - return nullptr; - - int nNumChar = atoi(papoGroup[0]->GetField(13, 14)); - if (nNumChar <= 0) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // NAME_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // TEXT_CODE - poFeature->SetField(1, papoGroup[0]->GetField(9, 12)); - - // TEXT - poFeature->SetField(2, papoGroup[0]->GetField(15, 15 + nNumChar - 1)); - - // FONT - poFeature->SetField(3, atoi(papoGroup[1]->GetField(3, 6))); - - // TEXT_HT - poFeature->SetField(4, atoi(papoGroup[1]->GetField(7, 9)) * 0.1); - - // DIG_POSTN - poFeature->SetField(5, atoi(papoGroup[1]->GetField(10, 10))); - - // ORIENT - poFeature->SetField(6, CPLAtof(papoGroup[1]->GetField(11, 14)) * 0.1); - - // TEXT_HT_GROUND - poFeature->SetField(7, poFeature->GetFieldAsDouble(4) * - poReader->GetPaperToGround()); - - // CHG_DATE (optional) - if (poFeature->GetFieldIndex("CHG_DATE") == 7) - { - poFeature->SetField(8, papoGroup[0]->GetField(15 + nNumChar + 2, - 15 + nNumChar + 2 + 5)); - } - - // CHG_TYPE (optional) - if (poFeature->GetFieldIndex("CHG_TYPE") == 9) - { - poFeature->SetField( - 9, papoGroup[0]->GetField(15 + nNumChar + 1, 15 + nNumChar + 1)); - } - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[2])); - - return poFeature; -} - -/************************************************************************/ -/* EstablishLayer() */ -/* */ -/* Establish one layer based on a simplified description of the */ -/* fields to be present. */ -/************************************************************************/ - -void NTFFileReader::EstablishLayer(const char *pszLayerName, - OGRwkbGeometryType eGeomType, - NTFFeatureTranslator pfnTranslator, - int nLeadRecordType, - NTFGenericClass *poClass, ...) - -{ - /* -------------------------------------------------------------------- */ - /* Does this layer already exist? If so, we do nothing */ - /* ... note that we don't check the definition. */ - /* -------------------------------------------------------------------- */ - OGRNTFLayer *poLayer = poDS->GetNamedLayer(pszLayerName); - - /* ==================================================================== */ - /* Create a new layer matching the request if we don't already */ - /* have one. */ - /* ==================================================================== */ - if (poLayer == nullptr) - { - /* -------------------------------------------------------------------- - */ - /* Create a new feature definition. */ - /* -------------------------------------------------------------------- - */ - OGRFeatureDefn *poDefn = new OGRFeatureDefn(pszLayerName); - poDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->DSGetSpatialRef()); - poDefn->SetGeomType(eGeomType); - poDefn->Reference(); - - /* -------------------------------------------------------------------- - */ - /* Fetch definitions of each field in turn. */ - /* -------------------------------------------------------------------- - */ - va_list hVaArgs; - va_start(hVaArgs, poClass); - while (true) - { - const char *pszFieldName = va_arg(hVaArgs, const char *); - - if (pszFieldName == nullptr) - break; - - const OGRFieldType eType = (OGRFieldType)va_arg(hVaArgs, int); - const int nWidth = va_arg(hVaArgs, int); - const int nPrecision = va_arg(hVaArgs, int); - - OGRFieldDefn oFieldDefn(pszFieldName, eType); - oFieldDefn.SetWidth(nWidth); - oFieldDefn.SetPrecision(nPrecision); - - poDefn->AddFieldDefn(&oFieldDefn); - } - - va_end(hVaArgs); - - /* -------------------------------------------------------------------- - */ - /* Add attributes collected in the generic class survey. */ - /* -------------------------------------------------------------------- - */ - if (poClass != nullptr) - { - for (int iGAtt = 0; iGAtt < poClass->nAttrCount; iGAtt++) - { - const char *pszFormat = poClass->papszAttrFormats[iGAtt]; - OGRFieldDefn oFieldDefn(poClass->papszAttrNames[iGAtt], - OFTInteger); - - if (STARTS_WITH_CI(pszFormat, "I")) - { - oFieldDefn.SetType(OFTInteger); - oFieldDefn.SetWidth(poClass->panAttrMaxWidth[iGAtt]); - } - else if (STARTS_WITH_CI(pszFormat, "D") || - STARTS_WITH_CI(pszFormat, "A")) - { - oFieldDefn.SetType(OFTString); - oFieldDefn.SetWidth(poClass->panAttrMaxWidth[iGAtt]); - } - else if (STARTS_WITH_CI(pszFormat, "R")) - { - oFieldDefn.SetType(OFTReal); - oFieldDefn.SetWidth(poClass->panAttrMaxWidth[iGAtt] + 1); - const size_t nFormatLen = strlen(pszFormat); - if (nFormatLen >= 4 && pszFormat[2] == ',') - oFieldDefn.SetPrecision(atoi(pszFormat + 3)); - else if (nFormatLen >= 5 && pszFormat[3] == ',') - oFieldDefn.SetPrecision(atoi(pszFormat + 4)); - } - - poDefn->AddFieldDefn(&oFieldDefn); - - /* - ** If this field can appear multiple times, create an - ** additional attribute to hold lists of values. This - ** is always created as a variable length string field. - */ - if (poClass->pabAttrMultiple[iGAtt]) - { - char szName[128]; - - snprintf(szName, sizeof(szName), "%s_LIST", - poClass->papszAttrNames[iGAtt]); - - OGRFieldDefn oFieldDefnL(szName, OFTString); - - poDefn->AddFieldDefn(&oFieldDefnL); - } - } - } - - /* -------------------------------------------------------------------- - */ - /* Add the TILE_REF attribute. */ - /* -------------------------------------------------------------------- - */ - OGRFieldDefn oTileID("TILE_REF", OFTString); - - oTileID.SetWidth(10); - - poDefn->AddFieldDefn(&oTileID); - - /* -------------------------------------------------------------------- - */ - /* Create the layer, and give over to the data source object to */ - /* maintain. */ - /* -------------------------------------------------------------------- - */ - poLayer = new OGRNTFLayer(poDS, poDefn, pfnTranslator); - - poDS->AddLayer(poLayer); - } - - /* -------------------------------------------------------------------- */ - /* Register this translator with this file reader for handling */ - /* the indicate record type. */ - /* -------------------------------------------------------------------- */ - apoTypeTranslation[nLeadRecordType] = poLayer; -} - -/************************************************************************/ -/* EstablishLayers() */ -/* */ -/* This method is responsible for creating any missing */ -/* OGRNTFLayers needed for the current product based on the */ -/* product name. */ -/* */ -/* NOTE: Any changes to the order of attribute fields in the */ -/* following EstablishLayer() calls must also result in updates */ -/* to the translate functions. Changes of names, widths and to */ -/* some extent types can be done without side effects. */ -/************************************************************************/ - -void NTFFileReader::EstablishLayers() - -{ - if (poDS == nullptr || fp == nullptr) - return; - - if (GetProductId() == NPC_LANDLINE) - { - EstablishLayer("LANDLINE_POINT", wkbPoint, TranslateLandlinePoint, - NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "ORIENT", OFTReal, 5, 1, - "DISTANCE", OFTReal, 6, 3, NULL); - - EstablishLayer("LANDLINE_LINE", wkbLineString, TranslateLandlineLine, - NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, NULL); - - EstablishLayer("LANDLINE_NAME", wkbPoint, TranslateLandlineName, - NRT_NAMEREC, nullptr, "NAME_ID", OFTInteger, 6, 0, - "TEXT_CODE", OFTString, 4, 0, "TEXT", OFTString, 0, 0, - "FONT", OFTInteger, 4, 0, "TEXT_HT", OFTReal, 4, 1, - "DIG_POSTN", OFTInteger, 1, 0, "ORIENT", OFTReal, 5, 1, - "TEXT_HT_GROUND", OFTReal, 10, 3, NULL); - } - else if (GetProductId() == NPC_LANDLINE99) - { - EstablishLayer("LANDLINE99_POINT", wkbPoint, TranslateLandlinePoint, - NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "ORIENT", OFTReal, 5, 1, - "DISTANCE", OFTReal, 6, 3, "CHG_DATE", OFTString, 6, 0, - "CHG_TYPE", OFTString, 1, 0, NULL); - - EstablishLayer("LANDLINE99_LINE", wkbLineString, TranslateLandlineLine, - NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "CHG_DATE", OFTString, 6, - 0, "CHG_TYPE", OFTString, 1, 0, NULL); - - EstablishLayer("LANDLINE99_NAME", wkbPoint, TranslateLandlineName, - NRT_NAMEREC, nullptr, "NAME_ID", OFTInteger, 6, 0, - "TEXT_CODE", OFTString, 4, 0, "TEXT", OFTString, 0, 0, - "FONT", OFTInteger, 4, 0, "TEXT_HT", OFTReal, 4, 1, - "DIG_POSTN", OFTInteger, 1, 0, "ORIENT", OFTReal, 5, 1, - "TEXT_HT_GROUND", OFTReal, 10, 3, "CHG_DATE", OFTString, - 6, 0, "CHG_TYPE", OFTString, 1, 0, NULL); - } - else if (GetProductId() == NPC_LANDRANGER_CONT) - { - EstablishLayer("PANORAMA_POINT", wkbPoint, TranslateLandrangerPoint, - NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "HEIGHT", OFTReal, 7, 2, - NULL); - - EstablishLayer("PANORAMA_CONTOUR", wkbLineString, - TranslateLandrangerLine, NRT_LINEREC, nullptr, "LINE_ID", - OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, 0, "HEIGHT", - OFTReal, 7, 2, NULL); - } - else if (GetProductId() == NPC_LANDFORM_PROFILE_CONT) - { - EstablishLayer("PROFILE_POINT", wkbPoint25D, TranslateProfilePoint, - NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "HEIGHT", OFTReal, 7, 2, - NULL); - - EstablishLayer("PROFILE_LINE", wkbLineString25D, TranslateProfileLine, - NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "HEIGHT", OFTReal, 7, 2, - NULL); - } - else if (GetProductId() == NPC_STRATEGI) - { - EstablishLayer( - "STRATEGI_POINT", wkbPoint, TranslateStrategiPoint, NRT_POINTREC, - nullptr, "POINT_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, 0, - "PROPER_NAME", OFTString, 0, 0, "FEATURE_NUMBER", OFTString, 0, 0, - "RB", OFTString, 1, 0, "RU", OFTString, 1, 0, "AN", OFTString, 0, 0, - "AO", OFTString, 0, 0, "COUNTY_NAME", OFTString, 0, 0, - "UNITARY_NAME", OFTString, 0, 0, "GEOM_ID", OFTInteger, 6, 0, - "DATE", OFTInteger, 8, 0, "DISTRICT_NAME", OFTString, 0, 0, - "FEATURE_NAME", OFTString, 0, 0, "GIS", OFTString, 0, 0, - "HEIGHT_IMPERIAL", OFTInteger, 4, 0, "HEIGHT_METRIC", OFTInteger, 4, - 0, "LOCATION", OFTInteger, 1, 0, "ORIENTATION", OFTReal, 4, 1, - "OWNER", OFTString, 0, 0, "RESTRICTION_NORTH", OFTString, 0, 0, - "RESTRICTION_SOUTH", OFTString, 0, 0, "RESTRICTION_EAST", OFTString, - 0, 0, "RESTRICTION_WEST", OFTString, 0, 0, "RESTRICTION_CLOCKWISE", - OFTString, 0, 0, "RESTRICTION_ANTICLOCKWISE", OFTString, 0, 0, - "USAGE", OFTInteger, 1, 0, NULL); - - EstablishLayer( - "STRATEGI_LINE", wkbLineString, TranslateStrategiLine, NRT_LINEREC, - nullptr, "LINE_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, 0, - "PROPER_NAME", OFTString, 0, 0, "GEOM_ID", OFTInteger, 6, 0, "DATE", - OFTInteger, 8, 0, "FERRY_ACCESS", OFTString, 0, 0, "FERRY_FROM", - OFTString, 0, 0, "FERRY_TIME", OFTString, 0, 0, "FEATURE_NAME", - OFTString, 0, 0, "FERRY_TYPE", OFTString, 0, 0, - "FERRY_RESTRICTIONS", OFTString, 0, 0, "FERRY_TO", OFTString, 0, 0, - "GIS", OFTString, 0, 0, "FEATURE_NUMBER", OFTString, 0, 0, NULL); - - EstablishLayer( - "STRATEGI_TEXT", wkbPoint, TranslateStrategiText, NRT_TEXTREC, - nullptr, "TEXT_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, 0, - "FONT", OFTInteger, 4, 0, "TEXT_HT", OFTReal, 5, 1, "DIG_POSTN", - OFTInteger, 1, 0, "ORIENT", OFTReal, 5, 1, "TEXT", OFTString, 0, 0, - "TEXT_HT_GROUND", OFTReal, 10, 3, "DATE", OFTInteger, 8, 0, NULL); - - EstablishLayer("STRATEGI_NODE", wkbNone, TranslateStrategiNode, - NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0, - "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS", - OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0, - "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL", - OFTIntegerList, 1, 0, "ORIENT", OFTRealList, 5, 1, NULL); - } - else if (GetProductId() == NPC_MERIDIAN) - { - EstablishLayer("MERIDIAN_POINT", wkbPoint, TranslateMeridianPoint, - NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0, - "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, - 0, "PROPER_NAME", OFTString, 0, 0, "OSMDR", OFTString, - 13, 0, "JUNCTION_NAME", OFTString, 0, 0, "ROUNDABOUT", - OFTString, 1, 0, "STATION_ID", OFTString, 13, 0, - "GLOBAL_ID", OFTInteger, 6, 0, "ADMIN_NAME", OFTString, - 0, 0, "DA_DLUA_ID", OFTString, 13, 0, NULL); - - EstablishLayer("MERIDIAN_LINE", wkbLineString, TranslateMeridianLine, - NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "GEOM_ID", OFTInteger, 6, - 0, "OSMDR", OFTString, 13, 0, "ROAD_NUM", OFTString, 0, - 0, "TRUNK_ROAD", OFTString, 1, 0, "RAIL_ID", OFTString, - 13, 0, "LEFT_COUNTY", OFTInteger, 6, 0, "RIGHT_COUNTY", - OFTInteger, 6, 0, "LEFT_DISTRICT", OFTInteger, 6, 0, - "RIGHT_DISTRICT", OFTInteger, 6, 0, NULL); - - EstablishLayer("MERIDIAN_TEXT", wkbPoint, TranslateStrategiText, - NRT_TEXTREC, nullptr, "TEXT_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "FONT", OFTInteger, 4, 0, - "TEXT_HT", OFTReal, 5, 1, "DIG_POSTN", OFTInteger, 1, 0, - "ORIENT", OFTReal, 5, 1, "TEXT", OFTString, 0, 0, - "TEXT_HT_GROUND", OFTReal, 10, 3, NULL); - - EstablishLayer("MERIDIAN_NODE", wkbNone, TranslateStrategiNode, - NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0, - "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS", - OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0, - "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL", - OFTIntegerList, 1, 0, "ORIENT", OFTRealList, 5, 1, NULL); - } - else if (GetProductId() == NPC_MERIDIAN2) - { - EstablishLayer( - "MERIDIAN2_POINT", wkbPoint, TranslateMeridian2Point, NRT_POINTREC, - nullptr, "POINT_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "PROPER_NAME", OFTString, 0, 0, - "OSODR", OFTString, 13, 0, "PARENT_OSODR", OFTString, 13, 0, - "JUNCTION_NAME", OFTString, 0, 0, "ROUNDABOUT", OFTString, 1, 0, - "SETTLEMENT_NAME", OFTString, 0, 0, "STATION_ID", OFTString, 13, 0, - "GLOBAL_ID", OFTInteger, 6, 0, "ADMIN_NAME", OFTString, 0, 0, - "DA_DLUA_ID", OFTString, 13, 0, "WATER_AREA", OFTString, 13, 0, - "HEIGHT", OFTInteger, 8, 0, "FOREST_ID", OFTString, 13, 0, NULL); - - EstablishLayer("MERIDIAN2_LINE", wkbLineString, TranslateMeridian2Line, - NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "GEOM_ID", OFTInteger, 6, - 0, "OSODR", OFTString, 13, 0, "PARENT_OSODR", OFTString, - 13, 0, "ROAD_NUM", OFTString, 0, 0, "TRUNK_ROAD", - OFTString, 1, 0, "PROPER_NAME", OFTString, 0, 0, - "RAIL_ID", OFTString, 13, 0, "LEFT_COUNTY", OFTInteger, - 6, 0, "RIGHT_COUNTY", OFTInteger, 6, 0, "LEFT_DISTRICT", - OFTInteger, 6, 0, "RIGHT_DISTRICT", OFTInteger, 6, 0, - "WATER_LINK_ID", OFTString, 13, 0, NULL); - - EstablishLayer("MERIDIAN2_TEXT", wkbPoint, TranslateStrategiText, - NRT_TEXTREC, nullptr, "TEXT_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "FONT", OFTInteger, 4, 0, - "TEXT_HT", OFTReal, 5, 1, "DIG_POSTN", OFTInteger, 1, 0, - "ORIENT", OFTReal, 5, 1, "TEXT", OFTString, 0, 0, - "TEXT_HT_GROUND", OFTReal, 10, 3, NULL); - - EstablishLayer("MERIDIAN2_NODE", wkbNone, TranslateStrategiNode, - NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0, - "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS", - OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0, - "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL", - OFTIntegerList, 1, 0, "ORIENT", OFTRealList, 5, 1, NULL); - } - else if (GetProductId() == NPC_BOUNDARYLINE) - { - EstablishLayer("BOUNDARYLINE_LINK", wkbLineString, - TranslateBoundarylineLink, NRT_GEOMETRY, nullptr, - "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, - 0, "GLOBAL_LINK_ID", OFTInteger, 10, 0, "HWM_FLAG", - OFTInteger, 1, 0, NULL); - - EstablishLayer("BOUNDARYLINE_POLY", bCacheLines ? wkbPolygon : wkbPoint, - TranslateBoundarylinePoly, NRT_POLYGON, nullptr, - "POLY_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, - 0, "GLOBAL_SEED_ID", OFTInteger, 6, 0, "HECTARES", - OFTReal, 9, 3, "NUM_PARTS", OFTInteger, 4, 0, "DIR", - OFTIntegerList, 1, 0, "GEOM_ID_OF_LINK", OFTIntegerList, - 6, 0, "RingStart", OFTIntegerList, 6, 0, NULL); - - EstablishLayer("BOUNDARYLINE_COLLECTIONS", wkbNone, - TranslateBoundarylineCollection, NRT_COLLECT, nullptr, - "COLL_ID", OFTInteger, 6, 0, "NUM_PARTS", OFTInteger, 4, - 0, "POLY_ID", OFTIntegerList, 6, 0, "ADMIN_AREA_ID", - OFTInteger, 6, 0, "OPCS_CODE", OFTString, 6, 0, - "ADMIN_NAME", OFTString, 0, 0, NULL); - } - else if (GetProductId() == NPC_BL2000) - { - EstablishLayer("BL2000_LINK", wkbLineString, TranslateBL2000Link, - NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0, - "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, - 0, "GLOBAL_LINK_ID", OFTInteger, 10, 0, NULL); - EstablishLayer("BL2000_POLY", bCacheLines ? wkbPolygon : wkbNone, - TranslateBL2000Poly, NRT_POLYGON, nullptr, "POLY_ID", - OFTInteger, 6, 0, "GLOBAL_SEED_ID", OFTInteger, 6, 0, - "HECTARES", OFTReal, 12, 3, "NUM_PARTS", OFTInteger, 4, - 0, "DIR", OFTIntegerList, 1, 0, "GEOM_ID_OF_LINK", - OFTIntegerList, 6, 0, "RingStart", OFTIntegerList, 6, 0, - NULL); - if (poDS->GetOption("CODELIST") != nullptr && - EQUAL(poDS->GetOption("CODELIST"), "ON")) - EstablishLayer( - "BL2000_COLLECTIONS", wkbNone, TranslateBL2000Collection, - NRT_COLLECT, nullptr, "COLL_ID", OFTInteger, 6, 0, "NUM_PARTS", - OFTInteger, 4, 0, "POLY_ID", OFTIntegerList, 6, 0, - "ADMIN_AREA_ID", OFTInteger, 6, 0, "CENSUS_CODE", OFTString, 7, - 0, "ADMIN_NAME", OFTString, 0, 0, "AREA_TYPE", OFTString, 2, 0, - "AREA_CODE", OFTString, 3, 0, "NON_TYPE_CODE", OFTString, 3, 0, - "NON_INLAND_AREA", OFTReal, 12, 3, "COLL_ID_REFS", - OFTIntegerList, 6, 0, "AREA_TYPE_DESC", OFTString, 0, 0, - "AREA_CODE_DESC", OFTString, 0, 0, "NON_TYPE_CODE_DESC", - OFTString, 0, 0, NULL); - else - EstablishLayer( - "BL2000_COLLECTIONS", wkbNone, TranslateBL2000Collection, - NRT_COLLECT, nullptr, "COLL_ID", OFTInteger, 6, 0, "NUM_PARTS", - OFTInteger, 4, 0, "POLY_ID", OFTIntegerList, 6, 0, - "ADMIN_AREA_ID", OFTInteger, 6, 0, "CENSUS_CODE", OFTString, 7, - 0, "ADMIN_NAME", OFTString, 0, 0, "AREA_TYPE", OFTString, 2, 0, - "AREA_CODE", OFTString, 3, 0, "NON_TYPE_CODE", OFTString, 3, 0, - "NON_INLAND_AREA", OFTReal, 12, 3, "COLL_ID_REFS", - OFTIntegerList, 6, 0, NULL); - } - else if (GetProductId() == NPC_BASEDATA) - { - EstablishLayer( - "BASEDATA_POINT", wkbPoint, TranslateBasedataPoint, NRT_POINTREC, - nullptr, "POINT_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "PROPER_NAME", OFTString, 0, 0, - "FEATURE_NUMBER", OFTString, 0, 0, "COUNTY_NAME", OFTString, 0, 0, - "UNITARY_NAME", OFTString, 0, 0, "ORIENT", OFTRealList, 5, 1, NULL); - - EstablishLayer("BASEDATA_LINE", wkbLineString, TranslateBasedataLine, - NRT_LINEREC, nullptr, "LINE_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "GEOM_ID", OFTInteger, 6, - 0, "PROPER_NAME", OFTString, 0, 0, "FEATURE_NUMBER", - OFTString, 0, 0, "RB", OFTString, 1, 0, NULL); - - EstablishLayer("BASEDATA_TEXT", wkbPoint, TranslateStrategiText, - NRT_TEXTREC, nullptr, "TEXT_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "FONT", OFTInteger, 4, 0, - "TEXT_HT", OFTReal, 5, 1, "DIG_POSTN", OFTInteger, 1, 0, - "ORIENT", OFTReal, 5, 1, "TEXT", OFTString, 0, 0, - "TEXT_HT_GROUND", OFTReal, 10, 3, NULL); - - EstablishLayer("BASEDATA_NODE", wkbNone, TranslateStrategiNode, - NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0, - "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS", - OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0, - "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL", - OFTIntegerList, 1, 0, "ORIENT", OFTRealList, 5, 1, NULL); - } - else if (GetProductId() == NPC_OSCAR_ASSET || - GetProductId() == NPC_OSCAR_TRAFFIC) - { - EstablishLayer("OSCAR_POINT", wkbPoint, TranslateOscarPoint, - NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0, - "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, - 0, "OSODR", OFTString, 13, 0, "JUNCTION_NAME", OFTString, - 0, 0, "SETTLE_NAME", OFTString, 0, 0, NULL); - - EstablishLayer( - "OSCAR_LINE", wkbLineString, TranslateOscarLine, NRT_LINEREC, - nullptr, "LINE_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "OSODR", OFTString, 13, 0, - "PROPER_NAME", OFTString, 0, 0, "LINE_LENGTH", OFTInteger, 5, 0, - "SOURCE", OFTString, 1, 0, "FORM_OF_WAY", OFTString, 1, 0, - "ROAD_NUM", OFTString, 0, 0, "TRUNK_ROAD", OFTString, 1, 0, NULL); - - EstablishLayer("OSCAR_NODE", wkbNone, TranslateStrategiNode, - NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0, - "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS", - OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0, - "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL", - OFTIntegerList, 1, 0, NULL); - - EstablishLayer("OSCAR_COMMENT", wkbNone, TranslateOscarComment, - NRT_COMMENT, nullptr, "RECORD_TYPE", OFTInteger, 2, 0, - "RECORD_ID", OFTString, 13, 0, "CHANGE_TYPE", OFTString, - 1, 0, NULL); - } - else if (GetProductId() == NPC_OSCAR_ROUTE) - { - EstablishLayer("OSCAR_ROUTE_POINT", wkbPoint, TranslateOscarRoutePoint, - NRT_POINTREC, nullptr, "POINT_ID", OFTInteger, 6, 0, - "GEOM_ID", OFTInteger, 6, 0, "FEAT_CODE", OFTString, 4, - 0, "OSODR", OFTString, 13, 0, "JUNCTION_NAME", OFTString, - 0, 0, "SETTLE_NAME", OFTString, 0, 0, "NUM_PARENTS", - OFTInteger, 2, 0, "PARENT_OSODR", OFTStringList, 13, 0, - "ROUNDABOUT", OFTString, 1, 0, NULL); - - EstablishLayer("OSCAR_ROUTE_LINE", wkbLineString, - TranslateOscarRouteLine, NRT_LINEREC, nullptr, "LINE_ID", - OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "OSODR", OFTString, 13, 0, - "PROPER_NAME", OFTString, 0, 0, "LINE_LENGTH", - OFTInteger, 5, 0, "ROAD_NUM", OFTString, 0, 0, - "TRUNK_ROAD", OFTString, 1, 0, "NUM_PARENTS", OFTInteger, - 2, 0, "PARENT_OSODR", OFTStringList, 13, 0, NULL); - - EstablishLayer("OSCAR_ROUTE_NODE", wkbNone, TranslateStrategiNode, - NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0, - "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS", - OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0, - "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL", - OFTIntegerList, 1, 0, NULL); - - EstablishLayer("OSCAR_COMMENT", wkbNone, TranslateOscarComment, - NRT_COMMENT, nullptr, "RECORD_TYPE", OFTInteger, 2, 0, - "RECORD_ID", OFTString, 13, 0, "CHANGE_TYPE", OFTString, - 1, 0, NULL); - } - else if (GetProductId() == NPC_OSCAR_NETWORK) - { - EstablishLayer("OSCAR_NETWORK_POINT", wkbPoint, - TranslateOscarNetworkPoint, NRT_POINTREC, nullptr, - "POINT_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, - 0, "FEAT_CODE", OFTString, 4, 0, "OSODR", OFTString, 13, - 0, "JUNCTION_NAME", OFTString, 0, 0, "SETTLE_NAME", - OFTString, 0, 0, "ROUNDABOUT", OFTString, 1, 0, NULL); - - EstablishLayer("OSCAR_NETWORK_LINE", wkbLineString, - TranslateOscarNetworkLine, NRT_LINEREC, nullptr, - "LINE_ID", OFTInteger, 6, 0, "GEOM_ID", OFTInteger, 6, 0, - "FEAT_CODE", OFTString, 4, 0, "OSODR", OFTString, 13, 0, - "PROPER_NAME", OFTString, 0, 0, "LINE_LENGTH", - OFTInteger, 5, 0, "ROAD_NUM", OFTString, 0, 0, NULL); - - EstablishLayer("OSCAR_NETWORK_NODE", wkbNone, TranslateStrategiNode, - NRT_NODEREC, nullptr, "NODE_ID", OFTInteger, 6, 0, - "GEOM_ID_OF_POINT", OFTInteger, 6, 0, "NUM_LINKS", - OFTInteger, 4, 0, "DIR", OFTIntegerList, 1, 0, - "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "LEVEL", - OFTIntegerList, 1, 0, NULL); - - EstablishLayer("OSCAR_COMMENT", wkbNone, TranslateOscarComment, - NRT_COMMENT, nullptr, "RECORD_TYPE", OFTInteger, 2, 0, - "RECORD_ID", OFTString, 13, 0, "CHANGE_TYPE", OFTString, - 1, 0, NULL); - } - else if (GetProductId() == NPC_ADDRESS_POINT) - { - EstablishLayer( - "ADDRESS_POINT", wkbPoint, TranslateAddressPoint, NRT_POINTREC, - nullptr, "POINT_ID", OFTInteger, 6, 0, "OSAPR", OFTString, 18, 0, - "ORGANISATION_NAME", OFTString, 0, 0, "DEPARTMENT_NAME", OFTString, - 0, 0, "PO_BOX", OFTString, 6, 0, "SUBBUILDING_NAME", OFTString, 0, - 0, "BUILDING_NAME", OFTString, 0, 0, "BUILDING_NUMBER", OFTInteger, - 4, 0, "DEPENDENT_THOROUGHFARE_NAME", OFTString, 0, 0, - "THOROUGHFARE_NAME", OFTString, 0, 0, - "DOUBLE_DEPENDENT_LOCALITY_NAME", OFTString, 0, 0, - "DEPENDENT_LOCALITY_NAME", OFTString, 0, 0, "POST_TOWN_NAME", - OFTString, 0, 0, "COUNTY_NAME", OFTString, 0, 0, "POSTCODE", - OFTString, 7, 0, "STATUS_FLAG", OFTString, 4, 0, "RM_VERSION_DATE", - OFTString, 8, 0, "CHG_TYPE", OFTString, 1, 0, "CHG_DATE", OFTString, - 6, 0, NULL); - } - else if (GetProductId() == NPC_CODE_POINT) - { - EstablishLayer( - "CODE_POINT", wkbPoint, TranslateCodePoint, NRT_POINTREC, nullptr, - "POINT_ID", OFTInteger, 6, 0, "UNIT_POSTCODE", OFTString, 7, 0, - "POSITIONAL_QUALITY", OFTInteger, 1, 0, "PO_BOX_INDICATOR", - OFTString, 1, 0, "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0, - "DELIVERY_POINTS", OFTInteger, 3, 0, "DOMESTIC_DELIVERY_POINTS", - OFTInteger, 3, 0, "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, - "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0, - "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0, - "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0, "RM_VERSION_DATA", - OFTString, 8, 0, NULL); - } - else if (GetProductId() == NPC_CODE_POINT_PLUS) - { - EstablishLayer( - "CODE_POINT_PLUS", wkbPoint, TranslateCodePoint, NRT_POINTREC, - nullptr, "POINT_ID", OFTInteger, 6, 0, "UNIT_POSTCODE", OFTString, - 7, 0, "POSITIONAL_QUALITY", OFTInteger, 1, 0, "PO_BOX_INDICATOR", - OFTString, 1, 0, "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0, - "DELIVERY_POINTS", OFTInteger, 3, 0, "DOMESTIC_DELIVERY_POINTS", - OFTInteger, 3, 0, "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, - "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0, - "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0, - "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0, "RM_VERSION_DATA", - OFTString, 8, 0, "NHS_REGIONAL_HEALTH_AUTHORITY", OFTString, 3, 0, - "NHS_HEALTH_AUTHORITY", OFTString, 3, 0, "ADMIN_COUNTY", OFTString, - 2, 0, "ADMIN_DISTRICT", OFTString, 2, 0, "ADMIN_WARD", OFTString, 2, - 0, NULL); - } - else // generic case - { - CPLAssert(GetProductId() == NPC_UNKNOWN); - - poDS->WorkupGeneric(this); - } -} diff --git a/ogr/ogrsf_frmts/ntf/ntf_generic.cpp b/ogr/ogrsf_frmts/ntf/ntf_generic.cpp deleted file mode 100644 index 53a78e49bc2b..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntf_generic.cpp +++ /dev/null @@ -1,941 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: Handle NTF products that aren't recognised generically. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include -#include "ntf.h" -#include "cpl_string.h" - -/************************************************************************/ -/* ==================================================================== */ -/* NTFGenericClass */ -/* */ -/* The NTFGenericClass class exists to hold aggregated */ -/* information for each type of record encountered in a set of */ -/* NTF files, primarily the list of attributes actually */ -/* encountered. */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* NTFGenericClass */ -/************************************************************************/ - -NTFGenericClass::NTFGenericClass() - : nFeatureCount(0), b3D(FALSE), nAttrCount(0), papszAttrNames(nullptr), - papszAttrFormats(nullptr), panAttrMaxWidth(nullptr), - pabAttrMultiple(nullptr) -{ -} - -/************************************************************************/ -/* ~NTFGenericClass */ -/************************************************************************/ - -NTFGenericClass::~NTFGenericClass() - -{ - CSLDestroy(papszAttrNames); - CSLDestroy(papszAttrFormats); - CPLFree(panAttrMaxWidth); - CPLFree(pabAttrMultiple); -} - -/************************************************************************/ -/* CheckAddAttr() */ -/* */ -/* Check if an attribute already exists. If not add it with */ -/* its format. Note we don't check for format conflicts at */ -/* this time. */ -/************************************************************************/ - -void NTFGenericClass::CheckAddAttr(const char *pszName, const char *pszFormat, - int nWidth) - -{ - if (EQUAL(pszName, "TX")) - pszName = "TEXT"; - if (EQUAL(pszName, "FC")) - pszName = "FEAT_CODE"; - - const int iAttrOffset = CSLFindString(papszAttrNames, pszName); - - if (iAttrOffset == -1) - { - nAttrCount++; - - papszAttrNames = CSLAddString(papszAttrNames, pszName); - papszAttrFormats = CSLAddString(papszAttrFormats, pszFormat); - - panAttrMaxWidth = static_cast( - CPLRealloc(panAttrMaxWidth, sizeof(int) * nAttrCount)); - - panAttrMaxWidth[nAttrCount - 1] = nWidth; - - pabAttrMultiple = static_cast( - CPLRealloc(pabAttrMultiple, sizeof(int) * nAttrCount)); - - pabAttrMultiple[nAttrCount - 1] = FALSE; - } - else - { - if (panAttrMaxWidth[iAttrOffset] < nWidth) - panAttrMaxWidth[iAttrOffset] = nWidth; - } -} - -/************************************************************************/ -/* SetMultiple() */ -/* */ -/* Mark this attribute as appearing multiple times on some */ -/* features. */ -/************************************************************************/ - -void NTFGenericClass::SetMultiple(const char *pszName) - -{ - if (EQUAL(pszName, "TX")) - pszName = "TEXT"; - if (EQUAL(pszName, "FC")) - pszName = "FEAT_CODE"; - - const int iAttrOffset = CSLFindString(papszAttrNames, pszName); - if (iAttrOffset == -1) - return; - - pabAttrMultiple[iAttrOffset] = TRUE; -} - -/************************************************************************/ -/* WorkupGeneric() */ -/* */ -/* Scan a whole file, in order to build up a list of attributes */ -/* for the generic types. */ -/************************************************************************/ - -void OGRNTFDataSource::WorkupGeneric(NTFFileReader *poReader) - -{ - NTFRecord **papoGroup = nullptr; - - if (poReader->GetNTFLevel() > 2) - { - poReader->IndexFile(); - if (CPLGetLastErrorType() == CE_Failure) - return; - } - else - poReader->Reset(); - - /* ==================================================================== */ - /* Read all record groups in the file. */ - /* ==================================================================== */ - while (true) - { - /* -------------------------------------------------------------------- - */ - /* Read a record group */ - /* -------------------------------------------------------------------- - */ - if (poReader->GetNTFLevel() > 2) - papoGroup = poReader->GetNextIndexedRecordGroup(papoGroup); - else - papoGroup = poReader->ReadRecordGroup(); - - if (papoGroup == nullptr || papoGroup[0]->GetType() < 0 || - papoGroup[0]->GetType() >= 99) - break; - - /* -------------------------------------------------------------------- - */ - /* Get the class corresponding to the anchor record. */ - /* -------------------------------------------------------------------- - */ - NTFGenericClass *poClass = GetGClass(papoGroup[0]->GetType()); - char **papszFullAttList = nullptr; - - poClass->nFeatureCount++; - - /* -------------------------------------------------------------------- - */ - /* Loop over constituent records collecting attributes. */ - /* -------------------------------------------------------------------- - */ - for (int iRec = 0; papoGroup[iRec] != nullptr; iRec++) - { - NTFRecord *poRecord = papoGroup[iRec]; - - switch (poRecord->GetType()) - { - case NRT_ATTREC: - { - char **papszTypes, **papszValues; - - poReader->ProcessAttRec(poRecord, nullptr, &papszTypes, - &papszValues); - - for (int iAtt = 0; - papszTypes != nullptr && papszTypes[iAtt] != nullptr; - iAtt++) - { - NTFAttDesc *poAttDesc = - poReader->GetAttDesc(papszTypes[iAtt]); - if (poAttDesc != nullptr && - papszValues[iAtt] != nullptr) - { - poClass->CheckAddAttr( - poAttDesc->val_type, poAttDesc->finter, - static_cast(strlen(papszValues[iAtt]))); - } - - if (CSLFindString(papszFullAttList, papszTypes[iAtt]) == - -1) - papszFullAttList = CSLAddString(papszFullAttList, - papszTypes[iAtt]); - else if (poAttDesc != nullptr) - poClass->SetMultiple(poAttDesc->val_type); - } - - CSLDestroy(papszTypes); - CSLDestroy(papszValues); - } - break; - - case NRT_TEXTREP: - case NRT_NAMEPOSTN: - poClass->CheckAddAttr("FONT", "I4", 4); - poClass->CheckAddAttr("TEXT_HT", "R3,1", 3); - poClass->CheckAddAttr("TEXT_HT_GROUND", "R9,3", 9); - poClass->CheckAddAttr("TEXT_HT", "R3,1", 3); - poClass->CheckAddAttr("DIG_POSTN", "I1", 1); - poClass->CheckAddAttr("ORIENT", "R4,1", 4); - break; - - case NRT_NAMEREC: - poClass->CheckAddAttr("TEXT", "A*", - atoi(poRecord->GetField(13, 14))); - break; - - case NRT_GEOMETRY: - case NRT_GEOMETRY3D: - if (atoi(poRecord->GetField(3, 8)) != 0) - poClass->CheckAddAttr("GEOM_ID", "I6", 6); - if (poRecord->GetType() == NRT_GEOMETRY3D) - poClass->b3D = TRUE; - break; - - case NRT_POINTREC: - case NRT_LINEREC: - if (poReader->GetNTFLevel() < 3) - { - NTFAttDesc *poAttDesc = - poReader->GetAttDesc(poRecord->GetField(9, 10)); - if (poAttDesc != nullptr) - poClass->CheckAddAttr(poAttDesc->val_type, - poAttDesc->finter, 6); - - if (!EQUAL(poRecord->GetField(17, 20), " ")) - poClass->CheckAddAttr("FEAT_CODE", "A4", 4); - } - break; - - default: - break; - } - } - - CSLDestroy(papszFullAttList); - } - - if (GetOption("CACHING") != nullptr && EQUAL(GetOption("CACHING"), "OFF")) - poReader->DestroyIndex(); - - poReader->Reset(); -} - -/************************************************************************/ -/* AddGenericAttributes() */ -/************************************************************************/ - -static void AddGenericAttributes(NTFFileReader *poReader, NTFRecord **papoGroup, - OGRFeature *poFeature) - -{ - char **papszTypes = nullptr; - char **papszValues = nullptr; - - if (!poReader->ProcessAttRecGroup(papoGroup, &papszTypes, &papszValues)) - return; - - for (int iAtt = 0; papszTypes != nullptr && papszTypes[iAtt] != nullptr; - iAtt++) - { - int iField = 0; - - if (EQUAL(papszTypes[iAtt], "TX")) - iField = poFeature->GetFieldIndex("TEXT"); - else if (EQUAL(papszTypes[iAtt], "FC")) - iField = poFeature->GetFieldIndex("FEAT_CODE"); - else - iField = poFeature->GetFieldIndex(papszTypes[iAtt]); - - if (iField == -1) - continue; - - poReader->ApplyAttributeValue(poFeature, iField, papszTypes[iAtt], - papszTypes, papszValues); - - /* -------------------------------------------------------------------- - */ - /* Do we have a corresponding list field we should be */ - /* accumulating this into? */ - /* -------------------------------------------------------------------- - */ - char szListName[128] = {}; - - snprintf(szListName, sizeof(szListName), "%s_LIST", - poFeature->GetFieldDefnRef(iField)->GetNameRef()); - const int iListField = poFeature->GetFieldIndex(szListName); - - /* -------------------------------------------------------------------- - */ - /* Yes, so perform processing similar to ApplyAttributeValue(), */ - /* and append to list value. */ - /* -------------------------------------------------------------------- - */ - if (iListField != -1) - { - const char *pszAttLongName = nullptr; - const char *pszAttValue = nullptr; - const char *pszCodeDesc = nullptr; - - poReader->ProcessAttValue(papszTypes[iAtt], papszValues[iAtt], - &pszAttLongName, &pszAttValue, - &pszCodeDesc); - - if (poFeature->IsFieldSetAndNotNull(iListField)) - { - poFeature->SetField( - iListField, - CPLSPrintf("%s,%s", poFeature->GetFieldAsString(iListField), - pszAttValue)); - } - else - { - poFeature->SetField(iListField, pszAttValue); - } - } - } - - CSLDestroy(papszTypes); - CSLDestroy(papszValues); -} - -/************************************************************************/ -/* TranslateGenericNode() */ -/************************************************************************/ - -static OGRFeature *TranslateGenericNode(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_NODEREC || - (papoGroup[1]->GetType() != NRT_GEOMETRY && - papoGroup[1]->GetType() != NRT_GEOMETRY3D)) - { - return nullptr; - } - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // NODE_ID - poFeature->SetField("NODE_ID", atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - poFeature->SetField("GEOM_ID", papoGroup[1]->GetField(3, 8)); - - // NUM_LINKS - int nLinkCount = 0; - if (papoGroup[0]->GetLength() > 18) - { - nLinkCount = atoi(papoGroup[0]->GetField(15, 18)); - if (nLinkCount > 0) - { - std::vector anLinks(nLinkCount); - - // GEOM_ID_OF_LINK - for (int iLink = 0; iLink < nLinkCount; iLink++) - anLinks[iLink] = atoi( - papoGroup[0]->GetField(20 + iLink * 12, 25 + iLink * 12)); - - poFeature->SetField("GEOM_ID_OF_LINK", nLinkCount, anLinks.data()); - - // DIR - for (int iLink = 0; iLink < nLinkCount; iLink++) - anLinks[iLink] = atoi( - papoGroup[0]->GetField(19 + iLink * 12, 19 + iLink * 12)); - - poFeature->SetField("DIR", nLinkCount, anLinks.data()); - } - } - - poFeature->SetField("NUM_LINKS", nLinkCount); - - // should we add LEVEL and/or ORIENT? - - return poFeature; -} - -/************************************************************************/ -/* TranslateGenericCollection() */ -/************************************************************************/ - -static OGRFeature *TranslateGenericCollection(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 1 || - papoGroup[0]->GetType() != NRT_COLLECT) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // COLL_ID - poFeature->SetField("COLL_ID", atoi(papoGroup[0]->GetField(3, 8))); - - // NUM_PARTS - int nPartCount = 0; - - if (papoGroup[0]->GetLength() >= 20) - { - nPartCount = atoi(papoGroup[0]->GetField(9, 12)); - if (nPartCount > 0 && - nPartCount - 1 <= (papoGroup[0]->GetLength() - 20) / 8) - { - std::vector anParts(nPartCount); - - // TYPE - for (int iPart = 0; iPart < nPartCount; iPart++) - anParts[iPart] = atoi( - papoGroup[0]->GetField(13 + iPart * 8, 14 + iPart * 8)); - - poFeature->SetField("TYPE", nPartCount, anParts.data()); - - // ID - for (int iPart = 0; iPart < nPartCount; iPart++) - anParts[iPart] = atoi( - papoGroup[0]->GetField(15 + iPart * 8, 20 + iPart * 8)); - - poFeature->SetField("ID", nPartCount, anParts.data()); - } - else - { - nPartCount = 0; - } - } - - poFeature->SetField("NUM_PARTS", nPartCount); - - // ATTREC Attributes - AddGenericAttributes(poReader, papoGroup, poFeature); - - return poFeature; -} - -/************************************************************************/ -/* TranslateGenericText() */ -/************************************************************************/ - -static OGRFeature *TranslateGenericText(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_TEXTREC) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // TEXT_ID - poFeature->SetField("TEXT_ID", atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - for (int iRec = 0; papoGroup[iRec] != nullptr; iRec++) - { - if (papoGroup[iRec]->GetType() == NRT_GEOMETRY || - papoGroup[iRec]->GetType() == NRT_GEOMETRY3D) - { - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[iRec])); - poFeature->SetField("GEOM_ID", papoGroup[iRec]->GetField(3, 8)); - break; - } - } - - // ATTREC Attributes - AddGenericAttributes(poReader, papoGroup, poFeature); - - // TEXTREP information - for (int iRec = 0; papoGroup[iRec] != nullptr; iRec++) - { - NTFRecord *poRecord = papoGroup[iRec]; - - if (poRecord->GetType() == NRT_TEXTREP) - { - poFeature->SetField("FONT", atoi(poRecord->GetField(9, 12))); - poFeature->SetField("TEXT_HT", - atoi(poRecord->GetField(13, 15)) * 0.1); - poFeature->SetField("TEXT_HT_GROUND", - atoi(poRecord->GetField(13, 15)) * 0.1 * - poReader->GetPaperToGround()); - poFeature->SetField("DIG_POSTN", atoi(poRecord->GetField(16, 16))); - poFeature->SetField("ORIENT", - atoi(poRecord->GetField(17, 20)) * 0.1); - break; - } - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateGenericName() */ -/************************************************************************/ - -static OGRFeature *TranslateGenericName(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_NAMEREC) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // NAME_ID - poFeature->SetField("NAME_ID", atoi(papoGroup[0]->GetField(3, 8))); - - // TEXT_CODE - poFeature->SetField("TEXT_CODE", papoGroup[0]->GetField(8, 12)); - - // TEXT - int nNumChar = atoi(papoGroup[0]->GetField(13, 14)); - - if (nNumChar > 0 && papoGroup[0]->GetLength() >= 15 + nNumChar - 1) - poFeature->SetField("TEXT", - papoGroup[0]->GetField(15, 15 + nNumChar - 1)); - - // Geometry - for (int iRec = 0; papoGroup[iRec] != nullptr; iRec++) - { - if (papoGroup[iRec]->GetType() == NRT_GEOMETRY || - papoGroup[iRec]->GetType() == NRT_GEOMETRY3D) - { - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[iRec])); - poFeature->SetField("GEOM_ID", papoGroup[iRec]->GetField(3, 8)); - break; - } - } - - // ATTREC Attributes - AddGenericAttributes(poReader, papoGroup, poFeature); - - // NAMEPOSTN information - for (int iRec = 0; papoGroup[iRec] != nullptr; iRec++) - { - NTFRecord *poRecord = papoGroup[iRec]; - - if (poRecord->GetType() == NRT_NAMEPOSTN) - { - poFeature->SetField("FONT", atoi(poRecord->GetField(3, 6))); - poFeature->SetField("TEXT_HT", - atoi(poRecord->GetField(7, 9)) * 0.1); - poFeature->SetField("TEXT_HT_GROUND", - atoi(poRecord->GetField(7, 9)) * 0.1 * - poReader->GetPaperToGround()); - poFeature->SetField("DIG_POSTN", atoi(poRecord->GetField(10, 10))); - poFeature->SetField("ORIENT", - atoi(poRecord->GetField(11, 14)) * 0.1); - break; - } - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateGenericPoint() */ -/************************************************************************/ - -static OGRFeature *TranslateGenericPoint(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_POINTREC || - (papoGroup[1]->GetType() != NRT_GEOMETRY && - papoGroup[1]->GetType() != NRT_GEOMETRY3D)) - { - return nullptr; - } - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POINT_ID - poFeature->SetField("POINT_ID", atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - poFeature->SetField("GEOM_ID", papoGroup[1]->GetField(3, 8)); - - // ATTREC Attributes - AddGenericAttributes(poReader, papoGroup, poFeature); - - // Handle singular attribute in pre-level 3 POINTREC. - if (poReader->GetNTFLevel() < 3) - { - char szValType[3]; - - snprintf(szValType, sizeof(szValType), "%s", - papoGroup[0]->GetField(9, 10)); - if (!EQUAL(szValType, " ")) - { - const char *pszProcessedValue = nullptr; - - if (poReader->ProcessAttValue(szValType, - papoGroup[0]->GetField(11, 16), - nullptr, &pszProcessedValue, nullptr)) - poFeature->SetField(szValType, pszProcessedValue); - } - - if (!EQUAL(papoGroup[0]->GetField(17, 20), " ")) - { - poFeature->SetField("FEAT_CODE", papoGroup[0]->GetField(17, 20)); - } - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateGenericLine() */ -/************************************************************************/ - -static OGRFeature *TranslateGenericLine(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - if (CSLCount((char **)papoGroup) < 2 || - papoGroup[0]->GetType() != NRT_LINEREC || - (papoGroup[1]->GetType() != NRT_GEOMETRY && - papoGroup[1]->GetType() != NRT_GEOMETRY3D)) - return nullptr; - - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // LINE_ID - poFeature->SetField("LINE_ID", atoi(papoGroup[0]->GetField(3, 8))); - - // Geometry - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - poFeature->SetField("GEOM_ID", papoGroup[1]->GetField(3, 8)); - - // ATTREC Attributes - AddGenericAttributes(poReader, papoGroup, poFeature); - - // Handle singular attribute in pre-level 3 LINEREC. - if (poReader->GetNTFLevel() < 3) - { - char szValType[3] = {}; - - snprintf(szValType, sizeof(szValType), "%s", - papoGroup[0]->GetField(9, 10)); - if (!EQUAL(szValType, " ")) - { - const char *pszProcessedValue = nullptr; - - if (poReader->ProcessAttValue(szValType, - papoGroup[0]->GetField(11, 16), - nullptr, &pszProcessedValue, nullptr)) - poFeature->SetField(szValType, pszProcessedValue); - } - - if (!EQUAL(papoGroup[0]->GetField(17, 20), " ")) - { - poFeature->SetField("FEAT_CODE", papoGroup[0]->GetField(17, 20)); - } - } - - return poFeature; -} - -/************************************************************************/ -/* TranslateGenericPoly() */ -/************************************************************************/ - -static OGRFeature *TranslateGenericPoly(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - /* ==================================================================== */ - /* Traditional POLYGON record groups. */ - /* ==================================================================== */ - if (CSLCount((char **)papoGroup) >= 2 && - papoGroup[0]->GetType() == NRT_POLYGON && - papoGroup[1]->GetType() == NRT_CHAIN) - { - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // POLY_ID - poFeature->SetField(0, atoi(papoGroup[0]->GetField(3, 8))); - - // NUM_PARTS - int nNumLinks = atoi(papoGroup[1]->GetField(9, 12)); - - if (nNumLinks < 0 || nNumLinks > MAX_LINK) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_generic.cpp."); - return poFeature; - } - - poFeature->SetField("NUM_PARTS", nNumLinks); - - // DIR - int i, anList[MAX_LINK] = {0}; - - for (i = 0; i < nNumLinks; i++) - anList[i] = atoi(papoGroup[1]->GetField(19 + i * 7, 19 + i * 7)); - - poFeature->SetField("DIR", nNumLinks, anList); - - // GEOM_ID_OF_LINK - for (i = 0; i < nNumLinks; i++) - anList[i] = atoi(papoGroup[1]->GetField(13 + i * 7, 18 + i * 7)); - - poFeature->SetField("GEOM_ID_OF_LINK", nNumLinks, anList); - - // RingStart - int nRingList = 0; - poFeature->SetField("RingStart", 1, &nRingList); - - // ATTREC Attributes - AddGenericAttributes(poReader, papoGroup, poFeature); - - // Read point geometry - if (papoGroup[2] != nullptr && - (papoGroup[2]->GetType() == NRT_GEOMETRY || - papoGroup[2]->GetType() == NRT_GEOMETRY3D)) - { - poFeature->SetGeometryDirectly( - poReader->ProcessGeometry(papoGroup[2])); - poFeature->SetField("GEOM_ID", papoGroup[2]->GetField(3, 8)); - } - - return poFeature; - } - - return nullptr; -} - -/************************************************************************/ -/* TranslateGenericCPoly() */ -/************************************************************************/ - -static OGRFeature *TranslateGenericCPoly(NTFFileReader *poReader, - OGRNTFLayer *poLayer, - NTFRecord **papoGroup) - -{ - /* -------------------------------------------------------------------- */ - /* First we do validation of the grouping. */ - /* -------------------------------------------------------------------- */ - if (papoGroup[0]->GetType() != NRT_CPOLY) - return nullptr; - - if (papoGroup[1] == nullptr || (papoGroup[1]->GetType() != NRT_GEOMETRY && - papoGroup[1]->GetType() != NRT_GEOMETRY3D)) - return nullptr; - - if (papoGroup[2] != nullptr && papoGroup[2]->GetType() != NRT_ATTREC) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* collect information for whole complex polygon. */ - /* -------------------------------------------------------------------- */ - OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn()); - - // CPOLY_ID - poFeature->SetField("CPOLY_ID", atoi(papoGroup[0]->GetField(3, 8))); - - // ATTREC Attributes - AddGenericAttributes(poReader, papoGroup, poFeature); - - // Read point geometry - if (papoGroup[1] != nullptr && (papoGroup[1]->GetType() == NRT_GEOMETRY || - papoGroup[1]->GetType() == NRT_GEOMETRY3D)) - { - poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1])); - poFeature->SetField("GEOM_ID", atoi(papoGroup[1]->GetField(3, 8))); - } - - /* -------------------------------------------------------------------- */ - /* Collect the chains for each of the rings, and just aggregate */ - /* these into the master list without any concept of where the */ - /* boundaries are. The boundary information will be emitted */ - /* in the RingStart field. */ - /* -------------------------------------------------------------------- */ - int nNumLink = 0; - int anPolyId[MAX_LINK * 2] = {0}; - - nNumLink = atoi(papoGroup[0]->GetField(9, 12)); - if (nNumLink < 0 || nNumLink > MAX_LINK) - { - CPLError(CE_Failure, CPLE_AppDefined, - "MAX_LINK exceeded in ntf_generic.cpp."); - return poFeature; - } - - for (int iLink = 0; iLink < nNumLink; iLink++) - { - anPolyId[iLink] = - atoi(papoGroup[0]->GetField(13 + iLink * 7, 18 + iLink * 7)); - } - - // NUM_PARTS - poFeature->SetField("NUM_PARTS", nNumLink); - - // POLY_ID - poFeature->SetField("POLY_ID", nNumLink, anPolyId); - - return poFeature; -} - -/************************************************************************/ -/* EstablishGenericLayers() */ -/************************************************************************/ - -void OGRNTFDataSource::EstablishGenericLayers() - -{ - /* -------------------------------------------------------------------- */ - /* Pick an initial NTFFileReader to build the layers against. */ - /* -------------------------------------------------------------------- */ - for (int iFile = 0; iFile < nNTFFileCount; iFile++) - { - int bHasZ = FALSE; - - NTFFileReader *poPReader = papoNTFFileReader[iFile]; - if (poPReader->GetProductId() != NPC_UNKNOWN) - continue; - - /* -------------------------------------------------------------------- - */ - /* If any of the generic classes are 3D, then assume all our */ - /* geometry should be marked as 3D. */ - /* -------------------------------------------------------------------- - */ - for (int iType = 0; iType < 99; iType++) - { - NTFGenericClass *poClass = aoGenericClass + iType; - - if (poClass->nFeatureCount > 0 && poClass->b3D) - bHasZ = TRUE; - } - - /* -------------------------------------------------------------------- - */ - /* Create layers for all recognised layer types with features. */ - /* -------------------------------------------------------------------- - */ - for (int iType = 0; iType < 99; iType++) - { - NTFGenericClass *poClass = aoGenericClass + iType; - - if (poClass->nFeatureCount == 0) - continue; - - if (iType == NRT_POINTREC) - { - poPReader->EstablishLayer( - "GENERIC_POINT", OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE), - TranslateGenericPoint, NRT_POINTREC, poClass, "POINT_ID", - OFTInteger, 6, 0, NULL); - } - else if (iType == NRT_LINEREC) - { - poPReader->EstablishLayer( - "GENERIC_LINE", - OGR_GT_SetModifier(wkbLineString, bHasZ, FALSE), - TranslateGenericLine, NRT_LINEREC, poClass, "LINE_ID", - OFTInteger, 6, 0, NULL); - } - else if (iType == NRT_TEXTREC) - { - poPReader->EstablishLayer( - "GENERIC_TEXT", OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE), - TranslateGenericText, NRT_TEXTREC, poClass, "TEXT_ID", - OFTInteger, 6, 0, NULL); - } - else if (iType == NRT_NAMEREC) - { - poPReader->EstablishLayer( - "GENERIC_NAME", OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE), - TranslateGenericName, NRT_NAMEREC, poClass, "NAME_ID", - OFTInteger, 6, 0, NULL); - } - else if (iType == NRT_NODEREC) - { - poPReader->EstablishLayer( - "GENERIC_NODE", OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE), - TranslateGenericNode, NRT_NODEREC, poClass, "NODE_ID", - OFTInteger, 6, 0, "NUM_LINKS", OFTInteger, 4, 0, - "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0, "DIR", - OFTIntegerList, 1, 0, NULL); - } - else if (iType == NRT_COLLECT) - { - poPReader->EstablishLayer( - "GENERIC_COLLECTION", wkbNone, TranslateGenericCollection, - NRT_COLLECT, poClass, "COLL_ID", OFTInteger, 6, 0, - "NUM_PARTS", OFTInteger, 4, 0, "TYPE", OFTIntegerList, 2, 0, - "ID", OFTIntegerList, 6, 0, NULL); - } - else if (iType == NRT_POLYGON) - { - poPReader->EstablishLayer( - "GENERIC_POLY", OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE), - TranslateGenericPoly, NRT_POLYGON, poClass, "POLY_ID", - OFTInteger, 6, 0, "NUM_PARTS", OFTInteger, 4, 0, "DIR", - OFTIntegerList, 1, 0, "GEOM_ID_OF_LINK", OFTIntegerList, 6, - 0, "RingStart", OFTIntegerList, 6, 0, NULL); - } - else if (iType == NRT_CPOLY) - { - poPReader->EstablishLayer( - "GENERIC_CPOLY", OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE), - TranslateGenericCPoly, NRT_CPOLY, poClass, "CPOLY_ID", - OFTInteger, 6, 0, "NUM_PARTS", OFTInteger, 4, 0, "POLY_ID", - OFTIntegerList, 1, 0, NULL); - } - } - } -} diff --git a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp deleted file mode 100644 index 77e498977d52..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: Handle UK Ordnance Survey Raster DTM products. Includes some - * raster related methods from NTFFileReader and the implementation - * of OGRNTFRasterLayer. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ntf.h" - -#include - -/************************************************************************/ -/* ==================================================================== */ -/* NTFFileReader Raster Methods */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* IsRasterProduct() */ -/************************************************************************/ - -int NTFFileReader::IsRasterProduct() - -{ - return GetProductId() == NPC_LANDRANGER_DTM || - GetProductId() == NPC_LANDFORM_PROFILE_DTM; -} - -/************************************************************************/ -/* EstablishRasterAccess() */ -/************************************************************************/ - -void NTFFileReader::EstablishRasterAccess() - -{ - /* -------------------------------------------------------------------- */ - /* Read the type 50 record. */ - /* -------------------------------------------------------------------- */ - NTFRecord *poRecord = nullptr; - - while ((poRecord = ReadRecord()) != nullptr && - poRecord->GetType() != NRT_GRIDHREC && - poRecord->GetType() != NRT_VTR) - { - delete poRecord; - } - - if (poRecord == nullptr || poRecord->GetType() != NRT_GRIDHREC) - { - delete poRecord; - CPLError(CE_Failure, CPLE_AppDefined, - "Unable to find GRIDHREC (type 50) record in what appears\n" - "to be an NTF Raster DTM product."); - return; - } - - /* -------------------------------------------------------------------- */ - /* Parse if LANDRANGER_DTM */ - /* -------------------------------------------------------------------- */ - if (GetProductId() == NPC_LANDRANGER_DTM) - { - nRasterXSize = atoi(poRecord->GetField(13, 16)); - nRasterYSize = atoi(poRecord->GetField(17, 20)); - - // NOTE: unusual use of GeoTransform - the pixel origin is the - // bottom left corner! - adfGeoTransform[0] = atoi(poRecord->GetField(25, 34)); - adfGeoTransform[1] = 50; - adfGeoTransform[2] = 0; - adfGeoTransform[3] = atoi(poRecord->GetField(35, 44)); - adfGeoTransform[4] = 0; - adfGeoTransform[5] = 50; - - nRasterDataType = 3; /* GDT_Int16 */ - } - - /* -------------------------------------------------------------------- */ - /* Parse if LANDFORM_PROFILE_DTM */ - /* -------------------------------------------------------------------- */ - else if (GetProductId() == NPC_LANDFORM_PROFILE_DTM) - { - nRasterXSize = atoi(poRecord->GetField(23, 30)); - nRasterYSize = atoi(poRecord->GetField(31, 38)); - - // NOTE: unusual use of GeoTransform - the pixel origin is the - // bottom left corner! - adfGeoTransform[0] = atoi(poRecord->GetField(13, 17)) + GetXOrigin(); - adfGeoTransform[1] = atoi(poRecord->GetField(39, 42)); - adfGeoTransform[2] = 0; - adfGeoTransform[3] = atoi(poRecord->GetField(18, 22)) + GetYOrigin(); - adfGeoTransform[4] = 0; - adfGeoTransform[5] = atoi(poRecord->GetField(43, 46)); - - nRasterDataType = 3; /* GDT_Int16 */ - } - - /* -------------------------------------------------------------------- */ - /* Initialize column offsets table. */ - /* -------------------------------------------------------------------- */ - delete poRecord; - - if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize)) - return; - - panColumnOffset = static_cast( - CPLCalloc(sizeof(vsi_l_offset), nRasterXSize)); - - GetFPPos(panColumnOffset + 0, nullptr); - - /* -------------------------------------------------------------------- */ - /* Create an OGRSFLayer for this file readers raster points. */ - /* -------------------------------------------------------------------- */ - if (poDS != nullptr) - { - poRasterLayer = new OGRNTFRasterLayer(poDS, this); - poDS->AddLayer(poRasterLayer); - } -} - -/************************************************************************/ -/* ReadRasterColumn() */ -/************************************************************************/ - -CPLErr NTFFileReader::ReadRasterColumn(int iColumn, float *pafElev) - -{ - /* -------------------------------------------------------------------- */ - /* If we don't already have the scanline offset of the previous */ - /* line, force reading of previous records to establish it. */ - /* -------------------------------------------------------------------- */ - if (panColumnOffset[iColumn] == 0) - { - for (int iPrev = 0; iPrev < iColumn - 1; iPrev++) - { - if (panColumnOffset[iPrev + 1] == 0) - { - CPLErr eErr; - - eErr = ReadRasterColumn(iPrev, nullptr); - if (eErr != CE_None) - return eErr; - } - } - } - - /* -------------------------------------------------------------------- */ - /* If the dataset isn't open, open it now. */ - /* -------------------------------------------------------------------- */ - if (GetFP() == nullptr) - Open(); - - /* -------------------------------------------------------------------- */ - /* Read requested record. */ - /* -------------------------------------------------------------------- */ - SetFPPos(panColumnOffset[iColumn], iColumn); - NTFRecord *poRecord = ReadRecord(); - if (poRecord == nullptr) - return CE_Failure; - - CPLErr eErr = CE_None; - if (iColumn < nRasterXSize - 1) - { - GetFPPos(panColumnOffset + iColumn + 1, nullptr); - } - - /* -------------------------------------------------------------------- */ - /* Handle LANDRANGER DTM columns. */ - /* -------------------------------------------------------------------- */ - if (pafElev != nullptr && GetProductId() == NPC_LANDRANGER_DTM) - { - const double dfVOffset = atoi(poRecord->GetField(56, 65)); - const double dfVScale = atoi(poRecord->GetField(66, 75)) * 0.001; - - for (int iPixel = 0; iPixel < nRasterYSize; iPixel++) - { - const char *pszValue = - poRecord->GetField(84 + iPixel * 4, 87 + iPixel * 4); - if (pszValue[0] == '\0' || pszValue[0] == ' ') - { - eErr = CE_Failure; - break; - } - pafElev[iPixel] = (float)(dfVOffset + dfVScale * atoi(pszValue)); - } - } - - /* -------------------------------------------------------------------- */ - /* Handle PROFILE */ - /* -------------------------------------------------------------------- */ - else if (pafElev != nullptr && GetProductId() == NPC_LANDFORM_PROFILE_DTM) - { - for (int iPixel = 0; iPixel < nRasterYSize; iPixel++) - { - const char *pszValue = - poRecord->GetField(19 + iPixel * 5, 23 + iPixel * 5); - if (pszValue[0] == '\0' || pszValue[0] == ' ') - { - eErr = CE_Failure; - break; - } - pafElev[iPixel] = (float)(atoi(pszValue) * GetZMult()); - } - } - - delete poRecord; - - return eErr; -} - -/************************************************************************/ -/* ==================================================================== */ -/* OGRNTFRasterLayer */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* OGRNTFRasterLayer */ -/************************************************************************/ - -OGRNTFRasterLayer::OGRNTFRasterLayer(OGRNTFDataSource *poDSIn, - NTFFileReader *poReaderIn) - : poFeatureDefn(nullptr), poFilterGeom(nullptr), poReader(poReaderIn), - pafColumn(static_cast( - CPLCalloc(sizeof(float), poReaderIn->GetRasterYSize()))), - iColumnOffset(-1), iCurrentFC(1), - // Check for DEM subsampling. - nDEMSample(poDSIn->GetOption("DEM_SAMPLE") == nullptr - ? 1 - : std::max(1, atoi(poDSIn->GetOption("DEM_SAMPLE")))), - nFeatureCount(0) -{ - char szLayerName[128]; - snprintf(szLayerName, sizeof(szLayerName), "DTM_%s", - poReaderIn->GetTileName()); - poFeatureDefn = new OGRFeatureDefn(szLayerName); - - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbPoint25D); - poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( - poDSIn->DSGetSpatialRef()); - - OGRFieldDefn oHeight("HEIGHT", OFTReal); - poFeatureDefn->AddFieldDefn(&oHeight); - - nFeatureCount = - static_cast(poReader->GetRasterXSize() / nDEMSample) * - (poReader->GetRasterYSize() / nDEMSample); -} - -/************************************************************************/ -/* ~OGRNTFRasterLayer() */ -/************************************************************************/ - -OGRNTFRasterLayer::~OGRNTFRasterLayer() - -{ - CPLFree(pafColumn); - if (poFeatureDefn) - poFeatureDefn->Release(); - - if (poFilterGeom != nullptr) - delete poFilterGeom; -} - -/************************************************************************/ -/* SetSpatialFilter() */ -/************************************************************************/ - -void OGRNTFRasterLayer::SetSpatialFilter(OGRGeometry *poGeomIn) - -{ - if (poFilterGeom != nullptr) - { - delete poFilterGeom; - poFilterGeom = nullptr; - } - - if (poGeomIn != nullptr) - poFilterGeom = poGeomIn->clone(); -} - -/************************************************************************/ -/* ResetReading() */ -/************************************************************************/ - -void OGRNTFRasterLayer::ResetReading() - -{ - iCurrentFC = 1; -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -OGRFeature *OGRNTFRasterLayer::GetNextFeature() - -{ - if (iCurrentFC > static_cast(poReader->GetRasterXSize()) * - poReader->GetRasterYSize()) - { - return nullptr; - } - - OGRFeature *poFeature = GetFeature(iCurrentFC); - - int iReqColumn, iReqRow; - - iReqColumn = - static_cast((iCurrentFC - 1) / poReader->GetRasterYSize()); - iReqRow = static_cast( - iCurrentFC - - static_cast(iReqColumn) * poReader->GetRasterYSize() - 1); - - if (iReqRow + nDEMSample > poReader->GetRasterYSize()) - { - iReqRow = 0; - iReqColumn += nDEMSample; - } - else - { - iReqRow += nDEMSample; - } - - iCurrentFC = static_cast(iReqColumn) * poReader->GetRasterYSize() + - iReqRow + 1; - - return poFeature; -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ - -OGRFeature *OGRNTFRasterLayer::GetFeature(GIntBig nFeatureId) - -{ - int iReqColumn, iReqRow; - - /* -------------------------------------------------------------------- */ - /* Is this in the range of legal feature ids (pixels)? */ - /* -------------------------------------------------------------------- */ - if (nFeatureId < 1 || - nFeatureId > static_cast(poReader->GetRasterXSize()) * - poReader->GetRasterYSize()) - { - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Do we need to load a different column. */ - /* -------------------------------------------------------------------- */ - iReqColumn = - static_cast((nFeatureId - 1) / poReader->GetRasterYSize()); - iReqRow = static_cast( - nFeatureId - - static_cast(iReqColumn) * poReader->GetRasterYSize() - 1); - - if (iReqColumn != iColumnOffset) - { - iColumnOffset = iReqColumn; - if (poReader->ReadRasterColumn(iReqColumn, pafColumn) != CE_None) - return nullptr; - } - if (iReqRow < 0 || iReqRow >= poReader->GetRasterYSize()) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Create a corresponding feature. */ - /* -------------------------------------------------------------------- */ - OGRFeature *poFeature = new OGRFeature(poFeatureDefn); - double *padfGeoTransform = poReader->GetGeoTransform(); - - poFeature->SetFID(nFeatureId); - - // NOTE: unusual use of GeoTransform - the pixel origin is the - // bottom left corner! - poFeature->SetGeometryDirectly( - new OGRPoint(padfGeoTransform[0] + padfGeoTransform[1] * iReqColumn, - padfGeoTransform[3] + padfGeoTransform[5] * iReqRow, - pafColumn[iReqRow])); - poFeature->SetField(0, pafColumn[iReqRow]); - - return poFeature; -} - -/************************************************************************/ -/* GetFeatureCount() */ -/* */ -/* If a spatial filter is in effect, we turn control over to */ -/* the generic counter. Otherwise we return the total count. */ -/* Eventually we should consider implementing a more efficient */ -/* way of counting features matching a spatial query. */ -/************************************************************************/ - -GIntBig OGRNTFRasterLayer::GetFeatureCount(CPL_UNUSED int bForce) -{ - return nFeatureCount; -} - -/************************************************************************/ -/* TestCapability() */ -/************************************************************************/ - -int OGRNTFRasterLayer::TestCapability(const char *pszCap) - -{ - if (EQUAL(pszCap, OLCRandomRead)) - return TRUE; - - else if (EQUAL(pszCap, OLCFastFeatureCount)) - return TRUE; - - return FALSE; -} diff --git a/ogr/ogrsf_frmts/ntf/ntfdump.cpp b/ogr/ogrsf_frmts/ntf/ntfdump.cpp deleted file mode 100644 index e833dfc58439..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntfdump.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: Simple test harness. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ntf.h" -#include "cpl_vsi.h" -#include "cpl_string.h" - -static void NTFDump(const char *pszFile, char **papszOptions); -static void NTFCount(const char *pszFile); - -/************************************************************************/ -/* main() */ -/************************************************************************/ - -int main(int argc, char **argv) - -{ - const char *pszMode = "-d"; - char **papszOptions = NULL; - - if (argc == 1) - printf("Usage: ntfdump [-s n] [-g] [-d] [-c] [-codelist] files\n"); - - for (int i = 1; i < argc; i++) - { - if (EQUAL(argv[i], "-g")) - papszOptions = CSLSetNameValue(papszOptions, "FORCE_GENERIC", "ON"); - else if (EQUAL(argv[i], "-s")) - { - papszOptions = - CSLSetNameValue(papszOptions, "DEM_SAMPLE", argv[++i]); - } - else if (EQUAL(argv[i], "-codelist")) - { - papszOptions = CSLSetNameValue(papszOptions, "CODELIST", "ON"); - } - else if (argv[i][0] == '-') - pszMode = argv[i]; - else if (EQUAL(pszMode, "-d")) - NTFDump(argv[i], papszOptions); - else if (EQUAL(pszMode, "-c")) - NTFCount(argv[i]); - } - - return 0; -} - -/************************************************************************/ -/* NTFCount() */ -/************************************************************************/ - -static void NTFCount(const char *pszFile) - -{ - FILE *fp = VSIFOpen(pszFile, "r"); - if (fp == NULL) - return; - - int anCount[100] = {}; - - NTFRecord *poRecord = NULL; - do - { - if (poRecord != NULL) - delete poRecord; - - poRecord = new NTFRecord(fp); - anCount[poRecord->GetType()]++; - } while (poRecord->GetType() != 99); - - VSIFClose(fp); - - printf("\nReporting on: %s\n", pszFile); - for (int i = 0; i < 100; i++) - { - if (anCount[i] > 0) - printf("Found %d records of type %d\n", anCount[i], i); - } -} - -/************************************************************************/ -/* NTFDump() */ -/************************************************************************/ - -static void NTFDump(const char *pszFile, char **papszOptions) - -{ - OGRNTFDataSource oDS; - - oDS.SetOptionList(papszOptions); - - if (!oDS.Open(pszFile)) - return; - - OGRFeature *poFeature = NULL; - while ((poFeature = oDS.GetNextFeature()) != NULL) - { - printf("-------------------------------------\n"); - poFeature->DumpReadable(stdout); - delete poFeature; - } -} diff --git a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp deleted file mode 100644 index f4fe811d76d4..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp +++ /dev/null @@ -1,2168 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: NTFFileReader class implementation. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include -#include "ntf.h" -#include "cpl_conv.h" -#include "cpl_string.h" -#include "ogr_api.h" - -#include - -#define DIGIT_ZERO '0' - -static int DefaultNTFRecordGrouper(NTFFileReader *, NTFRecord **, NTFRecord *); - -/************************************************************************/ -/* NTFFileReader */ -/************************************************************************/ - -NTFFileReader::NTFFileReader(OGRNTFDataSource *poDataSource) - : pszFilename(nullptr), poDS(poDataSource), fp(nullptr), nFCCount(0), - papszFCNum(nullptr), papszFCName(nullptr), nAttCount(0), - pasAttDesc(nullptr), pszTileName(nullptr), nCoordWidth(6), nZWidth(6), - nNTFLevel(0), dfXYMult(1.0), dfZMult(1.0), dfXOrigin(0), dfYOrigin(0), - dfTileXSize(0), dfTileYSize(0), dfScale(0.0), dfPaperToGround(0.0), - nStartPos(0), nPreSavedPos(0), nPostSavedPos(0), poSavedRecord(nullptr), - nSavedFeatureId(1), nBaseFeatureId(1), nFeatureCount(-1), - pszProduct(nullptr), pszPVName(nullptr), nProduct(NPC_UNKNOWN), - pfnRecordGrouper(DefaultNTFRecordGrouper), bIndexBuilt(FALSE), - bIndexNeeded(FALSE), nRasterXSize(1), nRasterYSize(1), nRasterDataType(1), - poRasterLayer(nullptr), panColumnOffset(nullptr), bCacheLines(TRUE), - nLineCacheSize(0), papoLineCache(nullptr) -{ - apoCGroup[0] = nullptr; - apoCGroup[1] = nullptr; - apoCGroup[MAX_REC_GROUP] = nullptr; - memset(adfGeoTransform, 0, sizeof(adfGeoTransform)); - memset(apoTypeTranslation, 0, sizeof(apoTypeTranslation)); - for (int i = 0; i < 100; i++) - { - anIndexSize[i] = 0; - apapoRecordIndex[i] = nullptr; - } - if (poDS->GetOption("CACHE_LINES") != nullptr && - EQUAL(poDS->GetOption("CACHE_LINES"), "OFF")) - bCacheLines = FALSE; -} - -/************************************************************************/ -/* ~NTFFileReader() */ -/************************************************************************/ - -NTFFileReader::~NTFFileReader() - -{ - CacheClean(); - DestroyIndex(); - ClearDefs(); - CPLFree(pszFilename); - CPLFree(panColumnOffset); -} - -/************************************************************************/ -/* SetBaseFID() */ -/************************************************************************/ - -void NTFFileReader::SetBaseFID(long nNewBase) - -{ - CPLAssert(nSavedFeatureId == 1); - - nBaseFeatureId = nNewBase; - nSavedFeatureId = nBaseFeatureId; -} - -/************************************************************************/ -/* ClearDefs() */ -/* */ -/* Clear attribute definitions and feature classes. All the */ -/* stuff that would have to be cleaned up by Open(), and the */ -/* destructor. */ -/************************************************************************/ - -void NTFFileReader::ClearDefs() - -{ - Close(); - - ClearCGroup(); - - CSLDestroy(papszFCNum); - papszFCNum = nullptr; - CSLDestroy(papszFCName); - papszFCName = nullptr; - nFCCount = 0; - - for (int i = 0; i < nAttCount; i++) - { - if (pasAttDesc[i].poCodeList != nullptr) - delete pasAttDesc[i].poCodeList; - } - - CPLFree(pasAttDesc); - nAttCount = 0; - pasAttDesc = nullptr; - - CPLFree(pszProduct); - pszProduct = nullptr; - - CPLFree(pszPVName); - pszPVName = nullptr; - - CPLFree(pszTileName); - pszTileName = nullptr; -} - -/************************************************************************/ -/* Close() */ -/* */ -/* Close the file, but don't wipe out our knowledge about this */ -/* file. */ -/************************************************************************/ - -void NTFFileReader::Close() - -{ - if (poSavedRecord != nullptr) - delete poSavedRecord; - poSavedRecord = nullptr; - - nPreSavedPos = nPostSavedPos = 0; - nSavedFeatureId = nBaseFeatureId; - if (fp != nullptr) - { - VSIFCloseL(fp); - fp = nullptr; - } - - CacheClean(); -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -int NTFFileReader::Open(const char *pszFilenameIn) - -{ - if (pszFilenameIn != nullptr) - { - ClearDefs(); - - CPLFree(pszFilename); - pszFilename = CPLStrdup(pszFilenameIn); - } - else - Close(); - - /* -------------------------------------------------------------------- */ - /* Open the file. */ - /* -------------------------------------------------------------------- */ - fp = VSIFOpenL(pszFilename, "rb"); - - // notdef: we should likely issue a proper CPL error message based - // based on errno here. - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Unable to open file `%s' for read access.\n", pszFilename); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* If we are just reopening an existing file we will just scan */ - /* past the section header ... no need to reform all the definitions.*/ - /* -------------------------------------------------------------------- */ - if (pszFilenameIn == nullptr) - { - NTFRecord *poRecord = nullptr; - - for (poRecord = new NTFRecord(fp); - poRecord->GetType() != NRT_VTR && poRecord->GetType() != NRT_SHR; - poRecord = new NTFRecord(fp)) - { - delete poRecord; - } - - delete poRecord; - - return TRUE; - } - - /* -------------------------------------------------------------------- */ - /* Read the first record, and verify it is a proper volume header. */ - /* -------------------------------------------------------------------- */ - NTFRecord oVHR(fp); - - if (oVHR.GetType() != NRT_VHR) - { - CPLError(CE_Failure, CPLE_AppDefined, - "File `%s' appears to not be a UK NTF file.\n", pszFilename); - return FALSE; - } - - nNTFLevel = atoi(oVHR.GetField(57, 57)); - if (!(nNTFLevel >= 1 && nNTFLevel <= 5)) - { - CPLError(CE_Failure, CPLE_AppDefined, "Invalid value : nNTFLevel = %d", - nNTFLevel); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Read records till we get the section header. */ - /* -------------------------------------------------------------------- */ - NTFRecord *poRecord = nullptr; - - for (poRecord = new NTFRecord(fp); - poRecord->GetType() != NRT_VTR && poRecord->GetType() != NRT_SHR; - poRecord = new NTFRecord(fp)) - { - /* -------------------------------------------------------------------- - */ - /* Handle feature class name records. */ - /* -------------------------------------------------------------------- - */ - if (poRecord->GetType() == NRT_FCR && poRecord->GetLength() >= 37) - { - nFCCount++; - - papszFCNum = CSLAddString(papszFCNum, poRecord->GetField(3, 6)); - - CPLString osFCName; - const char *pszData = poRecord->GetData(); - - // CODE_COM - int iChar = 15; - for (; pszData[iChar] == ' ' && iChar > 5; iChar--) - { - } - - if (iChar > 6) - osFCName += poRecord->GetField(7, iChar + 1); - - // STCLASS - for (iChar = 35; pszData[iChar] == ' ' && iChar > 15; iChar--) - { - } - - if (iChar > 15) - { - if (!osFCName.empty()) - osFCName += " : "; - osFCName += poRecord->GetField(17, iChar + 1); - } - - // FEATDES - for (iChar = 36; pszData[iChar] != '\0' && pszData[iChar] != '\\'; - iChar++) - { - } - - if (iChar > 37) - { - if (!osFCName.empty()) - osFCName += " : "; - osFCName += poRecord->GetField(37, iChar); - } - - papszFCName = CSLAddString(papszFCName, osFCName); - } - - /* -------------------------------------------------------------------- - */ - /* Handle attribute description records. */ - /* -------------------------------------------------------------------- - */ - else if (poRecord->GetType() == NRT_ADR) - { - nAttCount++; - - pasAttDesc = static_cast( - CPLRealloc(pasAttDesc, sizeof(NTFAttDesc) * nAttCount)); - memset(&pasAttDesc[nAttCount - 1], 0, sizeof(NTFAttDesc)); - - if (!ProcessAttDesc(poRecord, pasAttDesc + nAttCount - 1)) - nAttCount--; - } - - /* -------------------------------------------------------------------- - */ - /* Handle attribute description records. */ - /* -------------------------------------------------------------------- - */ - else if (poRecord->GetType() == NRT_CODELIST) - { - NTFCodeList *poCodeList = new NTFCodeList(poRecord); - NTFAttDesc *psAttDesc = GetAttDesc(poCodeList->szValType); - if (psAttDesc == nullptr) - { - CPLDebug("NTF", "Got CODELIST for %s without ATTDESC.", - poCodeList->szValType); - delete poCodeList; - } - else if (psAttDesc->poCodeList != nullptr) - { - // Should not happen on sane files. - delete poCodeList; - } - else - { - psAttDesc->poCodeList = poCodeList; - } - } - - /* -------------------------------------------------------------------- - */ - /* Handle database header record. */ - /* -------------------------------------------------------------------- - */ - else if (poRecord->GetType() == NRT_DHR && pszProduct == nullptr) - { - pszProduct = CPLStrdup(poRecord->GetField(3, 22)); - for (int iChar = static_cast(strlen(pszProduct)) - 1; - iChar > 0 && pszProduct[iChar] == ' '; - pszProduct[iChar--] = '\0') - { - } - - pszPVName = CPLStrdup(poRecord->GetField(76 + 3, 76 + 22)); - for (int iChar = static_cast(strlen(pszPVName)) - 1; - iChar > 0 && pszPVName[iChar] == ' '; - pszPVName[iChar--] = '\0') - { - } - } - - delete poRecord; - } - - /* -------------------------------------------------------------------- */ - /* Did we fall off the end without finding what we were looking */ - /* for? */ - /* -------------------------------------------------------------------- */ - if (poRecord->GetType() == NRT_VTR) - { - delete poRecord; - CPLError(CE_Failure, CPLE_AppDefined, - "Could not find section header record in %s.\n", pszFilename); - return FALSE; - } - - if (pszProduct == nullptr) - { - delete poRecord; - CPLError(CE_Failure, CPLE_AppDefined, - "Could not find product type in %s.\n", pszFilename); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Classify the product type. */ - /* -------------------------------------------------------------------- */ - if (STARTS_WITH_CI(pszProduct, "LAND-LINE") && strlen(pszPVName) > 5 && - CPLAtof(pszPVName + 5) < 1.3) - nProduct = NPC_LANDLINE; - else if (STARTS_WITH_CI(pszProduct, "LAND-LINE")) - nProduct = NPC_LANDLINE99; - else if (EQUAL(pszProduct, "OS_LANDRANGER_CONT")) // Panorama - nProduct = NPC_LANDRANGER_CONT; - else if (EQUAL(pszProduct, "L-F_PROFILE_CON")) // Panorama - nProduct = NPC_LANDFORM_PROFILE_CONT; - else if (STARTS_WITH_CI(pszProduct, "Strategi")) - nProduct = NPC_STRATEGI; - else if (STARTS_WITH_CI(pszProduct, "Meridian_02")) - nProduct = NPC_MERIDIAN2; - else if (STARTS_WITH_CI(pszProduct, "Meridian_01")) - nProduct = NPC_MERIDIAN; - else if (EQUAL(pszProduct, NTF_BOUNDARYLINE) && - STARTS_WITH_CI(pszPVName, "A10N_FC")) - nProduct = NPC_BOUNDARYLINE; - else if (EQUAL(pszProduct, NTF_BOUNDARYLINE) && - STARTS_WITH_CI(pszPVName, "A20N_FC")) - nProduct = NPC_BL2000; - else if (STARTS_WITH_CI(pszProduct, "BaseData.GB")) - nProduct = NPC_BASEDATA; - else if (STARTS_WITH_CI(pszProduct, "OSCAR_ASSET")) - nProduct = NPC_OSCAR_ASSET; - else if (STARTS_WITH_CI(pszProduct, "OSCAR_TRAFF")) - nProduct = NPC_OSCAR_TRAFFIC; - else if (STARTS_WITH_CI(pszProduct, "OSCAR_ROUTE")) - nProduct = NPC_OSCAR_ROUTE; - else if (STARTS_WITH_CI(pszProduct, "OSCAR_NETWO")) - nProduct = NPC_OSCAR_NETWORK; - else if (STARTS_WITH_CI(pszProduct, "ADDRESS_POI")) - nProduct = NPC_ADDRESS_POINT; - else if (STARTS_WITH_CI(pszProduct, "CODE_POINT")) - { - if (GetAttDesc("RH") == nullptr) - nProduct = NPC_CODE_POINT; - else - nProduct = NPC_CODE_POINT_PLUS; - } - else if (STARTS_WITH_CI(pszProduct, "OS_LANDRANGER_DTM")) - nProduct = NPC_LANDRANGER_DTM; - else if (STARTS_WITH_CI(pszProduct, "L-F_PROFILE_DTM")) - nProduct = NPC_LANDFORM_PROFILE_DTM; - else if (STARTS_WITH_CI(pszProduct, "NEXTMap Britain DTM")) - nProduct = NPC_LANDFORM_PROFILE_DTM; // Treat as landform - - if (poDS->GetOption("FORCE_GENERIC") != nullptr && - !EQUAL(poDS->GetOption("FORCE_GENERIC"), "OFF")) - nProduct = NPC_UNKNOWN; - - // No point in caching lines if there are no polygons. - if (nProduct != NPC_BOUNDARYLINE && nProduct != NPC_BL2000) - bCacheLines = FALSE; - - /* -------------------------------------------------------------------- */ - /* Handle the section header record. */ - /* -------------------------------------------------------------------- */ - nSavedFeatureId = nBaseFeatureId; - nStartPos = VSIFTellL(fp); - - pszTileName = CPLStrdup(poRecord->GetField(3, 12)); // SECT_REF - size_t nTileNameLen = strlen(pszTileName); - while (nTileNameLen > 0 && pszTileName[nTileNameLen - 1] == ' ') - { - pszTileName[nTileNameLen - 1] = '\0'; - nTileNameLen--; - } - - nCoordWidth = atoi(poRecord->GetField(15, 19)); // XYLEN - if (nCoordWidth <= 0) - nCoordWidth = 10; - - nZWidth = atoi(poRecord->GetField(31, 35)); // ZLEN - if (nZWidth <= 0) - nZWidth = 10; - - dfXYMult = atoi(poRecord->GetField(21, 30)) / 1000.0; // XY_MULT - dfXOrigin = atoi(poRecord->GetField(47, 56)); - dfYOrigin = atoi(poRecord->GetField(57, 66)); - dfTileXSize = atoi(poRecord->GetField(23 + 74, 32 + 74)); - dfTileYSize = atoi(poRecord->GetField(33 + 74, 42 + 74)); - dfZMult = atoi(poRecord->GetField(37, 46)) / 1000.0; - - /* -------------------------------------------------------------------- */ - /* Setup scale and transformation factor for text height. */ - /* -------------------------------------------------------------------- */ - if (poRecord->GetLength() >= 187) - dfScale = atoi(poRecord->GetField(148 + 31, 148 + 39)); - else if (nProduct == NPC_STRATEGI) - dfScale = 250000; - else if (nProduct == NPC_MERIDIAN || nProduct == NPC_MERIDIAN2) - dfScale = 100000; - else if (nProduct == NPC_LANDFORM_PROFILE_CONT) - dfScale = 10000; - else if (nProduct == NPC_LANDRANGER_CONT) - dfScale = 50000; - else if (nProduct == NPC_OSCAR_ASSET || nProduct == NPC_OSCAR_TRAFFIC || - nProduct == NPC_OSCAR_NETWORK || nProduct == NPC_OSCAR_ROUTE) - dfScale = 10000; - else if (nProduct == NPC_BASEDATA) - dfScale = 625000; - else /*if( nProduct == NPC_BOUNDARYLINE ) or default case */ - dfScale = 10000; - - if (dfScale != 0.0) - dfPaperToGround = dfScale / 1000.0; - else - dfPaperToGround = 0.0; - - delete poRecord; - - /* -------------------------------------------------------------------- */ - /* Ensure we have appropriate layers defined. */ - /* -------------------------------------------------------------------- */ - CPLErrorReset(); - - if (!IsRasterProduct()) - EstablishLayers(); - else - EstablishRasterAccess(); - - return CPLGetLastErrorType() != CE_Failure; -} - -/************************************************************************/ -/* DumpReadable() */ -/************************************************************************/ - -void NTFFileReader::DumpReadable(FILE *fpLog) - -{ - fprintf(fpLog, "Tile Name = %s\n", pszTileName); - fprintf(fpLog, "Product = %s\n", pszProduct); - fprintf(fpLog, "NTFLevel = %d\n", nNTFLevel); - fprintf(fpLog, "XYLEN = %d\n", nCoordWidth); - fprintf(fpLog, "XY_MULT = %g\n", dfXYMult); - fprintf(fpLog, "X_ORIG = %g\n", dfXOrigin); - fprintf(fpLog, "Y_ORIG = %g\n", dfYOrigin); - fprintf(fpLog, "XMAX = %g\n", dfTileXSize); - fprintf(fpLog, "YMAX = %g\n", dfTileYSize); -} - -/************************************************************************/ -/* ProcessGeometry() */ -/* */ -/* Drop duplicate vertices from line strings ... they mess up */ -/* FME's polygon handling sometimes. */ -/************************************************************************/ - -OGRGeometry *NTFFileReader::ProcessGeometry(NTFRecord *poRecord, int *pnGeomId) - -{ - if (poRecord->GetType() == NRT_GEOMETRY3D) - return ProcessGeometry3D(poRecord, pnGeomId); - - else if (poRecord->GetType() != NRT_GEOMETRY) - return nullptr; - - const int nGType = atoi(poRecord->GetField(9, 9)); // GTYPE - const int nNumCoord = atoi(poRecord->GetField(10, 13)); // NUM_COORD - if (nNumCoord < 0) - return nullptr; - if (pnGeomId != nullptr) - *pnGeomId = atoi(poRecord->GetField(3, 8)); // GEOM_ID - - /* -------------------------------------------------------------------- */ - /* Point */ - /* -------------------------------------------------------------------- */ - OGRGeometry *poGeometry = nullptr; - if (nGType == 1) - { - const double dfX = - atoi(poRecord->GetField(14, 14 + GetXYLen() - 1)) * GetXYMult() + - GetXOrigin(); - const double dfY = - atoi(poRecord->GetField(14 + GetXYLen(), 14 + GetXYLen() * 2 - 1)) * - GetXYMult() + - GetYOrigin(); - - poGeometry = new OGRPoint(dfX, dfY); - } - - /* -------------------------------------------------------------------- */ - /* Line (or arc) */ - /* -------------------------------------------------------------------- */ - else if (nGType == 2 || nGType == 3 || nGType == 4) - { - - if (nNumCoord > 0 && poRecord->GetLength() < - 14 + (nNumCoord - 1) * (GetXYLen() * 2 + 1) + - GetXYLen() * 2 - 1) - { - return nullptr; - } - - OGRLineString *poLine = new OGRLineString; - double dfXLast = 0.0; - double dfYLast = 0.0; - int nOutCount = 0; - - poGeometry = poLine; - poLine->setNumPoints(nNumCoord); - for (int iCoord = 0; iCoord < nNumCoord; iCoord++) - { - const int iStart = 14 + iCoord * (GetXYLen() * 2 + 1); - - const double dfX = - atoi(poRecord->GetField(iStart + 0, iStart + GetXYLen() - 1)) * - GetXYMult() + - GetXOrigin(); - const double dfY = - atoi(poRecord->GetField(iStart + GetXYLen(), - iStart + GetXYLen() * 2 - 1)) * - GetXYMult() + - GetYOrigin(); - - if (iCoord == 0) - { - dfXLast = dfX; - dfYLast = dfY; - poLine->setPoint(nOutCount++, dfX, dfY); - } - else if (dfXLast != dfX || dfYLast != dfY) - { - dfXLast = dfX; - dfYLast = dfY; - poLine->setPoint(nOutCount++, dfX, dfY); - } - } - poLine->setNumPoints(nOutCount); - - CacheAddByGeomId(atoi(poRecord->GetField(3, 8)), poLine); - } - - /* -------------------------------------------------------------------- */ - /* Arc defined by three points on the arc. */ - /* -------------------------------------------------------------------- */ - else if (nGType == 5 && nNumCoord == 3) - { - double adfX[3] = {0.0, 0.0, 0.0}; - double adfY[3] = {0.0, 0.0, 0.0}; - - for (int iCoord = 0; iCoord < nNumCoord; iCoord++) - { - const int iStart = 14 + iCoord * (GetXYLen() * 2 + 1); - - adfX[iCoord] = - atoi(poRecord->GetField(iStart + 0, iStart + GetXYLen() - 1)) * - GetXYMult() + - GetXOrigin(); - adfY[iCoord] = - atoi(poRecord->GetField(iStart + GetXYLen(), - iStart + GetXYLen() * 2 - 1)) * - GetXYMult() + - GetYOrigin(); - } - - poGeometry = NTFStrokeArcToOGRGeometry_Points( - adfX[0], adfY[0], adfX[1], adfY[1], adfX[2], adfY[2], 72); - } - - /* -------------------------------------------------------------------- */ - /* Circle */ - /* -------------------------------------------------------------------- */ - else if (nGType == 7) - { - const int iCenterStart = 14; - const int iArcStart = 14 + 2 * GetXYLen() + 1; - - const double dfCenterX = - atoi(poRecord->GetField(iCenterStart, - iCenterStart + GetXYLen() - 1)) * - GetXYMult() + - GetXOrigin(); - const double dfCenterY = - atoi(poRecord->GetField(iCenterStart + GetXYLen(), - iCenterStart + GetXYLen() * 2 - 1)) * - GetXYMult() + - GetYOrigin(); - - const double dfArcX = - atoi(poRecord->GetField(iArcStart, iArcStart + GetXYLen() - 1)) * - GetXYMult() + - GetXOrigin(); - const double dfArcY = - atoi(poRecord->GetField(iArcStart + GetXYLen(), - iArcStart + GetXYLen() * 2 - 1)) * - GetXYMult() + - GetYOrigin(); - - const double dfRadius = - sqrt((dfCenterX - dfArcX) * (dfCenterX - dfArcX) + - (dfCenterY - dfArcY) * (dfCenterY - dfArcY)); - - poGeometry = NTFStrokeArcToOGRGeometry_Angles(dfCenterX, dfCenterY, - dfRadius, 0.0, 360.0, 72); - } - - else - { - CPLError(CE_Failure, CPLE_AppDefined, "Unhandled GType = %d", nGType); - } - - if (poGeometry != nullptr) - poGeometry->assignSpatialReference(poDS->DSGetSpatialRef()); - - return poGeometry; -} - -/************************************************************************/ -/* ProcessGeometry3D() */ -/************************************************************************/ - -OGRGeometry *NTFFileReader::ProcessGeometry3D(NTFRecord *poRecord, - int *pnGeomId) - -{ - OGRGeometry *poGeometry = nullptr; - - if (poRecord->GetType() != NRT_GEOMETRY3D) - return nullptr; - - const int nGType = atoi(poRecord->GetField(9, 9)); // GTYPE - const int nNumCoord = atoi(poRecord->GetField(10, 13)); // NUM_COORD - if (pnGeomId != nullptr) - *pnGeomId = atoi(poRecord->GetField(3, 8)); // GEOM_ID - - if (nGType == 1) - { - if (14 + 1 + 2 * static_cast(GetXYLen()) + nZWidth - 1 > - INT_MAX) - { - return nullptr; - } - const double dfX = - atoi(poRecord->GetField(14, 14 + GetXYLen() - 1)) * GetXYMult() + - GetXOrigin(); - const double dfY = - atoi(poRecord->GetField(14 + GetXYLen(), 14 + GetXYLen() * 2 - 1)) * - GetXYMult() + - GetYOrigin(); - const double dfZ = - atoi(poRecord->GetField(14 + 1 + 2 * GetXYLen(), - 14 + 1 + 2 * GetXYLen() + nZWidth - 1)) * - dfZMult; - - poGeometry = new OGRPoint(dfX, dfY, dfZ); - } - - else if (nGType == 2) - { - if (nNumCoord < 0 || 14 + - static_cast(nNumCoord - 1) * - (GetXYLen() * 2 + nZWidth + 2) + - 1 + 2 * GetXYLen() + nZWidth - 1 > - INT_MAX) - { - return nullptr; - } - - OGRLineString *poLine = new OGRLineString; - double dfXLast = 0.0; - double dfYLast = 0.0; - int nOutCount = 0; - - poGeometry = poLine; - poLine->setNumPoints(nNumCoord); - const GUInt32 nErrorsBefore = CPLGetErrorCounter(); - for (int iCoord = 0; iCoord < nNumCoord; iCoord++) - { - const int iStart = 14 + iCoord * (GetXYLen() * 2 + nZWidth + 2); - - const char *pszX = - poRecord->GetField(iStart + 0, iStart + GetXYLen() - 1); - bool bSpace = pszX[0] == ' '; - const double dfX = atoi(pszX) * GetXYMult() + GetXOrigin(); - const char *pszY = poRecord->GetField(iStart + GetXYLen(), - iStart + GetXYLen() * 2 - 1); - bSpace |= pszY[0] == ' '; - const double dfY = atoi(pszY) * GetXYMult() + GetYOrigin(); - - const char *pszZ = - poRecord->GetField(iStart + 1 + 2 * GetXYLen(), - iStart + 1 + 2 * GetXYLen() + nZWidth - 1); - bSpace |= pszZ[0] == ' '; - const double dfZ = atoi(pszZ) * dfZMult; - if (bSpace && CPLGetErrorCounter() != nErrorsBefore) - { - delete poGeometry; - return nullptr; - } - - if (iCoord == 0) - { - dfXLast = dfX; - dfYLast = dfY; - poLine->setPoint(nOutCount++, dfX, dfY, dfZ); - } - else if (dfXLast != dfX || dfYLast != dfY) - { - dfXLast = dfX; - dfYLast = dfY; - poLine->setPoint(nOutCount++, dfX, dfY, dfZ); - } - } - poLine->setNumPoints(nOutCount); - - CacheAddByGeomId(atoi(poRecord->GetField(3, 8)), poLine); - } - - if (poGeometry != nullptr) - poGeometry->assignSpatialReference(poDS->DSGetSpatialRef()); - - return poGeometry; -} - -/************************************************************************/ -/* ProcessAttDesc() */ -/************************************************************************/ - -int NTFFileReader::ProcessAttDesc(NTFRecord *poRecord, NTFAttDesc *psAD) - -{ - psAD->poCodeList = nullptr; - if (poRecord->GetType() != NRT_ADR || poRecord->GetLength() < 13) - return FALSE; - - snprintf(psAD->val_type, sizeof(psAD->val_type), "%s", - poRecord->GetField(3, 4)); - snprintf(psAD->fwidth, sizeof(psAD->fwidth), "%s", - poRecord->GetField(5, 7)); - snprintf(psAD->finter, sizeof(psAD->finter), "%s", - poRecord->GetField(8, 12)); - - const char *pszData = poRecord->GetData(); - int iChar = 12; // Used after for. - for (; pszData[iChar] != '\0' && pszData[iChar] != '\\'; iChar++) - { - } - - snprintf(psAD->att_name, sizeof(psAD->att_name), "%s", - poRecord->GetField(13, iChar)); - - return TRUE; -} - -/************************************************************************/ -/* ProcessAttRecGroup() */ -/* */ -/* Extract attribute values from all attribute records in a */ -/* record set. */ -/************************************************************************/ - -int NTFFileReader::ProcessAttRecGroup(NTFRecord **papoRecords, - char ***ppapszTypes, char ***ppapszValues) - -{ - *ppapszTypes = nullptr; - *ppapszValues = nullptr; - - for (int iRec = 0; papoRecords[iRec] != nullptr; iRec++) - { - if (papoRecords[iRec]->GetType() != NRT_ATTREC) - continue; - - char **papszTypes1 = nullptr; - char **papszValues1 = nullptr; - if (!ProcessAttRec(papoRecords[iRec], nullptr, &papszTypes1, - &papszValues1)) - { - CSLDestroy(*ppapszTypes); - CSLDestroy(*ppapszValues); - *ppapszTypes = nullptr; - *ppapszValues = nullptr; - return FALSE; - } - - if (*ppapszTypes == nullptr) - { - *ppapszTypes = papszTypes1; - *ppapszValues = papszValues1; - } - else - { - for (int i = 0; papszTypes1[i] != nullptr; i++) - { - *ppapszTypes = CSLAddString(*ppapszTypes, papszTypes1[i]); - *ppapszValues = CSLAddString(*ppapszValues, papszValues1[i]); - } - CSLDestroy(papszTypes1); - CSLDestroy(papszValues1); - } - } - - return TRUE; -} - -/************************************************************************/ -/* ProcessAttRec() */ -/************************************************************************/ - -int NTFFileReader::ProcessAttRec(NTFRecord *poRecord, int *pnAttId, - char ***ppapszTypes, char ***ppapszValues) - -{ - if (pnAttId != nullptr) - *pnAttId = 0; - *ppapszTypes = nullptr; - *ppapszValues = nullptr; - - if (poRecord->GetType() != NRT_ATTREC || poRecord->GetLength() < 8) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Extract the attribute id. */ - /* -------------------------------------------------------------------- */ - if (pnAttId != nullptr) - *pnAttId = atoi(poRecord->GetField(3, 8)); - - /* ==================================================================== */ - /* Loop handling attribute till we get a '0' indicating the end */ - /* of the record. */ - /* ==================================================================== */ - - int iOffset = 8; - const char *pszData = poRecord->GetData(); - bool bError = false; - - while (iOffset < poRecord->GetLength() && pszData[iOffset] != DIGIT_ZERO) - { - /* -------------------------------------------------------------------- - */ - /* Extract the two letter code name for the attribute, and use */ - /* it to find the correct ATTDESC info. */ - /* -------------------------------------------------------------------- - */ - NTFAttDesc *psAttDesc = GetAttDesc(pszData + iOffset); - if (psAttDesc == nullptr) - { - CPLDebug("NTF", "Couldn't translate attrec type `%2.2s'.", - pszData + iOffset); - bError = true; - break; - } - - *ppapszTypes = CSLAddString( - *ppapszTypes, poRecord->GetField(iOffset + 1, iOffset + 2)); - - /* -------------------------------------------------------------------- - */ - /* Establish the width of the value. Zero width fields are */ - /* terminated by a backslash. */ - /* -------------------------------------------------------------------- - */ - const int nFWidth = atoi(psAttDesc->fwidth); - if (nFWidth < 0) - { - bError = true; - break; - } - int nEnd = 0; - if (nFWidth == 0) - { - const char *pszData2 = poRecord->GetData(); - if (iOffset + 2 >= poRecord->GetLength()) - { - bError = true; - break; - } - for (nEnd = iOffset + 2; - pszData2[nEnd] != '\\' && pszData2[nEnd] != '\0'; nEnd++) - { - } - } - else - { - nEnd = iOffset + 3 + nFWidth - 1; - } - - /* -------------------------------------------------------------------- - */ - /* Extract the value. If it is formatted as fixed point real */ - /* we reprocess it to insert the decimal point. */ - /* -------------------------------------------------------------------- - */ - const char *pszRawValue = poRecord->GetField(iOffset + 3, nEnd); - *ppapszValues = CSLAddString(*ppapszValues, pszRawValue); - - /* -------------------------------------------------------------------- - */ - /* Establish new offset position. */ - /* -------------------------------------------------------------------- - */ - if (nFWidth == 0) - { - iOffset = nEnd; - if (iOffset >= poRecord->GetLength()) - { - bError = (iOffset > poRecord->GetLength()); - break; - } - if (pszData[iOffset] == '\\') - iOffset++; - } - else - iOffset += 2 + nFWidth; - } - - if (bError) - { - CSLDestroy(*ppapszTypes); - CSLDestroy(*ppapszValues); - *ppapszTypes = nullptr; - *ppapszValues = nullptr; - } - - return (*ppapszTypes != nullptr); -} - -/************************************************************************/ -/* GetAttDesc() */ -/************************************************************************/ - -NTFAttDesc *NTFFileReader::GetAttDesc(const char *pszType) - -{ - for (int i = 0; i < nAttCount; i++) - { - if (EQUALN(pszType, pasAttDesc[i].val_type, 2)) - return pasAttDesc + i; - } - - return nullptr; -} - -/************************************************************************/ -/* ProcessAttValue() */ -/* */ -/* Take an attribute type/value pair and transform into a */ -/* meaningful attribute name, and value. The source can be an */ -/* ATTREC or the VAL_TYPE/VALUE pair of a POINTREC or LINEREC. */ -/* The name is transformed from the two character short form to */ -/* the long user name. The value will be transformed from */ -/* fixed point (with the decimal implicit) to fixed point with */ -/* an explicit decimal point if it has a "R" format. */ -/* Note: the returned *ppszAttValue has a very short lifetime */ -/* and should immediately be used. Further calls to */ -/* ProcessAttValue or CPLSPrintf() will invalidate it. */ -/************************************************************************/ - -int NTFFileReader::ProcessAttValue(const char *pszValType, - const char *pszRawValue, - const char **ppszAttName, - const char **ppszAttValue, - const char **ppszCodeDesc) - -{ - /* -------------------------------------------------------------------- */ - /* Find the ATTDESC for this attribute, and assign return name value.*/ - /* -------------------------------------------------------------------- */ - NTFAttDesc *psAttDesc = GetAttDesc(pszValType); - - if (psAttDesc == nullptr) - return FALSE; - - if (ppszAttName != nullptr) - *ppszAttName = psAttDesc->att_name; - - /* -------------------------------------------------------------------- */ - /* Extract the value. If it is formatted as fixed point real */ - /* we reprocess it to insert the decimal point. */ - /* -------------------------------------------------------------------- */ - if (psAttDesc->finter[0] == 'R') - { - const char *pszDecimalPortion = nullptr; // Used after for. - - for (pszDecimalPortion = psAttDesc->finter; - *pszDecimalPortion != ',' && *pszDecimalPortion != '\0'; - pszDecimalPortion++) - { - } - if (*pszDecimalPortion == '\0') - { - *ppszAttValue = ""; - } - else - { - const int nWidth = static_cast(strlen(pszRawValue)); - const int nPrecision = atoi(pszDecimalPortion + 1); - if (nPrecision < 0 || nPrecision >= nWidth) - { - *ppszAttValue = ""; - } - else - { - CPLString osResult(pszRawValue); - osResult.resize(nWidth - nPrecision); - osResult += "."; - osResult += pszRawValue + nWidth - nPrecision; - - *ppszAttValue = CPLSPrintf("%s", osResult.c_str()); - } - } - } - - /* -------------------------------------------------------------------- */ - /* If it is an integer, we just reformat to get rid of leading */ - /* zeros. */ - /* -------------------------------------------------------------------- */ - else if (psAttDesc->finter[0] == 'I') - { - *ppszAttValue = CPLSPrintf("%d", atoi(pszRawValue)); - } - - /* -------------------------------------------------------------------- */ - /* Otherwise we take the value directly. */ - /* -------------------------------------------------------------------- */ - else - { - *ppszAttValue = pszRawValue; - } - - /* -------------------------------------------------------------------- */ - /* Handle processing code values into code descriptions, if */ - /* applicable. */ - /* -------------------------------------------------------------------- */ - if (ppszCodeDesc == nullptr) - { - } - else if (psAttDesc->poCodeList != nullptr) - { - *ppszCodeDesc = psAttDesc->poCodeList->Lookup(*ppszAttValue); - } - else - { - *ppszCodeDesc = nullptr; - } - - return TRUE; -} - -/************************************************************************/ -/* ApplyAttributeValues() */ -/* */ -/* Apply a series of attribute values to a feature from generic */ -/* attribute records. */ -/************************************************************************/ - -void NTFFileReader::ApplyAttributeValues(OGRFeature *poFeature, - NTFRecord **papoGroup, ...) - -{ - /* -------------------------------------------------------------------- */ - /* Extract attribute values from record group. */ - /* -------------------------------------------------------------------- */ - char **papszTypes = nullptr; - char **papszValues = nullptr; - - if (!ProcessAttRecGroup(papoGroup, &papszTypes, &papszValues)) - return; - - /* -------------------------------------------------------------------- */ - /* Handle attribute pairs */ - /* -------------------------------------------------------------------- */ - va_list hVaArgs; - - va_start(hVaArgs, papoGroup); - - const char *pszAttName = nullptr; - while ((pszAttName = va_arg(hVaArgs, const char *)) != nullptr) - { - const int iField = va_arg(hVaArgs, int); - - ApplyAttributeValue(poFeature, iField, pszAttName, papszTypes, - papszValues); - } - - va_end(hVaArgs); - - /* -------------------------------------------------------------------- */ - /* Cleanup. */ - /* -------------------------------------------------------------------- */ - CSLDestroy(papszTypes); - CSLDestroy(papszValues); -} - -/************************************************************************/ -/* ApplyAttributeValue() */ -/* */ -/* Apply the indicated attribute value to an OGRFeature field */ -/* if it exists in the attribute value list given. */ -/************************************************************************/ - -int NTFFileReader::ApplyAttributeValue(OGRFeature *poFeature, int iField, - const char *pszAttName, - char **papszTypes, char **papszValues) - -{ - /* -------------------------------------------------------------------- */ - /* Find the requested attribute in the name/value pair */ - /* provided. If not found that's fine, just return with */ - /* notification. */ - /* -------------------------------------------------------------------- */ - const int iValue = CSLFindString(papszTypes, pszAttName); - if (iValue < 0) - return FALSE; - - CPLAssert(papszValues != nullptr); - /* -------------------------------------------------------------------- */ - /* Process the attribute value ... this really only has a */ - /* useful effect for real numbers. */ - /* -------------------------------------------------------------------- */ - const char *pszAttLongName = nullptr; - const char *pszAttValue = nullptr; - const char *pszCodeDesc = nullptr; - - if (!ProcessAttValue(pszAttName, papszValues[iValue], &pszAttLongName, - &pszAttValue, &pszCodeDesc)) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Apply the value to the field using the simple set string */ - /* method. Leave it to the OGRFeature::SetField() method to */ - /* take care of translation to other types. */ - /* -------------------------------------------------------------------- */ - poFeature->SetField(iField, pszAttValue); - - /* -------------------------------------------------------------------- */ - /* Apply the code description if we found one. */ - /* -------------------------------------------------------------------- */ - if (pszCodeDesc != nullptr) - { - char szDescFieldName[256]; - - snprintf(szDescFieldName, sizeof(szDescFieldName), "%s_DESC", - poFeature->GetDefnRef()->GetFieldDefn(iField)->GetNameRef()); - poFeature->SetField(szDescFieldName, pszCodeDesc); - } - - return TRUE; -} - -/************************************************************************/ -/* SaveRecord() */ -/************************************************************************/ - -void NTFFileReader::SaveRecord(NTFRecord *poRecord) - -{ - CPLAssert(poSavedRecord == nullptr); - poSavedRecord = poRecord; -} - -/************************************************************************/ -/* ReadRecord() */ -/************************************************************************/ - -NTFRecord *NTFFileReader::ReadRecord() - -{ - if (poSavedRecord != nullptr) - { - NTFRecord *poReturn = poSavedRecord; - - poSavedRecord = nullptr; - - return poReturn; - } - else - { - CPLErrorReset(); - if (fp != nullptr) - nPreSavedPos = VSIFTellL(fp); - NTFRecord *poRecord = new NTFRecord(fp); - if (fp != nullptr) - nPostSavedPos = VSIFTellL(fp); - - /* ensure termination if we fail to read a record */ - if (CPLGetLastErrorType() == CE_Failure) - { - delete poRecord; - poRecord = nullptr; - } - - return poRecord; - } -} - -/************************************************************************/ -/* GetFPPos() */ -/* */ -/* Return the current file pointer position. */ -/************************************************************************/ - -void NTFFileReader::GetFPPos(vsi_l_offset *pnPos, long *pnFID) - -{ - if (poSavedRecord != nullptr) - *pnPos = nPreSavedPos; - else - *pnPos = nPostSavedPos; - - if (pnFID != nullptr) - *pnFID = nSavedFeatureId; -} - -/************************************************************************/ -/* SetFPPos() */ -/************************************************************************/ - -int NTFFileReader::SetFPPos(vsi_l_offset nNewPos, long nNewFID) - -{ - if (nNewFID == nSavedFeatureId) - return TRUE; - - if (poSavedRecord != nullptr) - { - delete poSavedRecord; - poSavedRecord = nullptr; - } - - if (fp != nullptr && VSIFSeekL(fp, nNewPos, SEEK_SET) == 0) - { - nPreSavedPos = nPostSavedPos = nNewPos; - nSavedFeatureId = nNewFID; - return TRUE; - } - else - return FALSE; -} - -/************************************************************************/ -/* Reset() */ -/* */ -/* Reset reading to the first feature record. */ -/************************************************************************/ - -void NTFFileReader::Reset() - -{ - SetFPPos(nStartPos, nBaseFeatureId); - ClearCGroup(); -} - -/************************************************************************/ -/* ClearCGroup() */ -/* */ -/* Clear the currently loaded record group. */ -/************************************************************************/ - -void NTFFileReader::ClearCGroup() - -{ - for (int i = 0; apoCGroup[i] != nullptr; i++) - delete apoCGroup[i]; - - apoCGroup[0] = nullptr; - apoCGroup[1] = nullptr; -} - -/************************************************************************/ -/* DefaultNTFRecordGrouper() */ -/* */ -/* Default rules for figuring out if a new candidate record */ -/* belongs to a group of records that together form a feature */ -/* (a record group). */ -/************************************************************************/ - -int DefaultNTFRecordGrouper(NTFFileReader *, NTFRecord **papoGroup, - NTFRecord *poCandidate) - -{ - /* -------------------------------------------------------------------- */ - /* Is this group going to be a CPOLY set? We can recognise */ - /* this because we get repeating POLY/CHAIN sets without an */ - /* intermediate attribute record. This is a rather special case! */ - /* -------------------------------------------------------------------- */ - if (papoGroup[0] != nullptr && papoGroup[1] != nullptr && - papoGroup[0]->GetType() == NRT_POLYGON && - papoGroup[1]->GetType() == NRT_CHAIN) - { - // We keep going till we get the seed geometry. - int iRec, bGotCPOLY = FALSE; - - for (iRec = 0; papoGroup[iRec] != nullptr; iRec++) - { - if (papoGroup[iRec]->GetType() == NRT_CPOLY) - bGotCPOLY = TRUE; - } - - if (bGotCPOLY && poCandidate->GetType() != NRT_GEOMETRY && - poCandidate->GetType() != NRT_ATTREC) - return FALSE; - - /* - * this logic assumes we always get a point geometry with a CPOLY - * but that isn't always true, for instance with BL2000 data. The - * preceding check will handle this case. - */ - if (papoGroup[iRec - 1]->GetType() != NRT_GEOMETRY) - return TRUE; - else - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Is this a "feature" defining record? If so break out if it */ - /* isn't the first record in the group. */ - /* -------------------------------------------------------------------- */ - if (papoGroup[0] != nullptr && (poCandidate->GetType() == NRT_NAMEREC || - poCandidate->GetType() == NRT_NODEREC || - poCandidate->GetType() == NRT_LINEREC || - poCandidate->GetType() == NRT_POINTREC || - poCandidate->GetType() == NRT_POLYGON || - poCandidate->GetType() == NRT_CPOLY || - poCandidate->GetType() == NRT_COLLECT || - poCandidate->GetType() == NRT_TEXTREC || - poCandidate->GetType() == NRT_COMMENT)) - { - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Do we already have a record of this type? If so, it likely */ - /* doesn't belong in the group. Attribute records do repeat in */ - /* some products. */ - /* -------------------------------------------------------------------- */ - if (poCandidate->GetType() != NRT_ATTREC) - { - int iRec = 0; // Used after for. - for (; papoGroup[iRec] != nullptr; iRec++) - { - if (poCandidate->GetType() == papoGroup[iRec]->GetType()) - break; - } - - if (papoGroup[iRec] != nullptr) - return FALSE; - } - - return TRUE; -} - -/************************************************************************/ -/* ReadRecordGroup() */ -/* */ -/* Read a group of records that form a single feature. */ -/************************************************************************/ - -NTFRecord **NTFFileReader::ReadRecordGroup() - -{ - - ClearCGroup(); - - /* -------------------------------------------------------------------- */ - /* Loop, reading records till we think we have a grouping. */ - /* -------------------------------------------------------------------- */ - int nRecordCount = 0; - NTFRecord *poRecord = nullptr; - while ((poRecord = ReadRecord()) != nullptr && - poRecord->GetType() != NRT_VTR) - { - if (nRecordCount >= MAX_REC_GROUP) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Maximum record group size (%d) exceeded.\n", - MAX_REC_GROUP); - break; - } - - if (!pfnRecordGrouper(this, apoCGroup, poRecord)) - break; - - apoCGroup[nRecordCount++] = poRecord; - apoCGroup[nRecordCount] = nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Push the last record back on the input queue. */ - /* -------------------------------------------------------------------- */ - if (poRecord != nullptr) - SaveRecord(poRecord); - - /* -------------------------------------------------------------------- */ - /* Return the list, or NULL if we didn't get any records. */ - /* -------------------------------------------------------------------- */ - if (nRecordCount == 0) - return nullptr; - else - return apoCGroup; -} - -/************************************************************************/ -/* GetFeatureClass() */ -/************************************************************************/ - -int NTFFileReader::GetFeatureClass(int iFCIndex, char **ppszFCId, - char **ppszFCName) - -{ - if (iFCIndex < 0 || iFCIndex >= nFCCount) - { - *ppszFCId = nullptr; - *ppszFCName = nullptr; - return FALSE; - } - else - { - *ppszFCId = papszFCNum[iFCIndex]; - *ppszFCName = papszFCName[iFCIndex]; - return TRUE; - } -} - -/************************************************************************/ -/* ReadOGRFeature() */ -/************************************************************************/ - -OGRFeature *NTFFileReader::ReadOGRFeature(OGRNTFLayer *poTargetLayer) - -{ - /* -------------------------------------------------------------------- */ - /* If this is a raster file, use a custom method to read the */ - /* feature. */ - /* -------------------------------------------------------------------- */ - if (IsRasterProduct()) - return poRasterLayer->GetNextFeature(); - - /* -------------------------------------------------------------------- */ - /* Loop looking for a group we can translate, and that if */ - /* needed matches our layer request. */ - /* -------------------------------------------------------------------- */ - OGRNTFLayer *poLayer = nullptr; - OGRFeature *poFeature = nullptr; - - while (true) - { - NTFRecord **papoGroup = nullptr; - - if (GetProductId() == NPC_UNKNOWN && nNTFLevel > 2) - papoGroup = GetNextIndexedRecordGroup(apoCGroup + 1); - else - papoGroup = ReadRecordGroup(); - - if (papoGroup == nullptr || papoGroup[0] == nullptr) - break; - - int nType = papoGroup[0]->GetType(); - if (nType < 0 || nType >= (int)(sizeof(apoTypeTranslation) / - sizeof(apoTypeTranslation[0]))) - continue; - poLayer = apoTypeTranslation[nType]; - if (poLayer == nullptr) - continue; - - if (poTargetLayer != nullptr && poTargetLayer != poLayer) - { - CacheLineGeometryInGroup(papoGroup); - nSavedFeatureId++; - continue; - } - - poFeature = poLayer->FeatureTranslate(this, papoGroup); - if (poFeature == nullptr) - { - // should this be a real error? - CPLDebug("NTF", - "FeatureTranslate() failed for a type %d record group\n" - "in a %s type file.\n", - papoGroup[0]->GetType(), GetProduct()); - } - else - { - break; - } - } - - /* -------------------------------------------------------------------- */ - /* If we got a feature, set the TILE_REF on it. */ - /* -------------------------------------------------------------------- */ - if (poFeature != nullptr) - { - int iTileRefField = poLayer->GetLayerDefn()->GetFieldCount() - 1; - - CPLAssert(EQUAL( - poLayer->GetLayerDefn()->GetFieldDefn(iTileRefField)->GetNameRef(), - "TILE_REF")); - - poFeature->SetField(iTileRefField, GetTileName()); - poFeature->SetFID(nSavedFeatureId); - - nSavedFeatureId++; - } - - /* -------------------------------------------------------------------- */ - /* If we got to the end we can establish our feature count for */ - /* the file. */ - /* -------------------------------------------------------------------- */ - else - { - // This assertion was triggered by - // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1982 it doesn't - // look critical enough to be enabled. - // CPLAssert( nFeatureCount == -1 - // || nFeatureCount == nSavedFeatureId - nBaseFeatureId ); - nFeatureCount = nSavedFeatureId - nBaseFeatureId; - } - - return poFeature; -} - -/************************************************************************/ -/* TestForLayer() */ -/* */ -/* Return indicator of whether this file contains any features */ -/* of the indicated layer type. */ -/************************************************************************/ - -int NTFFileReader::TestForLayer(OGRNTFLayer *poLayer) - -{ - for (int i = 0; i < 100; i++) - { - if (apoTypeTranslation[i] == poLayer) - return TRUE; - } - - return FALSE; -} - -/************************************************************************/ -/* FreshenIndex() */ -/* */ -/* Rebuild the index if it is needed, and currently missing. */ -/************************************************************************/ - -void NTFFileReader::FreshenIndex() - -{ - if (!bIndexBuilt && bIndexNeeded) - IndexFile(); -} - -/************************************************************************/ -/* IndexFile() */ -/* */ -/* Read all records beyond the section header and build an */ -/* internal index of them. */ -/************************************************************************/ - -void NTFFileReader::IndexFile() - -{ - Reset(); - - DestroyIndex(); - - bIndexNeeded = TRUE; - bIndexBuilt = TRUE; - bCacheLines = FALSE; - - /* -------------------------------------------------------------------- */ - /* Process all records after the section header, and before 99 */ - /* to put them in the index. */ - /* -------------------------------------------------------------------- */ - NTFRecord *poRecord = nullptr; - while ((poRecord = ReadRecord()) != nullptr && poRecord->GetType() != 99) - { - const int iType = poRecord->GetType(); - const int iId = atoi(poRecord->GetField(3, 8)); - - if (iType < 0 || iType >= 100) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Illegal type %d record, skipping.", iType); - delete poRecord; - continue; - } - if (iId < 0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Illegal id %d record, skipping.", iId); - delete poRecord; - continue; - } - - /* -------------------------------------------------------------------- - */ - /* Grow type specific subindex if needed. */ - /* -------------------------------------------------------------------- - */ - if (anIndexSize[iType] <= iId) - { - const int nNewSize = std::max(iId + 1, anIndexSize[iType] * 2 + 10); - - apapoRecordIndex[iType] = static_cast( - CPLRealloc(apapoRecordIndex[iType], sizeof(void *) * nNewSize)); - - for (int i = anIndexSize[iType]; i < nNewSize; i++) - (apapoRecordIndex[iType])[i] = nullptr; - - anIndexSize[iType] = nNewSize; - } - - /* -------------------------------------------------------------------- - */ - /* Put record into type specific subindex based on its id as */ - /* the key. */ - /* -------------------------------------------------------------------- - */ - if (apapoRecordIndex[iType][iId] != nullptr) - { - CPLDebug("OGR_NTF", - "Duplicate record with index %d and type %d\n" - "in NTFFileReader::IndexFile().", - iId, iType); - delete apapoRecordIndex[iType][iId]; - } - (apapoRecordIndex[iType])[iId] = poRecord; - } - - if (poRecord != nullptr) - delete poRecord; -} - -/************************************************************************/ -/* DestroyIndex() */ -/************************************************************************/ - -void NTFFileReader::DestroyIndex() - -{ - for (int i = 0; i < 100; i++) - { - for (int iId = 0; iId < anIndexSize[i]; iId++) - { - if ((apapoRecordIndex[i])[iId] != nullptr) - delete (apapoRecordIndex[i])[iId]; - } - - CPLFree(apapoRecordIndex[i]); - apapoRecordIndex[i] = nullptr; - anIndexSize[i] = 0; - } - - bIndexBuilt = FALSE; -} - -/************************************************************************/ -/* GetIndexedRecord() */ -/************************************************************************/ - -NTFRecord *NTFFileReader::GetIndexedRecord(int iType, int iId) - -{ - if ((iType < 0 || iType > 99) || (iId < 0 || iId >= anIndexSize[iType]) || - (apapoRecordIndex[iType])[iId] == nullptr) - { - /* If NRT_GEOMETRY3D is an acceptable alternative to 2D */ - if (iType == NRT_GEOMETRY) - return GetIndexedRecord(NRT_GEOMETRY3D, iId); - else - return nullptr; - } - - return (apapoRecordIndex[iType])[iId]; -} - -/************************************************************************/ -/* AddToIndexGroup() */ -/************************************************************************/ - -void NTFFileReader::AddToIndexGroup(NTFRecord *poRecord) - -{ - int i = 1; // Used after for. - for (; apoCGroup[i] != nullptr; i++) - { - if (apoCGroup[i] == poRecord) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Record already inserted in group"); - return; - } - } - if (i == MAX_REC_GROUP) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Maximum number of records in group reached"); - delete poRecord; - return; - } - - apoCGroup[i] = poRecord; - apoCGroup[i + 1] = nullptr; -} - -/************************************************************************/ -/* GetNextIndexedRecordGroup() */ -/************************************************************************/ - -NTFRecord **NTFFileReader::GetNextIndexedRecordGroup(NTFRecord **papoPrevGroup) - -{ - int nPrevType, nPrevId; - - /* -------------------------------------------------------------------- */ - /* What was the identify of our previous anchor record? */ - /* -------------------------------------------------------------------- */ - if (papoPrevGroup == nullptr || papoPrevGroup[0] == nullptr) - { - nPrevType = NRT_POINTREC; - nPrevId = 0; - FreshenIndex(); - } - else - { - nPrevType = papoPrevGroup[0]->GetType(); - nPrevId = atoi(papoPrevGroup[0]->GetField(3, 8)); - if (nPrevId < 0) - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Find the next anchor record. */ - /* -------------------------------------------------------------------- */ - NTFRecord *poAnchor = nullptr; - - while (nPrevType != 99 && poAnchor == nullptr) - { - nPrevId++; - if (nPrevId >= anIndexSize[nPrevType]) - { - do - { - nPrevType++; - } while (nPrevType != NRT_VTR && nPrevType != NRT_NODEREC && - nPrevType != NRT_TEXTREC && nPrevType != NRT_NAMEREC && - nPrevType != NRT_COLLECT && nPrevType != NRT_POLYGON && - nPrevType != NRT_CPOLY && nPrevType != NRT_POINTREC && - nPrevType != NRT_LINEREC); - - nPrevId = 0; - } - else - { - poAnchor = (apapoRecordIndex[nPrevType])[nPrevId]; - } - } - - if (poAnchor == nullptr) - { - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Build record group depending on type of anchor and what it */ - /* refers to. */ - /* -------------------------------------------------------------------- */ - apoCGroup[0] = nullptr; - apoCGroup[1] = poAnchor; - apoCGroup[2] = nullptr; - - /* -------------------------------------------------------------------- */ - /* Handle POINTREC/LINEREC */ - /* -------------------------------------------------------------------- */ - if (poAnchor->GetType() == NRT_POINTREC || - poAnchor->GetType() == NRT_LINEREC) - { - int l_nAttCount = 0; - - AddToIndexGroup( - GetIndexedRecord(NRT_GEOMETRY, atoi(poAnchor->GetField(9, 14)))); - - if (poAnchor->GetLength() >= 16) - l_nAttCount = atoi(poAnchor->GetField(15, 16)); - - for (int iAtt = 0; iAtt < l_nAttCount; iAtt++) - { - AddToIndexGroup(GetIndexedRecord( - NRT_ATTREC, - atoi(poAnchor->GetField(17 + 6 * iAtt, 22 + 6 * iAtt)))); - } - } - - /* -------------------------------------------------------------------- */ - /* Handle TEXTREC */ - /* -------------------------------------------------------------------- */ - else if (poAnchor->GetType() == NRT_TEXTREC) - { - int l_nAttCount = 0; - int nSelCount = 0; - - // Add all the text position records. - nSelCount = atoi(poAnchor->GetField(9, 10)); - if (nSelCount < 0) - return nullptr; - - for (int iSel = 0; iSel < nSelCount; iSel++) - { - int iStart = 11 + 12 * iSel + 6; - - AddToIndexGroup(GetIndexedRecord( - NRT_TEXTPOS, atoi(poAnchor->GetField(iStart, iStart + 5)))); - } - - // Add all geometry and TEXR records pointed to by text position - // records. - for (int iRec = 1; apoCGroup[iRec] != nullptr; iRec++) - { - NTFRecord *poRecord = apoCGroup[iRec]; - - if (poRecord->GetType() != NRT_TEXTPOS) - continue; - - const int nNumTEXR = atoi(poRecord->GetField(9, 10)); - for (int iTEXR = 0; iTEXR < nNumTEXR; iTEXR++) - { - AddToIndexGroup(GetIndexedRecord( - NRT_TEXTREP, atoi(poRecord->GetField(11 + iTEXR * 12, - 16 + iTEXR * 12)))); - AddToIndexGroup(GetIndexedRecord( - NRT_GEOMETRY, atoi(poRecord->GetField(17 + iTEXR * 12, - 22 + iTEXR * 12)))); - } - } - - // Add all the attribute records. - if (poAnchor->GetLength() >= 10 + nSelCount * 12 + 2) - l_nAttCount = atoi( - poAnchor->GetField(11 + nSelCount * 12, 12 + nSelCount * 12)); - - for (int iAtt = 0; iAtt < l_nAttCount; iAtt++) - { - int iStart = 13 + nSelCount * 12 + 6 * iAtt; - - AddToIndexGroup(GetIndexedRecord( - NRT_ATTREC, atoi(poAnchor->GetField(iStart, iStart + 5)))); - } - } - - /* -------------------------------------------------------------------- */ - /* Handle NODEREC. */ - /* -------------------------------------------------------------------- */ - else if (poAnchor->GetType() == NRT_NODEREC) - { - AddToIndexGroup( - GetIndexedRecord(NRT_GEOMETRY, atoi(poAnchor->GetField(9, 14)))); - } - - /* -------------------------------------------------------------------- */ - /* Handle COLLECT. */ - /* -------------------------------------------------------------------- */ - else if (poAnchor->GetType() == NRT_COLLECT) - { - const int nParts = atoi(poAnchor->GetField(9, 12)); - if (nParts < 0) - return nullptr; - const int nAttOffset = 13 + nParts * 8; - int l_nAttCount = 0; - - if (poAnchor->GetLength() > nAttOffset + 2) - l_nAttCount = atoi(poAnchor->GetField(nAttOffset, nAttOffset + 1)); - - for (int iAtt = 0; iAtt < l_nAttCount; iAtt++) - { - const int iStart = nAttOffset + 2 + iAtt * 6; - - AddToIndexGroup(GetIndexedRecord( - NRT_ATTREC, atoi(poAnchor->GetField(iStart, iStart + 5)))); - } - } - - /* -------------------------------------------------------------------- */ - /* Handle POLYGON */ - /* -------------------------------------------------------------------- */ - else if (poAnchor->GetType() == NRT_POLYGON) - { - AddToIndexGroup( - GetIndexedRecord(NRT_CHAIN, atoi(poAnchor->GetField(9, 14)))); - - if (poAnchor->GetLength() >= 20) - AddToIndexGroup(GetIndexedRecord(NRT_GEOMETRY, - atoi(poAnchor->GetField(15, 20)))); - - // Attributes - int l_nAttCount = 0; - - if (poAnchor->GetLength() >= 22) - l_nAttCount = atoi(poAnchor->GetField(21, 22)); - - for (int iAtt = 0; iAtt < l_nAttCount; iAtt++) - { - AddToIndexGroup(GetIndexedRecord( - NRT_ATTREC, - atoi(poAnchor->GetField(23 + 6 * iAtt, 28 + 6 * iAtt)))); - } - } - /* -------------------------------------------------------------------- */ - /* Handle CPOLY */ - /* -------------------------------------------------------------------- */ - else if (poAnchor->GetType() == NRT_CPOLY) - { - int nPolyCount = atoi(poAnchor->GetField(9, 12)); - if (nPolyCount < 0) - return nullptr; - int nPostPoly = nPolyCount * 7 + 12; - - if (poAnchor->GetLength() >= nPostPoly + 6) - { - int nGeomId = - atoi(poAnchor->GetField(nPostPoly + 1, nPostPoly + 6)); - - AddToIndexGroup(GetIndexedRecord(NRT_GEOMETRY, nGeomId)); - } - - if (poAnchor->GetLength() >= nPostPoly + 8) - { - int l_nAttCount = - atoi(poAnchor->GetField(nPostPoly + 7, nPostPoly + 8)); - - for (int iAtt = 0; iAtt < l_nAttCount; iAtt++) - { - int nAttId = atoi(poAnchor->GetField( - nPostPoly + 9 + iAtt * 6, nPostPoly + 14 + iAtt * 6)); - AddToIndexGroup(GetIndexedRecord(NRT_ATTREC, nAttId)); - } - } - } - - return apoCGroup + 1; -} - -/************************************************************************/ -/* OverrideTileName() */ -/************************************************************************/ - -void NTFFileReader::OverrideTileName(const char *pszNewName) - -{ - CPLFree(pszTileName); - pszTileName = CPLStrdup(pszNewName); -} - -/************************************************************************/ -/* CacheAddByGeomId() */ -/* */ -/* Add a geometry to the geometry cache given its GEOMID as */ -/* the index. */ -/************************************************************************/ - -void NTFFileReader::CacheAddByGeomId(int nGeomId, OGRGeometry *poGeometry) - -{ - if (!bCacheLines) - return; - - CPLAssert(nGeomId >= 0); - - /* -------------------------------------------------------------------- */ - /* Grow the cache if it isn't large enough to hold the newly */ - /* requested geometry id. */ - /* -------------------------------------------------------------------- */ - if (nGeomId >= nLineCacheSize) - { - const int nNewSize = nGeomId + 100; - - papoLineCache = static_cast( - CPLRealloc(papoLineCache, sizeof(void *) * nNewSize)); - memset(papoLineCache + nLineCacheSize, 0, - sizeof(void *) * (nNewSize - nLineCacheSize)); - nLineCacheSize = nNewSize; - } - - /* -------------------------------------------------------------------- */ - /* Make a cloned copy of the geometry for the cache. */ - /* -------------------------------------------------------------------- */ - if (papoLineCache[nGeomId] != nullptr) - return; - - papoLineCache[nGeomId] = poGeometry->clone(); -} - -/************************************************************************/ -/* CacheGetByGeomId() */ -/************************************************************************/ - -OGRGeometry *NTFFileReader::CacheGetByGeomId(int nGeomId) - -{ - if (nGeomId < 0 || nGeomId >= nLineCacheSize) - return nullptr; - else - return papoLineCache[nGeomId]; -} - -/************************************************************************/ -/* CacheClean() */ -/************************************************************************/ - -void NTFFileReader::CacheClean() - -{ - for (int i = 0; i < nLineCacheSize; i++) - { - if (papoLineCache[i] != nullptr) - delete papoLineCache[i]; - } - if (papoLineCache != nullptr) - CPLFree(papoLineCache); - - nLineCacheSize = 0; - papoLineCache = nullptr; -} - -/************************************************************************/ -/* CacheLineGeometryInGroup() */ -/* */ -/* Run any line geometries in this group through the */ -/* ProcessGeometry() call just to ensure the line geometry will */ -/* be cached. */ -/************************************************************************/ - -void NTFFileReader::CacheLineGeometryInGroup(NTFRecord **papoGroup) - -{ - if (!bCacheLines) - return; - - for (int iRec = 0; papoGroup[iRec] != nullptr; iRec++) - { - if (papoGroup[iRec]->GetType() == NRT_GEOMETRY || - papoGroup[iRec]->GetType() == NRT_GEOMETRY3D) - { - OGRGeometry *poGeom = ProcessGeometry(papoGroup[iRec], nullptr); - if (poGeom != nullptr) - delete poGeom; - } - } -} - -/************************************************************************/ -/* FormPolygonFromCache() */ -/* */ -/* This method will attempt to find the line geometries */ -/* referenced by the GEOM_ID_OF_LINK ids of a feature in the */ -/* line cache (if available), and if so, assemble them into a */ -/* polygon. */ -/************************************************************************/ - -int NTFFileReader::FormPolygonFromCache(OGRFeature *poFeature) - -{ - if (!bCacheLines) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Collect all the linked lines. */ - /* -------------------------------------------------------------------- */ - int nLinkCount = 0; - const int *panLinks = - poFeature->GetFieldAsIntegerList("GEOM_ID_OF_LINK", &nLinkCount); - - if (panLinks == nullptr) - return FALSE; - - OGRGeometryCollection oLines; - - for (int i = 0; i < nLinkCount; i++) - { - OGRGeometry *poLine = CacheGetByGeomId(panLinks[i]); - if (poLine == nullptr) - { - oLines.removeGeometry(-1, FALSE); - return FALSE; - } - - oLines.addGeometryDirectly(poLine); - } - - /* -------------------------------------------------------------------- */ - /* Assemble into a polygon geometry. */ - /* -------------------------------------------------------------------- */ - OGRGeometry *poGeom = OGRGeometry::FromHandle(OGRBuildPolygonFromEdges( - (OGRGeometryH)&oLines, FALSE, FALSE, 0.1, nullptr)); - - poFeature->SetGeometryDirectly(poGeom); - - oLines.removeGeometry(-1, FALSE); - - return poGeom != nullptr; -} diff --git a/ogr/ogrsf_frmts/ntf/ntfrecord.cpp b/ogr/ogrsf_frmts/ntf/ntfrecord.cpp deleted file mode 100644 index e876f6d5d3f8..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntfrecord.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: NTFRecord class implementation. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ntf.h" -#include "cpl_conv.h" - -static int nFieldBufSize = 0; -static char *pszFieldBuf = nullptr; - -constexpr int MAX_RECORD_LEN = 160; - -/************************************************************************/ -/* NTFRecord() */ -/* */ -/* The constructor is where the record is read. This includes */ -/* transparent merging of continuation lines. */ -/************************************************************************/ - -NTFRecord::NTFRecord(VSILFILE *fp) : nType(99), nLength(0), pszData(nullptr) -{ - if (fp == nullptr) - return; - - /* ==================================================================== */ - /* Read lines until we get to one without a continuation mark. */ - /* ==================================================================== */ - char szLine[MAX_RECORD_LEN + 3] = {}; - int nNewLength = 0; - - do - { - nNewLength = ReadPhysicalLine(fp, szLine); - if (nNewLength == -1 || nNewLength == -2) - break; - - while (nNewLength > 0 && szLine[nNewLength - 1] == ' ') - szLine[--nNewLength] = '\0'; - - if (nNewLength < 2 || szLine[nNewLength - 1] != '%') - { - CPLError(CE_Failure, CPLE_AppDefined, - "Corrupt NTF record, missing end '%%'."); - CPLFree(pszData); - pszData = nullptr; - break; - } - - if (pszData == nullptr) - { - nLength = nNewLength - 2; - // coverity[overflow_sink] - pszData = static_cast(VSI_MALLOC_VERBOSE(nLength + 1)); - if (pszData == nullptr) - { - return; - } - memcpy(pszData, szLine, nLength); - pszData[nLength] = '\0'; - } - else - { - if (!STARTS_WITH_CI(szLine, "00") || nNewLength < 4) - { - CPLError(CE_Failure, CPLE_AppDefined, "Invalid line"); - VSIFree(pszData); - pszData = nullptr; - return; - } - - char *pszNewData = static_cast( - VSI_REALLOC_VERBOSE(pszData, nLength + (nNewLength - 4) + 1)); - if (pszNewData == nullptr) - { - VSIFree(pszData); - pszData = nullptr; - return; - } - - pszData = pszNewData; - memcpy(pszData + nLength, szLine + 2, nNewLength - 4); - nLength += nNewLength - 4; - pszData[nLength] = '\0'; - } - } while (szLine[nNewLength - 2] == '1'); - - /* -------------------------------------------------------------------- */ - /* Figure out the record type. */ - /* -------------------------------------------------------------------- */ - if (pszData != nullptr) - { - char szType[3]; - - strncpy(szType, pszData, 2); - szType[2] = '\0'; - - nType = atoi(szType); - } -} - -/************************************************************************/ -/* ~NTFRecord() */ -/************************************************************************/ - -NTFRecord::~NTFRecord() - -{ - CPLFree(pszData); - - if (pszFieldBuf != nullptr) - { - CPLFree(pszFieldBuf); - pszFieldBuf = nullptr; - nFieldBufSize = 0; - } -} - -/************************************************************************/ -/* ReadPhysicalLine() */ -/************************************************************************/ - -int NTFRecord::ReadPhysicalLine(VSILFILE *fp, char *pszLine) - -{ - /* -------------------------------------------------------------------- */ - /* Read enough data that we are sure we have a whole record. */ - /* -------------------------------------------------------------------- */ - int nRecordStart = static_cast(VSIFTellL(fp)); - const int nBytesRead = - static_cast(VSIFReadL(pszLine, 1, MAX_RECORD_LEN + 2, fp)); - - if (nBytesRead == 0) - { - if (VSIFEofL(fp)) - return -1; - else /* if (VSIFErrorL(fp)) */ - { - CPLError(CE_Failure, CPLE_AppDefined, - "Low level read error occurred while reading NTF file."); - return -2; - } - } - - /* -------------------------------------------------------------------- */ - /* Search for CR or LF. */ - /* -------------------------------------------------------------------- */ - int i = 0; // Used after for. - for (; i < nBytesRead; i++) - { - if (pszLine[i] == 10 || pszLine[i] == 13) - break; - } - - /* -------------------------------------------------------------------- */ - /* If we don't find EOL within 80 characters something has gone */ - /* badly wrong! */ - /* -------------------------------------------------------------------- */ - if (i == MAX_RECORD_LEN + 2) - { - CPLError(CE_Failure, CPLE_AppDefined, - "%d byte record too long for NTF format. " - "No line may be longer than 80 characters though up " - "to %d tolerated.", - nBytesRead, MAX_RECORD_LEN); - return -2; - } - - /* -------------------------------------------------------------------- */ - /* Trim CR/LF. */ - /* -------------------------------------------------------------------- */ - const int l_nLength = i; - const int nRecordEnd = - nRecordStart + i + - (pszLine[i + 1] == 10 || pszLine[i + 1] == 13 ? 2 : 1); - - pszLine[l_nLength] = '\0'; - - /* -------------------------------------------------------------------- */ - /* Restore read pointer to beginning of next record. */ - /* -------------------------------------------------------------------- */ - if (VSIFSeekL(fp, nRecordEnd, SEEK_SET) != 0) - return -1; - - return l_nLength; -} - -/************************************************************************/ -/* GetField() */ -/* */ -/* Note that the start position is 1 based, to match the */ -/* notation in the NTF document. The returned pointer is to an */ -/* internal buffer, but is zero terminated. */ -/************************************************************************/ - -const char *NTFRecord::GetField(int nStart, int nEnd) - -{ - const int nSize = nEnd - nStart + 1; - - if (pszData == nullptr) - return ""; - - /* -------------------------------------------------------------------- */ - /* Reallocate working buffer larger if needed. */ - /* -------------------------------------------------------------------- */ - if (nFieldBufSize < nSize + 1) - { - CPLFree(pszFieldBuf); - nFieldBufSize = nSize + 1; - pszFieldBuf = static_cast(CPLMalloc(nFieldBufSize)); - } - - /* -------------------------------------------------------------------- */ - /* Copy out desired data. */ - /* -------------------------------------------------------------------- */ - if (nStart + nSize > nLength + 1) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Attempt to read %d to %d, beyond the end of %d byte long\n" - "type `%2.2s' record.\n", - nStart, nEnd, nLength, pszData); - memset(pszFieldBuf, ' ', nSize); - pszFieldBuf[nSize] = '\0'; - } - else - { - strncpy(pszFieldBuf, pszData + nStart - 1, nSize); - pszFieldBuf[nSize] = '\0'; - } - - return pszFieldBuf; -} diff --git a/ogr/ogrsf_frmts/ntf/ntfstroke.cpp b/ogr/ogrsf_frmts/ntf/ntfstroke.cpp deleted file mode 100644 index 1cdb9ecd9a24..000000000000 --- a/ogr/ogrsf_frmts/ntf/ntfstroke.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/****************************************************************************** - * - * Project: NTF Translator - * Purpose: NTF Arc to polyline stroking code. This code is really generic, - * and might be moved into an OGR module at some point in the - * future. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2001, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include -#include "ntf.h" -#include "cpl_conv.h" -#include "cpl_string.h" - -#include -#include - -/************************************************************************/ -/* NTFArcCenterFromEdgePoints() */ -/* */ -/* Compute the center of an arc/circle from three edge points. */ -/************************************************************************/ - -int NTFArcCenterFromEdgePoints(double x_c0, double y_c0, double x_c1, - double y_c1, double x_c2, double y_c2, - double *x_center, double *y_center) - -{ - - /* -------------------------------------------------------------------- */ - /* Handle a degenerate case that occurs in OSNI products by */ - /* making some assumptions. If the first and third points are */ - /* the same assume they are intended to define a full circle, */ - /* and that the second point is on the opposite side of the */ - /* circle. */ - /* -------------------------------------------------------------------- */ - if (x_c0 == x_c2 && y_c0 == y_c2) - { - *x_center = (x_c0 + x_c1) * 0.5; - *y_center = (y_c0 + y_c1) * 0.5; - - return TRUE; - } - - /* -------------------------------------------------------------------- */ - /* Compute the inverse of the slopes connecting the first and */ - /* second points. Also compute the center point of the two */ - /* lines ... the point our crossing line will go through. */ - /* -------------------------------------------------------------------- */ - const double m1 = - (y_c1 - y_c0) != 0.0 ? (x_c0 - x_c1) / (y_c1 - y_c0) : 1e+10; - - const double x1 = (x_c0 + x_c1) * 0.5; - const double y1 = (y_c0 + y_c1) * 0.5; - - /* -------------------------------------------------------------------- */ - /* Compute the same for the second point compared to the third */ - /* point. */ - /* -------------------------------------------------------------------- */ - const double m2 = - (y_c2 - y_c1) != 0.0 ? (x_c1 - x_c2) / (y_c2 - y_c1) : 1e+10; - - const double x2 = (x_c1 + x_c2) * 0.5; - const double y2 = (y_c1 + y_c2) * 0.5; - - /* -------------------------------------------------------------------- */ - /* Turn these into the Ax+By+C = 0 form of the lines. */ - /* -------------------------------------------------------------------- */ - const double a1 = m1; - const double a2 = m2; - - const double b1 = -1.0; - const double b2 = -1.0; - - const double c1 = (y1 - m1 * x1); - const double c2 = (y2 - m2 * x2); - - /* -------------------------------------------------------------------- */ - /* Compute the intersection of the two lines through the center */ - /* of the circle, using Kramers rule. */ - /* -------------------------------------------------------------------- */ - if (a1 * b2 - a2 * b1 == 0.0) - return FALSE; - - const double det_inv = 1 / (a1 * b2 - a2 * b1); - - *x_center = (b1 * c2 - b2 * c1) * det_inv; - *y_center = (a2 * c1 - a1 * c2) * det_inv; - - return TRUE; -} - -/************************************************************************/ -/* NTFStrokeArcToOGRGeometry_Points() */ -/************************************************************************/ - -OGRGeometry *NTFStrokeArcToOGRGeometry_Points(double dfStartX, double dfStartY, - double dfAlongX, double dfAlongY, - double dfEndX, double dfEndY, - int nVertexCount) - -{ - double dfStartAngle = 0.0; - double dfEndAngle = 0.0; - double dfCenterX = 0.0; - double dfCenterY = 0.0; - double dfRadius = 0.0; - - if (!NTFArcCenterFromEdgePoints(dfStartX, dfStartY, dfAlongX, dfAlongY, - dfEndX, dfEndY, &dfCenterX, &dfCenterY)) - return nullptr; - - if (dfStartX == dfEndX && dfStartY == dfEndY) - { - dfStartAngle = 0.0; - dfEndAngle = 360.0; - } - else - { - double dfDeltaX = dfStartX - dfCenterX; - double dfDeltaY = dfStartY - dfCenterY; - dfStartAngle = atan2(dfDeltaY, dfDeltaX) * 180.0 / M_PI; - - dfDeltaX = dfAlongX - dfCenterX; - dfDeltaY = dfAlongY - dfCenterY; - double dfAlongAngle = atan2(dfDeltaY, dfDeltaX) * 180.0 / M_PI; - - dfDeltaX = dfEndX - dfCenterX; - dfDeltaY = dfEndY - dfCenterY; - dfEndAngle = atan2(dfDeltaY, dfDeltaX) * 180.0 / M_PI; - - while (dfAlongAngle < dfStartAngle) - dfAlongAngle += 360.0; - - while (dfEndAngle < dfAlongAngle) - dfEndAngle += 360.0; - - if (dfEndAngle - dfStartAngle > 360.0) - { - std::swap(dfStartAngle, dfEndAngle); - - while (dfEndAngle < dfStartAngle) - dfStartAngle -= 360.0; - } - } - - dfRadius = sqrt((dfCenterX - dfStartX) * (dfCenterX - dfStartX) + - (dfCenterY - dfStartY) * (dfCenterY - dfStartY)); - - return NTFStrokeArcToOGRGeometry_Angles( - dfCenterX, dfCenterY, dfRadius, dfStartAngle, dfEndAngle, nVertexCount); -} - -/************************************************************************/ -/* NTFStrokeArcToOGRGeometry_Angles() */ -/************************************************************************/ - -OGRGeometry *NTFStrokeArcToOGRGeometry_Angles(double dfCenterX, - double dfCenterY, double dfRadius, - double dfStartAngle, - double dfEndAngle, - int nVertexCount) - -{ - OGRLineString *poLine = new OGRLineString; - - nVertexCount = std::max(2, nVertexCount); - const double dfSlice = (dfEndAngle - dfStartAngle) / (nVertexCount - 1); - - poLine->setNumPoints(nVertexCount); - - for (int iPoint = 0; iPoint < nVertexCount; iPoint++) - { - const double dfAngle = (dfStartAngle + iPoint * dfSlice) * M_PI / 180.0; - - const double dfArcX = dfCenterX + cos(dfAngle) * dfRadius; - const double dfArcY = dfCenterY + sin(dfAngle) * dfRadius; - - poLine->setPoint(iPoint, dfArcX, dfArcY); - } - - return poLine; -} diff --git a/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp b/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp deleted file mode 100644 index 5c499f9585d9..000000000000 --- a/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/****************************************************************************** - * - * Project: UK NTF Reader - * Purpose: Implements OGRNTFDataSource class - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ntf.h" -#include "cpl_conv.h" -#include "cpl_string.h" - -/************************************************************************/ -/* OGRNTFDataSource() */ -/************************************************************************/ - -OGRNTFDataSource::OGRNTFDataSource() - : nLayers(0), papoLayers(nullptr), poFCLayer(nullptr), iCurrentFC(0), - iCurrentReader(-1), nCurrentPos(0), nCurrentFID(0), nNTFFileCount(0), - papoNTFFileReader(nullptr), nFCCount(0), papszFCNum(nullptr), - papszFCName(nullptr), - poSpatialRef(new OGRSpatialReference( - "PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\"," - "DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646," - "AUTHORITY[\"EPSG\",\"7001\"]],AUTHORITY[\"EPSG\",\"6277\"]]," - "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," - "UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4277\"]]," - "PROJECTION[\"Transverse_Mercator\"]," - "PARAMETER[\"latitude_of_origin\",49]," - "PARAMETER[\"central_meridian\",-2]," - "PARAMETER[\"scale_factor\",0.999601272]," - "PARAMETER[\"false_easting\",400000]," - "PARAMETER[\"false_northing\",-100000]," - "UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]]," - "AUTHORITY[\"EPSG\",\"27700\"]]")), - papszOptions(nullptr) -{ - poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - - /* -------------------------------------------------------------------- */ - /* Allow initialization of options from the environment. */ - /* -------------------------------------------------------------------- */ - if (getenv("OGR_NTF_OPTIONS") != nullptr) - { - papszOptions = CSLTokenizeStringComplex(getenv("OGR_NTF_OPTIONS"), ",", - FALSE, FALSE); - } -} - -/************************************************************************/ -/* ~OGRNTFDataSource() */ -/************************************************************************/ - -OGRNTFDataSource::~OGRNTFDataSource() - -{ - for (int i = 0; i < nNTFFileCount; i++) - delete papoNTFFileReader[i]; - - CPLFree(papoNTFFileReader); - - for (int i = 0; i < nLayers; i++) - delete papoLayers[i]; - - if (poFCLayer != nullptr) - delete poFCLayer; - - CPLFree(papoLayers); - - CSLDestroy(papszOptions); - - CSLDestroy(papszFCNum); - CSLDestroy(papszFCName); - - if (poSpatialRef) - poSpatialRef->Release(); -} - -/************************************************************************/ -/* TestCapability() */ -/************************************************************************/ - -int OGRNTFDataSource::TestCapability(const char *pszCap) - -{ - if (EQUAL(pszCap, ODsCZGeometries)) - return true; - - return false; -} - -/************************************************************************/ -/* GetNamedLayer() */ -/************************************************************************/ - -OGRNTFLayer *OGRNTFDataSource::GetNamedLayer(const char *pszNameIn) - -{ - for (int i = 0; i < nLayers; i++) - { - if (EQUAL(papoLayers[i]->GetLayerDefn()->GetName(), pszNameIn)) - return static_cast(papoLayers[i]); - } - - return nullptr; -} - -/************************************************************************/ -/* AddLayer() */ -/************************************************************************/ - -void OGRNTFDataSource::AddLayer(OGRLayer *poNewLayer) - -{ - papoLayers = static_cast( - CPLRealloc(papoLayers, sizeof(void *) * ++nLayers)); - - papoLayers[nLayers - 1] = poNewLayer; -} - -/************************************************************************/ -/* GetLayer() */ -/************************************************************************/ - -OGRLayer *OGRNTFDataSource::GetLayer(int iLayer) - -{ - if (iLayer < 0 || iLayer > nLayers) - return nullptr; - else if (iLayer == nLayers) - return poFCLayer; - else - return papoLayers[iLayer]; -} - -/************************************************************************/ -/* GetLayerCount() */ -/************************************************************************/ - -int OGRNTFDataSource::GetLayerCount() - -{ - if (poFCLayer == nullptr) - return nLayers; - else - return nLayers + 1; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -int OGRNTFDataSource::Open(const char *pszFilename, int bTestOpen, - char **papszLimitedFileList) - -{ - VSIStatBufL stat; - char **papszFileList = nullptr; - - /* -------------------------------------------------------------------- */ - /* Is the given path a directory or a regular file? */ - /* -------------------------------------------------------------------- */ - if (VSIStatL(pszFilename, &stat) != 0 || - (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode))) - { - if (!bTestOpen) - CPLError(CE_Failure, CPLE_AppDefined, - "%s is neither a file or directory, NTF access failed.\n", - pszFilename); - - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Build a list of filenames we figure are NTF files. */ - /* -------------------------------------------------------------------- */ - if (VSI_ISREG(stat.st_mode)) - { - papszFileList = CSLAddString(nullptr, pszFilename); - } - else - { - char **candidateFileList = VSIReadDir(pszFilename); - - for (int i = 0; - candidateFileList != nullptr && candidateFileList[i] != nullptr; - i++) - { - if (papszLimitedFileList != nullptr && - CSLFindString(papszLimitedFileList, candidateFileList[i]) == -1) - { - continue; - } - - if (strlen(candidateFileList[i]) > 4 && - STARTS_WITH_CI(candidateFileList[i] + - strlen(candidateFileList[i]) - 4, - ".ntf")) - { - char fullFilename[2048]; - - snprintf(fullFilename, sizeof(fullFilename), "%s%c%s", - pszFilename, -#ifdef _WIN32 - '\\', -#else - '/', -#endif - candidateFileList[i]); - - papszFileList = CSLAddString(papszFileList, fullFilename); - } - } - - CSLDestroy(candidateFileList); - - if (CSLCount(papszFileList) == 0) - { - if (!bTestOpen) - CPLError(CE_Failure, CPLE_OpenFailed, - "No candidate NTF files (.ntf) found in\n" - "directory: %s", - pszFilename); - CSLDestroy(papszFileList); - return FALSE; - } - } - - /* -------------------------------------------------------------------- */ - /* Loop over all these files trying to open them. In testopen */ - /* mode we first read the first 80 characters, to verify that */ - /* it looks like an NTF file. Note that we don't keep the file */ - /* open ... we don't want to occupy a lot of file handles when */ - /* handling a whole directory. */ - /* -------------------------------------------------------------------- */ - papoNTFFileReader = static_cast( - CPLCalloc(sizeof(void *), CSLCount(papszFileList))); - - for (int i = 0; papszFileList != nullptr && papszFileList[i] != nullptr; - i++) - { - if (bTestOpen) - { - VSILFILE *fp = VSIFOpenL(papszFileList[i], "rb"); - if (fp == nullptr) - continue; - - char szHeader[80] = {}; - if (VSIFReadL(szHeader, 80, 1, fp) < 1) - { - VSIFCloseL(fp); - continue; - } - - VSIFCloseL(fp); - - if (!STARTS_WITH_CI(szHeader, "01")) - continue; - - int j = 0; // Used after for. - for (; j < 80; j++) - { - if (szHeader[j] == 10 || szHeader[j] == 13) - break; - } - - if (j == 80 || (j > 0 && szHeader[j - 1] != '%')) - continue; - } - - NTFFileReader *poFR = new NTFFileReader(this); - - if (!poFR->Open(papszFileList[i])) - { - delete poFR; - CSLDestroy(papszFileList); - - return FALSE; - } - - poFR->SetBaseFID(nNTFFileCount * 1000000 + 1); - poFR->Close(); - - EnsureTileNameUnique(poFR); - - papoNTFFileReader[nNTFFileCount++] = poFR; - } - - CSLDestroy(papszFileList); - - if (nNTFFileCount == 0) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Establish generic layers. */ - /* -------------------------------------------------------------------- */ - EstablishGenericLayers(); - - /* -------------------------------------------------------------------- */ - /* Loop over all the files, collecting a unique feature class */ - /* listing. */ - /* -------------------------------------------------------------------- */ - for (int iSrcFile = 0; iSrcFile < nNTFFileCount; iSrcFile++) - { - NTFFileReader *poSrcReader = papoNTFFileReader[iSrcFile]; - - for (int iSrcFC = 0; iSrcFC < poSrcReader->GetFCCount(); iSrcFC++) - { - char *pszSrcFCName = nullptr; - char *pszSrcFCNum = nullptr; - - poSrcReader->GetFeatureClass(iSrcFC, &pszSrcFCNum, &pszSrcFCName); - - int iDstFC = 0; - for (; iDstFC < nFCCount; iDstFC++) - { - if (EQUAL(pszSrcFCNum, papszFCNum[iDstFC])) - break; - } - - if (iDstFC >= nFCCount) - { - nFCCount++; - papszFCNum = CSLAddString(papszFCNum, pszSrcFCNum); - papszFCName = CSLAddString(papszFCName, pszSrcFCName); - } - } - } - - /* -------------------------------------------------------------------- */ - /* Create a new layer specifically for feature classes. */ - /* -------------------------------------------------------------------- */ - if (nFCCount > 0) - poFCLayer = new OGRNTFFeatureClassLayer(this); - else - poFCLayer = nullptr; - - return TRUE; -} - -/************************************************************************/ -/* ResetReading() */ -/* */ -/* Cleanup, and start over. */ -/************************************************************************/ - -void OGRNTFDataSource::ResetReading() - -{ - for (int i = 0; i < nNTFFileCount; i++) - papoNTFFileReader[i]->Close(); - - iCurrentReader = -1; - nCurrentPos = (vsi_l_offset)-1; - nCurrentFID = 1; - iCurrentFC = 0; -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -OGRFeature *OGRNTFDataSource::GetNextFeature(OGRLayer **ppoBelongingLayer, - double *pdfProgressPct, - GDALProgressFunc /* pfnProgress */, - void * /* pProgressData */) - -{ - if (pdfProgressPct != nullptr) - *pdfProgressPct = 0.0; - if (ppoBelongingLayer != nullptr) - *ppoBelongingLayer = nullptr; - - OGRFeature *poFeature = nullptr; - - /* -------------------------------------------------------------------- */ - /* If we have already read all the conventional features, we */ - /* should try and return feature class features. */ - /* -------------------------------------------------------------------- */ - if (iCurrentReader == nNTFFileCount) - { - if (iCurrentFC < nFCCount) - return poFCLayer->GetFeature(iCurrentFC++); - else - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Do we need to open a file? */ - /* -------------------------------------------------------------------- */ - if (iCurrentReader == -1) - { - iCurrentReader++; - nCurrentPos = (vsi_l_offset)-1; - } - - if (papoNTFFileReader[iCurrentReader]->GetFP() == nullptr) - { - papoNTFFileReader[iCurrentReader]->Open(); - } - - /* -------------------------------------------------------------------- */ - /* Ensure we are reading on from the same point we were reading */ - /* from for the last feature, even if some other access */ - /* mechanism has moved the file pointer. */ - /* -------------------------------------------------------------------- */ - if (nCurrentPos != (vsi_l_offset)-1) - papoNTFFileReader[iCurrentReader]->SetFPPos(nCurrentPos, nCurrentFID); - - /* -------------------------------------------------------------------- */ - /* Read a feature. If we get NULL the file must be all */ - /* consumed, advance to the next file. */ - /* -------------------------------------------------------------------- */ - poFeature = papoNTFFileReader[iCurrentReader]->ReadOGRFeature(); - if (poFeature == nullptr) - { - papoNTFFileReader[iCurrentReader]->Close(); - if (GetOption("CACHING") != nullptr && - EQUAL(GetOption("CACHING"), "OFF")) - papoNTFFileReader[iCurrentReader]->DestroyIndex(); - - iCurrentReader++; - nCurrentPos = (vsi_l_offset)-1; - nCurrentFID = 1; - - poFeature = GetNextFeature(nullptr, nullptr, nullptr, nullptr); - } - else - { - papoNTFFileReader[iCurrentReader]->GetFPPos(&nCurrentPos, &nCurrentFID); - } - - return poFeature; -} - -/************************************************************************/ -/* GetFeatureClass() */ -/************************************************************************/ - -int OGRNTFDataSource::GetFeatureClass(int iFCIndex, char **ppszFCId, - char **ppszFCName) - -{ - if (iFCIndex < 0 || iFCIndex >= nFCCount) - { - *ppszFCId = nullptr; - *ppszFCName = nullptr; - return FALSE; - } - else - { - *ppszFCId = papszFCNum[iFCIndex]; - *ppszFCName = papszFCName[iFCIndex]; - return TRUE; - } -} - -/************************************************************************/ -/* SetOptions() */ -/************************************************************************/ - -void OGRNTFDataSource::SetOptionList(char **papszNewOptions) - -{ - CSLDestroy(papszOptions); - papszOptions = CSLDuplicate(papszNewOptions); -} - -/************************************************************************/ -/* GetOption() */ -/************************************************************************/ - -const char *OGRNTFDataSource::GetOption(const char *pszOption) - -{ - return CSLFetchNameValue(papszOptions, pszOption); -} - -/************************************************************************/ -/* EnsureTileNameUnique() */ -/* */ -/* This method is called with an NTFFileReader to ensure that */ -/* its tilename is unique relative to all the readers already */ -/* assigned to this data source. If not, a unique name is */ -/* selected for it and assigned. This method should not be */ -/* called with readers that are already attached to the data */ -/* source. */ -/************************************************************************/ - -void OGRNTFDataSource::EnsureTileNameUnique(NTFFileReader *poNewReader) - -{ - int iSequenceNumber = -1; - bool bIsUnique = false; - char szCandidateName[12] = {}; - - do - { - bIsUnique = TRUE; - if (iSequenceNumber++ == -1) - strncpy(szCandidateName, poNewReader->GetTileName(), - sizeof(szCandidateName) - 1); - else - snprintf(szCandidateName, sizeof(szCandidateName), "%010d", - iSequenceNumber); - - for (int iReader = 0; iReader < nNTFFileCount && bIsUnique; iReader++) - { - const char *pszTileName = GetFileReader(iReader)->GetTileName(); - if (pszTileName != nullptr && - strcmp(szCandidateName, pszTileName) == 0) - { - bIsUnique = FALSE; - } - } - } while (!bIsUnique); - - if (iSequenceNumber > 0) - { - poNewReader->OverrideTileName(szCandidateName); - CPLError(CE_Warning, CPLE_AppDefined, - "Forcing TILE_REF to `%s' on file %s\n" - "to avoid conflict with other tiles in this data source.", - szCandidateName, poNewReader->GetFilename()); - } -} diff --git a/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp b/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp deleted file mode 100644 index 5d5e3a1178ab..000000000000 --- a/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/****************************************************************************** - * - * Project: UK NTF Reader - * Purpose: Implements OGRNTFDriver - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ntf.h" -#include "cpl_conv.h" - -/************************************************************************/ -/* ==================================================================== */ -/* OGRNTFDriver */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -static GDALDataset *OGRNTFDriverOpen(GDALOpenInfo *poOpenInfo) - -{ - if (!poOpenInfo->bStatOK) - return nullptr; - - if (poOpenInfo->nHeaderBytes != 0) - { - if (poOpenInfo->nHeaderBytes < 80) - return nullptr; - const char *pszHeader = (const char *)poOpenInfo->pabyHeader; - if (!STARTS_WITH_CI(pszHeader, "01")) - return nullptr; - - int j = 0; // Used after for. - for (; j < 80; j++) - { - if (pszHeader[j] == 10 || pszHeader[j] == 13) - break; - } - - if (j == 80 || pszHeader[j - 1] != '%') - return nullptr; - } - - OGRNTFDataSource *poDS = new OGRNTFDataSource; - if (!poDS->Open(poOpenInfo->pszFilename, TRUE)) - { - delete poDS; - poDS = nullptr; - } - - if (poDS != nullptr && poOpenInfo->eAccess == GA_Update) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "NTF Driver doesn't support update."); - delete poDS; - poDS = nullptr; - } - - return poDS; -} - -/************************************************************************/ -/* RegisterOGRNTF() */ -/************************************************************************/ - -void RegisterOGRNTF() - -{ - if (GDALGetDriverByName("UK .NTF") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("UK .NTF"); - poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "UK .NTF"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/ntf.html"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); - - poDriver->pfnOpen = OGRNTFDriverOpen; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp b/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp deleted file mode 100644 index 28cffb8a6912..000000000000 --- a/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/****************************************************************************** - * - * Project: UK NTF Reader - * Purpose: Implements OGRNTFFeatureClassLayer class. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ntf.h" -#include "cpl_conv.h" - -/************************************************************************/ -/* OGRNTFFeatureClassLayer() */ -/* */ -/* Note that the OGRNTFLayer assumes ownership of the passed */ -/* OGRFeatureDefn object. */ -/************************************************************************/ - -OGRNTFFeatureClassLayer::OGRNTFFeatureClassLayer(OGRNTFDataSource *poDSIn) - : poFeatureDefn(new OGRFeatureDefn("FEATURE_CLASSES")), - poFilterGeom(nullptr), poDS(poDSIn), iCurrentFC(0) -{ - /* -------------------------------------------------------------------- */ - /* Establish the schema. */ - /* -------------------------------------------------------------------- */ - SetDescription(poFeatureDefn->GetName()); - poFeatureDefn->SetGeomType(wkbNone); - poFeatureDefn->Reference(); - - OGRFieldDefn oFCNum("FEAT_CODE", OFTString); - - oFCNum.SetWidth(4); - poFeatureDefn->AddFieldDefn(&oFCNum); - - OGRFieldDefn oFCName("FC_NAME", OFTString); - - oFCNum.SetWidth(80); - poFeatureDefn->AddFieldDefn(&oFCName); -} - -/************************************************************************/ -/* ~OGRNTFFeatureClassLayer() */ -/************************************************************************/ - -OGRNTFFeatureClassLayer::~OGRNTFFeatureClassLayer() - -{ - if (poFeatureDefn) - poFeatureDefn->Release(); - - if (poFilterGeom != nullptr) - delete poFilterGeom; -} - -/************************************************************************/ -/* SetSpatialFilter() */ -/************************************************************************/ - -void OGRNTFFeatureClassLayer::SetSpatialFilter(OGRGeometry *poGeomIn) - -{ - if (poFilterGeom != nullptr) - { - delete poFilterGeom; - poFilterGeom = nullptr; - } - - if (poGeomIn != nullptr) - poFilterGeom = poGeomIn->clone(); -} - -/************************************************************************/ -/* ResetReading() */ -/************************************************************************/ - -void OGRNTFFeatureClassLayer::ResetReading() - -{ - iCurrentFC = 0; -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -OGRFeature *OGRNTFFeatureClassLayer::GetNextFeature() - -{ - if (iCurrentFC >= GetFeatureCount()) - return nullptr; - - return GetFeature((long)iCurrentFC++); -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ - -OGRFeature *OGRNTFFeatureClassLayer::GetFeature(GIntBig nFeatureId) - -{ - char *pszFCName, *pszFCId; - - if (nFeatureId < 0 || nFeatureId >= poDS->GetFCCount()) - return nullptr; - - poDS->GetFeatureClass((int)nFeatureId, &pszFCId, &pszFCName); - - /* -------------------------------------------------------------------- */ - /* Create a corresponding feature. */ - /* -------------------------------------------------------------------- */ - OGRFeature *poFeature = new OGRFeature(poFeatureDefn); - - poFeature->SetField(0, pszFCId); - poFeature->SetField(1, pszFCName); - poFeature->SetFID(nFeatureId); - - return poFeature; -} - -/************************************************************************/ -/* GetFeatureCount() */ -/* */ -/* If a spatial filter is in effect, we turn control over to */ -/* the generic counter. Otherwise we return the total count. */ -/* Eventually we should consider implementing a more efficient */ -/* way of counting features matching a spatial query. */ -/************************************************************************/ - -GIntBig OGRNTFFeatureClassLayer::GetFeatureCount(CPL_UNUSED int bForce) -{ - return poDS->GetFCCount(); -} - -/************************************************************************/ -/* TestCapability() */ -/************************************************************************/ - -int OGRNTFFeatureClassLayer::TestCapability(const char *pszCap) - -{ - if (EQUAL(pszCap, OLCRandomRead)) - return TRUE; - - else if (EQUAL(pszCap, OLCSequentialWrite) || EQUAL(pszCap, OLCRandomWrite)) - return FALSE; - - else if (EQUAL(pszCap, OLCFastFeatureCount)) - return TRUE; - - else if (EQUAL(pszCap, OLCFastSpatialFilter)) - return TRUE; - - else - return FALSE; -} diff --git a/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp b/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp deleted file mode 100644 index 48a3ad444cbc..000000000000 --- a/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/****************************************************************************** - * - * Project: UK NTF Reader - * Purpose: Implements OGRNTFLayer class. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ntf.h" -#include "cpl_conv.h" - -/************************************************************************/ -/* OGRNTFLayer() */ -/* */ -/* Note that the OGRNTFLayer assumes ownership of the passed */ -/* OGRFeatureDefn object. */ -/************************************************************************/ - -OGRNTFLayer::OGRNTFLayer(OGRNTFDataSource *poDSIn, - OGRFeatureDefn *poFeatureDefine, - NTFFeatureTranslator pfnTranslatorIn) - : poFeatureDefn(poFeatureDefine), pfnTranslator(pfnTranslatorIn), - poDS(poDSIn), iCurrentReader(-1), nCurrentPos((vsi_l_offset)-1), - nCurrentFID(1) -{ - SetDescription(poFeatureDefn->GetName()); -} - -/************************************************************************/ -/* ~OGRNTFLayer() */ -/************************************************************************/ - -OGRNTFLayer::~OGRNTFLayer() - -{ - if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr) - { - CPLDebug("Mem", "%d features read on layer '%s'.", (int)m_nFeaturesRead, - poFeatureDefn->GetName()); - } - - if (poFeatureDefn) - poFeatureDefn->Release(); -} - -/************************************************************************/ -/* ResetReading() */ -/************************************************************************/ - -void OGRNTFLayer::ResetReading() - -{ - iCurrentReader = -1; - nCurrentPos = (vsi_l_offset)-1; - nCurrentFID = 1; -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -OGRFeature *OGRNTFLayer::GetNextFeature() - -{ - OGRFeature *poFeature = nullptr; - - /* -------------------------------------------------------------------- */ - /* Have we processed all features already? */ - /* -------------------------------------------------------------------- */ - if (iCurrentReader == poDS->GetFileCount()) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Do we need to open a file? */ - /* -------------------------------------------------------------------- */ - if (iCurrentReader == -1) - { - iCurrentReader++; - nCurrentPos = (vsi_l_offset)-1; - } - - NTFFileReader *poCurrentReader = poDS->GetFileReader(iCurrentReader); - if (poCurrentReader->GetFP() == nullptr) - { - poCurrentReader->Open(); - } - - /* -------------------------------------------------------------------- */ - /* Ensure we are reading on from the same point we were reading */ - /* from for the last feature, even if some other access */ - /* mechanism has moved the file pointer. */ - /* -------------------------------------------------------------------- */ - if (nCurrentPos != (vsi_l_offset)-1) - poCurrentReader->SetFPPos(nCurrentPos, nCurrentFID); - else - poCurrentReader->Reset(); - - /* -------------------------------------------------------------------- */ - /* Read features till we find one that satisfies our current */ - /* spatial criteria. */ - /* -------------------------------------------------------------------- */ - while (true) - { - poFeature = poCurrentReader->ReadOGRFeature(this); - if (poFeature == nullptr) - break; - - m_nFeaturesRead++; - - if ((m_poFilterGeom == nullptr || - poFeature->GetGeometryRef() == nullptr || - FilterGeometry(poFeature->GetGeometryRef())) && - (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature))) - break; - - delete poFeature; - } - - /* -------------------------------------------------------------------- */ - /* If we get NULL the file must be all consumed, advance to the */ - /* next file that contains features for this layer. */ - /* -------------------------------------------------------------------- */ - if (poFeature == nullptr) - { - poCurrentReader->Close(); - - if (poDS->GetOption("CACHING") != nullptr && - EQUAL(poDS->GetOption("CACHING"), "OFF")) - { - poCurrentReader->DestroyIndex(); - } - - do - { - iCurrentReader++; - } while (iCurrentReader < poDS->GetFileCount() && - !poDS->GetFileReader(iCurrentReader)->TestForLayer(this)); - - nCurrentPos = (vsi_l_offset)-1; - nCurrentFID = 1; - - poFeature = GetNextFeature(); - } - else - { - poCurrentReader->GetFPPos(&nCurrentPos, &nCurrentFID); - } - - return poFeature; -} - -/************************************************************************/ -/* TestCapability() */ -/************************************************************************/ - -int OGRNTFLayer::TestCapability(const char *pszCap) - -{ - if (EQUAL(pszCap, OLCZGeometries)) - return TRUE; - - return FALSE; -} - -/************************************************************************/ -/* FeatureTranslate() */ -/************************************************************************/ - -OGRFeature *OGRNTFLayer::FeatureTranslate(NTFFileReader *poReader, - NTFRecord **papoGroup) - -{ - if (pfnTranslator == nullptr) - return nullptr; - - return pfnTranslator(poReader, this, papoGroup); -} diff --git a/ogr/ogrsf_frmts/ogdi/CMakeLists.txt b/ogr/ogrsf_frmts/ogdi/CMakeLists.txt deleted file mode 100644 index b5ca93556c4f..000000000000 --- a/ogr/ogrsf_frmts/ogdi/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_gdal_driver(TARGET ogr_OGDI - SOURCES - ogrogdi.h - ogrogdidatasource.cpp - ogrogdidriver.cpp - ogrogdilayer.cpp - CORE_SOURCES - ogrogdidrivercore.cpp - PLUGIN_CAPABLE - NO_SHARED_SYMBOL_WITH_CORE) - -if(NOT TARGET ogr_OGDI) - return() -endif() - -gdal_standard_includes(ogr_OGDI) -gdal_target_link_libraries(ogr_OGDI PRIVATE PROJ::proj OGDI::OGDI) diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdi.h b/ogr/ogrsf_frmts/ogdi/ogrogdi.h deleted file mode 100644 index cee6b3ccbdf1..000000000000 --- a/ogr/ogrsf_frmts/ogdi/ogrogdi.h +++ /dev/null @@ -1,146 +0,0 @@ -/****************************************************************************** - * - * Project: OGDI Bridge - * Purpose: Private definitions within the OGDI driver to implement - * integration with OGR. - * Author: Daniel Morissette, danmo@videotron.ca - * (Based on some code contributed by Frank Warmerdam :) - * - ****************************************************************************** - * Copyright (c) 2000, Daniel Morissette - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef OGDOGDI_H_INCLUDED -#define OGDOGDI_H_INCLUDED - -#include -extern "C" -{ -/* Older versions of OGDI have register keywords as qualifier for arguments - * of functions, which is illegal in C++17 */ -#define register -#include "ecs.h" -#undef register -} -#include "ogrsf_frmts.h" - -/************************************************************************/ -/* OGROGDILayer */ -/************************************************************************/ -class OGROGDIDataSource; - -class OGROGDILayer final : public OGRLayer -{ - OGROGDIDataSource *m_poODS; - int m_nClientID; - char *m_pszOGDILayerName; - ecs_Family m_eFamily; - - OGRFeatureDefn *m_poFeatureDefn; - OGRSpatialReference *m_poSpatialRef; - ecs_Region m_sFilterBounds; - - int m_iNextShapeId; - int m_nTotalShapeCount; - int m_nFilteredOutShapes; - - OGRFeature *GetNextRawFeature(); - - public: - OGROGDILayer(OGROGDIDataSource *, const char *, ecs_Family); - virtual ~OGROGDILayer(); - - virtual void SetSpatialFilter(OGRGeometry *) override; - - virtual void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override - { - OGRLayer::SetSpatialFilter(iGeomField, poGeom); - } - - virtual OGRErr SetAttributeFilter(const char *pszQuery) override; - - void ResetReading() override; - OGRFeature *GetNextFeature() override; - - OGRFeature *GetFeature(GIntBig nFeatureId) override; - - OGRFeatureDefn *GetLayerDefn() override - { - return m_poFeatureDefn; - } - - GIntBig GetFeatureCount(int) override; - - int TestCapability(const char *) override; - - private: - void BuildFeatureDefn(); -}; - -/************************************************************************/ -/* OGROGDIDataSource */ -/************************************************************************/ - -class OGROGDIDataSource final : public GDALDataset -{ - OGROGDILayer **m_papoLayers; - int m_nLayers; - - int m_nClientID; - - ecs_Region m_sGlobalBounds; - OGRSpatialReference *m_poSpatialRef; - - OGROGDILayer *m_poCurrentLayer; - - int m_bLaunderLayerNames; - - void IAddLayer(const char *pszLayerName, ecs_Family eFamily); - - public: - OGROGDIDataSource(); - ~OGROGDIDataSource(); - - int Open(const char *); - - int GetLayerCount() override - { - return m_nLayers; - } - - OGRLayer *GetLayer(int) override; - - ecs_Region *GetGlobalBounds() - { - return &m_sGlobalBounds; - } - - OGRSpatialReference *DSGetSpatialRef() - { - return m_poSpatialRef; - } - - int GetClientID() - { - return m_nClientID; - } - - OGROGDILayer *GetCurrentLayer() - { - return m_poCurrentLayer; - } - - void SetCurrentLayer(OGROGDILayer *poLayer) - { - m_poCurrentLayer = poLayer; - } - - int LaunderLayerNames() - { - return m_bLaunderLayerNames; - } -}; - -#endif /* OGDOGDI_H_INCLUDED */ diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp deleted file mode 100644 index 274072c9b6e3..000000000000 --- a/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/****************************************************************************** - * - * Project: OGDI Bridge - * Purpose: Implements OGROGDIDataSource class. - * Author: Daniel Morissette, danmo@videotron.ca - * (Based on some code contributed by Frank Warmerdam :) - * - ****************************************************************************** - * Copyright (c) 2000, Daniel Morissette - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogrogdi.h" - -#include "cpl_conv.h" -#include "cpl_string.h" - -/************************************************************************/ -/* OGROGDIDataSource() */ -/************************************************************************/ - -OGROGDIDataSource::OGROGDIDataSource() - : m_papoLayers(nullptr), m_nLayers(0), m_nClientID(-1), - m_poSpatialRef(nullptr), m_poCurrentLayer(nullptr), - m_bLaunderLayerNames( - CPLTestBool(CPLGetConfigOption("OGR_OGDI_LAUNDER_LAYER_NAMES", "NO"))) -{ - m_sGlobalBounds.north = 0.0; - m_sGlobalBounds.south = 0.0; - m_sGlobalBounds.east = 0.0; - m_sGlobalBounds.west = 0.0; - m_sGlobalBounds.ns_res = 0.0; - m_sGlobalBounds.ew_res = 0.0; -} - -/************************************************************************/ -/* ~OGROGDIDataSource() */ -/************************************************************************/ - -OGROGDIDataSource::~OGROGDIDataSource() - -{ - for (int i = 0; i < m_nLayers; i++) - delete m_papoLayers[i]; - CPLFree(m_papoLayers); - - if (m_nClientID != -1) - { - ecs_Result *psResult = cln_DestroyClient(m_nClientID); - ecs_CleanUp(psResult); - } - - if (m_poSpatialRef) - m_poSpatialRef->Release(); -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -int OGROGDIDataSource::Open(const char *pszNewName) - -{ - CPLAssert(m_nLayers == 0); - - /* -------------------------------------------------------------------- */ - /* Parse the dataset name. */ - /* i.e. */ - /* gltp:////[::] */ - /* */ - /* Where is one of: Line, Area, Point, and Text */ - /* -------------------------------------------------------------------- */ - if (!STARTS_WITH_CI(pszNewName, "gltp:")) - return FALSE; - - char *pszWorkingName = CPLStrdup(pszNewName); - - char *pszFamily = strrchr(pszWorkingName, ':'); - CPLAssert(pszFamily); - - // Don't treat drive name colon as family separator. It is assumed - // that drive names are on character long, and preceded by a - // forward or backward slash. - if (pszFamily < pszWorkingName + 2 || pszFamily[-2] == '/' || - pszFamily[-2] == '\\') - pszFamily = nullptr; - - char *pszLyrName = nullptr; - if (pszFamily && pszFamily != pszWorkingName + 4) - { - *pszFamily = '\0'; - pszFamily++; - - pszLyrName = strrchr(pszWorkingName, ':'); - if (pszLyrName == pszWorkingName + 4) - pszLyrName = nullptr; - - if (pszLyrName != nullptr) - { - *pszLyrName = '\0'; - pszLyrName++; - } - } - - /* -------------------------------------------------------------------- */ - /* Open the client interface. */ - /* -------------------------------------------------------------------- */ - ecs_Result *psResult = cln_CreateClient(&m_nClientID, pszWorkingName); - - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, - "OGDI DataSource Open Failed: %s\n", - psResult->message ? psResult->message : "(no message string)"); - CPLFree(pszWorkingName); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Capture some information from the file. */ - /* -------------------------------------------------------------------- */ - psResult = cln_GetGlobalBound(m_nClientID); - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, "GetGlobalBound failed: %s", - psResult->message ? psResult->message : "(no message string)"); - CPLFree(pszWorkingName); - return FALSE; - } - - m_sGlobalBounds = ECSREGION(psResult); - - psResult = cln_GetServerProjection(m_nClientID); - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, "GetServerProjection failed: %s", - psResult->message ? psResult->message : "(no message string)"); - CPLFree(pszWorkingName); - return FALSE; - } - - m_poSpatialRef = new OGRSpatialReference; - m_poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - - CPLString osProjString(ECSTEXT(psResult)); - osProjString.replaceAll("datum=wgs84", "datum=WGS84"); - if (m_poSpatialRef->importFromProj4(osProjString) != OGRERR_NONE) - { - CPLError(CE_Warning, CPLE_NotSupported, - "untranslatable PROJ.4 projection: %s\n", - ECSTEXT(psResult) ? ECSTEXT(psResult) : "(no message string)"); - delete m_poSpatialRef; - m_poSpatialRef = nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Select the global region. */ - /* -------------------------------------------------------------------- */ - psResult = cln_SelectRegion(m_nClientID, &m_sGlobalBounds); - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, "SelectRegion failed: %s", - psResult->message ? psResult->message : "(no message string)"); - CPLFree(pszWorkingName); - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* If an explicit layer was selected, just create that layer. */ - /* -------------------------------------------------------------------- */ - m_poCurrentLayer = nullptr; - - if (pszLyrName != nullptr) - { - ecs_Family eFamily; - - if (EQUAL(pszFamily, "Line")) - eFamily = Line; - else if (EQUAL(pszFamily, "Area")) - eFamily = Area; - else if (EQUAL(pszFamily, "Point")) - eFamily = Point; - else if (EQUAL(pszFamily, "Text")) - eFamily = Text; - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "Invalid or unsupported family name (%s) in URL %s\n", - pszFamily, pszNewName); - CPLFree(pszWorkingName); - return FALSE; - } - - IAddLayer(pszLyrName, eFamily); - } - - /* -------------------------------------------------------------------- */ - /* Otherwise create a layer for every layer in the capabilities. */ - /* -------------------------------------------------------------------- */ - else - { - // Call cln_UpdateDictionary so as to be able to report errors - // since cln_GetLayerCapabilities() cannot do that - // Help in the case of DNC17/COA17A that has a missing env/fcs file - char *szEmpty = CPLStrdup(""); - psResult = cln_UpdateDictionary(m_nClientID, szEmpty); - CPLFree(szEmpty); - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, "UpdateDictionary failed: %s", - psResult->message ? psResult->message - : "(no message string)"); - CPLFree(pszWorkingName); - return FALSE; - } - - const ecs_LayerCapabilities *psLayerCap = nullptr; - for (int i = 0; - (psLayerCap = cln_GetLayerCapabilities(m_nClientID, i)) != nullptr; - i++) - { - if (psLayerCap->families[Point]) - IAddLayer(psLayerCap->name, Point); - if (psLayerCap->families[Line]) - IAddLayer(psLayerCap->name, Line); - if (psLayerCap->families[Area]) - IAddLayer(psLayerCap->name, Area); - if (psLayerCap->families[Text]) - IAddLayer(psLayerCap->name, Text); - } - } - - CPLFree(pszWorkingName); - - return TRUE; -} - -/************************************************************************/ -/* IAddLayer() */ -/* */ -/* Internal helper function for adding one existing layer to */ -/* the datasource. */ -/************************************************************************/ - -void OGROGDIDataSource::IAddLayer(const char *pszLayerName, ecs_Family eFamily) - -{ - m_papoLayers = (OGROGDILayer **)CPLRealloc( - m_papoLayers, (m_nLayers + 1) * sizeof(OGROGDILayer *)); - - m_papoLayers[m_nLayers++] = new OGROGDILayer(this, pszLayerName, eFamily); -} - -/************************************************************************/ -/* GetLayer() */ -/************************************************************************/ - -OGRLayer *OGROGDIDataSource::GetLayer(int iLayer) - -{ - if (iLayer < 0 || iLayer >= m_nLayers) - return nullptr; - else - return m_papoLayers[iLayer]; -} diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp deleted file mode 100644 index c402ae6bdbf1..000000000000 --- a/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - * - * Project: OGDI Bridge - * Purpose: Implements OGROGDIDriver class. - * Author: Daniel Morissette, danmo@videotron.ca - * (Based on some code contributed by Frank Warmerdam :) - * - ****************************************************************************** - * Copyright (c) 2000, Daniel Morissette - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogrogdi.h" -#include "ogrogdidrivercore.h" - -#include "cpl_conv.h" - -/************************************************************************/ -/* MyOGDIReportErrorFunction() */ -/************************************************************************/ - -#if OGDI_RELEASEDATE >= 20160705 -static int MyOGDIReportErrorFunction(int errorcode, const char *error_message) -{ - CPLError(CE_Failure, CPLE_AppDefined, "OGDI error %d: %s", errorcode, - error_message); - return FALSE; // go on -} -#endif - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -static GDALDataset *OGROGDIDriverOpen(GDALOpenInfo *poOpenInfo) - -{ - const char *pszFilename = poOpenInfo->pszFilename; - if (!STARTS_WITH_CI(pszFilename, "gltp:")) - return nullptr; - -#if OGDI_RELEASEDATE >= 20160705 - // Available only in post OGDI 3.2.0beta2 - // and only called if env variable OGDI_STOP_ON_ERROR is set to NO - ecs_SetReportErrorFunction(MyOGDIReportErrorFunction); -#endif - - OGROGDIDataSource *poDS = new OGROGDIDataSource(); - - if (!poDS->Open(pszFilename)) - { - delete poDS; - poDS = nullptr; - } - - const bool bUpdate = (poOpenInfo->nOpenFlags & GDAL_OF_UPDATE) != 0; - if (poDS != nullptr && bUpdate) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "OGDI Driver doesn't support update."); - delete poDS; - poDS = nullptr; - } - - return poDS; -} - -/************************************************************************/ -/* RegisterOGROGDI() */ -/************************************************************************/ - -void RegisterOGROGDI() - -{ - if (!GDAL_CHECK_VERSION("OGR/OGDI driver")) - return; - - if (GDALGetDriverByName(DRIVER_NAME) != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - OGROGDIDriverSetCommonMetadata(poDriver); - - poDriver->pfnOpen = OGROGDIDriverOpen; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdidrivercore.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdidrivercore.cpp deleted file mode 100644 index d0af538adc8d..000000000000 --- a/ogr/ogrsf_frmts/ogdi/ogrogdidrivercore.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * - * Project: OGDI Bridge - * Purpose: Implements OGROGDIDriver class. - * Author: Daniel Morissette, danmo@videotron.ca - * (Based on some code contributed by Frank Warmerdam :) - * - ****************************************************************************** - * Copyright (c) 2000, Daniel Morissette - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogrsf_frmts.h" - -#include "ogrogdidrivercore.h" - -/************************************************************************/ -/* OGROGDIDriverIdentify() */ -/************************************************************************/ - -static int OGROGDIDriverIdentify(GDALOpenInfo *poOpenInfo) - -{ - return STARTS_WITH(poOpenInfo->pszFilename, "gltp:"); -} - -/************************************************************************/ -/* OGROGDIDriverSetCommonMetadata() */ -/************************************************************************/ - -void OGROGDIDriverSetCommonMetadata(GDALDriver *poDriver) -{ - poDriver->SetDescription(DRIVER_NAME); - poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); - - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, - "OGDI Vectors (VPF, VMAP, DCW)"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/ogdi.html"); - poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); - - poDriver->pfnIdentify = OGROGDIDriverIdentify; - poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); -} - -/************************************************************************/ -/* DeclareDeferredOGROGDIPlugin() */ -/************************************************************************/ - -#ifdef PLUGIN_FILENAME -void DeclareDeferredOGROGDIPlugin() -{ - if (GDALGetDriverByName(DRIVER_NAME) != nullptr) - { - return; - } - auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME); -#ifdef PLUGIN_INSTALLATION_MESSAGE - poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE, - PLUGIN_INSTALLATION_MESSAGE); -#endif - OGROGDIDriverSetCommonMetadata(poDriver); - GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); -} -#endif diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdidrivercore.h b/ogr/ogrsf_frmts/ogdi/ogrogdidrivercore.h deleted file mode 100644 index 4bfedb183f65..000000000000 --- a/ogr/ogrsf_frmts/ogdi/ogrogdidrivercore.h +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * - * Project: OGDI Bridge - * Purpose: Implements OGROGDIDriver class. - * Author: Daniel Morissette, danmo@videotron.ca - * (Based on some code contributed by Frank Warmerdam :) - * - ****************************************************************************** - * Copyright (c) 2000, Daniel Morissette - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef OGROGDIDRIVERCORE_H -#define OGROGDIDRIVERCORE_H - -#include "gdal_priv.h" - -constexpr const char *DRIVER_NAME = "OGR_OGDI"; - -#define OGROGDIDriverSetCommonMetadata \ - PLUGIN_SYMBOL_NAME(OGROGDIDriverSetCommonMetadata) - -void OGROGDIDriverSetCommonMetadata(GDALDriver *poDriver); - -#endif diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp deleted file mode 100644 index 67df11e4af2b..000000000000 --- a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp +++ /dev/null @@ -1,587 +0,0 @@ -/****************************************************************************** - * - * Project: OGDI Bridge - * Purpose: Implements OGROGDILayer class. - * Author: Daniel Morissette, danmo@videotron.ca - * (Based on some code contributed by Frank Warmerdam :) - * - ****************************************************************************** - * Copyright (c) 2000, Daniel Morissette - * Copyright (c) 2008-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************** - */ - -#include "ogrogdi.h" -#include "cpl_conv.h" -#include "cpl_string.h" - -/************************************************************************/ -/* OGROGDILayer() */ -/************************************************************************/ - -OGROGDILayer::OGROGDILayer(OGROGDIDataSource *poODS, const char *pszName, - ecs_Family eFamily) - : m_poODS(poODS), m_nClientID(poODS->GetClientID()), - m_pszOGDILayerName(CPLStrdup(pszName)), m_eFamily(eFamily), - m_poFeatureDefn(nullptr), - // Keep a reference on the SpatialRef (owned by the dataset). - m_poSpatialRef(m_poODS->DSGetSpatialRef()), - m_sFilterBounds(*(m_poODS->GetGlobalBounds())), m_iNextShapeId(0), - m_nTotalShapeCount(-1), m_nFilteredOutShapes(0) -{ - - // Select layer and feature family. - OGROGDILayer::ResetReading(); - - BuildFeatureDefn(); -} - -/************************************************************************/ -/* ~OGROGDILayer() */ -/************************************************************************/ - -OGROGDILayer::~OGROGDILayer() - -{ - if (m_nFeaturesRead > 0 && m_poFeatureDefn != nullptr) - { - CPLDebug("OGDI", "%d features read on layer '%s'.", - (int)m_nFeaturesRead, m_poFeatureDefn->GetName()); - } - - if (m_poFeatureDefn) - m_poFeatureDefn->Release(); - - CPLFree(m_pszOGDILayerName); - - // Note: we do not delete m_poSpatialRef since it is owned by the dataset -} - -/************************************************************************/ -/* SetSpatialFilter() */ -/************************************************************************/ - -void OGROGDILayer::SetSpatialFilter(OGRGeometry *poGeomIn) - -{ - if (!InstallFilter(poGeomIn)) - return; - - ResetReading(); - - m_nTotalShapeCount = -1; -} - -/************************************************************************/ -/* SetAttributeFilter() */ -/************************************************************************/ - -OGRErr OGROGDILayer::SetAttributeFilter(const char *pszQuery) -{ - OGRErr eErr = OGRLayer::SetAttributeFilter(pszQuery); - - ResetReading(); - - m_nTotalShapeCount = -1; - - return eErr; -} - -/************************************************************************/ -/* ResetReading() */ -/************************************************************************/ - -void OGROGDILayer::ResetReading() - -{ - ecs_LayerSelection sSelectionLayer; - - sSelectionLayer.Select = m_pszOGDILayerName; - sSelectionLayer.F = m_eFamily; - - ecs_Result *psResult = cln_SelectLayer(m_nClientID, &sSelectionLayer); - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Access to layer '%s' Failed: %s\n", m_pszOGDILayerName, - psResult->message ? psResult->message : "(no message string)"); - return; - } - - /* Reset spatial filter */ - if (m_poFilterGeom != nullptr) - { - OGREnvelope oEnv; - - m_poFilterGeom->getEnvelope(&oEnv); - - m_sFilterBounds.north = oEnv.MaxY; - m_sFilterBounds.south = oEnv.MinY; - m_sFilterBounds.west = oEnv.MinX; - m_sFilterBounds.east = oEnv.MaxX; - - psResult = cln_SelectRegion(m_nClientID, &m_sFilterBounds); - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, "SelectRegion failed: %s", - psResult->message ? psResult->message - : "(no message string)"); - return; - } - } - else - { - /* Reset to global bounds */ - psResult = cln_SelectRegion(m_nClientID, m_poODS->GetGlobalBounds()); - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, "SelectRegion failed: %s", - psResult->message ? psResult->message - : "(no message string)"); - return; - } - } - - m_iNextShapeId = 0; - m_nFilteredOutShapes = 0; -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -OGRFeature *OGROGDILayer::GetNextFeature() - -{ - - /* Reset reading if we are not the current layer */ - /* WARNING : this does not allow interleaved reading of layers */ - if (m_poODS->GetCurrentLayer() != this) - { - m_poODS->SetCurrentLayer(this); - ResetReading(); - } - - while (true) - { - OGRFeature *poFeature = GetNextRawFeature(); - if (poFeature == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- - */ - /* Do we need to apply an attribute test? */ - /* -------------------------------------------------------------------- - */ - if ((m_poAttrQuery != nullptr && !m_poAttrQuery->Evaluate(poFeature)) || - (m_poFilterGeom != nullptr && - !FilterGeometry(poFeature->GetGeometryRef()))) - { - m_nFilteredOutShapes++; - delete poFeature; - } - else - return poFeature; - } -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -OGRFeature *OGROGDILayer::GetNextRawFeature() -{ - /* -------------------------------------------------------------------- */ - /* Retrieve object from OGDI server and create new feature */ - /* -------------------------------------------------------------------- */ - ecs_Result *psResult = cln_GetNextObject(m_nClientID); - if (!ECSSUCCESS(psResult)) - { - if (ECSERROR(psResult) && - (psResult->message == nullptr || - strstr(psResult->message, "End of selection") == nullptr)) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Access to next object of layer '%s' failed: %s\n", - m_pszOGDILayerName, - psResult->message ? psResult->message - : "(no error string)"); - } - // We probably reached EOF... keep track of shape count. - m_nTotalShapeCount = m_iNextShapeId - m_nFilteredOutShapes; - return nullptr; - } - - OGRFeature *poFeature = new OGRFeature(m_poFeatureDefn); - - poFeature->SetFID(m_iNextShapeId++); - m_nFeaturesRead++; - - /* -------------------------------------------------------------------- */ - /* Process geometry */ - /* -------------------------------------------------------------------- */ - if (m_eFamily == Point) - { - ecs_Point *psPoint = &(ECSGEOM(psResult).point); - OGRPoint *poOGRPoint = new OGRPoint(psPoint->c.x, psPoint->c.y); - - poOGRPoint->assignSpatialReference(m_poSpatialRef); - poFeature->SetGeometryDirectly(poOGRPoint); - } - else if (m_eFamily == Line) - { - ecs_Line *psLine = &(ECSGEOM(psResult).line); - OGRLineString *poOGRLine = new OGRLineString(); - - poOGRLine->setNumPoints(psLine->c.c_len); - - for (int i = 0; i < (int)psLine->c.c_len; i++) - { - poOGRLine->setPoint(i, psLine->c.c_val[i].x, psLine->c.c_val[i].y); - } - - poOGRLine->assignSpatialReference(m_poSpatialRef); - poFeature->SetGeometryDirectly(poOGRLine); - } - else if (m_eFamily == Area) - { - ecs_Area *psArea = &(ECSGEOM(psResult).area); - OGRPolygon *poOGRPolygon = new OGRPolygon(); - - for (int iRing = 0; iRing < (int)psArea->ring.ring_len; iRing++) - { - ecs_FeatureRing *psRing = &(psArea->ring.ring_val[iRing]); - OGRLinearRing *poOGRRing = new OGRLinearRing(); - - poOGRRing->setNumPoints(psRing->c.c_len); - - for (int i = 0; i < (int)psRing->c.c_len; i++) - { - poOGRRing->setPoint(i, psRing->c.c_val[i].x, - psRing->c.c_val[i].y); - } - poOGRPolygon->addRingDirectly(poOGRRing); - } - - // __TODO__ - // When OGR supports polygon centroids then we should carry them here - - poOGRPolygon->assignSpatialReference(m_poSpatialRef); - poFeature->SetGeometryDirectly(poOGRPolygon); - } - else if (m_eFamily == Text) - { - // __TODO__ - // For now text is treated as a point and string is lost - // - ecs_Text *psText = &(ECSGEOM(psResult).text); - OGRPoint *poOGRPoint = new OGRPoint(psText->c.x, psText->c.y); - - poOGRPoint->assignSpatialReference(m_poSpatialRef); - poFeature->SetGeometryDirectly(poOGRPoint); - } - else - { - CPLAssert(false); - } - - /* -------------------------------------------------------------------- */ - /* Set attributes */ - /* -------------------------------------------------------------------- */ - char *pszAttrList = ECSOBJECTATTR(psResult); - - for (int iField = 0; iField < m_poFeatureDefn->GetFieldCount(); iField++) - { - char *pszFieldStart = nullptr; - int nNameLen = 0; - - /* parse out the next attribute value */ - if (!ecs_FindElement(pszAttrList, &pszFieldStart, &pszAttrList, - &nNameLen, nullptr)) - { - nNameLen = 0; - pszFieldStart = pszAttrList; - } - - /* Skip any trailing white space (for string constants). */ - - if (nNameLen > 0 && pszFieldStart[nNameLen - 1] == ' ') - nNameLen--; - - /* skip leading white space */ - while (pszFieldStart[0] == ' ' && nNameLen > 0) - { - pszFieldStart++; - nNameLen--; - } - - /* zero terminate the single field value, but save the */ - /* character we overwrote, so we can restore it when done. */ - - char chSavedChar = pszFieldStart[nNameLen]; - pszFieldStart[nNameLen] = '\0'; - - /* OGR takes care of all field type conversions for us! */ - - poFeature->SetField(iField, pszFieldStart); - - pszFieldStart[nNameLen] = chSavedChar; - } - - /* -------------------------------------------------------------------- */ - /* Apply the text associated with text features if appropriate. */ - /* -------------------------------------------------------------------- */ - if (m_eFamily == Text) - { - poFeature->SetField("text", ECSGEOM(psResult).text.desc); - } - - return poFeature; -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ - -OGRFeature *OGROGDILayer::GetFeature(GIntBig nFeatureId) - -{ - - if (m_nTotalShapeCount != -1 && nFeatureId > m_nTotalShapeCount) - return nullptr; - - /* Unset spatial filter */ - OGRGeometry *poOldFilterGeom = - (m_poFilterGeom != nullptr) ? m_poFilterGeom->clone() : nullptr; - if (poOldFilterGeom != nullptr) - SetSpatialFilter(nullptr); - - /* Reset reading if we are not the current layer */ - /* WARNING : this does not allow interleaved reading of layers */ - if (m_poODS->GetCurrentLayer() != this) - { - m_poODS->SetCurrentLayer(this); - ResetReading(); - } - else if (nFeatureId < m_iNextShapeId) - ResetReading(); - - while (m_iNextShapeId != nFeatureId) - { - ecs_Result *psResult = cln_GetNextObject(m_nClientID); - if (ECSSUCCESS(psResult)) - m_iNextShapeId++; - else - { - // We probably reached EOF... keep track of shape count. - m_nTotalShapeCount = m_iNextShapeId; - if (poOldFilterGeom != nullptr) - { - SetSpatialFilter(poOldFilterGeom); - delete poOldFilterGeom; - } - return nullptr; - } - } - - // OK, we're ready to read the requested feature... - OGRFeature *poFeature = GetNextRawFeature(); - if (poOldFilterGeom != nullptr) - { - SetSpatialFilter(poOldFilterGeom); - delete poOldFilterGeom; - } - return poFeature; -} - -/************************************************************************/ -/* GetFeatureCount() */ -/* */ -/* If a spatial filter is in effect, we turn control over to */ -/* the generic counter. Otherwise we return the total count. */ -/* Eventually we should consider implementing a more efficient */ -/* way of counting features matching a spatial query. */ -/************************************************************************/ - -GIntBig OGROGDILayer::GetFeatureCount(int bForce) - -{ - if (m_nTotalShapeCount == -1) - { - m_nTotalShapeCount = - static_cast(OGRLayer::GetFeatureCount(bForce)); - } - - return m_nTotalShapeCount; -} - -/************************************************************************/ -/* TestCapability() */ -/************************************************************************/ - -int OGROGDILayer::TestCapability(const char *pszCap) - -{ -/* -------------------------------------------------------------------- */ -/* Hummm... what are the proper capabilities... */ -/* Does OGDI have any idea of capabilities??? */ -/* For now just return FALSE for everything. */ -/* -------------------------------------------------------------------- */ -#ifdef __TODO__ - if (EQUAL(pszCap, OLCFastFeatureCount)) - return m_poFilterGeom == NULL && m_poAttrQuery == NULL; - - else if (EQUAL(pszCap, OLCFastSpatialFilter)) - return FALSE; - - else - return FALSE; -#endif - - if (EQUAL(pszCap, OLCRandomRead)) - return TRUE; - - else - return FALSE; -} - -/************************************************************************/ -/* BuildFeatureDefn() */ -/* */ -/* (private) Initializes the schema in m_poFeatureDefn */ -/************************************************************************/ - -void OGROGDILayer::BuildFeatureDefn() -{ - const char *pszGeomName = nullptr; - OGRwkbGeometryType eLayerGeomType = wkbUnknown; - - /* -------------------------------------------------------------------- */ - /* Feature Defn name will be "_" */ - /* -------------------------------------------------------------------- */ - - switch (m_eFamily) - { - case Point: - pszGeomName = "point"; - eLayerGeomType = wkbPoint; - break; - case Line: - pszGeomName = "line"; - eLayerGeomType = wkbLineString; - break; - case Area: - pszGeomName = "area"; - eLayerGeomType = wkbPolygon; - break; - case Text: - pszGeomName = "text"; - eLayerGeomType = wkbPoint; - break; - default: - pszGeomName = "unknown"; - eLayerGeomType = wkbUnknown; - break; - } - - char *pszFeatureDefnName = nullptr; - if (m_poODS->LaunderLayerNames()) - { - pszFeatureDefnName = CPLStrdup(m_pszOGDILayerName); - char *pszAt = strchr(pszFeatureDefnName, '@'); - if (pszAt) - *pszAt = '_'; - char *pszLeftParenthesis = strchr(pszFeatureDefnName, '('); - if (pszLeftParenthesis) - *pszLeftParenthesis = '\0'; - } - else - pszFeatureDefnName = - CPLStrdup(CPLSPrintf("%s_%s", m_pszOGDILayerName, pszGeomName)); - - m_poFeatureDefn = new OGRFeatureDefn(pszFeatureDefnName); - SetDescription(m_poFeatureDefn->GetName()); - CPLFree(pszFeatureDefnName); - pszFeatureDefnName = nullptr; - - m_poFeatureDefn->SetGeomType(eLayerGeomType); - m_poFeatureDefn->Reference(); - m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poSpatialRef); - - /* -------------------------------------------------------------------- */ - /* Fetch schema from OGDI server and map to OGR types */ - /* -------------------------------------------------------------------- */ - ecs_Result *psResult = cln_GetAttributesFormat(m_nClientID); - if (ECSERROR(psResult)) - { - CPLError(CE_Failure, CPLE_AppDefined, "ECSERROR: %s\n", - psResult->message ? psResult->message : "(no message string)"); - return; - } - - ecs_ObjAttributeFormat *oaf = &(ECSRESULT(psResult).oaf); - const int numFields = oaf->oa.oa_len; - for (int i = 0; i < numFields; i++) - { - OGRFieldDefn oField("", OFTInteger); - - oField.SetName(oaf->oa.oa_val[i].name); - oField.SetPrecision(0); - - switch (oaf->oa.oa_val[i].type) - { - case Decimal: - case Smallint: - case Integer: - oField.SetType(OFTInteger); - // TODO: Fix spelling - lenght -> length - if (oaf->oa.oa_val[i].lenght > 0) - oField.SetWidth(oaf->oa.oa_val[i].lenght); - else - oField.SetWidth(11); - break; - - case Numeric: - case Real: - case Float: - case Double: - oField.SetType(OFTReal); - if (oaf->oa.oa_val[i].lenght > 0) - { - oField.SetWidth(oaf->oa.oa_val[i].lenght); - oField.SetPrecision(oaf->oa.oa_val[i].precision); - } - else - { - oField.SetWidth(18); - oField.SetPrecision(7); - } - break; - - case Char: - case Varchar: - case Longvarchar: - default: - oField.SetType(OFTString); - if (oaf->oa.oa_val[i].lenght > 0) - oField.SetWidth(oaf->oa.oa_val[i].lenght); - else - oField.SetWidth(64); - break; - } - - m_poFeatureDefn->AddFieldDefn(&oField); - } - - /* -------------------------------------------------------------------- */ - /* Add a text attribute for text objects. */ - /* -------------------------------------------------------------------- */ - if (m_eFamily == Text) - { - OGRFieldDefn oField("text", OFTString); - - m_poFeatureDefn->AddFieldDefn(&oField); - } -} diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.h b/ogr/ogrsf_frmts/ogrsf_frmts.h index 0d774075baa4..fff499d8d862 100644 --- a/ogr/ogrsf_frmts/ogrsf_frmts.h +++ b/ogr/ogrsf_frmts/ogrsf_frmts.h @@ -670,14 +670,9 @@ void OGRRegisterAllInternal(); void CPL_DLL RegisterOGRFileGDB(); void DeclareDeferredOGRFileGDBPlugin(); void CPL_DLL RegisterOGRShape(); -void CPL_DLL RegisterOGRNTF(); -void CPL_DLL RegisterOGRSDTS(); -void CPL_DLL RegisterOGRTiger(); void CPL_DLL RegisterOGRS57(); void CPL_DLL RegisterOGRTAB(); void CPL_DLL RegisterOGRMIF(); -void CPL_DLL RegisterOGROGDI(); -void DeclareDeferredOGROGDIPlugin(); void CPL_DLL RegisterOGRODBC(); void DeclareDeferredOGRODBCPlugin(); void CPL_DLL RegisterOGRWAsP(); diff --git a/ogr/ogrsf_frmts/sdts/CMakeLists.txt b/ogr/ogrsf_frmts/sdts/CMakeLists.txt deleted file mode 100644 index 24eaae40ac27..000000000000 --- a/ogr/ogrsf_frmts/sdts/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_gdal_driver( - TARGET ogr_SDTS - SOURCES ogr_sdts.h ogrsdtsdatasource.cpp ogrsdtsdriver.cpp ogrsdtslayer.cpp - BUILTIN) -gdal_standard_includes(ogr_SDTS) -target_include_directories(ogr_SDTS PRIVATE $ - $) diff --git a/ogr/ogrsf_frmts/sdts/install-libs.sh b/ogr/ogrsf_frmts/sdts/install-libs.sh deleted file mode 100755 index a7ac1c58c98b..000000000000 --- a/ogr/ogrsf_frmts/sdts/install-libs.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -SRCLIB=$1 -DSTLIB=$2 - -OBJ=$(ar t $SRCLIB | grep -v SORTED | grep -v SYMDEF) - -ar x $SRCLIB $OBJ -ar r $DSTLIB $OBJ -rm $OBJ - diff --git a/ogr/ogrsf_frmts/sdts/ogr_sdts.h b/ogr/ogrsf_frmts/sdts/ogr_sdts.h deleted file mode 100644 index fcd993c12493..000000000000 --- a/ogr/ogrsf_frmts/sdts/ogr_sdts.h +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * - * Project: STS Translator - * Purpose: Definition of classes finding SDTS support into OGRDriver - * framework. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef OGR_SDTS_H_INCLUDED -#define OGR_SDTS_H_INCLUDED - -#include "sdts_al.h" -#include "ogrsf_frmts.h" - -class OGRSDTSDataSource; - -/************************************************************************/ -/* OGRSDTSLayer */ -/************************************************************************/ - -class OGRSDTSLayer final : public OGRLayer -{ - OGRFeatureDefn *poFeatureDefn; - - SDTSTransfer *poTransfer; - int iLayer; - SDTSIndexedReader *poReader; - - OGRSDTSDataSource *poDS; - - OGRFeature *GetNextUnfilteredFeature(); - - public: - OGRSDTSLayer(SDTSTransfer *, int, OGRSDTSDataSource *); - ~OGRSDTSLayer(); - - void ResetReading() override; - OGRFeature *GetNextFeature() override; - - OGRFeatureDefn *GetLayerDefn() override - { - return poFeatureDefn; - } - - int TestCapability(const char *) override; -}; - -/************************************************************************/ -/* OGRSDTSDataSource */ -/************************************************************************/ - -class OGRSDTSDataSource final : public GDALDataset -{ - SDTSTransfer *poTransfer; - - int nLayers; - OGRSDTSLayer **papoLayers; - - OGRSpatialReference *poSRS; - - public: - OGRSDTSDataSource(); - ~OGRSDTSDataSource(); - - int Open(const char *pszFilename, int bTestOpen); - - int GetLayerCount() override - { - return nLayers; - } - - OGRLayer *GetLayer(int) override; -}; - -#endif /* ndef OGR_SDTS_H_INCLUDED */ diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp deleted file mode 100644 index f4b8877422a4..000000000000 --- a/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implements OGRSDTSDataSource class - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_sdts.h" -#include "cpl_conv.h" -#include "cpl_string.h" - -/************************************************************************/ -/* OGRSDTSDataSource() */ -/************************************************************************/ - -OGRSDTSDataSource::OGRSDTSDataSource() - : poTransfer(nullptr), nLayers(0), papoLayers(nullptr), poSRS(nullptr) -{ -} - -/************************************************************************/ -/* ~OGRSDTSDataSource() */ -/************************************************************************/ - -OGRSDTSDataSource::~OGRSDTSDataSource() - -{ - for (int i = 0; i < nLayers; i++) - delete papoLayers[i]; - - CPLFree(papoLayers); - - if (poSRS) - poSRS->Release(); - - if (poTransfer) - delete poTransfer; -} - -/************************************************************************/ -/* GetLayer() */ -/************************************************************************/ - -OGRLayer *OGRSDTSDataSource::GetLayer(int iLayer) - -{ - if (iLayer < 0 || iLayer >= nLayers) - return nullptr; - else - return papoLayers[iLayer]; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -int OGRSDTSDataSource::Open(const char *pszFilename, int bTestOpen) - -{ - /* -------------------------------------------------------------------- */ - /* Verify that the extension is DDF if we are testopening. */ - /* -------------------------------------------------------------------- */ - if (bTestOpen && !(strlen(pszFilename) > 4 && - EQUAL(pszFilename + strlen(pszFilename) - 4, ".ddf"))) - return FALSE; - - /* -------------------------------------------------------------------- */ - /* Check a few bits of the header to see if it looks like an */ - /* SDTS file (really, if it looks like an ISO8211 file). */ - /* -------------------------------------------------------------------- */ - if (bTestOpen) - { - VSILFILE *fp = VSIFOpenL(pszFilename, "rb"); - if (fp == nullptr) - return FALSE; - - char pachLeader[10] = {}; - if (VSIFReadL(pachLeader, 1, 10, fp) != 10 || - (pachLeader[5] != '1' && pachLeader[5] != '2' && - pachLeader[5] != '3') || - pachLeader[6] != 'L' || - (pachLeader[8] != '1' && pachLeader[8] != ' ')) - { - VSIFCloseL(fp); - return FALSE; - } - - VSIFCloseL(fp); - } - - /* -------------------------------------------------------------------- */ - /* Create a transfer, and open it. */ - /* -------------------------------------------------------------------- */ - poTransfer = new SDTSTransfer(); - - GUInt32 nInitialErrorCounter = CPLGetErrorCounter(); - if (!poTransfer->Open(pszFilename) || - CPLGetErrorCounter() > nInitialErrorCounter + 100) - { - delete poTransfer; - poTransfer = nullptr; - - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Initialize the projection. */ - /* -------------------------------------------------------------------- */ - SDTS_XREF *poXREF = poTransfer->GetXREF(); - - poSRS = new OGRSpatialReference(); - poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - - if (EQUAL(poXREF->pszSystemName, "UTM")) - { - poSRS->SetUTM(poXREF->nZone, TRUE); - } - - if (EQUAL(poXREF->pszDatum, "NAS")) - poSRS->SetGeogCS("NAD27", "North_American_Datum_1927", "Clarke 1866", - 6378206.4, 294.978698213901); - - else if (EQUAL(poXREF->pszDatum, "NAX")) - poSRS->SetGeogCS("NAD83", "North_American_Datum_1983", "GRS 1980", - 6378137, 298.257222101); - - else if (EQUAL(poXREF->pszDatum, "WGC")) - poSRS->SetGeogCS("WGS 72", "WGS_1972", "NWL 10D", 6378135, 298.26); - - else /* if( EQUAL(poXREF->pszDatum,"WGE") ) or default case */ - poSRS->SetGeogCS("WGS 84", "WGS_1984", "WGS 84", 6378137, - 298.257223563); - - /* -------------------------------------------------------------------- */ - /* Initialize a layer for each source dataset layer. */ - /* -------------------------------------------------------------------- */ - - for (int iLayer = 0; iLayer < poTransfer->GetLayerCount(); iLayer++) - { - if (poTransfer->GetLayerType(iLayer) == SLTRaster) - continue; - - SDTSIndexedReader *poReader = poTransfer->GetLayerIndexedReader(iLayer); - if (poReader == nullptr) - continue; - if (CPLGetErrorCounter() > nInitialErrorCounter + 100) - return FALSE; - - papoLayers = - (OGRSDTSLayer **)CPLRealloc(papoLayers, sizeof(void *) * ++nLayers); - papoLayers[nLayers - 1] = new OGRSDTSLayer(poTransfer, iLayer, this); - } - - return TRUE; -} diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp deleted file mode 100644 index a1b4b522ccbf..000000000000 --- a/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/****************************************************************************** - * - * Project: SDTS Translator - * Purpose: Implements OGRSDTSDriver - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_sdts.h" -#include "cpl_conv.h" - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -static GDALDataset *OGRSDTSDriverOpen(GDALOpenInfo *poOpenInfo) - -{ - if (!poOpenInfo->IsExtensionEqualToCI("DDF")) - return nullptr; - if (poOpenInfo->nHeaderBytes < 10) - return nullptr; - const char *pachLeader = (const char *)poOpenInfo->pabyHeader; - if ((pachLeader[5] != '1' && pachLeader[5] != '2' && - pachLeader[5] != '3') || - pachLeader[6] != 'L' || (pachLeader[8] != '1' && pachLeader[8] != ' ')) - { - return nullptr; - } - - OGRSDTSDataSource *poDS = new OGRSDTSDataSource(); - if (!poDS->Open(poOpenInfo->pszFilename, TRUE)) - { - delete poDS; - poDS = nullptr; - } - - if (poDS != nullptr && poOpenInfo->eAccess == GA_Update) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "SDTS Driver doesn't support update."); - delete poDS; - poDS = nullptr; - } - - return poDS; -} - -/************************************************************************/ -/* RegisterOGRSDTS() */ -/************************************************************************/ - -void RegisterOGRSDTS() - -{ - if (GDALGetDriverByName("OGR_SDTS") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("OGR_SDTS"); - poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "SDTS"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/sdts.html"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); - - poDriver->pfnOpen = OGRSDTSDriverOpen; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp deleted file mode 100644 index aeaf42dc554a..000000000000 --- a/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/****************************************************************************** - * - * Project: SDTSReader - * Purpose: Implements OGRSDTSLayer class. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_sdts.h" -#include "cpl_conv.h" -#include "cpl_string.h" - -/************************************************************************/ -/* OGRSDTSLayer() */ -/* */ -/* Note that the OGRSDTSLayer assumes ownership of the passed */ -/* OGRFeatureDefn object. */ -/************************************************************************/ - -OGRSDTSLayer::OGRSDTSLayer(SDTSTransfer *poTransferIn, int iLayerIn, - OGRSDTSDataSource *poDSIn) - : poFeatureDefn(nullptr), poTransfer(poTransferIn), iLayer(iLayerIn), - poReader(poTransferIn->GetLayerIndexedReader(iLayerIn)), poDS(poDSIn) -{ - /* -------------------------------------------------------------------- */ - /* Define the feature. */ - /* -------------------------------------------------------------------- */ - const int iCATDEntry = poTransfer->GetLayerCATDEntry(iLayer); - - poFeatureDefn = - new OGRFeatureDefn(poTransfer->GetCATD()->GetEntryModule(iCATDEntry)); - SetDescription(poFeatureDefn->GetName()); - poFeatureDefn->Reference(); - poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->GetSpatialRef()); - - OGRFieldDefn oRecId("RCID", OFTInteger); - poFeatureDefn->AddFieldDefn(&oRecId); - - if (poTransfer->GetLayerType(iLayer) == SLTPoint) - { - poFeatureDefn->SetGeomType(wkbPoint); - } - else if (poTransfer->GetLayerType(iLayer) == SLTLine) - { - poFeatureDefn->SetGeomType(wkbLineString); - - oRecId.SetName("SNID"); - poFeatureDefn->AddFieldDefn(&oRecId); - - oRecId.SetName("ENID"); - poFeatureDefn->AddFieldDefn(&oRecId); - } - else if (poTransfer->GetLayerType(iLayer) == SLTPoly) - { - poFeatureDefn->SetGeomType(wkbPolygon); - } - else if (poTransfer->GetLayerType(iLayer) == SLTAttr) - { - poFeatureDefn->SetGeomType(wkbNone); - } - - /* -------------------------------------------------------------------- */ - /* Add schema from referenced attribute records. */ - /* -------------------------------------------------------------------- */ - char **papszATIDRefs = nullptr; - - if (poTransfer->GetLayerType(iLayer) != SLTAttr) - papszATIDRefs = poReader->ScanModuleReferences(); - else - papszATIDRefs = CSLAddString( - papszATIDRefs, poTransfer->GetCATD()->GetEntryModule(iCATDEntry)); - - for (int iTable = 0; - papszATIDRefs != nullptr && papszATIDRefs[iTable] != nullptr; iTable++) - { - /* -------------------------------------------------------------------- - */ - /* Get the attribute table reader, and the associated user */ - /* attribute field. */ - /* -------------------------------------------------------------------- - */ - const int nLayerIdx = poTransfer->FindLayer(papszATIDRefs[iTable]); - if (nLayerIdx < 0) - continue; - SDTSAttrReader *poAttrReader = dynamic_cast( - poTransfer->GetLayerIndexedReader(nLayerIdx)); - - if (poAttrReader == nullptr) - continue; - - DDFFieldDefn *poFDefn = - poAttrReader->GetModule()->FindFieldDefn("ATTP"); - if (poFDefn == nullptr) - poFDefn = poAttrReader->GetModule()->FindFieldDefn("ATTS"); - if (poFDefn == nullptr) - continue; - - /* -------------------------------------------------------------------- - */ - /* Process each user subfield on the attribute table into an */ - /* OGR field definition. */ - /* -------------------------------------------------------------------- - */ - for (int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++) - { - DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield(iSF); - const int nWidth = poSFDefn->GetWidth(); - - char *pszFieldName = - poFeatureDefn->GetFieldIndex(poSFDefn->GetName()) != -1 - ? CPLStrdup(CPLSPrintf("%s_%s", papszATIDRefs[iTable], - poSFDefn->GetName())) - : CPLStrdup(poSFDefn->GetName()); - - switch (poSFDefn->GetType()) - { - case DDFString: - { - OGRFieldDefn oStrField(pszFieldName, OFTString); - - if (nWidth != 0) - oStrField.SetWidth(nWidth); - - poFeatureDefn->AddFieldDefn(&oStrField); - } - break; - - case DDFInt: - { - OGRFieldDefn oIntField(pszFieldName, OFTInteger); - - if (nWidth != 0) - oIntField.SetWidth(nWidth); - - poFeatureDefn->AddFieldDefn(&oIntField); - } - break; - - case DDFFloat: - { - OGRFieldDefn oRealField(pszFieldName, OFTReal); - - // We don't have a precision in DDF files, so we never even - // use the width. Otherwise with a precision of zero the - // result would look like an integer. - - poFeatureDefn->AddFieldDefn(&oRealField); - } - break; - - default: - break; - } - - CPLFree(pszFieldName); - } /* next iSF (subfield) */ - } /* next iTable */ - CSLDestroy(papszATIDRefs); -} - -/************************************************************************/ -/* ~OGRSDTSLayer() */ -/************************************************************************/ - -OGRSDTSLayer::~OGRSDTSLayer() - -{ - if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr) - { - CPLDebug("SDTS", "%d features read on layer '%s'.", - static_cast(m_nFeaturesRead), poFeatureDefn->GetName()); - } - - if (poFeatureDefn) - poFeatureDefn->Release(); -} - -/************************************************************************/ -/* ResetReading() */ -/************************************************************************/ - -void OGRSDTSLayer::ResetReading() - -{ - poReader->Rewind(); -} - -/************************************************************************/ -/* AssignAttrRecordToFeature() */ -/************************************************************************/ - -static void AssignAttrRecordToFeature(OGRFeature *poFeature, - CPL_UNUSED SDTSTransfer *poTransfer, - DDFField *poSR) -{ - /* -------------------------------------------------------------------- */ - /* Process each subfield in the record. */ - /* -------------------------------------------------------------------- */ - DDFFieldDefn *poFDefn = poSR->GetFieldDefn(); - - for (int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++) - { - DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield(iSF); - int nMaxBytes = 0; - const char *pachData = poSR->GetSubfieldData(poSFDefn, &nMaxBytes); - /* -------------------------------------------------------------------- - */ - /* Identify this field on the feature. */ - /* -------------------------------------------------------------------- - */ - const int iField = poFeature->GetFieldIndex(poSFDefn->GetName()); - - /* -------------------------------------------------------------------- - */ - /* Handle each of the types. */ - /* -------------------------------------------------------------------- - */ - switch (poSFDefn->GetType()) - { - case DDFString: - { - const char *pszValue = - poSFDefn->ExtractStringData(pachData, nMaxBytes, nullptr); - - if (iField != -1) - poFeature->SetField(iField, pszValue); - break; - } - case DDFFloat: - { - double dfValue = - poSFDefn->ExtractFloatData(pachData, nMaxBytes, nullptr); - - if (iField != -1) - poFeature->SetField(iField, dfValue); - break; - } - case DDFInt: - { - int nValue = - poSFDefn->ExtractIntData(pachData, nMaxBytes, nullptr); - - if (iField != -1) - poFeature->SetField(iField, nValue); - break; - } - default: - break; - } - } /* next subfield */ -} - -/************************************************************************/ -/* GetNextUnfilteredFeature() */ -/************************************************************************/ - -OGRFeature *OGRSDTSLayer::GetNextUnfilteredFeature() - -{ - /* -------------------------------------------------------------------- */ - /* If not done before we need to assemble the geometry for a */ - /* polygon layer. */ - /* -------------------------------------------------------------------- */ - if (poTransfer->GetLayerType(iLayer) == SLTPoly) - { - ((SDTSPolygonReader *)poReader)->AssembleRings(poTransfer, iLayer); - } - - /* -------------------------------------------------------------------- */ - /* Fetch the next sdts style feature object from the reader. */ - /* -------------------------------------------------------------------- */ - SDTSFeature *poSDTSFeature = poReader->GetNextFeature(); - // Retain now the IsIndexed state to determine if we must delete or - // not poSDTSFeature when done with it, because later calls might cause - // indexing. - const bool bIsIndexed = CPL_TO_BOOL(poReader->IsIndexed()); - - if (poSDTSFeature == nullptr) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* Create the OGR feature. */ - /* -------------------------------------------------------------------- */ - OGRFeature *poFeature = new OGRFeature(poFeatureDefn); - - m_nFeaturesRead++; - - switch (poTransfer->GetLayerType(iLayer)) - { - /* -------------------------------------------------------------------- - */ - /* Translate point feature specific information and geometry. - */ - /* -------------------------------------------------------------------- - */ - case SLTPoint: - { - SDTSRawPoint *poPoint = (SDTSRawPoint *)poSDTSFeature; - - poFeature->SetGeometryDirectly( - new OGRPoint(poPoint->dfX, poPoint->dfY, poPoint->dfZ)); - } - break; - - /* -------------------------------------------------------------------- - */ - /* Translate line feature specific information and geometry. */ - /* -------------------------------------------------------------------- - */ - case SLTLine: - { - SDTSRawLine *poLine = (SDTSRawLine *)poSDTSFeature; - OGRLineString *poOGRLine = new OGRLineString(); - - poOGRLine->setPoints(poLine->nVertices, poLine->padfX, - poLine->padfY, poLine->padfZ); - poFeature->SetGeometryDirectly(poOGRLine); - poFeature->SetField("SNID", (int)poLine->oStartNode.nRecord); - poFeature->SetField("ENID", (int)poLine->oEndNode.nRecord); - } - break; - - /* -------------------------------------------------------------------- - */ - /* Translate polygon feature specific information and geometry. - */ - /* -------------------------------------------------------------------- - */ - case SLTPoly: - { - SDTSRawPolygon *poPoly = (SDTSRawPolygon *)poSDTSFeature; - OGRPolygon *poOGRPoly = new OGRPolygon(); - - for (int iRing = 0; iRing < poPoly->nRings; iRing++) - { - OGRLinearRing *poRing = new OGRLinearRing(); - const int nVertices = - iRing == poPoly->nRings - 1 - ? poPoly->nVertices - poPoly->panRingStart[iRing] - : (poPoly->panRingStart[iRing + 1] - - poPoly->panRingStart[iRing]); - - poRing->setPoints(nVertices, - poPoly->padfX + poPoly->panRingStart[iRing], - poPoly->padfY + poPoly->panRingStart[iRing], - poPoly->padfZ + poPoly->panRingStart[iRing]); - - poOGRPoly->addRingDirectly(poRing); - } - - poFeature->SetGeometryDirectly(poOGRPoly); - } - break; - - default: - break; - } - - /* -------------------------------------------------------------------- */ - /* Set attributes for any indicated attribute records. */ - /* -------------------------------------------------------------------- */ - for (int iAttrRecord = 0; iAttrRecord < poSDTSFeature->nAttributes; - iAttrRecord++) - { - DDFField *poSR = - poTransfer->GetAttr(poSDTSFeature->paoATID + iAttrRecord); - if (poSR != nullptr) - AssignAttrRecordToFeature(poFeature, poTransfer, poSR); - } - - /* -------------------------------------------------------------------- */ - /* If this record is an attribute record, attach the local */ - /* attributes. */ - /* -------------------------------------------------------------------- */ - if (poTransfer->GetLayerType(iLayer) == SLTAttr) - { - AssignAttrRecordToFeature(poFeature, poTransfer, - ((SDTSAttrRecord *)poSDTSFeature)->poATTR); - } - - /* -------------------------------------------------------------------- */ - /* Translate the record id. */ - /* -------------------------------------------------------------------- */ - poFeature->SetFID(poSDTSFeature->oModId.nRecord); - poFeature->SetField(0, (int)poSDTSFeature->oModId.nRecord); - if (poFeature->GetGeometryRef() != nullptr) - poFeature->GetGeometryRef()->assignSpatialReference( - poDS->GetSpatialRef()); - - if (!bIsIndexed) - delete poSDTSFeature; - - return poFeature; -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -OGRFeature *OGRSDTSLayer::GetNextFeature() - -{ - OGRFeature *poFeature = nullptr; - - /* -------------------------------------------------------------------- */ - /* Read features till we find one that satisfies our current */ - /* spatial criteria. */ - /* -------------------------------------------------------------------- */ - while (true) - { - poFeature = GetNextUnfilteredFeature(); - if (poFeature == nullptr) - break; - - if ((m_poFilterGeom == nullptr || - FilterGeometry(poFeature->GetGeometryRef())) && - (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature))) - break; - - delete poFeature; - } - - return poFeature; -} - -/************************************************************************/ -/* TestCapability() */ -/************************************************************************/ - -int OGRSDTSLayer::TestCapability(const char * /* pszCap */) - -{ - return FALSE; -} diff --git a/ogr/ogrsf_frmts/tiger/CMakeLists.txt b/ogr/ogrsf_frmts/tiger/CMakeLists.txt deleted file mode 100644 index 3a2ab318a747..000000000000 --- a/ogr/ogrsf_frmts/tiger/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -add_gdal_driver( - TARGET ogr_Tiger - SOURCES ogr_tiger.h - tigerarealandmarks.cpp - tigeridhistory.cpp - tigerpoint.cpp - tigerspatialmetadata.cpp - ogrtigerdatasource.cpp - tigercompletechain.cpp - tigerkeyfeatures.cpp - tigerpolychainlink.cpp - tigertlidrange.cpp - ogrtigerdriver.cpp - tigerentitynames.cpp - tigerlandmarks.cpp - tigerpolygon.cpp - tigerzerocellid.cpp - ogrtigerlayer.cpp - tigerfeatureids.cpp - tigeroverunder.cpp - tigerpolygoncorrections.cpp - tigerzipcodes.cpp - tigeraltname.cpp - tigerfilebase.cpp - tigerpip.cpp - tigerpolygoneconomic.cpp - tigerzipplus4.cpp - PLUGIN_CAPABLE - NO_DEPS) -gdal_standard_includes(ogr_Tiger) diff --git a/ogr/ogrsf_frmts/tiger/ogr_tiger.h b/ogr/ogrsf_frmts/tiger/ogr_tiger.h deleted file mode 100644 index 26ba20043daa..000000000000 --- a/ogr/ogrsf_frmts/tiger/ogr_tiger.h +++ /dev/null @@ -1,555 +0,0 @@ -/*-*-C++-*-*/ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Main declarations for Tiger translator. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2008-2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef OGR_TIGER_H_INCLUDED -#define OGR_TIGER_H_INCLUDED - -#include "cpl_conv.h" -#include "ogrsf_frmts.h" - -class OGRTigerDataSource; - -/* -** TIGER Versions -** -** 0000 TIGER/Line Precensus Files, 1990 -** 0002 TIGER/Line Initial Voting District Codes Files, 1990 -** 0003 TIGER/Line Files, 1990 -** 0005 TIGER/Line Files, 1992 -** 0021 TIGER/Line Files, 1994 -** 0024 TIGER/Line Files, 1995 -** 0697 to 1098 TIGER/Line Files, 1997 -** 1298 to 0499 TIGER/Line Files, 1998 -** 0600 to 0800 TIGER/Line Files, 1999 -** 1000 to 1100 TIGER/Line Files, Redistricting Census 2000 -** 0301 to 0801 TIGER/Line Files, Census 2000 -** -** 0302 to 0502 TIGER/Line Files, UA 2000 -** ???? ???? -** -** 0602 & higher TIGER/Line Files, 2002 -** ???? ???? -*/ - -typedef enum -{ - TIGER_1990_Precensus = 0, - TIGER_1990 = 1, - TIGER_1992 = 2, - TIGER_1994 = 3, - TIGER_1995 = 4, - TIGER_1997 = 5, - TIGER_1998 = 6, - TIGER_1999 = 7, - TIGER_2000_Redistricting = 8, - TIGER_2000_Census = 9, - TIGER_UA2000 = 10, - TIGER_2002 = 11, - TIGER_2003 = 12, - TIGER_2004 = 13, - TIGER_Unknown -} TigerVersion; - -TigerVersion TigerClassifyVersion(int); -const char *TigerVersionString(TigerVersion); - -/*****************************************************************************/ -/* The TigerFieldInfo and TigerRecordInfo structures hold information about */ -/* the schema of a TIGER record type. In each layer implementation file */ -/* there are statically initialized variables of these types that describe */ -/* the record types associated with that layer. In the case where different */ -/* TIGER versions have different schemas, there is a */ -/* TigerFieldInfo/TigerRecordInfo for each version, and the constructor */ -/* for the layer chooses a pointer to the correct set based on the version. */ -/*****************************************************************************/ - -typedef struct TigerFieldInfo -{ - char pszFieldName[11]; // name of the field - char cFmt; // format of the field ('L' or 'R') - char cType; // type of the field ('A' or 'N') - char OGRtype; // OFTType of the field (OFTInteger, OFTString, ...?) - unsigned char nBeg; // beginning column number for field - unsigned char nEnd; // ending column number for field - unsigned char nLen; // length of field - - unsigned int bDefine : 1; // whether to add this field to the FeatureDefn - unsigned int bSet : 1; // whether to set this field in GetFeature() -} TigerFieldInfo; - -typedef struct TigerRecordInfo -{ - const TigerFieldInfo *pasFields; - unsigned char nFieldCount; - unsigned char nRecordLength; -} TigerRecordInfo; - -// OGR_TIGER_RECBUF_LEN should be a number that is larger than the -// longest possible record length for any record type; it is used to -// create arrays to hold the records. At the time of this writing the -// longest record (RT1) has length 228, but I'm choosing 500 because -// it is a good round number and will allow for growth without having -// to modify this file. The code never holds more than a few records -// in memory at a time, so having OGR_TIGER_RECBUF_LEN be much larger -// than is really necessary won't affect the amount of memory required -// in a substantial way. -// mbp Fri Dec 20 19:19:59 2002 -// Note: OGR_TIGER_RECBUF_LEN should also be larger than 255, since -// TigerRecordInfo::nRecordLength fits on unsigned char. -#define OGR_TIGER_RECBUF_LEN 500 - -/************************************************************************/ -/* TigerFileBase */ -/************************************************************************/ - -class TigerFileBase CPL_NON_FINAL -{ - protected: - OGRTigerDataSource *poDS; - - char *pszModule; - char *pszShortModule; - VSILFILE *fpPrimary; - - OGRFeatureDefn *poFeatureDefn; - - int nFeatures; - int nRecordLength; - - int OpenFile(const char *, const char *); - void EstablishFeatureCount(); - - static int EstablishRecordLength(VSILFILE *); - - void SetupVersion(); - - int nVersionCode; - TigerVersion nVersion; - - public: - explicit TigerFileBase(const TigerRecordInfo *psRTInfoIn = nullptr, - const char *m_pszFileCodeIn = nullptr); - virtual ~TigerFileBase(); - - TigerVersion GetVersion() - { - return nVersion; - } - - int GetVersionCode() - { - return nVersionCode; - } - - virtual const char *GetShortModule() - { - return pszShortModule; - } - - virtual const char *GetModule() - { - return pszModule; - } - - virtual int GetFeatureCount() - { - return nFeatures; - } - - OGRFeatureDefn *GetFeatureDefn() - { - return poFeatureDefn; - } - - static const char *GetField(const char *, int, int); - static void SetField(OGRFeature *, const char *, const char *, int, int); - - virtual bool SetModule(const char *pszModule); - virtual OGRFeature *GetFeature(int nRecordId); - - protected: - static void AddFieldDefns(const TigerRecordInfo *psRTInfo, - OGRFeatureDefn *poFeatureDefn); - - static void SetFields(const TigerRecordInfo *psRTInfo, - OGRFeature *poFeature, char *achRecord); - - const TigerRecordInfo *psRTInfo; - const char *m_pszFileCode; -}; - -/************************************************************************/ -/* TigerCompleteChain */ -/************************************************************************/ - -class TigerCompleteChain final : public TigerFileBase -{ - VSILFILE *fpShape; - int *panShapeRecordId; - - VSILFILE *fpRT3; - bool bUsingRT3; - int nRT1RecOffset; - - int GetShapeRecordId(int, int); - bool AddShapePoints(int, int, OGRLineString *, int); - - void AddFieldDefnsPre2002(); - OGRFeature *GetFeaturePre2002(int); - - OGRFeature *GetFeature2002(int); - void AddFieldDefns2002(); - - const TigerRecordInfo *psRT1Info; - const TigerRecordInfo *psRT2Info; - const TigerRecordInfo *psRT3Info; - - public: - TigerCompleteChain(OGRTigerDataSource *, const char *); - virtual ~TigerCompleteChain(); - - virtual bool SetModule(const char *) override; - - virtual OGRFeature *GetFeature(int) override; -}; - -/************************************************************************/ -/* TigerAltName (Type 4 records) */ -/************************************************************************/ - -class TigerAltName final : public TigerFileBase -{ - public: - TigerAltName(OGRTigerDataSource *, const char *); - - virtual OGRFeature *GetFeature(int) override; -}; - -/************************************************************************/ -/* TigerFeatureIds (Type 5 records) */ -/************************************************************************/ - -class TigerFeatureIds final : public TigerFileBase -{ - public: - TigerFeatureIds(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerZipCodes (Type 6 records) */ -/************************************************************************/ - -class TigerZipCodes final : public TigerFileBase -{ - public: - TigerZipCodes(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerPoint */ -/* This is an abstract base class for TIGER layers with point geometry. */ -/* Since much of the implementation of these layers is similar, I've */ -/* put it into this base class to avoid duplication in the actual */ -/* layer classes. mbp Sat Jan 4 16:41:19 2003. */ -/************************************************************************/ - -class TigerPoint CPL_NON_FINAL : public TigerFileBase -{ - protected: - explicit TigerPoint(const TigerRecordInfo *psRTInfoIn = nullptr, - const char *m_pszFileCodeIn = nullptr); - - public: - virtual OGRFeature *GetFeature(int nFID) override - { - return TigerFileBase::GetFeature(nFID); - } /* to avoid -Woverloaded-virtual warnings */ - - OGRFeature *GetFeature(int nRecordId, int nX0, int nX1, int nY0, int nY1); -}; - -/************************************************************************/ -/* TigerLandmarks (Type 7 records) */ -/************************************************************************/ - -class TigerLandmarks final : public TigerPoint -{ - public: - TigerLandmarks(OGRTigerDataSource *, const char *); - - virtual OGRFeature *GetFeature(int) override; -}; - -/************************************************************************/ -/* TigerAreaLandmarks (Type 8 records) */ -/************************************************************************/ - -class TigerAreaLandmarks final : public TigerFileBase -{ - public: - TigerAreaLandmarks(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerKeyFeatures (Type 9 records) */ -/************************************************************************/ - -class TigerKeyFeatures final : public TigerFileBase -{ - public: - TigerKeyFeatures(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerPolygon (Type A&S records) */ -/************************************************************************/ - -class TigerPolygon final : public TigerFileBase -{ - private: - const TigerRecordInfo *psRTAInfo; - const TigerRecordInfo *psRTSInfo; - - VSILFILE *fpRTS; - bool bUsingRTS; - int nRTSRecLen; - - public: - TigerPolygon(OGRTigerDataSource *, const char *); - virtual ~TigerPolygon(); - - virtual bool SetModule(const char *) override; - - virtual OGRFeature *GetFeature(int) override; -}; - -/************************************************************************/ -/* TigerPolygonCorrections (Type B records) */ -/************************************************************************/ - -class TigerPolygonCorrections final : public TigerFileBase -{ - public: - TigerPolygonCorrections(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerEntityNames (Type C records) */ -/************************************************************************/ - -class TigerEntityNames final : public TigerFileBase -{ - public: - TigerEntityNames(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerPolygonEconomic (Type E records) */ -/************************************************************************/ - -class TigerPolygonEconomic final : public TigerFileBase -{ - public: - TigerPolygonEconomic(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerIDHistory (Type H records) */ -/************************************************************************/ - -class TigerIDHistory final : public TigerFileBase -{ - public: - TigerIDHistory(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerPolyChainLink (Type I records) */ -/************************************************************************/ - -class TigerPolyChainLink final : public TigerFileBase -{ - public: - TigerPolyChainLink(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerSpatialMetadata (Type M records) */ -/************************************************************************/ - -class TigerSpatialMetadata final : public TigerFileBase -{ - public: - TigerSpatialMetadata(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerPIP (Type P records) */ -/************************************************************************/ - -class TigerPIP final : public TigerPoint -{ - public: - TigerPIP(OGRTigerDataSource *, const char *); - - virtual OGRFeature *GetFeature(int) override; -}; - -/************************************************************************/ -/* TigerTLIDRange (Type R records) */ -/************************************************************************/ - -class TigerTLIDRange final : public TigerFileBase -{ - public: - TigerTLIDRange(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerZeroCellID (Type T records) */ -/************************************************************************/ - -class TigerZeroCellID final : public TigerFileBase -{ - public: - TigerZeroCellID(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* TigerOverUnder (Type U records) */ -/************************************************************************/ - -class TigerOverUnder final : public TigerPoint -{ - public: - TigerOverUnder(OGRTigerDataSource *, const char *); - - virtual OGRFeature *GetFeature(int) override; -}; - -/************************************************************************/ -/* TigerZipPlus4 (Type Z records) */ -/************************************************************************/ - -class TigerZipPlus4 final : public TigerFileBase -{ - public: - TigerZipPlus4(OGRTigerDataSource *, const char *); -}; - -/************************************************************************/ -/* OGRTigerLayer */ -/************************************************************************/ - -class OGRTigerLayer final : public OGRLayer -{ - TigerFileBase *poReader; - - OGRTigerDataSource *poDS; - - int nFeatureCount; - int *panModuleFCount; - int *panModuleOffset; - - int iLastFeatureId; - int iLastModule; - - public: - OGRTigerLayer(OGRTigerDataSource *poDS, TigerFileBase *); - virtual ~OGRTigerLayer(); - - void ResetReading() override; - OGRFeature *GetNextFeature() override; - OGRFeature *GetFeature(GIntBig nFeatureId) override; - - OGRFeatureDefn *GetLayerDefn() override; - - GIntBig GetFeatureCount(int) override; - - int TestCapability(const char *) override; -}; - -/************************************************************************/ -/* OGRTigerDataSource */ -/************************************************************************/ - -class OGRTigerDataSource final : public GDALDataset -{ - int nLayers; - OGRTigerLayer **papoLayers; - - OGRSpatialReference *poSpatialRef; - - char **papszOptions; - - char *pszPath; - - int nModules; - char **papszModules; - - int nVersionCode; - TigerVersion nVersion; - - TigerVersion TigerCheckVersion(TigerVersion, const char *); - - CPL_DISALLOW_COPY_ASSIGN(OGRTigerDataSource) - - public: - OGRTigerDataSource(); - virtual ~OGRTigerDataSource(); - - TigerVersion GetVersion() const - { - return nVersion; - } - - int GetVersionCode() const - { - return nVersionCode; - } - - const char *GetOption(const char *); - - int Open(const char *pszName, int bTestOpen = FALSE, - char **papszFileList = nullptr); - - int GetLayerCount() override; - OGRLayer *GetLayer(int) override; - OGRLayer *GetLayer(const char *pszLayerName); - - void AddLayer(OGRTigerLayer *); - - OGRSpatialReference *DSGetSpatialRef() - { - return poSpatialRef; - } - - const char *GetDirPath() - { - return pszPath; - } - - char *BuildFilename(const char *pszModule, const char *pszExtension); - - int GetModuleCount() const - { - return nModules; - } - - const char *GetModule(int); - bool CheckModule(const char *pszModule); - void AddModule(const char *pszModule); -}; - -#endif /* ndef OGR_TIGER_H_INCLUDED */ diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp deleted file mode 100644 index edaacdaa8092..000000000000 --- a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp +++ /dev/null @@ -1,727 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements OGRTigerDataSource class - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_conv.h" -#include "cpl_string.h" -#include "ogr_tiger.h" - -#include -#include - -#define DIGIT_ZERO '0' - -/************************************************************************/ -/* TigerClassifyVersion() */ -/************************************************************************/ - -TigerVersion TigerClassifyVersion(int nVersionCode) - -{ - TigerVersion nVersion; - int nYear, nMonth; - - /* - ** TIGER Versions - ** - ** 0000 TIGER/Line Precensus Files, 1990 - ** 0002 TIGER/Line Initial Voting District Codes Files, 1990 - ** 0003 TIGER/Line Files, 1990 - ** 0005 TIGER/Line Files, 1992 - ** 0021 TIGER/Line Files, 1994 - ** 0024 TIGER/Line Files, 1995 - ** 9706 to 9810 TIGER/Line Files, 1997 - ** 9812 to 9904 TIGER/Line Files, 1998 - ** 0006 to 0008 TIGER/Line Files, 1999 - ** 0010 to 0011 TIGER/Line Files, Redistricting Census 2000 - ** 0103 to 0108 TIGER/Line Files, Census 2000 - ** - ** 0203 to 0205 TIGER/Line Files, UA 2000 - ** ???? ???? - ** - ** 0206 to 0299 TIGER/Line Files, 2002 - ** 0300 to 0399 TIGER/Line Files, 2003 - ** 0400+ TIGER/Line Files, 2004 - one sample is 0405 - ** ???? - */ - - nVersion = TIGER_Unknown; - if (nVersionCode == 0) - nVersion = TIGER_1990_Precensus; - else if (nVersionCode == 2) - nVersion = TIGER_1990; - else if (nVersionCode == 3) - nVersion = TIGER_1992; - else if (nVersionCode == 5) - nVersion = TIGER_1994; - else if (nVersionCode == 21) - nVersion = TIGER_1994; - else if (nVersionCode == 24) - nVersion = TIGER_1995; - - else if (nVersionCode == 9999) /* special hack, fme bug 7625 */ - nVersion = TIGER_UA2000; - - nYear = nVersionCode % 100; - nMonth = nVersionCode / 100; - - nVersionCode = nYear * 100 + nMonth; - - if (nVersion != TIGER_Unknown) - /* do nothing */; - else if (nVersionCode >= 9706 && nVersionCode <= 9810) - nVersion = TIGER_1997; - else if (nVersionCode >= 9812 && nVersionCode <= 9904) - nVersion = TIGER_1998; - else if (nVersionCode >= 6 /*0006*/ && nVersionCode <= 8 /*0008*/) - nVersion = TIGER_1999; - else if (nVersionCode >= 10 /*0010*/ && nVersionCode <= 11 /*0011*/) - nVersion = TIGER_2000_Redistricting; - else if (nVersionCode >= 103 /*0103*/ && nVersionCode <= 108 /*0108*/) - nVersion = TIGER_2000_Census; - else if (nVersionCode >= 203 /*0302*/ && nVersionCode <= 205 /*0502*/) - nVersion = TIGER_UA2000; - else if (nVersionCode >= 210 /*1002*/ && nVersionCode <= 306 /*0603*/) - nVersion = TIGER_2002; - else if (nVersionCode >= 312 /*1203*/ && nVersionCode <= 403 /*0304*/) - nVersion = TIGER_2003; - else if (nVersionCode >= 404) - nVersion = TIGER_2004; - - return nVersion; -} - -/************************************************************************/ -/* TigerVersionString() */ -/************************************************************************/ - -const char *TigerVersionString(TigerVersion nVersion) -{ - - if (nVersion == TIGER_1990_Precensus) - { - return "TIGER_1990_Precensus"; - } - if (nVersion == TIGER_1990) - { - return "TIGER_1990"; - } - if (nVersion == TIGER_1992) - { - return "TIGER_1992"; - } - if (nVersion == TIGER_1994) - { - return "TIGER_1994"; - } - if (nVersion == TIGER_1995) - { - return "TIGER_1995"; - } - if (nVersion == TIGER_1997) - { - return "TIGER_1997"; - } - if (nVersion == TIGER_1998) - { - return "TIGER_1998"; - } - if (nVersion == TIGER_1999) - { - return "TIGER_1999"; - } - if (nVersion == TIGER_2000_Redistricting) - { - return "TIGER_2000_Redistricting"; - } - if (nVersion == TIGER_UA2000) - { - return "TIGER_UA2000"; - } - if (nVersion == TIGER_2002) - { - return "TIGER_2002"; - } - if (nVersion == TIGER_2003) - { - return "TIGER_2003"; - } - if (nVersion == TIGER_2004) - { - return "TIGER_2004"; - } - if (nVersion == TIGER_Unknown) - { - return "TIGER_Unknown"; - } - return "???"; -} - -/************************************************************************/ -/* TigerCheckVersion() */ -/* */ -/* Some tiger products seem to be generated with version info */ -/* that doesn't match the tiger specs. We can sometimes */ -/* recognise the wrongness by checking the record length of */ -/* some well known changing files and adjusting the version */ -/* based on this. */ -/************************************************************************/ - -TigerVersion OGRTigerDataSource::TigerCheckVersion(TigerVersion nOldVersion, - const char *pszFilename) - -{ - if (nOldVersion != TIGER_2002) - return nOldVersion; - - char *pszRTCFilename = BuildFilename(pszFilename, "C"); - VSILFILE *fp = VSIFOpenL(pszRTCFilename, "rb"); - CPLFree(pszRTCFilename); - - if (fp == nullptr) - return nOldVersion; - - char szHeader[115]; - - if (VSIFReadL(szHeader, sizeof(szHeader) - 1, 1, fp) < 1) - { - VSIFCloseL(fp); - return nOldVersion; - } - - VSIFCloseL(fp); - - /* -------------------------------------------------------------------- */ - /* Is the record length 112? If so, it is an older version */ - /* than 2002. */ - /* -------------------------------------------------------------------- */ - if (szHeader[112] == 10 || szHeader[112] == 13) - { - CPLDebug("TIGER", - "Forcing version back to UA2000 since RTC records are short."); - return TIGER_UA2000; - } - - return nOldVersion; -} - -/************************************************************************/ -/* OGRTigerDataSource() */ -/************************************************************************/ - -OGRTigerDataSource::OGRTigerDataSource() - : nLayers(0), papoLayers(nullptr), poSpatialRef(new OGRSpatialReference()), - papszOptions(nullptr), pszPath(nullptr), nModules(0), - papszModules(nullptr), nVersionCode(0), nVersion(TIGER_Unknown) -{ - poSpatialRef->SetWellKnownGeogCS("NAD83"); - poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); -} - -/************************************************************************/ -/* ~OGRTigerDataSource() */ -/************************************************************************/ - -OGRTigerDataSource::~OGRTigerDataSource() - -{ - for (int i = 0; i < nLayers; i++) - delete papoLayers[i]; - - CPLFree(papoLayers); - - CPLFree(pszPath); - - CSLDestroy(papszOptions); - - CSLDestroy(papszModules); - - delete poSpatialRef; -} - -/************************************************************************/ -/* AddLayer() */ -/************************************************************************/ - -void OGRTigerDataSource::AddLayer(OGRTigerLayer *poNewLayer) - -{ - poNewLayer->SetDescription(poNewLayer->GetName()); - papoLayers = static_cast( - CPLRealloc(papoLayers, sizeof(void *) * ++nLayers)); - - papoLayers[nLayers - 1] = poNewLayer; -} - -/************************************************************************/ -/* GetLayer() */ -/************************************************************************/ - -OGRLayer *OGRTigerDataSource::GetLayer(int iLayer) - -{ - if (iLayer < 0 || iLayer >= nLayers) - return nullptr; - - return papoLayers[iLayer]; -} - -/************************************************************************/ -/* GetLayer() */ -/************************************************************************/ - -OGRLayer *OGRTigerDataSource::GetLayer(const char *pszLayerName) - -{ - for (int iLayer = 0; iLayer < nLayers; iLayer++) - { - if (EQUAL(papoLayers[iLayer]->GetLayerDefn()->GetName(), pszLayerName)) - return papoLayers[iLayer]; - } - - return nullptr; -} - -/************************************************************************/ -/* GetLayerCount() */ -/************************************************************************/ - -int OGRTigerDataSource::GetLayerCount() - -{ - return nLayers; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -int OGRTigerDataSource::Open(const char *pszFilename, int bTestOpen, - char **papszLimitedFileList) - -{ - /* -------------------------------------------------------------------- */ - /* Is the given path a directory or a regular file? */ - /* -------------------------------------------------------------------- */ - VSIStatBufL stat; - - if (VSIStatExL(pszFilename, &stat, - VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) != 0 || - (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode))) - { - if (!bTestOpen) - CPLError( - CE_Failure, CPLE_AppDefined, - "%s is neither a file or directory, Tiger access failed.\n", - pszFilename); - - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Build a list of filenames we figure are Tiger files. */ - /* -------------------------------------------------------------------- */ - char **papszFileList = nullptr; - if (VSI_ISREG(stat.st_mode)) - { - char szModule[128]; - - if (strlen(CPLGetFilename(pszFilename)) == 0) - { - return FALSE; - } - - pszPath = CPLStrdup(CPLGetPathSafe(pszFilename).c_str()); - - strncpy(szModule, CPLGetFilename(pszFilename), sizeof(szModule) - 1); - /* Make sure the buffer is 0 terminated */ - szModule[sizeof(szModule) - 1] = '\0'; - - /* And now remove last character of filename */ - szModule[strlen(szModule) - 1] = '\0'; - - papszFileList = CSLAddString(papszFileList, szModule); - } - else - { - char **candidateFileList = VSIReadDir(pszFilename); - - pszPath = CPLStrdup(pszFilename); - - for (int i = 0; - candidateFileList != nullptr && candidateFileList[i] != nullptr; - i++) - { - size_t nCandidateLen = strlen(candidateFileList[i]); - - if (papszLimitedFileList != nullptr && - CSLFindString( - papszLimitedFileList, - CPLGetBasenameSafe(candidateFileList[i]).c_str()) == -1) - { - continue; - } - - if (nCandidateLen > 4 && - candidateFileList[i][nCandidateLen - 4] == '.' && - candidateFileList[i][nCandidateLen - 1] == '1') - { - char szModule[128]; - - snprintf(szModule, sizeof(szModule), "%s", - candidateFileList[i]); - const size_t nLen = strlen(szModule); - if (nLen) - szModule[nLen - 1] = '\0'; - - papszFileList = CSLAddString(papszFileList, szModule); - } - } - - CSLDestroy(candidateFileList); - - if (CSLCount(papszFileList) == 0) - { - if (!bTestOpen) - CPLError(CE_Failure, CPLE_OpenFailed, - "No candidate Tiger files (TGR*.RT1) found in\n" - "directory: %s", - pszFilename); - CSLDestroy(papszFileList); - return FALSE; - } - } - - /* -------------------------------------------------------------------- */ - /* Loop over all these files trying to open them. In testopen */ - /* mode we first read the first 80 characters, to verify that */ - /* it looks like an Tiger file. Note that we don't keep the file */ - /* open ... we don't want to occupy a lot of file handles when */ - /* handling a whole directory. */ - /* -------------------------------------------------------------------- */ - papszModules = nullptr; - - for (int i = 0; papszFileList && papszFileList[i] != nullptr; i++) - { - if (bTestOpen || i == 0) - { - char *l_pszFilename = BuildFilename(papszFileList[i], "1"); - - VSILFILE *fp = VSIFOpenL(l_pszFilename, "rb"); - CPLFree(l_pszFilename); - - if (fp == nullptr) - continue; - - char szHeader[500] = {}; - if (VSIFReadL(szHeader, sizeof(szHeader) - 1, 1, fp) < 1) - { - VSIFCloseL(fp); - continue; - } - - VSIFCloseL(fp); - - char *pszRecStart = szHeader; - szHeader[sizeof(szHeader) - 1] = '\0'; - - bool bIsGDT = false; - - if (STARTS_WITH_CI(pszRecStart, "Copyright (C)") && - strstr(pszRecStart, "Geographic Data Tech") != nullptr) - { - bIsGDT = true; - - while (*pszRecStart != '\0' && *pszRecStart != 10 && - *pszRecStart != 13) - pszRecStart++; - - while (*pszRecStart == 10 || *pszRecStart == 13) - pszRecStart++; - } - - if (pszRecStart[0] != '1') - continue; - - if (!isdigit(static_cast(pszRecStart[1])) || - !isdigit(static_cast(pszRecStart[2])) || - !isdigit(static_cast(pszRecStart[3])) || - !isdigit(static_cast(pszRecStart[4]))) - continue; - - nVersionCode = atoi(TigerFileBase::GetField(pszRecStart, 2, 5)); - nVersion = TigerClassifyVersion(nVersionCode); - nVersion = TigerCheckVersion(nVersion, papszFileList[i]); - - CPLDebug("OGR", "Tiger Version Code=%d, Classified as %s ", - nVersionCode, TigerVersionString(nVersion)); - - if (nVersionCode != 0 && nVersionCode != 2 && nVersionCode != 3 && - nVersionCode != 5 && nVersionCode != 21 && nVersionCode != 24 && - pszRecStart[3] != '9' && pszRecStart[3] != DIGIT_ZERO && - !bIsGDT) - continue; - - // we could (and should) add a bunch more validation here. - } - - papszModules = CSLAddString(papszModules, papszFileList[i]); - } - - CSLDestroy(papszFileList); - - nModules = CSLCount(papszModules); - - if (nModules == 0 || papszModules == nullptr) - { - if (!bTestOpen) - { - if (VSI_ISREG(stat.st_mode)) - CPLError(CE_Failure, CPLE_OpenFailed, - "No TIGER/Line files (TGR*.RT1) found in\n" - "directory: %s", - pszFilename); - else - CPLError( - CE_Failure, CPLE_OpenFailed, - "File %s does not appear to be a TIGER/Line .RT1 file.", - pszFilename); - } - - return FALSE; - } - - /* -------------------------------------------------------------------- */ - /* Do we have a user provided version override? */ - /* -------------------------------------------------------------------- */ - const char *pszRequestedVersion = - CPLGetConfigOption("TIGER_VERSION", nullptr); - if (pszRequestedVersion != nullptr) - { - - if (STARTS_WITH_CI(pszRequestedVersion, "TIGER_")) - { - int iCode = 1; // Used after for. - - for (; iCode < TIGER_Unknown; iCode++) - { - if (EQUAL(TigerVersionString((TigerVersion)iCode), - pszRequestedVersion)) - { - nVersion = (TigerVersion)iCode; - break; - } - } - - if (iCode == TIGER_Unknown) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Failed to recognise TIGER_VERSION setting: %s", - pszRequestedVersion); - return FALSE; - } - - CPLDebug("OGR", "OVERRIDE Tiger Version %s ", - TigerVersionString(nVersion)); - } - else - { - nVersionCode = atoi(pszRequestedVersion); - nVersion = TigerClassifyVersion(nVersionCode); - - CPLDebug("OGR", "OVERRIDE Tiger Version Code=%d, Classified as %s ", - nVersionCode, TigerVersionString(nVersion)); - } - } - - /* -------------------------------------------------------------------- */ - /* Create the layers which appear to exist. */ - /* -------------------------------------------------------------------- */ - // RT1, RT2, RT3 - AddLayer( - new OGRTigerLayer(this, new TigerCompleteChain(this, papszModules[0]))); - - /* should we have kept track of whether we encountered an RT4 file? */ - // RT4 - AddLayer(new OGRTigerLayer(this, new TigerAltName(this, papszModules[0]))); - - // RT5 - AddLayer( - new OGRTigerLayer(this, new TigerFeatureIds(this, papszModules[0]))); - - // RT6 - AddLayer(new OGRTigerLayer(this, new TigerZipCodes(this, papszModules[0]))); - // RT7 - AddLayer( - new OGRTigerLayer(this, new TigerLandmarks(this, papszModules[0]))); - - // RT8 - AddLayer( - new OGRTigerLayer(this, new TigerAreaLandmarks(this, papszModules[0]))); - - // RT9 - if (nVersion < TIGER_2002) - { - AddLayer(new OGRTigerLayer( - this, new TigerKeyFeatures(this, papszModules[0]))); - } - - // RTA, RTS - AddLayer(new OGRTigerLayer(this, new TigerPolygon(this, papszModules[0]))); - - // RTB - if (nVersion >= TIGER_2002) - { - AddLayer(new OGRTigerLayer( - this, new TigerPolygonCorrections(this, papszModules[0]))); - } - - // RTC - AddLayer( - new OGRTigerLayer(this, new TigerEntityNames(this, papszModules[0]))); - - // RTE - if (nVersion >= TIGER_2002) - { - AddLayer(new OGRTigerLayer( - this, new TigerPolygonEconomic(this, papszModules[0]))); - } - - // RTH - AddLayer( - new OGRTigerLayer(this, new TigerIDHistory(this, papszModules[0]))); - - // RTI - AddLayer( - new OGRTigerLayer(this, new TigerPolyChainLink(this, papszModules[0]))); - - // RTM - AddLayer(new OGRTigerLayer( - this, new TigerSpatialMetadata(this, papszModules[0]))); - - // RTP - AddLayer(new OGRTigerLayer(this, new TigerPIP(this, papszModules[0]))); - - // RTR - AddLayer( - new OGRTigerLayer(this, new TigerTLIDRange(this, papszModules[0]))); - - // RTT - if (nVersion >= TIGER_2002) - { - AddLayer(new OGRTigerLayer(this, - new TigerZeroCellID(this, papszModules[0]))); - } - - // RTU - if (nVersion >= TIGER_2002) - { - AddLayer( - new OGRTigerLayer(this, new TigerOverUnder(this, papszModules[0]))); - } - - // RTZ - AddLayer(new OGRTigerLayer(this, new TigerZipPlus4(this, papszModules[0]))); - - return TRUE; -} - -/************************************************************************/ -/* GetOption() */ -/************************************************************************/ - -const char *OGRTigerDataSource::GetOption(const char *pszOption) - -{ - return CSLFetchNameValue(papszOptions, pszOption); -} - -/************************************************************************/ -/* GetModule() */ -/************************************************************************/ - -const char *OGRTigerDataSource::GetModule(int iModule) - -{ - if (iModule < 0 || iModule >= nModules) - return nullptr; - else - return papszModules[iModule]; -} - -/************************************************************************/ -/* CheckModule() */ -/* */ -/* This is used by the writer to check if this module has been */ -/* written to before. */ -/************************************************************************/ - -bool OGRTigerDataSource::CheckModule(const char *pszModule) - -{ - for (int i = 0; i < nModules; i++) - { - if (EQUAL(pszModule, papszModules[i])) - return true; - } - return false; -} - -/************************************************************************/ -/* AddModule() */ -/************************************************************************/ - -void OGRTigerDataSource::AddModule(const char *pszModule) - -{ - if (CheckModule(pszModule)) - return; - - papszModules = CSLAddString(papszModules, pszModule); - nModules++; -} - -/************************************************************************/ -/* BuildFilename() */ -/************************************************************************/ - -char *OGRTigerDataSource::BuildFilename(const char *pszModuleName, - const char *pszExtension) - -{ - /* -------------------------------------------------------------------- */ - /* Force the record type to lower case if the filename appears */ - /* to be in lower case. */ - /* -------------------------------------------------------------------- */ - char szLCExtension[3] = {}; - if (*pszExtension >= 'A' && *pszExtension <= 'Z' && *pszModuleName == 't') - { - szLCExtension[0] = (*pszExtension) + 'a' - 'A'; - szLCExtension[1] = '\0'; - pszExtension = szLCExtension; - } - - /* -------------------------------------------------------------------- */ - /* Build the filename. */ - /* -------------------------------------------------------------------- */ - const size_t nFilenameLen = strlen(GetDirPath()) + strlen(pszModuleName) + - strlen(pszExtension) + 10; - char *pszFilename = (char *)CPLMalloc(nFilenameLen); - - if (strlen(GetDirPath()) == 0) - snprintf(pszFilename, nFilenameLen, "%s%s", pszModuleName, - pszExtension); - else - snprintf(pszFilename, nFilenameLen, "%s/%s%s", GetDirPath(), - pszModuleName, pszExtension); - - return pszFilename; -} diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp deleted file mode 100644 index 29f41a4a6536..000000000000 --- a/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements OGRTigerDriver - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -static GDALDataset *OGRTigerDriverOpen(GDALOpenInfo *poOpenInfo) - -{ - if (!poOpenInfo->bStatOK) - return nullptr; - char **papszSiblingFiles = poOpenInfo->GetSiblingFiles(); - if (papszSiblingFiles != nullptr) - { - bool bFoundCompatibleFile = false; - for (int i = 0; papszSiblingFiles[i] != nullptr; i++) - { - int nLen = (int)strlen(papszSiblingFiles[i]); - if (nLen > 4 && papszSiblingFiles[i][nLen - 4] == '.' && - papszSiblingFiles[i][nLen - 1] == '1') - { - bFoundCompatibleFile = true; - break; - } - } - if (!bFoundCompatibleFile) - return nullptr; - } - - OGRTigerDataSource *poDS = new OGRTigerDataSource; - - if (!poDS->Open(poOpenInfo->pszFilename, TRUE)) - { - delete poDS; - poDS = nullptr; - } - - if (poDS != nullptr && poOpenInfo->eAccess == GA_Update) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Tiger Driver doesn't support update."); - delete poDS; - poDS = nullptr; - } - - return poDS; -} - -/************************************************************************/ -/* RegisterOGRTiger() */ -/************************************************************************/ - -void RegisterOGRTiger() - -{ - if (GDALGetDriverByName("TIGER") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("TIGER"); - poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "U.S. Census TIGER/Line"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/tiger.html"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); - - poDriver->pfnOpen = OGRTigerDriverOpen; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp deleted file mode 100644 index 38481b2ed501..000000000000 --- a/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements OGRTigerLayer class. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" - -/************************************************************************/ -/* OGRTigerLayer() */ -/* */ -/* Note that the OGRTigerLayer assumes ownership of the passed */ -/* OGRFeatureDefn object. */ -/************************************************************************/ - -OGRTigerLayer::OGRTigerLayer(OGRTigerDataSource *poDSIn, - TigerFileBase *poReaderIn) - : poReader(poReaderIn), poDS(poDSIn), nFeatureCount(0), - panModuleFCount(nullptr), panModuleOffset(nullptr), iLastFeatureId(0), - iLastModule(-1) -{ - /* -------------------------------------------------------------------- */ - /* Setup module feature counts. */ - /* -------------------------------------------------------------------- */ - panModuleFCount = (int *)CPLCalloc(poDS->GetModuleCount(), sizeof(int)); - panModuleOffset = (int *)CPLCalloc(poDS->GetModuleCount() + 1, sizeof(int)); - - nFeatureCount = 0; - - for (int iModule = 0; iModule < poDS->GetModuleCount(); iModule++) - { - if (poReader->SetModule(poDS->GetModule(iModule))) - panModuleFCount[iModule] = poReader->GetFeatureCount(); - else - panModuleFCount[iModule] = 0; - - panModuleOffset[iModule] = nFeatureCount; - nFeatureCount += panModuleFCount[iModule]; - } - - // this entry is just to make range comparisons easy without worrying - // about falling off the end of the array. - panModuleOffset[poDS->GetModuleCount()] = nFeatureCount; - - poReader->SetModule(nullptr); -} - -/************************************************************************/ -/* ~OGRTigerLayer() */ -/************************************************************************/ - -OGRTigerLayer::~OGRTigerLayer() - -{ - if (m_nFeaturesRead > 0 && poReader->GetFeatureDefn() != nullptr) - { - CPLDebug("TIGER", "%d features read on layer '%s'.", - (int)m_nFeaturesRead, poReader->GetFeatureDefn()->GetName()); - } - - delete poReader; - - CPLFree(panModuleFCount); - CPLFree(panModuleOffset); -} - -/************************************************************************/ -/* ResetReading() */ -/************************************************************************/ - -void OGRTigerLayer::ResetReading() - -{ - iLastFeatureId = 0; - iLastModule = -1; -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ - -OGRFeature *OGRTigerLayer::GetFeature(GIntBig nFeatureId) - -{ - if (nFeatureId < 1 || nFeatureId > nFeatureCount) - return nullptr; - - /* -------------------------------------------------------------------- */ - /* If we don't have the current module open for the requested */ - /* data, then open it now. */ - /* -------------------------------------------------------------------- */ - if (iLastModule == -1 || nFeatureId <= panModuleOffset[iLastModule] || - nFeatureId > panModuleOffset[iLastModule + 1]) - { - for (iLastModule = 0; iLastModule < poDS->GetModuleCount() && - nFeatureId > panModuleOffset[iLastModule + 1]; - iLastModule++) - { - } - - if (!poReader->SetModule(poDS->GetModule(iLastModule))) - { - return nullptr; - } - } - - /* -------------------------------------------------------------------- */ - /* Fetch the feature associated with the record. */ - /* -------------------------------------------------------------------- */ - OGRFeature *poFeature = poReader->GetFeature( - (int)nFeatureId - panModuleOffset[iLastModule] - 1); - - if (poFeature != nullptr) - { - poFeature->SetFID(nFeatureId); - - if (poFeature->GetGeometryRef() != nullptr) - poFeature->GetGeometryRef()->assignSpatialReference( - poDS->DSGetSpatialRef()); - - poFeature->SetField(0, poReader->GetShortModule()); - - m_nFeaturesRead++; - } - - return poFeature; -} - -/************************************************************************/ -/* GetNextFeature() */ -/************************************************************************/ - -OGRFeature *OGRTigerLayer::GetNextFeature() - -{ - /* -------------------------------------------------------------------- */ - /* Read features till we find one that satisfies our current */ - /* spatial criteria. */ - /* -------------------------------------------------------------------- */ - while (iLastFeatureId < nFeatureCount) - { - OGRFeature *poFeature = GetFeature(++iLastFeatureId); - - if (poFeature == nullptr) - break; - - if ((m_poFilterGeom == nullptr || - FilterGeometry(poFeature->GetGeometryRef())) && - (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature))) - return poFeature; - - delete poFeature; - } - - return nullptr; -} - -/************************************************************************/ -/* TestCapability() */ -/************************************************************************/ - -int OGRTigerLayer::TestCapability(const char *pszCap) - -{ - if (EQUAL(pszCap, OLCRandomRead)) - return TRUE; - - else if (EQUAL(pszCap, OLCFastFeatureCount)) - return TRUE; - - else - return FALSE; -} - -/************************************************************************/ -/* GetLayerDefn() */ -/************************************************************************/ - -OGRFeatureDefn *OGRTigerLayer::GetLayerDefn() - -{ - OGRFeatureDefn *poFDefn = poReader->GetFeatureDefn(); - if (poFDefn != nullptr) - { - if (poFDefn->GetGeomFieldCount() > 0) - poFDefn->GetGeomFieldDefn(0)->SetSpatialRef( - poDS->DSGetSpatialRef()); - } - return poFDefn; -} - -/************************************************************************/ -/* GetFeatureCount() */ -/************************************************************************/ - -GIntBig OGRTigerLayer::GetFeatureCount(int bForce) - -{ - if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr) - return nFeatureCount; - else - return OGRLayer::GetFeatureCount(bForce); -} diff --git a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp deleted file mode 100644 index f270d794460c..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerAltName, providing access to RT4 files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -#include - -static const char FOUR_FILE_CODE[] = "4"; - -static const TigerFieldInfo rt4_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 1, 1}, - {"RTSQ", 'R', 'N', OFTInteger, 16, 18, 3, 1, 1}, - {"FEAT", ' ', ' ', OFTIntegerList, 0, 0, 8, 1, 0} - // Note: we don't mention the FEAT1, FEAT2, FEAT3, FEAT4, FEAT5 fields - // here because they're handled separately in the code below; they - // correspond - // to the FEAT array field here. -}; - -static const TigerRecordInfo rt4_info = { - rt4_fields, sizeof(rt4_fields) / sizeof(TigerFieldInfo), 58}; - -/************************************************************************/ -/* TigerAltName() */ -/************************************************************************/ - -TigerAltName::TigerAltName(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rt4_info, FOUR_FILE_CODE) -{ - OGRFieldDefn oField("", OFTInteger); - - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("AltName"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from type 4 record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ - -OGRFeature *TigerAltName::GetFeature(int nRecordId) - -{ - char achRecord[OGR_TIGER_RECBUF_LEN]; - - if (nRecordId < 0 || nRecordId >= nFeatures) - { - CPLError(CE_Failure, CPLE_FileIO, - "Request for out-of-range feature %d of %s4", nRecordId, - pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Read the raw record data from the file. */ - /* -------------------------------------------------------------------- */ - if (fpPrimary == nullptr) - return nullptr; - - const auto nOffset = static_cast(nRecordId) * nRecordLength; - if (VSIFSeekL(fpPrimary, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %s4", nOffset, pszModule); - return nullptr; - } - - // Overflow cannot happen since psRTInfo->nRecordLength is unsigned - // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255 - if (VSIFReadL(achRecord, psRTInfo->nRecordLength, 1, fpPrimary) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to read record %d of %s4", - nRecordId, pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Set fields. */ - /* -------------------------------------------------------------------- */ - - OGRFeature *poFeature = new OGRFeature(poFeatureDefn); - int anFeatList[5] = {0}; - int nFeatCount = 0; - - SetFields(psRTInfo, poFeature, achRecord); - - for (int iFeat = 0; iFeat < 5; iFeat++) - { - const char *pszFieldText = - GetField(achRecord, 19 + iFeat * 8, 26 + iFeat * 8); - - if (*pszFieldText != '\0') - anFeatList[nFeatCount++] = atoi(pszFieldText); - } - - poFeature->SetField("FEAT", nFeatCount, anFeatList); - - return poFeature; -} diff --git a/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp b/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp deleted file mode 100644 index 8ec1ec7fa7ef..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerAreaLandmarks, providing access to .RT8 files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char EIGHT_FILE_CODE[] = "8"; - -static const TigerFieldInfo rt8_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 1, 1}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"LAND", 'R', 'N', OFTInteger, 26, 35, 10, 1, 1}}; - -static const TigerRecordInfo rt8_info = { - rt8_fields, sizeof(rt8_fields) / sizeof(TigerFieldInfo), 36}; - -/************************************************************************/ -/* TigerAreaLandmarks() */ -/************************************************************************/ - -TigerAreaLandmarks::TigerAreaLandmarks( - OGRTigerDataSource *poDSIn, CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rt8_info, EIGHT_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("AreaLandmarks"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from type 8 record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp deleted file mode 100644 index a281e5a42d89..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerCompleteChain, providing access to RT1 and - * related files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -#include - -static const TigerFieldInfo rt1_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 1, 1}, - {"SIDE1", 'R', 'N', OFTInteger, 16, 16, 1, 1, 1}, - {"SOURCE", 'L', 'A', OFTString, 17, 17, 1, 1, 1}, - {"FEDIRP", 'L', 'A', OFTString, 18, 19, 2, 1, 1}, - {"FENAME", 'L', 'A', OFTString, 20, 49, 30, 1, 1}, - {"FETYPE", 'L', 'A', OFTString, 50, 53, 4, 1, 1}, - {"FEDIRS", 'L', 'A', OFTString, 54, 55, 2, 1, 1}, - {"CFCC", 'L', 'A', OFTString, 56, 58, 3, 1, 1}, - {"FRADDL", 'R', 'A', OFTString, 59, 69, 11, 1, 1}, - {"TOADDL", 'R', 'A', OFTString, 70, 80, 11, 1, 1}, - {"FRADDR", 'R', 'A', OFTString, 81, 91, 11, 1, 1}, - {"TOADDR", 'R', 'A', OFTString, 92, 102, 11, 1, 1}, - {"FRIADDL", 'L', 'A', OFTString, 103, 103, 1, 1, 1}, - {"TOIADDL", 'L', 'A', OFTString, 104, 104, 1, 1, 1}, - {"FRIADDR", 'L', 'A', OFTString, 105, 105, 1, 1, 1}, - {"TOIADDR", 'L', 'A', OFTString, 106, 106, 1, 1, 1}, - {"ZIPL", 'L', 'N', OFTInteger, 107, 111, 5, 1, 1}, - {"ZIPR", 'L', 'N', OFTInteger, 112, 116, 5, 1, 1}, - {"AIANHHFPL", 'L', 'N', OFTInteger, 117, 121, 5, 1, 1}, - {"AIANHHFPR", 'L', 'N', OFTInteger, 122, 126, 5, 1, 1}, - {"AIHHTLIL", 'L', 'A', OFTString, 127, 127, 1, 1, 1}, - {"AIHHTLIR", 'L', 'A', OFTString, 128, 128, 1, 1, 1}, - {"CENSUS1", 'L', 'A', OFTString, 129, 129, 1, 1, 1}, - {"CENSUS2", 'L', 'A', OFTString, 130, 130, 1, 1, 1}, - {"STATEL", 'L', 'N', OFTInteger, 131, 132, 2, 1, 1}, - {"STATER", 'L', 'N', OFTInteger, 133, 134, 2, 1, 1}, - {"COUNTYL", 'L', 'N', OFTInteger, 135, 137, 3, 1, 1}, - {"COUNTYR", 'L', 'N', OFTInteger, 138, 140, 3, 1, 1}, - - {"COUSUBL", 'L', 'N', OFTInteger, 141, 145, 5, 1, 1}, - {"COUSUBR", 'L', 'N', OFTInteger, 146, 150, 5, 1, 1}, - {"SUBMCDL", 'L', 'N', OFTInteger, 151, 155, 5, 1, 1}, - {"SUBMCDR", 'L', 'N', OFTInteger, 156, 160, 5, 1, 1}, - {"PLACEL", 'L', 'N', OFTInteger, 161, 165, 5, 1, 1}, - {"PLACER", 'L', 'N', OFTInteger, 166, 170, 5, 1, 1}, - {"TRACTL", 'L', 'N', OFTInteger, 171, 176, 6, 1, 1}, - {"TRACTR", 'L', 'N', OFTInteger, 177, 182, 6, 1, 1}, - {"BLOCKL", 'L', 'N', OFTInteger, 183, 186, 4, 1, 1}, - {"BLOCKR", 'L', 'N', OFTInteger, 187, 190, 4, 1, 1}}; -static const TigerRecordInfo rt1_2002_info = { - rt1_2002_fields, sizeof(rt1_2002_fields) / sizeof(TigerFieldInfo), 228}; - -static const TigerFieldInfo rt1_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 1, 1}, - {"SIDE1", 'R', 'N', OFTInteger, 16, 16, 1, 1, 1}, - {"SOURCE", 'L', 'A', OFTString, 17, 17, 1, 1, 1}, - {"FEDIRP", 'L', 'A', OFTString, 18, 19, 2, 1, 1}, - {"FENAME", 'L', 'A', OFTString, 20, 49, 30, 1, 1}, - {"FETYPE", 'L', 'A', OFTString, 50, 53, 4, 1, 1}, - {"FEDIRS", 'L', 'A', OFTString, 54, 55, 2, 1, 1}, - {"CFCC", 'L', 'A', OFTString, 56, 58, 3, 1, 1}, - {"FRADDL", 'R', 'A', OFTString, 59, 69, 11, 1, 1}, - {"TOADDL", 'R', 'A', OFTString, 70, 80, 11, 1, 1}, - {"FRADDR", 'R', 'A', OFTString, 81, 91, 11, 1, 1}, - {"TOADDR", 'R', 'A', OFTString, 92, 102, 11, 1, 1}, - {"FRIADDL", 'L', 'A', OFTInteger, 103, 103, 1, 1, 1}, - {"TOIADDL", 'L', 'A', OFTInteger, 104, 104, 1, 1, 1}, - {"FRIADDR", 'L', 'A', OFTInteger, 105, 105, 1, 1, 1}, - {"TOIADDR", 'L', 'A', OFTInteger, 106, 106, 1, 1, 1}, - {"ZIPL", 'L', 'N', OFTInteger, 107, 111, 5, 1, 1}, - {"ZIPR", 'L', 'N', OFTInteger, 112, 116, 5, 1, 1}, - {"FAIRL", 'L', 'N', OFTInteger, 117, 121, 5, 1, 1}, - {"FAIRR", 'L', 'N', OFTInteger, 122, 126, 5, 1, 1}, - {"TRUSTL", 'L', 'A', OFTString, 127, 127, 1, 1, 1}, - {"TRUSTR", 'L', 'A', OFTString, 128, 128, 1, 1, 1}, - {"CENSUS1", 'L', 'A', OFTString, 129, 129, 1, 1, 1}, - {"CENSUS2", 'L', 'A', OFTString, 130, 130, 1, 1, 1}, - {"STATEL", 'L', 'N', OFTInteger, 131, 132, 2, 1, 1}, - {"STATER", 'L', 'N', OFTInteger, 133, 134, 2, 1, 1}, - {"COUNTYL", 'L', 'N', OFTInteger, 135, 137, 3, 1, 1}, - {"COUNTYR", 'L', 'N', OFTInteger, 138, 140, 3, 1, 1}, - - {"FMCDL", 'L', 'N', OFTInteger, 141, 145, 5, 1, 1}, - {"FMCDR", 'L', 'N', OFTInteger, 146, 150, 5, 1, 1}, - {"FSMCDL", 'L', 'N', OFTInteger, 151, 155, 5, 1, 1}, - {"FSMCDR", 'L', 'N', OFTInteger, 156, 160, 5, 1, 1}, - {"FPLL", 'L', 'N', OFTInteger, 161, 165, 5, 1, 1}, - {"FPLR", 'L', 'N', OFTInteger, 166, 170, 5, 1, 1}, - {"CTBNAL", 'L', 'N', OFTInteger, 171, 176, 6, 1, 1}, - {"CTBNAR", 'L', 'N', OFTInteger, 177, 182, 6, 1, 1}, - {"BLKL", 'L', 'N', OFTString, 183, 186, 4, 1, 1}, - {"BLKR", 'L', 'N', OFTString, 187, 190, 4, 1, 1}}; -static const TigerRecordInfo rt1_info = { - rt1_fields, sizeof(rt1_fields) / sizeof(TigerFieldInfo), 228}; - -static const TigerRecordInfo rt2_info = { - nullptr, // RT2 is handled specially in the code below; the only - 0, // thing from this structure that is used is: - 208 // <--- nRecordLength -}; - -static const TigerFieldInfo rt3_2000_Redistricting_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 0, 0}, - {"STATE90L", 'L', 'N', OFTInteger, 16, 17, 2, 1, 1}, - {"STATE90R", 'L', 'N', OFTInteger, 18, 19, 2, 1, 1}, - {"COUN90L", 'L', 'N', OFTInteger, 20, 22, 3, 1, 1}, - {"COUN90R", 'L', 'N', OFTInteger, 23, 25, 3, 1, 1}, - {"FMCD90L", 'L', 'N', OFTInteger, 26, 30, 5, 1, 1}, - {"FMCD90R", 'L', 'N', OFTInteger, 31, 35, 5, 1, 1}, - {"FPL90L", 'L', 'N', OFTInteger, 36, 40, 5, 1, 1}, - {"FPL90R", 'L', 'N', OFTInteger, 41, 45, 5, 1, 1}, - {"CTBNA90L", 'L', 'N', OFTInteger, 46, 51, 6, 1, 1}, - {"CTBNA90R", 'L', 'N', OFTInteger, 52, 57, 6, 1, 1}, - {"AIR90L", 'L', 'N', OFTInteger, 58, 61, 4, 1, 1}, - {"AIR90R", 'L', 'N', OFTInteger, 62, 65, 4, 1, 1}, - {"TRUST90L", 'L', 'A', OFTString, 66, 66, 1, 1, 1}, - {"TRUST90R", 'L', 'A', OFTString, 67, 67, 1, 1, 1}, - {"BLK90L", 'L', 'A', OFTString, 70, 73, 4, 1, 1}, - {"BLK90R", 'L', 'A', OFTString, 74, 77, 4, 1, 1}, - {"AIRL", 'L', 'N', OFTInteger, 78, 81, 4, 1, 1}, - {"AIRR", 'L', 'N', OFTInteger, 82, 85, 4, 1, 1}, - - {"ANRCL", 'L', 'N', OFTInteger, 86, 90, 5, 1, 1}, - {"ANRCR", 'L', 'N', OFTInteger, 91, 95, 5, 1, 1}, - {"AITSCEL", 'L', 'N', OFTInteger, 96, 98, 3, 1, 1}, - {"AITSCER", 'L', 'N', OFTInteger, 99, 101, 3, 1, 1}, - {"AITSL", 'L', 'N', OFTInteger, 102, 106, 5, 1, 1}, - {"AITSR", 'L', 'N', OFTInteger, 107, 111, 5, 1, 1}}; -static const TigerRecordInfo rt3_2000_Redistricting_info = { - rt3_2000_Redistricting_fields, - sizeof(rt3_2000_Redistricting_fields) / sizeof(TigerFieldInfo), 111}; - -static const TigerFieldInfo rt3_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 0, 0}, - {"STATE90L", 'L', 'N', OFTInteger, 16, 17, 2, 1, 1}, - {"STATE90R", 'L', 'N', OFTInteger, 18, 19, 2, 1, 1}, - {"COUN90L", 'L', 'N', OFTInteger, 20, 22, 3, 1, 1}, - {"COUN90R", 'L', 'N', OFTInteger, 23, 25, 3, 1, 1}, - {"FMCD90L", 'L', 'N', OFTInteger, 26, 30, 5, 1, 1}, - {"FMCD90R", 'L', 'N', OFTInteger, 31, 35, 5, 1, 1}, - {"FPL90L", 'L', 'N', OFTInteger, 36, 40, 5, 1, 1}, - {"FPL90R", 'L', 'N', OFTInteger, 41, 45, 5, 1, 1}, - {"CTBNA90L", 'L', 'N', OFTInteger, 46, 51, 6, 1, 1}, - {"CTBNA90R", 'L', 'N', OFTInteger, 52, 57, 6, 1, 1}, - {"AIR90L", 'L', 'N', OFTInteger, 58, 61, 4, 1, 1}, - {"AIR90R", 'L', 'N', OFTInteger, 62, 65, 4, 1, 1}, - {"TRUST90L", 'L', 'A', OFTInteger, 66, 66, 1, 1, 1}, - {"TRUST90R", 'L', 'A', OFTInteger, 67, 67, 1, 1, 1}, - {"BLK90L", 'L', 'A', OFTString, 70, 73, 4, 1, 1}, - {"BLK90R", 'L', 'A', OFTString, 74, 77, 4, 1, 1}, - {"AIRL", 'L', 'N', OFTInteger, 78, 81, 4, 1, 1}, - {"AIRR", 'L', 'N', OFTInteger, 82, 85, 4, 1, 1}, - - {"VTDL", 'L', 'A', OFTString, 104, 107, 4, 1, 1}, - {"VTDR", 'L', 'A', OFTString, 108, 111, 4, 1, 1}}; - -static const TigerRecordInfo rt3_info = { - rt3_fields, sizeof(rt3_fields) / sizeof(TigerFieldInfo), 111}; - -/************************************************************************/ -/* TigerCompleteChain() */ -/************************************************************************/ - -TigerCompleteChain::TigerCompleteChain(OGRTigerDataSource *poDSIn, - const char * /* pszPrototypeModule */) - : fpShape(nullptr), panShapeRecordId(nullptr), fpRT3(nullptr), - bUsingRT3(false), psRT1Info(nullptr), psRT2Info(nullptr), - psRT3Info(nullptr) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("CompleteChain"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbLineString); - - if (poDS->GetVersion() >= TIGER_2002) - { - psRT1Info = &rt1_2002_info; - // bUsingRT3 = false; - } - else - { - psRT1Info = &rt1_info; - bUsingRT3 = true; - } - - psRT2Info = &rt2_info; - - nRT1RecOffset = 0; - - if (poDS->GetVersion() >= TIGER_2000_Redistricting) - { - psRT3Info = &rt3_2000_Redistricting_info; - } - else - { - psRT3Info = &rt3_info; - } - - /* -------------------------------------------------------------------- */ - /* Fields from type 1 record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRT1Info, poFeatureDefn); - - /* -------------------------------------------------------------------- */ - /* Fields from type 3 record. Eventually we should verify that */ - /* a .RT3 file is available before adding these fields. */ - /* -------------------------------------------------------------------- */ - if (bUsingRT3) - { - AddFieldDefns(psRT3Info, poFeatureDefn); - } -} - -/************************************************************************/ -/* ~TigerCompleteChain() */ -/************************************************************************/ - -TigerCompleteChain::~TigerCompleteChain() - -{ - CPLFree(panShapeRecordId); - - if (fpRT3 != nullptr) - VSIFCloseL(fpRT3); - - if (fpShape != nullptr) - VSIFCloseL(fpShape); -} - -/************************************************************************/ -/* SetModule() */ -/************************************************************************/ - -bool TigerCompleteChain::SetModule(const char *pszModuleIn) - -{ - if (!OpenFile(pszModuleIn, "1")) - return false; - - EstablishFeatureCount(); - - /* -------------------------------------------------------------------- */ - /* Is this a copyright record inserted at the beginning of the */ - /* RT1 file by the folks at GDT? If so, setup to ignore the */ - /* first record. */ - /* -------------------------------------------------------------------- */ - nRT1RecOffset = 0; - if (pszModuleIn) - { - char achHeader[10]; - - VSIFSeekL(fpPrimary, 0, SEEK_SET); - VSIFReadL(achHeader, sizeof(achHeader), 1, fpPrimary); - - if (STARTS_WITH_CI(achHeader, "Copyright")) - { - nRT1RecOffset = 1; - nFeatures--; - } - } - - /* -------------------------------------------------------------------- */ - /* Open the RT3 file */ - /* -------------------------------------------------------------------- */ - if (bUsingRT3) - { - if (fpRT3 != nullptr) - { - VSIFCloseL(fpRT3); - fpRT3 = nullptr; - } - - if (pszModuleIn) - { - char *pszFilename = poDS->BuildFilename(pszModuleIn, "3"); - - fpRT3 = VSIFOpenL(pszFilename, "rb"); - - CPLFree(pszFilename); - } - } - - /* -------------------------------------------------------------------- */ - /* Close the shape point file, if open and free the list of */ - /* record ids. */ - /* -------------------------------------------------------------------- */ - if (fpShape != nullptr) - { - VSIFCloseL(fpShape); - fpShape = nullptr; - } - - CPLFree(panShapeRecordId); - panShapeRecordId = nullptr; - - /* -------------------------------------------------------------------- */ - /* Try to open the RT2 file corresponding to this RT1 file. */ - /* -------------------------------------------------------------------- */ - if (pszModuleIn != nullptr) - { - char *pszFilename = poDS->BuildFilename(pszModuleIn, "2"); - - fpShape = VSIFOpenL(pszFilename, "rb"); - - if (fpShape == nullptr) - { - if (nRT1RecOffset == 0) - CPLError(CE_Warning, CPLE_OpenFailed, - "Failed to open %s, intermediate shape arcs will not " - "be available.\n", - pszFilename); - } - else - panShapeRecordId = - (int *)CPLCalloc(sizeof(int), (size_t)GetFeatureCount()); - - CPLFree(pszFilename); - } - - return true; -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ - -OGRFeature *TigerCompleteChain::GetFeature(int nRecordId) - -{ - char achRecord[OGR_TIGER_RECBUF_LEN]; - - if (nRecordId < 0 || nRecordId >= nFeatures) - { - CPLError(CE_Failure, CPLE_FileIO, - "Request for out-of-range feature %d of %s1", nRecordId, - pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Read the raw record data from the file. */ - /* -------------------------------------------------------------------- */ - if (fpPrimary == nullptr) - return nullptr; - - { - const auto nOffset = - static_cast(nRecordId + nRT1RecOffset) * nRecordLength; - if (VSIFSeekL(fpPrimary, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %s1", nOffset, - pszModule); - return nullptr; - } - } - - // Overflow cannot happen since psRTInfo->nRecordLength is unsigned - // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255 - if (VSIFReadL(achRecord, psRT1Info->nRecordLength, 1, fpPrimary) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to read %d bytes of record %d of %s1 at offset %d", - psRT1Info->nRecordLength, nRecordId, pszModule, - (nRecordId + nRT1RecOffset) * nRecordLength); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Set fields. */ - /* -------------------------------------------------------------------- */ - - auto poFeature = std::make_unique(poFeatureDefn); - - SetFields(psRT1Info, poFeature.get(), achRecord); - - /* -------------------------------------------------------------------- */ - /* Read RT3 record, and apply fields. */ - /* -------------------------------------------------------------------- */ - - if (fpRT3 != nullptr) - { - char achRT3Rec[OGR_TIGER_RECBUF_LEN]; - int nRT3RecLen = - psRT3Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength; - - const auto nOffset = static_cast(nRecordId) * nRT3RecLen; - if (VSIFSeekL(fpRT3, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %s3", nOffset, - pszModule); - return nullptr; - } - - // Overflow cannot happen since psRTInfo->nRecordLength is unsigned - // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255 - if (VSIFReadL(achRT3Rec, psRT3Info->nRecordLength, 1, fpRT3) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to read record %d of %s3", - nRecordId, pszModule); - return nullptr; - } - - SetFields(psRT3Info, poFeature.get(), achRT3Rec); - } - - /* -------------------------------------------------------------------- */ - /* Set geometry */ - /* -------------------------------------------------------------------- */ - auto poLine = std::make_unique(); - - poLine->setPoint(0, atoi(GetField(achRecord, 191, 200)) / 1000000.0, - atoi(GetField(achRecord, 201, 209)) / 1000000.0); - - if (!AddShapePoints(poFeature->GetFieldAsInteger("TLID"), nRecordId, - poLine.get(), 0)) - { - return nullptr; - } - - poLine->addPoint(atoi(GetField(achRecord, 210, 219)) / 1000000.0, - atoi(GetField(achRecord, 220, 228)) / 1000000.0); - - poFeature->SetGeometryDirectly(poLine.release()); - - return poFeature.release(); -} - -/************************************************************************/ -/* AddShapePoints() */ -/* */ -/* Record zero or more shape records associated with this line */ -/* and add the points to the passed line geometry. */ -/************************************************************************/ - -bool TigerCompleteChain::AddShapePoints(int nTLID, int nRecordId, - OGRLineString *poLine, - CPL_UNUSED int nSeqNum) -{ - int nShapeRecId = GetShapeRecordId(nRecordId, nTLID); - - // -2 means an error occurred. - if (nShapeRecId == -2) - return false; - - // -1 means there are no extra shape vertices, but things worked fine. - if (nShapeRecId == -1) - return true; - - /* -------------------------------------------------------------------- */ - /* Read all the sequential records with the same TLID. */ - /* -------------------------------------------------------------------- */ - char achShapeRec[OGR_TIGER_RECBUF_LEN]; - const int nShapeRecLen = - psRT2Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength; - - for (; true; nShapeRecId++) - { - int nBytesRead = 0; - - const auto nOffset = - static_cast(nShapeRecId - 1) * nShapeRecLen; - if (VSIFSeekL(fpShape, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %s2", nOffset, - pszModule); - return false; - } - - nBytesRead = static_cast( - VSIFReadL(achShapeRec, 1, psRT2Info->nRecordLength, fpShape)); - - /* - ** Handle case where the last record in the file is full. We will - ** try to read another record but not find it. We require that we - ** have found at least one shape record for this case though. - */ - if (nBytesRead <= 0 && VSIFEofL(fpShape) && poLine->getNumPoints() > 0) - break; - - if (nBytesRead != psRT2Info->nRecordLength) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to read %d bytes of record %d of %s2 at offset %d", - psRT2Info->nRecordLength, nShapeRecId, pszModule, - (nShapeRecId - 1) * nShapeRecLen); - return false; - } - - if (atoi(GetField(achShapeRec, 6, 15)) != nTLID) - break; - - /* -------------------------------------------------------------------- - */ - /* Translate the locations into OGRLineString vertices. */ - /* -------------------------------------------------------------------- - */ - int iVertex = 0; // Used after for. - - for (; iVertex < 10; iVertex++) - { - const int iStart = 19 + 19 * iVertex; - const int nX = atoi(GetField(achShapeRec, iStart, iStart + 9)); - const int nY = - atoi(GetField(achShapeRec, iStart + 10, iStart + 18)); - - if (nX == 0 && nY == 0) - break; - - poLine->addPoint(nX / 1000000.0, nY / 1000000.0); - } - - /* -------------------------------------------------------------------- - */ - /* Don't get another record if this one was incomplete. */ - /* -------------------------------------------------------------------- - */ - if (iVertex < 10) - break; - } - - return true; -} - -/************************************************************************/ -/* GetShapeRecordId() */ -/* */ -/* Get the record id of the first record of shape points for */ -/* the provided TLID (complete chain). */ -/************************************************************************/ - -int TigerCompleteChain::GetShapeRecordId(int nChainId, int nTLID) - -{ - CPLAssert(nChainId >= 0 && nChainId < GetFeatureCount()); - - if (fpShape == nullptr || panShapeRecordId == nullptr) - return -1; - - /* -------------------------------------------------------------------- */ - /* Do we already have the answer? */ - /* -------------------------------------------------------------------- */ - if (panShapeRecordId[nChainId] != 0) - return panShapeRecordId[nChainId]; - - /* -------------------------------------------------------------------- */ - /* If we don't already have this value, then search from the */ - /* previous known record. */ - /* -------------------------------------------------------------------- */ - int iTestChain, nWorkingRecId; - - for (iTestChain = nChainId - 1; - iTestChain >= 0 && panShapeRecordId[iTestChain] <= 0; iTestChain--) - { - } - - if (iTestChain < 0) - { - iTestChain = -1; - nWorkingRecId = 1; - } - else - { - nWorkingRecId = panShapeRecordId[iTestChain] + 1; - } - - /* -------------------------------------------------------------------- */ - /* If we have non existent records following (-1's) we can */ - /* narrow our search a bit. */ - /* -------------------------------------------------------------------- */ - while (panShapeRecordId[iTestChain + 1] == -1) - { - iTestChain++; - } - - /* -------------------------------------------------------------------- */ - /* Read records up to the maximum distance that is possibly */ - /* required, looking for our target TLID. */ - /* -------------------------------------------------------------------- */ - int nMaxChainToRead = nChainId - iTestChain; - int nChainsRead = 0; - char achShapeRec[OGR_TIGER_RECBUF_LEN]; - int nShapeRecLen = - psRT2Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength; - - if (nShapeRecLen <= 0) - { - return -2; - } - - while (nChainsRead < nMaxChainToRead) - { - const auto nOffset = - static_cast(nWorkingRecId - 1) * nShapeRecLen; - if (VSIFSeekL(fpShape, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %s2", nOffset, - pszModule); - return -2; - } - - if (VSIFReadL(achShapeRec, psRT2Info->nRecordLength, 1, fpShape) != 1) - { - if (!VSIFEofL(fpShape)) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to read record %d of %s2", nWorkingRecId - 1, - pszModule); - return -2; - } - else - return -1; - } - - if (atoi(GetField(achShapeRec, 6, 15)) == nTLID) - { - panShapeRecordId[nChainId] = nWorkingRecId; - - return nWorkingRecId; - } - - if (atoi(GetField(achShapeRec, 16, 18)) == 1) - { - nChainsRead++; - } - - nWorkingRecId++; - } - - panShapeRecordId[nChainId] = -1; - - return -1; -} diff --git a/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp b/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp deleted file mode 100644 index c822eb78afac..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerEntityNames, providing access to .RTC files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char C_FILE_CODE[] = "C"; - -static const TigerFieldInfo rtC_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"DATAYR", 'L', 'A', OFTString, 11, 14, 4, 1, 1}, - {"FIPS", 'L', 'N', OFTInteger, 15, 19, 5, 1, 1}, - {"FIPSCC", 'L', 'A', OFTString, 20, 21, 2, 1, 1}, - {"PLACEDC", 'L', 'A', OFTString, 22, 22, 1, 1, 1}, - {"LSADC", 'L', 'A', OFTString, 23, 24, 2, 1, 1}, - {"ENTITY", 'L', 'A', OFTString, 25, 25, 1, 1, 1}, - {"MA", 'L', 'N', OFTInteger, 26, 29, 4, 1, 1}, - {"SD", 'L', 'N', OFTInteger, 30, 34, 5, 1, 1}, - {"AIANHH", 'L', 'N', OFTInteger, 35, 38, 4, 1, 1}, - {"VTDTRACT", 'R', 'A', OFTString, 39, 44, 6, 1, 1}, - {"UAUGA", 'L', 'N', OFTInteger, 45, 49, 5, 1, 1}, - {"AITSCE", 'L', 'N', OFTInteger, 50, 52, 3, 1, 1}, - {"RS_C1", 'L', 'N', OFTInteger, 53, 54, 2, 1, 1}, - {"RS_C2", 'L', 'N', OFTInteger, 55, 62, 8, 1, 1}, - {"NAME", 'L', 'A', OFTString, 63, 122, 60, 1, 1}, -}; -static const TigerRecordInfo rtC_2002_info = { - rtC_2002_fields, sizeof(rtC_2002_fields) / sizeof(TigerFieldInfo), 122}; - -static const TigerFieldInfo rtC_2000_Redistricting_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"FIPSYR", 'L', 'N', OFTString, 11, 14, 4, 1, 1}, - {"FIPS", 'L', 'N', OFTInteger, 15, 19, 5, 1, 1}, - {"FIPSCC", 'L', 'A', OFTString, 20, 21, 2, 1, 1}, - {"PDC", 'L', 'A', OFTString, 22, 22, 1, 1, 1}, - {"LASAD", 'L', 'A', OFTString, 23, 24, 2, 1, 1}, - {"ENTITY", 'L', 'A', OFTString, 25, 25, 1, 1, 1}, - {"MA", 'L', 'N', OFTInteger, 26, 29, 4, 1, 1}, - {"SD", 'L', 'N', OFTInteger, 30, 34, 5, 1, 1}, - {"AIR", 'L', 'N', OFTInteger, 35, 38, 4, 1, 1}, - {"VTD", 'R', 'A', OFTString, 39, 44, 6, 1, 1}, - {"UA", 'L', 'N', OFTInteger, 45, 49, 5, 1, 1}, - {"AITSCE", 'L', 'N', OFTInteger, 50, 52, 3, 1, 1}, - {"NAME", 'L', 'A', OFTString, 53, 112, 66, 1, 1}}; -static const TigerRecordInfo rtC_2000_Redistricting_info = { - rtC_2000_Redistricting_fields, - sizeof(rtC_2000_Redistricting_fields) / sizeof(TigerFieldInfo), 112}; - -static const TigerFieldInfo rtC_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"FIPSYR", 'L', 'N', OFTString, 11, 12, 4, 1, 1}, - {"FIPS", 'L', 'N', OFTInteger, 13, 17, 5, 1, 1}, - {"FIPSCC", 'L', 'A', OFTString, 18, 19, 2, 1, 1}, - {"PDC", 'L', 'A', OFTString, 20, 20, 1, 1, 1}, - {"LASAD", 'L', 'A', OFTString, 21, 22, 2, 1, 1}, - {"ENTITY", 'L', 'A', OFTString, 23, 23, 1, 1, 1}, - {"MA", 'L', 'N', OFTInteger, 24, 27, 4, 1, 1}, - {"SD", 'L', 'N', OFTInteger, 28, 32, 5, 1, 1}, - {"AIR", 'L', 'N', OFTInteger, 33, 36, 4, 1, 1}, - {"VTD", 'R', 'A', OFTString, 37, 42, 6, 1, 1}, - {"UA", 'L', 'N', OFTInteger, 43, 46, 4, 1, 1}, - {"NAME", 'L', 'A', OFTString, 47, 112, 66, 1, 1}}; -static const TigerRecordInfo rtC_info = { - rtC_fields, sizeof(rtC_fields) / sizeof(TigerFieldInfo), 112}; - -/************************************************************************/ -/* TigerEntityNames() */ -/************************************************************************/ - -TigerEntityNames::TigerEntityNames(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(nullptr, C_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("EntityNames"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbPoint); - - if (poDS->GetVersion() >= TIGER_2002) - { - psRTInfo = &rtC_2002_info; - } - else if (poDS->GetVersion() >= TIGER_2000_Redistricting) - { - psRTInfo = &rtC_2000_Redistricting_info; - } - else - { - psRTInfo = &rtC_info; - } - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp b/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp deleted file mode 100644 index 644320b199cc..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerFeatureIds, providing access to .RT5 files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char FILE_CODE[] = "5"; - -static const TigerFieldInfo rt5_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"FEAT", 'R', 'N', OFTInteger, 11, 18, 8, 1, 1}, - {"FEDIRP", 'L', 'A', OFTString, 19, 20, 2, 1, 1}, - {"FENAME", 'L', 'A', OFTString, 21, 50, 30, 1, 1}, - {"FETYPE", 'L', 'A', OFTString, 51, 54, 4, 1, 1}, - {"FEDIRS", 'L', 'A', OFTString, 55, 56, 2, 1, 1}, -}; -static const TigerRecordInfo rt5_2002_info = { - rt5_2002_fields, sizeof(rt5_2002_fields) / sizeof(TigerFieldInfo), 56}; - -static const TigerFieldInfo rt5_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTString, 2, 6, 5, 1, 1}, - {"STATE", 'L', 'N', OFTInteger, 2, 3, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 4, 6, 3, 1, 1}, - {"FEAT", 'R', 'N', OFTInteger, 7, 14, 8, 1, 1}, - {"FEDIRP", 'L', 'A', OFTString, 15, 16, 2, 1, 1}, - {"FENAME", 'L', 'A', OFTString, 17, 46, 30, 1, 1}, - {"FETYPE", 'L', 'A', OFTString, 47, 50, 4, 1, 1}, - {"FEDIRS", 'L', 'A', OFTString, 51, 52, 2, 1, 1}}; - -static const TigerRecordInfo rt5_info = { - rt5_fields, sizeof(rt5_fields) / sizeof(TigerFieldInfo), 52}; - -/************************************************************************/ -/* TigerFeatureIds() */ -/************************************************************************/ - -TigerFeatureIds::TigerFeatureIds(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(nullptr, FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("FeatureIds"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - if (poDS->GetVersion() >= TIGER_2002) - { - psRTInfo = &rt5_2002_info; - } - else - { - psRTInfo = &rt5_info; - } - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp deleted file mode 100644 index 0917aa025b9b..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerBaseFile class, providing common services to all - * the tiger file readers. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" -#include "cpl_error.h" -#include "cpl_string.h" - -#include - -/************************************************************************/ -/* TigerFileBase() */ -/************************************************************************/ - -TigerFileBase::TigerFileBase(const TigerRecordInfo *psRTInfoIn, - const char *m_pszFileCodeIn) - : poDS(nullptr), pszModule(nullptr), pszShortModule(nullptr), - fpPrimary(nullptr), poFeatureDefn(nullptr), nFeatures(0), - nRecordLength(0), nVersionCode(0), nVersion(TIGER_Unknown), - psRTInfo(psRTInfoIn), m_pszFileCode(m_pszFileCodeIn) -{ -} - -/************************************************************************/ -/* ~TigerFileBase() */ -/************************************************************************/ - -TigerFileBase::~TigerFileBase() - -{ - CPLFree(pszModule); - CPLFree(pszShortModule); - - if (poFeatureDefn != nullptr) - { - poFeatureDefn->Release(); - poFeatureDefn = nullptr; - } - - if (fpPrimary != nullptr) - { - VSIFCloseL(fpPrimary); - fpPrimary = nullptr; - } -} - -/************************************************************************/ -/* OpenFile() */ -/************************************************************************/ - -int TigerFileBase::OpenFile(const char *pszModuleToOpen, - const char *pszExtension) - -{ - - CPLFree(pszModule); - pszModule = nullptr; - CPLFree(pszShortModule); - pszShortModule = nullptr; - - if (fpPrimary != nullptr) - { - VSIFCloseL(fpPrimary); - fpPrimary = nullptr; - } - - if (pszModuleToOpen == nullptr) - return TRUE; - - char *pszFilename = poDS->BuildFilename(pszModuleToOpen, pszExtension); - - fpPrimary = VSIFOpenL(pszFilename, "rb"); - - CPLFree(pszFilename); - - if (fpPrimary == nullptr) - return FALSE; - - pszModule = CPLStrdup(pszModuleToOpen); - pszShortModule = CPLStrdup(pszModuleToOpen); - for (int i = 0; pszShortModule[i] != '\0'; i++) - { - if (pszShortModule[i] == '.') - pszShortModule[i] = '\0'; - } - - SetupVersion(); - - return TRUE; -} - -/************************************************************************/ -/* SetupVersion() */ -/************************************************************************/ - -void TigerFileBase::SetupVersion() - -{ - char aszRecordHead[6]; - - VSIFSeekL(fpPrimary, 0, SEEK_SET); - VSIFReadL(aszRecordHead, 1, 5, fpPrimary); - aszRecordHead[5] = '\0'; - nVersionCode = atoi(aszRecordHead + 1); - VSIFSeekL(fpPrimary, 0, SEEK_SET); - - nVersion = TigerClassifyVersion(nVersionCode); -} - -/************************************************************************/ -/* EstablishRecordLength() */ -/************************************************************************/ - -int TigerFileBase::EstablishRecordLength(VSILFILE *fp) - -{ - if (fp == nullptr || VSIFSeekL(fp, 0, SEEK_SET) != 0) - return -1; - - /* -------------------------------------------------------------------- */ - /* Read through to the end of line. */ - /* -------------------------------------------------------------------- */ - int nRecLen = 0; - char chCurrent = '\0'; - while (VSIFReadL(&chCurrent, 1, 1, fp) == 1 && chCurrent != 10 && - chCurrent != 13) - { - nRecLen++; - } - - /* -------------------------------------------------------------------- */ - /* Is the file zero length? */ - /* -------------------------------------------------------------------- */ - if (nRecLen == 0) - { - return -1; - } - - nRecLen++; /* for the 10 or 13 we encountered */ - - /* -------------------------------------------------------------------- */ - /* Read through line terminator characters. We are trying to */ - /* handle cases of CR, CR/LF and LF/CR gracefully. */ - /* -------------------------------------------------------------------- */ - while (VSIFReadL(&chCurrent, 1, 1, fp) == 1 && - (chCurrent == 10 || chCurrent == 13)) - { - nRecLen++; - } - - VSIFSeekL(fp, 0, SEEK_SET); - - return nRecLen; -} - -/************************************************************************/ -/* EstablishFeatureCount() */ -/************************************************************************/ - -void TigerFileBase::EstablishFeatureCount() - -{ - if (fpPrimary == nullptr) - return; - - nRecordLength = EstablishRecordLength(fpPrimary); - - if (nRecordLength == -1) - { - nRecordLength = 1; - nFeatures = 0; - return; - } - - /* -------------------------------------------------------------------- */ - /* Now we think we know the fixed record length for the file */ - /* (including line terminators). Get the total file size, and */ - /* divide by this length to get the presumed number of records. */ - /* -------------------------------------------------------------------- */ - - VSIFSeekL(fpPrimary, 0, SEEK_END); - const vsi_l_offset nFileSize = VSIFTellL(fpPrimary); - - if ((nFileSize % (vsi_l_offset)nRecordLength) != 0) - { - CPLError(CE_Warning, CPLE_FileIO, - "TigerFileBase::EstablishFeatureCount(): " - "File length %d doesn't divide by record length %d.\n", - (int)nFileSize, (int)nRecordLength); - } - - if (nFileSize / (vsi_l_offset)nRecordLength > (vsi_l_offset)INT_MAX) - nFeatures = INT_MAX; - else - nFeatures = static_cast(nFileSize / (vsi_l_offset)nRecordLength); -} - -/************************************************************************/ -/* GetField() */ -/************************************************************************/ - -const char *TigerFileBase::GetField(const char *pachRawDataRecord, - int nStartChar, int nEndChar) - -{ - char aszField[128]; - int nLength = nEndChar - nStartChar + 1; - - CPLAssert(nEndChar - nStartChar + 2 < (int)sizeof(aszField)); - - strncpy(aszField, pachRawDataRecord + nStartChar - 1, nLength); - - aszField[nLength] = '\0'; - while (nLength > 0 && aszField[nLength - 1] == ' ') - aszField[--nLength] = '\0'; - - return CPLSPrintf("%s", aszField); -} - -/************************************************************************/ -/* SetField() */ -/* */ -/* Set a field on an OGRFeature from a tiger record, or leave */ -/* NULL if the value isn't found. */ -/************************************************************************/ - -void TigerFileBase::SetField(OGRFeature *poFeature, const char *pszField, - const char *pachRecord, int nStart, int nEnd) - -{ - const char *pszFieldValue = GetField(pachRecord, nStart, nEnd); - - if (pszFieldValue[0] == '\0') - return; - - poFeature->SetField(pszField, pszFieldValue); -} - -/************************************************************************/ -/* AddFieldDefns() */ -/************************************************************************/ -void TigerFileBase::AddFieldDefns(const TigerRecordInfo *psRTInfoIn, - OGRFeatureDefn *poFeatureDefnIn) -{ - OGRFieldDefn oField("", OFTInteger); - int i, bLFieldHack; - - bLFieldHack = - CPLTestBool(CPLGetConfigOption("TIGER_LFIELD_AS_STRING", "NO")); - - for (i = 0; i < psRTInfoIn->nFieldCount; ++i) - { - if (psRTInfoIn->pasFields[i].bDefine) - { - OGRFieldType eFT = (OGRFieldType)psRTInfoIn->pasFields[i].OGRtype; - - if (bLFieldHack && psRTInfoIn->pasFields[i].cFmt == 'L' && - psRTInfoIn->pasFields[i].cType == 'N') - eFT = OFTString; - - oField.Set(psRTInfoIn->pasFields[i].pszFieldName, eFT, - psRTInfoIn->pasFields[i].nLen); - poFeatureDefnIn->AddFieldDefn(&oField); - } - } -} - -/************************************************************************/ -/* SetFields() */ -/************************************************************************/ - -void TigerFileBase::SetFields(const TigerRecordInfo *psRTInfoIn, - OGRFeature *poFeature, char *achRecord) -{ - for (int i = 0; i < psRTInfoIn->nFieldCount; ++i) - { - if (psRTInfoIn->pasFields[i].bSet) - { - SetField(poFeature, psRTInfoIn->pasFields[i].pszFieldName, - achRecord, psRTInfoIn->pasFields[i].nBeg, - psRTInfoIn->pasFields[i].nEnd); - } - } -} - -/************************************************************************/ -/* SetModule() */ -/************************************************************************/ - -bool TigerFileBase::SetModule(const char *pszModuleIn) - -{ - if (m_pszFileCode == nullptr) - return false; - - if (!OpenFile(pszModuleIn, m_pszFileCode)) - return false; - - EstablishFeatureCount(); - - return true; -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ - -OGRFeature *TigerFileBase::GetFeature(int nRecordId) - -{ - char achRecord[OGR_TIGER_RECBUF_LEN]; - - if (psRTInfo == nullptr) - return nullptr; - - if (nRecordId < 0 || nRecordId >= nFeatures) - { - CPLError(CE_Failure, CPLE_FileIO, - "Request for out-of-range feature %d of %s", nRecordId, - pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Read the raw record data from the file. */ - /* -------------------------------------------------------------------- */ - if (fpPrimary == nullptr) - return nullptr; - - { - const auto nOffset = static_cast(nRecordId) * nRecordLength; - if (VSIFSeekL(fpPrimary, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %s", nOffset, pszModule); - return nullptr; - } - } - - // Overflow cannot happen since psRTInfo->nRecordLength is unsigned - // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255 - if (VSIFReadL(achRecord, psRTInfo->nRecordLength, 1, fpPrimary) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to read record %d of %s", - nRecordId, pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Set fields. */ - /* -------------------------------------------------------------------- */ - OGRFeature *poFeature = new OGRFeature(poFeatureDefn); - - SetFields(psRTInfo, poFeature, achRecord); - - return poFeature; -} diff --git a/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp b/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp deleted file mode 100644 index 48307081ca49..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerIDHistory, providing access to .RTH files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char FILE_CODE[] = "H"; - -static const TigerFieldInfo rtH_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 1, 1}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"TLID", 'R', 'N', OFTInteger, 11, 20, 10, 1, 1}, - {"HIST", 'L', 'A', OFTString, 21, 21, 1, 1, 1}, - {"SOURCE", 'L', 'A', OFTString, 22, 22, 1, 1, 1}, - {"TLIDFR1", 'R', 'N', OFTInteger, 23, 32, 10, 1, 1}, - {"TLIDFR2", 'R', 'N', OFTInteger, 33, 42, 10, 1, 1}, - {"TLIDTO1", 'R', 'N', OFTInteger, 43, 52, 10, 1, 1}, - {"TLIDTO2", 'R', 'N', OFTInteger, 53, 62, 10, 1, 1}}; -static const TigerRecordInfo rtH_info = { - rtH_fields, sizeof(rtH_fields) / sizeof(TigerFieldInfo), 62}; - -/************************************************************************/ -/* TigerIDHistory() */ -/************************************************************************/ - -TigerIDHistory::TigerIDHistory(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rtH_info, FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("IDHistory"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from record type H */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp b/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp deleted file mode 100644 index 9e4fed7fbd54..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerKeyFeatures, providing access to .RT9 files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char NINE_FILE_CODE[] = "9"; - -static const TigerFieldInfo rt9_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 1, 1}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"SOURCE", 'L', 'A', OFTString, 26, 26, 1, 1, 1}, - {"CFCC", 'L', 'A', OFTString, 27, 29, 3, 1, 1}, - {"KGLNAME", 'L', 'A', OFTString, 30, 59, 30, 1, 1}, - {"KGLADD", 'R', 'A', OFTString, 60, 70, 11, 1, 1}, - {"KGLZIP", 'L', 'N', OFTInteger, 71, 75, 5, 1, 1}, - {"KGLZIP4", 'L', 'N', OFTInteger, 76, 79, 4, 1, 1}, - {"FEAT", 'R', 'N', OFTInteger, 80, 87, 8, 1, 1}}; - -static const TigerRecordInfo rt9_info = { - rt9_fields, sizeof(rt9_fields) / sizeof(TigerFieldInfo), 88}; - -/************************************************************************/ -/* TigerKeyFeatures() */ -/************************************************************************/ - -TigerKeyFeatures::TigerKeyFeatures(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rt9_info, NINE_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("KeyFeatures"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from type 9 record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp b/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp deleted file mode 100644 index c86dcfa74633..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerLandmarks, providing access to .RT7 files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char SEVEN_FILE_CODE[] = "7"; - -static const TigerFieldInfo rt7_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"LAND", 'R', 'N', OFTInteger, 11, 20, 10, 1, 1}, - {"SOURCE", 'L', 'A', OFTString, 21, 21, 1, 1, 1}, - {"CFCC", 'L', 'A', OFTString, 22, 24, 3, 1, 1}, - {"LANAME", 'L', 'A', OFTString, 25, 54, 30, 1, 1}, - {"LALONG", 'R', 'N', OFTInteger, 55, 64, 10, 1, 1}, - {"LALAT", 'R', 'N', OFTInteger, 65, 73, 9, 1, 1}, - {"FILLER", 'L', 'A', OFTString, 74, 74, 1, 1, 1}, -}; -static const TigerRecordInfo rt7_2002_info = { - rt7_2002_fields, sizeof(rt7_2002_fields) / sizeof(TigerFieldInfo), 74}; - -static const TigerFieldInfo rt7_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 1, 0}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"LAND", 'R', 'N', OFTInteger, 11, 20, 10, 1, 1}, - {"SOURCE", 'L', 'A', OFTString, 21, 21, 1, 1, 1}, - {"CFCC", 'L', 'A', OFTString, 22, 24, 3, 1, 1}, - {"LANAME", 'L', 'A', OFTString, 25, 54, 30, 1, 1}}; -static const TigerRecordInfo rt7_info = { - rt7_fields, sizeof(rt7_fields) / sizeof(TigerFieldInfo), 74}; - -/************************************************************************/ -/* TigerLandmarks() */ -/************************************************************************/ - -TigerLandmarks::TigerLandmarks(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerPoint(nullptr, SEVEN_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("Landmarks"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbPoint); - - if (poDS->GetVersion() >= TIGER_2002) - { - psRTInfo = &rt7_2002_info; - } - else - { - psRTInfo = &rt7_info; - } - - AddFieldDefns(psRTInfo, poFeatureDefn); -} - -OGRFeature *TigerLandmarks::GetFeature(int nRecordId) -{ - return TigerPoint::GetFeature(nRecordId, 55, 64, 65, 73); -} diff --git a/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp b/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp deleted file mode 100644 index db41e092b620..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerOverUnder, providing access to .RTU files. - * Author: Mark Phillips, mbp@geomtech.com - * - ****************************************************************************** - * Copyright (c) 2002, Frank Warmerdam, Mark Phillips - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char U_FILE_CODE[] = "U"; - -static const TigerFieldInfo rtU_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"TZID", 'R', 'N', OFTInteger, 11, 20, 10, 1, 1}, - {"RTSQ", 'R', 'N', OFTInteger, 21, 21, 1, 1, 1}, - {"TLIDOV1", 'R', 'N', OFTInteger, 22, 31, 10, 1, 1}, - {"TLIDOV2", 'R', 'N', OFTInteger, 32, 41, 10, 1, 1}, - {"TLIDUN1", 'R', 'N', OFTInteger, 42, 51, 10, 1, 1}, - {"TLIDUN2", 'R', 'N', OFTInteger, 52, 61, 10, 1, 1}, - {"FRLONG", 'R', 'N', OFTInteger, 62, 71, 10, 1, 1}, - {"FRLAT", 'R', 'N', OFTInteger, 72, 80, 9, 1, 1}, -}; -static const TigerRecordInfo rtU_info = { - rtU_fields, sizeof(rtU_fields) / sizeof(TigerFieldInfo), 80}; - -/************************************************************************/ -/* TigerOverUnder() */ -/************************************************************************/ - -TigerOverUnder::TigerOverUnder(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerPoint(&rtU_info, U_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("OverUnder"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - AddFieldDefns(psRTInfo, poFeatureDefn); -} - -OGRFeature *TigerOverUnder::GetFeature(int nRecordId) -{ - return TigerPoint::GetFeature(nRecordId, 62, 71, 72, 80); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerpip.cpp b/ogr/ogrsf_frmts/tiger/tigerpip.cpp deleted file mode 100644 index bf8610b0c6e2..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerpip.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerPIP, providing access to .RTP files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char P_FILE_CODE[] = "P"; - -static const TigerFieldInfo rtP_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"POLYLONG", 'R', 'N', OFTInteger, 26, 35, 10, 1, 1}, - {"POLYLAT", 'R', 'N', OFTInteger, 36, 44, 9, 1, 1}, - {"WATER", 'L', 'N', OFTInteger, 45, 45, 1, 1, 1}, -}; -static const TigerRecordInfo rtP_2002_info = { - rtP_2002_fields, sizeof(rtP_2002_fields) / sizeof(TigerFieldInfo), 45}; - -static const TigerFieldInfo rtP_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 1, 1}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}}; -static const TigerRecordInfo rtP_info = { - rtP_fields, sizeof(rtP_fields) / sizeof(TigerFieldInfo), 44}; - -/************************************************************************/ -/* TigerPIP() */ -/************************************************************************/ - -TigerPIP::TigerPIP(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerPoint(nullptr, P_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("PIP"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbPoint); - - if (poDS->GetVersion() >= TIGER_2002) - { - psRTInfo = &rtP_2002_info; - } - else - { - psRTInfo = &rtP_info; - } - AddFieldDefns(psRTInfo, poFeatureDefn); -} - -OGRFeature *TigerPIP::GetFeature(int nRecordId) -{ - return TigerPoint::GetFeature(nRecordId, 26, 35, 36, 44); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp deleted file mode 100644 index a8f0abca8292..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerPoint class. - * Author: Mark Phillips, mbp@geomtech.com - * - ****************************************************************************** - * Copyright (c) 2002, Mark Phillips - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -#include - -/************************************************************************/ -/* TigerPoint() */ -/************************************************************************/ -TigerPoint::TigerPoint(const TigerRecordInfo *psRTInfoIn, - const char *m_pszFileCodeIn) - : TigerFileBase(psRTInfoIn, m_pszFileCodeIn) -{ -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ -OGRFeature *TigerPoint::GetFeature(int nRecordId, int nX0, int nX1, int nY0, - int nY1) -{ - char achRecord[OGR_TIGER_RECBUF_LEN]; - - if (nRecordId < 0 || nRecordId >= nFeatures) - { - CPLError(CE_Failure, CPLE_FileIO, - "Request for out-of-range feature %d of %sP", nRecordId, - pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Read the raw record data from the file. */ - /* -------------------------------------------------------------------- */ - - if (fpPrimary == nullptr) - return nullptr; - - { - const auto nOffset = static_cast(nRecordId) * nRecordLength; - if (VSIFSeekL(fpPrimary, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %sP", nOffset, - pszModule); - return nullptr; - } - } - - // Overflow cannot happen since psRTInfo->nRecordLength is unsigned - // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255 - if (VSIFReadL(achRecord, psRTInfo->nRecordLength, 1, fpPrimary) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to read record %d of %sP", - nRecordId, pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Set fields. */ - /* -------------------------------------------------------------------- */ - - OGRFeature *poFeature = new OGRFeature(poFeatureDefn); - - SetFields(psRTInfo, poFeature, achRecord); - - /* -------------------------------------------------------------------- */ - /* Set geometry */ - /* -------------------------------------------------------------------- */ - - const double dfX = atoi(GetField(achRecord, nX0, nX1)) / 1000000.0; - const double dfY = atoi(GetField(achRecord, nY0, nY1)) / 1000000.0; - - if (dfX != 0.0 || dfY != 0.0) - { - poFeature->SetGeometryDirectly(new OGRPoint(dfX, dfY)); - } - - return poFeature; -} diff --git a/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp b/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp deleted file mode 100644 index 7efbeac44fca..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerPolyChainLink, providing access to .RTI files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char I_FILE_CODE[] = "I"; - -static const TigerFieldInfo rtI_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"TLID", 'R', 'N', OFTInteger, 11, 20, 10, 1, 1}, - {"TZIDS", 'R', 'N', OFTInteger, 21, 30, 10, 1, 1}, - {"TZIDE", 'R', 'N', OFTInteger, 31, 40, 10, 1, 1}, - {"CENIDL", 'L', 'A', OFTString, 41, 45, 5, 1, 1}, - {"POLYIDL", 'R', 'N', OFTInteger, 46, 55, 10, 1, 1}, - {"CENIDR", 'L', 'A', OFTString, 56, 60, 5, 1, 1}, - {"POLYIDR", 'R', 'N', OFTInteger, 61, 70, 10, 1, 1}, - {"SOURCE", 'L', 'A', OFTString, 71, 80, 10, 1, 1}, - {"FTSEG", 'L', 'A', OFTString, 81, 97, 17, 1, 1}, - {"RS_I1", 'L', 'A', OFTString, 98, 107, 10, 1, 1}, - {"RS_I2", 'L', 'A', OFTString, 108, 117, 10, 1, 1}, - {"RS_I3", 'L', 'A', OFTString, 118, 127, 10, 1, 1}, -}; -static const TigerRecordInfo rtI_2002_info = { - rtI_2002_fields, sizeof(rtI_2002_fields) / sizeof(TigerFieldInfo), 127}; - -static const TigerFieldInfo rtI_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 1, 1}, - {"FILE", 'L', 'N', OFTString, 16, 20, 5, 1, 1}, - {"STATE", 'L', 'N', OFTInteger, 16, 17, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 18, 20, 3, 1, 1}, - {"RTLINK", 'L', 'A', OFTString, 21, 21, 1, 1, 1}, - {"CENIDL", 'L', 'A', OFTString, 22, 26, 5, 1, 1}, - {"POLYIDL", 'R', 'N', OFTInteger, 27, 36, 10, 1, 1}, - {"CENIDR", 'L', 'A', OFTString, 37, 41, 5, 1, 1}, - {"POLYIDR", 'R', 'N', OFTInteger, 42, 51, 10, 1, 1}}; -static const TigerRecordInfo rtI_info = { - rtI_fields, sizeof(rtI_fields) / sizeof(TigerFieldInfo), 52}; - -/************************************************************************/ -/* TigerPolyChainLink() */ -/************************************************************************/ - -TigerPolyChainLink::TigerPolyChainLink( - OGRTigerDataSource *poDSIn, CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(nullptr, I_FILE_CODE) -{ - OGRFieldDefn oField("", OFTInteger); - - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("PolyChainLink"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - if (poDS->GetVersion() >= TIGER_2002) - { - psRTInfo = &rtI_2002_info; - } - else - { - psRTInfo = &rtI_info; - } - - /* -------------------------------------------------------------------- */ - /* Fields from type I record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp deleted file mode 100644 index 36b395a7a46b..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp +++ /dev/null @@ -1,524 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerPolygon, providing access to .RTA files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * Copyright (c) 2011, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -#include - -static const TigerFieldInfo rtA_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"STATECU", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1}, - {"COUNTYCU", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1}, - - {"TRACT", 'L', 'N', OFTInteger, 31, 36, 6, 1, 1}, - {"BLOCK", 'L', 'N', OFTInteger, 37, 40, 4, 1, 1}, - {"BLOCKSUFCU", 'L', 'A', OFTString, 41, 41, 1, 1, 1}, - - {"RS_A1", 'L', 'A', OFTString, 42, 42, 1, 1, 1}, - {"AIANHHFPCU", 'L', 'N', OFTInteger, 43, 47, 5, 1, 1}, - {"AIANHHCU", 'L', 'N', OFTInteger, 48, 51, 4, 1, 1}, - {"AIHHTLICU", 'L', 'A', OFTString, 52, 52, 1, 1, 1}, - {"ANRCCU", 'L', 'N', OFTInteger, 53, 57, 5, 1, 1}, - {"AITSCECU", 'L', 'N', OFTInteger, 58, 60, 3, 1, 1}, - {"AITSCU", 'L', 'N', OFTInteger, 61, 65, 5, 1, 1}, - {"CONCITCU", 'L', 'N', OFTInteger, 66, 70, 5, 1, 1}, - {"COUSUBCU", 'L', 'N', OFTInteger, 71, 75, 5, 1, 1}, - {"SUBMCDCU", 'L', 'N', OFTInteger, 76, 80, 5, 1, 1}, - {"PLACECU", 'L', 'N', OFTInteger, 81, 85, 5, 1, 1}, - {"SDELMCU", 'L', 'A', OFTString, 86, 90, 5, 1, 1}, - {"SDSECCU", 'L', 'A', OFTString, 91, 95, 5, 1, 1}, - {"SDUNICU", 'L', 'A', OFTString, 96, 100, 5, 1, 1}, - {"MSACMSACU", 'L', 'N', OFTInteger, 101, 104, 4, 1, 1}, - {"PMSACU", 'L', 'N', OFTInteger, 105, 108, 4, 1, 1}, - {"NECMACU", 'L', 'N', OFTInteger, 109, 112, 4, 1, 1}, - {"CDCU", 'R', 'N', OFTInteger, 113, 114, 2, 1, 1}, - {"RS_A2", 'L', 'A', OFTString, 115, 119, 5, 1, 1}, - {"RS_A3", 'R', 'A', OFTString, 120, 122, 3, 1, 1}, - {"RS_A4", 'R', 'A', OFTString, 123, 128, 6, 1, 1}, - {"RS_A5", 'R', 'A', OFTString, 129, 131, 3, 1, 1}, - {"RS_A6", 'R', 'A', OFTString, 132, 134, 3, 1, 1}, - {"RS_A7", 'R', 'A', OFTString, 135, 139, 5, 1, 1}, - {"RS_A8", 'R', 'A', OFTString, 140, 145, 6, 1, 1}, - {"RS_A9", 'L', 'A', OFTString, 146, 151, 6, 1, 1}, - {"RS_A10", 'L', 'A', OFTString, 152, 157, 6, 1, 1}, - {"RS_A11", 'L', 'A', OFTString, 158, 163, 6, 1, 1}, - {"RS_A12", 'L', 'A', OFTString, 164, 169, 6, 1, 1}, - {"RS_A13", 'L', 'A', OFTString, 170, 175, 6, 1, 1}, - {"RS_A14", 'L', 'A', OFTString, 176, 181, 6, 1, 1}, - {"RS_A15", 'L', 'A', OFTString, 182, 186, 5, 1, 1}, - {"RS_A16", 'L', 'A', OFTString, 187, 187, 1, 1, 1}, - {"RS_A17", 'L', 'A', OFTString, 188, 193, 6, 1, 1}, - {"RS_A18", 'L', 'A', OFTString, 194, 199, 6, 1, 1}, - {"RS_A19", 'L', 'A', OFTString, 200, 210, 11, 1, 1}, -}; -static const TigerRecordInfo rtA_2002_info = { - rtA_2002_fields, sizeof(rtA_2002_fields) / sizeof(TigerFieldInfo), 210}; - -static const TigerFieldInfo rtA_2003_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"STATECU", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1}, - {"COUNTYCU", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1}, - - {"TRACT", 'L', 'N', OFTInteger, 31, 36, 6, 1, 1}, - {"BLOCK", 'L', 'N', OFTInteger, 37, 40, 4, 1, 1}, - {"BLOCKSUFCU", 'L', 'A', OFTString, 41, 41, 1, 1, 1}, - - {"RS_A1", 'L', 'A', OFTString, 42, 42, 1, 1, 1}, - {"AIANHHFPCU", 'L', 'N', OFTInteger, 43, 47, 5, 1, 1}, - {"AIANHHCU", 'L', 'N', OFTInteger, 48, 51, 4, 1, 1}, - {"AIHHTLICU", 'L', 'A', OFTString, 52, 52, 1, 1, 1}, - {"ANRCCU", 'L', 'N', OFTInteger, 53, 57, 5, 1, 1}, - {"AITSCECU", 'L', 'N', OFTInteger, 58, 60, 3, 1, 1}, - {"AITSCU", 'L', 'N', OFTInteger, 61, 65, 5, 1, 1}, - {"CONCITCU", 'L', 'N', OFTInteger, 66, 70, 5, 1, 1}, - {"COUSUBCU", 'L', 'N', OFTInteger, 71, 75, 5, 1, 1}, - {"SUBMCDCU", 'L', 'N', OFTInteger, 76, 80, 5, 1, 1}, - {"PLACECU", 'L', 'N', OFTInteger, 81, 85, 5, 1, 1}, - {"SDELMCU", 'L', 'A', OFTString, 86, 90, 5, 1, 1}, - {"SDSECCU", 'L', 'A', OFTString, 91, 95, 5, 1, 1}, - {"SDUNICU", 'L', 'A', OFTString, 96, 100, 5, 1, 1}, - {"RS_A20", 'L', 'A', OFTString, 101, 104, 4, 1, 1}, - {"RS_A21", 'L', 'A', OFTString, 105, 108, 4, 1, 1}, - {"RS_A22", 'L', 'A', OFTString, 109, 112, 4, 1, 1}, - {"CDCU", 'R', 'N', OFTInteger, 113, 114, 2, 1, 1}, - {"ZCTA5CU", 'L', 'A', OFTString, 115, 119, 5, 1, 1}, - {"ZCTA3CU", 'R', 'A', OFTString, 120, 122, 3, 1, 1}, - {"RS_A4", 'R', 'A', OFTString, 123, 128, 6, 1, 1}, - {"RS_A5", 'R', 'A', OFTString, 129, 131, 3, 1, 1}, - {"RS_A6", 'R', 'A', OFTString, 132, 134, 3, 1, 1}, - {"RS_A7", 'R', 'A', OFTString, 135, 139, 5, 1, 1}, - {"RS_A8", 'R', 'A', OFTString, 140, 145, 6, 1, 1}, - {"RS_A9", 'L', 'A', OFTString, 146, 151, 6, 1, 1}, - {"CBSACU", 'L', 'A', OFTInteger, 152, 156, 5, 1, 1}, - {"CSACU", 'L', 'A', OFTInteger, 157, 159, 3, 1, 1}, - {"NECTACU", 'L', 'A', OFTInteger, 160, 164, 5, 1, 1}, - {"CNECTACU", 'L', 'A', OFTInteger, 165, 167, 3, 1, 1}, - {"METDIVCU", 'L', 'A', OFTInteger, 168, 172, 5, 1, 1}, - {"NECTADIVCU", 'L', 'A', OFTInteger, 173, 177, 5, 1, 1}, - {"RS_A14", 'L', 'A', OFTString, 178, 181, 4, 1, 1}, - {"RS_A15", 'L', 'A', OFTString, 182, 186, 5, 1, 1}, - {"RS_A16", 'L', 'A', OFTString, 187, 187, 1, 1, 1}, - {"RS_A17", 'L', 'A', OFTString, 188, 193, 6, 1, 1}, - {"RS_A18", 'L', 'A', OFTString, 194, 199, 6, 1, 1}, - {"RS_A19", 'L', 'A', OFTString, 200, 210, 11, 1, 1}, -}; -static const TigerRecordInfo rtA_2003_info = { - rtA_2003_fields, sizeof(rtA_2003_fields) / sizeof(TigerFieldInfo), 210}; - -static const TigerFieldInfo rtA_2004_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"STATECU", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1}, - {"COUNTYCU", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1}, - - {"TRACT", 'L', 'N', OFTInteger, 31, 36, 6, 1, 1}, - {"BLOCK", 'L', 'N', OFTInteger, 37, 40, 4, 1, 1}, - {"BLOCKSUFCU", 'L', 'A', OFTString, 41, 41, 1, 1, 1}, - - {"RS_A1", 'L', 'A', OFTString, 42, 42, 1, 1, 1}, - {"AIANHHFPCU", 'L', 'N', OFTInteger, 43, 47, 5, 1, 1}, - {"AIANHHCU", 'L', 'N', OFTInteger, 48, 51, 4, 1, 1}, - {"AIHHTLICU", 'L', 'A', OFTString, 52, 52, 1, 1, 1}, - {"ANRCCU", 'L', 'N', OFTInteger, 53, 57, 5, 1, 1}, - {"AITSCECU", 'L', 'N', OFTInteger, 58, 60, 3, 1, 1}, - {"AITSCU", 'L', 'N', OFTInteger, 61, 65, 5, 1, 1}, - {"CONCITCU", 'L', 'N', OFTInteger, 66, 70, 5, 1, 1}, - {"COUSUBCU", 'L', 'N', OFTInteger, 71, 75, 5, 1, 1}, - {"SUBMCDCU", 'L', 'N', OFTInteger, 76, 80, 5, 1, 1}, - {"PLACECU", 'L', 'N', OFTInteger, 81, 85, 5, 1, 1}, - {"SDELMCU", 'L', 'A', OFTString, 86, 90, 5, 1, 1}, - {"SDSECCU", 'L', 'A', OFTString, 91, 95, 5, 1, 1}, - {"SDUNICU", 'L', 'A', OFTString, 96, 100, 5, 1, 1}, - {"RS_A20", 'L', 'A', OFTString, 101, 104, 4, 1, 1}, - {"RS_A21", 'L', 'A', OFTString, 105, 108, 4, 1, 1}, - {"RS_A22", 'L', 'A', OFTString, 109, 112, 4, 1, 1}, - {"CDCU", 'R', 'N', OFTInteger, 113, 114, 2, 1, 1}, - {"ZCTA5CU", 'L', 'A', OFTString, 115, 119, 5, 1, 1}, - {"ZCTA3CU", 'R', 'A', OFTString, 120, 122, 3, 1, 1}, - {"RS_A4", 'R', 'A', OFTString, 123, 128, 6, 1, 1}, - {"RS_A5", 'R', 'A', OFTString, 129, 131, 3, 1, 1}, - {"RS_A6", 'R', 'A', OFTString, 132, 134, 3, 1, 1}, - {"RS_A7", 'R', 'A', OFTString, 135, 139, 5, 1, 1}, - {"RS_A8", 'R', 'A', OFTString, 140, 145, 6, 1, 1}, - {"RS_A9", 'L', 'A', OFTString, 146, 151, 6, 1, 1}, - {"CBSACU", 'L', 'A', OFTInteger, 152, 156, 5, 1, 1}, - {"CSACU", 'L', 'A', OFTInteger, 157, 159, 3, 1, 1}, - {"NECTACU", 'L', 'A', OFTInteger, 160, 164, 5, 1, 1}, - {"CNECTACU", 'L', 'A', OFTInteger, 165, 167, 3, 1, 1}, - {"METDIVCU", 'L', 'A', OFTInteger, 168, 172, 5, 1, 1}, - {"NECTADIVCU", 'L', 'A', OFTInteger, 173, 177, 5, 1, 1}, - {"RS_A14", 'L', 'A', OFTString, 178, 181, 4, 1, 1}, - {"UACU", 'L', 'N', OFTInteger, 182, 186, 5, 1, 1}, - {"URCU", 'L', 'A', OFTString, 187, 187, 1, 1, 1}, - {"RS_A17", 'L', 'A', OFTString, 188, 193, 6, 1, 1}, - {"RS_A18", 'L', 'A', OFTString, 194, 199, 6, 1, 1}, - {"RS_A19", 'L', 'A', OFTString, 200, 210, 11, 1, 1}, -}; -static const TigerRecordInfo rtA_2004_info = { - rtA_2004_fields, sizeof(rtA_2004_fields) / sizeof(TigerFieldInfo), 210}; - -static const TigerFieldInfo rtA_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 1, 1}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"FAIR", 'L', 'N', OFTInteger, 26, 30, 5, 1, 1}, - {"FMCD", 'L', 'N', OFTInteger, 31, 35, 5, 1, 1}, - {"FPL", 'L', 'N', OFTInteger, 36, 40, 5, 1, 1}, - {"CTBNA90", 'L', 'N', OFTInteger, 41, 46, 6, 1, 1}, - {"BLK90", 'L', 'A', OFTString, 47, 50, 4, 1, 1}, - {"CD106", 'L', 'N', OFTInteger, 51, 52, 2, 1, 1}, - {"CD108", 'L', 'N', OFTInteger, 53, 54, 2, 1, 1}, - {"SDELM", 'L', 'A', OFTString, 55, 59, 5, 1, 1}, - {"SDSEC", 'L', 'N', OFTString, 65, 69, 5, 1, 1}, - {"SDUNI", 'L', 'A', OFTString, 70, 74, 5, 1, 1}, - {"TAZ", 'R', 'A', OFTString, 75, 80, 6, 1, 1}, - {"UA", 'L', 'N', OFTInteger, 81, 84, 4, 1, 1}, - {"URBFLAG", 'L', 'A', OFTString, 85, 85, 1, 1, 1}, - {"CTPP", 'L', 'A', OFTString, 86, 89, 4, 1, 1}, - {"STATE90", 'L', 'N', OFTInteger, 90, 91, 2, 1, 1}, - {"COUN90", 'L', 'N', OFTInteger, 92, 94, 3, 1, 1}, - {"AIR90", 'L', 'N', OFTInteger, 95, 98, 4, 1, 1}}; - -static const TigerRecordInfo rtA_info = { - rtA_fields, sizeof(rtA_fields) / sizeof(TigerFieldInfo), 98}; - -static const TigerFieldInfo rtS_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 0, 0}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 0, 0}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 0, 0}, - {"STATE", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1}, - {"TRACT", 'L', 'N', OFTInteger, 31, 36, 6, 0, 0}, - {"BLOCK", 'L', 'N', OFTInteger, 37, 40, 4, 0, 0}, - {"BLKGRP", 'L', 'N', OFTInteger, 41, 41, 1, 1, 1}, - {"AIANHHFP", 'L', 'N', OFTInteger, 42, 46, 5, 1, 1}, - {"AIANHH", 'L', 'N', OFTInteger, 47, 50, 4, 1, 1}, - {"AIHHTLI", 'L', 'A', OFTString, 51, 51, 1, 1, 1}, - {"ANRC", 'L', 'N', OFTInteger, 52, 56, 5, 1, 1}, - {"AITSCE", 'L', 'N', OFTInteger, 57, 59, 3, 1, 1}, - {"AITS", 'L', 'N', OFTInteger, 60, 64, 5, 1, 1}, - {"CONCIT", 'L', 'N', OFTInteger, 65, 69, 5, 1, 1}, - {"COUSUB", 'L', 'N', OFTInteger, 70, 74, 5, 1, 1}, - {"SUBMCD", 'L', 'N', OFTInteger, 75, 79, 5, 1, 1}, - {"PLACE", 'L', 'N', OFTInteger, 80, 84, 5, 1, 1}, - {"SDELM", 'L', 'N', OFTInteger, 85, 89, 5, 1, 1}, - {"SDSEC", 'L', 'N', OFTInteger, 90, 94, 5, 1, 1}, - {"SDUNI", 'L', 'N', OFTInteger, 95, 99, 5, 1, 1}, - {"MSACMSA", 'L', 'N', OFTInteger, 100, 103, 4, 1, 1}, - {"PMSA", 'L', 'N', OFTInteger, 104, 107, 4, 1, 1}, - {"NECMA", 'L', 'N', OFTInteger, 108, 111, 4, 1, 1}, - {"CD106", 'L', 'N', OFTInteger, 112, 113, 2, 1, 1}, - // Note: spec has CD106 with 'R', but sample data file (08005) seems to - // have been written with 'L', so I'm using 'L' here. mbp Tue Dec 24 - // 19:03:40 2002 - {"CD108", 'R', 'N', OFTInteger, 114, 115, 2, 1, 1}, - {"PUMA5", 'L', 'N', OFTInteger, 116, 120, 5, 1, 1}, - {"PUMA1", 'L', 'N', OFTInteger, 121, 125, 5, 1, 1}, - {"ZCTA5", 'L', 'A', OFTString, 126, 130, 5, 1, 1}, - {"ZCTA3", 'L', 'A', OFTString, 131, 133, 3, 1, 1}, - {"TAZ", 'L', 'A', OFTString, 134, 139, 6, 1, 1}, - {"TAZCOMB", 'L', 'A', OFTString, 140, 145, 6, 1, 1}, - {"UA", 'L', 'N', OFTInteger, 146, 150, 5, 1, 1}, - {"UR", 'L', 'A', OFTString, 151, 151, 1, 1, 1}, - {"VTD", 'R', 'A', OFTString, 152, 157, 6, 1, 1}, - {"SLDU", 'R', 'A', OFTString, 158, 160, 3, 1, 1}, - {"SLDL", 'R', 'A', OFTString, 161, 163, 3, 1, 1}, - {"UGA", 'L', 'A', OFTString, 164, 168, 5, 1, 1}, -}; -static const TigerRecordInfo rtS_2002_info = { - rtS_2002_fields, sizeof(rtS_2002_fields) / sizeof(TigerFieldInfo), 168}; - -static const TigerFieldInfo rtS_2000_Redistricting_fields[] = { - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 0, 0}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 0, 0}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 0, 0}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 0, 0}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 0, 0}, - {"WATER", 'L', 'N', OFTString, 26, 26, 1, 1, 1}, - {"CMSAMSA", 'L', 'N', OFTInteger, 27, 30, 4, 1, 1}, - {"PMSA", 'L', 'N', OFTInteger, 31, 34, 4, 1, 1}, - {"AIANHH", 'L', 'N', OFTInteger, 35, 39, 5, 1, 1}, - {"AIR", 'L', 'N', OFTInteger, 40, 43, 4, 1, 1}, - {"TRUST", 'L', 'A', OFTString, 44, 44, 1, 1, 1}, - {"ANRC", 'L', 'A', OFTInteger, 45, 46, 2, 1, 1}, - {"STATECU", 'L', 'N', OFTInteger, 47, 48, 2, 1, 1}, - {"COUNTYCU", 'L', 'N', OFTInteger, 49, 51, 3, 1, 1}, - {"FCCITY", 'L', 'N', OFTInteger, 52, 56, 5, 1, 1}, - {"FMCD", 'L', 'N', OFTInteger, 57, 61, 5, 0, 0}, - {"FSMCD", 'L', 'N', OFTInteger, 62, 66, 5, 1, 1}, - {"PLACE", 'L', 'N', OFTInteger, 67, 71, 5, 1, 1}, - {"CTBNA00", 'L', 'N', OFTInteger, 72, 77, 6, 1, 1}, - {"BLK00", 'L', 'N', OFTString, 78, 81, 4, 1, 1}, - {"RS10", 'R', 'N', OFTInteger, 82, 82, 0, 0, 1}, - {"CDCU", 'L', 'N', OFTInteger, 83, 84, 2, 1, 1}, - - {"SLDU", 'R', 'A', OFTString, 85, 87, 3, 1, 1}, - {"SLDL", 'R', 'A', OFTString, 88, 90, 3, 1, 1}, - {"UGA", 'L', 'A', OFTString, 91, 95, 5, 1, 1}, - {"BLKGRP", 'L', 'N', OFTInteger, 96, 96, 1, 1, 1}, - {"VTD", 'R', 'A', OFTString, 97, 102, 6, 1, 1}, - {"STATECOL", 'L', 'N', OFTInteger, 103, 104, 2, 1, 1}, - {"COUNTYCOL", 'L', 'N', OFTInteger, 105, 107, 3, 1, 1}, - {"BLOCKCOL", 'R', 'N', OFTInteger, 108, 112, 5, 1, 1}, - {"BLKSUFCOL", 'L', 'A', OFTString, 113, 113, 1, 1, 1}, - {"ZCTA5", 'L', 'A', OFTString, 114, 118, 5, 1, 1}}; - -static const TigerRecordInfo rtS_2000_Redistricting_info = { - rtS_2000_Redistricting_fields, - sizeof(rtS_2000_Redistricting_fields) / sizeof(TigerFieldInfo), 120}; - -static const TigerFieldInfo rtS_fields[] = { - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 0, 0}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 0, 0}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 0, 0}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 0, 0}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 0, 0}, - - {"WATER", 'L', 'N', OFTString, 26, 26, 1, 1, 1}, - {"CMSAMSA", 'L', 'N', OFTInteger, 27, 30, 4, 1, 1}, - {"PMSA", 'L', 'N', OFTInteger, 31, 34, 4, 1, 1}, - {"AIANHH", 'L', 'N', OFTInteger, 35, 39, 5, 1, 1}, - {"AIR", 'L', 'N', OFTInteger, 40, 43, 4, 1, 1}, - {"TRUST", 'L', 'A', OFTString, 44, 44, 1, 1, 1}, - {"ANRC", 'L', 'A', OFTInteger, 45, 46, 2, 1, 1}, - {"STATECU", 'L', 'N', OFTInteger, 47, 48, 2, 1, 1}, - {"COUNTYCU", 'L', 'N', OFTInteger, 49, 51, 3, 1, 1}, - {"FCCITY", 'L', 'N', OFTInteger, 52, 56, 5, 1, 1}, - {"FMCD", 'L', 'N', OFTInteger, 57, 61, 5, 0, 0}, - {"FSMCD", 'L', 'N', OFTInteger, 62, 66, 5, 1, 1}, - {"PLACE", 'L', 'N', OFTInteger, 67, 71, 5, 1, 1}, - {"CTBNA00", 'L', 'N', OFTInteger, 72, 77, 6, 1, 1}, - {"BLK00", 'L', 'N', OFTString, 78, 81, 4, 1, 1}, - {"RS10", 'R', 'N', OFTInteger, 82, 82, 0, 0, 1}, - {"CDCU", 'L', 'N', OFTInteger, 83, 84, 2, 1, 1}, - - {"STSENATE", 'L', 'A', OFTString, 85, 90, 6, 1, 1}, - {"STHOUSE", 'L', 'A', OFTString, 91, 96, 6, 1, 1}, - {"VTD00", 'L', 'A', OFTString, 97, 102, 6, 1, 1}}; -static const TigerRecordInfo rtS_info = { - rtS_fields, sizeof(rtS_fields) / sizeof(TigerFieldInfo), 120}; - -/************************************************************************/ -/* TigerPolygon() */ -/************************************************************************/ - -TigerPolygon::TigerPolygon(OGRTigerDataSource *poDSIn, - const char * /* pszPrototypeModule */) - : psRTAInfo(nullptr), psRTSInfo(nullptr), fpRTS(nullptr), bUsingRTS(true), - nRTSRecLen(0) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("Polygon"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - if (poDS->GetVersion() >= TIGER_2004) - { - psRTAInfo = &rtA_2004_info; - } - else if (poDS->GetVersion() >= TIGER_2003) - { - psRTAInfo = &rtA_2003_info; - } - else if (poDS->GetVersion() >= TIGER_2002) - { - psRTAInfo = &rtA_2002_info; - } - else - { - psRTAInfo = &rtA_info; - } - - if (poDS->GetVersion() >= TIGER_2002) - { - psRTSInfo = &rtS_2002_info; - } - else if (poDS->GetVersion() >= TIGER_2000_Redistricting) - { - psRTSInfo = &rtS_2000_Redistricting_info; - } - else - { - psRTSInfo = &rtS_info; - } - - /* -------------------------------------------------------------------- */ - /* Fields from type A record. */ - /* -------------------------------------------------------------------- */ - AddFieldDefns(psRTAInfo, poFeatureDefn); - - /* -------------------------------------------------------------------- */ - /* Add the RTS records if it is available. */ - /* -------------------------------------------------------------------- */ - if (bUsingRTS) - { - AddFieldDefns(psRTSInfo, poFeatureDefn); - } -} - -/************************************************************************/ -/* ~TigerPolygon() */ -/************************************************************************/ - -TigerPolygon::~TigerPolygon() - -{ - if (fpRTS != nullptr) - VSIFCloseL(fpRTS); -} - -/************************************************************************/ -/* SetModule() */ -/************************************************************************/ - -bool TigerPolygon::SetModule(const char *pszModuleIn) - -{ - if (!OpenFile(pszModuleIn, "A")) - return false; - - EstablishFeatureCount(); - - /* -------------------------------------------------------------------- */ - /* Open the RTS file */ - /* -------------------------------------------------------------------- */ - if (bUsingRTS) - { - if (fpRTS != nullptr) - { - VSIFCloseL(fpRTS); - fpRTS = nullptr; - } - - if (pszModuleIn) - { - char *pszFilename = poDS->BuildFilename(pszModuleIn, "S"); - - fpRTS = VSIFOpenL(pszFilename, "rb"); - - CPLFree(pszFilename); - - nRTSRecLen = EstablishRecordLength(fpRTS); - } - } - - return true; -} - -/************************************************************************/ -/* GetFeature() */ -/************************************************************************/ - -OGRFeature *TigerPolygon::GetFeature(int nRecordId) - -{ - char achRecord[OGR_TIGER_RECBUF_LEN]; - - if (nRecordId < 0 || nRecordId >= nFeatures) - { - CPLError(CE_Failure, CPLE_FileIO, - "Request for out-of-range feature %d of %sA", nRecordId, - pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Read the raw record data from the file. */ - /* -------------------------------------------------------------------- */ - if (fpPrimary == nullptr) - return nullptr; - - if (nRecordLength > static_cast(sizeof(achRecord))) - { - CPLError(CE_Failure, CPLE_AppDefined, "Record length too large"); - return nullptr; - } - - { - const auto nOffset = static_cast(nRecordId) * nRecordLength; - if (VSIFSeekL(fpPrimary, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %sA", nOffset, - pszModule); - return nullptr; - } - } - - if (VSIFReadL(achRecord, nRecordLength, 1, fpPrimary) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to read record %d of %sA", - nRecordId, pszModule); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Set fields. */ - /* -------------------------------------------------------------------- */ - - OGRFeature *poFeature = new OGRFeature(poFeatureDefn); - - SetFields(psRTAInfo, poFeature, achRecord); - - /* -------------------------------------------------------------------- */ - /* Read RTS record, and apply fields. */ - /* -------------------------------------------------------------------- */ - - if (fpRTS != nullptr) - { - char achRTSRec[OGR_TIGER_RECBUF_LEN]; - - { - const auto nOffset = static_cast(nRecordId) * nRTSRecLen; - if (VSIFSeekL(fpRTS, nOffset, SEEK_SET) != 0) - { - CPLError(CE_Failure, CPLE_FileIO, - "Failed to seek to %" PRIu64 " of %sS", nOffset, - pszModule); - delete poFeature; - return nullptr; - } - } - - // Overflow cannot happen since psRTInfo->nRecordLength is unsigned - // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255 - if (VSIFReadL(achRTSRec, psRTSInfo->nRecordLength, 1, fpRTS) != 1) - { - CPLError(CE_Failure, CPLE_FileIO, "Failed to read record %d of %sS", - nRecordId, pszModule); - delete poFeature; - return nullptr; - } - - SetFields(psRTSInfo, poFeature, achRTSRec); - } - - return poFeature; -} diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp deleted file mode 100644 index b19aa77076e9..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerPolygonCorrections, providing access to .RTB files. - * Author: Mark Phillips, mbp@geomtech.com - * - ****************************************************************************** - * Copyright (c) 2002, Frank Warmerdam, Mark Phillips - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char B_FILE_CODE[] = "B"; - -static const TigerFieldInfo rtB_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"STATECQ", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1}, - {"COUNTYCQ", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1}, - {"TRACTCQ", 'L', 'N', OFTInteger, 31, 36, 6, 1, 1}, - {"BLOCKCQ", 'L', 'A', OFTString, 37, 41, 5, 1, 1}, - {"AIANHHFPCQ", 'L', 'N', OFTInteger, 42, 46, 5, 1, 1}, - {"AIANHHCQ", 'L', 'N', OFTInteger, 47, 50, 4, 1, 1}, - {"AIHHTLICQ", 'L', 'A', OFTString, 51, 51, 1, 1, 1}, - {"AITSCECQ", 'L', 'N', OFTInteger, 52, 54, 3, 1, 1}, - {"AITSCQ", 'L', 'N', OFTInteger, 55, 59, 5, 1, 1}, - {"ANRCCQ", 'L', 'N', OFTInteger, 60, 64, 5, 1, 1}, - {"CONCITCQ", 'L', 'N', OFTInteger, 65, 69, 5, 1, 1}, - {"COUSUBCQ", 'L', 'N', OFTInteger, 70, 74, 5, 1, 1}, - {"SUBMCDCQ", 'L', 'N', OFTInteger, 75, 79, 5, 1, 1}, - {"PLACECQ", 'L', 'N', OFTInteger, 80, 84, 5, 1, 1}, - {"UACC", 'L', 'N', OFTInteger, 85, 89, 5, 1, 1}, - {"URCC", 'L', 'A', OFTString, 90, 90, 1, 1, 1}, - {"RS-B1", 'L', 'A', OFTString, 91, 98, 12, 1, 1}, -}; -static const TigerRecordInfo rtB_info = { - rtB_fields, sizeof(rtB_fields) / sizeof(TigerFieldInfo), 98}; - -/************************************************************************/ -/* TigerPolygonCorrections() */ -/************************************************************************/ - -TigerPolygonCorrections::TigerPolygonCorrections( - OGRTigerDataSource *poDSIn, const char * /* pszPrototypeModule */) - : TigerFileBase(&rtB_info, B_FILE_CODE) -{ - OGRFieldDefn oField("", OFTInteger); - - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("PolygonCorrections"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from type B record. */ - /* -------------------------------------------------------------------- */ - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp deleted file mode 100644 index fcd417c00d3e..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerPolygonEconomic, providing access to .RTE files. - * Author: Mark Phillips, mbp@geomtech.com - * - ****************************************************************************** - * Copyright (c) 2002, Frank Warmerdam, Mark Phillips - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char FILE_CODE[] = "E"; - -/* I think this was the expected RTE format, but was never deployed, leaving - it in the code in case I am missing something. - -static TigerFieldInfo rtE_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - { "MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0 }, - { "FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1 }, - { "CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1 }, - { "POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1 }, - { "STATEEC", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1 }, - { "COUNTYEC", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1 }, - { "CONCITEC", 'L', 'N', OFTInteger, 31, 35, 5, 1, 1 }, - { "COUSUBEC", 'L', 'N', OFTInteger, 36, 40, 5, 1, 1 }, - { "PLACEEC", 'L', 'N', OFTInteger, 41, 45, 5, 1, 1 }, - { "AIANHHFPEC", 'L', 'N', OFTInteger, 46, 50, 5, 1, 1 }, - { "AIANHHEC", 'L', 'N', OFTInteger, 51, 54, 4, 1, 1 }, - { "AIAHHTLIEC", 'L', 'A', OFTString, 55, 55, 1, 1, 1 }, - { "RS_E1", 'L', 'A', OFTString, 56, 73, 18, 1, 1 } -}; -*/ - -static const TigerFieldInfo rtE_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"STATEEC", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1}, - {"COUNTYEC", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1}, - {"RS_E1", 'L', 'A', OFTString, 31, 35, 5, 1, 1}, - {"RS_E2", 'L', 'A', OFTString, 36, 40, 5, 1, 1}, - {"PLACEEC", 'L', 'N', OFTInteger, 41, 45, 5, 1, 1}, - {"RS-E3", 'L', 'A', OFTString, 46, 50, 5, 1, 1}, - {"RS-E4", 'L', 'A', OFTString, 51, 54, 4, 1, 1}, - {"RS-E5", 'L', 'A', OFTString, 55, 55, 1, 1, 1}, - {"COMMREGEC", 'L', 'N', OFTInteger, 56, 56, 1, 1, 1}, - {"RS_E6", 'L', 'A', OFTString, 57, 73, 17, 1, 1}}; -static const TigerRecordInfo rtE_info = { - rtE_fields, sizeof(rtE_fields) / sizeof(TigerFieldInfo), 73}; - -/************************************************************************/ -/* TigerPolygonEconomic() */ -/************************************************************************/ - -TigerPolygonEconomic::TigerPolygonEconomic( - OGRTigerDataSource *poDSIn, CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rtE_info, FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("PolygonEconomic"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from type E record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp b/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp deleted file mode 100644 index 9990767c7ace..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerSpatialMetadata, providing access to .RTM files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2005, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char M_FILE_CODE[] = "M"; - -static const TigerFieldInfo rtM_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 1, 1}, - {"RTSQ", 'R', 'N', OFTInteger, 16, 18, 3, 1, 1}, - {"SOURCEID", 'L', 'A', OFTString, 19, 28, 10, 1, 1}, - {"ID", 'L', 'A', OFTString, 29, 46, 18, 1, 1}, - {"IDFLAG", 'R', 'A', OFTString, 47, 47, 1, 1, 1}, - {"RS-M1", 'L', 'A', OFTString, 48, 65, 18, 1, 1}, - {"RS-M2", 'L', 'A', OFTString, 66, 67, 2, 1, 1}, - {"RS-M3", 'L', 'A', OFTString, 68, 90, 23, 1, 1}}; -static const TigerRecordInfo rtM_info = { - rtM_fields, sizeof(rtM_fields) / sizeof(TigerFieldInfo), 90}; - -/************************************************************************/ -/* TigerSpatialMetadata() */ -/************************************************************************/ - -TigerSpatialMetadata::TigerSpatialMetadata( - OGRTigerDataSource *poDSIn, CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rtM_info, M_FILE_CODE) - -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("SpatialMetadata"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from record type H */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp b/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp deleted file mode 100644 index 8cc04a5ff360..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerTLIDRange, providing access to .RTR files. - * Author: Frank Warmerdam, warmerda@home.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char R_FILE_CODE[] = "R"; - -static const TigerFieldInfo rtR_2002_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"TLMAXID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"TLMINID", 'R', 'N', OFTInteger, 26, 35, 10, 1, 1}, - {"TLIGHID", 'R', 'N', OFTInteger, 36, 45, 10, 1, 1}, - {"TZMAXID", 'R', 'N', OFTInteger, 46, 55, 10, 1, 1}, - {"TZMINID", 'R', 'N', OFTInteger, 56, 65, 10, 1, 1}, - {"TZHIGHID", 'R', 'N', OFTInteger, 66, 75, 10, 1, 1}, - {"FILLER", 'L', 'A', OFTString, 76, 76, 1, 1, 1}, -}; -static const TigerRecordInfo rtR_2002_info = { - rtR_2002_fields, sizeof(rtR_2002_fields) / sizeof(TigerFieldInfo), 76}; - -static const TigerFieldInfo rtR_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTString, 6, 10, 5, 1, 1}, - {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1}, - {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1}, - {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1}, - {"MAXID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1}, - {"MINID", 'R', 'N', OFTInteger, 26, 35, 10, 1, 1}, - {"HIGHID", 'R', 'N', OFTInteger, 36, 45, 10, 1, 1}}; - -static const TigerRecordInfo rtR_info = { - rtR_fields, sizeof(rtR_fields) / sizeof(TigerFieldInfo), 46}; - -/************************************************************************/ -/* TigerTLIDRange() */ -/************************************************************************/ - -TigerTLIDRange::TigerTLIDRange(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(nullptr, R_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("TLIDRange"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - if (poDS->GetVersion() >= TIGER_2002) - { - psRTInfo = &rtR_2002_info; - } - else - { - psRTInfo = &rtR_info; - } - - /* -------------------------------------------------------------------- */ - /* Fields from type R record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp b/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp deleted file mode 100644 index 7c4cb9cc67a6..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerZeroCellID, providing access to .RTT files. - * Author: Mark Phillips, mbp@geomtech.com - * - ****************************************************************************** - * Copyright (c) 2002, Frank Warmerdam, Mark Phillips - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char T_FILE_CODE[] = "T"; - -static const TigerFieldInfo rtT_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1}, - {"TZID", 'R', 'N', OFTInteger, 11, 20, 10, 1, 1}, - {"SOURCE", 'L', 'A', OFTString, 21, 30, 10, 1, 1}, - {"FTRP", 'L', 'A', OFTString, 31, 47, 17, 1, 1}}; -static const TigerRecordInfo rtT_info = { - rtT_fields, sizeof(rtT_fields) / sizeof(TigerFieldInfo), 47}; - -/************************************************************************/ -/* TigerZeroCellID() */ -/************************************************************************/ - -TigerZeroCellID::TigerZeroCellID(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rtT_info, T_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("ZeroCellID"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from type T record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp b/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp deleted file mode 100644 index c64ed7a561ca..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerZipCodes, providing access to .RT6 files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char SIX_FILE_CODE[] = "6"; - -static const TigerFieldInfo rt6_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 1, 1}, - {"RTSQ", 'R', 'N', OFTInteger, 16, 18, 3, 1, 1}, - {"FRADDL", 'R', 'A', OFTString, 19, 29, 11, 1, 1}, - {"TOADDL", 'R', 'A', OFTString, 30, 40, 11, 1, 1}, - {"FRADDR", 'R', 'A', OFTString, 41, 51, 11, 1, 1}, - {"TOADDR", 'R', 'A', OFTString, 52, 62, 11, 1, 1}, - {"FRIADDL", 'L', 'A', OFTInteger, 63, 63, 1, 1, 1}, - {"TOIADDL", 'L', 'A', OFTInteger, 64, 64, 1, 1, 1}, - {"FRIADDR", 'L', 'A', OFTInteger, 65, 65, 1, 1, 1}, - {"TOIADDR", 'L', 'A', OFTInteger, 66, 66, 1, 1, 1}, - {"ZIPL", 'L', 'N', OFTInteger, 67, 71, 5, 1, 1}, - {"ZIPR", 'L', 'N', OFTInteger, 72, 76, 5, 1, 1}}; -static const TigerRecordInfo rt6_info = { - rt6_fields, sizeof(rt6_fields) / sizeof(TigerFieldInfo), 76}; - -/************************************************************************/ -/* TigerZipCodes() */ -/************************************************************************/ - -TigerZipCodes::TigerZipCodes(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rt6_info, SIX_FILE_CODE) - -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("ZipCodes"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from type 6 record. */ - /* -------------------------------------------------------------------- */ - - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp b/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp deleted file mode 100644 index 8a7aea3a9374..000000000000 --- a/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * - * Project: TIGER/Line Translator - * Purpose: Implements TigerZipPlus4, providing access to .RTZ files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 1999, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "ogr_tiger.h" -#include "cpl_conv.h" - -static const char Z_FILE_CODE[] = "Z"; - -static const TigerFieldInfo rtZ_fields[] = { - // fieldname fmt type OFTType beg end len bDefine bSet - {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0}, - {"TLID", 'R', 'N', OFTInteger, 6, 15, 10, 1, 1}, - {"RTSQ", 'R', 'N', OFTInteger, 16, 18, 3, 1, 1}, - {"ZIP4L", 'L', 'N', OFTInteger, 19, 22, 4, 1, 1}, - {"ZIP4R", 'L', 'N', OFTInteger, 23, 26, 4, 1, 1}}; -static const TigerRecordInfo rtZ_info = { - rtZ_fields, sizeof(rtZ_fields) / sizeof(TigerFieldInfo), 26}; - -/************************************************************************/ -/* TigerZipPlus4() */ -/************************************************************************/ - -TigerZipPlus4::TigerZipPlus4(OGRTigerDataSource *poDSIn, - CPL_UNUSED const char *pszPrototypeModule) - : TigerFileBase(&rtZ_info, Z_FILE_CODE) -{ - poDS = poDSIn; - poFeatureDefn = new OGRFeatureDefn("ZipPlus4"); - poFeatureDefn->Reference(); - poFeatureDefn->SetGeomType(wkbNone); - - /* -------------------------------------------------------------------- */ - /* Fields from type Z record. */ - /* -------------------------------------------------------------------- */ - AddFieldDefns(psRTInfo, poFeatureDefn); -} diff --git a/port/cpl_known_config_options.h b/port/cpl_known_config_options.h index d30894ea527e..012f1b045f0e 100644 --- a/port/cpl_known_config_options.h +++ b/port/cpl_known_config_options.h @@ -4,7 +4,6 @@ // clang-format off constexpr static const char* const apszKnownConfigOptions[] = { - "ADRG_SIMULATE_MULTI_IMG", // from adrgdataset.cpp "ALLOW_GPKG_ZOOM_OTHER_EXTENSION", // from ogrgeopackagedatasource.cpp "ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW", // from ogrsqlitedatasource.cpp "ALLOW_VIRTUAL_OGR_FROM_TRIGGER_AND_VIEW", // from ogrsqlitevirtualogr.cpp @@ -733,7 +732,6 @@ constexpr static const char* const apszKnownConfigOptions[] = "OGR_ODS_FIELD_TYPES", // from ogrodsdatasource.cpp "OGR_ODS_HEADERS", // from ogrodsdatasource.cpp "OGR_ODS_MAX_FIELD_COUNT", // from ogrodsdatasource.cpp - "OGR_OGDI_LAUNDER_LAYER_NAMES", // from ogrogdidatasource.cpp "OGR_OPENFILEGDB_ERROR_ON_INCONSISTENT_BUFFER_MAX_SIZE", // from filegdbtable.cpp "OGR_OPENFILEGDB_WRITE_EMPTY_GEOMETRY", // from ogropenfilegdblayer_write.cpp "OGR_ORGANIZE_POLYGONS", // from filegdbtable.cpp, ogrgeometryfactory.cpp @@ -952,7 +950,6 @@ constexpr static const char* const apszKnownConfigOptions[] = "PYTHONSO", // from gdalpython.cpp "QGIS_HACK", // from ogrfeaturedefn.cpp "QHULL_LOG_TO_TEMP_FILE", // from delaunay.c - "RASTERLITE_OVR_OPTIONS", // from rasterliteoverviews.cpp "RAW_CHECK_FILE_SIZE", // from rawdataset.cpp "RAW_MEM_ALLOC_LIMIT_MB", // from rawdataset.cpp "REPORT_COMPD_CS", // from dteddataset.cpp, srtmhgtdataset.cpp @@ -994,8 +991,6 @@ constexpr static const char* const apszKnownConfigOptions[] = "THRESHOLD", // from ogrct.cpp "TIFF_READ_STREAMING", // from gtiffdataset_read.cpp "TIFF_USE_OVR", // from gtiffdataset_write.cpp - "TIGER_LFIELD_AS_STRING", // from tigerfilebase.cpp - "TIGER_VERSION", // from ogrtigerdatasource.cpp "TILEDB_ATTRIBUTE", // from tiledbdense.cpp "TILEDB_BINARY_TYPE", // from tiledbsparse.cpp "TILEDB_BUG", // from tiledbsparse.cpp