Isis 3 Programmer Reference
RingCylindrical.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "RingCylindrical.h"
8
9#include <cmath>
10#include <cfloat>
11
12#include "Constants.h"
13#include "IException.h"
14#include "Pvl.h"
15#include "PvlGroup.h"
16#include "PvlKeyword.h"
17#include "RingPlaneProjection.h"
18#include "SpecialPixel.h"
19
20using namespace std;
21namespace Isis {
22
39 RingCylindrical::RingCylindrical(Pvl &label, bool allowDefaults) :
41 try {
42 // Try to read the mapping group
43 PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
44
45 // Compute the default value if allowed and needed
46 if ((allowDefaults) && (!mapGroup.hasKeyword("CenterRingLongitude"))) {
48 mapGroup += PvlKeyword("CenterRingLongitude", toString(az));
49 }
50
51 // Compute and write the default center radius if allowed and
52 // necessary
53 if ((allowDefaults) && (!mapGroup.hasKeyword("CenterRingRadius"))) {
54 double radius = (m_minimumRingRadius + m_maximumRingRadius) / 2.0;
55 mapGroup += PvlKeyword("CenterRingRadius", toString(radius));
56 }
57
58 // Get the center ring radius and center ring longitude.
59 m_centerRingLongitude = mapGroup["CenterRingLongitude"];
60 m_centerRingRadius = mapGroup["CenterRingRadius"];
61
62 // Because the center radius is used to scale the y values of the projection, it cannot be 0.
63 // For now, we will reset the center to the radius of Saturn.
64 // Perhaps we should fail and issue an error message??? TODO
65 if (m_centerRingRadius == 0.0) {
66 m_centerRingRadius = 18000.;
67 }
68
69 // Convert to radians, adjust for azimuth direction
72 }
73 catch (IException &e) {
74 string message = "Invalid label group [Mapping]";
75 throw IException(e, IException::Io, message, _FILEINFO_);
76 }
77 }
78
82
92 if (!Projection::operator==(proj)) return false;
93 // dont do the below it is a recusive plunge
94 // if (Projection::operator!=(proj)) return false;
95 RingCylindrical *ringCyl = (RingCylindrical *) &proj;
96 if ((ringCyl->m_centerRingLongitude != m_centerRingLongitude) ||
97 (ringCyl->m_centerRingRadius != m_centerRingRadius)) return false;
98 return true;
99 }
100
106 QString RingCylindrical::Name() const {
107 return "RingCylindrical";
108 }
109
115 QString RingCylindrical::Version() const {
116 return "1.0";
117 }
118
119
131 return true;
132 }
133
134
151
152
159 double dir = 1.0;
160 if (m_ringLongitudeDirection == Clockwise) dir = -1.0;
161 return m_centerRingLongitude * RAD2DEG * dir;
162 }
163
164
171 return m_centerRingRadius;
172 }
173
174
188 bool RingCylindrical::SetGround(const double ringRadius, const double ringLongitude) {
189 //TODO Add scalar to make azimuth distance equivalent to radius distance at center rad
190 // Convert to azimuth to radians and adjust
191 m_ringLongitude = ringLongitude;
192 double ringLongitudeRadians = ringLongitude * DEG2RAD;
193 if (m_ringLongitudeDirection == Clockwise) ringLongitudeRadians *= -1.0;
194
195 // Check to make sure radius is valid
196 if (ringRadius <= 0) {
197 m_good = false;
198 // cout << "Unable to set radius. The given radius value ["
199 // << IString(ringRadius) << "] is invalid." << endl;
200 // throw IException(IException::Unknown,
201 // "Unable to set radius. The given radius value ["
202 // + IString(ringRadius) + "] is invalid.",
203 // _FILEINFO_);
204 return m_good;
205 }
206 m_ringRadius = ringRadius;
207
208 // Compute helper variable
209 double deltaAz = (ringLongitudeRadians - m_centerRingLongitude);
210
211 // Compute the coordinates
212 if (ringRadius ==0) {
213 // TODO How should we handle this case? We should use epsilon probably instead of 0 too
214 m_good = false;
215 return m_good;
216 }
217 double x = deltaAz * m_centerRingRadius;
218 double y = m_centerRingRadius - ringRadius;
219 SetComputedXY(x, y);
220 m_good = true;
221 return m_good;
222 }
223
239 bool RingCylindrical::SetCoordinate(const double x, const double y) {
240 // Save the coordinate
241 SetXY(x, y);
242
243 // Compute radius and make sure it is valid
244 // m_ringRadius = GetY() + m_centerRingRadius;
246 if (m_ringRadius < m_minimumRingRadius || m_ringRadius > m_maximumRingRadius) {
247 m_good = false;
248 return m_good;
249 }
250
251 // Compute azimuth
253
254 // Convert to degrees
256
257 // Cleanup the azimuth
259 // Do these if the projection is circular
260 // m_ringLongitude = To360Domain (m_ringLongitude);
261 // if (m_ringLongitudeDomain == 180) m_ringLongitude = To180Domain(m_ringLongitude);
262
263 m_good = true;
264 return m_good;
265 }
266
267
276
277 mapping += PvlKeyword("CenterRingRadius", toString(m_centerRingRadius));
278 double dir = 1.0;
279 if (m_ringLongitudeDirection == Clockwise) dir = -1.0;
280 double lonDegrees = m_centerRingLongitude*RAD2DEG*dir;
281 mapping += PvlKeyword("CenterRingLongitude", toString(lonDegrees));
282
283 return mapping;
284 }
285
294
295 if (HasGroundRange())
296 mapping += m_mappingGrp["CenterRingRadius"];
297
298 return mapping;
299 }
300
301
310
311 if (HasGroundRange())
312 mapping += m_mappingGrp["CenterRingLongitude"];
313
314 return mapping;
315 }
316
317
355 bool RingCylindrical::XYRange(double &minX, double &maxX,
356 double &minY, double &maxY) {
357
358 double rad, az;
359
360 // Check the corners of the rad/az range
365
366 // Walk top and bottom edges in half pixel increments
367 double radiusInc = 2. * (m_maximumRingRadius - m_minimumRingRadius) / PixelResolution();
368
369 for (rad = m_minimumRingRadius; rad <= m_maximumRingRadius; rad += radiusInc) {
371 XYRangeCheck(rad, az);
372
374 XYRangeCheck(rad, az);
375 }
376
377 // Walk left and right edges
378 for (az = m_minimumRingLongitude; az <= m_maximumRingLongitude; az += 0.01) {
380 XYRangeCheck(rad, az);
381
383 XYRangeCheck(rad, az);
384 }
385
386 // Make sure everything is ordered
387 if (m_minimumX >= m_maximumX) return false;
388 if (m_minimumY >= m_maximumY) return false;
389
390 // Return X/Y min/maxs
391 // m_maximumX = m_maximumRingRadius*cos(m_maximumRingLongitude);
392 // m_minimumX = -m_maximumX;
393 // m_maximumY = m_maximumRingRadius*sin(m_maximumRingLongitude);
394 // m_minimumY = -m_maximumY;
395
396 minX = m_minimumX;
397 maxX = m_maximumX;
398 minY = m_minimumY;
399 maxY = m_maximumY;
400
401 return true;
402 }
403} // end namespace isis
404
417extern "C" Isis::Projection *RingCylindricalPlugin(Isis::Pvl &lab,
418 bool allowDefaults) {
419 return new Isis::RingCylindrical(lab, allowDefaults);
420}
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
Base class for Map Projections.
Definition Projection.h:155
double m_maximumX
See minimumX description.
Definition Projection.h:326
virtual bool HasGroundRange() const
This indicates if the longitude direction type is positive west (as opposed to postive east).
double PixelResolution() const
Returns the pixel resolution value from the PVL mapping group in meters/pixel.
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
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
Definition Projection.h:317
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition Projection.h:329
double m_minimumY
See minimumX description.
Definition Projection.h:327
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.
double m_maximumY
See minimumX description.
Definition Projection.h:328
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
Ring Cylindrical Map Projection.
double CenterRingRadius() const
Returns the center radius, in meters.
PvlGroup MappingRingRadii()
This function returns the radii keywords that this projection uses.
PvlGroup MappingRingLongitudes()
This function returns the longitude keywords that this projection uses.
double m_centerRingRadius
The center ring radius for the map projection.
bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
double TrueScaleRingRadius() const
Returns the center radius, in meters.
double CenterRingLongitude() const
Returns the center longitude, in degrees.
RingCylindrical(Pvl &label, bool allowDefaults=false)
Constructs a RingCylindrical object.
bool IsEquatorialCylindrical()
This method returns true if the projection is equatorial cylindrical.
~RingCylindrical()
Destroys the RingCylindrical object.
bool operator==(const Projection &proj)
Compares two Projection objects to see if they are equal.
QString Version() const
Returns the version of the map projection.
PvlGroup Mapping()
This function returns the keywords that this projection uses.
double m_centerRingLongitude
The center ring longitude (azimuth) for the map projection, in radians.
QString Name() const
Returns the name of the map projection, "RingCylindrical".
bool SetGround(const double ringRadius, const double ringLongitude)
This method is used to set the radius/longitude (assumed to be of the correct RingLongitudeDirection,...
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...
Base class for Map Projections of plane shapes.
double m_minimumRingLongitude
Contains the minimum longitude for the entire ground range.
virtual PvlGroup MappingRingLongitudes()
This function returns the ring longitude keywords that this projection uses.
virtual PvlGroup Mapping()
This method is used to find the XY range for oblique aspect projections (non-polar projections) by "w...
double m_maximumRingRadius
Contains the maximum ring radius for the entire ground range.
double m_maximumRingLongitude
Contains the maximum longitude for the entire ground range.
void XYRangeCheck(const double ringRadius, const double ringLongitude)
This convience function is established to assist in the development of the XYRange virtual method.
double m_ringRadius
This contain a ring radius value in m.
virtual PvlGroup MappingRingRadii()
This function returns the ring radius keywords that this projection uses.
double m_ringLongitude
This contain a ring longitude value.
@ Clockwise
Ring longitude values increase in the clockwise direction.
RingLongitudeDirection m_ringLongitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
double m_minimumRingRadius
Contains the minimum ring radius for the entire ground range.
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 DEG2RAD
Multiplier for converting from degrees to radians.
Definition Constants.h:43
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition Constants.h:44
Namespace for the standard library.