Skip to content

Commit c81e61e

Browse files
authored
Merge pull request #117 from rouault/gridshift_projected
check_gtiff_grid.py: enhance to support grids referenced in projected…
2 parents a810a6d + 4495fac commit c81e61e

File tree

1 file changed

+72
-32
lines changed

1 file changed

+72
-32
lines changed

grid_tools/check_gtiff_grid.py

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def get_srs(ds, epsg_code_key, wkt_key, is_first_subds, infos, warnings, errors)
7575
return srs
7676

7777

78-
def validate_horizontal_offset(type, ds, is_first_subds):
78+
def validate_horizontal_offset(type, ds, src_crs, is_first_subds):
7979

8080
infos = []
8181
warnings = []
@@ -84,8 +84,12 @@ def validate_horizontal_offset(type, ds, is_first_subds):
8484
target_crs = get_srs(ds, 'target_crs_epsg_code', 'target_crs_wkt',
8585
is_first_subds, infos, warnings, errors)
8686
if target_crs:
87-
if not target_crs.IsGeographic():
88-
warnings.append("target_crs found, but not a Geographic CRS")
87+
if not src_crs or src_crs.IsGeographic():
88+
if not target_crs.IsGeographic():
89+
warnings.append("target_crs found, but not a Geographic CRS")
90+
elif src_crs.IsProjected():
91+
if not target_crs.IsProjected():
92+
warnings.append("target_crs found, but not a Projected CRS")
8993

9094
if ds.RasterCount < 2:
9195
return infos, warnings, [f"TYPE={type} should have at least 2 bands"]
@@ -100,6 +104,8 @@ def validate_horizontal_offset(type, ds, is_first_subds):
100104
eht_offset_idx = 0
101105
lat_accuracy_idx = 0
102106
lon_accuracy_idx = 0
107+
easting_offset_idx = 0
108+
northing_offset_idx = 0
103109
for i in range(ds.RasterCount):
104110
b = ds.GetRasterBand(i+1)
105111
desc = b.GetDescription()
@@ -111,6 +117,14 @@ def validate_horizontal_offset(type, ds, is_first_subds):
111117
if lon_offset_idx > 0:
112118
return infos, warnings, ["At least, 2 bands are tagged with Description = longitude_offset"]
113119
lon_offset_idx = i+1
120+
elif desc == 'easting_offset':
121+
if easting_offset_idx > 0:
122+
return infos, warnings, ["At least, 2 bands are tagged with Description = easting_offset"]
123+
easting_offset_idx = i+1
124+
elif desc == 'northing_offset':
125+
if northing_offset_idx > 0:
126+
return infos, warnings, ["At least, 2 bands are tagged with Description = northing_offset"]
127+
northing_offset_idx = i+1
114128
elif desc == 'ellipsoidal_height_offset':
115129
if eht_offset_idx > 0:
116130
return infos, warnings, ["At least, 3 bands are tagged with Description = ellipsoidal_height_offset"]
@@ -128,12 +142,25 @@ def validate_horizontal_offset(type, ds, is_first_subds):
128142
'Usually the first band should be latitude_offset and the second longitude_offset.')
129143
elif lat_offset_idx > 0 or lon_offset_idx > 0:
130144
return infos, warnings, ["One of the band is tagged with Description = latitude_offset/longitude_offset but not the other one"]
145+
elif easting_offset_idx > 0 and northing_offset_idx > 0:
146+
if easting_offset_idx != 1 or northing_offset_idx != 2:
147+
infos.append(
148+
'Usually the first band should be easting_offset and the second northing_offset.')
149+
elif easting_offset_idx > 0 or northing_offset_idx > 0:
150+
return infos, warnings, ["One of the band is tagged with Description = easting_offset/northing_offset but not the other one"]
131151
else:
132-
if is_first_subds:
133-
warnings.append(
134-
'No explicit bands tagged with Description = latitude_offset and longitude_offset. Assuming first one is latitude_offset and second one longitude_offset')
135-
lat_offset_idx = 1
136-
lon_offset_idx = 2
152+
if src_crs and src_crs.IsProjected():
153+
if is_first_subds:
154+
warnings.append(
155+
'No explicit bands tagged with Description = easting_offset and northing_offset. Assuming first one is easting_offset and second one northing_offset')
156+
easting_offset_idx = 1
157+
northing_offset_idx = 2
158+
else:
159+
if is_first_subds:
160+
warnings.append(
161+
'No explicit bands tagged with Description = latitude_offset and longitude_offset. Assuming first one is latitude_offset and second one longitude_offset')
162+
lat_offset_idx = 1
163+
lon_offset_idx = 2
137164

138165
if type == "GEOGRAPHIC_3D_OFFSET":
139166
if eht_offset_idx == 0:
@@ -145,29 +172,42 @@ def validate_horizontal_offset(type, ds, is_first_subds):
145172
if eht_offset_idx != 0:
146173
return infos, warnings, ["Band with Description = ellipsoidal_height_offset found, but not expected"]
147174

