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