From 36268a8cbb5ec20847853d430eb1349ea734f017 Mon Sep 17 00:00:00 2001 From: Charles Gaydon Date: Tue, 8 Aug 2023 19:50:19 +0200 Subject: [PATCH] feat: support colorization for <0.2m clouds (including height=0/width=0) --- CHANGELOG.md | 10 ++++++++-- pdaltools/_version.py | 2 +- pdaltools/color.py | 44 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1c5f14..a50402a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,14 @@ # dev + +# 1.3.0 +- color: support colorization for <0.2m clouds (including height=0/width=0) +- color: ceil width/height to have a bbox that contains all points + +# 1.2.1 - fix cicd_full github action: deployment was triggered on pushing to dev instead of master only # 1.2.0 -color: keep downloaded orthoimages by returning them to make them stay in executionn scope +- color: keep downloaded orthoimages by returning them to make them stay in execution scope # 1.1.1 - unlock: fix main @@ -12,7 +18,7 @@ color: keep downloaded orthoimages by returning them to make them stay in execut # 1.1.0 - standardization: handle malformed laz input ("Global encoding WKT flag not set for point format 6 - 10") -color: extract unlock module from colorization and rename colorization function +- color: extract unlock module from colorization and rename colorization function # 1.0.0 - first public version diff --git a/pdaltools/_version.py b/pdaltools/_version.py index 986d109..692e5cc 100644 --- a/pdaltools/_version.py +++ b/pdaltools/_version.py @@ -1,4 +1,4 @@ -__version__ = "1.2.0" +__version__ = "1.3.0" if __name__ == "__main__": diff --git a/pdaltools/color.py b/pdaltools/color.py index d1e840b..48efa27 100644 --- a/pdaltools/color.py +++ b/pdaltools/color.py @@ -1,4 +1,5 @@ import json +from math import ceil import subprocess as sp import tempfile import pdal @@ -59,13 +60,22 @@ def newfn(*args, **kwargs): def download_image_from_geoportail(proj, layer, minx, miny, maxx, maxy, pixel_per_meter, outfile, timeout): + # Give single-point clouds a width/height of at least one pixel to have valid BBOX and SIZE + if minx == maxx: + maxx = minx + 1 / pixel_per_meter + if miny == maxy: + maxy = miny + 1 / pixel_per_meter + # for layer in layers: URL_GPP = "https://wxs.ign.fr/ortho/geoportail/r/wms?" URL_FORMAT = "&EXCEPTIONS=text/xml&FORMAT=image/geotiff&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&STYLES=" URL_EPSG = "&CRS=EPSG:" + str(proj) URL_BBOX = "&BBOX=" + str(minx) + "," + str(miny) + "," + str(maxx) + "," + str(maxy) URL_SIZE = ( - "&WIDTH=" + str(int((maxx - minx) * pixel_per_meter)) + "&HEIGHT=" + str(int((maxy - miny) * pixel_per_meter)) + "&WIDTH=" + + str(ceil((maxx - minx) * pixel_per_meter)) + + "&HEIGHT=" + + str(ceil((maxy - miny) * pixel_per_meter)) ) URL = URL_GPP + "LAYERS=" + layer + URL_FORMAT + URL_EPSG + URL_BBOX + URL_SIZE @@ -143,7 +153,15 @@ def color( if color_rvb_enabled: tmp_ortho = tempfile.NamedTemporaryFile().name download_image_from_geoportail_retrying( - proj, "ORTHOIMAGERY.ORTHOPHOTOS", minx, miny, maxx, maxy, pixel_per_meter, tmp_ortho, timeout_second + proj, + "ORTHOIMAGERY.ORTHOPHOTOS", + minx, + miny, + maxx, + maxy, + pixel_per_meter, + tmp_ortho, + timeout_second, ) pipeline |= pdal.Filter.colorization(raster=tmp_ortho, dimensions="Red:1:256.0, Green:2:256.0, Blue:3:256.0") @@ -181,18 +199,34 @@ def parse_args(): parser.add_argument("--input", "-i", type=str, required=True, help="Input file") parser.add_argument("--output", "-o", type=str, default="", help="Output file") parser.add_argument( - "--proj", "-p", type=str, default="", help="Projection, default will use projection from metadata input" + "--proj", + "-p", + type=str, + default="", + help="Projection, default will use projection from metadata input", ) parser.add_argument("--resolution", "-r", type=float, default=5, help="Resolution, in pixel per meter") parser.add_argument("--timeout", "-t", type=int, default=300, help="Timeout, in seconds") parser.add_argument("--rvb", action="store_true", help="Colorize RVB") parser.add_argument("--ir", action="store_true", help="Colorize IR") parser.add_argument( - "--vegetation", type=str, default="", help="Vegetation file, value will be stored in Deviation field" + "--vegetation", + type=str, + default="", + help="Vegetation file, value will be stored in Deviation field", ) return parser.parse_args() if __name__ == "__main__": args = parse_args() - color(args.input, args.output, args.proj, args.resolution, args.timeout, args.rvb, args.ir, args.vegetation) + color( + args.input, + args.output, + args.proj, + args.resolution, + args.timeout, + args.rvb, + args.ir, + args.vegetation, + )