summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/dms.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/dms.cpp')
-rw-r--r--kstars/kstars/dms.cpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/kstars/kstars/dms.cpp b/kstars/kstars/dms.cpp
new file mode 100644
index 00000000..c6defc32
--- /dev/null
+++ b/kstars/kstars/dms.cpp
@@ -0,0 +1,318 @@
+/***************************************************************************
+ dms.cpp - K Desktop Planetarium
+ -------------------
+ begin : Sun Feb 11 2001
+ copyright : (C) 2001 by Jason Harris
+ email : jharris@30doradus.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <stdlib.h>
+
+#include "dms.h"
+#include <kglobal.h>
+#include <klocale.h>
+#include <qregexp.h>
+
+void dms::setD( const double &x ) {
+ D = x;
+ scDirty = true;
+ rDirty = true;
+}
+
+void dms::setD(const int &d, const int &m, const int &s, const int &ms) {
+ D = (double)abs(d) + ((double)m + ((double)s + (double)ms/1000.)/60.)/60.;
+ if (d<0) {D = -1.0*D;}
+ scDirty = true;
+ rDirty = true;
+}
+
+void dms::setH( const double &x ) {
+ setD( x*15.0 );
+}
+
+void dms::setH(const int &h, const int &m, const int &s, const int &ms) {
+ D = 15.0*((double)abs(h) + ((double)m + ((double)s + (double)ms/1000.)/60.)/60.);
+ if (h<0) {D = -1.0*D;}
+ scDirty = true;
+ rDirty = true;
+}
+
+void dms::setRadians( const double &Rad ) {
+ setD( Rad/DegToRad );
+ Radians = Rad;
+}
+
+bool dms::setFromString( const QString &str, bool isDeg ) {
+ int d(0), m(0);
+ double s(0.0);
+ bool checkValue( false ), badEntry( false ), negative( false );
+ QString entry = str.stripWhiteSpace();
+
+ //remove any instances of unit characters.
+ //h, d, m, s, ', ", or the degree symbol (ASCII 176)
+ entry.replace( QRegExp("h"), "" );
+ entry.replace( QRegExp("d"), "" );
+ entry.replace( QRegExp("m"), "" );
+ entry.replace( QRegExp("s"), "" );
+ QString sdeg;
+ sdeg.sprintf("%c", 176);
+ entry.replace( QRegExp(sdeg), "" );
+ entry.replace( QRegExp("\'"), "" );
+ entry.replace( QRegExp("\""), "" );
+
+ //Account for localized decimal-point settings
+ //QString::toDouble() requires that the decimal symbol is "."
+ entry.replace( KGlobal::locale()->decimalSymbol(), "." );
+
+ //empty entry returns false
+ if ( entry.isEmpty() ) {
+ setD( 0.0 );
+ return false;
+ }
+
+ //try parsing a simple integer
+ d = entry.toInt( &checkValue );
+ if ( checkValue ) {
+ if (isDeg) setD( d, 0, 0 );
+ else setH( d, 0, 0 );
+ return true;
+ }
+
+ //try parsing a simple double
+ double x = entry.toDouble( &checkValue );
+ if ( checkValue ) {
+ if ( isDeg ) setD( x );
+ else setH( x );
+ return true;
+ }
+
+ //try parsing multiple fields.
+ QStringList fields;
+
+ //check for colon-delimiters or space-delimiters
+ if ( entry.contains(':') )
+ fields = QStringList::split( ':', entry );
+ else fields = QStringList::split( " ", entry );
+
+ //anything with one field is invalid!
+ if ( fields.count() == 1 ) {
+ setD(0.0);
+ return false;
+ }
+
+ //If two fields we will add a third one, and then parse with
+ //the 3-field code block. If field[1] is an int, add a third field equal to "0".
+ //If field[1] is a double, convert it to integer arcmin, and convert
+ //the remainder to integer arcsec
+ //If field[1] is neither int nor double, return false.
+ if ( fields.count() == 2 ) {
+ m = fields[1].toInt( &checkValue );
+ if ( checkValue ) fields.append( QString( "0" ) );
+ else {
+ double mx = fields[1].toDouble( &checkValue );
+ if ( checkValue ) {
+ fields[1] = QString("%1").arg( int(mx) );
+ fields.append( QString("%1").arg( int( 60.0*(mx - int(mx)) ) ) );
+ } else {
+ setD( 0.0 );
+ return false;
+ }
+ }
+ }
+
+ //Now have (at least) three fields ( h/d m s );
+ //we can ignore anything after 3rd field
+ if ( fields.count() >= 3 ) {
+ //See if first two fields parse as integers, and third field as a double
+
+ d = fields[0].toInt( &checkValue );
+ if ( !checkValue ) badEntry = true;
+ m = fields[1].toInt( &checkValue );
+ if ( !checkValue ) badEntry = true;
+ s = fields[2].toDouble( &checkValue );
+ if ( !checkValue ) badEntry = true;
+
+ //Special case: If first field is "-0", store the negative sign.
+ //(otherwise it gets dropped)
+ if ( fields[0].at(0) == '-' && d == 0 ) negative = true;
+ }
+
+ if ( !badEntry ) {
+ double D = (double)abs(d) + (double)abs(m)/60.
+ + (double)fabs(s)/3600.;
+
+ if ( negative || d<0 || m < 0 || s<0 ) { D = -1.0*D;}
+
+ if (isDeg) {
+ setD( D );
+ } else {
+ setH( D );
+ }
+ } else {
+ setD( 0.0 );
+ return false;
+ }
+
+ return true;
+}
+
+const int dms::arcmin( void ) const {
+ int am = int( float( 60.0*( fabs(D) - abs( degree() ) ) ) );
+ if ( D<0.0 && D>-1.0 ) { //angle less than zero, but greater than -1.0
+ am = -1*am; //make minute negative
+ }
+ return am;
+}
+
+const int dms::arcsec( void ) const {
+ int as = int( float( 60.0*( 60.0*( fabs(D) - abs( degree() ) ) - abs( arcmin() ) ) ) );
+ //If the angle is slightly less than 0.0, give ArcSec a neg. sgn.
+ if ( degree()==0 && arcmin()==0 && D<0.0 ) {
+ as = -1*as;
+ }
+ return as;
+}
+
+const int dms::marcsec( void ) const {
+ int as = int( float( 1000.0*(60.0*( 60.0*( fabs(D) - abs( degree() ) ) - abs( arcmin() ) ) - abs( arcsec() ) ) ) );
+ //If the angle is slightly less than 0.0, give ArcSec a neg. sgn.
+ if ( degree()==0 && arcmin()==0 && arcsec()== 0 && D<0.0 ) {
+ as = -1*as;
+ }
+ return as;
+}
+
+const int dms::minute( void ) const {
+ int hm = int( float( 60.0*( fabs( Hours() ) - abs( hour() ) ) ) );
+ if ( Hours()<0.0 && Hours()>-1.0 ) { //angle less than zero, but greater than -1.0
+ hm = -1*hm; //make minute negative
+ }
+ return hm;
+}
+
+const int dms::second( void ) const {
+ int hs = int( float( 60.0*( 60.0*( fabs( Hours() ) - abs( hour() ) ) - abs( minute() ) ) ) );
+ if ( hour()==0 && minute()==0 && Hours()<0.0 ) {
+ hs = -1*hs;
+ }
+ return hs;
+}
+
+const int dms::msecond( void ) const {
+ int hs = int( float( 1000.0*(60.0*( 60.0*( fabs( Hours() ) - abs( hour() ) ) - abs( minute() ) ) - abs( second() ) ) ) );
+ if ( hour()==0 && minute()==0 && second()==0 && Hours()<0.0 ) {
+ hs = -1*hs;
+ }
+ return hs;
+}
+
+const double& dms::sin( void ) const {
+ if ( scDirty ) {
+ double s,c;
+ SinCos( s, c );
+ }
+
+ return Sin;
+}
+
+const double& dms::cos( void ) const {
+ if ( scDirty ) {
+ double s,c;
+ SinCos( s, c );
+ }
+
+ return Cos;
+}
+
+void dms::SinCos( double &sina, double &cosa ) const {
+ /**We have two versions of this function. One is ANSI standard, but
+ *slower. The other is faster, but is GNU only.
+ *Using the __GLIBC_ and __GLIBC_MINOR_ constants to determine if the
+ * GNU extension sincos() is defined.
+ */
+
+ if ( scDirty ) {
+ #ifdef __GLIBC__
+ #if ( __GLIBC__ >= 2 && __GLIBC_MINOR__ >=1 && !defined(__UCLIBC__))
+ //GNU version
+ sincos( radians(), &Sin, &Cos );
+ #else
+ //For older GLIBC versions
+ Sin = ::sin( radians() );
+ Cos = ::cos( radians() );
+ #endif
+ #else
+ //ANSI-compliant version
+ Sin = ::sin( radians() );
+ Cos = ::cos( radians() );
+ #endif
+ scDirty = false;
+ }
+ sina = Sin;
+ cosa = Cos;
+}
+
+const double& dms::radians( void ) const {
+ if ( rDirty ) {
+ Radians = D*DegToRad;
+ rDirty = false;
+ }
+
+ return Radians;
+}
+
+const dms dms::reduce( void ) const {
+ double a = D;
+ while (a<0.0) {a += 360.0;}
+ while (a>=360.0) {a -= 360.0;}
+ return dms( a );
+}
+
+const QString dms::toDMSString(bool forceSign) const {
+ QString dummy;
+ char pm(' ');
+ int dd = abs(degree());
+ int dm = abs(arcmin());
+ int ds = abs(arcsec());
+
+ if ( Degrees() < 0.0 ) pm = '-';
+ else if (forceSign && Degrees() > 0.0 ) pm = '+';
+
+ QString format( "%c%3d%c %02d\' %02d\"" );
+ if ( dd < 100 ) format = "%c%2d%c %02d\' %02d\"";
+ if ( dd < 10 ) format = "%c%1d%c %02d\' %02d\"";
+
+ return dummy.sprintf(format.local8Bit(), pm, dd, 176, dm, ds);
+}
+
+const QString dms::toHMSString() const {
+ QString dummy;
+ return dummy.sprintf("%02dh %02dm %02ds", hour(), minute(), second());
+}
+
+dms dms::fromString(QString & st, bool deg) {
+ dms result;
+ bool ok( false );
+
+ ok = result.setFromString( st, deg );
+
+// if ( ok )
+ return result;
+// else {
+// kdDebug() << i18n( "Could Not Set Angle from string: " ) << st << endl;
+// return result;
+// }
+}
+
+// M_PI is defined in math.h
+const double dms::PI = M_PI;
+const double dms::DegToRad = PI/180.0;