1 /* 2 3 -Procedure llgrid_pl02 ( Lon/lat grid using DSK type 2 plate model ) 4 5 -Abstract 6 7 Deprecated: This routine has been superseded by the CSPICE routine 8 latsrf_c. This routine is supported for purposes of backward 9 compatibility only. 10 11 Given the planetocentric longitude and latitude values of a set of 12 surface points on a specified target body, compute the corresponding 13 rectangular coordinates of those points. The target body's 14 surface is represented by a triangular plate model contained in a 15 type 2 DSK segment. 16 17 -Disclaimer 18 19 THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE 20 CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. 21 GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE 22 ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE 23 PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" 24 TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY 25 WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A 26 PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC 27 SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE 28 SOFTWARE AND RELATED MATERIALS, HOWEVER USED. 29 30 IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA 31 BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT 32 LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, 33 INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, 34 REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE 35 REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. 36 37 RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF 38 THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY 39 CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE 40 ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. 41 42 -Required_Reading 43 44 FRAMES 45 PCK 46 SPK 47 TIME 48 49 -Keywords 50 51 GEOMETRY 52 53 */ 54 55 #include "SpiceUsr.h" 56 #include "SpiceZfc.h" 57 #include "SpiceZmc.h" 58 59 llgrid_pl02(SpiceInt handle,ConstSpiceDLADescr * dladsc,SpiceInt npoints,ConstSpiceDouble grid[][2],SpiceDouble spoints[][3],SpiceInt plateIDs[])60 void llgrid_pl02 ( SpiceInt handle, 61 ConstSpiceDLADescr * dladsc, 62 SpiceInt npoints, 63 ConstSpiceDouble grid [][2], 64 SpiceDouble spoints [][3], 65 SpiceInt plateIDs [] ) 66 /* 67 68 -Brief_I/O 69 70 Variable I/O Description 71 -------- --- -------------------------------------------------- 72 handle I DSK handle. 73 dlasdc I DLA descriptor of target body segment. 74 npoints I Number of grid coordinate pairs. 75 grid I Lon/lat values of surface points (radians). 76 spoints O Rectangular coordinates of surface points. 77 plateIDs O DSK plate IDs of surface points. 78 79 -Detailed_Input 80 81 handle is the DAS file handle of a DSK file open for read 82 access. This kernel must contain a type 2 segment 83 that provides a plate model representing the entire 84 surface of the target body. 85 86 dladsc is the DLA descriptor of a DSK segment representing 87 the surface of a target body. 88 89 npoints is the number of longitude/latitude pairs in the array 90 of grid points `grid'. 91 92 grid is an array of planetocentric longitude/latitude pairs 93 to be mapped to surface points on the target body. 94 `grid' should be declared by the caller 95 96 SpiceDouble grid [npoints][2]; 97 98 Elements 99 100 grid[i][0] 101 grid[i][1] 102 103 are, respectively, the planetocentric longitude and 104 latitude of the ith grid point. 105 106 Units are radians. 107 108 -Detailed_Output 109 110 spoints is an array containing the rectangular (Cartesian) 111 coordinates of the surface points on the target body, 112 expressed relative to the body-fixed reference frame of 113 the target body, corresponding to the input grid points. 114 115 `spoints' should be declared by the caller 116 117 SpiceDouble spoints [npoints][3]; 118 119 120 plateIDs is an array of integer ID codes of the plates on which 121 the surface points are located. The ith plate ID 122 corresponds to the ith surface point. These ID codes can 123 be use to look up data associated with the plate, such 124 as the plate's vertices or outward normal vector. 125 126 `plateIDs' should be declared by the caller 127 128 SpiceInt plateIDs [npoints]; 129 130 -Parameters 131 132 None. 133 134 -Exceptions 135 136 If any of the listed errors occur, the output arguments are 137 left unchanged. 138 139 140 1) If a DSK providing a DSK type 2 plate model has not been 141 loaded prior to calling llgrid_pl02, the error will be 142 diagnosed and signaled by a routine in the call tree of this 143 routine. 144 145 2) If the segment associated with the input DLA descriptor is not 146 of data type 2, the error SPICE(WRONGDATATYPE) is signaled. 147 148 3) If a surface point cannot be computed because the ray corresponding 149 to a longitude/latitude pair fails to intersect the target 150 surface as defined by the plate model, the error 151 SPICE(NOINTERCEPT) is signaled. 152 153 154 -Files 155 156 The following data are required: 157 158 - DSK data: a DSK file containing a plate model representing the 159 target body's surface must be loaded. This kernel must contain 160 a type 2 segment that contains data for the entire surface of 161 the target body. 162 163 In all cases, kernel data are normally loaded once per program 164 run, NOT every time this routine is called. 165 166 -Particulars 167 168 See the headers of the CSPICE routines 169 170 reclat_c 171 latrec_c 172 173 for detailed definitions of Planetocentric coordinates. 174 175 -Examples 176 177 The numerical results shown for this example may differ across 178 platforms. The results depend on the SPICE kernels used as input, 179 the compiler and supporting libraries, and the machine specific 180 arithmetic implementation. 181 182 In the following example program, the file 183 184 phobos.3.3.bds 185 186 is a DSK file containing a type 2 segment that provides a plate model 187 representation of the surface of Phobos. 188 189 Find the surface points on a target body corresponding to a given 190 planetocentric longitude/latitude grid. In order to duplicate 191 the example output, the kernel name 192 193 phobos.3.3.bds 194 195 should be supplied at the prompt. 196 197 198 #include <stdio.h> 199 #include <math.h> 200 #include "SpiceUsr.h" 201 202 int main() 203 { 204 /. 205 Local parameters 206 ./ 207 #define FILSIZ 256 208 #define NAMLEN 33 209 #define NLAT 9 210 #define NLON 9 211 #define MAXGRID ( NLAT * NLON ) 212 #define TOL ( 1.e-12 ) 213 214 /. 215 Local variables 216 ./ 217 SpiceBoolean found; 218 219 SpiceChar dsk [ FILSIZ ]; 220 221 SpiceDLADescr dladsc; 222 223 SpiceDouble grid [ MAXGRID ][2]; 224 SpiceDouble lat; 225 SpiceDouble lon; 226 SpiceDouble spoints [ MAXGRID ][3]; 227 SpiceDouble xlat; 228 SpiceDouble xlon; 229 SpiceDouble xr; 230 231 SpiceInt handle; 232 SpiceInt i; 233 SpiceInt j; 234 SpiceInt n; 235 SpiceInt npoints; 236 SpiceInt plateIDs [ MAXGRID ]; 237 238 239 240 /. 241 Prompt for the name of the DSK to read and the name of 242 the target body. 243 ./ 244 prompt_c ( "Enter DSK name > ", FILSIZ, dsk ); 245 246 /. 247 Open the DSK file for read access. 248 We use the DAS-level interface for 249 this function. 250 ./ 251 dasopr_c ( dsk, &handle ); 252 253 /. 254 Begin a forward search through the 255 kernel, treating the file as a DLA. 256 In this example, it's a very short 257 search. 258 ./ 259 dlabfs_c ( handle, &dladsc, &found ); 260 261 if ( !found ) 262 { 263 /. 264 We arrive here only if the kernel 265 contains no segments. This is 266 unexpected, but we're prepared for it. 267 ./ 268 setmsg_c ( "No segments found in DSK file #."); 269 errch_c ( "#", dsk ); 270 sigerr_c ( "SPICE(NODATA)" ); 271 } 272 273 /. 274 If we made it this far, DLADSC is the 275 DLA descriptor of the first segment. 276 277 Now generate the grid points. We generate 278 points along latitude bands, working from 279 north to south. The latitude range is selected 280 to range from +80 to -80 degrees. Longitude 281 ranges from 0 to 350 degrees. The increment 282 is 20 degrees for latitude and 40 degrees for 283 longitude. 284 ./ 285 286 n = 0; 287 288 for ( i = 0; i < NLAT; i++ ) 289 { 290 lat = rpd_c() * ( 80.0 - 20.0*i ); 291 292 for ( j = 0; j < NLON; j++ ) 293 { 294 lon = rpd_c() * 40.0*j; 295 296 grid[n][0] = lon; 297 grid[n][1] = lat; 298 299 ++n; 300 } 301 } 302 npoints = n - 1; 303 304 /. 305 Find the surface points corresponding to the grid points. 306 ./ 307 llgrid_pl02 ( handle, 308 &dladsc, 309 npoints, 310 (ConstSpiceDouble (*)[2])grid, 311 spoints, 312 plateIDs ); 313 314 /. 315 Print out the surface points in latitudinal 316 coordinates and compare the derived lon/lat values 317 to those of the input grid. 318 ./ 319 for ( i = 0; i < npoints; i++ ) 320 { 321 /. 322 Use recrad_c rather than reclat_c to produce 323 non-negative longitudes. 324 ./ 325 recrad_c ( spoints[i], &xr, &xlon, &xlat ); 326 327 printf ( "\n" 328 "Intercept for grid point %d:\n" 329 " Plate ID: %d\n" 330 " Cartesian Coordinates: (%e %e %e)\n" 331 " Latitudinal Coordinates:\n" 332 " Longitude (deg): %f\n" 333 " Latitude (deg): %f\n" 334 " Radius (km): %f\n" 335 "\n" 336 "Original grid coordinates:\n" 337 " Longitude (deg): %f\n" 338 " Latitude (deg): %f\n" 339 "\n", 340 (int)i, 341 (int)plateIDs[i], 342 spoints[i][0], spoints[i][1], spoints[i][2], 343 xlon * dpr_c(), 344 xlat * dpr_c(), 345 xr, 346 grid[i][0] * dpr_c(), 347 grid[i][1] * dpr_c() ); 348 349 /. 350 Perform sanity checks on the intercept 351 coordinates. Stop the program if any error 352 is larger than our tolerance value. 353 ./ 354 lon = grid[i][0]; 355 lat = grid[i][1]; 356 357 if ( fabs(xlat-lat) > TOL ) 358 { 359 sigerr_c ( "Latitude error!" ); 360 } 361 362 if ( (xlon - lon) > pi_c() ) 363 { 364 xlon -= twopi_c(); 365 } 366 367 if ( (xlon - lon) > TOL ) 368 { 369 sigerr_c ( "Longitude error!" ); 370 } 371 372 } 373 374 /. 375 Close the kernel. This isn't necessary in a stand- 376 alone program, but it's good practice in subroutines 377 because it frees program and system resources. 378 ./ 379 dascls_c ( handle ); 380 381 return ( 0 ); 382 } 383 384 385 When this program was executed on a PC/Linux/gcc platform, 386 the output for the first 3 points (the rest of the output 387 is not shown due to its large volume) was: 388 389 390 Enter DSK name > phobos.3.3.bds 391 392 Intercept for grid point 0: 393 Plate ID: 306238 394 Cartesian Coordinates: (1.520878e+00 -7.129713e-16 8.625327e+00) 395 Latitudinal Coordinates: 396 Longitude (deg): 360.000000 397 Latitude (deg): 80.000000 398 Radius (km): 8.758387 399 400 Original grid coordinates: 401 Longitude (deg): 0.000000 402 Latitude (deg): 80.000000 403 404 405 Intercept for grid point 1: 406 Plate ID: 317112 407 Cartesian Coordinates: (1.189704e+00 9.982799e-01 8.807772e+00) 408 Latitudinal Coordinates: 409 Longitude (deg): 40.000000 410 Latitude (deg): 80.000000 411 Radius (km): 8.943646 412 413 Original grid coordinates: 414 Longitude (deg): 40.000000 415 Latitude (deg): 80.000000 416 417 418 Intercept for grid point 2: 419 Plate ID: 324141 420 Cartesian Coordinates: (2.777752e-01 1.575341e+00 9.072029e+00) 421 Latitudinal Coordinates: 422 Longitude (deg): 80.000000 423 Latitude (deg): 80.000000 424 Radius (km): 9.211980 425 426 Original grid coordinates: 427 Longitude (deg): 80.000000 428 Latitude (deg): 80.000000 429 430 431 432 433 -Restrictions 434 435 1) This routine assumes that the origin of the body-fixed reference 436 frame associated with the target body is located in the interior 437 of that body. 438 439 2) The results returned by this routine may not be meaningful 440 if the target surface has multiple surface points associated 441 with some (longitude, latitude) coordinates. 442 443 -Literature_References 444 445 None. 446 447 -Author_and_Institution 448 449 N.J. Bachman (JPL) 450 451 -Version 452 453 -CSPICE Version 2.0.0, 23-JUL-2016 (NJB) 454 455 Added failed_c calls. 456 457 Include file references have been updated. Now calls 458 zzdsksgr_ instead of dsksgr_. Integer output format 459 in example program has been updated. 460 461 -Beta Version 1.3.0, 30-APR-2014 (NJB) (BVS) 462 463 Now includes dsk_proto.h. 464 465 Last update was 1.2.1, 07-APR-2014 (BVS) 466 467 Changed FRAME to FRAMES in the Required_Reading section. 468 469 -Beta Version 1.2.0, 14-MAY-2010 (NJB) 470 471 Updated for compatibility with new DSK design. 472 DSK name was updated in example program. 473 474 -Beta Version 1.1.0, 09-FEB-2007 (NJB) 475 476 Bug fix: type of local variable fDLADescr was changed to SpiceInt. 477 478 -Beta Version 1.0.0, 06-NOV-2006 (NJB) 479 480 -Index_Entries 481 482 map latitudinal grid to DSK type 2 plate model surface 483 484 -& 485 */ 486 487 { /* Begin llgrid_pl02 */ 488 489 490 /* 491 Prototypes 492 */ 493 494 495 /* 496 Local parameters 497 */ 498 #define CTRIDX 1 499 #define TYPIDX 3 500 501 /* 502 Local variables 503 */ 504 SpiceBoolean found; 505 506 SpiceDouble fDSKDescr [ SPICE_DSK_DSCSIZ ]; 507 SpiceDouble maxrad; 508 SpiceDouble raydir [3]; 509 SpiceDouble scale; 510 SpiceDouble vertex [3]; 511 512 SpiceInt centerID; 513 SpiceInt dataType; 514 SpiceInt fDLADescr [ SPICE_DLA_DSCSIZ ]; 515 SpiceInt i; 516 517 518 /* 519 Participate in error tracing. 520 */ 521 if ( return_c() ) 522 { 523 return; 524 } 525 chkin_c ( "llgrid_pl02" ); 526 527 /* 528 Fetch and examine the DSK descriptor of the segment from which we're 529 getting the shape data. Make sure this is a type 2 segment for the 530 specified target. Since we don't know a priori that the segment 531 has type 2, we can't use the type 2 fetch routine for this operation. 532 Instead, we use the f2c'd version of the Fortran routine dskgd. 533 We must prepare a Fortran-style DLA descriptor in order to call 534 this routine. 535 536 Populate the Fortran DLA descriptor array fCurrent with the contents 537 of the input descriptor. 538 */ 539 fDLADescr[SPICE_DLA_BWDIDX] = dladsc->bwdptr; 540 fDLADescr[SPICE_DLA_FWDIDX] = dladsc->fwdptr; 541 fDLADescr[SPICE_DLA_IBSIDX] = dladsc->ibase; 542 fDLADescr[SPICE_DLA_ISZIDX] = dladsc->isize; 543 fDLADescr[SPICE_DLA_DBSIDX] = dladsc->dbase; 544 fDLADescr[SPICE_DLA_DSZIDX] = dladsc->dsize; 545 fDLADescr[SPICE_DLA_CBSIDX] = dladsc->cbase; 546 fDLADescr[SPICE_DLA_CSZIDX] = dladsc->csize; 547 548 /* 549 Call the f2c'd "get DSK descriptor" routine. 550 */ 551 dskgd_ ( ( integer * ) &handle, 552 ( integer * ) fDLADescr, 553 ( doublereal * ) fDSKDescr ); 554 555 if ( failed_c() ) 556 { 557 chkout_c ( "llgrid_pl02" ); 558 return; 559 } 560 561 /* 562 Extract object ID and DSK data type from the descriptor. 563 */ 564 centerID = (SpiceInt)fDSKDescr[CTRIDX]; 565 dataType = (SpiceInt)fDSKDescr[TYPIDX]; 566 567 568 if ( dataType != 2 ) 569 { 570 setmsg_c ( "Input segment has DSK data type #. A segment of " 571 "type 2 is required." ); 572 errint_c ( "#", dataType ); 573 sigerr_c ( "SPICE(WRONGDATATYPE)" ); 574 chkout_c ( "llgrid_pl02" ); 575 return; 576 } 577 578 /* 579 We're done with error checks on our inputs. 580 581 Get the maximum radius value associated with the target body. 582 We'll use this later to compute a numerically safe ray vertex. 583 */ 584 maxrad = zzdsksgr_ ( fDSKDescr ); 585 586 if ( failed_c() ) 587 { 588 chkout_c ( "llgrid_pl02" ); 589 return; 590 } 591 592 for ( i = 0; i < npoints; i++ ) 593 { 594 /* 595 Find the outward unit vector corresponding to the ith lon/lat pair. 596 Note: longitude comes first! 597 */ 598 latrec_c ( 1.0, grid[i][0], grid[i][1], vertex ); 599 600 vminus_c ( vertex, raydir ); 601 602 /* 603 To avoid numerical problems, we pick a vertex that is guaranteed 604 to be a reasonable distance away from the target's surface. 605 */ 606 scale = maxd_c ( 2, 1.0, 2.0*maxrad ); 607 608 vscl_c ( scale, vertex, vertex ); 609 610 611 /* 612 Find the surface intercept defined by the vertex, ray direction, 613 and surface plate model. 614 */ 615 dskx02_c ( handle, dladsc, vertex, raydir, 616 plateIDs+i, spoints[i], &found ); 617 618 if ( failed_c() ) 619 { 620 chkout_c ( "llgrid_pl02" ); 621 return; 622 } 623 624 if ( !found ) 625 { 626 setmsg_c ( "Ray from vertex number # having longitude # " 627 "and latitude # (radians) to center " 628 "of target # did not intersect the surface " 629 "defined by the input handle and descriptor." ); 630 errint_c ( "#", i ); 631 errdp_c ( "#", grid[i][0] ); 632 errdp_c ( "#", grid[i][1] ); 633 errint_c ( "#", centerID ); 634 sigerr_c ( "SPICE(NOINTERCEPT)" ); 635 chkout_c ( "llgrid_pl02" ); 636 return; 637 } 638 } 639 640 641 /* 642 At this point, `spoints' and `plateIDs' are set. 643 */ 644 645 chkout_c ( "llgrid_pl02" ); 646 647 } /* End llgrid_pl02 */ 648