00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <stddef.h>
00037 #include <math.h>
00038 #include <assert.h>
00039
00040 #include "visir_spc_optmod.h"
00041
00042
00057
00058
00059
00060
00061
00062
00063 enum visir_spc_mode_ {
00064 VISIR_SPC_M_ERR = 0,
00065 VISIR_SPC_M_LSWN,
00066 VISIR_SPC_M_LLWN,
00067 VISIR_SPC_M_LSWQ,
00068 VISIR_SPC_M_LLWQ,
00069 VISIR_SPC_M_MSWN,
00070 VISIR_SPC_M_MLWN,
00071 VISIR_SPC_M_MSWQ,
00072 VISIR_SPC_M_MLWQ,
00073 VISIR_SPC_M_GHR01,
00074 VISIR_SPC_M_GHR02,
00075 VISIR_SPC_M_GHR03,
00076 VISIR_SPC_M_GHR04,
00077 VISIR_SPC_M_GHR05,
00078 VISIR_SPC_M_GHR06,
00079 VISIR_SPC_M_GHR07,
00080 VISIR_SPC_M_GHR08,
00081 VISIR_SPC_M_GHR09,
00082 VISIR_SPC_M_GHR10,
00083 VISIR_SPC_M_GHR11,
00084 VISIR_SPC_M_GHR12,
00085 VISIR_SPC_M_GHR13,
00086 VISIR_SPC_M_GHR14,
00087 VISIR_SPC_M_GHR15,
00088 VISIR_SPC_M_GHR16,
00089 VISIR_SPC_M_GHR17,
00090 VISIR_SPC_M_GHR18,
00091 VISIR_SPC_M_GHR19,
00092 VISIR_SPC_M_GHR20,
00093 VISIR_SPC_M_GHR21,
00094 VISIR_SPC_M_GHR22,
00095 VISIR_SPC_M_GHR23,
00096 VISIR_SPC_M_GHR24,
00097 VISIR_SPC_M_GHR25,
00098 VISIR_SPC_M_GHR26,
00099 VISIR_SPC_M_GHR27,
00100 VISIR_SPC_M_HR01,
00101 VISIR_SPC_M_HR02,
00102 VISIR_SPC_M_HR03,
00103 VISIR_SPC_M_HR04,
00104 VISIR_SPC_M_HR05,
00105 VISIR_SPC_M_HR06,
00106 VISIR_SPC_M_HR07,
00107 VISIR_SPC_M_HR08,
00108 VISIR_SPC_M_HR09,
00109 VISIR_SPC_M_HR10
00110 };
00111
00112 typedef enum visir_spc_mode_ visir_spc_mode;
00113
00114 struct visir_optmod_private_ {
00115
00116 double wlen;
00117
00118
00119 double angle_a;
00120 double angle_b0;
00121 double angle_bm;
00122 double angle_b1;
00123
00124 double angle_scan;
00125 double sinus_sum;
00126
00127
00128 double d;
00129
00130
00131
00132 double gg;
00133 double w;
00134 double offset;
00135 double factor;
00136
00137 double dcolbeam;
00138 double ld;
00139
00140
00141 visir_spc_resol resolution;
00142
00143
00144 visir_spc_mode mode;
00145
00146 int m;
00147
00148
00149
00150 int side_is_A;
00151
00152 };
00153
00154 typedef struct visir_optmod_private_ visir_optmod_private;
00155
00156
00157
00158
00159
00160 static double visir_spc_optmod_krs5(double);
00161 static void visir_spc_optmod_scan_angle(visir_optmod_private *);
00162
00165
00166
00167
00168
00169
00182
00183 int visir_spc_optmod_init(visir_spc_resol resol, double wlen,
00184 visir_optmod * pins)
00185 {
00186
00187 visir_optmod_private * self = (visir_optmod_private*)pins;
00188
00189
00190 const double rad_per_deg = atan(1)/45;
00191
00192 visir_spc_mode mode = VISIR_SPC_M_ERR;
00193
00194
00195
00196 assert( sizeof(visir_optmod_private) == sizeof(visir_optmod) );
00197
00198 if (self == NULL) return -1;
00199
00200
00201
00202 wlen *= 1e6;
00203 switch (resol) {
00204 case VISIR_SPC_R_LR:
00205 {
00206 if ( 7.5 <= wlen && wlen <= 10.2) mode = VISIR_SPC_M_LSWN;
00207 else if (10.2 < wlen && wlen <= 14.5) mode = VISIR_SPC_M_LLWN;
00208 else if (15.0 <= wlen && wlen <= 20.4) mode = VISIR_SPC_M_LSWQ;
00209 else if (20.4 < wlen && wlen <= 28.0) mode = VISIR_SPC_M_LLWQ;
00210 break;
00211 }
00212
00213 case VISIR_SPC_R_MR:
00214 {
00215 if ( 7.5 <= wlen && wlen <= 10.2) mode = VISIR_SPC_M_MSWN;
00216 else if (10.2 < wlen && wlen <= 14.0) mode = VISIR_SPC_M_MLWN;
00217 else if (15.0 <= wlen && wlen <= 20.4) mode = VISIR_SPC_M_MSWQ;
00218 else if (20.4 < wlen && wlen <= 28.0) mode = VISIR_SPC_M_MLWQ;
00219 break;
00220 }
00221
00222 case VISIR_SPC_R_GHR:
00223 {
00224 if ( 7.6 <= wlen && wlen <= 7.8 ) mode = VISIR_SPC_M_GHR01;
00225 else if ( 7.8 < wlen && wlen <= 8.03) mode = VISIR_SPC_M_GHR02;
00226 else if ( 8.03 < wlen && wlen <= 8.26) mode = VISIR_SPC_M_GHR03;
00227 else if ( 8.26 < wlen && wlen <= 8.52) mode = VISIR_SPC_M_GHR04;
00228 else if ( 8.52 < wlen && wlen <= 8.78) mode = VISIR_SPC_M_GHR05;
00229 else if ( 8.78 < wlen && wlen <= 9.07) mode = VISIR_SPC_M_GHR06;
00230 else if ( 9.07 < wlen && wlen <= 9.36) mode = VISIR_SPC_M_GHR07;
00231 else if ( 9.36 < wlen && wlen <= 9.69) mode = VISIR_SPC_M_GHR08;
00232 else if ( 9.69 < wlen && wlen <= 10.03) mode = VISIR_SPC_M_GHR09;
00233 else if (10.03 < wlen && wlen <= 10.20) mode = VISIR_SPC_M_GHR10;
00234 else if (10.2 < wlen && wlen <= 10.41) mode = VISIR_SPC_M_GHR11;
00235 else if (10.41 < wlen && wlen <= 10.80) mode = VISIR_SPC_M_GHR12;
00236 else if (10.80 < wlen && wlen <= 11.24) mode = VISIR_SPC_M_GHR13;
00237 else if (11.24 < wlen && wlen <= 11.70) mode = VISIR_SPC_M_GHR14;
00238 else if (11.70 < wlen && wlen <= 12.21) mode = VISIR_SPC_M_GHR15;
00239 else if (12.21 < wlen && wlen <= 12.76) mode = VISIR_SPC_M_GHR16;
00240 else if (12.76 < wlen && wlen <= 13.37) mode = VISIR_SPC_M_GHR17;
00241 else if (13.37 < wlen && wlen <= 14.04) mode = VISIR_SPC_M_GHR18;
00242 else if (14.04 < wlen && wlen <= 14.77) mode = VISIR_SPC_M_GHR19;
00243 else if (15.60 < wlen && wlen <= 16.49) mode = VISIR_SPC_M_GHR20;
00244 else if (16.49 < wlen && wlen <= 17.55) mode = VISIR_SPC_M_GHR21;
00245 else if (17.55 < wlen && wlen <= 18.67) mode = VISIR_SPC_M_GHR22;
00246 else if (18.67 < wlen && wlen <= 20.06) mode = VISIR_SPC_M_GHR23;
00247 else if (20.06 < wlen && wlen <= 21.49) mode = VISIR_SPC_M_GHR24;
00248 else if (21.49 < wlen && wlen <= 23.40) mode = VISIR_SPC_M_GHR25;
00249 else if (23.40 < wlen && wlen <= 25.32) mode = VISIR_SPC_M_GHR26;
00250 else if (25.32 < wlen && wlen <= 28.08) mode = VISIR_SPC_M_GHR27;
00251 break;
00252 }
00253 case VISIR_SPC_R_HR:
00254 {
00255 if ( 7.97 <= wlen && wlen <= 8.27) mode = VISIR_SPC_M_HR01;
00256 else if ( 8.83 <= wlen && wlen <= 9.05) mode = VISIR_SPC_M_HR02;
00257 else if ( 9.52 <= wlen && wlen <= 9.72) mode = VISIR_SPC_M_HR03;
00258
00259 else if (11.85 <= wlen && wlen < 12.19) mode = VISIR_SPC_M_HR04;
00260 else if (12.19 <= wlen && wlen <= 12.37) mode = VISIR_SPC_M_HR05;
00261 else if (12.37 < wlen && wlen <= 12.71) mode = VISIR_SPC_M_HR06;
00262 else if (12.71 < wlen && wlen <= 12.91) mode = VISIR_SPC_M_HR07;
00263 else if (16.80 <= wlen && wlen <= 17.20) mode = VISIR_SPC_M_HR08;
00264 else if (18.32 <= wlen && wlen <= 18.67) mode = VISIR_SPC_M_HR09;
00265 else if (18.67 < wlen && wlen <= 19.18) mode = VISIR_SPC_M_HR10;
00266 break;
00267 }
00268 default:;
00269 }
00270 wlen *= 1e-6;
00271
00272 if (mode == VISIR_SPC_M_ERR) return -2;
00273
00274 self->resolution = resol;
00275 self->mode = mode;
00276 self->wlen = wlen;
00277 self->m = 0;
00278
00279 self->angle_a = 0;
00280 self->angle_b0 = 0;
00281 self->angle_bm = 0;
00282 self->angle_b1 = 0;
00283
00284
00285 switch (resol) {
00286 case VISIR_SPC_R_LR:
00287 {
00288 self->angle_a = 6.708;
00289 self->angle_bm = 1.291;
00290 self->angle_b0 = 0.586;
00291 self->angle_b1 = 2.0;
00292 self->dcolbeam = 53000;
00293 self->ld = 10332;
00294
00295
00296 switch (mode) {
00297 case VISIR_SPC_M_LSWN:
00298 {
00299 self->d = 129.162;
00300 self->m = 2;
00301 break;
00302 }
00303 case VISIR_SPC_M_LLWN:
00304 {
00305 self->d = 172.308;
00306 self->m = 2;
00307 break;
00308 }
00309 case VISIR_SPC_M_LSWQ:
00310 {
00311 self->d = 129.162;
00312 self->m = 1;
00313 break;
00314 }
00315 case VISIR_SPC_M_LLWQ:
00316 {
00317 self->d = 172.308;
00318 self->m = 1;
00319 break;
00320 }
00321 default:;
00322 }
00323 break;
00324 }
00325 case VISIR_SPC_R_MR:
00326 {
00327 self->angle_a = 34.208;
00328 self->angle_bm = 28.791;
00329 self->angle_b0 = 28.086;
00330 self->angle_b1 = 29.500;
00331 self->dcolbeam = 53000;
00332 self->ld = 10332;
00333
00334
00335 switch (mode) {
00336 case VISIR_SPC_M_MSWN:
00337 {
00338 self->d = 17.1478;
00339 self->m = 2;
00340 break;
00341 }
00342 case VISIR_SPC_M_MLWN:
00343 {
00344 self->d = 22.9560;
00345 self->m = 2;
00346 break;
00347 }
00348 case VISIR_SPC_M_MSWQ:
00349 {
00350 self->d = 17.1478;
00351 self->m = 1;
00352 break;
00353 }
00354 case VISIR_SPC_M_MLWQ:
00355 {
00356 self->d = 22.9560;
00357 self->m = 1;
00358 break;
00359 }
00360 default:;
00361 }
00362 break;
00363 }
00364 case VISIR_SPC_R_GHR:
00365 {
00366
00367 self->side_is_A = 0;
00368 self->dcolbeam = 125000;
00369 self->ld = 23403;
00370
00371 switch (mode) {
00372 case VISIR_SPC_M_GHR01:
00373 {
00374 self->d=77.16526;
00375 self->m=18;
00376 self->gg=36.8906;
00377 self->w=9.8;
00378 self->offset=166.9;
00379 self->factor=2940;
00380 break;
00381 }
00382
00383 case VISIR_SPC_M_GHR02:
00384 {
00385 self->side_is_A = 1;
00386 self->d=79.93104;
00387 self->m=18;
00388 self->gg=36.8906;
00389 self->w=9.8;
00390 self->offset=178;
00391 self->factor=2940;
00392 break;
00393 }
00394
00395 case VISIR_SPC_M_GHR03:
00396 {
00397 self->d=77.16526;
00398 self->m=17;
00399 self->gg=36.8906;
00400 self->w=9.8;
00401 self->offset=166.9;
00402 self->factor=2940;
00403 break;
00404 }
00405
00406 case VISIR_SPC_M_GHR04:
00407 {
00408 self->side_is_A = 1;
00409 self->d=79.93104;
00410 self->m=17;
00411 self->gg=36.8906;
00412 self->w=9.8;
00413 self->offset=178;
00414 self->factor=2940;
00415 break;
00416 }
00417
00418 case VISIR_SPC_M_GHR05:
00419 {
00420 self->d=77.16526;
00421 self->m=16;
00422 self->gg=36.8906;
00423 self->w=9.8;
00424 self->offset=166.9;
00425 self->factor=2940;
00426 break;
00427 }
00428
00429 case VISIR_SPC_M_GHR06:
00430 {
00431 self->side_is_A = 1;
00432 self->d=79.93104;
00433 self->m=16;
00434 self->gg=36.8906;
00435 self->w=9.8;
00436 self->offset=178;
00437 self->factor=2940;
00438 break;
00439 }
00440
00441 case VISIR_SPC_M_GHR07:
00442 {
00443 self->d=77.16526;
00444 self->m=15;
00445 self->gg=36.8906;
00446 self->w=9.8;
00447 self->offset=166.9;
00448 self->factor=2940;
00449 break;
00450 }
00451
00452 case VISIR_SPC_M_GHR08:
00453 {
00454 self->side_is_A = 1;
00455 self->d=79.93104;
00456 self->m=15;
00457 self->gg=36.8906;
00458 self->w=9.8;
00459 self->offset=178;
00460 self->factor=2940;
00461 break;
00462 }
00463
00464 case VISIR_SPC_M_GHR09:
00465 {
00466 self->d=77.16526;
00467 self->m=14;
00468 self->gg=36.8906;
00469 self->w=9.8;
00470 self->offset=166.9;
00471 self->factor=2940;
00472 break;
00473 }
00474
00475 case VISIR_SPC_M_GHR10:
00476 {
00477 self->side_is_A = 1;
00478 self->d=79.93104;
00479 self->m=14;
00480 self->gg=36.8906;
00481 self->w=9.8;
00482 self->offset=178;
00483 self->factor=2940;
00484 break;
00485 }
00486
00487 case VISIR_SPC_M_GHR11:
00488 {
00489 self->side_is_A = 1;
00490 self->d=79.93104;
00491 self->m=14;
00492 self->gg=63.5470;
00493 self->w=7.6;
00494 self->offset=143.1;
00495 self->factor=3004;
00496 break;
00497 }
00498
00499 case VISIR_SPC_M_GHR12:
00500 {
00501 self->d=77.16526;
00502 self->m=13;
00503 self->gg=63.5470;
00504 self->w=7.6;
00505 self->offset=131.6;
00506 self->factor=3004;
00507 break;
00508 }
00509
00510 case VISIR_SPC_M_GHR13:
00511 {
00512 self->side_is_A = 1;
00513 self->d=79.93104;
00514 self->m=13;
00515 self->gg=63.5470;
00516 self->w=7.6;
00517 self->offset=143.1;
00518 self->factor=3004;
00519 break;
00520 }
00521
00522 case VISIR_SPC_M_GHR14:
00523 {
00524 self->d=77.16526;
00525 self->m=12;
00526 self->gg=63.5470;
00527 self->w=7.6;
00528 self->offset=131.6;
00529 self->factor=3004;
00530 break;
00531 }
00532
00533 case VISIR_SPC_M_GHR15:
00534 {
00535 self->side_is_A = 1;
00536 self->d=79.93104;
00537 self->m=12;
00538 self->gg=63.5470;
00539 self->w=7.6;
00540 self->offset=143.1;
00541 self->factor=3004;
00542 break;
00543 }
00544
00545 case VISIR_SPC_M_GHR16:
00546 {
00547 self->d=77.16526;
00548 self->m=11;
00549 self->gg=63.5470;
00550 self->w=7.6;
00551 self->offset=131.6;
00552 self->factor=3004;
00553 break;
00554 }
00555
00556 case VISIR_SPC_M_GHR17:
00557 {
00558 self->side_is_A = 1;
00559 self->d=79.93104;
00560 self->m=11;
00561 self->gg=63.5470;
00562 self->w=7.6;
00563 self->offset=143.1;
00564 self->factor=3004;
00565 break;
00566 }
00567
00568 case VISIR_SPC_M_GHR18:
00569 {
00570 self->d=77.16526;
00571 self->m=10;
00572 self->gg=63.5470;
00573 self->w=7.6;
00574 self->offset=131.6;
00575 self->factor=3004;
00576 break;
00577 }
00578
00579 case VISIR_SPC_M_GHR19:
00580 {
00581 self->side_is_A = 1;
00582 self->d=79.93104;
00583 self->m=10;
00584 self->gg=63.5470;
00585 self->w=7.6;
00586 self->offset=143.1;
00587 self->factor=3004;
00588 break;
00589 }
00590
00591 case VISIR_SPC_M_GHR20:
00592 {
00593 self->side_is_A = 1;
00594 self->d=79.93104;
00595 self->m=9;
00596 self->gg=217.8772;
00597 self->w=4.1;
00598 self->offset=120.3;
00599 self->factor=2980;
00600 break;
00601 }
00602
00603 case VISIR_SPC_M_GHR21:
00604 {
00605 self->d=77.16526;
00606 self->m=8;
00607 self->gg=217.8772;
00608 self->w=4.1;
00609 self->offset=108.7;
00610 self->factor=2980;
00611 break;
00612 }
00613
00614 case VISIR_SPC_M_GHR22:
00615 {
00616 self->side_is_A = 1;
00617 self->d=79.93104;
00618 self->m=8;
00619 self->gg=217.8772;
00620 self->w=4.1;
00621 self->offset=120.3;
00622 self->factor=2980;
00623 break;
00624 }
00625
00626 case VISIR_SPC_M_GHR23:
00627 {
00628 self->d=77.16526;
00629 self->m=7;
00630 self->gg=217.8772;
00631 self->w=4.1;
00632 self->offset=108.7;
00633 self->factor=2980;
00634 break;
00635 }
00636
00637 case VISIR_SPC_M_GHR24:
00638 {
00639 self->side_is_A = 1;
00640 self->d=79.93104;
00641 self->m=7;
00642 self->gg=217.8772;
00643 self->w=4.1;
00644 self->offset=120.3;
00645 self->factor=2980;
00646 break;
00647 }
00648
00649 case VISIR_SPC_M_GHR25:
00650 {
00651 self->d=77.16526;
00652 self->m=6;
00653 self->gg=217.8772;
00654 self->w=4.1;
00655 self->offset=108.7;
00656 self->factor=2980;
00657 break;
00658 }
00659
00660 case VISIR_SPC_M_GHR26:
00661 {
00662 self->side_is_A = 1;
00663 self->d=79.93104;
00664 self->m=6;
00665 self->gg=217.8772;
00666 self->w=4.1;
00667 self->offset=120.3;
00668 self->factor=2980;
00669 break;
00670 }
00671
00672 case VISIR_SPC_M_GHR27:
00673 {
00674 self->d=77.16526;
00675 self->m=5;
00676 self->gg=217.8772;
00677 self->w=4.1;
00678 self->offset=108.7;
00679 self->factor=2980;
00680 break;
00681 }
00682 default:;
00683 }
00684
00685 if (self->side_is_A) {
00686
00687 self->angle_a = 62.1299;
00688 self->angle_bm = 64.8519;
00689 self->angle_b0 = 64.5393;
00690 self->angle_b1 = 65.1641;
00691 } else {
00692
00693 self->angle_a = 64.8701;
00694 self->angle_bm = 62.1483;
00695 self->angle_b0 = 62.4609;
00696 self->angle_b1 = 61.8361;
00697 }
00698 self->w *= rad_per_deg;
00699
00700
00701 self->gg *= 1e-6;
00702 break;
00703 }
00704 case VISIR_SPC_R_HR:
00705 {
00706
00707 self->side_is_A = 0;
00708 self->dcolbeam = 125000;
00709 self->ld = 23403;
00710
00711 switch (mode) {
00712 case VISIR_SPC_M_HR01:
00713 {
00714 self->m=17;
00715 break;
00716 }
00717 case VISIR_SPC_M_HR02:
00718 {
00719 self->side_is_A = 1;
00720 self->m=16;
00721 break;
00722 }
00723 case VISIR_SPC_M_HR03:
00724 {
00725 self->side_is_A = 1;
00726 self->m=15;
00727 break;
00728 }
00729 case VISIR_SPC_M_HR04:
00730 {
00731 self->side_is_A = 1;
00732 self->m=12;
00733 break;
00734 }
00735 case VISIR_SPC_M_HR05:
00736 {
00737 self->m=11;
00738 break;
00739 }
00740 case VISIR_SPC_M_HR06:
00741 {
00742 self->m=11;
00743 break;
00744 }
00745 case VISIR_SPC_M_HR07:
00746 {
00747 self->side_is_A = 1;
00748 self->m=11;
00749 break;
00750 }
00751 case VISIR_SPC_M_HR08:
00752 {
00753 self->m=8;
00754 break;
00755 }
00756 case VISIR_SPC_M_HR09:
00757 {
00758 self->side_is_A = 1;
00759 self->m=8;
00760 break;
00761 }
00762 case VISIR_SPC_M_HR10:
00763 {
00764 self->m=7;
00765 break;
00766 }
00767 default:;
00768 }
00769 if (self->side_is_A) {
00770
00771 self->d=79.93104;
00772 self->angle_a = 62.1299;
00773 self->angle_bm = 64.8519;
00774 self->angle_b0 = 64.5393;
00775 self->angle_b1 = 65.1641;
00776 } else {
00777
00778 self->d=77.16526;
00779 self->angle_a = 64.8701;
00780 self->angle_bm = 62.1483;
00781 self->angle_b0 = 62.4609;
00782 self->angle_b1 = 61.8361;
00783 }
00784 break;
00785 }
00786 default:;
00787 }
00788
00789 self->angle_a *= rad_per_deg;
00790 self->angle_b0 *= rad_per_deg;
00791 self->angle_bm *= rad_per_deg;
00792 self->angle_b1 *= rad_per_deg;
00793
00794
00795 self->d *= 1e-6;
00796 self->dcolbeam *= 1e-6;
00797
00798 assert( self->m > 0);
00799
00800 visir_spc_optmod_scan_angle(self);
00801
00802 self->sinus_sum = sin(self->angle_a + self->angle_scan)
00803 + sin(self->angle_bm + self->angle_scan);
00804
00805 return 0;
00806
00807 }
00808
00809
00810
00824
00825 double visir_spc_optmod_wlen(const visir_optmod * pins, double * pwl0,
00826 double * pwl1)
00827 {
00828
00829 const visir_optmod_private * self = (const visir_optmod_private*)pins;
00830
00831 if (self == NULL) return -1;
00832
00833
00834 if (pwl0) *pwl0 = self->d/self->m*( sin(self->angle_a + self->angle_scan)
00835 + sin(self->angle_b0 + self->angle_scan));
00836
00837
00838 if (pwl1) *pwl1 = self->d/self->m*( sin(self->angle_a + self->angle_scan)
00839 + sin(self->angle_b1 + self->angle_scan));
00840
00841
00842 return self->d / self->m * self->sinus_sum;
00843
00844 }
00845
00846
00865
00866 double visir_spc_optmod_cross_dispersion(const visir_optmod * pins, double wlen)
00867 {
00868
00869 double sinbeta;
00870 double rf_index;
00871 const visir_optmod_private * self = (const visir_optmod_private*)pins;
00872
00873 if (self == NULL) return -1;
00874
00875 if (self->resolution != VISIR_SPC_R_GHR) return -2;
00876 if (wlen <= 0) return -3;
00877
00878 assert( self->gg != 0 );
00879
00880 rf_index = visir_spc_optmod_krs5(wlen);
00881
00882 if (rf_index < 1) return -8;
00883
00884 sinbeta = sin(self->w) * rf_index - wlen / self->gg;
00885
00886
00887 if (sinbeta < -1) return -9;
00888 if (sinbeta > 1) return -10;
00889
00890 return self->offset + self->factor * tan(asin(sinbeta) - self->w);
00891
00892 }
00893
00894
00895
00918
00919 double visir_spc_optmod_echelle(const visir_optmod * pins, double wlen,
00920 int ioffset)
00921 {
00922
00923 int order;
00924 const visir_optmod_private * self = (const visir_optmod_private*)pins;
00925
00926 if (self == NULL) return -1;
00927 if (self->resolution != VISIR_SPC_R_GHR) return -2;
00928 if (wlen <= 0) return -3;
00929 if (ioffset < -4) return -4;
00930 if (ioffset > 4) return -5;
00931
00932 order = ioffset + self->m;
00933
00934
00935 if (order < 1) return -6;
00936 if (order > 18) return -7;
00937
00938 return wlen * self->m / (double) order;
00939
00940 }
00941
00942
00957
00958 int visir_spc_optmod_side_is_A(const visir_optmod * pins)
00959 {
00960 const visir_optmod_private * self = (const visir_optmod_private*)pins;
00961
00962 if (self == NULL) return -1;
00963
00964 if (self->resolution != VISIR_SPC_R_GHR &&
00965 self->resolution != VISIR_SPC_R_HR) return -2;
00966
00967 return self->side_is_A;
00968
00969 }
00970
00971
00986
00987 int visir_spc_optmod_get_echelle_order(const visir_optmod * pins)
00988 {
00989 const visir_optmod_private * self = (const visir_optmod_private*)pins;
00990
00991 if (self == NULL) return -1;
00992
00993 if (self->resolution != VISIR_SPC_R_GHR &&
00994 self->resolution != VISIR_SPC_R_HR) return -2;
00995
00996 return self->m;
00997 }
00998
00999
01000
01012
01013
01014 double visir_spc_optmod_resolution(const visir_optmod * pins)
01015 {
01016 const visir_optmod_private * self = (const visir_optmod_private*)pins;
01017
01018 if (self == NULL) return -1;
01019
01020 return self->dcolbeam * self->sinus_sum
01021 /(2.0 * self->wlen * cos(self->angle_a + self->angle_scan));
01022 }
01023
01024
01037
01038
01039 double visir_spc_optmod_dispersion(const visir_optmod * pins)
01040 {
01041 const visir_optmod_private * self = (const visir_optmod_private*)pins;
01042
01043 if (self == NULL) return -1;
01044
01045 return self->ld * self->sinus_sum
01046 /(self->wlen * cos(self->angle_bm + self->angle_scan));
01047 }
01048
01051
01058
01059 static double visir_spc_optmod_krs5(double wlen) {
01060
01061 const double a0 = 5.96032159;
01062 const double a1 = -5.36135205e-4;
01063 const double a2 = 1.77047634;
01064 const double a3 = -2.79310980e1;
01065 const double a4 = -1.28684883;
01066 const double a5 = -4.34541795e-2;
01067
01068 double n2 = 0;
01069
01070
01071 assert( wlen > 0 );
01072
01073
01074 wlen *= 1e6;
01075
01076 wlen *= wlen;
01077
01078 n2 = a0 + a1 * wlen + (((a5/wlen + a4)/wlen + a3)/ wlen + a2)/wlen;
01079
01080
01081 return n2 > 1 ? sqrt(n2) : -1;
01082
01083 }
01084
01085
01092
01093 static void visir_spc_optmod_scan_angle(visir_optmod_private * self)
01094 {
01095
01096
01097
01098 const double mld = self->m * self->wlen / self->d;
01099 const double sab = sin(self->angle_bm) + sin(self->angle_a);
01100 const double cab = cos(self->angle_bm) + cos(self->angle_a);
01101 const double A = sab * sab + cab * cab;
01102
01103
01104
01105 const double C = mld * mld - sab * sab;
01106
01107 double D = A - mld * mld;
01108 double u1, u2;
01109
01110
01111 D = D > 0 ? sqrt(D) : 0;
01112 D *= fabs(sab);
01113
01114
01115 u1 = (cab * mld + D) / A;
01116
01117
01118
01119
01120 u2 = C / A / u1;
01121
01122
01123
01124
01125 self->angle_scan = asin(u2);
01126
01127 }