10 using namespace boost::numeric::ublas;
 
   19   SurfacePoint::SurfacePoint() {
 
   30     if(other.p_majorAxis) {
 
   31       p_majorAxis = 
new Distance(*other.p_majorAxis);
 
   37     if(other.p_minorAxis) {
 
   38       p_minorAxis = 
new Distance(*other.p_minorAxis);
 
   44     if(other.p_polarAxis) {
 
   45       p_polarAxis = 
new Distance(*other.p_polarAxis);
 
   73       p_rectCovar = 
new symmetric_matrix<double, upper>(*other.
p_rectCovar);
 
   80       p_sphereCovar = 
new symmetric_matrix<double, upper>(*other.
p_sphereCovar);
 
  100     SetSphericalPoint(lat, lon, radius);
 
  125     SetSpherical(lat, lon, radius, latSigma, lonSigma, radiusSigma);
 
  135       const Distance &radius, 
const symmetric_matrix<double, upper> &covar) {
 
  139     SetSpherical(lat, lon, radius, covar);
 
  155     SetRectangular(x, y, z);
 
  179     SetRectangular(x, y, z, xSigma, ySigma, zSigma);
 
  193       const Displacement &z, 
const symmetric_matrix<double, upper> &covar) {
 
  197     SetRectangular(x, y, z, covar);
 
  205   SurfacePoint::~SurfacePoint() {
 
  206     FreeAllocatedMemory();
 
  214   void SurfacePoint::InitCovariance() {
 
  216     p_sphereCovar = NULL;
 
  224   void SurfacePoint::InitPoint() {
 
  234   void SurfacePoint::InitRadii() {
 
  257       IString msg = 
"x, y, and z must be set to valid displacements.  One or " 
  258         "more coordinates have been set to an invalid displacement.";
 
  302     SetRectangularPoint(x, y, z);
 
  305       SetRectangularSigmas(xSigma, ySigma, zSigma);
 
  321                                     const symmetric_matrix<double,upper>& covar) {
 
  322     SetRectangularPoint(x, y, z);
 
  323     SetRectangularMatrix(covar);
 
  335   void SurfacePoint::SetRectangularSigmas(
const Distance &xSigma,
 
  340       IString msg = 
"x sigma, y sigma , and z sigma must be set to valid " 
  341         "distances.  One or more sigmas have been set to an invalid distance.";
 
  345     symmetric_matrix<double,upper> covar(3);
 
  350     SetRectangularMatrix(covar);
 
  361   void SurfacePoint::SetRectangularMatrix(
 
  362        const symmetric_matrix<double, upper> &covar) {
 
  365       IString msg = 
"A point must be set before a variance/covariance matrix " 
  371       *p_rectCovar = covar;
 
  374       p_rectCovar = 
new symmetric_matrix<double, upper>(covar);
 
  377     SpiceDouble rectMat[3][3];
 
  380     double x2  = p_x->meters() * p_x->meters();
 
  381     double y2  = p_y->meters() * p_y->meters();
 
  382     double z   = p_z->meters();
 
  383     double radius = sqrt(x2 + y2 + z*z);
 
  386     rectMat[0][0] = covar(0,0);
 
  387     rectMat[0][1] = rectMat[1][0] = covar(0,1);
 
  388     rectMat[0][2] = rectMat[2][0] = covar(0,2);
 
  389     rectMat[1][1] = covar(1,1);
 
  390     rectMat[1][2] = rectMat[2][1] = covar(1,2);
 
  391     rectMat[2][2] = covar(2,2);
 
  395     double zOverR = p_z->meters() / radius;
 
  396     double r2 = radius*radius;
 
  397     double denom = r2*radius*sqrt(1.0 - (zOverR*zOverR));
 
  398     J[0][0] = -p_x->meters() * p_z->meters() / denom;
 
  399     J[0][1] = -p_y->meters() * p_z->meters() / denom;
 
  400     J[0][2] = (r2 - p_z->meters() * p_z->meters()) / denom;
 
  401     J[1][0] = -p_y->meters() / (x2 + y2);
 
  402     J[1][1] = p_x->meters() / (x2 + y2);
 
  404     J[2][0] = p_x->meters() / radius;
 
  405     J[2][1] = p_y->meters() / radius;
 
  406     J[2][2] = p_z->meters() / radius;
 
  409       p_sphereCovar = 
new symmetric_matrix<double, upper>(3);
 
  411     SpiceDouble mat[3][3];
 
  412     mxm_c (J, rectMat, mat);
 
  413     mxmt_c (mat, J, mat);
 
  414     (*p_sphereCovar)(0,0) = mat[0][0];
 
  415     (*p_sphereCovar)(0,1) = mat[0][1];
 
  416     (*p_sphereCovar)(0,2) = mat[0][2];
 
  417     (*p_sphereCovar)(1,1) = mat[1][1];
 
  418     (*p_sphereCovar)(1,2) = mat[1][2];
 
  419     (*p_sphereCovar)(2,2) = mat[2][2];
 
  434   void SurfacePoint::SetSphericalPoint(
const Latitude  &lat,
 
  439       IString msg = 
"Latitude, longitude, or radius is an invalid value.";
 
  443     SpiceDouble dlat = (double) lat.
radians();
 
  444     SpiceDouble dlon = (double) lon.
radians();
 
  448     latrec_c ( dradius, dlon, dlat, rect);
 
  450     SetRectangularPoint(
Displacement(rect[0], Displacement::Kilometers),
 
  472     SetSphericalPoint(lat, lon, radius);
 
  475       SetSphericalSigmas(latSigma, lonSigma, radiusSigma);
 
  489       const Distance &radius, 
const symmetric_matrix<double, upper> &covar) {
 
  490     SetSphericalPoint(lat, lon, radius);
 
  491     SetSphericalMatrix(covar);
 
  503   void SurfacePoint::SetSphericalCoordinates(
const Latitude &lat,
 
  506       SetSphericalPoint(lat, lon, radius);
 
  517   void SurfacePoint::SetSphericalSigmas(
const Angle &latSigma,
 
  518                                         const Angle &lonSigma,
 
  521       symmetric_matrix<double,upper> covar(3);
 
  524       double sphericalCoordinate;
 
  525       sphericalCoordinate = (double) latSigma.
radians();
 
  526       covar(0,0) =  sphericalCoordinate*sphericalCoordinate;
 
  527       sphericalCoordinate = (double) lonSigma.
radians();
 
  528       covar(1,1) = sphericalCoordinate*sphericalCoordinate;
 
  529       sphericalCoordinate = (double) radiusSigma.
meters();
 
  530       covar(2,2) = sphericalCoordinate*sphericalCoordinate;
 
  532       SetSphericalMatrix(covar);
 
  535       delete p_sphereCovar;
 
  536       p_sphereCovar = NULL;
 
  555   void SurfacePoint::SetSphericalSigmasDistance(
const Distance &latSigma,
 
  558     if (!p_majorAxis || !p_minorAxis || !p_polarAxis || !p_majorAxis->isValid() ||
 
  559         !p_minorAxis->isValid() || !p_polarAxis->isValid()) {
 
  560       IString msg = 
"In order to use sigmas in meter units, the equitorial " 
  561         "radius must be set with a call to SetRadii or an appropriate " 
  567       IString msg = 
"Cannot set spherical sigmas on an invalid surface point";
 
  571     double scaledLatSig = latSigma / *p_majorAxis;
 
  572     double scaledLonSig = lonSigma * cos((
double)GetLatitude().radians())
 
  574     SetSphericalSigmas( 
Angle(scaledLatSig, Angle::Radians),
 
  575                         Angle(scaledLonSig, Angle::Radians), radiusSigma);
 
  586   void SurfacePoint::SetSphericalMatrix(
 
  587      const symmetric_matrix<double, upper> & covar) {
 
  591       IString msg = 
"A point must be set before a variance/covariance matrix " 
  597       *p_sphereCovar = covar;
 
  600       p_sphereCovar = 
new symmetric_matrix<double, upper>(covar);
 
  603     SpiceDouble sphereMat[3][3];
 
  605     sphereMat[0][0] = covar(0,0);
 
  606     sphereMat[0][1] = sphereMat[1][0] = covar(0,1);
 
  607     sphereMat[0][2] = sphereMat[2][0] = covar(0,2);
 
  608     sphereMat[1][1] = covar(1,1);
 
  609     sphereMat[1][2] = sphereMat[2][1] = covar(1,2);
 
  610     sphereMat[2][2] = covar(2,2);
 
  617     double lat = (double) GetLatitude().radians();
 
  618     double lon = (double) GetLongitude().radians();
 
  619     double radius = (double) GetLocalRadius().meters();
 
  623     double cosPhi = cos(lat);
 
  624     double sinPhi = sin(lat);
 
  625     double cosLamda = cos(lon);
 
  626     double sinLamda = sin(lon);
 
  627     double rcosPhi = radius*cosPhi;
 
  628     double rsinPhi = radius*sinPhi;
 
  629     J[0][0] = -rsinPhi * cosLamda;
 
  630     J[0][1] = -rcosPhi * sinLamda;
 
  631     J[0][2] = cosPhi * cosLamda;
 
  632     J[1][0] = -rsinPhi * sinLamda;
 
  633     J[1][1] = rcosPhi * cosLamda;
 
  634     J[1][2] = cosPhi * sinLamda;
 
  640       p_rectCovar = 
new symmetric_matrix<double, upper>(3);
 
  642     SpiceDouble mat[3][3];
 
  643     mxm_c (J, sphereMat, mat);
 
  644     mxmt_c (mat, J, mat);
 
  646     (*p_rectCovar)(0,0) = mat[0][0];
 
  647     (*p_rectCovar)(0,1) = mat[0][1];
 
  648     (*p_rectCovar)(0,2) = mat[0][2];
 
  649     (*p_rectCovar)(1,1) = mat[1][1];
 
  650     (*p_rectCovar)(1,2) = mat[1][2];
 
  651     (*p_rectCovar)(2,2) = mat[2][2];
 
  668   void SurfacePoint::ToNaifArray(
double naifOutput[3])
 const {
 
  670       naifOutput[0] = p_x->kilometers();
 
  671       naifOutput[1] = p_y->kilometers();
 
  672       naifOutput[2] = p_z->kilometers();
 
  675       IString msg = 
"Cannot convert an invalid surface point to a naif array";
 
  689   void SurfacePoint::FromNaifArray(
const double naifValues[3]) {
 
  690     if(p_x && p_y && p_z) {
 
  691       p_x->setKilometers(naifValues[0]);
 
  692       p_y->setKilometers(naifValues[1]);
 
  693       p_z->setKilometers(naifValues[2]);
 
  696       p_x = 
new Displacement(naifValues[0], Displacement::Kilometers);
 
  697       p_y = 
new Displacement(naifValues[1], Displacement::Kilometers);
 
  698       p_z = 
new Displacement(naifValues[2], Displacement::Kilometers);
 
  710   void SurfacePoint::SetRadii(
const Distance &majorRadius,
 
  717       IString msg = 
"Radii must be set to valid distances.  One or more radii " 
  718         "have been set to an invalid distance.";
 
  723       *p_majorAxis = majorRadius;
 
  726       p_majorAxis = 
new Distance(majorRadius);
 
  730       *p_minorAxis = minorRadius;
 
  733       p_minorAxis = 
new Distance(minorRadius);
 
  737       *p_polarAxis = polarRadius;
 
  740       p_polarAxis = 
new Distance(polarRadius);
 
  751   void SurfacePoint::ResetLocalRadius(
const Distance &radius) {
 
  754       IString msg = 
"Radius value must be a valid Distance.";
 
  758     if (!p_x || !p_y || !p_z || !p_x->isValid() || !p_y->isValid() ||
 
  760         IString msg = 
"In order to reset the local radius, a Surface Point must " 
  765     SpiceDouble lat = (double) GetLatitude().radians();
 
  766     SpiceDouble lon = (double) GetLongitude().radians();
 
  768     latrec_c ((SpiceDouble) radius.
kilometers(), lon, lat, rect);
 
  769     p_x->setKilometers(rect[0]);
 
  770     p_y->setKilometers(rect[1]);
 
  771     p_z->setKilometers(rect[2]);
 
  779   bool SurfacePoint::Valid()
 const {
 
  780     static const Displacement zero(0, Displacement::Meters);
 
  781     return p_x && p_y && p_z && p_x->isValid() && p_y->isValid() && p_z->isValid() &&
 
  782            (*p_x != zero || *p_y != zero || *p_z != zero);
 
  786   Displacement SurfacePoint::GetX()
 const {
 
  787     if(!p_x) 
return Displacement();
 
  793   Displacement SurfacePoint::GetY()
 const {
 
  794     if(!p_y) 
return Displacement();
 
  800   Displacement SurfacePoint::GetZ()
 const {
 
  801     if(!p_z) 
return Displacement();
 
  807   Distance SurfacePoint::GetXSigma()
 const {
 
  808     if(!p_rectCovar) 
return Distance();
 
  810     return Distance(sqrt((*p_rectCovar)(0, 0)), Distance::Meters);
 
  814   Distance SurfacePoint::GetYSigma()
 const {
 
  815     if(!p_rectCovar) 
return Distance();
 
  817     return Distance(sqrt((*p_rectCovar)(1, 1)), Distance::Meters);
 
  821   Distance SurfacePoint::GetZSigma()
 const {
 
  822     if(!p_rectCovar) 
return Distance();
 
  824     return Distance(sqrt((*p_rectCovar)(2, 2)), Distance::Meters);
 
  828   symmetric_matrix<double, upper> SurfacePoint::GetRectangularMatrix()
 
  831       symmetric_matrix<double, upper> tmp(3);
 
  840   Angle SurfacePoint::GetLatSigma()
 const {
 
  844     return Angle(sqrt((*p_sphereCovar)(0, 0)), Angle::Radians);
 
  848   Angle SurfacePoint::GetLonSigma()
 const {
 
  852     return Angle(sqrt((*p_sphereCovar)(1, 1)), Angle::Radians);
 
  865       double x = p_x->meters();
 
  866       double y = p_y->meters();
 
  867       double z = p_z->meters();
 
  869       if (x != 0.  ||  y != 0.  || z != 0.)
 
  870         return Latitude(atan2(z, sqrt(x*x + y*y) ), Angle::Radians);
 
  884       double x = p_x->meters();
 
  885       double y = p_y->meters();
 
  887       if(x == 0.0 && y == 0.0) {
 
  891       double lon = atan2(y, x);
 
  908       double x = p_x->meters();
 
  909       double y = p_y->meters();
 
  910       double z = p_z->meters();
 
  912       return Distance(sqrt(x*x + y*y + z*z), Distance::Meters);
 
  920     Distance SurfacePoint::GetLatSigmaDistance()
 const {
 
  924         Angle latSigma = GetLatSigma();
 
  927           if (!p_majorAxis || !p_majorAxis->isValid()) {
 
  928             IString msg = 
"In order to calculate sigmas in meter units, the " 
  929               "equitorial radius must be set with a call to SetRadii.";
 
  934           latSigmaDistance = latSigma.
radians() * *p_majorAxis;
 
  938       return latSigmaDistance;
 
  946   Distance SurfacePoint::GetLonSigmaDistance()
 const {
 
  950       Angle lonSigma = GetLonSigma();
 
  953         if (!p_majorAxis || !p_majorAxis->isValid()) {
 
  954           IString msg = 
"In order to calculate sigmas in meter units, the " 
  955             "equitorial radius must be set with a call to SetRadii.";
 
  960         double scaler = cos(lat.
radians());
 
  964           lonSigmaDistance = lonSigma.
radians() * *p_majorAxis / scaler;
 
  968     return lonSigmaDistance;
 
  972   Distance SurfacePoint::GetLocalRadiusSigma()
 const {
 
  976     return Distance(sqrt((*p_sphereCovar)(2, 2)), Distance::Meters);
 
  980   symmetric_matrix<double, upper> SurfacePoint::GetSphericalMatrix()
 const {
 
  982       symmetric_matrix<double, upper> tmp(3);
 
  987     return *p_sphereCovar;
 
  996   double SurfacePoint::GetLatWeight()
 const {
 
  997     double dlatSigma = GetLatSigma().radians();
 
  999       if( dlatSigma <= 0.0 ) {
 
 1000           IString msg = 
"SurfacePoint::GetLatWeight(): Sigma <= 0.0";
 
 1004       return 1.0/(dlatSigma*dlatSigma);
 
 1012   double SurfacePoint::GetLonWeight()
 const {
 
 1013     double dlonSigma = GetLonSigma().radians();
 
 1015         if( dlonSigma <= 0.0 ) {
 
 1016             IString msg = 
"SurfacePoint::GetLonWeight(): Sigma <= 0.0";
 
 1020         return 1.0/(dlonSigma*dlonSigma);
 
 1028   double SurfacePoint::GetLocalRadiusWeight()
 const {
 
 1030     double dlocalRadiusSigma = GetLocalRadiusSigma().kilometers();
 
 1032         if (dlocalRadiusSigma <= 0.0 ) {
 
 1033             IString msg = 
"SurfacePoint::GetRadWeight(): Sigma <= 0.0";
 
 1037         return 1.0/(dlocalRadiusSigma*dlocalRadiusSigma);
 
 1047     if(p_majorAxis || p_minorAxis || p_polarAxis ||
 
 1048        other.p_majorAxis || other.p_minorAxis || other.p_polarAxis) {
 
 1049       IString msg = 
"SurfacePoint::GetDistanceToPoint not yet implemented for " 
 1054     if(!Valid() || !other.Valid())
 
 1057     return GetDistanceToPoint(other,
 
 1070       const Distance &sphereRadius)
 const {
 
 1071     if(!Valid() || !other.Valid())
 
 1075     const Angle &latitude = GetLatitude();
 
 1076     const Angle &longitude = GetLongitude();
 
 1082     Angle deltaLat = latitude - otherLatitude;
 
 1083     Angle deltaLon = longitude - otherLongitude;
 
 1085     double haversinLat = sin(deltaLat.
radians() / 2.0);
 
 1086     haversinLat *= haversinLat;
 
 1088     double haversinLon = sin(deltaLon.
radians() / 2.0);
 
 1089     haversinLon *= haversinLon;
 
 1091     double a = haversinLat + cos(latitude.
radians()) *
 
 1092                cos(otherLatitude.radians()) *
 
 1095     double c = 2 * atan(sqrt(a) / sqrt(1 - a));
 
 1097     return sphereRadius * c;
 
 1101   bool SurfacePoint::operator==(
const SurfacePoint &other)
 const {
 
 1104     if(equal && p_x && p_y && p_z && other.p_x && other.p_y && other.p_z) {
 
 1105       equal = equal && *p_x == *other.p_x;
 
 1106       equal = equal && *p_y == *other.p_y;
 
 1107       equal = equal && *p_z == *other.p_z;
 
 1110       equal = equal && p_x == NULL && other.p_x == NULL;
 
 1111       equal = equal && p_y == NULL && other.p_y == NULL;
 
 1112       equal = equal && p_z == NULL && other.p_z == NULL;
 
 1115     if(equal && p_majorAxis && p_minorAxis && p_polarAxis) {
 
 1116       equal = equal && *p_majorAxis == *other.p_majorAxis;
 
 1117       equal = equal && *p_minorAxis == *other.p_minorAxis;
 
 1118       equal = equal && *p_polarAxis == *other.p_polarAxis;
 
 1121       equal = equal && p_majorAxis == NULL && other.p_majorAxis == NULL;
 
 1122       equal = equal && p_minorAxis == NULL && other.p_minorAxis == NULL;
 
 1123       equal = equal && p_polarAxis == NULL && other.p_polarAxis == NULL;
 
 1126     if(equal && p_rectCovar) {
 
 1127       equal = equal && (*p_rectCovar)(0, 0) == (*other.
p_rectCovar)(0, 0);
 
 1128       equal = equal && (*p_rectCovar)(0, 1) == (*other.
p_rectCovar)(0, 1);
 
 1129       equal = equal && (*p_rectCovar)(0, 2) == (*other.
p_rectCovar)(0, 2);
 
 1130       equal = equal && (*p_rectCovar)(1, 1) == (*other.
p_rectCovar)(1, 1);
 
 1131       equal = equal && (*p_rectCovar)(1, 2) == (*other.
p_rectCovar)(1, 2);
 
 1132       equal = equal && (*p_rectCovar)(2, 2) == (*other.
p_rectCovar)(2, 2);
 
 1135       equal = equal && p_rectCovar == NULL && other.
p_rectCovar == NULL;
 
 1138     if(equal && p_sphereCovar) {
 
 1139       equal = equal && (*p_sphereCovar)(0, 0) == (*other.
p_sphereCovar)(0, 0);
 
 1140       equal = equal && (*p_sphereCovar)(0, 1) == (*other.
p_sphereCovar)(0, 1);
 
 1141       equal = equal && (*p_sphereCovar)(0, 2) == (*other.
p_sphereCovar)(0, 2);
 
 1142       equal = equal && (*p_sphereCovar)(1, 1) == (*other.
p_sphereCovar)(1, 1);
 
 1143       equal = equal && (*p_sphereCovar)(1, 2) == (*other.
p_sphereCovar)(1, 2);
 
 1144       equal = equal && (*p_sphereCovar)(2, 2) == (*other.
p_sphereCovar)(2, 2);
 
 1147       equal = equal && p_sphereCovar == NULL && other.
p_sphereCovar == NULL;
 
 1153   SurfacePoint &SurfacePoint::operator=(
const SurfacePoint &other) {
 
 1156     if(p_x && other.p_x &&
 
 1159        !p_majorAxis && !other.p_majorAxis &&
 
 1160        !p_minorAxis && !other.p_minorAxis &&
 
 1161        !p_polarAxis && !other.p_polarAxis &&
 
 1162        !p_rectCovar && !other.p_rectCovar &&
 
 1163        !p_sphereCovar && !other.p_sphereCovar) {
 
 1169       FreeAllocatedMemory();
 
 1170       if(other.p_majorAxis) {
 
 1171         p_majorAxis = 
new Distance(*other.p_majorAxis);
 
 1174       if(other.p_minorAxis) {
 
 1175         p_minorAxis = 
new Distance(*other.p_minorAxis);
 
 1178       if(other.p_polarAxis) {
 
 1179         p_polarAxis = 
new Distance(*other.p_polarAxis);
 
 1183         p_x = 
new Displacement(*other.p_x);
 
 1187         p_y = 
new Displacement(*other.p_y);
 
 1191         p_z = 
new Displacement(*other.p_z);
 
 1194       if(other.p_rectCovar) {
 
 1195         p_rectCovar = 
new symmetric_matrix<double, upper>(*other.p_rectCovar);
 
 1198       if(other.p_sphereCovar) {
 
 1199         p_sphereCovar = 
new symmetric_matrix<double, upper>(*other.p_sphereCovar);
 
 1206   void SurfacePoint::FreeAllocatedMemory() {
 
 1243       delete p_sphereCovar;
 
 1244       p_sphereCovar = NULL;
 
This class defines a body-fixed surface point. 
 
bool isValid() const 
Test if this displacement has been initialized or not. 
 
boost::numeric::ublas::symmetric_matrix< double, boost::numeric::ublas::upper > * p_sphereCovar
3x3 upper triangular covariance matrix ocentric coordinates 
 
boost::numeric::ublas::symmetric_matrix< double, boost::numeric::ublas::upper > * p_rectCovar
3x3 upper triangular covariance matrix rectangular coordinates 
 
Distance GetLocalRadius() const 
Return the radius of the surface point. 
 
double radians() const 
Convert an angle to a double. 
 
const double PI(3.14159265358979323846)
The mathematical constant PI. 
 
This class is designed to encapsulate the concept of a Latitude. 
 
Distance measurement, usually in meters. 
 
Longitude GetLongitude() const 
Return the body-fixed longitude for the surface point. 
 
This class is designed to encapsulate the concept of a Longitude. 
 
double meters() const 
Get the distance in meters. 
 
Latitude GetLatitude() const 
Return the body-fixed latitude for the surface point. 
 
#define _FILEINFO_
Macro for the filename and line number. 
 
bool isValid() const 
Test if this distance has been initialized or not. 
 
bool isValid() const 
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state. 
 
Defines an angle and provides unit conversions. 
 
Unless noted otherwise, the portions of Isis written by the USGS are public domain. 
 
Displacement is a signed length, usually in meters. 
 
Adds specific functionality to C++ strings. 
 
double kilometers() const 
Get the distance in kilometers. 
 
Unless noted otherwise, the portions of Isis written by the USGS are public domain.