Compler les NaN du MNT 8x plus vite via transformée de distance

Remplace NearestNDInterpolator (cKDTree sur les 25 M de points valides,
plusieurs secondes par dalle trouée en mode IGN pur) par
distance_transform_edt : plus proche voisin en une passe O(n).
Voisins équidistants arbitres differemment, sans effet sur les rendus.
This commit is contained in:
Antoine Jacquin
2026-09-16 20:21:54 +02:00
parent 06a8dd5604
commit 6780f2e25b

View File

@ -214,22 +214,19 @@ def _fill_nans(arr):
"""Fill NaN values using nearest-neighbor interpolation. """Fill NaN values using nearest-neighbor interpolation.
Returns (filled_array, nan_mask) so the caller can restore NaN after filtering. Returns (filled_array, nan_mask) so the caller can restore NaN after filtering.
Via transformée de distance (O(n), vectorisé) : les indices du plus proche
voisin valides sortent en une passe. NearestNDInterpolator construisait un
cKDTree sur TOUS les points valides (25 M à 0,2 m) — plusieurs secondes
par dalle trouée, payées au premier accès de SharedDEM.filled.
""" """
from scipy.interpolate import NearestNDInterpolator
nan_mask = np.isnan(arr) nan_mask = np.isnan(arr)
if not np.any(nan_mask): if not np.any(nan_mask):
return arr, nan_mask return arr, nan_mask
valid = ~nan_mask from scipy.ndimage import distance_transform_edt
y_coords, x_coords = np.where(valid) _, (iy, ix) = distance_transform_edt(nan_mask, return_indices=True)
if len(y_coords) == 0:
return np.zeros_like(arr), nan_mask
z_values = arr[valid]
interp = NearestNDInterpolator(
np.column_stack((y_coords, x_coords)), z_values
)
y_missing, x_missing = np.where(nan_mask)
filled = arr.copy() filled = arr.copy()
filled[y_missing, x_missing] = interp(y_missing, x_missing) filled[nan_mask] = arr[iy[nan_mask], ix[nan_mask]]
return filled, nan_mask return filled, nan_mask