@@ -653,9 +653,9 @@ int i = 0, j = 0, ii, jj;
653
653
int left , right ;
654
654
int top , bottom ;
655
655
int sv_nx = 0 , sv_ny = 0 ;
656
- float * * s_sz = NULL , * * s_sa = NULL ;
657
- float * * s_vz = NULL , * * s_va = NULL ;
658
- int * * k_vz = NULL , * * k_va = NULL ;
656
+ int d = 0 , nd ;
657
+ float * s_sz = NULL , * s_sa = NULL ;
658
+ float * * * s_vz = NULL , * * * s_va = NULL ;
659
659
bool s = false, v = false, z = false, a = false;
660
660
char d_img [NPOW_10 ];
661
661
char id_img [NPOW_10 ];
@@ -677,7 +677,8 @@ int svgrid = 5000;
677
677
meta -> sat = 65535 ;
678
678
679
679
680
- nb = 13 ;
680
+ nb = 13 ; // number of bands
681
+ nd = 12 ; // number of detectors
681
682
DN = allocate_brick (nb , 0 , _DT_NONE_ );
682
683
683
684
set_brick_res (DN , INT_MAX );
@@ -961,20 +962,33 @@ int svgrid = 5000;
961
962
if (svgrid != atoi (tokenptr )){
962
963
printf ("SUN_VIEW_GRID is incompatible with Sentinel-2 metadata. " ); return FAILURE ;}
963
964
964
- sv_nx = ceil (get_brick_width (DN )/(float )svgrid );
965
- sv_ny = ceil (get_brick_height (DN )/(float )svgrid );
966
- if (s_sz == NULL ) alloc_2D ((void * * * )& s_sz , sv_ny , sv_nx , sizeof (float ));
967
- if (s_vz == NULL ) alloc_2D ((void * * * ) & s_vz , sv_ny , sv_nx , sizeof (float ));
968
- if (s_sa == NULL ) alloc_2D ((void * * * ) & s_sa , sv_ny , sv_nx , sizeof (float ));
969
- if (s_va == NULL ) alloc_2D ((void * * * )& s_va , sv_ny , sv_nx , sizeof (float ));
970
- if (k_vz == NULL ) alloc_2D ((void * * * )& k_vz , sv_ny , sv_nx , sizeof (int ));
971
- if (k_va == NULL ) alloc_2D ((void * * * )& k_va , sv_ny , sv_nx , sizeof (int ));
965
+ sv_nx = ceil (get_brick_width (DN )/(float )svgrid ) + 1 ;
966
+ sv_ny = ceil (get_brick_height (DN )/(float )svgrid ) + 1 ;
967
+ if (s_sz == NULL ) alloc ((void * * )& s_sz , sv_ny * sv_nx , sizeof (float ));
968
+ if (s_sa == NULL ) alloc ((void * * ) & s_sa , sv_ny * sv_nx , sizeof (float ));
969
+ if (s_vz == NULL ) alloc_3D ((void * * * * ) & s_vz , nb , nd , sv_ny * sv_nx , sizeof (float ));
970
+ if (s_va == NULL ) alloc_3D ((void * * * * )& s_va , nb , nd , sv_ny * sv_nx , sizeof (float ));
971
+ // if (k_vz == NULL) alloc_2D((void***)&k_vz, sv_ny, sv_nx, sizeof(int));
972
+ // if (k_va == NULL) alloc_2D((void***)&k_va, sv_ny, sv_nx, sizeof(int));
972
973
} else if (strcmp (tag , "Sun_Angles_Grid" ) == 0 ){
973
974
s = true;
974
975
} else if (strcmp (tag , "/Sun_Angles_Grid" ) == 0 ){
975
976
s = false;
976
977
} else if (strcmp (tag , "Viewing_Incidence_Angles_Grids" ) == 0 ){
977
978
v = true;
979
+ b = 0 ;
980
+ d = 0 ;
981
+ while (tokenptr != NULL ){
982
+ if (strcmp (tokenptr , "bandId" ) == 0 ){
983
+ tokenptr = strtok (NULL , separator );
984
+ b = atoi (tokenptr );
985
+ }
986
+ if (strcmp (tokenptr , "detectorId" ) == 0 ){
987
+ tokenptr = strtok (NULL , separator );
988
+ d = atoi (tokenptr ) - 1 ;
989
+ }
990
+ tokenptr = strtok (NULL , separator );
991
+ }
978
992
} else if (strcmp (tag , "/Viewing_Incidence_Angles_Grids" ) == 0 ){
979
993
v = false;
980
994
} else if (strcmp (tag , "Zenith" ) == 0 ){
@@ -993,20 +1007,18 @@ int svgrid = 5000;
993
1007
994
1008
if (s ){
995
1009
if (z ){
996
- if (strcmp (tokenptr , "NaN" ) != 0 ) s_sz [i ][ j ] = atof (tokenptr );
1010
+ if (strcmp (tokenptr , "NaN" ) != 0 ) s_sz [i * sv_ny + j ] = atof (tokenptr );
997
1011
} else if (a ){
998
- if (strcmp (tokenptr , "NaN" ) != 0 ) s_sa [i ][ j ] = atof (tokenptr );
1012
+ if (strcmp (tokenptr , "NaN" ) != 0 ) s_sa [i * sv_ny + j ] = atof (tokenptr );
999
1013
}
1000
1014
} else if (v ){
1001
1015
if (z ){
1002
1016
if (strcmp (tokenptr , "NaN" ) != 0 ){
1003
- s_vz [i ][j ] += atof (tokenptr );
1004
- k_vz [i ][j ]++ ;
1017
+ s_vz [b ][d ][i * sv_ny + j ] += atof (tokenptr );
1005
1018
}
1006
1019
} else if (a ){
1007
1020
if (strcmp (tokenptr , "NaN" ) != 0 ){
1008
- s_va [i ][j ] += atof (tokenptr );
1009
- k_va [i ][j ]++ ;
1021
+ s_va [b ][d ][i * sv_ny + j ] += atof (tokenptr );
1010
1022
}
1011
1023
}
1012
1024
}
@@ -1029,15 +1041,33 @@ int svgrid = 5000;
1029
1041
fclose (fp );
1030
1042
1031
1043
1032
- // get image subset
1044
+ // interpolate the grids
1045
+ // angles are given at grid intersections, we need one value per cell
1046
+ interpolate_sunview_grid (s_sz , sv_nx , sv_ny , meta -> s2 .nodata );
1047
+ interpolate_sunview_grid (s_sa , sv_nx , sv_ny , meta -> s2 .nodata );
1048
+ for (b = 0 ; b < nb ; b ++ ){
1049
+ for (d = 0 ; d < nd ; d ++ ){
1050
+ interpolate_sunview_grid (s_vz [b ][d ], sv_nx , sv_ny , meta -> s2 .nodata );
1051
+ interpolate_sunview_grid (s_va [b ][d ], sv_nx , sv_ny , meta -> s2 .nodata );
1052
+ }
1053
+ }
1054
+ sv_nx -- ;
1055
+ sv_ny -- ;
1056
+
1057
+ // collapse view grids
1058
+ collapse_view_grid (s_vz , nb , nd , sv_nx , sv_ny , meta -> s2 .nodata );
1059
+ collapse_view_grid (s_va , nb , nd , sv_nx , sv_ny , meta -> s2 .nodata );
1033
1060
1061
+
1062
+ // get image subset
1034
1063
left = sv_nx - 1 ; right = 0 ;
1035
1064
top = sv_ny - 1 ; bottom = 0 ;
1036
1065
1037
1066
for (i = 0 ; i < sv_ny ; i ++ ){
1038
1067
for (j = 0 ; j < sv_nx ; j ++ ){
1039
1068
1040
- if (k_vz [i ][j ] > 0 && k_va [i ][j ] > 0 ){
1069
+ if (s_vz [0 ][0 ][i * sv_ny + j ] != meta -> s2 .nodata &&
1070
+ s_va [0 ][0 ][i * sv_ny + j ] != meta -> s2 .nodata ){
1041
1071
if (j < left ) left = j ;
1042
1072
if (j > right ) right = j ;
1043
1073
if (i < top ) top = i ;
@@ -1081,73 +1111,35 @@ int svgrid = 5000;
1081
1111
if (meta -> s2 .vazi == NULL ) alloc_2D ((void * * * )& meta -> s2 .vazi , meta -> s2 .ny , meta -> s2 .nx , sizeof (float ));
1082
1112
1083
1113
1084
- // average of view angles
1114
+ // copy values to final view sun grids
1085
1115
for (i = 0 ; i < meta -> s2 .ny ; i ++ ){
1086
1116
for (j = 0 ; j < meta -> s2 .nx ; j ++ ){
1087
1117
1088
1118
ii = i + top ;
1089
1119
jj = j + left ;
1090
1120
1091
- if (k_vz [ii ][jj ] > 0 ){
1092
- meta -> s2 .vzen [i ][j ] = s_vz [ii ][jj ]/k_vz [ii ][jj ];
1093
- meta -> s2 .szen [i ][j ] = s_sz [ii ][jj ];
1094
- } else {
1095
- meta -> s2 .vzen [i ][j ] = meta -> s2 .nodata ;
1096
- meta -> s2 .szen [i ][j ] = meta -> s2 .nodata ;
1097
- }
1098
- if (k_va [ii ][jj ] > 0 ){
1099
- meta -> s2 .vazi [i ][j ] = s_va [ii ][jj ]/k_va [ii ][jj ];
1100
- meta -> s2 .sazi [i ][j ] = s_sa [ii ][jj ];
1101
- } else {
1102
- meta -> s2 .vazi [i ][j ] = meta -> s2 .nodata ;
1103
- meta -> s2 .sazi [i ][j ] = meta -> s2 .nodata ;
1104
- }
1105
-
1106
- }
1107
- }
1108
-
1121
+ meta -> s2 .szen [i ][j ] = s_sz [ii * sv_ny + jj ];
1122
+ meta -> s2 .sazi [i ][j ] = s_sa [ii * sv_ny + jj ];
1123
+ meta -> s2 .vzen [i ][j ] = s_vz [0 ][0 ][ii * sv_ny + jj ];
1124
+ meta -> s2 .vazi [i ][j ] = s_va [0 ][0 ][ii * sv_ny + jj ];
1109
1125
1110
- // try to fill the left edge (duplicate values - silly method, but it will do for now)
1111
-
1112
- // average of view angles
1113
- for (i = 0 ; i < meta -> s2 .ny ; i ++ ){
1114
- for (j = 0 ; j < meta -> s2 .nx ; j ++ ){
1115
-
1116
- if ((jj = j + 1 ) == meta -> s2 .nx ) continue ;
1117
-
1118
- if (meta -> s2 .vzen [i ][j ] == meta -> s2 .nodata &&
1119
- meta -> s2 .vzen [i ][jj ] != meta -> s2 .nodata ){
1120
-
1121
- meta -> s2 .vzen [i ][j ] = meta -> s2 .vzen [i ][jj ];
1122
- meta -> s2 .szen [i ][j ] = meta -> s2 .szen [i ][jj ];
1123
- meta -> s2 .vazi [i ][j ] = meta -> s2 .vazi [i ][jj ];
1124
- meta -> s2 .sazi [i ][j ] = meta -> s2 .sazi [i ][jj ];
1125
-
1126
- }
1127
1126
1128
1127
}
1129
1128
}
1130
1129
1131
1130
1132
-
1133
-
1134
- //right++;
1135
- //bottom++;
1136
-
1137
1131
meta -> s2 .left = left * svgrid /get_brick_res (DN );
1138
1132
meta -> s2 .top = top * svgrid /get_brick_res (DN );
1139
1133
meta -> s2 .right = right * svgrid /get_brick_res (DN );
1140
1134
meta -> s2 .bottom = bottom * svgrid /get_brick_res (DN );
1141
1135
1142
- if (meta -> s2 .right > get_brick_ncols (DN )) meta -> s2 .right = get_brick_ncols (DN );
1136
+ if (meta -> s2 .right > get_brick_ncols (DN )) meta -> s2 .right = get_brick_ncols (DN );
1143
1137
if (meta -> s2 .bottom > get_brick_nrows (DN )) meta -> s2 .bottom = get_brick_nrows (DN );
1144
1138
1145
- free_2D ((void * * )s_sz , sv_ny );
1146
- free_2D ((void * * )s_sa , sv_ny );
1147
- free_2D ((void * * )s_vz , sv_ny );
1148
- free_2D ((void * * )s_va , sv_ny );
1149
- free_2D ((void * * )k_vz , sv_ny );
1150
- free_2D ((void * * )k_va , sv_ny );
1139
+ free ((void * )s_sz );
1140
+ free ((void * )s_sa );
1141
+ free_3D ((void * * * )s_vz , nb , nd );
1142
+ free_3D ((void * * * )s_va , nb , nd );
1151
1143
1152
1144
#ifdef FORCE_DEBUG
1153
1145
printf ("active image subset: UL %d/%d to LR %d/%d\n" , meta -> s2 .left , meta -> s2 .top , meta -> s2 .right , meta -> s2 .bottom );
@@ -1333,6 +1325,111 @@ int nchar;
1333
1325
}
1334
1326
1335
1327
1328
+ /** This function interpolates the sun and view angle grids given in the
1329
+ +++ Sentinel-2 metadata. The interpolation grid will be interpolated to
1330
+ +++ a cell-based grid, and then clipped to the image extent.
1331
+ +++ int_grid: interpolation grid (modified)
1332
+ --- nx: number of columns
1333
+ --- ny: number of rows
1334
+ --- nodata: nodata value
1335
+ +++ Return: void
1336
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**/
1337
+ void interpolate_sunview_grid (float * int_grid , int int_nx , int int_ny , float nodata ){
1338
+ int i , j , ii , jj ;
1339
+ int cell_nx , cell_ny ;
1340
+ int cell_p , int_p ;
1341
+ float * cell_grid = NULL ;
1342
+ float sum , num ;
1343
+
1344
+
1345
+ cell_nx = int_nx - 1 ;
1346
+ cell_ny = int_ny - 1 ;
1347
+
1348
+ alloc ((void * * )& cell_grid , cell_ny * cell_nx , sizeof (float ));
1349
+
1350
+
1351
+ for (i = 0 , cell_p = 0 ; i < cell_ny ; i ++ ){
1352
+ for (j = 0 ; j < cell_nx ; j ++ , cell_p ++ ){
1353
+
1354
+ sum = num = 0 ;
1355
+
1356
+ for (ii = 0 ; ii <=1 ; ii ++ ){
1357
+ for (jj = 0 ; jj <=1 ; jj ++ ){
1358
+
1359
+ int_p = (i + ii ) * int_ny + (j + jj );
1360
+
1361
+ if (int_grid [int_p ] > 0 ){
1362
+ sum += int_grid [int_p ];
1363
+ num ++ ;
1364
+ }
1365
+ }
1366
+ }
1367
+
1368
+ if (num > 0 ){
1369
+ cell_grid [cell_p ] = sum /num ;
1370
+ } else {
1371
+ cell_grid [cell_p ] = nodata ;
1372
+ }
1373
+
1374
+ }
1375
+ }
1376
+
1377
+ memmove (int_grid , cell_grid , cell_nx * cell_ny * sizeof (float ));
1378
+ re_alloc ((void * * )& int_grid , int_nx * int_ny , cell_nx * cell_ny , sizeof (float ));
1379
+ free ((void * )cell_grid );
1380
+
1381
+ return ;
1382
+ }
1383
+
1384
+
1385
+ /** This function collapses the Sentinel-2 view angle grids to a single
1386
+ +++ grid. All band- and detector-based grids will be averaged. There is
1387
+ +++ room for improvement at this point. The collapsed grid will be put
1388
+ +++ into the first slot.
1389
+ +++ grid: 3D grid (modified)
1390
+ --- nb: number of bands
1391
+ --- nd: number of detectors
1392
+ --- nx: number of columns
1393
+ --- ny: number of rows
1394
+ --- nodata: nodata value
1395
+ +++ Return: void
1396
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**/
1397
+ void collapse_view_grid (float * * * grid , int nb , int nd , int nx , int ny , float nodata ){
1398
+ int b , d , i , j , p ;
1399
+ float sum , num ;
1400
+
1401
+
1402
+ for (i = 0 , p = 0 ; i < ny ; i ++ ){
1403
+ for (j = 0 ; j < nx ; j ++ , p ++ ){
1404
+
1405
+ sum = num = 0 ;
1406
+
1407
+ for (b = 0 ; b < nb ; b ++ ){
1408
+ for (d = 0 ; d < nd ; d ++ ){
1409
+
1410
+ if (grid [b ][d ][p ] != nodata ){
1411
+ sum += grid [b ][d ][p ];
1412
+ num ++ ;
1413
+ }
1414
+
1415
+ }
1416
+ }
1417
+
1418
+ if (num > 0 ){
1419
+ grid [0 ][0 ][p ] = sum /num ;
1420
+ } else {
1421
+ grid [0 ][0 ][p ] = nodata ;
1422
+ }
1423
+
1424
+ }
1425
+ }
1426
+
1427
+
1428
+ return ;
1429
+ }
1430
+
1431
+
1432
+
1336
1433
/** This function identifies the satellite mission, i.e. Landsat or Senti-
1337
1434
+++ nel-2
1338
1435
--- pl2: L2 parameters
0 commit comments