7 #include "SurfacePoint.h" 
   11 #include "IException.h" 
   14 #include "Longitude.h" 
   15 #include "SpecialPixel.h" 
   17 using namespace boost::numeric::ublas;
 
   26   SurfacePoint::SurfacePoint() {
 
   36     p_localRadius = other.p_localRadius;
 
   60       p_rectCovar = 
new symmetric_matrix<double, upper>(*other.
p_rectCovar);
 
   67       p_sphereCovar = 
new symmetric_matrix<double, upper>(*other.
p_sphereCovar);
 
   86     SetSphericalPoint(lat, lon, radius);
 
  110     SetSpherical(lat, lon, radius, latSigma, lonSigma, radiusSigma);
 
  120       const Distance &radius, 
const symmetric_matrix<double, upper> &covar) {
 
  123     SetSpherical(lat, lon, radius, covar);
 
  138     SetRectangular(x, y, z);
 
  161     SetRectangular(x, y, z, xSigma, ySigma, zSigma);
 
  175       const Displacement &z, 
const symmetric_matrix<double, upper> &covar) {
 
  178     SetRectangular(x, y, z, covar);
 
  186   SurfacePoint::~SurfacePoint() {
 
  187     FreeAllocatedMemory();
 
  195   void SurfacePoint::InitCovariance() {
 
  197     p_sphereCovar = NULL;
 
  205   void SurfacePoint::InitPoint() {
 
  229       IString msg = 
"x, y, and z must be set to valid displacements.  One or " 
  230         "more coordinates have been set to an invalid displacement.";
 
  231       throw IException(IException::User, msg, _FILEINFO_);
 
  262     if (!p_localRadius.isValid()) {
 
  263       ComputeLocalRadius();
 
  264       p_localRadius = GetLocalRadius();
 
  290     SetRectangularPoint(x, y, z);
 
  293       SetRectangularSigmas(xSigma, ySigma, zSigma);
 
  309                                     const symmetric_matrix<double,upper>& covar) {
 
  313     SetRectangularPoint(x, y, z);
 
  314     SetRectangularMatrix(covar);
 
  333     SetRectangularPoint(x, y, z);
 
  350   void SurfacePoint::SetRectangularSigmas(
const Distance &xSigma,
 
  354       IString msg = 
"x sigma, y sigma , and z sigma must be set to valid " 
  355         "distances.  One or more sigmas have been set to an invalid distance.";
 
  356       throw IException(IException::User, msg, _FILEINFO_);
 
  359     symmetric_matrix<double,upper> covar(3);
 
  364     SetRectangularMatrix(covar, Meters);
 
  376   void SurfacePoint::SetRectangularMatrix(
const symmetric_matrix<double, upper> &covar,
 
  377                                           SurfacePoint::CoordUnits units) {
 
  381       IString msg = 
"A point must be set before a variance/covariance matrix " 
  383       throw IException(IException::Programmer, msg, _FILEINFO_);
 
  387     if (units != Kilometers && units != Meters) {
 
  388       IString msg = 
"Units must be Kilometers or Meters";
 
  389       throw IException(IException::Programmer, msg, _FILEINFO_);
 
  394       *p_rectCovar = covar;
 
  397       p_rectCovar = 
new symmetric_matrix<double, upper>(covar);
 
  400     if (units == Meters) {
 
  402       (*p_rectCovar)(0,0) = covar(0,0)/1.0e6;
 
  403       (*p_rectCovar)(0,1) = covar(0,1)/1.0e6;
 
  404       (*p_rectCovar)(0,2) = covar(0,2)/1.0e6;
 
  405       (*p_rectCovar)(1,1) = covar(1,1)/1.0e6;
 
  406       (*p_rectCovar)(1,2) = covar(1,2)/1.0e6;
 
  407       (*p_rectCovar)(2,2) = covar(2,2)/1.0e6;
 
  410     SpiceDouble rectMat[3][3];
 
  413     double x2  = p_x->meters() * p_x->meters();
 
  414     double y2  = p_y->meters() * p_y->meters();
 
  415     double z   = p_z->meters();
 
  416     double radius = sqrt(x2 + y2 + z*z);
 
  419     rectMat[0][0] = covar(0,0);
 
  420     rectMat[0][1] = rectMat[1][0] = covar(0,1);
 
  421     rectMat[0][2] = rectMat[2][0] = covar(0,2);
 
  422     rectMat[1][1] = covar(1,1);
 
  423     rectMat[1][2] = rectMat[2][1] = covar(1,2);
 
  424     rectMat[2][2] = covar(2,2);
 
  428     double zOverR = p_z->meters() / radius;
 
  429     double r2 = radius*radius;
 
  430     double denom = r2*radius*sqrt(1.0 - (zOverR*zOverR));
 
  431     J[0][0] = -p_x->meters() * p_z->meters() / denom;
 
  432     J[0][1] = -p_y->meters() * p_z->meters() / denom;
 
  433     J[0][2] = (r2 - p_z->meters() * p_z->meters()) / denom;
 
  434     J[1][0] = -p_y->meters() / (x2 + y2);
 
  435     J[1][1] = p_x->meters() / (x2 + y2);
 
  437     J[2][0] = p_x->meters() / radius;  
 
  438     J[2][1] = p_y->meters() / radius;
 
  439     J[2][2] = p_z->meters() / radius;
 
  442       p_sphereCovar = 
new symmetric_matrix<double, upper>(3);
 
  444     SpiceDouble mat[3][3];
 
  445     mxm_c (J, rectMat, mat);
 
  446     mxmt_c (mat, J, mat);
 
  447     if (units == Kilometers) {
 
  449       (*p_sphereCovar)(0,0) = mat[0][0] * 1.0e6;
 
  450       (*p_sphereCovar)(0,1) = mat[0][1] * 1.0e6;
 
  451       (*p_sphereCovar)(0,2) = mat[0][2] * 1000.0;
 
  452       (*p_sphereCovar)(1,1) = mat[1][1] * 1.0e6;
 
  454       (*p_sphereCovar)(1,2) = mat[1][2] * 1000.0;
 
  455       (*p_sphereCovar)(2,2) = mat[2][2];
 
  459       (*p_sphereCovar)(0,0) = mat[0][0];
 
  460       (*p_sphereCovar)(0,1) = mat[0][1];
 
  461       (*p_sphereCovar)(0,2) = mat[0][2] / 1000.0;
 
  462       (*p_sphereCovar)(1,1) = mat[1][1];
 
  463       (*p_sphereCovar)(1,2) = mat[1][2] / 1000.0;
 
  464       (*p_sphereCovar)(2,2) = mat[2][2] / 1.0e6;
 
  480   void SurfacePoint::SetSphericalPoint(
const Latitude  &lat,
 
  485       IString msg = 
"Latitude, longitude, or radius is an invalid value.";
 
  486       throw IException(IException::User, msg, _FILEINFO_);
 
  489     SpiceDouble dlat = (double) lat.
radians();
 
  490     SpiceDouble dlon = (double) lon.
radians();
 
  494     latrec_c ( dradius, dlon, dlat, rect);
 
  497     p_localRadius = radius;
 
  499     SetRectangularPoint(
Displacement(rect[0], Displacement::Kilometers),
 
  522     SetSphericalPoint(lat, lon, radius);
 
  525       SetSphericalSigmas(latSigma, lonSigma, radiusSigma);
 
  539       const Distance &radius, 
const symmetric_matrix<double, upper> &covar) {
 
  540     SetSphericalPoint(lat, lon, radius);
 
  541     SetSphericalMatrix(covar);
 
  553   void SurfacePoint::SetSphericalCoordinates(
const Latitude &lat,
 
  555     SetSphericalPoint(lat, lon, radius);
 
  573   void SurfacePoint::SetSphericalSigmas(
const Angle &latSigma,
 
  574                                         const Angle &lonSigma,
 
  577       symmetric_matrix<double,upper> covar(3);
 
  580       double sphericalCoordinate;
 
  581       sphericalCoordinate = (double) latSigma.
radians();
 
  582       covar(0,0) =  sphericalCoordinate*sphericalCoordinate;
 
  583       sphericalCoordinate = (double) lonSigma.
radians();
 
  584       covar(1,1) = sphericalCoordinate*sphericalCoordinate;
 
  585       sphericalCoordinate = (double) radiusSigma.
meters();
 
  586       covar(2,2) = sphericalCoordinate*sphericalCoordinate;
 
  589       SetSphericalMatrix(covar);
 
  592       delete p_sphereCovar;
 
  593       p_sphereCovar = NULL;
 
  617   void SurfacePoint::SetSphericalSigmasDistance(
const Distance &latSigma,
 
  621       IString msg = 
"Cannot set spherical sigmas on an invalid surface point";
 
  622       throw IException(IException::Programmer, msg, _FILEINFO_);
 
  625     SetSphericalSigmas(
Angle(MetersToLatitude(latSigma.
meters()),Angle::Radians),
 
  626            Angle(MetersToLongitude(lonSigma.
meters()), Angle::Radians), radiusSigma);
 
  637   void SurfacePoint::SetSphericalMatrix(
 
  638                                         const symmetric_matrix<double, upper> & covar,
 
  639                                         SurfacePoint::CoordUnits units) {
 
  643       IString msg = 
"A point must be set before a variance/covariance matrix " 
  645       throw IException(IException::Programmer, msg, _FILEINFO_);
 
  649     if (units != Kilometers && units != Meters) {
 
  650       IString msg = 
"Units must be Kilometers or Meters";
 
  651       throw IException(IException::Programmer, msg, _FILEINFO_);
 
  655     double radius = (double) GetLocalRadius().kilometers();
 
  659         *p_sphereCovar = covar;
 
  662       p_sphereCovar = 
new symmetric_matrix<double, upper>(covar);
 
  665     if (units == Meters) {
 
  667       (*p_sphereCovar)(0,0) = covar(0,0);
 
  668       (*p_sphereCovar)(0,1) = covar(0,1);
 
  669       (*p_sphereCovar)(0,2) = covar(0,2) / 1000.;
 
  670       (*p_sphereCovar)(1,1) = covar(1,1);
 
  671       (*p_sphereCovar)(1,2) = covar(1,2) / 1000.;
 
  672       (*p_sphereCovar)(2,2) = covar(2,2) / 1.0e6;
 
  673       radius = (double) GetLocalRadius().meters();
 
  677     SpiceDouble sphereMat[3][3];
 
  679     sphereMat[0][0] = covar(0,0);
 
  680     sphereMat[0][1] = sphereMat[1][0] = covar(0,1);
 
  681     sphereMat[0][2] = sphereMat[2][0] = covar(0,2);
 
  682     sphereMat[1][1] = covar(1,1);
 
  683     sphereMat[1][2] = sphereMat[2][1] = covar(1,2);
 
  684     sphereMat[2][2] = covar(2,2);
 
  691     double lat = (double) GetLatitude().radians();
 
  692     double lon = (double) GetLongitude().radians();
 
  696     double cosPhi = cos(lat);
 
  697     double sinPhi = sin(lat);
 
  698     double cosLamda = cos(lon);
 
  699     double sinLamda = sin(lon);
 
  700     double rcosPhi = radius*cosPhi;
 
  701     double rsinPhi = radius*sinPhi;
 
  702     J[0][0] = -rsinPhi * cosLamda;
 
  703     J[0][1] = -rcosPhi * sinLamda;
 
  704     J[0][2] = cosPhi * cosLamda;
 
  705     J[1][0] = -rsinPhi * sinLamda;
 
  706     J[1][1] = rcosPhi * cosLamda;
 
  707     J[1][2] = cosPhi * sinLamda;
 
  713       p_rectCovar = 
new symmetric_matrix<double, upper>(3);
 
  715     SpiceDouble mat[3][3];
 
  716     mxm_c (J, sphereMat, mat);
 
  717     mxmt_c (mat, J, mat);
 
  719     if (units == Kilometers) {
 
  720       (*p_rectCovar)(0,0) = mat[0][0];
 
  721       (*p_rectCovar)(0,1) = mat[0][1];
 
  722       (*p_rectCovar)(0,2) = mat[0][2];
 
  723       (*p_rectCovar)(1,1) = mat[1][1];
 
  724       (*p_rectCovar)(1,2) = mat[1][2];
 
  725       (*p_rectCovar)(2,2) = mat[2][2];
 
  729       (*p_rectCovar)(0,0) = mat[0][0]/1.0e6;
 
  730       (*p_rectCovar)(0,1) = mat[0][1]/1.0e6;
 
  731       (*p_rectCovar)(0,2) = mat[0][2]/1.0e6;
 
  732       (*p_rectCovar)(1,1) = mat[1][1]/1.0e6;
 
  733       (*p_rectCovar)(1,2) = mat[1][2]/1.0e6;
 
  734       (*p_rectCovar)(2,2) = mat[2][2]/1.0e6;
 
  749   void SurfacePoint::SetMatrix(
CoordinateType type, 
const symmetric_matrix<double, upper>& covar) {
 
  753         SetSphericalMatrix(covar, SurfacePoint::Kilometers);
 
  756         SetRectangularMatrix(covar, SurfacePoint::Kilometers);
 
  759          IString msg =
"Unknown surface point coordinate type enum [" + 
toString(type) + 
"]." ;
 
  760          throw IException(IException::Programmer, msg, _FILEINFO_);
 
  773   std::vector<double> SurfacePoint::Partial(
CoordinateType type, CoordIndex index) {
 
  774     std::vector<double> derivative(3);
 
  777         derivative = LatitudinalDerivative(index);
 
  780         derivative = RectangularDerivative(index);
 
  783          IString msg =
"Unknown surface point coordinate type enum [" + 
toString(type) + 
"]." ;
 
  784          throw IException(IException::Programmer, msg, _FILEINFO_);
 
  798   std::vector<double> SurfacePoint::LatitudinalDerivative(CoordIndex index) {
 
  799     std::vector<double> derivative(3);
 
  800     double rlat = GetLatitude().radians();
 
  801     double rlon = GetLongitude().radians();
 
  802     double sinLon = sin(rlon);
 
  803     double cosLon = cos(rlon);
 
  804     double sinLat = sin(rlat);
 
  805     double cosLat = cos(rlat);
 
  806     double radkm = GetLocalRadius().kilometers();
 
  810         derivative[0] = -radkm * sinLat * cosLon;
 
  811         derivative[1] = -radkm * sinLon * sinLat;
 
  812         derivative[2] =  radkm * cosLat;
 
  815         derivative[0] = -radkm * cosLat * sinLon;
 
  816         derivative[1] =  radkm * cosLat * cosLon;
 
  820         derivative[0] = cosLon * cosLat;
 
  821         derivative[1] = sinLon * cosLat;
 
  822         derivative[2] = sinLat;
 
  825         IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
  826         throw IException(IException::Programmer, msg, _FILEINFO_);
 
  840   std::vector<double> SurfacePoint::RectangularDerivative(CoordIndex index) {
 
  841     std::vector<double> derivative(3,0.0);
 
  854         IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
  855         throw IException(IException::Programmer, msg, _FILEINFO_);
 
  870   void SurfacePoint::ToNaifArray(
double naifOutput[3])
 const {
 
  872       naifOutput[0] = p_x->kilometers();
 
  873       naifOutput[1] = p_y->kilometers();
 
  874       naifOutput[2] = p_z->kilometers();
 
  877       IString msg = 
"Cannot convert an invalid surface point to a naif array";
 
  878       throw IException(IException::Programmer, msg, _FILEINFO_);
 
  891   void SurfacePoint::FromNaifArray(
const double naifValues[3]) {
 
  892     if(p_x && p_y && p_z) {
 
  893       p_x->setKilometers(naifValues[0]);
 
  894       p_y->setKilometers(naifValues[1]);
 
  895       p_z->setKilometers(naifValues[2]);
 
  898       p_x = 
new Displacement(naifValues[0], Displacement::Kilometers);
 
  899       p_y = 
new Displacement(naifValues[1], Displacement::Kilometers);
 
  900       p_z = 
new Displacement(naifValues[2], Displacement::Kilometers);
 
  903     ComputeLocalRadius();
 
  904     p_localRadius = GetLocalRadius();
 
  914   void SurfacePoint::ResetLocalRadius(
const Distance &radius) {
 
  917       IString msg = 
"Radius value must be a valid Distance.";
 
  918       throw IException(IException::Programmer, msg, _FILEINFO_);
 
  921     if (!p_x || !p_y || !p_z || !p_x->isValid() || !p_y->isValid() ||
 
  923         IString msg = 
"In order to reset the local radius, a Surface Point must " 
  925         throw IException(IException::Programmer, msg, _FILEINFO_);
 
  929     SpiceDouble lat = (double) GetLatitude().radians();
 
  930     SpiceDouble lon = (double) GetLongitude().radians();
 
  932     p_localRadius = radius;
 
  936     latrec_c ((SpiceDouble) radius.
kilometers(), lon, lat, rect);
 
  937     p_x->setKilometers(rect[0]);
 
  938     p_y->setKilometers(rect[1]);
 
  939     p_z->setKilometers(rect[2]);
 
  947   bool SurfacePoint::Valid()
 const {
 
  948     static const Displacement zero(0, Displacement::Meters);
 
  949     return p_x && p_y && p_z && p_x->isValid() && p_y->isValid() && p_z->isValid() &&
 
  950            (*p_x != zero || *p_y != zero || *p_z != zero);
 
  962   double SurfacePoint::GetCoord(
CoordinateType type, CoordIndex index, CoordUnits units) {
 
  974             value = LatToDouble(GetLatitude(), units);
 
  978             value = LonToDouble(GetLongitude(), units);
 
  982             value = DistanceToDouble(GetLocalRadius(), units);
 
  986             IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
  987             throw IException(IException::Programmer, msg, _FILEINFO_);
 
  996             value = DisplacementToDouble(GetX(), units);
 
 1000             value = DisplacementToDouble(GetY(), units);
 
 1004             value = DisplacementToDouble(GetZ(), units);
 
 1008             IString msg = 
"Invalid coordinate index  enum (must be less than 3).";
 
 1009             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1014          IString msg =
"Unknown surface point coordinate type enum [" + 
toString(type) + 
"]." ;
 
 1015          throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1029   double SurfacePoint::GetSigma(
CoordinateType type, CoordIndex index, CoordUnits units) {
 
 1039             value = DistanceToDouble(GetLatSigmaDistance(), units);
 
 1043              value = DistanceToDouble(GetLonSigmaDistance(), units);
 
 1047              value = DistanceToDouble(GetLocalRadiusSigma(), units);
 
 1051             IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
 1052             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1061             value = DistanceToDouble(GetXSigma(), units);
 
 1065              value = DistanceToDouble(GetYSigma(), units);
 
 1069              value = DistanceToDouble(GetZSigma(), units);
 
 1073             IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
 1074             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1079          IString msg =
"Unknown surface point coordinate type enum [" + 
toString(type) + 
"]." ;
 
 1080          throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1105             dist = GetLatSigmaDistance();
 
 1109              dist = GetLonSigmaDistance();
 
 1113              dist = GetLocalRadiusSigma();
 
 1117             IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
 1118             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1139             IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
 1140             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1145          IString msg =
"Unknown surface point coordinate type enum [" + 
toString(type) + 
"]." ;
 
 1146          throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1160   double SurfacePoint::DisplacementToDouble(
Displacement disp, CoordUnits units) {
 
 1174            IString msg = 
"Unrecognized unit for a Displacement (must be meters or kilometers).";
 
 1175            throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1188   double SurfacePoint::DistanceToDouble(
Distance dist, CoordUnits units) {
 
 1202            IString msg = 
"Unrecognized unit for a Distance (not meters or kilometers).";
 
 1203            throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1216   double SurfacePoint::LatToDouble(
Latitude lat, CoordUnits units) {
 
 1222         value = GetLatitude().radians();
 
 1226         value = GetLatitude().degrees();
 
 1230          IString msg = 
"Invalid unit for latitude (must be Radians or Degrees).";
 
 1231          throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1248   double SurfacePoint::MetersToLatitude(
double latLength) {
 
 1251       return latLength / GetLocalRadius().meters();
 
 1276   double SurfacePoint::MetersToLongitude(
double deltaLonMeters) {
 
 1278     if (Valid() && !
IsSpecial(deltaLonMeters)) {
 
 1279       double convFactor = cos((
double)GetLatitude().radians());
 
 1280       double deltaLonRadians;
 
 1283       if (convFactor > 1.0e-50) {             
 
 1284         deltaLonRadians = deltaLonMeters / (convFactor*GetLocalRadius().meters());
 
 1288         deltaLonRadians = 
PI;
 
 1290       return deltaLonRadians;
 
 1310   double SurfacePoint::LatitudeToMeters(
double relativeLat)
 const {
 
 1312     if (relativeLat == 0.) {
 
 1315     else if (Valid() && !
IsSpecial(relativeLat) && GetLocalRadius().isValid() ) {
 
 1316       return relativeLat * GetLocalRadius().meters();
 
 1336   double SurfacePoint::LongitudeToMeters(
double deltaLonRadians)
 const{
 
 1340     if (deltaLonRadians == 0.) {
 
 1341       deltaLonMeters = 0.;
 
 1343     else if (Valid() && !
IsSpecial(deltaLonRadians) && GetLocalRadius().isValid() ) {
 
 1345       double scalingRadius = cos(GetLatitude().radians()) * GetLocalRadius().meters();
 
 1346       deltaLonMeters = deltaLonRadians * scalingRadius;
 
 1349     return deltaLonMeters;
 
 1363                  SurfacePoint::stringToCoordinateType(QString type)  {
 
 1364     if (type.compare(
"LATITUDINAL", Qt::CaseInsensitive) == 0) {
 
 1365       return SurfacePoint::Latitudinal;
 
 1367     else if (type.compare(
"RECTANGULAR", Qt::CaseInsensitive) == 0) {
 
 1368       return SurfacePoint::Rectangular;
 
 1372                           "Unknown coordinate type for a SurfacePoint [" + type + 
"].",
 
 1389   QString SurfacePoint::coordinateTypeToString(
 
 1394         return "Latitudinal";
 
 1398         return "Rectangular";
 
 1402          IString msg =
"Unknown surface point coordinate type enum [" + 
toString(type) + 
"]." ;
 
 1403          throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1415   double SurfacePoint::LonToDouble(
Longitude lon, CoordUnits units) {
 
 1421         value = GetLongitude().radians();
 
 1425         value = GetLongitude().degrees();
 
 1429          IString msg = 
"Invalid unit for longitude (must be Radians of Degrees).";
 
 1430          throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1443   Displacement SurfacePoint::GetY()
 const {
 
 1444     if(!p_y) 
return Displacement();
 
 1450   Displacement SurfacePoint::GetZ()
 const {
 
 1451     if(!p_z) 
return Displacement();
 
 1457   Distance SurfacePoint::GetXSigma()
 const {
 
 1458     if(!p_rectCovar) 
return Distance();
 
 1460     return Distance(sqrt((*p_rectCovar)(0, 0)), Distance::Kilometers);
 
 1464   Distance SurfacePoint::GetYSigma()
 const {
 
 1465     if(!p_rectCovar) 
return Distance();
 
 1467     return Distance(sqrt((*p_rectCovar)(1, 1)), Distance::Kilometers);
 
 1471   Distance SurfacePoint::GetZSigma()
 const {
 
 1472     if(!p_rectCovar) 
return Distance();
 
 1474     return Distance(sqrt((*p_rectCovar)(2, 2)), Distance::Kilometers);
 
 1501             value = GetLatWeight();  
 
 1505             value = GetLonWeight();  
 
 1509             value = GetLocalRadiusWeight();  
 
 1513             IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
 1514             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1523             value = GetXWeight();   
 
 1527             value = GetYWeight();   
 
 1531             value = GetZWeight();  
 
 1535             IString msg = 
"Invalid coordinate index  (must be less than 3).";
 
 1536             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1541          IString msg =
"Unknown surface point coordinate type enum [" + 
toString(type) + 
"]." ;
 
 1542          throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1553   double SurfacePoint::GetXWeight()
 const {
 
 1555     double dXSigma = GetXSigma().kilometers();
 
 1557     if (dXSigma <= 0.0 ) {
 
 1558         IString msg = 
"SurfacePoint::GetXWeight(): Sigma <= 0.0";
 
 1559         throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1562     return 1.0/(dXSigma*dXSigma);
 
 1571   double SurfacePoint::GetYWeight()
 const {
 
 1573     double dYSigma = GetYSigma().kilometers();
 
 1575     if (dYSigma <= 0.0 ) {
 
 1576         IString msg = 
"SurfacePoint::GetYWeight(): Sigma <= 0.0";
 
 1577         throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1580     return 1.0/(dYSigma*dYSigma);
 
 1589   double SurfacePoint::GetZWeight()
 const {
 
 1591     double dZSigma = GetZSigma().kilometers();
 
 1593     if (dZSigma <= 0.0 ) {
 
 1594         IString msg = 
"SurfacePoint::GetZWeight(): Sigma <= 0.0";
 
 1595         throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1598     return 1.0/(dZSigma*dZSigma);
 
 1602   symmetric_matrix<double, upper> SurfacePoint::GetRectangularMatrix
 
 1603                                (SurfacePoint::CoordUnits units)
 const {
 
 1605       symmetric_matrix<double, upper> tmp(3);
 
 1611     if (units != Kilometers && units != Meters) {
 
 1612       IString msg = 
"Units must be Kilometers or Meters";
 
 1613       throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1616     symmetric_matrix<double, upper> covar(3);
 
 1623         covar(0,0) = (*p_rectCovar)(0,0)*1.0e6;
 
 1624         covar(0,1) = (*p_rectCovar)(0,1)*1.0e6;
 
 1625         covar(0,2) = (*p_rectCovar)(0,2)*1.0e6;
 
 1626         covar(1,1) = (*p_rectCovar)(1,1)*1.0e6;
 
 1627         covar(1,2) = (*p_rectCovar)(1,2)*1.0e6;
 
 1628         covar(2,2) = (*p_rectCovar)(2,2)*1.0e6;
 
 1633         return *p_rectCovar;
 
 1637         IString msg = 
"Unrecognized unit for a Displacement (must be meters or kilometers).";
 
 1638         throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1641     return *p_rectCovar;
 
 1645   Angle SurfacePoint::GetLatSigma()
 const {
 
 1649     return Angle(sqrt((*p_sphereCovar)(0, 0)), Angle::Radians);
 
 1653   Angle SurfacePoint::GetLonSigma()
 const {
 
 1657     return Angle(sqrt((*p_sphereCovar)(1, 1)), Angle::Radians);
 
 1670       double x = p_x->meters();
 
 1671       double y = p_y->meters();
 
 1672       double z = p_z->meters();
 
 1674       if (x != 0.  ||  y != 0.  || z != 0.)
 
 1675         return Latitude(atan2(z, sqrt(x*x + y*y) ), Angle::Radians);
 
 1689       double x = p_x->meters();
 
 1690       double y = p_y->meters();
 
 1692       if(x == 0.0 && y == 0.0) {
 
 1696       double lon = atan2(y, x);
 
 1709     void SurfacePoint::ComputeLocalRadius() {
 
 1710     static const Displacement zero(0, Displacement::Meters);
 
 1712         double x = p_x->meters();
 
 1713         double y = p_y->meters();
 
 1714         double z = p_z->meters();
 
 1716         p_localRadius = 
Distance(sqrt(x*x + y*y + z*z), Distance::Meters);
 
 1718       else if (*p_x == zero && *p_y == zero && *p_z == zero) { 
 
 1719         p_localRadius = 
Distance(0., Distance::Meters);
 
 1722         IString msg = 
"SurfacePoint::Can't compute local radius on invalid point";
 
 1723         throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1733      return p_localRadius;
 
 1748     double d = LatitudeToMeters(GetLatSigma().radians());
 
 1751       return Distance(d,  Distance::Meters);
 
 1765     double d = LongitudeToMeters(GetLonSigma().radians());
 
 1768       return Distance(d,  Distance::Meters);
 
 1776   Distance SurfacePoint::GetLocalRadiusSigma()
 const {
 
 1780     return Distance(sqrt((*p_sphereCovar)(2, 2)), Distance::Kilometers);
 
 1784   symmetric_matrix<double, upper> SurfacePoint::GetSphericalMatrix
 
 1785                                (SurfacePoint::CoordUnits units)
 const {
 
 1786     if(!p_sphereCovar) {
 
 1787       symmetric_matrix<double, upper> tmp(3);
 
 1793     if (units != Kilometers && units != Meters) {
 
 1794       IString msg = 
"Units must be Kilometers or Meters";
 
 1795       throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1798     symmetric_matrix<double, upper> covar(3);
 
 1805         covar(0,0) = (*p_sphereCovar)(0,0);
 
 1806         covar(0,1) = (*p_sphereCovar)(0,1);
 
 1807         covar(0,2) = (*p_sphereCovar)(0,2)*1000.;
 
 1808         covar(1,1) = (*p_sphereCovar)(1,1);
 
 1809         covar(1,2) = (*p_sphereCovar)(1,2)*1000.;
 
 1810         covar(2,2) = (*p_sphereCovar)(2,2)*1.0e6;
 
 1815         return *p_sphereCovar;
 
 1819         IString msg = 
"Unrecognized unit for a Displacement (must be meters or kilometers).";
 
 1820         throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1823     return *p_sphereCovar;
 
 1832   double SurfacePoint::GetLatWeight()
 const {
 
 1833     double dlatSigma = GetLatSigma().radians();
 
 1835       if( dlatSigma <= 0.0 ) {
 
 1836           IString msg = 
"SurfacePoint::GetLatWeight(): Sigma <= 0.0";
 
 1837           throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1840       return 1.0/(dlatSigma*dlatSigma);
 
 1848   double SurfacePoint::GetLonWeight()
 const {
 
 1849     double dlonSigma = GetLonSigma().radians();
 
 1851         if( dlonSigma <= 0.0 ) {
 
 1852             IString msg = 
"SurfacePoint::GetLonWeight(): Sigma <= 0.0";
 
 1853             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1856         return 1.0/(dlonSigma*dlonSigma);
 
 1864   double SurfacePoint::GetLocalRadiusWeight()
 const {
 
 1866     double dlocalRadiusSigma = GetLocalRadiusSigma().kilometers();
 
 1868         if (dlocalRadiusSigma <= 0.0 ) {
 
 1869             IString msg = 
"SurfacePoint::GetRadWeight(): Sigma <= 0.0";
 
 1870             throw IException(IException::Programmer, msg, _FILEINFO_);
 
 1873         return 1.0/(dlocalRadiusSigma*dlocalRadiusSigma);
 
 1882     if(!Valid() || !other.Valid())
 
 1885     return GetDistanceToPoint(other,
 
 1898       const Distance &sphereRadius)
 const {
 
 1899     if(!Valid() || !other.Valid())
 
 1903     const Angle &latitude = GetLatitude();
 
 1904     const Angle &longitude = GetLongitude();
 
 1910     Angle deltaLat = latitude - otherLatitude;
 
 1911     Angle deltaLon = longitude - otherLongitude;
 
 1913     double haversinLat = sin(deltaLat.
radians() / 2.0);
 
 1914     haversinLat *= haversinLat;
 
 1916     double haversinLon = sin(deltaLon.
radians() / 2.0);
 
 1917     haversinLon *= haversinLon;
 
 1919     double a = haversinLat + cos(latitude.
radians()) *
 
 1920                cos(otherLatitude.radians()) *
 
 1923     double c = 2 * atan(sqrt(a) / sqrt(1 - a));
 
 1925     return sphereRadius * c;
 
 1929   bool SurfacePoint::operator==(
const SurfacePoint &other)
 const {
 
 1932     if(equal && p_x && p_y && p_z && other.p_x && other.p_y && other.p_z) {
 
 1933       equal = equal && *p_x == *other.p_x;
 
 1934       equal = equal && *p_y == *other.p_y;
 
 1935       equal = equal && *p_z == *other.p_z;
 
 1938       equal = equal && p_x == NULL && other.p_x == NULL;
 
 1939       equal = equal && p_y == NULL && other.p_y == NULL;
 
 1940       equal = equal && p_z == NULL && other.p_z == NULL;
 
 1943     if(equal && p_rectCovar) {
 
 1944       equal = equal && (*p_rectCovar)(0, 0) == (*other.
p_rectCovar)(0, 0);
 
 1945       equal = equal && (*p_rectCovar)(0, 1) == (*other.
p_rectCovar)(0, 1);
 
 1946       equal = equal && (*p_rectCovar)(0, 2) == (*other.
p_rectCovar)(0, 2);
 
 1947       equal = equal && (*p_rectCovar)(1, 1) == (*other.
p_rectCovar)(1, 1);
 
 1948       equal = equal && (*p_rectCovar)(1, 2) == (*other.
p_rectCovar)(1, 2);
 
 1949       equal = equal && (*p_rectCovar)(2, 2) == (*other.
p_rectCovar)(2, 2);
 
 1952       equal = equal && p_rectCovar == NULL && other.
p_rectCovar == NULL;
 
 1955     if(equal && p_sphereCovar) {
 
 1956       equal = equal && (*p_sphereCovar)(0, 0) == (*other.
p_sphereCovar)(0, 0);
 
 1957       equal = equal && (*p_sphereCovar)(0, 1) == (*other.
p_sphereCovar)(0, 1);
 
 1958       equal = equal && (*p_sphereCovar)(0, 2) == (*other.
p_sphereCovar)(0, 2);
 
 1959       equal = equal && (*p_sphereCovar)(1, 1) == (*other.
p_sphereCovar)(1, 1);
 
 1960       equal = equal && (*p_sphereCovar)(1, 2) == (*other.
p_sphereCovar)(1, 2);
 
 1961       equal = equal && (*p_sphereCovar)(2, 2) == (*other.
p_sphereCovar)(2, 2);
 
 1964       equal = equal && p_sphereCovar == NULL && other.
p_sphereCovar == NULL;
 
 1970   SurfacePoint &SurfacePoint::operator=(
const SurfacePoint &other) {
 
 1973     if(p_x && other.p_x &&
 
 1976        !p_rectCovar && !other.p_rectCovar &&
 
 1977        !p_sphereCovar && !other.p_sphereCovar) {
 
 1983       FreeAllocatedMemory();
 
 1986         p_x = 
new Displacement(*other.p_x);
 
 1990         p_y = 
new Displacement(*other.p_y);
 
 1994         p_z = 
new Displacement(*other.p_z);
 
 1997       if(other.p_rectCovar) {
 
 1998         p_rectCovar = 
new symmetric_matrix<double, upper>(*other.p_rectCovar);
 
 2001       if(other.p_sphereCovar) {
 
 2002         p_sphereCovar = 
new symmetric_matrix<double, upper>(*other.p_sphereCovar);
 
 2007     p_localRadius = other.GetLocalRadius();
 
 2012   void SurfacePoint::FreeAllocatedMemory() {
 
 2034       delete p_sphereCovar;
 
 2035       p_sphereCovar = NULL;