From 73ab31021c59e1a0ffe7b0f0ca4fef45e2637646 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 9 Nov 2025 21:55:15 +0100 Subject: [PATCH] Add tin_json_to_tin_gpkg.py --- grid_tools/README.md | 15 ++ grid_tools/tin_json_to_tin_gpkg.py | 274 +++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100755 grid_tools/tin_json_to_tin_gpkg.py diff --git a/grid_tools/README.md b/grid_tools/README.md index 28ca096..3008ecd 100644 --- a/grid_tools/README.md +++ b/grid_tools/README.md @@ -190,3 +190,18 @@ such as [gdal_translate](https://gdal.org/programs/gdal_translate.html) or [gdal_edit.py](https://gdal.org/programs/gdal_edit.html) Note: this script will not compress data. This must be done in a prior step. + +## Converting a TIN JSON file to a TIN GeoPackage file + +With the [tin_json_to_tin_gpkg.py](tin_json_to_tin_gpkg.py) script. + +Both formats may be used by the +proj=tinshift operation. + +Usage: +``` +usage: tin_json_to_tin_gpkg.py [-h] source dest +``` + +See https://proj.org/en/latest/specifications/tin_json.html and +https://proj.org/en/latest/specifications/tin_gpkg.html for the specification +of both format. diff --git a/grid_tools/tin_json_to_tin_gpkg.py b/grid_tools/tin_json_to_tin_gpkg.py new file mode 100755 index 0000000..b92ecdd --- /dev/null +++ b/grid_tools/tin_json_to_tin_gpkg.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +############################################################################### +# +# Project: PROJ +# Purpose: Convert a TIN JSON to a TIN GeoPackage +# Author: Even Rouault +# +############################################################################### +# Copyright (c) 2025, Even Rouault +# +# SPDX-License-Identifier: MIT +############################################################################### + +import argparse +import json +import struct + +from osgeo import gdal, ogr, osr + + +def get_args(): + parser = argparse.ArgumentParser( + description="Convert a TIN JSON to a TIN GeoPackage." + ) + parser.add_argument("source", help="Source JSON file") + parser.add_argument("dest", help="Destination GeoPackage file") + return parser.parse_args() + + +def as_i32le_hex(v): + return "".join(["%02X" % b for b in struct.pack("= "3120000": + with gdal.alg.vector.check_coverage( + input=dest, output="", output_format="MEM", input_layer="triangles" + ) as alg: + out_ds = alg.Output() + out_lyr = out_ds.GetLayer(0) + if out_lyr.GetFeatureCount(): + print("Coverage of triangles has issues. Invalid edges:") + for f in out_lyr: + f.DumpReadable() + + +if __name__ == "__main__": + + gdal.UseExceptions() + args = get_args() + convert_json_to_gpkg(args.source, args.dest)