|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +# SPDX-License-Identifier: MIT |
| 4 | +# Copyright 2024, Even Rouault <even.rouault at spatialys.com> |
| 5 | +# Convert file table_yx_3_v1710.dat(https://www.cuzk.cz/Zememerictvi/Geodeticke-zaklady-na-uzemi-CR/GNSS/Nova-realizace-systemu-ETRS89-v-CR/table_yx_3_v1710.aspx) |
| 6 | +# doing S-JTSK to S-JTSK/05 shifts (in projected units) to GTG. |
| 7 | + |
| 8 | +import datetime |
| 9 | +import os |
| 10 | +from osgeo import gdal, osr |
| 11 | + |
| 12 | +gdal.UseExceptions() |
| 13 | + |
| 14 | +src_filename = "table_yx_3_v1710.dat" |
| 15 | + |
| 16 | +assert os.path.exists(src_filename), "Download file table_yx_3_v1710.dat from https://www.cuzk.cz/Zememerictvi/Geodeticke-zaklady-na-uzemi-CR/GNSS/Nova-realizace-systemu-ETRS89-v-CR/table_yx_3_v1710.aspx" |
| 17 | + |
| 18 | +ds = gdal.Open(src_filename) |
| 19 | +delta_westing = ds.GetRasterBand(1).ReadAsArray() |
| 20 | + |
| 21 | +tmp_tif_name = "table_yx_3_v1710_east_north_tmp.tif" |
| 22 | +width = ds.RasterXSize |
| 23 | +height = ds.RasterYSize |
| 24 | +out_ds = gdal.GetDriverByName("GTiff").Create(tmp_tif_name, |
| 25 | + width, |
| 26 | + height, |
| 27 | + 2, # number of bands |
| 28 | + gdal.GDT_Float32) |
| 29 | +orig_gt = ds.GetGeoTransform() |
| 30 | +horizontal_res = orig_gt[1] |
| 31 | +vertical_res = orig_gt[5] |
| 32 | +assert vertical_res > 0 # XYZ driver returns a "south-up" raster |
| 33 | +# min_westing = orig_gt[0] |
| 34 | +min_southing = orig_gt[3] |
| 35 | +max_westing = orig_gt[0] + horizontal_res * width |
| 36 | +# max_southing = orig_gt[3] + vertical_res * height |
| 37 | + |
| 38 | +min_easting = -max_westing |
| 39 | +max_northing = -min_southing |
| 40 | +gt = [ min_easting, horizontal_res, 0, max_northing, 0, -vertical_res ] |
| 41 | +out_ds.SetGeoTransform(gt) |
| 42 | + |
| 43 | +srs = osr.SpatialReference() |
| 44 | +srs.ImportFromEPSG(5514) # S-JTSK / Krovak East North |
| 45 | +out_ds.SetSpatialRef(srs) |
| 46 | + |
| 47 | +OFFSET_SJTSK_TO_SJTSK05 = -5000000 |
| 48 | + |
| 49 | +md = {} |
| 50 | +md["area_of_use"] = "Czechia" |
| 51 | +md["AREA_OR_POINT"] = "Point" |
| 52 | +md["target_crs_epsg_code"] = "5516" # S-JTSK/05 / Modified Krovak East North |
| 53 | +md["TIFFTAG_COPYRIGHT"] = "Derived from work by Czech Office of Surveying and Cadastre (CUZK). !!!LICENSE TO BE DEFINED!!!" |
| 54 | +md["TIFFTAG_IMAGEDESCRIPTION"] = f"S-JTSK / Krovak East North (EPSG:5514) to S-JTSK/05 / Modified Krovak East North (EPSG:5516). Converted from {src_filename} by switching to easting/northing rather than original westing/southing. Note also that an extra offset of {OFFSET_SJTSK_TO_SJTSK05} in easting and northing must be applied" |
| 55 | +md["TYPE"] = "HORIZONTAL_OFFSET" |
| 56 | +md["TIFFTAG_DATETIME"] = datetime.date.today().strftime("%Y:%m:%d %H:%M:%S") |
| 57 | +md["interpolation_method"] = "biquadratic" |
| 58 | +out_ds.SetMetadata(md) |
| 59 | + |
| 60 | +source_nodata = ds.GetRasterBand(1).GetNoDataValue() |
| 61 | + |
| 62 | +target_nodata = -9999 |
| 63 | + |
| 64 | +# Transform delta_westing into delta_easting by negating the sign of the |
| 65 | +# values, and flipping the array in horizontal direction. |
| 66 | +delta_easting = -1.0 * delta_westing[...,::-1] |
| 67 | +delta_easting[delta_easting == -source_nodata] = target_nodata |
| 68 | +delta_easting_band = out_ds.GetRasterBand(1) |
| 69 | +delta_easting_band.WriteArray(delta_easting) |
| 70 | +delta_easting_band.SetDescription("easting_offset") |
| 71 | +delta_easting_band.SetUnitType("metre") |
| 72 | +delta_easting_band.SetMetadataItem("positive_value", "east") |
| 73 | +delta_easting_band.SetMetadataItem("constant_offset", str(OFFSET_SJTSK_TO_SJTSK05)) |
| 74 | +delta_easting_band.SetNoDataValue(target_nodata) |
| 75 | + |
| 76 | +tmp_dat_filename = src_filename + ".tmp" |
| 77 | +with open(tmp_dat_filename, "wb") as f: |
| 78 | + # Do not be fooled by the labels... They are just for the purpose of |
| 79 | + # the GDAL XYZ driver. So the below X is actually a westing(Y in S-JTSK...), |
| 80 | + # Y a southing (X in S-JTSK...), the ignored column is the delta_westing, |
| 81 | + # and GDAL Z is delta_southing |
| 82 | + f.write(b"X,Y,ignored,Z\n") |
| 83 | + with open(src_filename, "rb") as src_f: |
| 84 | + f.write(src_f.read()) |
| 85 | + |
| 86 | +ds = gdal.Open(tmp_dat_filename) |
| 87 | +delta_southing = ds.GetRasterBand(1).ReadAsArray() |
| 88 | + |
| 89 | +# Transform delta_southing into delta_northing by negating the sign of the |
| 90 | +# values, and flipping the array in horizontal direction. |
| 91 | +delta_northing = -1.0 * delta_southing[...,::-1] |
| 92 | +delta_northing[delta_northing == -source_nodata] = target_nodata |
| 93 | +delata_northing_band = out_ds.GetRasterBand(2) |
| 94 | +delata_northing_band.WriteArray(delta_northing) |
| 95 | +delata_northing_band.SetDescription("northing_offset") |
| 96 | +delata_northing_band.SetUnitType("metre") |
| 97 | +delata_northing_band.SetMetadataItem("positive_value", "north") |
| 98 | +delata_northing_band.SetMetadataItem("constant_offset", str(OFFSET_SJTSK_TO_SJTSK05)) |
| 99 | +delata_northing_band.SetNoDataValue(target_nodata) |
| 100 | + |
| 101 | +del out_ds |
| 102 | + |
| 103 | +gdal.Unlink(tmp_dat_filename) |
| 104 | + |
| 105 | +# Generate final file |
| 106 | +gdal.Translate("cz_cuzk_table_yx_3_v1710_east_north.tif", |
| 107 | + tmp_tif_name, |
| 108 | + creationOptions=["BLOCKYSIZE=" + str(height), "COMPRESS=LZW", "PREDICTOR=3"]) |
| 109 | + |
| 110 | +gdal.Unlink(tmp_tif_name) |
0 commit comments