Isis 3 Programmer Reference
ShapeModel.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "ShapeModel.h"
8
9#include <QDebug>
10
11#include <algorithm>
12#include <cfloat>
13#include <iostream>
14#include <iomanip>
15#include <vector>
16
17#include <cmath>
18
19#include <SpiceUsr.h>
20#include <SpiceZfc.h>
21#include <SpiceZmc.h>
22
23#include "Distance.h"
24#include "SurfacePoint.h"
25#include "IException.h"
26#include "IString.h"
27#include "NaifStatus.h"
28#include "Spice.h"
29#include "Target.h"
30
31using namespace std;
32
33namespace Isis {
41 Initialize();
42 m_target = NULL;
43 }
44
45
57 Initialize();
58 m_target = target;
59 }
60
61
66 m_name = new QString();
68 m_hasIntersection = false;
69 m_hasNormal = false;
70 m_hasLocalNormal = false;
71 m_normal.resize(3,0.);
72 m_localNormal.resize(3, 0.);
74 }
75
76
79
80 delete m_name;
81 m_name = NULL;
82
83 delete m_surfacePoint;
84 m_surfacePoint = NULL;
85 }
86
87
105 bool ShapeModel::intersectSurface(const Latitude &lat, const Longitude &lon,
106 const std::vector<double> &observerPos,
107 const bool &backCheck) {
108 // Distance radius = localRadius(lat, lon);
109 return (intersectSurface(SurfacePoint(lat, lon, localRadius(lat, lon)), observerPos, backCheck));
110 }
111
112
129 bool ShapeModel::intersectSurface(const SurfacePoint &surfpt,
130 const std::vector<double> &observerPos,
131 const bool &backCheck) {
132
133 // The default behavior is to set the point in the model without
134 // intersection tests at all
135 setSurfacePoint(surfpt);
136 return (true);
137 }
138
143 // The below code is not truly normal unless the ellipsoid is a sphere. TODO Should this be
144 // fixed? Send an email asking Jeff and Stuart. See Naif routine surfnm.c to get the true
145 // for an ellipsoid. For testing purposes to match old results do as Isis currently does until
146 // Jeff and Stuart respond.
147
148 if (!m_hasIntersection || !surfaceIntersection()->Valid()) {
149 QString msg = "A valid intersection must be defined before computing the surface normal";
150 throw IException(IException::Programmer, msg, _FILEINFO_);
151 }
152
153 // Get the coordinates of the current surface point
154 SpiceDouble pB[3];
155 pB[0] = surfaceIntersection()->GetX().kilometers();
156 pB[1] = surfaceIntersection()->GetY().kilometers();
157 pB[2] = surfaceIntersection()->GetZ().kilometers();
158
159 // Unitize the vector
160 SpiceDouble upB[3];
161 SpiceDouble dist;
162 unorm_c(pB, upB, &dist);
163 memcpy(&m_normal[0], upB, sizeof(double) * 3);
164
165 m_hasNormal = true;
166 }
167
168
187 double ShapeModel::emissionAngle(const std::vector<double> &observerBodyFixedPosition) {
188
189 // Calculate the surface normal if we haven't yet
190 if (!hasNormal()) calculateDefaultNormal();
191
192 // Get vector from center of body to surface point
193 SpiceDouble pB[3];
194 pB[0] = surfaceIntersection()->GetX().kilometers();
195 pB[1] = surfaceIntersection()->GetY().kilometers();
196 pB[2] = surfaceIntersection()->GetZ().kilometers();
197
198 // Get vector from surface point to observer and normalize it
199 SpiceDouble psB[3], upsB[3], dist;
200 vsub_c((ConstSpiceDouble *) &observerBodyFixedPosition[0], pB, psB);
201 unorm_c(psB, upsB, &dist);
202
203 double angle = vdot_c((SpiceDouble *) &m_normal[0], upsB);
204 if(angle > 1.0) return 0.0;
205 if(angle < -1.0) return 180.0;
206 return acos(angle) * RAD2DEG;
207 }
208
209
218
219
234 double ShapeModel::incidenceAngle(const std::vector<double> &illuminatorBodyFixedPosition) {
235
236 // Calculate the surface normal if we haven't yet.
237 if (!hasNormal()) calculateDefaultNormal();
238
239 // Get vector from center of body to surface point
240 SpiceDouble pB[3];
241 pB[0] = surfaceIntersection()->GetX().kilometers();
242 pB[1] = surfaceIntersection()->GetY().kilometers();
243 pB[2] = surfaceIntersection()->GetZ().kilometers();
244
245 // Get vector from surface point to sun and normalize it
246 SpiceDouble puB[3], upuB[3], dist;
247 vsub_c((SpiceDouble *) &illuminatorBodyFixedPosition[0], pB, puB);
248 unorm_c(puB, upuB, &dist);
249
250 double angle = vdot_c((SpiceDouble *) &m_normal[0], upuB);
251 if(angle > 1.0) return 0.0;
252 if(angle < -1.0) return 180.0;
253 return acos(angle) * RAD2DEG;
254 }
255
256
269 bool ShapeModel::intersectEllipsoid(const std::vector<double> observerBodyFixedPosition,
270 const std::vector<double> &observerLookVectorToTarget) {
271
272 // Clear out previous surface point and normal
274
275 SpiceDouble lookB[3];
276
277 // This memcpy does:
278 // lookB[0] = observerLookVectorToTarget[0];
279 // lookB[1] = observerLookVectorToTarget[1];
280 // lookB[2] = observerLookVectorToTarget[2];
281 memcpy(lookB,&observerLookVectorToTarget[0], 3*sizeof(double));
282
283 // get target radii
284 std::vector<Distance> radii = targetRadii();
285 SpiceDouble a = radii[0].kilometers();
286 SpiceDouble b = radii[1].kilometers();
287 SpiceDouble c = radii[2].kilometers();
288
289 // check if observer look vector intersects the target
290 SpiceDouble intersectionPoint[3];
291 SpiceBoolean intersected = false;
292
294 surfpt_c((SpiceDouble *) &observerBodyFixedPosition[0], lookB, a, b, c,
295 intersectionPoint, &intersected);
297
298 if (intersected) {
299 m_surfacePoint->FromNaifArray(intersectionPoint);
300 m_hasIntersection = true;
301 }
302 else {
303 m_hasIntersection = false;
304 }
305
307 return m_hasIntersection;
308 }
309
310
326 double ShapeModel::phaseAngle(const std::vector<double> &observerBodyFixedPosition,
327 const std::vector<double> &illuminatorBodyFixedPosition) {
328
329 // Get vector from center of body to surface point
330 SpiceDouble pB[3];
331 pB[0] = surfaceIntersection()->GetX().kilometers();
332 pB[1] = surfaceIntersection()->GetY().kilometers();
333 pB[2] = surfaceIntersection()->GetZ().kilometers();
334
335 // Get vector from surface point to observer and normalize it
336 SpiceDouble psB[3], upsB[3], dist;
337 vsub_c((SpiceDouble *) &observerBodyFixedPosition[0], pB, psB);
338 unorm_c(psB, upsB, &dist);
339
340 // Get vector from surface point to sun and normalize it
341 SpiceDouble puB[3], upuB[3];
342 vsub_c((SpiceDouble *) &illuminatorBodyFixedPosition[0], pB, puB);
343 unorm_c(puB, upuB, &dist);
344
345 double angle = vdot_c(upsB, upuB);
346
347 // How can these lines be tested???
348 if(angle > 1.0) return 0.0;
349 if(angle < -1.0) return 180.0;
350 return acos(angle) * RAD2DEG;
351 }
352
353
363
364
373
374
381 return m_hasNormal;
382 }
383
384
391 return m_hasLocalNormal;
392 }
393
394
402
403
413 std::vector<double> ShapeModel::normal() {
414 if (m_hasNormal ) {
415 return m_normal;
416 }
417 else {
418 QString message = "The normal has not been computed.";
419 throw IException(IException::Unknown, message, _FILEINFO_);
420 }
421 }
422
432 std::vector<double> ShapeModel::localNormal() {
433 if (m_hasLocalNormal ) {
434 return m_localNormal;
435 }
436 else {
437 QString message = "The local normal has not been computed.";
438 throw IException(IException::Unknown, message, _FILEINFO_);
439 }
440 }
441
461 bool ShapeModel::isVisibleFrom(const std::vector<double> observerPos,
462 const std::vector<double> lookDirection) {
463 if ( hasIntersection() ) {
464 if ( fabs(emissionAngle(observerPos)) <= 90.0 ) {
465 return (true);
466 }
467 }
468
469 // All other conditions indicate the point is not visable from the observer
470 return (false);
471 }
472
480 return (m_target != NULL);
481 }
482
483
495 std::vector<Distance> ShapeModel::targetRadii() const {
496 if (hasValidTarget()) {
497 return m_target->radii();
498 }
499 else {
500 QString message = "Unable to find target radii for ShapeModel. Target is NULL. ";
501 throw IException(IException::Programmer, message, _FILEINFO_);
502 }
503 }
504
505
517 void ShapeModel::setNormal(const std::vector<double> normal) {
518 if (m_hasIntersection) {
520 m_hasNormal = true;
521 }
522 else {
523 QString message = "No intersection point is known. A normal cannot be set.";
524 throw IException(IException::Unknown, message, _FILEINFO_);
525 }
526 }
527
539 void ShapeModel::setLocalNormal(const std::vector<double> normal) {
540 if (m_hasIntersection) {
542 m_hasLocalNormal = true;
543 }
544 else {
545 QString message = "No intersection point is known. A local normal cannot be set.";
546 throw IException(IException::Unknown, message, _FILEINFO_);
547 }
548 }
549
550
564 void ShapeModel::setNormal(const double a, const double b, const double c) {
565 if (m_hasIntersection) {
566 m_normal[0] = a;
567 m_normal[1] = b;
568 m_normal[2] = c;
569 m_hasNormal = true;
570 }
571 else {
572 QString message = "No intersection point is known. A normal cannot be set.";
573 throw IException(IException::Unknown, message, _FILEINFO_);
574 }
575 }
576
590 void ShapeModel::setLocalNormal(const double a, const double b, const double c) {
591 if (m_hasIntersection) {
592 m_localNormal[0] = a;
593 m_localNormal[1] = b;
594 m_localNormal[2] = c;
595 m_hasLocalNormal = true;
596 }
597 else {
598 QString message = "No intersection point is known. A local normal cannot be set.";
599 throw IException(IException::Unknown, message, _FILEINFO_);
600 }
601 }
602
609 void ShapeModel::setName(QString name) {
610 *m_name = name;
611 }
612
613
620 QString ShapeModel::name() const{
621 return *m_name;
622 }
623
624
633 setHasNormal(false);
634 setHasLocalNormal(false);
635 }
636
637
643 void ShapeModel::setSurfacePoint(const SurfacePoint &surfacePoint) {
644 *m_surfacePoint = surfacePoint;
645
646 // Update status of intersection and normal
647 m_hasIntersection = true;
648 // Set normal as not calculated
649 setHasNormal(false);
650 setHasLocalNormal(false);
651 }
652
653
660 void ShapeModel::setHasNormal(bool status) {
661 m_hasNormal = status;
662 }
663
671 m_hasLocalNormal = status;
672 }
673
674
683 return m_target->spice()->resolution();
684 }
685 else {
686 QString message = "No valid intersection point for computing resolution.";
687 throw IException(IException::Programmer, message, _FILEINFO_);
688 }
689 }
690
691}
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
This class is designed to encapsulate the concept of a Latitude.
Definition Latitude.h:51
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
double resolution()
Convenience method to get pixel resolution (m/pix) at current intersection point.
virtual void clearSurfacePoint()
Clears or resets the current surface point.
void setHasNormal(bool status)
Sets the flag to indicate whether this ShapeModel has a surface normal.
bool hasIntersection()
Returns intersection status.
void Initialize()
Initializes the ShapeModel private variables.
bool m_hasNormal
indicates normal has been computed
Definition ShapeModel.h:186
virtual ~ShapeModel()=0
Virtual destructor to destroy the ShapeModel object.
bool hasLocalNormal() const
Returns surface point local normal status.
void setHasIntersection(bool b)
Sets the flag to indicate whether this ShapeModel has an intersection.
void setNormal(const std::vector< double >)
Sets the surface normal for the currect intersection point.
void setLocalNormal(const std::vector< double >)
Sets the local normal for the currect intersection point.
virtual SurfacePoint * surfaceIntersection() const
Returns the surface intersection for this ShapeModel.
SurfacePoint * m_surfacePoint
< Name of the shape
Definition ShapeModel.h:191
bool m_hasEllipsoidIntersection
Indicates the ellipsoid was successfully intersected.
Definition ShapeModel.h:184
bool hasValidTarget() const
Returns the status of the target.
virtual double emissionAngle(const std::vector< double > &sB)
Computes and returns emission angle, in degrees, given the observer position.
QString name() const
Gets the shape name.
void calculateEllipsoidalSurfaceNormal()
Calculates the ellipsoidal surface normal.
virtual bool isVisibleFrom(const std::vector< double > observerPos, const std::vector< double > lookDirection)
Default occulsion implementation.
bool intersectEllipsoid(const std::vector< double > observerPosRelativeToTarget, const std::vector< double > &observerLookVectorToTarget)
Finds the intersection point on the ellipsoid model using the given position of the observer (spacecr...
bool m_hasIntersection
indicates good intersection exists
Definition ShapeModel.h:185
virtual double incidenceAngle(const std::vector< double > &uB)
Computes and returns incidence angle, in degrees, given the illuminator position.
bool hasEllipsoidIntersection()
Returns the status of the ellipsoid model intersection.
virtual void setSurfacePoint(const SurfacePoint &surfacePoint)
Set surface intersection point.
virtual double phaseAngle(const std::vector< double > &sB, const std::vector< double > &uB)
Computes and returns phase angle, in degrees, given the positions of the observer and illuminator.
virtual std::vector< double > normal()
Returns the surface normal at the current intersection point.
virtual std::vector< double > localNormal()
Returns the local surface normal at the current intersection point.
std::vector< Distance > targetRadii() const
Returns the radii of the body in km.
void setHasLocalNormal(bool status)
Sets the flag to indicate whether this ShapeModel has a local normal.
ShapeModel()
Default constructor creates ShapeModel object, initializing name to an empty string,...
bool m_hasLocalNormal
indicates local normal has been computed
Definition ShapeModel.h:187
std::vector< double > m_normal
Surface normal of current intersection point.
Definition ShapeModel.h:188
std::vector< double > m_localNormal
Local normal of current intersection point.
Definition ShapeModel.h:189
bool hasNormal() const
Returns surface point normal status.
void setName(QString name)
Sets the shape name.
virtual double resolution()
Virtual method that returns the pixel resolution of the sensor in meters/pix.
Definition Spice.cpp:1016
This class defines a body-fixed surface point.
void FromNaifArray(const double naifValues[3])
A naif array is a c-style array of size 3.
This class is used to create and store valid Isis targets.
Definition Target.h:63
Spice * spice() const
Return the spice object.
Definition Target.cpp:688
std::vector< Distance > radii() const
Returns the radii of the body in km.
Definition Target.cpp:557
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition Constants.h:44
Namespace for the standard library.