Isis 3 Programmer Reference
PointPerspective.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "PointPerspective.h"
8
9#include <cfloat>
10#include <cmath>
11#include <iomanip>
12
13#include "Constants.h"
14#include "IException.h"
15#include "Pvl.h"
16#include "PvlGroup.h"
17#include "PvlKeyword.h"
18#include "TProjection.h"
19
20using namespace std;
21
22namespace Isis {
39 PointPerspective::PointPerspective(Pvl &label, bool allowDefaults) :
40 TProjection::TProjection(label) {
41 try {
42 // Try to read the mapping group
43 PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
44
45 // Compute and write the default center longitude if allowed and
46 // necessary
47 if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLongitude"))) {
48 double lon = (m_minimumLongitude + m_maximumLongitude) / 2.0;
49 mapGroup += PvlKeyword("CenterLongitude", toString(lon));
50 }
51
52 // Compute and write the default center latitude if allowed and
53 // necessary
54 if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLatitude"))) {
55 double lat = (m_minimumLatitude + m_maximumLatitude) / 2.0;
56 mapGroup += PvlKeyword("CenterLatitude", toString(lat));
57 }
58
59 // Get the center longitude & latitude
60 m_centerLongitude = mapGroup["CenterLongitude"];
61 m_centerLatitude = mapGroup["CenterLatitude"];
62 if (IsPlanetocentric()) {
64 }
65
66 // convert to radians, adjust for longitude direction
67 m_centerLongitude *= PI / 180.0;
68 m_centerLatitude *= PI / 180.0;
70
71 // Calculate sine & cosine of center latitude
74
75 // Get the distance above planet center (the point of perspective from
76 // the center of planet), and calculate P
77 m_distance = mapGroup["Distance"];
78 m_distance *= 1000.;
79
81 }
82 catch(IException &e) {
83 QString message = "Invalid label group [Mapping]";
84 throw IException(e, IException::Io, message, _FILEINFO_);
85 }
86 }
87
91
101 if (!Projection::operator==(proj)) return false;
102 // dont do the below it is a recusive plunge
103 // if (Projection::operator!=(proj)) return false;
104 PointPerspective *point = (PointPerspective *) &proj;
105 if((point->m_centerLongitude != this->m_centerLongitude) ||
106 (point->m_centerLatitude != this->m_centerLatitude) ||
107 (point->m_distance != this->m_distance)) return false;
108 return true;
109 }
110
116 QString PointPerspective::Name() const {
117 return "PointPerspective";
118 }
119
126 return "1.0";
127 }
128
136 return m_centerLatitude * 180.0 / PI;
137 }
138
159 bool PointPerspective::SetGround(const double lat, const double lon) {
160 // Convert longitude to radians & clean up
161 double projectionRadius = m_equatorialRadius*sqrt((m_P+1)/(m_P+1));
162
163 m_longitude = lon;
164 double lonRadians = lon * PI / 180.0;
165 if (m_longitudeDirection == PositiveWest) lonRadians *= -1.0;
166
167 // Now convert latitude to radians & clean up ... it must be planetographic
168 m_latitude = lat;
169 double latRadians = lat;
170 if (IsPlanetocentric()) latRadians = ToPlanetographic(latRadians);
171 latRadians *= PI / 180.0;
172
173 // Compute helper variables
174 double deltaLon = (lonRadians - m_centerLongitude);
175 double sinphi = sin(latRadians);
176 double cosphi = cos(latRadians);
177 double coslon = cos(deltaLon);
178
179 // Lat/Lon cannot be projected
180 double g = m_sinph0 * sinphi + m_cosph0 * cosphi * coslon;
181 if (g < (1.0 / m_P)) {
182 m_good = false;
183 return m_good;
184 }
185 // Compute the coordinates
186 double ksp = (m_P - 1.0) / (m_P - g);
187
188 double x = m_equatorialRadius * ksp * cosphi * sin(deltaLon);
189 double y = m_equatorialRadius * ksp *
190 (m_cosph0 * sinphi - m_sinph0 * cosphi * coslon);
191
192 if (sqrt(x*x+y*y)> projectionRadius) {
193
194 m_good =false;
195
196 return m_good;
197 }
198
199 SetComputedXY(x,y);
200 m_good = true;
201 return m_good;
202 }
203
217 bool PointPerspective::SetCoordinate(const double x, const double y) {
218
219
220 // Save the coordinate
221 SetXY(x, y);
222
223 // Declare instance variables and calculate rho
224 double rho, rp, con, com, z, sinz, cosz;
225 const double epsilon = 1.0e-10;
226 rho = sqrt(GetX() * GetX() + GetY() * GetY());
227 rp = rho / m_equatorialRadius;
228 con = m_P - 1.0;
229 com = m_P + 1.0;
230
231 // Error calculating rho - should be less than equatorial radius
232 if (rp > (sqrt(con / com))) {
233 m_good = false;
234 return m_good;
235 }
236
237 // Calculate the latitude and longitude
239 if (fabs(rho) <= epsilon) {
241 }
242 else {
243 if (rp <= epsilon) {
244 sinz = 0.0;
245 }
246 else {
247 sinz = (m_P - sqrt(1.0 - rp * rp * com / con)) / (con / rp + rp / con);
248 }
249 z = asin(sinz);
250 sinz = sin(z);
251 cosz = cos(z);
252 con = cosz * m_sinph0 + GetY() * sinz * m_cosph0 / rho;
253 if (con > 1.0) con = 1.0;
254 if (con < -1.0) con = -1.0;
255 m_latitude = asin(con);
256
257 con = fabs(m_centerLatitude) - HALFPI;
258 if (fabs(con) <= epsilon) {
259 if (m_centerLatitude >= 0.0) {
260 m_longitude += atan2(GetX(), -GetY());
261 }
262 else {
263 m_longitude += atan2(-GetX(), GetY());
264 }
265 }
266 else {
267 con = cosz - m_sinph0 * sin(m_latitude);
268 if ((fabs(con) >= epsilon) || (fabs(GetX()) >= epsilon)) {
269 m_longitude += atan2(GetX() * sinz * m_cosph0, con * rho);
270 }
271 }
272 }
273
274 // Convert to degrees
275 m_latitude *= 180.0 / PI;
276 m_longitude *= 180.0 / PI;
277
278 // Cleanup the longitude
280 // These need to be done for circular type projections
283
284 // Cleanup the latitude
286
287
288 m_good = true;
289 return m_good;
290 }
291
324 bool PointPerspective::XYRange(double &minX, double &maxX, double &minY, double &maxY) {
325
326 double projectionRadius = m_equatorialRadius*sqrt((m_P-1.0)/(m_P+1.0));
327
328 SetCoordinate(0.0,0.0);
329 minX = XCoord() - projectionRadius;
330 maxX = XCoord() + projectionRadius;
331 minY = YCoord() - projectionRadius;
332 maxY = YCoord() + projectionRadius;
333
334 return true;
335
336 }
337
338
345 PvlGroup mapping = TProjection::Mapping();
346
347 mapping += m_mappingGrp["CenterLatitude"];
348 mapping += m_mappingGrp["CenterLongitude"];
349 mapping += m_mappingGrp["Distance"];
350
351 return mapping;
352 }
353
361
362 mapping += m_mappingGrp["CenterLatitude"];
363
364 return mapping;
365 }
366
374
375 mapping += m_mappingGrp["CenterLongitude"];
376
377 return mapping;
378 }
379} // end namespace isis
380
390extern "C" Isis::Projection *PointPerspectivePlugin(Isis::Pvl &lab,
391 bool allowDefaults) {
392 return new Isis::PointPerspective(lab, allowDefaults);
393}
Isis exception class.
Definition IException.h:91
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
PointPerspective Map Projection.
double m_centerLongitude
The center longitude for the map projection.
bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
QString Name() const
Returns the name of the map projection, "PointPerspective".
double TrueScaleLatitude() const
Returns the latitude of true scale, in degrees.
PvlGroup Mapping()
This function returns the keywords that this projection uses.
double m_sinph0
Sine of the center latitude.
bool XYRange(double &minX, double &maxX, double &minY, double &maxY)
This method is used to determine the x/y range which completely covers the area of interest specified...
double m_P
Perspective Point.
PointPerspective(Pvl &label, bool allowDefaults=false)
Constructs an PointPerspective object.
bool operator==(const Projection &proj)
Compares two Projection objects to see if they are equal.
double m_centerLatitude
The center latitude for the map projection.
double m_distance
Distance fromp perspective point to planet center.
double m_cosph0
Cosine of the center latitude.
PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
bool SetGround(const double lat, const double lon)
This method is used to set the latitude/longitude (assumed to be of the correct LatitudeType,...
~PointPerspective()
Destroys the PointPerspective object.
QString Version() const
Returns the version of the map projection.
PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
Base class for Map Projections.
Definition Projection.h:155
double XCoord() const
This returns the projection X provided SetGround, SetCoordinate, SetUniversalGround,...
double YCoord() const
This returns the projection Y provided SetGround, SetCoordinate, SetUniversalGround,...
double GetX() const
Calculates the unrotated form of current x value.
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
Definition Projection.h:300
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition Projection.h:329
double GetY() const
Calculates the unrotated form of the current y value.
void SetXY(double x, double y)
This protected method is a helper for derived classes.
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
@ Traverse
Search child objects.
Definition PvlObject.h:158
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition PvlObject.h:129
Base class for Map TProjections.
double m_longitude
This contains the currently set longitude value.
bool IsPlanetocentric() const
This indicates if the latitude type is planetocentric (as opposed to planetographic).
double m_minimumLatitude
Contains the minimum latitude for the entire ground range.
double m_maximumLongitude
Contains the maximum longitude for the entire ground range.
static double To180Domain(const double lon)
This method converts a longitude into the -180 to 180 domain.
double m_equatorialRadius
Polar radius of the target.
LongitudeDirection m_longitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
virtual PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
int m_longitudeDomain
This integer is either 180 or 360 and is read from the labels.
double ToPlanetocentric(const double lat) const
This method converts a planetographic latitude to a planetocentric latitude.
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
double m_minimumLongitude
Contains the minimum longitude for the entire ground range.
@ PositiveWest
Longitude values increase in the westerly direction.
double m_maximumLatitude
Contains the maximum latitude for the entire ground range.
static double To360Domain(const double lon)
This method converts a longitude into the 0 to 360 domain.
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
double ToPlanetographic(const double lat) const
This method converts a planetocentric latitude to a planetographic latitude.
double m_latitude
This contains the currently set latitude value.
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
const double HALFPI
The mathematical constant PI/2.
Definition Constants.h:41
const double PI
The mathematical constant PI.
Definition Constants.h:40
Namespace for the standard library.