2727import logging
2828import os
2929from ast import literal_eval
30+ from typing import Union
3031
3132# Third party imports
3233import numpy as np
34+ from affine import Affine
3335from numba import config , njit , prange
3436
37+ import bindings_cpp
38+ from shareloc .geofunctions .dtm_intersection import DTMIntersection
39+
3540# Shareloc imports
3641from shareloc .geomodels .geomodel import GeoModel
3742from shareloc .geomodels .geomodel_template import GeoModelTemplate
3843from shareloc .geomodels .rpc_readers import rpc_reader
39- from shareloc .proj_utils import coordinates_conversion
44+ from shareloc .proj_utils import coordinates_conversion , transform_index_to_physical_point
4045
4146# Set numba type of threading layer before parallel target compilation
4247config .THREADING_LAYER = "omp"
@@ -315,21 +320,22 @@ def direct_loc_dtm(self, row, col, dtm):
315320 row = np .array ([row ])
316321 col = np .array ([col ])
317322
318- diff_alti_min , diff_alti_max = dtm .get_alt_offset (self .epsg )
323+ diff_alti_min , diff_alti_max = self .get_dtm_alt_offset (dtm .get_footprint_corners (), dtm )
324+
319325 # print("min {} max {}".format(dtm.Zmin,dtm.Zmax))
320326 (min_dtm , max_dtm ) = (dtm .get_alt_min () - 1.0 + diff_alti_min , dtm .get_alt_max () + 1.0 + diff_alti_max )
321327 if min_dtm < self .offset_alt - self .scale_alt :
322328 logging .debug ("minimum dtm value is outside RPC validity domain, extrapolation will be done" )
323329 if max_dtm > self .offset_alt + self .scale_alt :
324330 logging .debug ("maximum dtm value is outside RPC validity domain, extrapolation will be done" )
331+
325332 los = self .los_extrema (row , col , min_dtm , max_dtm , epsg = dtm .get_epsg ())
326333
327334 # los -> (nb_point,nb_alt,3)
328335 los = los .T
329336 los = np .expand_dims (los , axis = 0 )
330337 los = np .moveaxis (los , 1 , - 1 )
331338 los = los .reshape ((len (col ), 2 , 3 ))
332-
333339 direct_dtm = dtm .intersection_n_los_dtm (los )
334340
335341 return direct_dtm
@@ -559,6 +565,29 @@ def get_alt_min_max(self):
559565 """
560566 return [self .offset_alt - self .scale_alt / 2.0 , self .offset_alt + self .scale_alt / 2.0 ]
561567
568+ def get_dtm_alt_offset (self , corners : np .ndarray , dtm : Union [DTMIntersection , bindings_cpp .DTMIntersection ]):
569+ """
570+ returns min/max altitude offset between dtm coordinates system and RPC one
571+
572+ :param corners: corners of the DTM's footprint
573+ :type corners: np.ndarray (4x2)
574+ :param dtm: DTM to get alt offset from
575+ :type dtm: DTMIntersection or bindings_cpp.DTMIntersection
576+ :return: min/max altimetric difference between RPC's epsg minus dtm alti expressed in dtm epsg
577+ :rtype: list of float (1x2)
578+ """
579+
580+ alti_moy = (dtm .get_alt_min () + dtm .get_alt_max ()) / 2.0
581+
582+ ground_corners = np .zeros ([3 , 4 ])
583+ ground_corners [2 , :] = alti_moy
584+ transform = dtm .get_transform ()
585+ if not isinstance (transform , Affine ):
586+ transform = Affine .from_gdal (* transform )
587+ ground_corners [1 ::- 1 , :] = transform_index_to_physical_point (transform , corners [:, 0 ], corners [:, 1 ])
588+ converted_corners = coordinates_conversion (ground_corners .transpose (), dtm .get_epsg (), self .epsg )
589+ return [np .min (converted_corners [:, 2 ]) - alti_moy , np .max (converted_corners [:, 2 ]) - alti_moy ]
590+
562591 def los_extrema (self , row , col , alt_min = None , alt_max = None , fill_nan = False , epsg = None ):
563592 """
564593 compute los extrema
@@ -603,6 +632,7 @@ def los_extrema(self, row, col, alt_min=None, alt_max=None, fill_nan=False, epsg
603632 col_array = np .array ([col , col ])
604633 alt_array = np .array ([los_alt_max , los_alt_min ])
605634 los_edges = self .direct_loc_h (row_array , col_array , alt_array , fill_nan )
635+
606636 if extrapolate :
607637 diff = los_edges [0 ::2 , :] - los_edges [1 ::2 , :]
608638 delta_alt = diff [:, 2 ]
@@ -612,8 +642,10 @@ def los_extrema(self, row, col, alt_min=None, alt_max=None, fill_nan=False, epsg
612642 coeff_alt_min = np .tile (coeff_alt_min [:, np .newaxis ], (1 , 3 ))
613643 los_edges [0 ::2 , :] = los_edges [1 ::2 , :] + diff * coeff_alt_max
614644 los_edges [1 ::2 , :] = los_edges [1 ::2 , :] + diff * coeff_alt_min
645+
615646 if epsg is not None and epsg != self .epsg :
616647 los_edges = coordinates_conversion (los_edges , self .epsg , epsg )
648+
617649 return los_edges
618650
619651
0 commit comments