1 /* 2 3 -Procedure srfnrm_c ( Map surface points to outward normal vectors ) 4 5 -Abstract 6 7 Map array of surface points on a specified target body to 8 the corresponding unit length outward surface normal vectors. 9 10 The surface of the target body may be represented by a triaxial 11 ellipsoid or by topographic data provided by DSK files. 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 DSK 41 FRAMES 42 PCK 43 SPK 44 TIME 45 46 -Keywords 47 48 COORDINATES 49 DSK 50 GEOMETRY 51 SURFACE 52 53 */ 54 55 #include "SpiceUsr.h" 56 #include "SpiceZfc.h" 57 #include "SpiceZst.h" 58 #include "SpiceZmc.h" 59 #undef srfnrm_c 60 61 srfnrm_c(ConstSpiceChar * method,ConstSpiceChar * target,SpiceDouble et,ConstSpiceChar * fixref,SpiceInt npts,ConstSpiceDouble srfpts[][3],SpiceDouble normls[][3])62 void srfnrm_c ( ConstSpiceChar * method, 63 ConstSpiceChar * target, 64 SpiceDouble et, 65 ConstSpiceChar * fixref, 66 SpiceInt npts, 67 ConstSpiceDouble srfpts[][3], 68 SpiceDouble normls[][3] ) 69 /* 70 71 -Brief_I/O 72 73 Variable I/O Description 74 -------- --- -------------------------------------------------- 75 method I Computation method. 76 target I Name of target body. 77 et I Epoch in TDB seconds past J2000 TDB. 78 fixref I Body-fixed, body-centered target body frame. 79 npts I Number of surface points in input array. 80 srfpts I Array of surface points. 81 normls O Array of outward, unit length normal vectors. 82 83 SPICE_DSKTOL_PTMEMM 84 P Default point-surface membership margin. 85 86 -Detailed_Input 87 88 89 method is a short string providing parameters defining 90 the computation method to be used. In the syntax 91 descriptions below, items delimited by brackets 92 are optional. 93 94 `method' may be assigned the following values: 95 96 "ELLIPSOID" 97 98 The normal vector computation uses a triaxial 99 ellipsoid to model the surface of the target 100 body. The ellipsoid's radii must be available 101 in the kernel pool. 102 103 104 "DSK/UNPRIORITIZED[/SURFACES = <surface list>]" 105 106 The normal vector computation uses topographic 107 data to model the surface of the target body. 108 These data must be provided by loaded DSK 109 files. 110 111 The surface list specification is optional. The 112 syntax of the list is 113 114 <surface 1> [, <surface 2>...] 115 116 If present, it indicates that data only for the 117 listed surfaces are to be used; however, data 118 need not be available for all surfaces in the 119 list. If absent, loaded DSK data for any surface 120 associated with the target body are used. 121 122 The surface list may contain surface names or 123 surface ID codes. Names containing blanks must 124 be delimited by double quotes, for example 125 126 SURFACES = \"Mars MEGDR 128 PIXEL/DEG\" 127 128 If multiple surfaces are specified, their names 129 or IDs must be separated by commas. 130 131 See the Particulars section below for details 132 concerning use of DSK data. 133 134 135 Neither case nor white space are significant in 136 `method', except within double-quoted strings. For 137 example, the string " eLLipsoid " is valid. 138 139 Within double-quoted strings, blank characters are 140 significant, but multiple consecutive blanks are 141 considered equivalent to a single blank. Case is 142 not significant. So 143 144 "Mars MEGDR 128 PIXEL/DEG" 145 146 is equivalent to 147 148 " mars megdr 128 pixel/deg " 149 150 but not to 151 152 "MARS MEGDR128PIXEL/DEG" 153 154 155 target is the name of the target body. `target' is 156 case-insensitive, and leading and trailing blanks in 157 `target' are not significant. Optionally, you may 158 supply a string containing the integer ID code for 159 the object. For example both "MOON" and "301" are 160 legitimate strings that indicate the Moon is the 161 target body. 162 163 When the target body's surface is represented by a 164 tri-axial ellipsoid, this routine assumes that a 165 kernel variable representing the ellipsoid's radii is 166 present in the kernel pool. Normally the kernel 167 variable would be defined by loading a PCK file. 168 169 170 et is the epoch for which target surface data will be 171 selected, if the surface is modeled using DSK data. 172 In this case, only segments having time coverage that 173 includes the epoch `et' will be used. 174 175 `et' is ignored if the target is modeled as an 176 ellipsoid. 177 178 `et' is expressed as TDB seconds past J2000 TDB. 179 180 181 fixref is the name of a body-fixed reference frame centered 182 on the target body. `fixref' may be any such frame 183 supported by the SPICE system, including built-in 184 frames (documented in the Frames Required Reading) 185 and frames defined by a loaded frame kernel (FK). The 186 string `fixref' is case-insensitive, and leading and 187 trailing blanks in `fixref' are not significant. 188 189 The input surface points in the array `srfpts' are 190 expressed relative to this reference frame, as are 191 the normal vectors computed by this routine. 192 193 194 npts is the number of surface points in the array `srfpts'. 195 196 197 srfpts is an array of target body surface points. Elements 198 199 srfpts[0][i] 200 srfpts[1][i] 201 srfpts[2][i] 202 203 are the Cartesian coordinates, expressed in the 204 reference frame designated by `fixref', of the ith 205 surface point in the array. Each surface point 206 represents an offset from the center of that frame. 207 208 All surface points must actually be "on" the surface, 209 that is, the distance of each point from the surface 210 must be less than a small margin. See the Parameters 211 section below for a description of this margin. 212 213 -Detailed_Output 214 215 normls is an array of unit length, outward normal vectors 216 corresponding to the points in `srfpts'. Elements 217 218 normls[0][i] 219 normls[1][i] 220 normls[2][i] 221 222 are the Cartesian coordinates, expressed in the 223 reference frame designated by `fixref', of the ith 224 normal vector in the array. 225 226 -Parameters 227 228 SPICE_DSKTOL_PTMEMM 229 230 is the default point-surface membership margin. This 231 margin limits the distance an input point can be from 232 a surface and still be considered to lie on that 233 surface. 234 235 The details of the application of 236 237 SPICE_DSKTOL_PTMEMM 238 239 are implementation-dependent. In the DSK case, roughly 240 speaking, a point-surface distance limit within a DSK 241 segment is set to 242 243 SPICE_DSKTOL_PTMEMM * MAXR 244 245 where MAXR is the radius of an outer bounding sphere 246 for the segment. 247 248 For shapes modeled as ellipsoids, the expression 249 above is applied to the maximum radius of the 250 ellipsoid. 251 252 See the header file 253 254 SpiceDtl.h 255 256 for the declaration of SPICE_DSKTOL_PTMEMM. This margin 257 can be overridden. See this header file 258 and the routine dskstl_c for details. 259 260 -Exceptions 261 262 1) If the target body name specified in the input string cannot 263 be converted to an integer ID code, the error 264 SPICE(IDCODENOTFOUND) is signaled. 265 266 2) If the input target body-fixed frame `fixref' is not 267 recognized, the error SPICE(NOFRAME) is signaled. A frame 268 name may fail to be recognized because a required frame 269 specification kernel has not been loaded; another cause is a 270 misspelling of the frame name. 271 272 3) If the input frame `fixref' is not centered at the target body, 273 the error SPICE(INVALIDFRAME) is signaled. 274 275 4) If data are not available to convert between the frame 276 `fixref' and the frame of a DSK segment of interest, the error 277 will be signaled by a routine in the call tree of this 278 routine. 279 280 5) If the input argument `method' cannot be parsed, the error 281 will be signaled either by this routine or by a routine in 282 the call tree of this routine. 283 284 6) If the computation method specifies an ellipsoidal target 285 model, and if triaxial radii of the target body have not been 286 loaded into the kernel pool prior to calling srfnrm_c, the 287 error will be diagnosed and signaled by a routine in the call 288 tree of this routine. 289 290 7) The target must be an extended body: if the computation 291 method specifies an ellipsoidal target model, and if any of 292 the radii of the target body are non-positive, the error will 293 be signaled by routines in the call tree of this routine. 294 295 8) If `method' specifies that the target surface is represented by 296 DSK data, and no DSK files are loaded for the specified 297 target, the error is signaled by a routine in the call tree 298 of this routine. 299 300 9) If `method' specifies that the target surface is represented by 301 DSK data, and data representing the portion of the surface 302 corresponding to the surface points provided in `srfpts' are 303 not available, an error will be signaled by a routine in the 304 call tree of this routine. 305 306 10) If an input surface point is not within a small tolerance 307 of the specified surface, the error SPICE(POINTNOTONSURFACE) 308 is signaled. See the Parameters section for details. 309 310 11) If any input string argument pointer is null, the error 311 SPICE(NULLPOINTER) will be signaled. 312 313 12) If any input string argument is empty, the error 314 SPICE(EMPTYSTRING) will be signaled. 315 316 317 -Files 318 319 Appropriate kernels must be loaded by the calling program before 320 this routine is called. 321 322 The following data are required: 323 324 - Shape data for the target body: 325 326 PCK data: 327 328 If the target shape is modeled as an ellipsoid, 329 triaxial radii for the target body must be loaded into 330 the kernel pool. Typically this is done by loading a 331 text PCK file via furnsh_c. 332 333 DSK data: 334 335 If the target shape is modeled by DSK data, DSK files 336 containing topographic data for the target body must be 337 loaded. If a surface list is specified, data for at 338 least one of the listed surfaces must be loaded. 339 340 - Target body orientation data: these may be provided in a 341 text or binary PCK file. In some cases, target body 342 orientation may be provided by one more more CK files. In 343 either case, data are made available by loading the files 344 via furnsh_c. 345 346 The following data may be required: 347 348 - Frame data: if a frame definition is required to convert 349 between the body-fixed frame of the target and the frame of 350 a DSK segment providing topographic data, that definition 351 must be available in the kernel pool. Typically the 352 definition is supplied by loading a frame kernel via furnsh_c. 353 354 - Surface name-ID associations: if surface names are specified 355 in `method', the association of these names with their 356 corresponding surface ID codes must be established by 357 assignments of the kernel variables 358 359 NAIF_SURFACE_NAME 360 NAIF_SURFACE_CODE 361 NAIF_SURFACE_BODY 362 363 Normally these associations are made by loading a text 364 kernel containing the necessary assignments. An example of 365 such a set of assignments is 366 367 NAIF_SURFACE_NAME += 'Mars MEGDR 128 PIXEL/DEG' 368 NAIF_SURFACE_CODE += 1 369 NAIF_SURFACE_BODY += 499 370 371 - SCLK data: if the target body's orientation is provided by 372 CK files, an associated SCLK kernel must be loaded. 373 374 In all cases, kernel data are normally loaded once per program 375 run, NOT every time this routine is called. 376 377 378 -Particulars 379 380 381 Using DSK data 382 ============== 383 384 DSK loading and unloading 385 ------------------------- 386 387 DSK files providing data used by this routine are loaded by 388 calling furnsh_c and can be unloaded by calling unload_c or 389 KCLEAR. See the documentation of furnsh_c for limits on numbers 390 of loaded DSK files. 391 392 For run-time efficiency, it's desirable to avoid frequent 393 loading and unloading of DSK files. When there is a reason to 394 use multiple versions of data for a given target body---for 395 example, if topographic data at varying resolutions are to be 396 used---the surface list can be used to select DSK data to be 397 used for a given computation. It is not necessary to unload 398 the data that are not to be used. This recommendation presumes 399 that DSKs containing different versions of surface data for a 400 given body have different surface ID codes. 401 402 403 DSK data priority 404 ----------------- 405 406 A DSK coverage overlap occurs when two segments in loaded DSK 407 files cover part or all of the same domain---for example, a 408 given longitude-latitude rectangle---and when the time 409 intervals of the segments overlap as well. 410 411 When DSK data selection is prioritized, in case of a coverage 412 overlap, if the two competing segments are in different DSK 413 files, the segment in the DSK file loaded last takes 414 precedence. If the two segments are in the same file, the 415 segment located closer to the end of the file takes 416 precedence. 417 418 When DSK data selection is unprioritized, data from competing 419 segments are combined. For example, if two competing segments 420 both represent a surface as sets of triangular plates, the 421 union of those sets of plates is considered to represent the 422 surface. 423 424 Currently only unprioritized data selection is supported. 425 Because prioritized data selection may be the default behavior 426 in a later version of the routine, the UNPRIORITIZED keyword is 427 required in the `method' argument. 428 429 430 Syntax of the `method' input argument 431 ------------------------------------- 432 433 The keywords and surface list in the `method' argument 434 are called "clauses." The clauses may appear in any 435 order, for example 436 437 DSK/<surface list>/UNPRIORITIZED 438 DSK/UNPRIORITIZED/<surface list> 439 UNPRIORITIZED/<surface list>/DSK 440 441 The simplest form of the `method' argument specifying use of 442 DSK data is one that lacks a surface list, for example: 443 444 "DSK/UNPRIORITIZED" 445 446 For applications in which all loaded DSK data for the target 447 body are for a single surface, and there are no competing 448 segments, the above string suffices. This is expected to be 449 the usual case. 450 451 When, for the specified target body, there are loaded DSK 452 files providing data for multiple surfaces for that body, the 453 surfaces to be used by this routine for a given call must be 454 specified in a surface list, unless data from all of the 455 surfaces are to be used together. 456 457 The surface list consists of the string 458 459 SURFACES = 460 461 followed by a comma-separated list of one or more surface 462 identifiers. The identifiers may be names or integer codes in 463 string format. For example, suppose we have the surface 464 names and corresponding ID codes shown below: 465 466 Surface Name ID code 467 ------------ ------- 468 "Mars MEGDR 128 PIXEL/DEG" 1 469 "Mars MEGDR 64 PIXEL/DEG" 2 470 "Mars_MRO_HIRISE" 3 471 472 If data for all of the above surfaces are loaded, then 473 data for surface 1 can be specified by either 474 475 "SURFACES = 1" 476 477 or 478 479 "SURFACES = \"Mars MEGDR 128 PIXEL/DEG\"" 480 481 Double quotes are used to delimit the surface name because 482 it contains blank characters. 483 484 To use data for surfaces 2 and 3 together, any 485 of the following surface lists could be used: 486 487 "SURFACES = 2, 3" 488 489 "SURFACES = \"Mars MEGDR 64 PIXEL/DEG\", 3" 490 491 "SURFACES = 2, Mars_MRO_HIRISE" 492 493 "SURFACES = \"Mars MEGDR 64 PIXEL/DEG\", Mars_MRO_HIRISE" 494 495 An example of a `method' argument that could be constructed 496 using one of the surface lists above is 497 498 "DSK/UNPRIORITIZED/SURFACES = \"Mars MEGDR 64 PIXEL/DEG\", 3" 499 500 501 -Examples 502 503 The numerical results shown for this example may differ across 504 platforms. The results depend on the SPICE kernels used as input, 505 the compiler and supporting libraries, and the machine specific 506 arithmetic implementation. 507 508 1) Compute outward normal vectors at surface points on a target 509 body, where the points correspond to a given planetocentric 510 longitude/latitude grid. Use both ellipsoid and DSK shape 511 models. 512 513 Use the meta-kernel shown below to load the required SPICE 514 kernels. 515 516 517 KPL/MK 518 519 File: srfnrm_ex1.tm 520 521 This meta-kernel is intended to support operation of SPICE 522 example programs. The kernels shown here should not be 523 assumed to contain adequate or correct versions of data 524 required by SPICE-based user applications. 525 526 In order for an application to use this meta-kernel, the 527 kernels referenced here must be present in the user's 528 current working directory. 529 530 The names and contents of the kernels referenced 531 by this meta-kernel are as follows: 532 533 File name Contents 534 --------- -------- 535 pck00010.tpc Planet orientation and 536 radii 537 phobos512.bds DSK based on 538 Gaskell ICQ Q=512 539 plate model 540 \begindata 541 542 PATH_SYMBOLS = 'GEN' 543 PATH_VALUES = '/ftp/pub/naif/generic_kernels' 544 545 KERNELS_TO_LOAD = ( '$GEN/pck/pck00010.tpc', 546 '$GEN/dsk/phobos/phobos512.bds' ) 547 \begintext 548 549 550 Example code begins here. 551 552 553 #include <stdio.h> 554 #include "SpiceUsr.h" 555 556 int main() 557 { 558 /. 559 Local constants 560 ./ 561 #define MAXN 10000 562 #define META "srfnrm_ex1.tm" 563 564 /. 565 Local variables 566 ./ 567 SpiceChar * fixref; 568 SpiceChar * method [2]; 569 SpiceChar * target; 570 571 SpiceDouble dlat; 572 SpiceDouble dlon; 573 SpiceDouble et; 574 static SpiceDouble grid [MAXN][2]; 575 SpiceDouble lat; 576 SpiceDouble lat0; 577 SpiceDouble lon; 578 SpiceDouble lon0; 579 static SpiceDouble normls [2][MAXN][3]; 580 SpiceDouble nrmlat; 581 SpiceDouble nrmlon; 582 SpiceDouble nrmrad; 583 static SpiceDouble srfpts [2][MAXN][3]; 584 SpiceDouble xlat; 585 SpiceDouble xlon; 586 SpiceDouble xr; 587 588 SpiceInt i; 589 SpiceInt j; 590 SpiceInt n; 591 SpiceInt nlat; 592 SpiceInt nlon; 593 594 /. 595 Set target, reference frame, and epoch. 596 ./ 597 target = "phobos"; 598 fixref = "iau_phobos"; 599 et = 0.0; 600 601 /. 602 Use both a reference ellipsoid and DSK data 603 to represent the surface. 604 ./ 605 method[0] = "ELLIPSOID"; 606 method[1] = "DSK/UNPRIORITIZED"; 607 608 /. 609 Set the grid dimensions. 610 ./ 611 nlon = 6; 612 nlat = 3; 613 614 /. 615 Derive evenly spaced grid separations and starting 616 values in the longitude and latitude dimensions. 617 Units are degrees. 618 ./ 619 lat0 = 90.0; 620 lon0 = 0.0; 621 622 dlat = 180.0 / (nlat + 1); 623 dlon = 360.0 / nlon; 624 625 /. 626 Load the meta-kernel. 627 ./ 628 furnsh_c ( META ); 629 630 /. 631 Now generate the grid points. We generate 632 points along latitude bands, working from 633 north to south. The latitude range is selected 634 to range from +45 to -45 degrees. Longitude 635 ranges from 0 to 300 degrees. The increment 636 is 45 degrees for latitude and 60 degrees for 637 longitude. 638 ./ 639 640 n = 0; 641 642 for ( i = 0; i < nlat; i++ ) 643 { 644 lat = rpd_c() * ( lat0 - (i+1)*dlat ); 645 646 for ( j = 0; j < nlon; j++ ) 647 { 648 lon = rpd_c() * ( lon0 + j*dlon ); 649 650 grid[n][0] = lon; 651 grid[n][1] = lat; 652 653 ++n; 654 } 655 } 656 657 /. 658 Find the surface points corresponding to the grid points. 659 660 Compute outward normal vectors at the surface points, 661 using both surface representations. 662 ./ 663 for ( i = 0; i < 2; i++ ) 664 { 665 latsrf_c ( method[i], target, et, 666 fixref, n, grid, srfpts[i] ); 667 668 srfnrm_c ( method[i], target, et, 669 fixref, n, srfpts[i], normls[i] ); 670 } 671 672 /. 673 Print out the surface points in latitudinal 674 coordinates and compare the derived lon/lat values 675 to those of the input grid. 676 ./ 677 printf ( "\n" ); 678 679 for ( i = 0; i < n; i++ ) 680 { 681 /. 682 Use recrad_c rather than reclat_c to produce 683 non-negative longitudes. 684 ./ 685 recrad_c ( srfpts[0][i], &xr, &xlon, &xlat ); 686 687 printf ( "\n" 688 "Surface point for grid point %d:\n" 689 " Latitudinal Coordinates:\n" 690 " Longitude (deg): %12.6f\n" 691 " Latitude (deg): %12.6f\n" 692 " Ellipsoid Radius (km): %12.6f\n", 693 (int)i, 694 xlon*dpr_c(), xlat*dpr_c(), xr ); 695 696 recrad_c ( srfpts[1][i], &xr, &xlon, &xlat ); 697 698 printf ( " DSK Radius (km): %12.6f\n", 699 xr ); 700 701 recrad_c ( normls[0][i], &nrmrad, &nrmlon, &nrmlat ); 702 703 printf ( " Ellipsoid normal vector direction:\n" 704 " Longitude (deg): %12.6f\n" 705 " Latitude (deg): %12.6f\n", 706 nrmlon * dpr_c(), 707 nrmlat * dpr_c() ); 708 709 recrad_c ( normls[1][i], &nrmrad, &nrmlon, &nrmlat ); 710 711 printf ( " DSK normal vector direction:\n" 712 " Longitude (deg): %12.6f\n" 713 " Latitude (deg): %12.6f\n", 714 nrmlon * dpr_c(), 715 nrmlat * dpr_c() ); 716 } 717 printf ( "\n" ); 718 return ( 0 ); 719 } 720 721 722 When this program was executed on a PC/Linux/gcc 64-bit platform, 723 the output for the first 3 points (the rest of the output is not 724 shown due to its large volume) was: 725 726 727 Enter meta-kernel name > srfnrm_ex1.tm 728 729 Surface point for grid point 0: 730 Latitudinal Coordinates: 731 Longitude (deg): 0.000000 732 Latitude (deg): 45.000000 733 Ellipsoid Radius (km): 10.542977 734 DSK Radius (km): 10.156402 735 Ellipsoid normal vector direction: 736 Longitude (deg): 0.000000 737 Latitude (deg): 63.895146 738 DSK normal vector direction: 739 Longitude (deg): 341.337568 740 Latitude (deg): 62.610726 741 742 Surface point for grid point 1: 743 Latitudinal Coordinates: 744 Longitude (deg): 60.000000 745 Latitude (deg): 45.000000 746 Ellipsoid Radius (km): 10.172847 747 DSK Radius (km): 10.131412 748 Ellipsoid normal vector direction: 749 Longitude (deg): 66.059787 750 Latitude (deg): 58.877649 751 DSK normal vector direction: 752 Longitude (deg): 48.859884 753 Latitude (deg): 56.924717 754 755 Surface point for grid point 2: 756 Latitudinal Coordinates: 757 Longitude (deg): 120.000000 758 Latitude (deg): 45.000000 759 Ellipsoid Radius (km): 10.172847 760 DSK Radius (km): 10.423766 761 Ellipsoid normal vector direction: 762 Longitude (deg): 113.940213 763 Latitude (deg): 58.877649 764 DSK normal vector direction: 765 Longitude (deg): 118.553200 766 Latitude (deg): 55.906774 767 768 769 -Restrictions 770 771 None. 772 773 -Literature_References 774 775 None. 776 777 -Author_and_Institution 778 779 N.J. Bachman (JPL) 780 781 -Version 782 783 -CSPICE Version 1.0.0, 20-MAR-2016 (NJB) 784 785 -Index_Entries 786 787 map Cartesian surface points to normal vectors 788 compute normal vectors on topographic surface 789 compute normal vectors on dsk surface 790 791 -& 792 */ 793 794 { /* Begin srfnrm_c */ 795 796 797 798 /* 799 Participate in error tracing. 800 */ 801 chkin_c ( "srfnrm_c" ); 802 803 804 /* 805 Check the input string arguments: 806 807 method 808 target 809 fixref 810 811 Make sure each pointer is non-null and each string contains 812 at least one data character: that is, one character 813 preceding the null terminator. 814 */ 815 CHKFSTR ( CHK_STANDARD, "srfnrm_c", method ); 816 CHKFSTR ( CHK_STANDARD, "srfnrm_c", target ); 817 CHKFSTR ( CHK_STANDARD, "srfnrm_c", fixref ); 818 819 820 srfnrm_ ( ( char * ) method, 821 ( char * ) target, 822 ( doublereal * ) &et, 823 ( char * ) fixref, 824 ( integer * ) &npts, 825 ( doublereal * ) srfpts, 826 ( doublereal * ) normls, 827 ( ftnlen ) strlen(method), 828 ( ftnlen ) strlen(target), 829 ( ftnlen ) strlen(fixref) ); 830 831 832 chkout_c ( "srfnrm_c" ); 833 834 } /* End srfnrm_c */ 835