1 /* 2 3 -Procedure dskxsi_c (DSK, ray-surface intercept with source information) 4 5 -Abstract 6 7 Compute a ray-surface intercept using data provided by 8 multiple loaded DSK segments. Return information about 9 the source of the data defining the surface on which the 10 intercept was found: DSK handle, DLA and DSK descriptors, 11 and DSK data type-dependent parameters. 12 13 -Disclaimer 14 15 THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE 16 CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. 17 GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE 18 ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE 19 PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" 20 TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY 21 WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A 22 PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC 23 SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE 24 SOFTWARE AND RELATED MATERIALS, HOWEVER USED. 25 26 IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA 27 BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT 28 LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, 29 INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, 30 REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE 31 REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. 32 33 RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF 34 THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY 35 CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE 36 ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. 37 38 -Required_Reading 39 40 CK 41 DSK 42 FRAMES 43 PCK 44 SPK 45 TIME 46 47 -Keywords 48 49 GEOMETRY 50 INTERCEPT 51 SURFACE 52 TOPOGRAPHY 53 54 */ 55 56 #include "SpiceUsr.h" 57 #include "SpiceZfc.h" 58 #include "SpiceZst.h" 59 #include "SpiceZmc.h" 60 #undef dskxsi_c 61 62 dskxsi_c(SpiceBoolean pri,ConstSpiceChar * target,SpiceInt nsurf,ConstSpiceInt srflst[],SpiceDouble et,ConstSpiceChar * fixref,ConstSpiceDouble vertex[3],ConstSpiceDouble raydir[3],SpiceInt maxd,SpiceInt maxi,SpiceDouble xpt[3],SpiceInt * handle,SpiceDLADescr * dladsc,SpiceDSKDescr * dskdsc,SpiceDouble dc[],SpiceInt ic[],SpiceBoolean * found)63 void dskxsi_c ( SpiceBoolean pri, 64 ConstSpiceChar * target, 65 SpiceInt nsurf, 66 ConstSpiceInt srflst [], 67 SpiceDouble et, 68 ConstSpiceChar * fixref, 69 ConstSpiceDouble vertex [3], 70 ConstSpiceDouble raydir [3], 71 SpiceInt maxd, 72 SpiceInt maxi, 73 SpiceDouble xpt [3], 74 SpiceInt * handle, 75 SpiceDLADescr * dladsc, 76 SpiceDSKDescr * dskdsc, 77 SpiceDouble dc [], 78 SpiceInt ic [], 79 SpiceBoolean * found ) 80 /* 81 82 -Brief_I/O 83 84 VARIABLE I/O DESCRIPTION 85 -------- --- -------------------------------------------------- 86 pri I Data prioritization flag. 87 target I Target body name. 88 nsurf I Number of surface IDs in list. 89 srflst I Surface ID list. 90 et I Epoch, expressed as seconds past J2000 TDB. 91 fixref I Name of target body-fixed reference frame. 92 vertex I Vertex of ray. 93 raydir I Direction vector of ray. 94 maxd I Size of DC array. 95 maxi I Size of IC array. 96 xpt O Intercept point. 97 handle O Handle of segment contributing surface data. 98 dladsc O DLA descriptor of segment. 99 dskdsc O DSK descriptor of segment. 100 dc O Double precision component of source info. 101 ic O Integer component of source info. 102 found O Found flag. 103 SPICE_DSKXSI_DCSIZE 104 P Required size of DC array. 105 SPICE_DSKXSI_ICSIZE 106 P Required size of IC array. 107 108 -Detailed_Input 109 110 pri is a logical flag indicating whether to perform 111 a prioritized or unprioritized DSK segment search. 112 In an unprioritized search, no segment masks another: 113 data from all specified segments are used to 114 define the surface of interest. 115 116 The search is unprioritized if and only if `pri' 117 is set to SPICEFALSE. In the N0066 SPICE Toolkit, this 118 is the only allowed value. 119 120 121 target is the name of the target body on which a surface 122 intercept is sought. 123 124 125 nsurf, 126 srflst are, respectively, a count of surface ID codes in a list 127 and an array containing the list. Only DSK segments for 128 the body designated by `target' and having surface IDs in 129 this list will be considered in the intercept 130 computation. If the list is empty, all DSK segments for 131 `target' will be considered. 132 133 134 et is the epoch of the intersection computation, expressed 135 as seconds past J2000 TDB. This epoch is used only for 136 DSK segment selection. Segments used in the intercept 137 computation must include `et' in their time coverage 138 intervals. 139 140 141 fixref is the name of a body-fixed, body-centered reference 142 frame associated with the target. The input ray vectors 143 are specified in this frame, as is the output intercept 144 point. 145 146 The frame designated by `fixref' must have a fixed 147 orientation relative to the frame of any DSK segment 148 used in the computation. 149 150 151 vertex, 152 raydir are, respectively, the vertex and direction vector of 153 the ray to be used in the intercept computation. 154 155 Both the vertex and ray's direction vector must be 156 represented in the reference frame designated by 157 `fixref'. The vertex is considered to be an offset from 158 the target body. 159 160 maxd, 161 maxi are, respectively, the declared sizes of the arrays 162 `dc' and `ic'. `maxd' must be at least 163 164 SPICE_DSKXSI_DCSIZE 165 166 while `maxi' must be at least 167 168 SPICE_DSKXSI_ICSIZE 169 170 See the Parameters section for details. 171 172 -Detailed_Output 173 174 175 xpt is the intercept of the input ray on the surface 176 specified by the inputs 177 178 pri 179 target 180 nsurf 181 srflst 182 et 183 184 if such an intercept exists. If the ray intersects the 185 surface at multiple points, the one closest to the 186 ray's vertex is selected. 187 188 `xpt' is defined if and only if `found' is SPICETRUE. 189 190 Units are km. 191 192 193 handle, 194 dladsc, 195 dskdsk are, respectively, the DSK file handle, DLA descriptor, 196 and DSK descriptor of the DSK file and segment that 197 contributed the surface data on which the intercept 198 was found. 199 200 These outputs are defined if and only if `found' is 201 SPICETRUE. 202 203 dc, 204 ic are, respectively, double precision and integer arrays 205 that may contain additional information associated 206 with the segment contributing the surface data on 207 which the intercept was found. The information is 208 DSK data type-dependent. 209 210 For DSK type 2 segments 211 212 ic[0] is the intercept plate ID. 213 `dc' is unused. 214 215 These outputs are defined if and only if `found' is 216 SPICETRUE. 217 218 219 found is a logical flag that is set to SPICETRUE if and only if 220 and intercept was found. 221 222 223 -Parameters 224 225 See the header file 226 227 SpiceDSK.h 228 229 for declarations of size parameters for the output arguments 230 231 dc 232 ic 233 234 See the header files 235 236 SpiceDLA.h 237 SpiceDSK.h 238 239 for declarations of DLA and DSK descriptor sizes and 240 documentation of the contents of these descriptors. 241 242 See the header file 243 244 SpiceDtl.h 245 246 for the values of tolerance parameters used by default by the 247 ray-surface intercept algorithm. These are discussed in in the 248 Particulars section below. 249 250 -Exceptions 251 252 1) If the input prioritization flag `pri' is set to SPICETRUE, 253 the error SPICE(NOPRIORITIZATION) is signaled. 254 255 2) If the input body name `target' cannot be mapped to an 256 ID code, the error SPICE(IDCODENOTFOUND) is signaled. 257 258 3) If the input frame name `fixref' cannot be mapped to an 259 ID code, the error SPICE(IDCODENOTFOUND) is signaled. 260 261 4) If the frame center associated with `fixref' cannot be 262 retrieved, the error SPICE(NOFRAMEINFO) is signaled. 263 264 5) If the frame center associated with `fixref' is not 265 the target body, the error SPICE(INVALIDFRAME) is signaled. 266 267 6) Any errors that occur during the intercept computation 268 will be signaled by routines in the call tree of this 269 routine. 270 271 7) If `maxd' is less than SPICE_DSKXIS_DCSIZE or `maxi' is less 272 than SPICE_DSKXSI_ICSIZE, the error SPICE(ARRAYTOOSMALL) will 273 be signaled. 274 275 8) If any input string argument pointer is null, the error 276 SPICE(NULLPOINTER) will be signaled. 277 278 9) If any input string argument is empty, the error 279 SPICE(EMPTYSTRING) will be signaled. 280 281 -Files 282 283 Appropriate kernels must be loaded by the calling program before 284 this routine is called. 285 286 The following data are required: 287 288 - SPK data: ephemeris data for the positions of the centers 289 of DSK reference frames relative to the target body are 290 required if those frames are not centered at the target 291 body center. 292 293 Typically ephemeris data are made available by loading one 294 or more SPK files via furnsh_c. 295 296 - DSK data: DSK files containing topographic data for the 297 target body must be loaded. If a surface list is specified, 298 data for at least one of the listed surfaces must be loaded. 299 300 - Frame data: if a frame definition is required to convert 301 DSK segment data to the body-fixed frame designated by 302 `fixref', the target, that definition must be available in the 303 kernel pool. Typically the definitions of frames not already 304 built-in to SPICE are supplied by loading a frame kernel. 305 306 - CK data: if the frame to which `fixref' refers is a CK frame, 307 and if any DSK segments used in the computation have a 308 different frame, at least one CK file will be needed to 309 permit transformation of vectors between that frame and both 310 the J2000 and the target body-fixed frames. 311 312 - SCLK data: if a CK file is needed, an associated SCLK 313 kernel is required to enable conversion between encoded SCLK 314 (used to time-tag CK data) and barycentric dynamical time 315 (TDB). 316 317 In all cases, kernel data are normally loaded once per program 318 run, NOT every time this routine is called. 319 320 321 -Particulars 322 323 324 This is the lowest-level public interface for computing 325 ray-surface intercepts, where the surface is modeled using 326 topographic data provided by DSK files. The highest-level 327 interface for this purpose is sincpt_c. 328 329 In cases where the data source information returned by this 330 routine are not needed, the routine dskxv_c may be more suitable. 331 332 This routine works with multiple DSK files. It places no 333 restrictions on the data types or coordinate systems of the DSK 334 segments used in the computation. DSK segments using different 335 reference frames may be used in a single computation. The only 336 restriction is that any pair of reference frames used directly or 337 indirectly are related by a constant rotation. 338 339 This routine enables calling applications to identify the source of 340 the data defining the surface on which an intercept was found. The 341 file, segment, and segment-specific information such as a DSK type 2 342 plate ID are returned. 343 344 This routine can be used for improved efficiency in situations 345 in which multiple ray-surface intercepts are to be performed 346 using a constant ray vertex. 347 348 349 Using DSK data 350 ============== 351 352 DSK loading and unloading 353 ------------------------- 354 355 DSK files providing data used by this routine are loaded by 356 calling furnsh_c and can be unloaded by calling unload_c or 357 kclear_c. See the documentation of furnsh_c for limits on numbers 358 of loaded DSK files. 359 360 For run-time efficiency, it's desirable to avoid frequent 361 loading and unloading of DSK files. When there is a reason to 362 use multiple versions of data for a given target body---for 363 example, if topographic data at varying resolutions are to be 364 used---the surface list can be used to select DSK data to be 365 used for a given computation. It is not necessary to unload 366 the data that are not to be used. This recommendation presumes 367 that DSKs containing different versions of surface data for a 368 given body have different surface ID codes. 369 370 371 DSK data priority 372 ----------------- 373 374 A DSK coverage overlap occurs when two segments in loaded DSK 375 files cover part or all of the same domain---for example, a 376 given longitude-latitude rectangle---and when the time 377 intervals of the segments overlap as well. 378 379 When DSK data selection is prioritized, in case of a coverage 380 overlap, if the two competing segments are in different DSK 381 files, the segment in the DSK file loaded last takes 382 precedence. If the two segments are in the same file, the 383 segment located closer to the end of the file takes 384 precedence. 385 386 When DSK data selection is unprioritized, data from competing 387 segments are combined. For example, if two competing segments 388 both represent a surface as sets of triangular plates, the 389 union of those sets of plates is considered to represent the 390 surface. 391 392 Currently only unprioritized data selection is supported. 393 Because prioritized data selection may be the default behavior 394 in a later version of the routine, the presence of the `pri' 395 argument is required. 396 397 398 Round-off errors and mitigating algorithms 399 ------------------------------------------ 400 401 When topographic data are used to represent the surface of a 402 target body, round-off errors can produce some results that 403 may seem surprising. 404 405 Note that, since the surface in question might have mountains, 406 valleys, and cliffs, the points of intersection found for 407 nearly identical sets of inputs may be quite far apart from 408 each other: for example, a ray that hits a mountain side in a 409 nearly tangent fashion may, on a different host computer, be 410 found to miss the mountain and hit a valley floor much farther 411 from the observer, or even miss the target altogether. 412 413 Round-off errors can affect segment selection: for example, a 414 ray that is expected to intersect the target body's surface 415 near the boundary between two segments might hit either 416 segment, or neither of them; the result may be 417 platform-dependent. 418 419 A similar situation exists when a surface is modeled by a set 420 of triangular plates, and the ray is expected to intersect the 421 surface near a plate boundary. 422 423 To avoid having the routine fail to find an intersection when 424 one clearly should exist, this routine uses two "greedy" 425 algorithms: 426 427 1) If the ray passes sufficiently close to any of the 428 boundary surfaces of a segment (for example, surfaces of 429 maximum and minimum longitude or latitude), that segment 430 is tested for an intersection of the ray with the 431 surface represented by the segment's data. 432 433 This choice prevents all of the segments from being 434 missed when at least one should be hit, but it could, on 435 rare occasions, cause an intersection to be found in a 436 segment other than the one that would be found if higher 437 precision arithmetic were used. 438 439 2) For type 2 segments, which represent surfaces as 440 sets of triangular plates, each plate is expanded very 441 slightly before a ray-plate intersection test is 442 performed. The default plate expansion factor is 443 444 1 + XFRACT 445 446 where XFRACT is declared in 447 448 SpiceDtl.h 449 450 For example, given a value for XFRACT of 1.e-10, the 451 sides of the plate are lengthened by 1/10 of a micron 452 per km. The expansion keeps the centroid of the plate 453 fixed. 454 455 Plate expansion prevents all plates from being missed 456 in cases where clearly at least one should be hit. 457 458 As with the greedy segment selection algorithm, plate 459 expansion can occasionally cause an intercept to be 460 found on a different plate than would be found if higher 461 precision arithmetic were used. It also can occasionally 462 cause an intersection to be found when the ray misses 463 the target by a very small distance. 464 465 -Examples 466 467 The numerical results shown for these examples may differ across 468 platforms. The results depend on the SPICE kernels used as 469 input, the compiler and supporting libraries, and the machine 470 specific arithmetic implementation. 471 472 1) Compute surface intercepts of rays emanating from a set of 473 vertices distributed on a longitude-latitude grid. All 474 vertices are outside the target body, and all rays point 475 toward the target's center. 476 477 Check intercepts against expected values. Indicate the 478 number of errors, the number of computations, and the 479 number of intercepts found. 480 481 Use the meta-kernel shown below to load example SPICE 482 kernels. 483 484 KPL/MK 485 486 File: dskxsi_ex1.tm 487 488 This meta-kernel is intended to support operation of SPICE 489 example programs. The kernels shown here should not be 490 assumed to contain adequate or correct versions of data 491 required by SPICE-based user applications. 492 493 In order for an application to use this meta-kernel, the 494 kernels referenced here must be present in the user's 495 current working directory. 496 497 The names and contents of the kernels referenced 498 by this meta-kernel are as follows: 499 500 File name Contents 501 --------- -------- 502 phobos512.bds DSK based on 503 Gaskell ICQ Q=512 504 plate model 505 \begindata 506 507 PATH_SYMBOLS = 'GEN' 508 PATH_VALUES = '/ftp/pub/naif/generic_kernels' 509 510 KERNELS_TO_LOAD = ( '$GEN/dsk/phobos/phobos512.bds' ) 511 512 \begintext 513 514 515 Example code begins here. 516 517 518 /. 519 Multi-segment spear program. 520 521 This program expects all loaded DSKs 522 to represent the same body and surface. 523 524 Syntax: spear <meta-kernel> 525 ./ 526 527 #include <stdio.h> 528 #include <stdlib.h> 529 #include "SpiceUsr.h" 530 531 int main( int argc, char **argv ) 532 { 533 /. 534 Local constants 535 ./ 536 #define DTOL 1.0e-14 537 #define FILSIZ 256 538 #define FRNMLN 33 539 #define BDNMLN 37 540 #define TYPLEN 5 541 #define INTLEN 12 542 #define MAXN 100000 543 #define MAXSRF 100 544 #define MAXD SPICE_DSKXSI_DCSIZE 545 #define MAXI SPICE_DSKXSI_ICSIZE 546 547 /. 548 Local variables 549 ./ 550 SpiceBoolean found; 551 552 SpiceChar dsk1 [FILSIZ]; 553 SpiceChar fixref [FRNMLN]; 554 SpiceChar source [FILSIZ]; 555 SpiceChar filtyp [TYPLEN]; 556 SpiceChar target [BDNMLN]; 557 558 SpiceDLADescr dladsc; 559 SpiceDLADescr xptDLAdsc; 560 561 SpiceDSKDescr dskdsc; 562 SpiceDSKDescr xptDSKdsc; 563 564 SpiceDouble d; 565 SpiceDouble dc [1]; 566 static SpiceDouble dirarr[MAXN][3]; 567 SpiceDouble et; 568 SpiceDouble lat; 569 SpiceDouble latcrd[3]; 570 SpiceDouble latstp; 571 SpiceDouble lon; 572 SpiceDouble lonstp; 573 SpiceDouble polmrg; 574 SpiceDouble r; 575 SpiceDouble radius; 576 SpiceDouble vlat; 577 SpiceDouble vlon; 578 SpiceDouble vrad; 579 static SpiceDouble vtxarr[MAXN][3]; 580 static SpiceDouble xpt [3]; 581 SpiceDouble xyzhit[3]; 582 583 SpiceInt bodyid; 584 SpiceInt framid; 585 SpiceInt handle; 586 SpiceInt i; 587 SpiceInt ic [1]; 588 SpiceInt nderr; 589 SpiceInt nhits; 590 SpiceInt nlstep; 591 SpiceInt nrays; 592 SpiceInt nsurf; 593 static SpiceInt srflst [MAXSRF]; 594 SpiceInt surfid; 595 SpiceInt xpthan; 596 597 598 599 chkin_c ( "spear" ); 600 601 /. 602 Get meta-kernel name from the command line. 603 ./ 604 if ( argc != 2 ) 605 { 606 printf ( "Command syntax: spear <meta-kernel>\n" ); 607 exit(1); 608 } 609 610 /. 611 Load the meta-kernel. 612 ./ 613 furnsh_c ( argv[1] ); 614 615 /. 616 Get a handle for one of the loaded DSKs, 617 then find the first segment and extract 618 the body and surface IDs. 619 ./ 620 kdata_c ( 0, "DSK", FILSIZ, TYPLEN, FILSIZ, 621 dsk1, filtyp, source, &handle, &found ); 622 if ( !found ) 623 { 624 sigerr_c ( "SPICE(NOINFO)" ); 625 } 626 627 dlabfs_c ( handle, &dladsc, &found ); 628 629 if ( !found ) 630 { 631 sigerr_c ( "SPICE(NOSEGMENT)" ); 632 } 633 634 dskgd_c ( handle, &dladsc, &dskdsc ); 635 636 bodyid = dskdsc.center; 637 surfid = dskdsc.surfce; 638 framid = dskdsc.frmcde; 639 640 bodc2n_c ( bodyid, BDNMLN, target, &found ); 641 642 if ( !found ) 643 { 644 setmsg_c ( "Cannot map body ID # to a name." ); 645 errint_c ( "#", bodyid ); 646 sigerr_c ( "SPICE(BODYNAMENOTFOUND)" ); 647 } 648 649 frmnam_c ( framid, FRNMLN, fixref ); 650 651 if ( eqstr_c( fixref, " " ) ) 652 { 653 setmsg_c ( "Cannot map frame ID # to a name." ); 654 errint_c ( "#", framid ); 655 sigerr_c ( "SPICE(BODYNAMENOTFOUND)" ); 656 } 657 658 /. 659 Set the magnitude of the ray vertices. Use a large 660 number to ensure the vertices are outside of 661 any realistic target. 662 ./ 663 r = 1.0e10; 664 665 /. 666 Spear the target with rays pointing toward 667 the origin. Use a grid of ray vertices 668 located on a sphere enclosing the target. 669 670 The variable `polmrg' ("pole margin") can 671 be set to a small positive value to reduce 672 the number of intercepts done at the poles. 673 This may speed up the computation for 674 the multi-segment case, since rays parallel 675 to the Z axis will cause all segments converging 676 at the pole of interest to be tested for an 677 intersection. 678 ./ 679 680 polmrg = 0.5; 681 latstp = 1.0; 682 lonstp = 2.0; 683 684 nhits = 0; 685 nderr = 0; 686 687 lon = -180.0; 688 lat = 90.0; 689 nlstep = 0; 690 nrays = 0; 691 692 /. 693 Generate rays. 694 ./ 695 while ( lon < 180.0 ) 696 { 697 while ( nlstep <= 180 ) 698 { 699 if ( lon == 180.0 ) 700 { 701 lat = 90.0 - nlstep*latstp; 702 } 703 else 704 { 705 if ( nlstep == 0 ) 706 { 707 lat = 90.0 - polmrg; 708 } 709 else if ( nlstep == 180 ) 710 { 711 lat = -90.0 + polmrg; 712 } 713 else 714 { 715 lat = 90.0 - nlstep*latstp; 716 } 717 } 718 719 latrec_c ( r, lon*rpd_c(), 720 lat*rpd_c(), vtxarr[nrays] ); 721 722 vminus_c ( vtxarr[nrays], dirarr[nrays] ); 723 724 ++ nrays; 725 ++ nlstep; 726 } 727 728 lon += lonstp; 729 lat = 90.0; 730 nlstep = 0; 731 } 732 733 /. 734 Assign surface ID list. 735 736 Note that, if we knew that all files had the desired 737 surface ID, we could set `nsurf' to 0 and omit the 738 initialization of the surface ID list. 739 ./ 740 nsurf = 1; 741 srflst[0] = surfid; 742 743 printf ( "Computing intercepts...\n" ); 744 745 for ( i = 0; i < nrays; i++ ) 746 { 747 /. 748 Find the surface intercept of the ith ray. 749 ./ 750 751 dskxsi_c ( SPICEFALSE, target, nsurf, srflst, 752 et, fixref, vtxarr[i], dirarr[i], 753 MAXD, MAXI, xpt, &xpthan, 754 &xptDLAdsc, &xptDSKdsc, dc, ic, 755 &found ); 756 757 if ( found ) 758 { 759 760 /. 761 Record that a new intercept was found. 762 ./ 763 ++ nhits; 764 765 /. 766 Check results. 767 768 769 Compute the latitude and longitude of 770 the intercept. Make sure these agree 771 well with those of the vertex. 772 ./ 773 reclat_c ( xpt, latcrd, latcrd+1, latcrd+2 ); 774 radius = latcrd[0]; 775 776 /. 777 Recover the vertex longitude and latitude. 778 ./ 779 reclat_c ( vtxarr[i], &vrad, &vlon, &vlat ); 780 latrec_c ( radius, vlon, vlat, xyzhit ); 781 782 d = vdist_c( xpt, xyzhit ); 783 784 if ( d/r > DTOL ) 785 { 786 printf ( "===========================\n" ); 787 printf ( "Lon = %f; Lat = %f\n", 788 lon, lat ); 789 printf ( "Bad intercept\n" ); 790 printf ( "Distance error = %e\n", d ); 791 printf ( "xpt = (%e %e %e)\n", 792 xpt[0], xpt[1], xpt[2] ); 793 printf ( "xyzhit = (%e %e %e)\n", 794 xyzhit[0], xyzhit[1], xyzhit[2] ); 795 /. 796 Display the intercept segment's plate ID if 797 applicable. 798 ./ 799 if ( xptDSKdsc.dtype == 2 ) 800 { 801 printf ( "Plate ID = %d\n", (int)ic[0] ); 802 } 803 804 805 ++ nderr; 806 } 807 } 808 else 809 { 810 /. 811 Missing the target entirely is a fatal error. 812 813 This is true only for this program, not in 814 general. For example, if the target shape is 815 a torus, many rays would miss the target. 816 ./ 817 printf ( "===========================\n" ); 818 printf ( "Lon = %f; Lat = %f\n", 819 lon, lat ); 820 printf ( "No intercept\n" ); 821 exit( 1 ); 822 } 823 } 824 printf ( "Done.\n\n" ); 825 826 printf( "nrays = %d\n", (int)nrays ); 827 printf( "nhits = %d\n", (int)nhits ); 828 printf( "nderr = %d\n", (int)nderr ); 829 830 return ( 0 ); 831 } 832 833 834 When this program was executed on a PC/Linux/gcc 64-bit 835 platform, using the meta-kernel shown above, the output was: 836 837 838 Computing intercepts... 839 Done. 840 841 nrays = 32580 842 nhits = 32580 843 nderr = 0 844 845 846 -Restrictions 847 848 1) The frame designated by `fixref' must have a fixed 849 orientation relative to the frame of any DSK segment 850 used in the computation. This routine has no 851 practical way of ensuring that this condition is met; 852 so this responsibility is delegated to the calling 853 application. 854 855 -Literature_References 856 857 None. 858 859 -Author_and_Institution 860 861 N.J. Bachman (JPL) 862 863 -Version 864 865 -CSPICE Version 1.0.0, 04-APR-2017 (NJB) 866 867 -Index_Entries 868 869 dsk ray-surface intercept with source information 870 dsk ray-surface intercept with handle and descriptors 871 872 -& 873 */ 874 875 { /* Begin dskxsi_c */ 876 877 /* 878 Local variables 879 */ 880 SpiceDouble fDSKDescr [ SPICE_DSK_DSCSIZ ]; 881 882 SpiceInt fDLADescr [ SPICE_DLA_DSCSIZ ]; 883 884 logical foundFlag; 885 logical priFlag; 886 887 888 /* 889 Participate in error tracing. 890 */ 891 chkin_c ( "dskxsi_c" ); 892 893 /* 894 Check the input string arguments: 895 896 target 897 fixref 898 899 Make sure each pointer is non-null and each string contains 900 at least one data character: that is, one character 901 preceding the null terminator. 902 */ 903 CHKFSTR ( CHK_STANDARD, "dskxsi_c", target ); 904 CHKFSTR ( CHK_STANDARD, "dskxsi_c", fixref ); 905 906 907 /* 908 The input prioritization flag must be converted to type 909 logical for the following call. 910 */ 911 priFlag = (logical)pri; 912 913 dskxsi_ ( (logical *) &priFlag, 914 (char *) target, 915 (integer *) &nsurf, 916 (integer *) srflst, 917 (doublereal *) &et, 918 (char *) fixref, 919 (doublereal *) vertex, 920 (doublereal *) raydir, 921 (integer *) &maxd, 922 (integer *) &maxi, 923 (doublereal *) xpt, 924 (integer *) handle, 925 (integer *) fDLADescr, 926 (doublereal *) fDSKDescr, 927 (doublereal *) dc, 928 (integer *) ic, 929 (logical *) &foundFlag, 930 (ftnlen ) strlen(target), 931 (ftnlen ) strlen(fixref) ); 932 933 /* 934 Regardless of whether the call succeeded, transfer data from the DLA 935 and DSK descriptors to their respective output arguments. 936 937 Set the contents of the output DLA descriptor. 938 */ 939 dladsc->bwdptr = fDLADescr[SPICE_DLA_BWDIDX]; 940 dladsc->fwdptr = fDLADescr[SPICE_DLA_FWDIDX]; 941 dladsc->ibase = fDLADescr[SPICE_DLA_IBSIDX]; 942 dladsc->isize = fDLADescr[SPICE_DLA_ISZIDX]; 943 dladsc->dbase = fDLADescr[SPICE_DLA_DBSIDX]; 944 dladsc->dsize = fDLADescr[SPICE_DLA_DSZIDX]; 945 dladsc->cbase = fDLADescr[SPICE_DLA_CBSIDX]; 946 dladsc->csize = fDLADescr[SPICE_DLA_CSZIDX]; 947 948 /* 949 Set the contents of the output DSK descriptor. 950 */ 951 dskdsc->surfce = fDSKDescr[SPICE_DSK_SRFIDX]; 952 dskdsc->center = fDSKDescr[SPICE_DSK_CTRIDX]; 953 dskdsc->dclass = fDSKDescr[SPICE_DSK_CLSIDX]; 954 dskdsc->dtype = fDSKDescr[SPICE_DSK_TYPIDX]; 955 dskdsc->corsys = fDSKDescr[SPICE_DSK_SYSIDX]; 956 dskdsc->frmcde = fDSKDescr[SPICE_DSK_FRMIDX]; 957 958 MOVED ( fDSKDescr + SPICE_DSK_PARIDX, 959 SPICE_DSK_NSYPAR, 960 dskdsc->corpar ); 961 962 dskdsc->co1min = fDSKDescr[SPICE_DSK_MN1IDX]; 963 dskdsc->co1max = fDSKDescr[SPICE_DSK_MX1IDX]; 964 dskdsc->co2min = fDSKDescr[SPICE_DSK_MN2IDX]; 965 dskdsc->co2max = fDSKDescr[SPICE_DSK_MX2IDX]; 966 dskdsc->co3min = fDSKDescr[SPICE_DSK_MN3IDX]; 967 dskdsc->co3max = fDSKDescr[SPICE_DSK_MX3IDX]; 968 dskdsc->start = fDSKDescr[SPICE_DSK_BTMIDX]; 969 dskdsc->stop = fDSKDescr[SPICE_DSK_ETMIDX]; 970 971 /* 972 Cast the logical found flag to the output type. 973 */ 974 975 *found = (SpiceBoolean) foundFlag; 976 977 978 chkout_c ( "dskxsi_c" ); 979 980 } /* End dskxsi_c */ 981