Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

Isis 3 Programmer Reference
Longitude.cpp
1
5
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "Longitude.h"
8
9#include <cmath>
10
11#include <QtCore>
12#include <QDebug>
13
14#include "Constants.h"
15#include "IException.h"
16#include "IString.h"
17#include "PvlGroup.h"
18#include "SpecialPixel.h"
19
20namespace Isis {
27
28
39 Longitude::Longitude(double longitude, PvlGroup mapping,
40 Angle::Units longitudeUnits) :
41 Angle(longitude, longitudeUnits) {
42 if(mapping["LongitudeDomain"][0] == "360") {
44 }
45 else if(mapping["LongitudeDomain"][0] == "180") {
47 }
48 else {
49 IString msg = "Longitude domain [" +
50 IString(mapping["LongitudeDomain"][0]) + "] not recognized";
51 throw IException(IException::Programmer, msg, _FILEINFO_);
52 }
53
54 if(mapping["LongitudeDirection"][0] == "PositiveEast") {
55 setPositiveEast(longitude, longitudeUnits);
56 }
57 else if(mapping["LongitudeDirection"][0] == "PositiveWest") {
58 setPositiveWest(longitude, longitudeUnits);
59 }
60 else {
61 IString msg = "Longitude direction [" +
62 IString(mapping["LongitudeDirection"][0]) + "] not recognized";
63 throw IException(IException::Programmer, msg, _FILEINFO_);
64 }
65 }
66
67
77 Direction lonDir, Domain lonDomain) :
78 Angle(longitude) {
79 m_currentDomain = lonDomain;
80
81 if(lonDir == PositiveEast) {
82 setPositiveEast(longitude.radians(), Radians);
83 }
84 else if(lonDir == PositiveWest) {
85 setPositiveWest(longitude.radians(), Radians);
86 }
87 else {
88 IString msg = "Longitude direction [" + IString(lonDir) + "] not valid";
89 throw IException(IException::Programmer, msg, _FILEINFO_);
90 }
91 }
92
93
103 Longitude::Longitude(double longitude, Angle::Units longitudeUnits,
104 Direction lonDir, Domain lonDomain) :
105 Angle(longitude, longitudeUnits) {
106 m_currentDomain = lonDomain;
107
108 if(lonDir == PositiveEast) {
109 setPositiveEast(longitude, longitudeUnits);
110 }
111 else if(lonDir == PositiveWest) {
112 setPositiveWest(longitude, longitudeUnits);
113 }
114 else {
115 IString msg = "Longitude direction [" + IString(lonDir) + "] not valid";
116 throw IException(IException::Programmer, msg, _FILEINFO_);
117 }
118 }
119
120
126 Longitude::Longitude(const Longitude &longitudeToCopy)
127 : Angle(longitudeToCopy) {
128 m_currentDomain = longitudeToCopy.m_currentDomain;
129 }
130
131
137
138
147 return angle(units);
148 }
149
150
159 double longitude = angle(units);
160
161 if (!IsSpecial(longitude)) {
163 double wrapPoint = unitWrapValue(units);
164 double halfWrap = wrapPoint / 2.0;
165
166 int numPlanetWraps = qFloor(longitude / wrapPoint);
167
168 // If the input is 360, then we want numPlanetWraps == 0. Compare the input to the border
169 // case (wraps * wrapPoint == longitude) and bring the number of wraps down if it's true.
170 // If it's false, then the rounding already took care of this border case.
171 if (numPlanetWraps != 0 && qFuzzyCompare(numPlanetWraps * wrapPoint, longitude)) {
172 if (numPlanetWraps > 0)
173 numPlanetWraps--;
174 else
175 numPlanetWraps++;
176 }
177
178 longitude -= numPlanetWraps * wrapPoint;
179 longitude = -(longitude - halfWrap) + halfWrap;
180 longitude -= numPlanetWraps * wrapPoint;
181 }
182 else {
183 // 180 domain is just a negation in this conversion,
184 // no more work needs done
185 longitude = -1 * longitude;
186 }
187 }
188
189 return longitude;
190 }
191
192
199 void Longitude::setPositiveEast(double longitude, Angle::Units units) {
200 setAngle(longitude, units);
201 }
202
203
210 void Longitude::setPositiveWest(double longitude, Angle::Units units) {
211 if(!IsSpecial(longitude)) {
213 // Same as positiveWest
214 double wrapPoint = unitWrapValue(units);
215 double halfWrap = wrapPoint / 2.0;
216
217 int numPlanetWraps = qFloor(longitude / wrapPoint);
218
219 // If the input is 360, then we want numPlanetWraps == 0. Compare the input to the border
220 // case (wraps * wrapPoint == longitude) and bring the number of wraps down if it's true.
221 // If it's false, then the rounding already took care of this border case.
222 if (numPlanetWraps != 0 && qFuzzyCompare(numPlanetWraps * wrapPoint, longitude)) {
223 if (numPlanetWraps > 0)
224 numPlanetWraps--;
225 else
226 numPlanetWraps++;
227 }
228
229
230 longitude -= numPlanetWraps * wrapPoint;
231 longitude = -(longitude - halfWrap) + halfWrap;
232 longitude -= numPlanetWraps * wrapPoint;
233 }
234 else {
235 // 180 domain is just a negation in this conversion,
236 // no more work needs done
237 longitude = -1 * longitude;
238 }
239 }
240
241 setAngle(longitude, units);
242 }
243
244
252 Longitude& Longitude::operator=(const Longitude & longitudeToCopy) {
253 if(this == &longitudeToCopy) return *this;
254
255 m_currentDomain = longitudeToCopy.m_currentDomain;
256 setPositiveEast(longitudeToCopy.positiveEast());
257
258 return *this;
259 }
260
261
268 if(!isValid()) return Longitude();
269
270 double resultantLongitude = angle(Angle::Degrees);
271
272 // Bring the number in the 0 to 360 range
273 if (qFuzzyCompare(degrees(), 360.0)) {
274 resultantLongitude = 360.0;
275 }
276 else {
277 resultantLongitude -= 360 * qFloor(resultantLongitude / 360);
278 }
279
280 return Longitude(resultantLongitude, Angle::Degrees);
281 }
282
283
290 if(!isValid()) return Longitude();
291
292 Longitude forced = force360Domain();
293
294 if(forced.degrees() > 180.0)
295 forced -= Angle(360.0, Angle::Degrees);
296
297 return forced;
298 }
299
300
320 bool result = false;
321
323
324 Longitude thisLon = force360Domain();
325
326 QPair<Longitude, Longitude> range;
327 foreach (range, ranges) {
328 if (thisLon >= range.first && thisLon <= range.second) {
329 result = true;
330 }
331
332 double thisLonRadians = thisLon.radians();
333 double rangeStartRadians = range.first.radians();
334 double rangeEndRadians = range.second.radians();
335 // Check equality on edges of range
336 if (qFuzzyCompare(thisLonRadians, rangeStartRadians) ||
337 qFuzzyCompare(thisLonRadians, rangeEndRadians)) {
338 result = true;
339 }
340
341 // Be very careful at the 0-360 boundary
342 if ((qFuzzyCompare(thisLonRadians, 0.0) || qFuzzyCompare(thisLonRadians, 2.0 * PI)) &&
343 (qFuzzyCompare(rangeStartRadians, 0.0) ||
344 qFuzzyCompare(rangeEndRadians, 2.0 * PI))) {
345 result = true;
346 }
347 }
348
349 return result;
350 }
351
365
367
368 if (startLon.isValid() && endLon.isValid() && startLon < endLon) {
369
370 int multiplier = floor(startLon / fullRotation());
371
372 startLon -= multiplier * fullRotation();
373 endLon -= multiplier * fullRotation();
374
375 if (endLon > fullRotation()) {
376
377 Longitude startLon2(0, Angle::Degrees);
378 Longitude endLon2(endLon - fullRotation());
379
380 if (endLon2 < startLon) {
381 range.append(qMakePair(startLon2, endLon2));
382 }
383 else {
384 startLon = Longitude(0, Angle::Degrees);
385 }
386 endLon = Longitude(360, Angle::Degrees);
387 }
388 startLon = Longitude((Angle)startLon);
389 endLon = Longitude((Angle)endLon);
390
391 range.append(qMakePair(startLon, endLon));
392 }
393 return range;
394 }
395}
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid,...
Definition Angle.cpp:96
Angle()
Constructs a blank angle object which needs a value to be set in order to do any calculations.
Definition Angle.cpp:24
virtual void setAngle(const double &angle, const Units &unit)
Set angle value in desired units.
Definition Angle.cpp:324
double unitWrapValue(const Units &unit) const
Return wrap value in desired units.
Definition Angle.cpp:267
double radians() const
Convert an angle to a double.
Definition Angle.h:226
double degrees() const
Get the angle in units of Degrees.
Definition Angle.h:232
static Angle fullRotation()
Makes an angle to represent a full rotation (0-360 or 0-2pi).
Definition Angle.cpp:107
virtual double angle(const Units &unit) const
Return angle value in desired units.
Definition Angle.cpp:290
Units
The set of usable angle measurement units.
Definition Angle.h:49
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
@ Radians
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition Angle.h:63
double positiveWest(Angle::Units units=Angle::Radians) const
Get the longitude in the PositiveWest coordinate system.
void setPositiveEast(double longitude, Angle::Units units=Angle::Radians)
Set the longitude given a value in the PositiveEast longitude system.
Direction
Possible longitude directions: Is a positive longitude towards east or towards west?
Definition Longitude.h:46
@ PositiveWest
As the longitude increases the actual position is more west.
Definition Longitude.h:50
@ PositiveEast
As the longitude increases the actual position is more east.
Definition Longitude.h:48
void setPositiveWest(double longitude, Angle::Units units=Angle::Radians)
Set the longitude given a value in the PositiveWest longitude system.
Longitude()
Create a blank Longitude object with 0-360 domain.
Definition Longitude.cpp:24
~Longitude()
This cleans up the Longitude class.
Domain
Use LongitudeDomain360 if 0-360 is the primary range of the longitude values with 180 being the 'cent...
Definition Longitude.h:62
@ Domain180
As the longitude increases the actual position is more west.
Definition Longitude.h:66
@ Domain360
As the longitude increases the actual position is more east.
Definition Longitude.h:64
Longitude force180Domain() const
This returns a longitude that is constricted to -180 to 180 degrees.
static QList< QPair< Longitude, Longitude > > to360Range(Longitude startLon, Longitude endLon)
Calculates where the longitude range is in 0-360.
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
Domain m_currentDomain
This is necessary for converting to PositiveWest and back.
Definition Longitude.h:111
double positiveEast(Angle::Units units=Angle::Radians) const
Get the longitude in the PositiveEast coordinate system.
Longitude & operator=(const Longitude &longitudeToCopy)
Same as positiveEast.
bool inRange(Longitude min, Longitude max) const
Checks if this longitude value is within the given range.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16