geocoordinatecalculator/angle.cpp

164 lines
3.8 KiB
C++

#include "utils.h"
#include "angle.h"
#include <c++utilities/application/failure.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265359
#endif
using namespace std;
using namespace ApplicationUtilities;
Angle::Angle() :
m_val(0)
{
}
Angle::Angle(double value, AngularMeasure measure) :
m_val(0)
{
switch(measure)
{
case AngularMeasure::Radian:
m_val = value;
break;
case AngularMeasure::Degree:
m_val = value * M_PI / 180.0;
}
}
Angle::Angle(const string &value, AngularMeasure measure) :
m_val(0)
{
switch(measure) {
case AngularMeasure::Radian:
m_val += ConversionUtilities::numberFromString<double>(value);
break;
case AngularMeasure::Degree:
{
string::size_type mpos, spos = string::npos;
mpos = value.find(':');
if(mpos == string::npos)
m_val += ConversionUtilities::numberFromString<double>(value);
else if(mpos >= (value.length() - 1))
throw Failure("excepted minutes after ':' in " + value);
else {
m_val += ConversionUtilities::numberFromString<double>(value.substr(0, mpos));
spos = value.find(':', mpos + 1);
if(spos == string::npos)
m_val += ConversionUtilities::numberFromString<double>(value.substr(mpos + 1)) / 60.0;
else if(spos >= (value.length() - 1))
throw Failure("excepted seconds after second ':'' in " + value);
else
m_val += (ConversionUtilities::numberFromString<double>(value.substr(mpos + 1, spos - mpos - 1)) / 60.0)
+ (ConversionUtilities::numberFromString<double>(value.substr(spos + 1)) / 3600.0);
}
m_val = m_val * M_PI / 180.0;
break;
}
}
}
double Angle::degreeValue() const
{
return m_val * 180.0 / M_PI;
}
double Angle::radianValue() const
{
return m_val;
}
bool Angle::isNull() const
{
return m_val == 0.0;
}
void Angle::adjust0To360()
{
while(m_val < 0) m_val += 2.0 * M_PI;
while(m_val > 2.0 * M_PI) m_val -= 2.0 * M_PI;
}
void Angle::adjust180To180()
{
while(m_val > M_PI) m_val -= 2.0 * M_PI;
while(m_val < -M_PI) m_val += 2.0 * M_PI;
}
void Angle::reverse()
{
m_val += M_PI;
adjust0To360();
}
string Angle::toString(OutputForm format) const
{
stringstream sstream(stringstream::in | stringstream::out);
sstream << setprecision(9);
double intpart, fractpart;
switch(format) {
case OutputForm::Degrees:
sstream << degreeValue();
break;
case OutputForm::Minutes:
if(degreeValue() < 0)
sstream << "-";
fractpart = modf(fabs(degreeValue()), &intpart);
fractpart *= 60;
sstream << intpart << ":" << fractpart;
break;
case OutputForm::Seconds:
if(degreeValue() < 0)
sstream << "-";
fractpart = modf(fabs(degreeValue()), &intpart);
sstream << intpart << ":";
fractpart *= 60;
fractpart = modf(fractpart, &intpart);
fractpart *= 60;
sstream << intpart << ":" << fractpart;
break;
case OutputForm::Radians:
sstream << radianValue();
}
return sstream.str();
}
bool Angle::operator ==(const Angle &other) const
{
return m_val == other.m_val;
}
bool Angle::operator !=(const Angle &other) const
{
return m_val != other.m_val;
}
Angle Angle::operator +(const Angle &other) const
{
return Angle(m_val + other.m_val);
}
Angle Angle::operator -(const Angle &other) const
{
return Angle(m_val - other.m_val);
}
Angle &Angle::operator +=(const Angle &other)
{
m_val += other.m_val;
return *this;
}
Angle &Angle::operator -=(const Angle &other)
{
m_val -= other.m_val;
return *this;
}