148-
for idx in (lat_offset_idx, lon_offset_idx):
149-
band = ds.GetRasterBand(idx)
150-
if band.GetNoDataValue():
151-
warnings.append(
152-
"One of latitude_offset/longitude_offset band has a nodata setting. Nodata for horizontal shift grids is ignored by PROJ")
153-
units = band.GetUnitType()
154-
if not units:
155-
if is_first_subds:
175+
if lat_offset_idx:
176+
for idx in (lat_offset_idx, lon_offset_idx):
177+
band = ds.GetRasterBand(idx)
178+
if band.GetNoDataValue():
156179
warnings.append(
157-
"One of latitude_offset/longitude_offset band is missing units description. arc-second will be assumed")
158-
elif units not in ('arc-second', 'arc-seconds per year', 'degree', 'radians'):
159-
errors.append(
160-
"One of latitude_offset/longitude_offset band is using a unit not supported by PROJ")
180+
"One of latitude_offset/longitude_offset band has a nodata setting. Nodata for horizontal shift grids is ignored by PROJ")
181+
units = band.GetUnitType()
182+
if not units:
183+
if is_first_subds:
184+
warnings.append(
185+
"One of latitude_offset/longitude_offset band is missing units description. arc-second will be assumed")
186+
elif units not in ('arc-second', 'arc-seconds per year', 'degree', 'radians'):
187+
errors.append(
188+
"One of latitude_offset/longitude_offset band is using a unit not supported by PROJ")
189+
else:
190+
for idx in (easting_offset_idx, northing_offset_idx):
191+
band = ds.GetRasterBand(idx)
192+
units = band.GetUnitType()
193+
if not units:
194+
if is_first_subds:
195+
warnings.append(
196+
"One of easting_offset/northing_offset band is missing units description.metre will be assumed")
197+
elif units not in ('metre'):
198+
errors.append(
199+
"One of easting_offset/northing_offset band is using a unit not supported by PROJ")
161200

162-
positive_value = ds.GetRasterBand(
163-
lon_offset_idx).GetMetadataItem('positive_value')
164-
if not positive_value:
165-
if is_first_subds:
166-
warnings.append(
167-
"The latitude_offset band should include a positive_value=west/east metadata item, to avoid any ambiguity w.r.t NTv2 original convention. 'east' will be assumed")
168-
elif positive_value not in ('west', 'east'):
169-
errors.append("positive_value=%s not supported by PROJ" %
170-
positive_value)
201+
if lon_offset_idx:
202+
positive_value = ds.GetRasterBand(
203+
lon_offset_idx).GetMetadataItem('positive_value')
204+
if not positive_value:
205+
if is_first_subds:
206+
warnings.append(
207+
"The latitude_offset band should include a positive_value=west/east metadata item, to avoid any ambiguity w.r.t NTv2 original convention. 'east' will be assumed")
208+
elif positive_value not in ('west', 'east'):
209+
errors.append("positive_value=%s not supported by PROJ" %
210+
positive_value)
171211

172212
if eht_offset_idx > 0:
173213
band = ds.GetRasterBand(eht_offset_idx)
@@ -628,7 +668,7 @@ def validate_ifd(global_info, ds, is_first_subds, first_subds):
628668
if is_first_subds:
629669
errors.append("No CRS found in the GeoTIFF encoding")
630670
else:
631-
if not srs.IsGeographic() and ds.GetMetadataItem('TYPE') != 'DEFORMATION_MODEL':
671+
if not srs.IsGeographic() and ds.GetMetadataItem('TYPE') not in ('DEFORMATION_MODEL', 'HORIZONTAL_OFFSET'):
632672
errors.append("CRS found, but not a Geographic CRS")
633673

634674
if ds.GetMetadataItem('AREA_OR_POINT') != 'Point':
@@ -713,7 +753,7 @@ def validate_ifd(global_info, ds, is_first_subds, first_subds):
713753
'Image uses %s compression. Might cause compatibility problems' % compression)
714754

715755
if type in ('HORIZONTAL_OFFSET', 'GEOGRAPHIC_3D_OFFSET'):
716-
i, w, e = validate_horizontal_offset(type, ds, is_first_subds)
756+
i, w, e = validate_horizontal_offset(type, ds, srs, is_first_subds)
717757
infos += i
718758
warnings += w
719759
errors += e
@@ -807,7 +847,7 @@ def validate_ifd(global_info, ds, is_first_subds, first_subds):
807847
md = b.GetMetadata_Dict()
808848
md_keys = md.keys()
809849
for key in md_keys:
810-
if key not in ('positive_value'):
850+
if key not in ('positive_value', 'constant_offset'):
811851
infos.append('Metadata %s=%s on band %d ignored' %
812852
(key, md[key], i+1))
813853

0 commit comments

Comments
 (0)