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;