32 ShapeModel::ShapeModel() {
48 ShapeModel::ShapeModel(
Target *target) {
57 void ShapeModel::Initialize() {
58 m_name =
new QString();
60 m_hasIntersection =
false;
62 m_normal.resize(3,0.);
63 m_hasEllipsoidIntersection =
false;
68 ShapeModel::~ShapeModel() {
73 delete m_surfacePoint;
74 m_surfacePoint = NULL;
81 void ShapeModel::calculateEllipsoidalSurfaceNormal() {
87 if (!m_hasIntersection || !surfaceIntersection()->Valid()) {
88 QString msg =
"A valid intersection must be defined before computing the surface normal";
94 pB[0] = surfaceIntersection()->GetX().kilometers();
95 pB[1] = surfaceIntersection()->GetY().kilometers();
96 pB[2] = surfaceIntersection()->GetZ().kilometers();
101 unorm_c(pB, upB, &dist);
102 memcpy(&m_normal[0], upB,
sizeof(
double) * 3);
126 double ShapeModel::emissionAngle(
const std::vector<double> &observerBodyFixedPosition) {
129 if (!hasNormal()) calculateDefaultNormal();
133 pB[0] = surfaceIntersection()->GetX().kilometers();
134 pB[1] = surfaceIntersection()->GetY().kilometers();
135 pB[2] = surfaceIntersection()->GetZ().kilometers();
138 SpiceDouble psB[3], upsB[3], dist;
139 vsub_c((ConstSpiceDouble *) &observerBodyFixedPosition[0], pB, psB);
140 unorm_c(psB, upsB, &dist);
142 double angle = vdot_c((SpiceDouble *) &m_normal[0], upsB);
143 if(angle > 1.0)
return 0.0;
144 if(angle < -1.0)
return 180.0;
154 bool ShapeModel::hasEllipsoidIntersection() {
155 return m_hasEllipsoidIntersection;
173 double ShapeModel::incidenceAngle(
const std::vector<double> &illuminatorBodyFixedPosition) {
176 if (!m_hasNormal) calculateDefaultNormal();
180 pB[0] = surfaceIntersection()->GetX().kilometers();
181 pB[1] = surfaceIntersection()->GetY().kilometers();
182 pB[2] = surfaceIntersection()->GetZ().kilometers();
185 SpiceDouble puB[3], upuB[3], dist;
186 vsub_c((SpiceDouble *) &illuminatorBodyFixedPosition[0], pB, puB);
187 unorm_c(puB, upuB, &dist);
189 double angle = vdot_c((SpiceDouble *) &m_normal[0], upuB);
190 if(angle > 1.0)
return 0.0;
191 if(angle < -1.0)
return 180.0;
208 bool ShapeModel::intersectEllipsoid(
const std::vector<double> observerBodyFixedPosition,
209 const std::vector<double> &observerLookVectorToTarget) {
214 SpiceDouble lookB[3];
220 memcpy(lookB,&observerLookVectorToTarget[0], 3*
sizeof(
double));
223 std::vector<Distance> radii = targetRadii();
224 SpiceDouble a = radii[0].kilometers();
225 SpiceDouble b = radii[1].kilometers();
226 SpiceDouble c = radii[2].kilometers();
229 SpiceDouble intersectionPoint[3];
230 SpiceBoolean intersected =
false;
232 NaifStatus::CheckErrors();
233 surfpt_c((SpiceDouble *) &observerBodyFixedPosition[0], lookB, a, b, c,
234 intersectionPoint, &intersected);
235 NaifStatus::CheckErrors();
238 m_surfacePoint->FromNaifArray(intersectionPoint);
239 m_hasIntersection =
true;
242 m_hasIntersection =
false;
245 m_hasEllipsoidIntersection = m_hasIntersection;
246 return m_hasIntersection;
265 double ShapeModel::phaseAngle(
const std::vector<double> &observerBodyFixedPosition,
266 const std::vector<double> &illuminatorBodyFixedPosition) {
270 pB[0] = surfaceIntersection()->GetX().kilometers();
271 pB[1] = surfaceIntersection()->GetY().kilometers();
272 pB[2] = surfaceIntersection()->GetZ().kilometers();
275 SpiceDouble psB[3], upsB[3], dist;
276 vsub_c((SpiceDouble *) &observerBodyFixedPosition[0], pB, psB);
277 unorm_c(psB, upsB, &dist);
280 SpiceDouble puB[3], upuB[3];
281 vsub_c((SpiceDouble *) &illuminatorBodyFixedPosition[0], pB, puB);
282 unorm_c(puB, upuB, &dist);
284 double angle = vdot_c(upsB, upuB);
287 if(angle > 1.0)
return 0.0;
288 if(angle < -1.0)
return 180.0;
300 return m_surfacePoint;
309 bool ShapeModel::hasIntersection() {
310 return m_hasIntersection;
319 bool ShapeModel::hasNormal()
const {
327 void ShapeModel::clearSurfacePoint() {
328 setHasIntersection(
false);
329 m_hasEllipsoidIntersection =
false;
342 std::vector<double> ShapeModel::normal() {
347 QString message =
"The local normal has not been computed.";
360 bool ShapeModel::hasValidTarget()
const {
361 return (m_target != NULL);
376 std::vector<Distance> ShapeModel::targetRadii()
const {
377 if (hasValidTarget()) {
378 return m_target->radii();
381 QString message =
"Unable to find target radii for ShapeModel. Target is NULL. ";
398 void ShapeModel::setNormal(
const std::vector<double> normal) {
399 if (m_hasIntersection) {
404 QString message =
"No intersection point in known. A normal can not be set.";
423 void ShapeModel::setNormal(
const double a,
const double b,
const double c) {
424 if (m_hasIntersection) {
431 QString message =
"No intersection point in known. A normal can not be set.";
443 void ShapeModel::setName(QString name) {
454 QString ShapeModel::name()
const{
465 void ShapeModel::setHasIntersection(
bool b) {
466 m_hasIntersection = b;
477 *m_surfacePoint = surfacePoint;
480 m_hasIntersection =
true;
492 void ShapeModel::setHasNormal(
bool status) {
493 m_hasNormal = status;
503 double ShapeModel::resolution() {
504 if (hasValidTarget() && m_hasIntersection) {
505 return m_target->spice()->resolution();
508 QString message =
"No valid intersection point for computing resolution.";
This class defines a body-fixed surface point.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
#define _FILEINFO_
Macro for the filename and line number.
This class is used to create and store valid Isis3 targets.
const double RAD2DEG(57.29577951308232087679815481)
Multiplier for converting from radians to degrees.