@@ -184,7 +184,8 @@ void Grid::get_cubesphere_grid_range(struct cubesphere_range &cr) const {
184
184
// Almost the copy of interp_sphere_linear_helper
185
185
// --------------------------------------------------------------------------
186
186
187
- void Grid::set_interp_coef_sphere (const sphere_range &sr,
187
+ struct interp_coef_t Grid::get_interp_coef_sphere (
188
+ const sphere_range &sr,
188
189
const precision_t lon_in,
189
190
const precision_t lat_in,
190
191
const precision_t alt_in) {
@@ -200,13 +201,15 @@ void Grid::set_interp_coef_sphere(const sphere_range &sr,
200
201
201
202
// Determine whether the point is inside this grid
202
203
// Treat north pole specially because latitude is inclusive for both -cPI/2 and cPI/2
204
+ // Dpn't check for altitude here!
203
205
if (lon_in < sr.lon_min || lon_in >= sr.lon_max || lat_in < sr.lat_min
204
- || lat_in > sr.lat_max || (lat_in == sr.lat_max && sr.lat_max != cPI / 2 )
205
- || alt_in < sr.alt_min || alt_in > sr.alt_max ) {
206
- interp_coefs.push_back (coef);
207
- return ;
206
+ || lat_in > sr.lat_max || (lat_in == sr.lat_max && sr.lat_max != cPI / 2 )) {
207
+ return coef;
208
208
}
209
209
210
+ // This point is in the grid!
211
+ coef.in_grid = true ;
212
+
210
213
// ASSUMPTION: LONGITUDE AND LATITUDE ARE LINEARLY SPACED, nGCs >= 1
211
214
// For the cell containing it, directly calculate its x and y index
212
215
// Find its z index using binary search
@@ -228,21 +231,35 @@ void Grid::set_interp_coef_sphere(const sphere_range &sr,
228
231
// The altitude may not be linearly spaced, so use binary search to find
229
232
// the first element smaller than or equal to the altitude of the give point
230
233
// Implemented in search_altitude
231
- coef.iAlt = search_altitude (alt_in);
232
- coef.rAlt = (alt_in - geoAlt_scgc (0 , 0 , coef.iAlt ))
233
- / (geoAlt_scgc (0 , 0 , coef.iAlt + 1 ) - geoAlt_scgc (0 , 0 , coef.iAlt ));
234
234
235
- // Put the coefficient into the vector
236
- coef.in_grid = true ;
237
- interp_coefs.push_back (coef);
235
+ if (alt_in < sr.alt_min ) {
236
+ coef.iAlt = nGCs;
237
+ coef.rAlt = alt_in - sr.alt_min ;
238
+ coef.below_grid = true ;
239
+ coef.above_grid = false ;
240
+ } else {
241
+ if (alt_in > sr.alt_max ) {
242
+ coef.iAlt = nAlts - nGCs;
243
+ coef.rAlt = alt_in - sr.alt_max ;
244
+ coef.below_grid = false ;
245
+ coef.above_grid = true ;
246
+ } else {
247
+ coef.iAlt = search_altitude (alt_in);
248
+ coef.rAlt = (alt_in - geoAlt_scgc (0 , 0 , coef.iAlt ))
249
+ / (geoAlt_scgc (0 , 0 , coef.iAlt + 1 ) - geoAlt_scgc (0 , 0 , coef.iAlt ));
250
+ coef.below_grid = false ;
251
+ coef.above_grid = false ;
252
+ }
253
+ }
254
+ return coef;
238
255
}
239
256
240
257
// --------------------------------------------------------------------------
241
258
// Set interpolation coefficients helper function for cubesphere grid
242
259
// Almost the copy of interp_cubesphere_linear_helper
243
260
// --------------------------------------------------------------------------
244
261
245
- void Grid::set_interp_coef_cubesphere (const cubesphere_range &cr,
262
+ struct interp_coef_t Grid::get_interp_coef_cubesphere (const cubesphere_range &cr,
246
263
const precision_t lon_in,
247
264
const precision_t lat_in,
248
265
const precision_t alt_in) {
@@ -259,8 +276,7 @@ void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
259
276
260
277
// Determine whether the projection point is on the surface of the grid
261
278
if (surface_in != cr.surface_number ) {
262
- interp_coefs.push_back (coef);
263
- return ;
279
+ return coef;
264
280
}
265
281
266
282
// Calculate the theoretical fractional row index and column index
@@ -280,12 +296,13 @@ void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
280
296
|| row_frac_index > row_index_max || (row_frac_index == row_index_max &&
281
297
cr.row_max_exclusive )
282
298
|| col_frac_index > col_index_max || (col_frac_index == col_index_max &&
283
- cr.col_max_exclusive )
284
- || alt_in < cr.alt_min || alt_in > cr.alt_max ) {
285
- interp_coefs.push_back (coef);
286
- return ;
299
+ cr.col_max_exclusive )) {
300
+ return coef;
287
301
}
288
302
303
+ // This point is in the grid!
304
+ coef.in_grid = true ;
305
+
289
306
// Get the real integer index and the interpolation coefficient
290
307
uint64_t row_index, col_index, alt_index;
291
308
precision_t rRow, rCol, rAlt;
@@ -303,13 +320,27 @@ void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
303
320
coef.rCol = col_frac_index - coef.iCol ;
304
321
coef.iCol += nGCs - 1 ;
305
322
// Use binary search to find the index for altitude
306
- coef.iAlt = search_altitude (alt_in);
307
- coef.rAlt = (alt_in - geoAlt_scgc (0 , 0 , coef.iAlt ))
308
- / (geoAlt_scgc (0 , 0 , coef.iAlt + 1 ) - geoAlt_scgc (0 , 0 , coef.iAlt ));
309
323
310
- // Put the coefficient into the vector
311
- coef.in_grid = true ;
312
- interp_coefs.push_back (coef);
324
+ if (alt_in < cr.alt_min ) {
325
+ coef.iAlt = nGCs;
326
+ coef.rAlt = 0.0 ;
327
+ coef.below_grid = true ;
328
+ coef.above_grid = false ;
329
+ } else {
330
+ if (alt_in > cr.alt_max ) {
331
+ coef.iAlt = nAlts - nGCs;
332
+ coef.rAlt = 0.0 ;
333
+ coef.below_grid = false ;
334
+ coef.above_grid = true ;
335
+ } else {
336
+ coef.iAlt = search_altitude (alt_in);
337
+ coef.rAlt = (alt_in - geoAlt_scgc (0 , 0 , coef.iAlt ))
338
+ / (geoAlt_scgc (0 , 0 , coef.iAlt + 1 ) - geoAlt_scgc (0 , 0 , coef.iAlt ));
339
+ coef.below_grid = false ;
340
+ coef.above_grid = false ;
341
+ }
342
+ }
343
+ return coef;
313
344
}
314
345
315
346
// --------------------------------------------------------------------------
@@ -319,6 +350,8 @@ void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
319
350
bool Grid::set_interpolation_coefs (const std::vector<precision_t > &Lons,
320
351
const std::vector<precision_t > &Lats,
321
352
const std::vector<precision_t > &Alts) {
353
+
354
+ struct interp_coef_t coef;
322
355
// If this is not a geo grid, return false
323
356
if (!IsGeoGrid)
324
357
return false ;
@@ -337,21 +370,84 @@ bool Grid::set_interpolation_coefs(const std::vector<precision_t> &Lons,
337
370
get_cubesphere_grid_range (cr);
338
371
339
372
// Calculate the index and coefficients for each point
340
- for (size_t i = 0 ; i < Lons.size (); ++i)
341
- set_interp_coef_cubesphere (cr, Lons[i], Lats[i], Alts[i]);
373
+ for (size_t i = 0 ; i < Lons.size (); ++i) {
374
+ coef = get_interp_coef_cubesphere (cr, Lons[i], Lats[i], Alts[i]);
375
+ interp_coefs.push_back (coef);
376
+ }
377
+
342
378
} else {
343
379
// Calculate the range of the grid
344
380
struct sphere_range sr;
345
381
get_sphere_grid_range (sr);
346
382
347
383
// Calculate the index and coefficients for each point
348
- for (size_t i = 0 ; i < Lons.size (); ++i)
349
- set_interp_coef_sphere (sr, Lons[i], Lats[i], Alts[i]);
384
+ for (size_t i = 0 ; i < Lons.size (); ++i) {
385
+ coef = get_interp_coef_sphere (sr, Lons[i], Lats[i], Alts[i]);
386
+ interp_coefs.push_back (coef);
387
+ }
350
388
}
351
389
352
390
return true ;
353
391
}
354
392
393
+ // --------------------------------------------------------------------------
394
+ // Set the interpolation coefficients
395
+ // (v2 - return a list of interpolation coefficients)
396
+ // --------------------------------------------------------------------------
397
+
398
+ std::vector<struct interp_coef_t > Grid::get_interpolation_coefs (
399
+ const std::vector<precision_t > &Lons,
400
+ const std::vector<precision_t > &Lats,
401
+ const std::vector<precision_t > &Alts) {
402
+
403
+ int64_t nPts = Lons.size (), iPt;
404
+ std::vector<struct interp_coef_t > listOfCoefs;
405
+ struct interp_coef_t singleCoef;
406
+ bool isBad = false ;
407
+
408
+ // If this is not a geo grid, return false
409
+ if (!IsGeoGrid)
410
+ isBad = true ;
411
+
412
+ // If the size of Lons, Lats and Alts are not the same, return false
413
+ if (Lons.size () != Lats.size () || Lats.size () != Alts.size ())
414
+ isBad = true ;
415
+
416
+ if (isBad) {
417
+ for (iPt = 0 ; iPt < nPts; ++iPt) {
418
+ // Put the coefficient into the vector
419
+ singleCoef.in_grid = false ;
420
+ listOfCoefs.push_back (singleCoef);
421
+ }
422
+ return listOfCoefs;
423
+ }
424
+
425
+ // Handle according to whether it is cubesphere or not
426
+ if (IsCubeSphereGrid) {
427
+ // Calculate the range of the grid
428
+ struct cubesphere_range cr;
429
+ get_cubesphere_grid_range (cr);
430
+
431
+ // Calculate the index and coefficients for each point
432
+ for (iPt = 0 ; iPt < nPts; ++iPt) {
433
+ singleCoef = get_interp_coef_cubesphere (cr, Lons[iPt], Lats[iPt], Alts[iPt]);
434
+ listOfCoefs.push_back (singleCoef);
435
+ }
436
+ } else {
437
+ // Calculate the range of the grid
438
+ struct sphere_range sr;
439
+ get_sphere_grid_range (sr);
440
+
441
+ // Calculate the index and coefficients for each point
442
+ for (iPt = 0 ; iPt < nPts; ++iPt) {
443
+ singleCoef = get_interp_coef_sphere (sr, Lons[iPt], Lats[iPt], Alts[iPt]);
444
+ listOfCoefs.push_back (singleCoef);
445
+ }
446
+ }
447
+
448
+ return listOfCoefs;
449
+ }
450
+
355
451
// --------------------------------------------------------------------------
356
452
// Do the interpolation based on the coefficients stored in interp_coefs
357
453
// --------------------------------------------------------------------------
@@ -381,3 +477,34 @@ std::vector<precision_t> Grid::get_interpolation_values(
381
477
382
478
return ans;
383
479
}
480
+
481
+ // --------------------------------------------------------------------------
482
+ // Do the interpolation based on the coefficients passed in
483
+ // --------------------------------------------------------------------------
484
+
485
+ std::vector<precision_t > Grid::get_interpolation_values (arma_cube data,
486
+ std::vector<struct interp_coef_t > coefArray ) {
487
+ std::vector<precision_t > ans;
488
+
489
+ // If the size of data is not the same as the size of grid, return an empty vector
490
+ if (data.n_rows != nLons || data.n_cols != nLats || data.n_slices != nAlts)
491
+ return ans;
492
+
493
+ for (auto &it : coefArray) {
494
+ // Do interpolation if in_grid = true. Push cNinf otherwise
495
+ if (it.in_grid ) {
496
+ ans.push_back (interpolate_unit_cube (
497
+ data.subcube (it.iRow , it.iCol , it.iAlt , unit_cube_size),
498
+ it.rRow ,
499
+ it.rCol ,
500
+ it.rAlt
501
+ ));
502
+ // Add std::cout if needed here
503
+ // std::cout << "iProc = " << iProc << " interpolates the point successfully\n";
504
+ } else
505
+ ans.push_back (cNinf);
506
+ }
507
+
508
+ return ans;
509
+ }
510
+
0 commit comments