USGS

Isis 3.0 Object Programmers' Reference

Home

PushFrameCameraGroundMap.cpp

Go to the documentation of this file.
00001 
00023 #include "PushFrameCameraGroundMap.h"
00024 
00025 #include "CameraDistortionMap.h"
00026 #include "CameraFocalPlaneMap.h"
00027 #include "Latitude.h"
00028 #include "Longitude.h"
00029 #include "PushFrameCameraDetectorMap.h"
00030 #include "SurfacePoint.h"
00031 
00032 namespace Isis {
00041   bool PushFrameCameraGroundMap::SetGround(const Latitude &lat,
00042                                            const Longitude &lon) {
00043     PushFrameCameraDetectorMap *detectorMap = (PushFrameCameraDetectorMap *) p_camera->DetectorMap();
00044 
00045     SurfacePoint surfacePoint(lat, lon, p_camera->LocalRadius(lat, lon));
00046 
00047     // Get ending bounding framelets and distances for iterative loop to minimize the spacecraft distance
00048     int startFramelet = 1;
00049     double startDist = FindSpacecraftDistance(1, surfacePoint);
00050 
00051     int endFramelet = detectorMap->TotalFramelets();
00052     double endDist = FindSpacecraftDistance(endFramelet, surfacePoint);
00053 
00054     bool minimizedSpacecraftDist = false;
00055 
00056     for(int j = 0; j < 30 && !minimizedSpacecraftDist; j++) {
00057       int deltaX = abs(startFramelet - endFramelet) / 2;
00058 
00059       // start + deltaX = middle framelet.
00060       //  We're able to optimize this modified binary search
00061       //  because the 'V' shape -- it's mostly parallel. Meaning,
00062       //  if the left side is higher than the right, then the
00063       //  solution is closer to the right. The bias factor will
00064       //  determine how much closer, and then back off a little so
00065       //  we dont overshoot it.
00066       double biasFactor = startDist / endDist;
00067 
00068       if(biasFactor < 1.0) {
00069         biasFactor = -1.0 / biasFactor;
00070         biasFactor = -(biasFactor + 1) / biasFactor;
00071 
00072         // The bias is about 50% unsure... sometimes our V is a U
00073         biasFactor = std::min(biasFactor + 0.50, 0.0);
00074       }
00075       else {
00076         biasFactor = (biasFactor - 1) / biasFactor;
00077 
00078         // The bias is about 50% unsure... sometimes our V is a U
00079         biasFactor = std::max(biasFactor - 0.50, 0.0);
00080       }
00081 
00082       int middleFramelet = startFramelet + (int)(deltaX + biasFactor * deltaX);
00083       double middleDist = FindSpacecraftDistance(middleFramelet, surfacePoint);
00084 
00085       if(startDist > endDist) {
00086         // This makes sure we don't get stuck halfway between framelets
00087         if(startFramelet == middleFramelet) middleFramelet++;
00088         startFramelet = middleFramelet;
00089         startDist = middleDist;
00090       }
00091       else {
00092         endFramelet = middleFramelet;
00093         endDist = middleDist;
00094       }
00095 
00096       if(startFramelet == endFramelet) {
00097         minimizedSpacecraftDist = true;
00098       }
00099     }
00100 
00101     if(!minimizedSpacecraftDist) {
00102       return false;
00103     }
00104 
00105     int realFramelet = startFramelet;
00106     bool frameletEven = (realFramelet % 2 == 0);
00107     bool timeAscendingFramelets = detectorMap->timeAscendingFramelets();
00108 
00109     // Do we need to find a neighboring framelet? Get the closest (minimize distance)
00110     if((timeAscendingFramelets && frameletEven != p_evenFramelets) ||
00111         (!timeAscendingFramelets && frameletEven == p_evenFramelets)) {
00112       realFramelet ++; // this direction doesnt really matter... it's simply a guess
00113     }
00114 
00115     int direction = 2;
00116 
00117     double realDist = FindDistance(realFramelet, surfacePoint);
00118     int guessFramelet = realFramelet + direction;
00119     double guessDist = FindDistance(guessFramelet, surfacePoint);
00120 
00121     if(guessDist > realDist) {
00122       direction = -1 * direction; // reverse the search direction
00123       guessFramelet = realFramelet + direction;
00124       guessDist = FindDistance(guessFramelet, surfacePoint);
00125     }
00126 
00127     for(int j = 0; (realDist >= guessDist) && (j < 30); j++) {
00128       realFramelet = guessFramelet;
00129       realDist = guessDist;
00130 
00131       guessFramelet = realFramelet + direction;
00132       guessDist = FindDistance(guessFramelet, surfacePoint);
00133 
00134       if(realFramelet <= 0 || realFramelet > detectorMap->TotalFramelets()) {
00135         return false;
00136       }
00137     }
00138 
00139     detectorMap->SetFramelet(realFramelet);
00140 
00141     return CameraGroundMap::SetGround(surfacePoint);
00142   }
00143 
00144 
00145   bool PushFrameCameraGroundMap::SetGround(const SurfacePoint &surfacePt) {
00146     return SetGround(surfacePt.GetLatitude(), surfacePt.GetLongitude());
00147   }
00148 
00149 
00160   double PushFrameCameraGroundMap::FindDistance(int framelet,
00161       const SurfacePoint &surfacePoint) {
00162     PushFrameCameraDetectorMap *detectorMap = (PushFrameCameraDetectorMap *) p_camera->DetectorMap();
00163     CameraDistortionMap *distortionMap = (CameraDistortionMap *) p_camera->DistortionMap();
00164 
00165     detectorMap->SetFramelet(framelet);
00166     if(!p_camera->Sensor::SetGround(surfacePoint, false)) return DBL_MAX;
00167 
00168     double lookC[3];
00169     p_camera->Sensor::LookDirection(lookC);
00170     double ux = p_camera->FocalLength() * lookC[0] / lookC[2];
00171     double uy = p_camera->FocalLength() * lookC[1] / lookC[2];
00172 
00173     if(!distortionMap->SetUndistortedFocalPlane(ux, uy)) return DBL_MAX;
00174 
00175     double dx = distortionMap->FocalPlaneX();
00176     double dy = distortionMap->FocalPlaneY();
00177 
00178     CameraFocalPlaneMap *focalMap = p_camera->FocalPlaneMap();
00179     if(!focalMap->SetFocalPlane(dx, dy)) return DBL_MAX;
00180 
00181     detectorMap->SetDetector(focalMap->DetectorSample(), focalMap->DetectorLine());
00182 
00183     double actualFrameletHeight = detectorMap->frameletHeight() / detectorMap->LineScaleFactor();
00184     double frameletDeltaY = detectorMap->frameletLine() - (actualFrameletHeight / 2.0);
00185 
00186     return frameletDeltaY * frameletDeltaY;
00187   }
00188 
00199   double PushFrameCameraGroundMap::FindSpacecraftDistance(int framelet,
00200       const SurfacePoint &surfacePoint) {
00201     PushFrameCameraDetectorMap *detectorMap = (PushFrameCameraDetectorMap *) p_camera->DetectorMap();
00202 
00203     detectorMap->SetFramelet(framelet);
00204     if(!p_camera->Sensor::SetGround(surfacePoint, false)) return DBL_MAX;
00205 
00206     return p_camera->SlantDistance();
00207   }
00208 }