Isis 3 Programmer Reference
TriangularPlate.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "TriangularPlate.h"
8
9#include <string>
10#include <vector>
11#include <numeric>
12
13#include <QtGlobal>
14
15#include "AbstractPlate.h"
16#include "Angle.h"
17#include "Distance.h"
18#include "Intercept.h"
19#include "IException.h"
20#include "IString.h"
21#include "Latitude.h"
22#include "Longitude.h"
23#include "NaifDskApi.h"
24#include "SurfacePoint.h"
25
26using namespace std;
27
28namespace Isis {
29
31 // no need to implement this method since it is private and never called
32 // within this class
33 // TriangularPlate::TriangularPlate() : AbstractPlate(), m_plate(3, 3, 0.0) { }
34
36 TriangularPlate::TriangularPlate(const NaifTriangle &plate, const int &plateId) :
37 AbstractPlate(), m_plate(plate.copy()),
38 m_plateId(plateId) { }
39
40 TriangularPlate::~TriangularPlate() { }
41
42 int TriangularPlate::id() const {
43 return m_plateId;
44 }
45
46 QString TriangularPlate::name() const {
47 return "TriangularPlate";
48 }
49
65 double radius = qMax(qMax(vnorm_c(m_plate[0]), vnorm_c(m_plate[1])),
66 vnorm_c(m_plate[2]));
67 return ( Distance(radius, Distance::Kilometers) );
68 }
69
71 double radius = qMin(qMin(vnorm_c(m_plate[0]), vnorm_c(m_plate[1])),
72 vnorm_c(m_plate[2]));
73 return ( Distance(radius, Distance::Kilometers) );
74 }
75
85 double TriangularPlate::area() const {
86
87 // Get the lengths of each side
88 NaifVector edge(3);
89 vsub_c(m_plate[1], m_plate[0], &edge[0]);
90 double s1 = vnorm_c(&edge[0]);
91
92 vsub_c(m_plate[2], m_plate[0], &edge[0]);
93 double s2 = vnorm_c(&edge[0]);
94
95 vsub_c(m_plate[2], m_plate[1], &edge[0]);
96 double s3 = vnorm_c(&edge[0]);
97
98 // Heron's formula for area
99 double S = (s1 + s2 + s3) / 2.0;
100 double p_area = std::sqrt(S * (S - s1) * (S - s2) * (S - s3));
101
102 return (p_area);
103 }
104
116
117 // Get the lengths of each side
118 NaifVector edge1(3);
119 vsub_c(m_plate[1], m_plate[0], &edge1[0]);
120
121 NaifVector edge2(3);
122 vsub_c(m_plate[2], m_plate[0], &edge2[0]);
123
124 NaifVector norm(3);
125 ucrss_c(&edge1[0], &edge2[0], &norm[0]);
126
127 return (norm);
128 }
129
130 NaifVector TriangularPlate::center() const {
131 double third(0.33333333333333331);
132 NaifVector midPt(3);
133 vlcom3_c(third, m_plate[0], third, m_plate[1], third, m_plate[2], &midPt[0]);
134 return (midPt);
135 }
136
154 // Get two sides
155 NaifVector norm(normal());
156 double sepang = vsep_c(&norm[0], &raydir[0]);
157 return ( Angle(sepang, Angle::Radians) );
158 }
159
177 const NaifVector &raydir) const {
179 return (findPlateIntercept(vertex, raydir, point));
180 }
181
199 const Longitude &lon) const {
200
201 // Extend the maximum height of the plate to a resonable distance
202 double maxrad = maxRadius().kilometers() * 1.5;
203
204 // Create a surface point above the highest plate vertex
206 NaifVertex obs(3);
207 point.ToNaifArray(&obs[0]);
208
209 // Set the ray direction back toward the center of the body
210 NaifVector raydir(3);
211 vminus_c(&obs[0], &raydir[0]);
212
213 // Determine where the point/ray intercepts the plate
214 NaifVertex xpt;
215 return (findPlateIntercept(obs, raydir, xpt));
216 }
217
238 const Longitude &lon) const {
239 // Extend the maximum height of the plate
240 double maxrad = maxRadius().kilometers() * 1.5;
241
242 // Create a surface point 1.5 times above the highest plate vertex
244 NaifVertex obs(3);
245 point.ToNaifArray(&obs[0]);
246
247 // Set the ray direction back toward the center of the body
248 NaifVector raydir(3);
249 vminus_c(&obs[0], &raydir[0]);
250
251 // Determine if the point/ray intercepts the plate
252 NaifVertex xpt;
253 if ( !findPlateIntercept(obs, raydir, xpt) ) return (0);
254
255 // Construct the intercept point and return it
256 SurfacePoint *ipoint(new SurfacePoint());
257 ipoint->FromNaifArray(&xpt[0]);
258 return (ipoint);
259 }
260
261
281 const NaifVector &raydir) const {
283 if ( !findPlateIntercept(vertex, raydir, point) ) return (0);
284
285 // Got a valid intercept. Construct it and return
286 SurfacePoint *xpt = new SurfacePoint();
287 xpt->FromNaifArray(&point[0]);
288 return (new Intercept(vertex, raydir, xpt, clone()));
289 }
290
291
307 NaifVertex vec(3);
308 if ( (v < 0) || (v > 2) ) {
309 QString msg = "Unable to get TriangularPlate vertex for index ["
310 + toString(v) + "]. Valid index range is 0-2.";
311 throw IException(IException::Programmer, msg, _FILEINFO_);
312 }
313 for ( int i = 0 ; i < 3 ; i++ ) {
314 vec[i] = m_plate[v][i];
315 }
316 return (vec);
317 }
318
319
336
358 const NaifVector &raydir,
359 NaifVertex &point) const {
360
361 // Construct three edges of the solid tehtrahderal between plate and observer
362 NaifVector e1(3), e2(3), e3(3);
363 vsub_c(m_plate[0], &obs[0], &e1[0]);
364 vsub_c(m_plate[1], &obs[0], &e2[0]);
365 vsub_c(m_plate[2], &obs[0], &e3[0]);
366
367 // Test to see if the ray direction and plate normal are perpendicular
368 NaifVector tnorm12(3);
369 vcrss_c(&e1[0], &e2[0], &tnorm12[0]);
370 double tdot12 = vdot_c(&raydir[0], &tnorm12[0]);
371 double en = vdot_c(&e3[0], &tnorm12[0]);
372
373 // Check for e3 perpendicular to plate normal. If true, e3 is a linear
374 // combination of e1 and e2.
375 if ( qFuzzyCompare(en+1.0, 1.0) ) return (false);
376
377 // Check if raydir and e3 are in same half space
378 if ( (en > 0.0) && (tdot12 < 0.0) ) return (false);
379 if ( (en < 0.0) && (tdot12 > 0.0) ) return (false);
380
381 // Check that raydir and e1 are on the same side of the plane spanned by e2
382 // and e3.
383 NaifVector tnorm23(3);
384 vcrss_c(&e2[0], &e3[0], &tnorm23[0]);
385 double tdot23 = vdot_c(&raydir[0], &tnorm23[0]);
386
387 // Check if raydir and e3 are in same halfspace
388 if ( (en > 0.0) && (tdot23 < 0.0) ) return (false);
389 if ( (en < 0.0) && (tdot23 > 0.0) ) return (false);
390
391 // Finally check that raydir and e2 are in the same half space bounded by e3
392 // and e2.
393 NaifVector tnorm31(3);
394 vcrss_c(&e3[0], &e1[0], &tnorm31[0]);
395 double tdot31 = vdot_c(&raydir[0], &tnorm31[0]);
396
397 // Check if raydir and e2 are in same halfspace
398 if ( (en > 0.0) && (tdot31 < 0.0) ) return (false);
399 if ( (en < 0.0) && (tdot31 > 0.0) ) return (false);
400
401 // Ok, we know raydir intersects the plate. Compute the intercept point if
402 // the denominator is not 0.
403 double denom = tdot12 + tdot23 + tdot31;
404
405 // NOTE: If we have gotten this far in the method,
406 // we have checked that en != 0
407 // if en < 0, then tdot12 <= 0, tdot23 <= 0 and tdot31 <= 0
408 // if en > 0, then tdot12 >= 0, tdot23 >= 0 and tdot31 >= 0
409 // So, in order for the denominator to be 0, then it must be that
410 // tdot12 == tdot23 == tdot31 == 0
411 if ( qFuzzyCompare(denom+1.0, 1.0) ) return (false);
412
413 double scale = en / denom;
414 NaifVertex xpt(3);
415 vlcom_c(1.0, &obs[0], scale, &raydir[0], &xpt[0]);
416 point = xpt;
417 return (true);
418 }
419
420} // namespace Isis
Abstract interface to a TIN plate.
Defines an angle and provides unit conversions.
Definition Angle.h:45
@ Radians
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition Angle.h:63
Distance measurement, usually in meters.
Definition Distance.h:34
double kilometers() const
Get the distance in kilometers.
Definition Distance.cpp:106
@ Kilometers
The distance is being specified in kilometers.
Definition Distance.h:45
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Container for a intercept condition.
Definition Intercept.h:36
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
This class defines a body-fixed surface point.
void ToNaifArray(double naifOutput[3]) const
A naif array is a c-style array of size 3.
Specification for an abstract triangular plate.
SurfacePoint * point(const Latitude &lat, const Longitude &lon) const
Determine the intercept point of a lat/lon location for the plate.
double area() const
Returns the area of the plate in km.
Distance minRadius() const
Gets the minimum radius.
QString name() const
Gets the name of this Plate type.
NaifTriangle m_plate
Tetrahedron, defined by the coordinate system origin and 3 vertices, used to represent the Triangular...
NaifVertex vertex(int v) const
Returns the vth point of the triangle.
AbstractPlate * clone() const
Retrns a clone of the current plate.
NaifVector normal() const
Compute the surface normal of the plate.
Intercept * intercept(const NaifVertex &vertex, const NaifVector &raydir) const
Conpute the intercept point on a triangular plate.
bool hasIntercept(const NaifVertex &vertex, const NaifVector &raydir) const
Determines if a look direction from a point intercepts the plate.
Distance maxRadius() const
Determines the maximum radius from all the vertices of the plate.
Angle separationAngle(const NaifVector &raydir) const
Computes the separation angle from the plate normal of a given vector.
bool hasPoint(const Latitude &lat, const Longitude &lon) const
Determines the give lat/lon point intercept the triangular plate.
bool findPlateIntercept(const NaifVertex &obs, const NaifVector &raydir, NaifVertex &point) const
Determines of if given a vertex and look direction intercepts the plate.
int m_plateId
ID for this plate on the ShapeModel.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
TNT::Array1D< SpiceDouble > NaifVector
Namespace to contain type definitions of NAIF DSK fundamentals.
Definition NaifDskApi.h:46
TNT::Array2D< SpiceDouble > NaifTriangle
3-D triangle[3][3]
Definition NaifDskApi.h:48
TNT::Array1D< SpiceDouble > NaifVertex
1-D Buffer[3]
Definition NaifDskApi.h:47
Namespace for the standard library.