@@ -22,6 +22,16 @@ type Stats = {
2222 std_dev ?: number ;
2323} ;
2424
25+ type GdalUnitInfo = {
26+ units ?: string ;
27+ value ?: number ;
28+ } ;
29+
30+ type SpatialReferenceWithUnits = SpatialReference & {
31+ getAngularUnits ?: ( ) => GdalUnitInfo ;
32+ getLinearUnits ?: ( ) => GdalUnitInfo ;
33+ } ;
34+
2535export async function loadDsmProject (
2636 paths : string [ ] ,
2737) : Promise < DsmProjectSummary > {
@@ -76,6 +86,9 @@ export async function loadDsmProject(
7686 projection ,
7787 ) ;
7888 const firstNoData = openedFiles [ 0 ] ! . nodata ;
89+ const distanceUnit = distanceUnitForSrs ( firstSrs ) ;
90+ const elevationUnit = firstFile . band . unitType || "unknown" ;
91+ const elevationMetersPerUnit = metersPerElevationUnit ( elevationUnit ) ;
7992
8093 const summary : DsmProjectSummary = {
8194 id : projectId ,
@@ -91,10 +104,12 @@ export async function loadDsmProject(
91104 ) ,
92105 crsWkt : firstSrs ?. toWKT ( ) ?? "" ,
93106 epsg,
107+ distance : distanceUnit ,
94108 extent : projectExtent ,
95109 pixelSize : firstFile . pixelSize ,
96110 elevation : {
97- unit : firstFile . band . unitType || "unknown" ,
111+ unit : elevationUnit ,
112+ metersPerUnit : elevationMetersPerUnit ,
98113 min : projectMin ,
99114 max : projectMax ,
100115 ...( firstNoData === undefined ? { } : { nodata : firstNoData } ) ,
@@ -208,6 +223,8 @@ function warningsForProject(
208223 sourceSrs : SpatialReference | null ,
209224) : string [ ] {
210225 const warnings : string [ ] = [ ] ;
226+ const horizontalUnit = distanceUnitForSrs ( sourceSrs ) ;
227+ const elevationUnit = files [ 0 ] ?. band . unitType || "unknown" ;
211228
212229 if ( ! sourceSrs ) {
213230 warnings . push (
@@ -219,6 +236,18 @@ function warningsForProject(
219236 ) ;
220237 }
221238
239+ if ( horizontalUnit . metersPerUnit === null ) {
240+ warnings . push (
241+ "Fresnel zones are hidden because the DSM horizontal unit cannot be converted to metres." ,
242+ ) ;
243+ }
244+
245+ if ( metersPerElevationUnit ( elevationUnit ) === null ) {
246+ warnings . push (
247+ "Fresnel zones are hidden because the DSM elevation unit cannot be converted to metres." ,
248+ ) ;
249+ }
250+
222251 for ( let i = 0 ; i < files . length ; i ++ ) {
223252 for ( let j = i + 1 ; j < files . length ; j ++ ) {
224253 if ( extentsOverlap ( files [ i ] ! . extent , files [ j ] ! . extent ) ) {
@@ -239,6 +268,57 @@ function warningsForProject(
239268 return warnings ;
240269}
241270
271+ function distanceUnitForSrs ( sourceSrs : SpatialReference | null ) : {
272+ unit : string ;
273+ metersPerUnit : number | null ;
274+ } {
275+ if ( ! sourceSrs ) return { unit : "unknown" , metersPerUnit : null } ;
276+
277+ const srsWithUnits = sourceSrs as SpatialReferenceWithUnits ;
278+ const unitInfo = sourceSrs . isGeographic ( )
279+ ? srsWithUnits . getAngularUnits ?.( )
280+ : srsWithUnits . getLinearUnits ?.( ) ;
281+ const unit = unitInfo ?. units || "unknown" ;
282+ const metersPerUnit = sourceSrs . isGeographic ( )
283+ ? null
284+ : finitePositiveOrNull ( unitInfo ?. value ) ;
285+
286+ return { unit, metersPerUnit } ;
287+ }
288+
289+ function metersPerElevationUnit ( unit : string ) : number | null {
290+ const normalized = unit . trim ( ) . toLowerCase ( ) ;
291+ if ( normalized === "" || normalized === "unknown" ) return null ;
292+
293+ if ( [ "m" , "meter" , "meters" , "metre" , "metres" ] . includes ( normalized ) ) {
294+ return 1 ;
295+ }
296+
297+ if (
298+ [
299+ "ft" ,
300+ "foot" ,
301+ "feet" ,
302+ "international foot" ,
303+ "international feet" ,
304+ "us survey foot" ,
305+ "us survey feet" ,
306+ "survey foot" ,
307+ "survey feet" ,
308+ ] . includes ( normalized )
309+ ) {
310+ return 0.3048 ;
311+ }
312+
313+ return null ;
314+ }
315+
316+ function finitePositiveOrNull ( value : number | undefined ) : number | null {
317+ return typeof value === "number" && Number . isFinite ( value ) && value > 0
318+ ? value
319+ : null ;
320+ }
321+
242322function rasterStats ( band : RasterBand ) : Stats {
243323 try {
244324 const stats = band . computeStatistics ( true ) as Stats ;
0 commit comments