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