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"
43class LineOffsetFunctor :
44 public std::function<double(double)> {
49 m_surfacePoint = surPt;
53 ~LineOffsetFunctor() {}
65 double lookC[3] = {0.0, 0.0, 0.0};
72 double startTime = m_camera->cacheStartTime().Et();
73 double endTime = m_camera->cacheEndTime().Et();
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);
91 ux = m_camera->FocalLength() * lookC[0] / lookC[2];
92 uy = m_camera->FocalLength() * lookC[1] / lookC[2];
115 if (m_camera->DistortionMap()->SetUndistortedFocalPlane(ux, uy)) {
117 dx = m_camera->DistortionMap()->FocalPlaneX();
118 dy = m_camera->DistortionMap()->FocalPlaneY();
125 if (!m_camera->FocalPlaneMap()->SetFocalPlane(dx, dy)) {
126 IString msg =
"FocalPlaneMap::SetFocalPlane failed for surface point in "
127 "LineScanCameraGroundMap.cpp LineOffsetFunctor";
132 return (m_camera->FocalPlaneMap()->DetectorLineOffset() -
133 m_camera->FocalPlaneMap()->DetectorLine());
43class LineOffsetFunctor : {
…};
148class SensorSurfacePointDistanceFunctor :
149 public std::function<double(double)> {
154 surfacePoint = surPt;
158 ~SensorSurfacePointDistanceFunctor() {}
161 double operator()(
double et) {
165 double startTime = m_camera->cacheStartTime().Et();
166 double endTime = m_camera->cacheEndTime().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";
178 m_camera->instrumentPosition(s);
179 m_camera->Coordinate(p);
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]) );
148class SensorSurfacePointDistanceFunctor : {
…};
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();
286 double lineRate = ((LineScanCameraDetectorMap *)
p_camera->DetectorMap())->LineRate();
288 if (lineRate == 0.0)
return Failure;
290 LineOffsetFunctor offsetFunc(
p_camera,surfacePoint);
291 SensorSurfacePointDistanceFunctor distanceFunc(
p_camera,surfacePoint);
295 if (approxLine >= 0.5) {
298 p_camera->DetectorMap()->SetParent(
p_camera->ParentSamples() / 2.0, approxLine);
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);
311 ux =
p_camera->FocalLength() * lookC[0] / lookC[2];
312 uy =
p_camera->FocalLength() * lookC[1] / lookC[2];
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);
366 ux =
p_camera->FocalLength() * lookC[0] / lookC[2];
367 uy =
p_camera->FocalLength() * lookC[1] / lookC[2];
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);
515 ux =
p_camera->FocalLength() * lookC[0] / lookC[2];
516 uy =
p_camera->FocalLength() * lookC[1] / lookC[2];
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) ) {
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);
605 ux =
p_camera->FocalLength() * lookC[0] / lookC[2];
606 uy =
p_camera->FocalLength() * lookC[1] / lookC[2];
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.
CameraGroundMap(Camera *parent)
Constructor.
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.
Distance measurement, usually in meters.
bool isValid() const
Test if this distance has been initialized or not.
@ 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.
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.
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.
This is free and unencumbered software released into the public domain.
Namespace for the standard library.