|
JNISpice version 2.0.0 |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectspice.basic.SurfaceIntercept
public class SurfaceIntercept
Class SurfaceIntercept supports ray-target surface intercept computations.
Surface intercept computations are performed by creation of SurfaceIntercept objects. Each SurfaceIntercept instance consists of:
If a surface intercept computation does not find
a point of intersection, an attempt to access a member,
other than the "found" flag, of the
resulting SurfaceIntercept instance will cause a
PointNotFoundException
to be thrown.
For functionality similar to that of the SPICE routine
SINCPT, see the constructor
SurfaceIntercept( String, Body, Time, ReferenceFrame,
AberrationCorrection, Body, ReferenceFrame, Vector3 )
.
For functionality similar to that of the SPICE routine
DSKXV, see the method
create( boolean, Body, Surface[], Time, ReferenceFrame,
Vector3[], Vector3[])
.
For functionality similar to that of the SPICE routine
DSKXSI, see the constructor
SurfaceInterceptWithDSKInfo.SurfaceInterceptWithDSKInfo(
boolean, Body, Surface[], Time, ReferenceFrame,
Vector3, Vector3 )
.
Code examples are provided in the detailed documentation for the constructors and methods.
Appropriate SPICE kernels must be loaded by the calling program before methods of this class are called.
The following data are required:
KernelDatabase.load(java.lang.String)
.
PCK data: If the target body shape is modeled as an ellipsoid, triaxial radii for the target body must be loaded into the kernel pool. Typically this is done by loading a text PCK file via KernelDatabase.load. DSK data: If the target shape is modeled by DSK data, DSK files containing topographic data for the target body must be loaded. If a surface list is specified, data for at least one of the listed surfaces must be loaded.
The following data may be required:
NAIF_SURFACE_NAME NAIF_SURFACE_CODE NAIF_SURFACE_BODY
Normally these associations are made by loading a text kernel containing the necessary assignments. An example of such a set of assignments is
NAIF_SURFACE_NAME += 'Mars MEGDR 128 PIXEL/DEG' NAIF_SURFACE_CODE += 1 NAIF_SURFACE_BODY += 499
Kernel data are normally loaded once per program run, NOT every time a method of this class is called.
DSK loading and unloading
DSK files providing data used by this class are loaded by
calling KernelDatabase.load(java.lang.String)
and can be unloaded by
calling KernelDatabase.unload(java.lang.String)
or
KernelDatabase.clear()
. See the documentation of
KernelDatabase.load(java.lang.String)
for limits on numbers
of loaded DSK files.
For run-time efficiency, it's desirable to avoid frequent
loading and unloading of DSK files. When there is a reason to
use multiple versions of data for a given target body---for
example, if topographic data at varying resolutions are to be
used---the surface list can be used to select DSK data to be
used for a given computation. It is not necessary to unload
the data that are not to be used. This recommendation presumes
that DSKs containing different versions of surface data for a
given body have different surface ID codes.
DSK data priority
A DSK coverage overlap occurs when two segments in loaded DSK files cover part or all of the same domain---for example, a given longitude-latitude rectangle---and when the time intervals of the segments overlap as well.
When DSK data selection is prioritized, in case of a coverage overlap, if the two competing segments are in different DSK files, the segment in the DSK file loaded last takes precedence. If the two segments are in the same file, the segment located closer to the end of the file takes precedence.
When DSK data selection is unprioritized, data from competing segments are combined. For example, if two competing segments both represent a surface as a set of triangular plates, the union of those sets of plates is considered to represent the surface.
Currently only unprioritized data selection is supported. Because prioritized data selection may be the default behavior in a later version of the routine, the UNPRIORITIZED keyword is required in the constructors' `method' arguments.
Access of fields has been changed from private to package private. Added vectorized creation method using arrays of ray vertices and directions as inputs. Added copy constructor. Changed private fields: inputs are now stored in a separate object of an inner class. There are separate inner classes for the different types of intercept methods: FullInputs, RayArrayInputs, and SurfaceInterceptWithDSKInfo.RayInputs.
Field Summary | |
---|---|
static java.lang.String |
ELLIPSOID
|
Constructor Summary | |
---|---|
SurfaceIntercept()
No-arguments constructor. |
|
SurfaceIntercept(java.lang.String method,
Body target,
Time time,
ReferenceFrame fixRef,
AberrationCorrection abcorr,
Body observer,
ReferenceFrame rayRef,
Vector3 rayDir)
Find a specified surface intercept point; create a SurfaceIntercept instance containing the result. |
|
SurfaceIntercept(SurfaceIntercept surfx)
Copy constructor. |
Method Summary | |
---|---|
static SurfaceIntercept[] |
create(boolean prioritized,
Body target,
Surface[] surfList,
Time t,
ReferenceFrame fixref,
Vector3[] rayVertices,
Vector3[] rayDirections)
Vectorized SurfaceIntercept creation method. |
Vector3 |
getIntercept()
Return the surface intercept. |
Vector3 |
getSurfaceVector()
Return the observer to intercept vector. |
TDBTime |
getTargetEpoch()
Return the target epoch. |
boolean |
wasFound()
Indicate whether the intercept was found. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
public static final java.lang.String ELLIPSOID
Constructor Detail |
---|
public SurfaceIntercept()
public SurfaceIntercept(SurfaceIntercept surfx) throws SpiceException
SpiceException
public SurfaceIntercept(java.lang.String method, Body target, Time time, ReferenceFrame fixRef, AberrationCorrection abcorr, Body observer, ReferenceFrame rayRef, Vector3 rayDir) throws SpiceException
The numerical results shown for these examples may differ across platforms. The results depend on the SPICE kernels used as input, the compiler and supporting libraries, and the machine specific arithmetic implementation.
Intercepts are computed using both triaxial ellipsoid and topographic surface models.
The topographic model is based on data from the MGS MOLA DEM megr90n000cb, which has a resolution of 4 pixels/degree. A triangular plate model was produced by computing a 720 x 1440 grid of interpolated heights from this DEM, then tessellating the height grid. The plate model is stored in a type 2 segment in the referenced DSK file.
Use the meta-kernel shown below to load the required SPICE kernels.
KPL/MK File: SurfaceIntercept_ex1.tm This meta-kernel is intended to support operation of SPICE example programs. The kernels shown here should not be assumed to contain adequate or correct versions of data required by SPICE-based user applications. In order for an application to use this meta-kernel, the kernels referenced here must be present in the user's current working directory. The names and contents of the kernels referenced by this meta-kernel are as follows: File name Contents --------- -------- de430.bsp Planetary ephemeris mar097.bsp Mars satellite ephemeris pck00010.tpc Planet orientation and radii naif0011.tls Leapseconds mgs_moc_v20.ti MGS MOC instrument parameters mgs_sclkscet_00061.tsc MGS SCLK coefficients mgs_sc_ext12.bc MGS s/c bus attitude mgs_ext12_ipng_mgs95j.bsp MGS ephemeris megr90n000cb_plate.bds Plate model based on MEGDR DEM, resolution 4 pixels/degree. \begindata KERNELS_TO_LOAD = ( 'de430.bsp', 'mar097.bsp', 'pck00010.tpc', 'naif0012.tls', 'mgs_moc_v20.ti', 'mgs_sclkscet_00061.tsc', 'mgs_sc_ext12.bc', 'mgs_ext12_ipng_mgs95j.bsp', 'megr90n000cb_plate.bds' ) \begintext
Example code begins here.
// // Program SurfaceInterceptEx1 // // Compute surface intercept points on Mars // for the boresight and FOV boundary vectors of the MGS MOC // narrow angle camera. // import spice.basic.*; import static spice.basic.AngularUnits.*; public class SurfaceInterceptEx1 { // // Load SPICE shared library. // static{ System.loadLibrary( "JNISpice" ); } public static void main( String[] args ) throws SpiceException { // // Local constants // final String META = "SurfaceInterceptEx1.tm"; final int NMETH = 2; // // Local variables // AberrationCorrection abcorr = new AberrationCorrection( "CN+S" ); Body obsrvr = new Body( "MGS" ); Body target = new Body( "Mars" ); FOV MOCNACFov; String camnam = "MGS_MOC_NA"; Instrument camera = new Instrument( camnam ); LatitudinalCoordinates latCoords; ReferenceFrame fixref = new ReferenceFrame( "IAU_MARS" ); ReferenceFrame dref; String[] methds = { "Ellipsoid", "DSK/Unprioritized" }; String[] srftyp = { "Ellipsoid", "MGS/MOLA topography, 4 pixel/deg" }; String utc = "2003 OCT 13 06:00:00 UTC"; String title; SurfaceIntercept surfx; TDBTime et; Time trgepc; Vector3[] bounds; Vector3 bsight; Vector3 dvec; Vector3 spoint; Vector3 srfvec; boolean found; double dist; double lat; double lon; double radius; int i; int j; int ncornr; try { // // Load kernels. // KernelDatabase.load( META ); // // Convert the UTC request time to ET (seconds past // J2000, TDB). // et = new TDBTime( utc ); // // Get the MGS MOC Narrow angle camera (MGS_MOC_NA) // field of view (FOV) parameters. // // We'll store the camera-fixed frame in `dref', // the camera boresight vector in `bsight', and the // FOV corner vectors in the array `bounds'. // MOCNACFov = new FOV( camera ); bsight = MOCNACFov.getBoresight(); bounds = MOCNACFov.getBoundary(); ncornr = bounds.length; dref = MOCNACFov.getReferenceFrame(); System.out.format( "%n" + "Surface Intercept Locations for Camera%n" + "FOV Boundary and Boresight Vectors%n" + "%n" + " Instrument: %s%n" + " Epoch: %s%n" + " Aberration correction: %s%n" + "%n", camera.getName(), utc, abcorr.toString() ); // // Now compute and display the surface intercepts for the // boresight and all of the FOV boundary vectors. // for( i = 0; i <= ncornr; i++ ) { if ( i < ncornr ) { title = String.format( "Corner vector %d", (i+1) ); dvec = bounds[i]; } else { title = "Boresight vector"; dvec = bsight; } System.out.format( "%n" + "%s%n", title ); System.out.format( "%n" + " Vector in %s frame = %n", dref.toString() ); System.out.format( " %18.10e %18.10e %18.10e%n", dvec.getElt(0), dvec.getElt(1), dvec.getElt(2) ); System.out.format( "%n" + " Intercept:%n" ); // // Compute the surface intercept point using // the specified aberration corrections. Loop // over the set of computation methods. // for ( j = 0; j < NMETH; j++ ) { surfx = new SurfaceIntercept ( methds[j], target, et, fixref, abcorr, obsrvr, dref, dvec ); if ( surfx.wasFound() ) { // // Compute range from observer to apparent intercept. // srfvec = surfx.getSurfaceVector(); dist = srfvec.norm(); // // Convert rectangular coordinates of the intercept // point `surfx' to planetocentric latitude and longitude. // Convert radians to degrees. // latCoords = new LatitudinalCoordinates(surfx.getIntercept() ); lon = latCoords.getLongitude() * DPR; lat = latCoords.getLatitude() * DPR; radius = latCoords.getRadius(); // // Display the results. // System.out.format ( "%n" + " Surface representation: %s%n" + "%n" + " Radius (km) = %18.10f%n" + " Planetocentric Latitude (deg) = %18.10f%n" + " Planetocentric Longitude (deg) = %18.10f%n" + " Range (km) = %18.10f%n" + "%n", srftyp[j], radius, lat, lon, dist ); } else { System.out.format ( "%n" + "Intercept not found.%n" + "%n" ); } // End of intercept processing for current vector } // End of method loop } // End of vector loop } // End of try block catch ( SpiceException exc ) { exc.printStackTrace(); } } // End of main method }
When this program was executed on a PC/Linux/gcc/64-bit/java 1.5 platform, the output was:
Surface Intercept Locations for Camera FOV Boundary and Boresight Vectors Instrument: MGS_MOC_NA Epoch: 2003 OCT 13 06:00:00 UTC Aberration correction: CN+S Corner vector 1 Vector in MGS_MOC_NA frame = 1.8571383810e-06 -3.8015622659e-03 9.9999277403e-01 Intercept: Surface representation: Ellipsoid Radius (km) = 3384.9411357607 Planetocentric Latitude (deg) = -48.4774823672 Planetocentric Longitude (deg) = -123.4740748197 Range (km) = 388.9830822570 Surface representation: MGS/MOLA topography, 4 pixel/deg Radius (km) = 3387.6408267726 Planetocentric Latitude (deg) = -48.4922595600 Planetocentric Longitude (deg) = -123.4754119350 Range (km) = 386.1451004041 Corner vector 2 Vector in MGS_MOC_NA frame = 1.8571383810e-06 3.8015622659e-03 9.9999277403e-01 Intercept: Surface representation: Ellipsoid Radius (km) = 3384.9396985743 Planetocentric Latitude (deg) = -48.4816367789 Planetocentric Longitude (deg) = -123.3988187487 Range (km) = 388.9751000527 Surface representation: MGS/MOLA topography, 4 pixel/deg Radius (km) = 3387.6403704508 Planetocentric Latitude (deg) = -48.4963866889 Planetocentric Longitude (deg) = -123.4007435481 Range (km) = 386.1361644332 Corner vector 3 Vector in MGS_MOC_NA frame = -1.8571383810e-06 3.8015622659e-03 9.9999277403e-01 Intercept: Surface representation: Ellipsoid Radius (km) = 3384.9396897287 Planetocentric Latitude (deg) = -48.4816623489 Planetocentric Longitude (deg) = -123.3988219550 Range (km) = 388.9746411355 Surface representation: MGS/MOLA topography, 4 pixel/deg Radius (km) = 3387.6403603146 Planetocentric Latitude (deg) = -48.4964120424 Planetocentric Longitude (deg) = -123.4007467292 Range (km) = 386.1357106985 Corner vector 4 Vector in MGS_MOC_NA frame = -1.8571383810e-06 -3.8015622659e-03 9.9999277403e-01 Intercept: Surface representation: Ellipsoid Radius (km) = 3384.9411269138 Planetocentric Latitude (deg) = -48.4775079405 Planetocentric Longitude (deg) = -123.4740779752 Range (km) = 388.9826233195 Surface representation: MGS/MOLA topography, 4 pixel/deg Radius (km) = 3387.6408166345 Planetocentric Latitude (deg) = -48.4922849169 Planetocentric Longitude (deg) = -123.4754150656 Range (km) = 386.1446466486 Boresight vector Vector in MGS_MOC_NA frame = 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 Intercept: Surface representation: Ellipsoid Radius (km) = 3384.9404100069 Planetocentric Latitude (deg) = -48.4795802622 Planetocentric Longitude (deg) = -123.4364497355 Range (km) = 388.9757144062 Surface representation: MGS/MOLA topography, 4 pixel/deg Radius (km) = 3387.6402755068 Planetocentric Latitude (deg) = -48.4943418633 Planetocentric Longitude (deg) = -123.4380804236 Range (km) = 386.1376152656
SpiceException
Method Detail |
---|
public static SurfaceIntercept[] create(boolean prioritized, Body target, Surface[] surfList, Time t, ReferenceFrame fixref, Vector3[] rayVertices, Vector3[] rayDirections) throws SpiceException
The numerical results shown for these examples may differ across platforms. The results depend on the SPICE kernels used as input, the compiler and supporting libraries, and the machine specific arithmetic implementation.
Check intercepts against expected values. Indicate the number of errors, the number of computations, and the number of intercepts found.
Use the meta-kernel shown below to load the required SPICE kernels.
KPL/MK File: SurfaceInterceptCreateEx1.tm This meta-kernel is intended to support operation of SPICE example programs. The kernels shown here should not be assumed to contain adequate or correct versions of data required by SPICE-based user applications. In order for an application to use this meta-kernel, the kernels referenced here must be present in the user's current working directory. The names and contents of the kernels referenced by this meta-kernel are as follows: File name Contents --------- -------- phobos512.bds DSK based on Gaskell ICQ Q=512 plate model \begindata PATH_SYMBOLS = 'GEN' PATH_VALUES = '/ftp/pub/naif/generic_kernels/dsk' KERNELS_TO_LOAD = ( '$GEN/phobos/phobos512.bds' ) \begintext
Example code begins here.
// // Program SurfaceInterceptCreateEx1 // import java.util.ArrayList; import spice.basic.*; import static spice.basic.AngularUnits.*; // //Multi-segment, vectorized spear program. // //
This program computes surface intercepts of rays emanating from a set of // vertices distributed on a longitude-latitude grid. All // vertices are outside the target body, and all rays point // toward the target's center. // //
The program checks intercepts against expected values. It reports the // number of errors, the number of computations, and the // number of intercepts found. // //
This program expects all loaded DSKs // to represent the same body and surface. // //
Syntax: java -Djava.library.path=
// SurfaceInterceptCreateEx1 // public class SurfaceInterceptCreateEx1 { // // Load SPICE shared library. // static{ System.loadLibrary( "JNISpice" ); } public static void main( String[] args ) throws SpiceException { // // Local constants // final double DTOL = 1.0e-14; final double SML = 1.0e-12; final int MAXN = 100000; final int MAXSRF = 100; // // Local variables // Body target; DLADescriptor dladsc; DSK dsk; DSKDescriptor dskdsc; LatitudinalCoordinates vtxLatCoords; LatitudinalCoordinates xptLatCoords; LatitudinalCoordinates xxLatCoords; ReferenceFrame fixref; String DSKName; String meta; Surface[] srflst; SurfaceIntercept[] surfxArr; TDBTime et; Vector3[] dirArr; Vector3[] rayVertices; Vector3[] rayDirections; Vector3[] vtxArr; Vector3 xpt; Vector3 xxpt; boolean prioritized = false; double d; double lat; double latstp; double lon; double lonstp; double polmrg; double r; double[] timcov; double[] xptArr; double[] xhitArr; int bodyid; int framid; int i; int latix; int lonix; int nderr; int nhits; int nlat; int nlon; int nrays; int nstep; int nsurf; int nvals; int surfid; try { // // Get meta-kernel name. // if ( args.length != 1 ) { System.out.println( "Command syntax: " + "SurfaceInterceptCreateEx1 " ); return; } meta = args[0]; // // Load kernels. // KernelDatabase.load( meta ); // // Open the first (according to load order) loaded DSK, // then find the first segment and extract the body and // surface IDs. // DSKName = KernelDatabase.getFileName( 0, "DSK" ); dsk = DSK.openForRead( DSKName ); dladsc = dsk.beginForwardSearch(); dskdsc = dsk.getDSKDescriptor( dladsc ); bodyid = dskdsc.getCenterID(); target = new Body( bodyid ); surfid = dskdsc.getSurfaceID(); framid = dskdsc.getFrameID(); fixref = new ReferenceFrame( framid ); // // Set the DSK data look-up time to the midpoint of // the time coverage of the segment we just looked up. // timcov = dskdsc.getTimeBounds(); et = new TDBTime( ( timcov[0] + timcov[1] ) / 2 ); // // Set the magnitude of the ray vertices. Use a large // number to ensure the vertices are outside of // any realistic target. // r = 1.0e10; // // Spear the target with rays pointing toward // the origin. Use a grid of ray vertices // located on a sphere enclosing the target. // // The variable `polmrg' ("pole margin") can // be set to a small positive value to reduce // the number of intercepts done at the poles. // This may speed up the computation for // the multi-segment case, since rays parallel // to the Z axis will cause all segments converging // at the pole of interest to be tested for an // intersection. // polmrg = 0.5; latstp = 1.0; lonstp = 2.0; nlat = (int)( (180.0 + SML) / latstp ) + 1; nlon = (int)( (360.0 + SML) / lonstp ); nhits = 0; nderr = 0; lon = -180.0; lat = 90.0; lonix = 0; latix = 0; nrays = nlat * nlon; vtxArr = new Vector3[nrays]; dirArr = new Vector3[nrays]; // // Generate rays. // i = 0; while ( lonix < nlon ) { lon = lonix * lonstp; while ( latix < nlat ) { if ( lonix == 0 ) { lat = 90.0 - latix*latstp; } else { if ( latix == 0 ) { lat = 90.0 - polmrg; } else if ( latix == nlat-1 ) { lat = -90.0 + polmrg; } else { lat = 90.0 - latix*latstp; } } vtxLatCoords = new LatitudinalCoordinates( r, lon*RPD, lat*RPD ); vtxArr[i] = vtxLatCoords.toRectangular(); dirArr[i] = vtxArr[i].negate(); ++ i; ++ latix; } ++lonix; latix = 0; } // // Assign surface ID list. // // We assume all DSK files referenced in the // meta-kernel have the same body and surface IDs. // We could check this using the DSK coverage routines, // but for brevity, we won't do so here. We'll create // a trivial surface list containing the surface from // the first segment of the first loaded DSK file. // nsurf = 1; srflst = new Surface[nsurf]; srflst[0] = new Surface( surfid, target ); System.out.println ( "Computing intercepts..." ); surfxArr = SurfaceIntercept.create ( prioritized, target, srflst, et, fixref, vtxArr, dirArr ); System.out.println ( "Done." ); // // Check results. // for ( i = 0; i < nrays; i++ ) { // // Recover the vertex longitude and latitude. These // values will be used to generate diagnostic messages, // if necessary. // vtxLatCoords = new LatitudinalCoordinates( vtxArr[i] ); lon = vtxLatCoords.getLongitude() * DPR; lat = vtxLatCoords.getLatitude() * DPR; if ( surfxArr[i].wasFound() ) { // // Record the fact that a new intercept was found. // ++ nhits; // // Compute the latitude and longitude of // the intercept. Make sure these agree // well with those of the vertex. // xpt = surfxArr[i].getIntercept(); xptLatCoords = new LatitudinalCoordinates( xpt ); // // Recover the vertex longitude and latitude. Generate // a new point having these coordinates and radius equal // to that of xpt. // vtxLatCoords = new LatitudinalCoordinates( vtxArr[i] ); xxLatCoords = new LatitudinalCoordinates( xptLatCoords.getRadius(), vtxLatCoords.getLongitude(), vtxLatCoords.getLatitude() ); // // Compute the distance between the intercept and the // point having latitude and longitude of the ray's vertex, // and radius equal to the radius of the intercept. // xxpt = xxLatCoords.toRectangular(); d = xpt.dist( xxpt ); if ( d/r > DTOL ) { xptArr = xpt.toArray(); xhitArr = xxpt.toArray(); System.out.format ( "===========================%n" ); System.out.format ( "Lon = %f; Lat = %f%n", lon, lat ); System.out.format ( "Bad intercept%n" ); System.out.format ( "Distance error = %e%n", d ); System.out.format ( "xpt = (%e %e %e)%n", xptArr[0], xptArr[1], xptArr[2] ); System.out.format ( "xhitArr = (%e %e %e)%n", xhitArr[0], xhitArr[1], xhitArr[2] ); ++ nderr; } } else { // // Missing the target entirely is a fatal error. // // This is true only for this program, not in // general. For example, if the target shape is // a torus, many rays would miss the target. System.out.format ( "===========================%n" ); System.out.format ( "Lon = %f; Lat = %f%n", lon, lat ); System.out.format ( "No intercept%n" ); return; } } System.out.format( "nrays = %d%n", nrays ); System.out.format( "nhits = %d%n", nhits ); System.out.format( "nderr = %d%n", nderr ); } // End of try block catch ( SpiceException exc ) { exc.printStackTrace(); } } // End of main }
When this program was executed on a PC/Linux/gcc/64-bit/java 1.5 platform, using the meta-kernel shown above, the output was:
Computing intercepts... Done. nrays = 32580 nhits = 32580 nderr = 0
SpiceException
public boolean wasFound()
public Vector3 getIntercept() throws PointNotFoundException, SpiceException
PointNotFoundException
SpiceException
public TDBTime getTargetEpoch() throws PointNotFoundException, SpiceException
PointNotFoundException
SpiceException
public Vector3 getSurfaceVector() throws PointNotFoundException, SpiceException
PointNotFoundException
SpiceException
|
JNISpice version 2.0.0 |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |