8#include "LineScanCameraGroundMap.h"
18#include "IException.h"
21#include "CameraDistortionMap.h"
22#include "CameraFocalPlaneMap.h"
24#include "LineScanCameraDetectorMap.h"
28#include "Statistics.h"
29#include "SurfacePoint.h"
30#include "FunctionTools.h"
36bool ptXLessThan(
const QList<double> l1,
const QList<double> l2);
44 public std::function<double(double)> {
49 m_surfacePoint = surPt;
65 double lookC[3] = {0.0, 0.0, 0.0};
74 if (et < startTime || et > endTime) {
75 IString msg =
"Ephemeris time passed to LineOffsetFunctor is not within the image "
80 m_camera->Sensor::setTime(et);
83 if (!m_camera->Sensor::SetGround(m_surfacePoint,
false)) {
84 IString msg =
"Sensor::SetGround failed for surface point in LineScanCameraGroundMap.cpp"
90 m_camera->Sensor::LookDirection(lookC);
126 IString msg =
"FocalPlaneMap::SetFocalPlane failed for surface point in "
127 "LineScanCameraGroundMap.cpp LineOffsetFunctor";
149 public std::function<double(double)> {
154 surfacePoint = surPt;
161 double operator()(
double et) {
168 if (et < startTime || et > endTime) {
169 IString msg =
"Ephemeris time passed to SensorSurfacePointDistanceFunctor is not within the image "
173 m_camera->Sensor::setTime(et);
174 if (!m_camera->Sensor::SetGround(surfacePoint,
false)) {
175 IString msg =
"Sensor::SetGround failed for surface point in LineScanCameraGroundMap.cpp"
176 "SensorSurfacePointDistanceFunctor";
180 return sqrt((s[0] - p[0]) * (s[0] - p[0]) +
181 (s[1] - p[1]) * (s[1] - p[1]) +
182 (s[2] - p[2]) * (s[2] - p[2]) );
216 if (radius.isValid()) {
234 FindFocalPlaneStatus status = FindFocalPlane(approxLine, surfacePoint);
235 if (status == Success)
return true;
248 FindFocalPlaneStatus status = FindFocalPlane(-1, surfacePoint);
250 if (status == Success)
return true;
256 double LineScanCameraGroundMap::FindSpacecraftDistance(
int line,
261 if (!
p_camera->Sensor::SetGround(surfacePoint,
false)) {
269 LineScanCameraGroundMap::FindFocalPlaneStatus
270 LineScanCameraGroundMap::FindFocalPlane(
const int &approxLine,
276 double approxTime = 0;
277 double approxOffset = 0;
278 double lookC[3] = {0.0, 0.0, 0.0};
283 const double cacheStart =
p_camera->Spice::cacheStartTime().Et();
284 const double cacheEnd =
p_camera->Spice::cacheEndTime().Et();
288 if (lineRate == 0.0)
return Failure;
295 if (approxLine >= 0.5) {
301 approxOffset = offsetFunc(approxTime);
304 if (fabs(approxOffset) < 1e-2) {
305 p_camera->Sensor::setTime(approxTime);
307 if (!
p_camera->Sensor::SetGround(surfacePoint,
true)) {
310 p_camera->Sensor::LookDirection(lookC);
320 double fl, fh, xl, xh;
324 if (xh + lineRate < cacheEnd) {
336 for (
int j=0; j < 10; j++) {
340 double etGuess = xl + (xh - xl) * fl / (fl - fh);
342 if (etGuess < cacheStart) etGuess = cacheStart;
343 if (etGuess > cacheEnd) etGuess = cacheEnd;
345 double f = offsetFunc(etGuess);
349 if (fabs( xl- etGuess) > fabs( xh - etGuess)) {
359 if (fabs(f) < 1e-2) {
360 p_camera->Sensor::setTime(approxTime);
362 if (!
p_camera->Sensor::SetGround(surfacePoint,
true)) {
365 p_camera->Sensor::LookDirection(lookC);
385 double offsetNodes[3];
390 QList<double> offset;
393 timeNodes[0] = cacheStart;
394 timeNodes[2] = cacheEnd;
395 timeNodes[1] = (cacheStart+cacheEnd) / 2.0;
400 for (
int i=0; i<3; i++) {
401 offsetNodes[i] = offsetFunc(timeNodes[i]);
405 timeAverage = (timeNodes[0] + timeNodes[1] + timeNodes[2]) / 3.0;
406 timeNodes[0] -= timeAverage;
407 timeNodes[1] -= timeAverage;
408 timeNodes[2] -= timeAverage;
410 scale = 1.0 / sqrt((timeNodes[0] - timeNodes[2]) *
411 (timeNodes[0] - timeNodes[2]) +
412 (offsetNodes[0] - offsetNodes[2]) *
413 (offsetNodes[0] - offsetNodes[2]));
415 timeNodes[0] *= scale;
416 timeNodes[1] *= scale;
417 timeNodes[2] *= scale;
419 offsetNodes[0] *= scale;
420 offsetNodes[1] *= scale;
421 offsetNodes[2] *= scale;
426 quadPoly[0] = quadPoly[1] = quadPoly[2] = 0.0;
428 temp = offsetNodes[0] / ((timeNodes[0] - timeNodes[1]) * (timeNodes[0] - timeNodes[2]));
430 quadPoly[1] += temp * (-timeNodes[1] - timeNodes[2]);
431 quadPoly[2] += temp * timeNodes[1] * timeNodes[2];
433 temp = offsetNodes[1] / ((timeNodes[1] - timeNodes[0]) * (timeNodes[1] - timeNodes[2]));
435 quadPoly[1] += temp * (-timeNodes[0] - timeNodes[2]);
436 quadPoly[2] += temp * timeNodes[0] * timeNodes[2];
438 temp = offsetNodes[2] / ((timeNodes[2] - timeNodes[0]) * (timeNodes[2] - timeNodes[1]));
440 quadPoly[1] += temp * (-timeNodes[0] - timeNodes[1]);
441 quadPoly[2] += temp * timeNodes[0] * timeNodes[1];
445 temp = quadPoly[1] * quadPoly[1] - 4.0 * quadPoly[0] * quadPoly[2];
452 if (quadPoly[1] >= 0.0) {
453 temp = -0.5 * (quadPoly[1] + sqrt(temp));
456 temp = -0.5 * (quadPoly[1] - sqrt(temp));
459 if (quadPoly[0] != 0.0) {
460 root.push_back(temp/quadPoly[0]);
463 if (quadPoly[2] != 0.0) {
464 root.push_back(quadPoly[2]/temp);
468 for (
int i=root.size()-1; i>=0; i--) {
469 if ( root[i] < timeNodes[0] || root[i] > timeNodes[2] ) {
475 for (
int i=0; i<root.size(); i++) {
476 root[i] = root[i]/scale + timeAverage;
480 if (root.size() == 0) {
490 for (
int i=0; i<root.size(); i++) {
491 dist << distanceFunc(root[i]);
492 offset << offsetFunc(root[i]);
498 for (
int i=1; i<root.size(); i++) {
499 if (dist[i] < dist[j]) j=i;
502 approxTime = root[j];
503 approxOffset = offset[j];
506 if (fabs(approxOffset) < 1.0e-2) {
507 p_camera->Sensor::setTime(approxTime);
510 if (!
p_camera->Sensor::SetGround(surfacePoint,
true)) {
514 p_camera->Sensor::LookDirection(lookC);
541 QList <QList <double> > pts;
543 for (
int i=0; i<3; i++) {
545 pt << timeNodes[i] / scale + timeAverage;
546 pt << offsetNodes[i] / scale;
550 for (
int i=0; i<root.size(); i++) {
557 std::sort(pts.begin(), pts.end(), ptXLessThan);
560 for (
int i=1; i<pts.size(); i++) {
562 if ( (pts[i-1][1] > 0) - (pts[i-1][1] < 0) != (pts[i][1] > 0) - (pts[i][1] < 0) ) {
564 if (FunctionTools::brentsRootFinder <LineOffsetFunctor> (offsetFunc, pts[i-1], pts[i],
565 1.0e-3, 200, temp)) {
572 for (
int i = root.size()-1; i>=0; i--) {
575 if (!
p_camera->Sensor::SetGround(surfacePoint,
true)) {
581 if (root.size() == 0) {
588 for (
int i=0; i<root.size(); i++) {
589 dist << distanceFunc(root[i]);
590 offset << offsetFunc(root[i]);
596 for (
int i=1; i<root.size(); i++) {
597 if (dist[i] < dist[j]) j=i;
604 p_camera->Sensor::LookDirection(lookC);
616bool ptXLessThan(
const QList<double> l1,
const QList<double> l2) {
617 return l1[0] < l2[0];
Convert between parent image coordinates and detector coordinates.
virtual bool SetParent(const double sample, const double line)
Compute detector position from a parent image coordinate.
virtual bool SetUndistortedFocalPlane(double ux, double uy)
Compute distorted focal plane x/y.
double FocalPlaneX() const
Gets the x-value in the focal plane coordinate system.
double FocalPlaneY() const
Gets the y-value in the focal plane coordinate system.
double DetectorLine() const
virtual bool SetFocalPlane(const double dx, const double dy)
Compute detector position (sample,line) from focal plane coordinates.
double DetectorLineOffset() const
Convert between undistorted focal plane and ground coordinates.
double p_focalPlaneX
Camera's x focal plane coordinate.
double p_focalPlaneY
Camera's y focal plane coordinate.
CameraDetectorMap * DetectorMap()
Returns a pointer to the CameraDetectorMap object.
int ParentSamples() const
Returns the number of samples in the parent alphacube.
double FocalLength() const
Returns the focal length.
CameraDistortionMap * DistortionMap()
Returns a pointer to the CameraDistortionMap object.
CameraFocalPlaneMap * FocalPlaneMap()
Returns a pointer to the CameraFocalPlaneMap object.
Distance measurement, usually in meters.
@ Programmer
This error is for when a programmer made an API call that was illegal.
Adds specific functionality to C++ strings.
This class is designed to encapsulate the concept of a Latitude.
Convert between parent image coordinates and detector coordinates.
LineScanCameraGroundMap(Camera *cam)
Constructor.
virtual bool SetGround(const Latitude &lat, const Longitude &lon)
Compute undistorted focal plane coordinate from ground position.
virtual ~LineScanCameraGroundMap()
Destructor.
This class is designed to encapsulate the concept of a Longitude.
virtual double SlantDistance() const
Return the distance between the spacecraft and surface point in kmv.
void Coordinate(double p[3]) const
Returns the x,y,z of the surface intersection in BodyFixed km.
Distance LocalRadius() const
Returns the local radius at the intersection point.
virtual iTime cacheEndTime() const
Accessor method for the cache end time.
void instrumentPosition(double p[3]) const
Returns the spacecraft position in body-fixed frame km units.
virtual iTime time() const
Returns the ephemeris time in seconds which was used to obtain the spacecraft and sun positions.
virtual iTime cacheStartTime() const
Accessor method for the cache start time.
This class defines a body-fixed surface point.
double operator()(double et)
Compute the number of lines between the current line (i.e., the line imaged at the et as set in the c...
This is free and unencumbered software released into the public domain.
Namespace for the standard library.