78 if (lab.
findObject(
"IsisCube").hasGroup(
"Mapping")) {
104 p_groundRangeComputed =
false;
105 p_raDecRangeComputed =
false;
106 p_ringRangeComputed =
false;
175 bool success =
false;
204 if (tproj->
SetWorld(sample, line)) {
220 if (shape->
name() !=
"Plane") {
302 if (shape->
name() !=
"Plane") {
331 if (!surfacePt.Valid()) {
440 const double radius) {
463 double a = sB[0] - pB[0];
464 double b = sB[1] - pB[1];
465 double c = sB[2] - pB[2];
466 double dist = sqrt(a * a + b * b + c * c) * 1000.0;
498 if (lineRes < 0.0)
return -1.0;
499 if (sampRes < 0.0)
return -1.0;
500 return (lineRes + sampRes) / 2.0;
528 if (
target()->shape()->name() ==
"Plane") {
529 IString msg =
"Images with plane targets should use Camera method RingRangeResolution ";
530 msg +=
"instead of GroundRangeResolution";
535 if (p_groundRangeComputed)
return;
536 p_groundRangeComputed =
true;
539 double originalSample =
Sample();
540 double originalLine =
Line();
541 int originalBand =
Band();
556 for (
int band = 1; band <= eband; band++) {
560 for (
int line = 1; line <=
p_lines + 1; line++) {
564 for (samp = 1; samp <=
p_samples + 1; samp++) {
566 if (
SetImage((
double)samp - 0.5, (
double)line - 0.5)) {
574 if (lon > 180.0) lon -= 360.0;
583 if ((line != 1) && (line !=
p_lines + 1))
break;
588 if (line == 1)
continue;
589 if (line ==
p_lines + 1)
continue;
593 for (samp =
p_samples + 1; samp >= 1; samp--) {
594 if (
SetImage((
double)samp - 0.5, (
double)line - 0.5)) {
602 if (lon > 180.0) lon -= 360.0;
717 SetImage(originalSample, originalLine);
724 string message =
"Camera missed planet or SPICE data off.";
745 if (p_ringRangeComputed)
return;
747 p_ringRangeComputed =
true;
750 double originalSample =
Sample();
751 double originalLine =
Line();
752 int originalBand =
Band();
769 for (
int band = 1; band <= eband; band++) {
773 for (
int line = 1; line <=
p_lines + 1; line++) {
778 for (samp = 1; samp <=
p_samples + 1; samp++) {
780 if (
SetImage((
double)samp - 0.5, (
double)line - 0.5)) {
788 if (azimuth > 180.0) azimuth -= 360.0;
797 if ((line != 1) && (line !=
p_lines + 1))
break;
801 if (line == 1)
continue;
802 if (line ==
p_lines + 1)
continue;
806 for(samp =
p_samples + 1; samp >= 1; samp--) {
807 if (
SetImage((
double)samp - 0.5, (
double)line - 0.5)) {
815 if (azimuth > 180.0) azimuth -= 360.0;
901 SetImage(originalSample, originalLine);
909 string message =
"RingPlane ShapeModel - Camera missed plane or SPICE data off.";
924 double minlat, minlon, maxlat, maxlon;
925 return GroundRange(minlat, maxlat, minlon, maxlon, pvl);
941 double &minlon,
double &maxlon,
965 QString latType = (QString) map[
"LatitudeType"];
966 if (latType.toUpper() ==
"PLANETOGRAPHIC") {
967 if (abs(minlat) < 90.0) {
968 minlat *=
PI / 180.0;
969 minlat = atan(tan(minlat) * (a / b) * (a / b));
970 minlat *= 180.0 /
PI;
973 if(abs(maxlat) < 90.0) {
974 maxlat *=
PI / 180.0;
975 maxlat = atan(tan(maxlat) * (a / b) * (a / b));
976 maxlat *= 180.0 /
PI;
984 bool domain360 =
true;
986 QString lonDomain = (QString) map[
"LongitudeDomain"];
987 if(lonDomain.toUpper() ==
"180") {
996 QString lonDirection = (QString) map[
"LongitudeDirection"];
997 if(lonDirection.toUpper() ==
"POSITIVEWEST") {
998 double swap = minlon;
1006 while(minlon < 0.0) {
1010 while(minlon > 360.0) {
1016 while(minlon < -180.0) {
1020 while(minlon > 180.0) {
1027 if((maxlon - minlon) > 359.0)
return true;
1045 double &minRingLongitude,
double &maxRingLongitude,
Pvl &pvl) {
1059 bool domain360 =
true;
1061 QString ringLongitudeDomain = (QString) map[
"RingLongitudeDomain"];
1062 if (ringLongitudeDomain ==
"180") {
1070 if (map.
hasKeyword(
"RingLongitudeDirection")) {
1071 QString ringLongitudeDirection = (QString) map[
"RingLongitudeDirection"];
1072 if (ringLongitudeDirection.toUpper() ==
"Clockwise") {
1073 double swap = minRingLongitude;
1074 minRingLongitude = -maxRingLongitude;
1075 maxRingLongitude = -swap;
1081 while (minRingLongitude < 0.0) {
1082 minRingLongitude += 360.0;
1083 maxRingLongitude += 360.0;
1085 while (minRingLongitude > 360.0) {
1086 minRingLongitude -= 360.0;
1087 maxRingLongitude -= 360.0;
1091 while (minRingLongitude < -180.0) {
1092 minRingLongitude += 360.0;
1093 maxRingLongitude += 360.0;
1095 while (minRingLongitude > 180.0) {
1096 minRingLongitude -= 360.0;
1097 maxRingLongitude -= 360.0;
1102 if ((maxRingLongitude - minRingLongitude) > 359.0) {
1122 map +=
PvlKeyword(
"LatitudeType",
"Planetocentric");
1123 map +=
PvlKeyword(
"LongitudeDirection",
"PositiveEast");
1133 map +=
PvlKeyword(
"ProjectionName",
"Sinusoidal");
1144 if (
target()->shape()->name() !=
"Plane") {
1145 IString msg =
"A ring plane projection has been requested on an image whose shape is not a ring plane. ";
1146 msg +=
"Rerun spiceinit with shape=RINGPLANE. ";
1153 map +=
PvlKeyword(
"RingLongitudeDirection",
"CounterClockwise");
1154 map +=
PvlKeyword(
"RingLongitudeDomain",
"360");
1163 map +=
PvlKeyword(
"ProjectionName",
"Planar");
1171 QString key =
"INS" +
toString(code) +
"_FOCAL_LENGTH";
1178 QString key =
"INS" +
toString(code) +
"_PIXEL_PITCH";
1219 else if (
target()->shape()->hasIntersection()) {
1249 normal[0] = normal[1] = normal[2] = 0.0;
1255 if (QString::compare(shapeModel->
name(),
"DemShape", Qt::CaseInsensitive) == 0) {
1259 shapeModel->calculateLocalNormal(cornerNeighborPoints);
1266 double line =
Line();
1270 surroundingPoints.append(qMakePair(samp, line - 0.5));
1271 surroundingPoints.append(qMakePair(samp, line + 0.5));
1272 surroundingPoints.append(qMakePair(samp - 0.5, line));
1273 surroundingPoints.append(qMakePair(samp + 0.5, line));
1276 double originalSample = samp;
1277 double originalLine = line;
1280 for (
int i = 0; i < cornerNeighborPoints.size(); i++) {
1281 cornerNeighborPoints[i] =
new double[3];
1289 for (
int i = 0; i < cornerNeighborPoints.size(); i++) {
1291 if (!(
SetImage(surroundingPoints[i].first, surroundingPoints[i].second))) {
1292 surroundingPoints[i].first = samp;
1293 surroundingPoints[i].second = line;
1296 if (!(
SetImage(surroundingPoints[i].first, surroundingPoints[i].second))) {
1303 SetImage(originalSample, originalLine);
1310 for (
int i = 0; i < cornerNeighborPoints.size(); i++) {
1311 delete [] cornerNeighborPoints[i];
1328 if ((surroundingPoints[0].first == surroundingPoints[1].first &&
1329 surroundingPoints[0].second == surroundingPoints[1].second) ||
1330 (surroundingPoints[2].first == surroundingPoints[3].first &&
1331 surroundingPoints[2].second == surroundingPoints[3].second)) {
1338 SetImage(originalSample, originalLine);
1345 for (
int i = 0; i < cornerNeighborPoints.size(); i++)
1346 delete [] cornerNeighborPoints[i];
1352 SetImage(originalSample, originalLine);
1353 shapeModel->calculateLocalNormal(cornerNeighborPoints);
1356 for (
int i = 0; i < cornerNeighborPoints.size(); i++)
1357 delete [] cornerNeighborPoints[i];
1373 std::vector<double> localNormal(3);
1374 localNormal = shapeModel->
normal();
1375 memcpy(normal, (
double *) &localNormal[0],
sizeof(
double) * 3);
1392 Angle & emission,
bool &success) {
1401 unorm_c(normal,normal,&mag);
1408 SpiceDouble surfSpaceVect[3], unitizedSurfSpaceVect[3], dist;
1418 vsub_c((SpiceDouble *) &sB[0], pB, surfSpaceVect);
1419 unorm_c(surfSpaceVect, unitizedSurfSpaceVect, &dist);
1422 SpiceDouble surfaceSunVect[3];
1423 vsub_c(
m_uB, pB, surfaceSunVect);
1424 SpiceDouble unitizedSurfSunVect[3];
1425 unorm_c(surfaceSunVect, unitizedSurfSunVect, &dist);
1429 phase =
Angle(vsep_c(unitizedSurfSpaceVect, unitizedSurfSunVect),
1434 emission =
Angle(vsep_c(unitizedSurfSpaceVect, normal),
1439 incidence =
Angle(vsep_c(unitizedSurfSunVect, normal),
1459 double &mindec,
double &maxdec) {
1462 IString msg =
"Camera::RaDecRange can not calculate a right ascension, declination range";
1463 msg +=
" for projected images which are not projected to sky";
1468 double originalSample =
Sample();
1469 double originalLine =
Line();
1470 int originalBand =
Band();
1473 if (!p_raDecRangeComputed) {
1474 p_raDecRangeComputed =
true;
1487 for (
int band = 1; band <= eband; band++) {
1490 for (
int line = 1; line <=
p_lines; line++) {
1493 for (samp = 1; samp <=
p_samples; samp++) {
1494 SetImage((
double)samp, (
double)line);
1502 if (ra > 180.0) ra -= 360.0;
1506 if ((line != 1) && (line !=
p_lines))
break;
1511 for (samp =
p_samples; samp >= 1; samp--) {
1512 SetImage((
double)samp, (
double)line);
1520 if (ra > 180.0) ra -= 360.0;
1590 SetImage(originalSample, originalLine);
1608 IString msg =
"Camera::RaDecResolution can not calculate a right ascension, declination resolution";
1609 msg +=
" for projected images which are not projected to sky";
1614 double originalSample =
Sample();
1615 double originalLine =
Line();
1616 int originalBand =
Band();
1626 double dist = (ra1 - ra2) * (ra1 - ra2) + (dec1 - dec2) * (dec1 - dec2);
1628 double lineRes = dist / (p_lines - 1);
1634 dist = (ra1 - ra2) * (ra1 - ra2) + (dec1 - dec2) * (dec1 - dec2);
1636 double sampRes = dist / (p_samples - 1);
1641 SetImage(originalSample, originalLine);
1647 return (sampRes < lineRes) ? sampRes : lineRes;
1656 if (
target()->shape()->name() ==
"Plane") {
1657 QString msg =
"North Azimuth is not available for plane target shapes.";
1670 -90.0, 0.0) + 180.0;
1671 if (azimuth > 360.0) azimuth = azimuth - 360.0;
1803 const double lat,
const double lon) {
1814 SpiceDouble azimuthOrigin[3];
1817 if (!originRadius.
isValid()) {
1824 SpiceDouble pointOfInterestFromBodyCenter[3];
1826 lat *
PI / 180.0, pointOfInterestFromBodyCenter);
1834 SpiceDouble pointOfInterest[3];
1835 vsub_c(pointOfInterestFromBodyCenter, azimuthOrigin, pointOfInterest);
1841 SpiceDouble pointOfInterestProj[3];
1842 vperp_c(pointOfInterest, azimuthOrigin, pointOfInterestProj);
1845 SpiceDouble pointOfInterestProjUnit[3];
1846 vhat_c(pointOfInterestProj, pointOfInterestProjUnit);
1852 SpiceDouble pointOfInterestProjUnitScaled[3];
1853 vscl_c(scale, pointOfInterestProjUnit, pointOfInterestProjUnitScaled);
1858 SpiceDouble adjustedPointOfInterestFromBodyCenter[3];
1859 vadd_c(azimuthOrigin, pointOfInterestProjUnitScaled, adjustedPointOfInterestFromBodyCenter);
1862 double azimuthOriginSample =
Sample();
1863 double azimuthOriginLine =
Line();
1866 double adjustedPointOfInterestRad, adjustedPointOfInterestLon, adjustedPointOfInterestLat;
1867 reclat_c(adjustedPointOfInterestFromBodyCenter,
1868 &adjustedPointOfInterestRad,
1869 &adjustedPointOfInterestLon,
1870 &adjustedPointOfInterestLat);
1871 adjustedPointOfInterestLat = adjustedPointOfInterestLat * 180.0 /
PI;
1872 adjustedPointOfInterestLon = adjustedPointOfInterestLon * 180.0 /
PI;
1873 if (adjustedPointOfInterestLon < 0) adjustedPointOfInterestLon += 360.0;
1879 adjustedPointOfInterestLon,
1884 SetImage(azimuthOriginSample, azimuthOriginLine);
1888 double adjustedPointOfInterestSample =
Sample();
1889 double adjustedPointOfInterestLine =
Line();
1917 double deltaSample = adjustedPointOfInterestSample - azimuthOriginSample;
1918 double deltaLine = adjustedPointOfInterestLine - azimuthOriginLine;
1927 double azimuth = 0.0;
1928 if (deltaSample != 0.0 || deltaLine != 0.0) {
1929 azimuth = atan2(deltaLine, deltaSample);
1930 azimuth *= 180.0 /
PI;
1934 if (azimuth < 0.0) azimuth += 360.0;
1935 if (azimuth > 360.0) azimuth -= 360.0;
1943 SetImage(azimuthOriginSample, azimuthOriginLine);
1961 double coord[3], spCoord[3];
1966 double a = vsep_c(coord, spCoord) * 180.0 /
PI;
1970 double c = 180.0 - (a + b);
1999 double slat,
double slon) {
2003 a = (90.0 - slat) *
PI / 180.0;
2004 b = (90.0 - glat) *
PI / 180.0;
2007 a = (90.0 + slat) *
PI / 180.0;
2008 b = (90.0 + glat) *
PI / 180.0;
2011 double cslon = slon;
2012 double cglon = glon;
2013 if (cslon > cglon) {
2014 if ((cslon-cglon) > 180.0) {
2015 while ((cslon-cglon) > 180.0) cslon = cslon - 360.0;
2018 if (cglon > cslon) {
2019 if ((cglon-cslon) > 180.0) {
2020 while ((cglon-cslon) > 180.0) cglon = cglon - 360.0;
2027 if (cslon > cglon) {
2030 else if (cslon < cglon) {
2037 else if (slat < glat) {
2038 if (cslon > cglon) {
2041 else if (cslon < cglon) {
2049 if (cslon > cglon) {
2052 else if (cslon < cglon) {
2060 double C = (cglon - cslon) *
PI / 180.0;
2062 double c = acos(cos(a)*cos(b) + sin(a)*sin(b)*cos(C));
2063 double azimuth = 0.0;
2064 if (sin(b) == 0.0 || sin(c) == 0.0) {
2067 double A = acos((cos(a) - cos(b)*cos(c))/(sin(b)*sin(c))) * 180.0 /
PI;
2070 if (quad == 1 || quad == 4) {
2073 else if (quad == 2 || quad == 3) {
2074 azimuth = 360.0 - A;
2078 if (quad == 1 || quad == 4) {
2079 azimuth = 180.0 - A;
2081 else if (quad == 2 || quad == 3) {
2082 azimuth = 180.0 + A;
2176 int cacheSize =
CacheSize(ephemerisTimes.first, ephemerisTimes.second);
2184 double altitudeMeters;
2186 altitudeMeters = 1.0;
2199 setTime(ephemerisTimes.first);
2227 pair<double,double> ephemerisTimes;
2228 double startTime = -DBL_MAX;
2229 double endTime = -DBL_MAX;
2231 for (
int band = 1; band <=
Bands(); band++) {
2234 double etStart =
time().
Et();
2237 double etEnd =
time().
Et();
2239 startTime = min(etStart, etEnd);
2240 endTime = max(etStart, etEnd);
2242 startTime = min(startTime, min(etStart, etEnd));
2243 endTime = max(endTime, max(etStart, etEnd));
2245 if (startTime == -DBL_MAX || endTime == -DBL_MAX) {
2246 string msg =
"Unable to find time range for the spice kernels";
2249 ephemerisTimes.first = startTime;
2250 ephemerisTimes.second = endTime;
2251 return ephemerisTimes;
2272 if (startTime == endTime) {
2300 if (startSize == 2 && endSize == 2) {
2306 if (endSize > startSize) {
2307 IString message =
"Camera::SetGeometricTilingHint End size must be smaller than the start size";
2311 if (startSize < 4) {
2312 IString message =
"Camera::SetGeometricTilingHint Start size must be at least 4";
2316 bool foundEnd =
false;
2317 while (powerOf2 > 0 && startSize != powerOf2) {
2318 if (powerOf2 == endSize) foundEnd =
true;
2325 IString message =
"Camera::SetGeometricTilingHint Start size must be a power of 2";
2330 IString message =
"Camera::SetGeometricTilingHint End size must be a power of 2 less than the start size, but greater than 2";