Isis 3 Programmer Reference
Longitude.cpp
Go to the documentation of this file.
1 
20 #include "Longitude.h"
21 
22 #include <cmath>
23 
24 #include <QtCore>
25 #include <QDebug>
26 
27 #include "Constants.h"
28 #include "IException.h"
29 #include "IString.h"
30 #include "PvlGroup.h"
31 #include "SpecialPixel.h"
32 
33 namespace Isis {
39  }
40 
41 
52  Longitude::Longitude(double longitude, PvlGroup mapping,
53  Angle::Units longitudeUnits) :
54  Angle(longitude, longitudeUnits) {
55  if(mapping["LongitudeDomain"][0] == "360") {
57  }
58  else if(mapping["LongitudeDomain"][0] == "180") {
60  }
61  else {
62  IString msg = "Longitude domain [" +
63  IString(mapping["LongitudeDomain"][0]) + "] not recognized";
65  }
66 
67  if(mapping["LongitudeDirection"][0] == "PositiveEast") {
68  setPositiveEast(longitude, longitudeUnits);
69  }
70  else if(mapping["LongitudeDirection"][0] == "PositiveWest") {
71  setPositiveWest(longitude, longitudeUnits);
72  }
73  else {
74  IString msg = "Longitude direction [" +
75  IString(mapping["LongitudeDirection"][0]) + "] not recognized";
77  }
78  }
79 
80 
90  Direction lonDir, Domain lonDomain) :
91  Angle(longitude) {
92  m_currentDomain = lonDomain;
93 
94  if(lonDir == PositiveEast) {
95  setPositiveEast(longitude.radians(), Radians);
96  }
97  else if(lonDir == PositiveWest) {
98  setPositiveWest(longitude.radians(), Radians);
99  }
100  else {
101  IString msg = "Longitude direction [" + IString(lonDir) + "] not valid";
103  }
104  }
105 
106 
116  Longitude::Longitude(double longitude, Angle::Units longitudeUnits,
117  Direction lonDir, Domain lonDomain) :
118  Angle(longitude, longitudeUnits) {
119  m_currentDomain = lonDomain;
120 
121  if(lonDir == PositiveEast) {
122  setPositiveEast(longitude, longitudeUnits);
123  }
124  else if(lonDir == PositiveWest) {
125  setPositiveWest(longitude, longitudeUnits);
126  }
127  else {
128  IString msg = "Longitude direction [" + IString(lonDir) + "] not valid";
130  }
131  }
132 
133 
139  Longitude::Longitude(const Longitude &longitudeToCopy)
140  : Angle(longitudeToCopy) {
141  m_currentDomain = longitudeToCopy.m_currentDomain;
142  }
143 
144 
149  }
150 
151 
159  double Longitude::positiveEast(Angle::Units units) const {
160  return angle(units);
161  }
162 
163 
171  double Longitude::positiveWest(Angle::Units units) const {
172  double longitude = angle(units);
173 
174  if (!IsSpecial(longitude)) {
175  if(m_currentDomain == Domain360) {
176  double wrapPoint = unitWrapValue(units);
177  double halfWrap = wrapPoint / 2.0;
178 
179  int numPlanetWraps = qFloor(longitude / wrapPoint);
180 
181  // If the input is 360, then we want numPlanetWraps == 0. Compare the input to the border
182  // case (wraps * wrapPoint == longitude) and bring the number of wraps down if it's true.
183  // If it's false, then the rounding already took care of this border case.
184  if (numPlanetWraps != 0 && qFuzzyCompare(numPlanetWraps * wrapPoint, longitude)) {
185  if (numPlanetWraps > 0)
186  numPlanetWraps--;
187  else
188  numPlanetWraps++;
189  }
190 
191  longitude -= numPlanetWraps * wrapPoint;
192  longitude = -(longitude - halfWrap) + halfWrap;
193  longitude -= numPlanetWraps * wrapPoint;
194  }
195  else {
196  // 180 domain is just a negation in this conversion,
197  // no more work needs done
198  longitude = -1 * longitude;
199  }
200  }
201 
202  return longitude;
203  }
204 
205 
212  void Longitude::setPositiveEast(double longitude, Angle::Units units) {
213  setAngle(longitude, units);
214  }
215 
216 
223  void Longitude::setPositiveWest(double longitude, Angle::Units units) {
224  if(!IsSpecial(longitude)) {
225  if(m_currentDomain == Domain360) {
226  // Same as positiveWest
227  double wrapPoint = unitWrapValue(units);
228  double halfWrap = wrapPoint / 2.0;
229 
230  int numPlanetWraps = qFloor(longitude / wrapPoint);
231 
232  // If the input is 360, then we want numPlanetWraps == 0. Compare the input to the border
233  // case (wraps * wrapPoint == longitude) and bring the number of wraps down if it's true.
234  // If it's false, then the rounding already took care of this border case.
235  if (numPlanetWraps != 0 && qFuzzyCompare(numPlanetWraps * wrapPoint, longitude)) {
236  if (numPlanetWraps > 0)
237  numPlanetWraps--;
238  else
239  numPlanetWraps++;
240  }
241 
242 
243  longitude -= numPlanetWraps * wrapPoint;
244  longitude = -(longitude - halfWrap) + halfWrap;
245  longitude -= numPlanetWraps * wrapPoint;
246  }
247  else {
248  // 180 domain is just a negation in this conversion,
249  // no more work needs done
250  longitude = -1 * longitude;
251  }
252  }
253 
254  setAngle(longitude, units);
255  }
256 
257 
265  Longitude& Longitude::operator=(const Longitude & longitudeToCopy) {
266  if(this == &longitudeToCopy) return *this;
267 
268  m_currentDomain = longitudeToCopy.m_currentDomain;
269  setPositiveEast(longitudeToCopy.positiveEast());
270 
271  return *this;
272  }
273 
274 
281  if(!isValid()) return Longitude();
282 
283  double resultantLongitude = angle(Angle::Degrees);
284 
285  // Bring the number in the 0 to 360 range
286  if (qFuzzyCompare(degrees(), 360.0)) {
287  resultantLongitude = 360.0;
288  }
289  else {
290  resultantLongitude -= 360 * qFloor(resultantLongitude / 360);
291  }
292 
293  return Longitude(resultantLongitude, Angle::Degrees);
294  }
295 
296 
303  if(!isValid()) return Longitude();
304 
305  Longitude forced = force360Domain();
306 
307  if(forced.degrees() > 180.0)
308  forced -= Angle(360.0, Angle::Degrees);
309 
310  return forced;
311  }
312 
313 
332  bool Longitude::inRange(Longitude min, Longitude max) const {
333  bool result = false;
334 
335  QList< QPair<Longitude, Longitude> > ranges = to360Range(min, max);
336 
337  Longitude thisLon = force360Domain();
338 
340  foreach (range, ranges) {
341  if (thisLon >= range.first && thisLon <= range.second) {
342  result = true;
343  }
344 
345  double thisLonRadians = thisLon.radians();
346  double rangeStartRadians = range.first.radians();
347  double rangeEndRadians = range.second.radians();
348  // Check equality on edges of range
349  if (qFuzzyCompare(thisLonRadians, rangeStartRadians) ||
350  qFuzzyCompare(thisLonRadians, rangeEndRadians)) {
351  result = true;
352  }
353 
354  // Be very careful at the 0-360 boundary
355  if ((qFuzzyCompare(thisLonRadians, 0.0) || qFuzzyCompare(thisLonRadians, 2.0 * PI)) &&
356  (qFuzzyCompare(rangeStartRadians, 0.0) ||
357  qFuzzyCompare(rangeEndRadians, 2.0 * PI))) {
358  result = true;
359  }
360  }
361 
362  return result;
363  }
364 
378 
380 
381  if (startLon.isValid() && endLon.isValid() && startLon < endLon) {
382 
383  int multiplier = floor(startLon / fullRotation());
384 
385  startLon -= multiplier * fullRotation();
386  endLon -= multiplier * fullRotation();
387 
388  if (endLon > fullRotation()) {
389 
390  Longitude startLon2(0, Angle::Degrees);
391  Longitude endLon2(endLon - fullRotation());
392 
393  if (endLon2 < startLon) {
394  range.append(qMakePair(startLon2, endLon2));
395  }
396  else {
397  startLon = Longitude(0, Angle::Degrees);
398  }
399  endLon = Longitude(360, Angle::Degrees);
400  }
401  startLon = Longitude((Angle)startLon);
402  endLon = Longitude((Angle)endLon);
403 
404  range.append(qMakePair(startLon, endLon));
405  }
406  return range;
407  }
408 }
Direction
Possible longitude directions: Is a positive longitude towards east or towards west?
Definition: Longitude.h:58
Units
The set of usable angle measurement units.
Definition: Angle.h:66
const double PI
The mathematical constant PI.
Definition: Constants.h:56
double radians() const
Convert an angle to a double.
Definition: Angle.h:243
virtual void setAngle(const double &angle, const Units &unit)
Set angle value in desired units.
Definition: Angle.cpp:338
Domain
Use LongitudeDomain360 if 0-360 is the primary range of the longitude values with 180 being the &#39;cent...
Definition: Longitude.h:74
double positiveWest(Angle::Units units=Angle::Radians) const
Get the longitude in the PositiveWest coordinate system.
Definition: Longitude.cpp:171
~Longitude()
This cleans up the Longitude class.
Definition: Longitude.cpp:148
Longitude force180Domain() const
This returns a longitude that is constricted to -180 to 180 degrees.
Definition: Longitude.cpp:302
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
Definition: Longitude.cpp:280
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:249
As the longitude increases the actual position is more west.
Definition: Longitude.h:62
Domain m_currentDomain
This is necessary for converting to PositiveWest and back.
Definition: Longitude.h:123
void setPositiveEast(double longitude, Angle::Units units=Angle::Radians)
Set the longitude given a value in the PositiveEast longitude system.
Definition: Longitude.cpp:212
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
Longitude & operator=(const Longitude &longitudeToCopy)
Same as positiveEast.
Definition: Longitude.cpp:265
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
As the longitude increases the actual position is more east.
Definition: Longitude.h:60
Angle()
Constructs a blank angle object which needs a value to be set in order to do any calculations.
Definition: Angle.cpp:38
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
static QList< QPair< Longitude, Longitude > > to360Range(Longitude startLon, Longitude endLon)
Calculates where the longitude range is in 0-360.
Definition: Longitude.cpp:377
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:212
As the longitude increases the actual position is more east.
Definition: Longitude.h:76
double unitWrapValue(const Units &unit) const
Return wrap value in desired units.
Definition: Angle.cpp:281
double positiveEast(Angle::Units units=Angle::Radians) const
Get the longitude in the PositiveEast coordinate system.
Definition: Longitude.cpp:159
static Angle fullRotation()
Makes an angle to represent a full rotation (0-360 or 0-2pi).
Definition: Angle.cpp:121
Defines an angle and provides unit conversions.
Definition: Angle.h:62
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void setPositiveWest(double longitude, Angle::Units units=Angle::Radians)
Set the longitude given a value in the PositiveWest longitude system.
Definition: Longitude.cpp:223
Longitude()
Create a blank Longitude object with 0-360 domain.
Definition: Longitude.cpp:37
virtual double angle(const Units &unit) const
Return angle value in desired units.
Definition: Angle.cpp:304
Isis exception class.
Definition: IException.h:107
As the longitude increases the actual position is more west.
Definition: Longitude.h:78
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
bool inRange(Longitude min, Longitude max) const
Checks if this longitude value is within the given range.
Definition: Longitude.cpp:332
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
Definition: Angle.cpp:110
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition: Angle.h:80