#!/usr/bin/env python
'''
BDAlti maps module
==================
Convertion tools for BDAlti maps (https://geoservices.ign.fr/documentation/diffusion/telechargement-donnees-libres.html#bd-alti) and their use in :mod:`catamap`.
API
---
'''
from __future__ import print_function
import numpy as np
import os
import glob
try:
from soma import aims
except ImportError:
# allow toi generate docs without aims
aims = None
import json
import math
osp = os.path
[docs]def get_map_image(xi, yi, meta_map, base):
'''
get image at coords xi, yi in the map table. Lazy load and cache it.
'''
# print(xi, yi)
metadata = meta_map['table'][yi][xi]
if metadata is None:
return None
image = metadata.get('image')
if not image:
fname = osp.join(base, 'raw_images', metadata['file'])
print('load altitude map:', fname)
image = aims.read(fname)
metadata['image'] = image
return image
[docs]def get_z(x, y, meta_map, base, background_z=-99999.00):
'''
get the altitude from (x, y) coords in Lambert93 coords
'''
xpos = meta_map['xllcorners']
x0 = x - xpos[0]
cs = meta_map['cellsize']
xi = int(x0 / cs)
if xi < 0 or xi >= len(xpos):
return background_z
x1 = x0 / cs - xi
ypos = meta_map['yllcorners']
y0 = y - ypos[0]
# cs = meta_map['cellsize']
yi = int(y0 / cs)
if yi < 0 or yi >= len(ypos):
return background_z
y1 = y0 / cs - yi
image = get_map_image(xi, yi, meta_map, base)
if image is None:
return background_z
x2 = int(x1 * image.getSizeX())
y2 = int(y1 * image.getSizeY())
# print(' ->', x2, y2)
z = image.at(x2, image.getSizeY() - y2 - 1)
if z == image.header()['NODATA_value']:
z = background_z
return z
[docs]def convert_raw_map(fname, out_fname):
'''
convert one raw map from bdalti (.asc) to .ima format
'''
with open(fname) as f:
lines = f.readlines()
types = {
'ncols': int,
'cellsize': float,
'xllcorner': float,
'yllcorner': float,
'NODATA_value': float,
}
metadata = {}
for l in lines[:6]:
item = l.strip().split()
k = item[0]
metadata[k] = types.get(k, str)(item[1])
# print(metadata)
image = aims.Volume((int(metadata['ncols']), int(metadata['nrows'])),
dtype='float')
array = np.asarray(image)
for i, l in enumerate(lines[6:]):
array[:, i, 0, 0] = [float(x) for x in l.strip().split()]
image.header().update(metadata)
aims.write(image, out_fname)
[docs]def convert_raw_maps(fnames, out_fnames):
'''
convert all raw data files from bdalti (.asc) to .ima format
fnames:
input files pattern (used with glob.glob())
out_fnames:
output files pattern, should contain a "%s" pattern
'''
for fname in glob.glob(fnames):
bname = osp.basename(fname)
out_fname = out_fnames % bname.split('.')[0]
convert_raw_map(fname, out_fname)
# ----
if __name__ == '__main__':
base = '/volatile/home/denis/catacombes/plans/14/plan_14_2017/altitude/BDALTIV2_2-0_75M_ASC_LAMB93-IGN69_FRANCE_2020-04-28/BDALTIV2'
fnames = osp.join(base, '1_DONNEES_LIVRAISON_2020-05-00201/BDALTIV2_MNT_75M_ASC_LAMB93_IGN69_FRANCE/*.asc')
out_fnames = osp.join(base, 'raw_images/%s.ima')
out_map = osp.join(base, 'map.json')
# ---
#convert_raw_maps(fnames, out_fnames)
# ---
#meta_map = build_meta_table(out_fnames)
#with open(out_map, 'w') as f:
#json.dump(meta_map, f)
# ----
with open(out_map) as f:
meta_map = json.load(f)
coords = [(648076.25, 6858784.37),
(651831.92, 6857938.91),
(652528.99, 6861468.52)]
ztest = [58.24, 59.8, 26.97]
for c, zt in zip(coords, ztest):
z = get_z(c[0], c[1], meta_map, base)
print(c, ', z:', z, ', expected:', zt, '(D=%f)' % (z - zt))