7 #include "ShapeModel.h"
24 #include "SurfacePoint.h"
25 #include "IException.h"
27 #include "NaifStatus.h"
40 ShapeModel::ShapeModel() {
56 ShapeModel::ShapeModel(
Target *target) {
65 void ShapeModel::Initialize() {
66 m_name =
new QString();
68 m_hasIntersection =
false;
70 m_normal.resize(3,0.);
71 m_hasEllipsoidIntersection =
false;
76 ShapeModel::~ShapeModel() {
81 delete m_surfacePoint;
82 m_surfacePoint = NULL;
104 const std::vector<double> &observerPos,
105 const bool &backCheck) {
107 return (intersectSurface(
SurfacePoint(lat, lon, localRadius(lat, lon)), observerPos, backCheck));
128 const std::vector<double> &observerPos,
129 const bool &backCheck) {
133 setSurfacePoint(surfpt);
140 void ShapeModel::calculateEllipsoidalSurfaceNormal() {
146 if (!m_hasIntersection || !surfaceIntersection()->Valid()) {
147 QString msg =
"A valid intersection must be defined before computing the surface normal";
148 throw IException(IException::Programmer, msg, _FILEINFO_);
153 pB[0] = surfaceIntersection()->GetX().kilometers();
154 pB[1] = surfaceIntersection()->GetY().kilometers();
155 pB[2] = surfaceIntersection()->GetZ().kilometers();
160 unorm_c(pB, upB, &dist);
161 memcpy(&m_normal[0], upB,
sizeof(
double) * 3);
185 double ShapeModel::emissionAngle(
const std::vector<double> &observerBodyFixedPosition) {
188 if (!hasNormal()) calculateDefaultNormal();
192 pB[0] = surfaceIntersection()->GetX().kilometers();
193 pB[1] = surfaceIntersection()->GetY().kilometers();
194 pB[2] = surfaceIntersection()->GetZ().kilometers();
197 SpiceDouble psB[3], upsB[3], dist;
198 vsub_c((ConstSpiceDouble *) &observerBodyFixedPosition[0], pB, psB);
199 unorm_c(psB, upsB, &dist);
201 double angle = vdot_c((SpiceDouble *) &m_normal[0], upsB);
202 if(angle > 1.0)
return 0.0;
203 if(angle < -1.0)
return 180.0;
213 bool ShapeModel::hasEllipsoidIntersection() {
214 return m_hasEllipsoidIntersection;
232 double ShapeModel::incidenceAngle(
const std::vector<double> &illuminatorBodyFixedPosition) {
235 if (!m_hasNormal) calculateDefaultNormal();
239 pB[0] = surfaceIntersection()->GetX().kilometers();
240 pB[1] = surfaceIntersection()->GetY().kilometers();
241 pB[2] = surfaceIntersection()->GetZ().kilometers();
244 SpiceDouble puB[3], upuB[3], dist;
245 vsub_c((SpiceDouble *) &illuminatorBodyFixedPosition[0], pB, puB);
246 unorm_c(puB, upuB, &dist);
248 double angle = vdot_c((SpiceDouble *) &m_normal[0], upuB);
249 if(angle > 1.0)
return 0.0;
250 if(angle < -1.0)
return 180.0;
267 bool ShapeModel::intersectEllipsoid(
const std::vector<double> observerBodyFixedPosition,
268 const std::vector<double> &observerLookVectorToTarget) {
273 SpiceDouble lookB[3];
279 memcpy(lookB,&observerLookVectorToTarget[0], 3*
sizeof(
double));
282 std::vector<Distance> radii = targetRadii();
283 SpiceDouble a = radii[0].kilometers();
284 SpiceDouble b = radii[1].kilometers();
285 SpiceDouble c = radii[2].kilometers();
288 SpiceDouble intersectionPoint[3];
289 SpiceBoolean intersected =
false;
291 NaifStatus::CheckErrors();
292 surfpt_c((SpiceDouble *) &observerBodyFixedPosition[0], lookB, a, b, c,
293 intersectionPoint, &intersected);
294 NaifStatus::CheckErrors();
297 m_surfacePoint->FromNaifArray(intersectionPoint);
298 m_hasIntersection =
true;
301 m_hasIntersection =
false;
304 m_hasEllipsoidIntersection = m_hasIntersection;
305 return m_hasIntersection;
324 double ShapeModel::phaseAngle(
const std::vector<double> &observerBodyFixedPosition,
325 const std::vector<double> &illuminatorBodyFixedPosition) {
329 pB[0] = surfaceIntersection()->GetX().kilometers();
330 pB[1] = surfaceIntersection()->GetY().kilometers();
331 pB[2] = surfaceIntersection()->GetZ().kilometers();
334 SpiceDouble psB[3], upsB[3], dist;
335 vsub_c((SpiceDouble *) &observerBodyFixedPosition[0], pB, psB);
336 unorm_c(psB, upsB, &dist);
339 SpiceDouble puB[3], upuB[3];
340 vsub_c((SpiceDouble *) &illuminatorBodyFixedPosition[0], pB, puB);
341 unorm_c(puB, upuB, &dist);
343 double angle = vdot_c(upsB, upuB);
346 if(angle > 1.0)
return 0.0;
347 if(angle < -1.0)
return 180.0;
359 return m_surfacePoint;
368 bool ShapeModel::hasIntersection() {
369 return m_hasIntersection;
378 bool ShapeModel::hasNormal()
const {
386 void ShapeModel::clearSurfacePoint() {
387 setHasIntersection(
false);
388 m_hasEllipsoidIntersection =
false;
401 std::vector<double> ShapeModel::normal() {
406 QString message =
"The local normal has not been computed.";
407 throw IException(IException::Unknown, message, _FILEINFO_);
431 bool ShapeModel::isVisibleFrom(
const std::vector<double> observerPos,
432 const std::vector<double> lookDirection) {
433 if ( hasIntersection() ) {
434 if ( fabs(emissionAngle(observerPos)) <= 90.0 ) {
449 bool ShapeModel::hasValidTarget()
const {
450 return (m_target != NULL);
465 std::vector<Distance> ShapeModel::targetRadii()
const {
466 if (hasValidTarget()) {
467 return m_target->radii();
470 QString message =
"Unable to find target radii for ShapeModel. Target is NULL. ";
471 throw IException(IException::Programmer, message, _FILEINFO_);
487 void ShapeModel::setNormal(
const std::vector<double> normal) {
488 if (m_hasIntersection) {
493 QString message =
"No intersection point in known. A normal can not be set.";
494 throw IException(IException::Unknown, message, _FILEINFO_);
512 void ShapeModel::setNormal(
const double a,
const double b,
const double c) {
513 if (m_hasIntersection) {
520 QString message =
"No intersection point in known. A normal can not be set.";
521 throw IException(IException::Unknown, message, _FILEINFO_);
532 void ShapeModel::setName(QString name) {
543 QString ShapeModel::name()
const{
554 void ShapeModel::setHasIntersection(
bool b) {
555 m_hasIntersection = b;
566 *m_surfacePoint = surfacePoint;
569 m_hasIntersection =
true;
581 void ShapeModel::setHasNormal(
bool status) {
582 m_hasNormal = status;
592 double ShapeModel::resolution() {
593 if (hasValidTarget() && m_hasIntersection) {
594 return m_target->spice()->resolution();
597 QString message =
"No valid intersection point for computing resolution.";
598 throw IException(IException::Programmer, message, _FILEINFO_);